aboutsummaryrefslogtreecommitdiff
path: root/node_modules/stylus-loader/lib/evaluator.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/stylus-loader/lib/evaluator.js')
-rw-r--r--node_modules/stylus-loader/lib/evaluator.js166
1 files changed, 166 insertions, 0 deletions
diff --git a/node_modules/stylus-loader/lib/evaluator.js b/node_modules/stylus-loader/lib/evaluator.js
new file mode 100644
index 00000000..dc6013d8
--- /dev/null
+++ b/node_modules/stylus-loader/lib/evaluator.js
@@ -0,0 +1,166 @@
+// Except for a block in #visitImport, everything here is an exact copy of the
+// source in stylus this currently depends on. If stylus is updated, update
+// this appropriately.
+
+var Evaluator = require('stylus/lib/visitor/evaluator')
+ , nodes = require('stylus/lib/nodes')
+ , Stack = require('stylus/lib/stack')
+ , Frame = require('stylus/lib/stack/frame')
+ , Scope = require('stylus/lib/stack/scope')
+ , utils = require('stylus/lib/utils')
+ , bifs = require('stylus/lib/functions')
+ , basename = require('path').basename
+ , dirname = require('path').dirname
+ , relative = require('path').relative
+ , join = require('path').join
+ , colors = require('stylus/lib/colors')
+ // , debug = require('debug')('stylus:evaluator')
+ , fs = require('fs');
+
+module.exports = CachedPathEvaluator;
+
+/**
+ * Import `file` and return Block node.
+ *
+ * @api private
+ */
+function importFile(node, file, literal, index) {
+ var importStack = this.importStack
+ , Parser = require('stylus/lib/parser')
+ , stat;
+
+ // Handling the `require`
+ if (node.once) {
+ if (this.requireHistory[file]) return nodes.null;
+ this.requireHistory[file] = true;
+
+ if (literal && !this.includeCSS) {
+ return node;
+ }
+ }
+
+ // Expose imports
+ node.path = file;
+ node.dirname = dirname(file);
+ // Store the modified time
+ stat = fs.statSync(file);
+ node.mtime = stat.mtime;
+ this.paths.push(node.dirname);
+
+ // Avoid overflows from importing the same file over again
+ if (file === importStack[importStack.length - 1]) return nodes.null;
+
+ if (this.options._imports) this.options._imports.push(node.clone());
+
+ // Parse the file
+ importStack.push(file);
+ nodes.filename = file;
+
+ var str;
+ if (this.cache.sources && this.cache.sources[file]) {
+ str = this.cache.sources[file];
+ } else {
+ str = fs.readFileSync(file, 'utf8');
+ }
+
+ if (literal && !this.resolveURL) return new nodes.Literal(str.replace(/\r\n?/g, '\n'));
+
+ // parse
+ var block = new nodes.Block
+ , parser = new Parser(str, utils.merge({ root: block }, this.options));
+
+ try {
+ block = parser.parse();
+ } catch (err) {
+ err.filename = file;
+ err.lineno = parser.lexer.lineno;
+ err.input = str;
+ throw err;
+ }
+
+ // Evaluate imported "root"
+ block.parent = this.root;
+ block.scope = false;
+ var ret = this.visit(block);
+ importStack.pop();
+ if (importStack.length || index) this.paths.pop();
+
+ return ret;
+}
+
+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'
+ , 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;
+}