function CachedPathEvaluator(root, options) { Evaluator.apply(this, arguments); this.cache = options.cache; }
n/a
function PathCache(contexts, sources, imports) { this.contexts = contexts; this.sources = sources; this.imports = imports; // Non relative paths are simpler and looked up in this as a fallback // to this.context. this.simpleContext = {}; for (var dirname in this.contexts) { for (var path in this.contexts[dirname]) { this.simpleContext[path] = this.contexts[dirname][path]; } } }
n/a
function CachedPathEvaluator(root, options) { Evaluator.apply(this, arguments); this.cache = options.cache; }
n/a
function CachedPathEvaluator(root, options) { Evaluator.apply(this, arguments); this.cache = options.cache; }
n/a
visitImport = function (imported) {
this.return++;
var path = this.visit(imported.path).first
, nodeName = imported.once ? 'require' : 'import'
, found
, literal
, index;
this.return--;
// debug('import %s', path);
// url() passed
if ('url' == path.name) {
if (imported.once) throw new Error('You cannot @require a url');
return imported;
}
// Ensure string
if (!path.string) throw new Error('@' + nodeName + ' string expected');
var name = path = path.string;
// Absolute URL
if (/url\s*\(\s*['"]?(?:https?:)?\/\//i.test(path)) {
if (imported.once) throw new Error('You cannot @require a url');
return imported;
}
// Literal
if (/\.css(?:"|$)/.test(path)) {
literal = true;
if (!imported.once && !this.includeCSS) {
return imported;
}
}
// support optional .styl
if (!literal && !/\.styl$/i.test(path)) path += '.styl';
/*****************************************************************************
* THIS IS THE ONLY BLOCK THAT DIFFERS FROM THE ACTUAL STYLUS IMPLEMENTATION. *
*****************************************************************************/
// Lookup
var dirname = this.paths[this.paths.length - 1];
found = this.cache.find(path, dirname);
index = this.cache.isIndex(path, dirname);
if (!found) {
found = utils.find(path, this.paths, this.filename);
if (!found) {
found = utils.lookupIndex(name, this.paths, this.filename);
index = true;
}
}
// Throw if import failed
if (!found) throw new Error('failed to locate @' + nodeName + ' file ' + path);
var block = new nodes.Block;
for (var i = 0, len = found.length; i < len; ++i) {
block.push(importFile.call(this, imported, found[i], literal, index));
}
return block;
}
n/a
function PathCache(contexts, sources, imports) { this.contexts = contexts; this.sources = sources; this.imports = imports; // Non relative paths are simpler and looked up in this as a fallback // to this.context. this.simpleContext = {}; for (var dirname in this.contexts) { for (var path in this.contexts[dirname]) { this.simpleContext[path] = this.contexts[dirname][path]; } } }
n/a
create = function (contexts, sources, imports) { return when(new PathCache(contexts, sources, imports)); }
...
function CachedPathEvaluator(root, options) {
Evaluator.apply(this, arguments);
this.cache = options.cache;
}
CachedPathEvaluator.prototype = Object.create(Evaluator.prototype);
CachedPathEvaluator.prototype.constructor = CachedPathEvaluator;
CachedPathEvaluator.prototype.visitImport = function(imported) {
this.return++;
var path = this.visit(imported.path).first
, nodeName = imported.once ? 'require' : 'import'
...
function resolveFileDeep(helpers, parentCache, source, fullPath) { var resolvers = helpers.resolvers; var readFile = helpers.readFile; var contexts = parentCache.contexts; var sources = parentCache.sources; contexts = contexts || {}; var nestResolve = resolveFileDeep.bind(null, helpers, parentCache, null); var context = path.dirname(fullPath); readFile = whenNodefn.lift(readFile); return when .resolve(source || sources[fullPath] || readFile(fullPath)) // Cast the buffer from the cached input file system to a string. .then(String) // Store the source so that the evaluator doesn't need to touch the // file system. .then(function(_source) { sources[fullPath] = _source; return _source; }) // Make sure the stylus functions/index.styl source is stored. .then(partial(ensureFunctionsSource, sources)) // List imports and use its cache. The source file is translated into a // list of imports. Where the source file came from isn't important for the // list. The where is added by resolveMany with the context and resolvers. .then(partialRight(listImports, { cache: parentCache.imports })) .then(resolveMany.bind(null, resolvers, context)) .then(function(newPaths) { // Contexts are the full path since multiple could be in the same folder // but different deps. contexts[context] = merge(contexts[context] || {}, newPaths); return when.map(Object.keys(newPaths), function(key) { var found = newPaths[key] && newPaths[key].path; if (found) { return when.map(found, nestResolve); } }); }) .then(function() { return PathCache.create(contexts, sources, parentCache.imports); }); }
...
paths.forEach(styl.import.bind(styl));
paths.forEach(self.addDependency);
var readFile = whenNodefn.lift(pathCacheHelpers.readFile);
return when.reduce(paths, function(cache, filepath) {
return readFile(filepath)
.then(function(source) {
return PathCache.createFromFile(
pathCacheHelpers, cache, source.toString(), filepath
);
});
}, {
contexts: {},
sources: {},
imports: importsCache,
...
function resolvers(options, webpackResolver) { var evaluator = new Evaluator(nodes.null, options); var whenWebpackResolver = whenNodefn.lift(webpackResolver); // Stylus's normal resolver for single files. var stylusFile = function(context, path) { // Stylus adds .styl to paths for normal "paths" lookup if it isn't there. if (!/.styl$/.test(path)) { path += '.styl'; } var paths = options.paths.concat(context); var found = utils.find(path, paths, options.filename) if (found) { return normalizePaths(found); } }; // Stylus's normal resolver for node_modules packages. Cannot locate paths // inside a package. var stylusIndex = function(context, path) { // Stylus calls the argument name. If it exists it should match the name // of a module in node_modules. if (!path) { return null; } var paths = options.paths.concat(context); var found = utils.lookupIndex(path, paths, options.filename); if (found) { return {path: normalizePaths(found), index: true}; } }; // Fallback to resolving with webpack's configured resovler. var webpackResolve = function(context, path) { // Follow the webpack stylesheet idiom of '~path' meaning a path in a // modules folder and a unprefixed 'path' meaning a relative path like // './path'. path = loaderUtils.urlToRequest(path, options.root); // First try with a '.styl' extension. return whenWebpackResolver(context, path + '.styl') // If the user adds ".styl" to resolve.extensions, webpack can find // index files like stylus but it uses all of webpack's configuration, // by default for example the module could be web_modules. .catch(function() { return whenWebpackResolver(context, path); }) .catch(function() { return null; }) .then(function(result) { return Array.isArray(result) && result[1] && result[1].path || result }); }; if (options.preferPathResolver === 'webpack') { return [ webpackResolve, stylusFile, stylusIndex ]; } else { return [ stylusFile, stylusIndex, webpackResolve ]; } }
...
try {
var inputFileSystem = this._compiler.inputFileSystem;
readFile = inputFileSystem.readFile.bind(inputFileSystem);
} catch (error) {
readFile = fs.readFile;
}
var boundResolvers = PathCache.resolvers(options, this.resolve);
var pathCacheHelpers = {
resolvers: boundResolvers,
readFile: readFile,
};
// Use plugins here so that resolve related side effects can be used while we resolve imports.
(Array.isArray(use) ? use : [use]).forEach(styl.use, styl);
...
allDeps = function () { var deps = []; for (var dirname in this.contexts) { for (var path in this.contexts[dirname]) { if (this.contexts[dirname][path]) { deps = deps.concat(this.contexts[dirname][path].path); } } } return deps; }
...
.then(function(cache) {
return PathCache
.createFromFile(pathCacheHelpers, cache, source, options.filename);
})
.then(function(importPathCache) {
// CachedPathEvaluator will use this PathCache to find its dependencies.
options.cache = importPathCache;
importPathCache.allDeps().forEach(function(f) {
self.addDependency(path.normalize(f));
});
// var paths = importPathCache.origins;
styl.render(function(err, css) {
if (err) {
...
find = function (path, dirname) { if (this.contexts[dirname] && this.contexts[dirname][path]) { return this.contexts[dirname][path].path; } else if (this.simpleContext[path]) { return this.simpleContext[path].path; } else if (/.styl$/.test(path)) { // A user can specify @import 'something.styl' but if they specify // @import 'something' stylus adds .styl, we drop that here to see if we // looked for it without .styl. return this.find(path.replace(/.styl$/, ''), dirname); } else { return undefined; } }
...
if (!literal && !/\.styl$/i.test(path)) path += '.styl';
/*****************************************************************************
* THIS IS THE ONLY BLOCK THAT DIFFERS FROM THE ACTUAL STYLUS IMPLEMENTATION. *
*****************************************************************************/
// Lookup
var dirname = this.paths[this.paths.length - 1];
found = this.cache.find(path, dirname);
index = this.cache.isIndex(path, dirname);
if (!found) {
found = utils.find(path, this.paths, this.filename);
if (!found) {
found = utils.lookupIndex(name, this.paths, this.filename);
index = true;
}
...
isIndex = function (path, dirname) { if (this.contexts[dirname] && this.contexts[dirname][path]) { return this.contexts[dirname][path].index; } else { return undefined; } }
...
/*****************************************************************************
* THIS IS THE ONLY BLOCK THAT DIFFERS FROM THE ACTUAL STYLUS IMPLEMENTATION. *
*****************************************************************************/
// Lookup
var dirname = this.paths[this.paths.length - 1];
found = this.cache.find(path, dirname);
index = this.cache.isIndex(path, dirname);
if (!found) {
found = utils.find(path, this.paths, this.filename);
if (!found) {
found = utils.lookupIndex(name, this.paths, this.filename);
index = true;
}
}
...