aboutsummaryrefslogtreecommitdiff
path: root/node_modules/stylus/lib/utils.js
diff options
context:
space:
mode:
authorruki <waruqi@gmail.com>2018-11-08 00:38:48 +0800
committerruki <waruqi@gmail.com>2018-11-07 21:53:09 +0800
commit26105034da4fcce7ac883c899d781f016559310d (patch)
treec459a5dc4e3aa0972d9919033ece511ce76dd129 /node_modules/stylus/lib/utils.js
parent2c77f00f1a7ecb6c8192f9c16d3b2001b254a107 (diff)
downloadxmake-docs-26105034da4fcce7ac883c899d781f016559310d.tar.gz
xmake-docs-26105034da4fcce7ac883c899d781f016559310d.zip
switch to vuepress
Diffstat (limited to 'node_modules/stylus/lib/utils.js')
-rw-r--r--node_modules/stylus/lib/utils.js526
1 files changed, 526 insertions, 0 deletions
diff --git a/node_modules/stylus/lib/utils.js b/node_modules/stylus/lib/utils.js
new file mode 100644
index 00000000..e53910ac
--- /dev/null
+++ b/node_modules/stylus/lib/utils.js
@@ -0,0 +1,526 @@
+
+/*!
+ * Stylus - utils
+ * Copyright (c) Automattic <developer.wordpress.com>
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var nodes = require('./nodes')
+ , basename = require('path').basename
+ , relative = require('path').relative
+ , join = require('path').join
+ , isAbsolute = require('path').isAbsolute
+ , glob = require('glob')
+ , fs = require('fs');
+
+/**
+ * Check if `path` looks absolute.
+ *
+ * @param {String} path
+ * @return {Boolean}
+ * @api private
+ */
+
+exports.absolute = isAbsolute || function(path){
+ // On Windows the path could start with a drive letter, i.e. a:\\ or two leading backslashes.
+ // Also on Windows, the path may have been normalized to forward slashes, so check for this too.
+ return path.substr(0, 2) == '\\\\' || '/' === path.charAt(0) || /^[a-z]:[\\\/]/i.test(path);
+};
+
+/**
+ * Attempt to lookup `path` within `paths` from tail to head.
+ * Optionally a path to `ignore` may be passed.
+ *
+ * @param {String} path
+ * @param {String} paths
+ * @param {String} ignore
+ * @return {String}
+ * @api private
+ */
+
+exports.lookup = function(path, paths, ignore){
+ var lookup
+ , i = paths.length;
+
+ // Absolute
+ if (exports.absolute(path)) {
+ try {
+ fs.statSync(path);
+ return path;
+ } catch (err) {
+ // Ignore, continue on
+ // to trying relative lookup.
+ // Needed for url(/images/foo.png)
+ // for example
+ }
+ }
+
+ // Relative
+ while (i--) {
+ try {
+ lookup = join(paths[i], path);
+ if (ignore == lookup) continue;
+ fs.statSync(lookup);
+ return lookup;
+ } catch (err) {
+ // Ignore
+ }
+ }
+};
+
+/**
+ * Like `utils.lookup` but uses `glob` to find files.
+ *
+ * @param {String} path
+ * @param {String} paths
+ * @param {String} ignore
+ * @return {Array}
+ * @api private
+ */
+exports.find = function(path, paths, ignore) {
+ var lookup
+ , found
+ , i = paths.length;
+
+ // Absolute
+ if (exports.absolute(path)) {
+ if ((found = glob.sync(path)).length) {
+ return found;
+ }
+ }
+
+ // Relative
+ while (i--) {
+ lookup = join(paths[i], path);
+ if (ignore == lookup) continue;
+ if ((found = glob.sync(lookup)).length) {
+ return found;
+ }
+ }
+};
+
+/**
+ * Lookup index file inside dir with given `name`.
+ *
+ * @param {String} name
+ * @return {Array}
+ * @api private
+ */
+
+exports.lookupIndex = function(name, paths, filename){
+ // foo/index.styl
+ var found = exports.find(join(name, 'index.styl'), paths, filename);
+ if (!found) {
+ // foo/foo.styl
+ found = exports.find(join(name, basename(name).replace(/\.styl/i, '') + '.styl'), paths, filename);
+ }
+ if (!found && !~name.indexOf('node_modules')) {
+ // node_modules/foo/.. or node_modules/foo.styl/..
+ found = lookupPackage(join('node_modules', name));
+ }
+ return found;
+
+ function lookupPackage(dir) {
+ var pkg = exports.lookup(join(dir, 'package.json'), paths, filename);
+ if (!pkg) {
+ return /\.styl$/i.test(dir) ? exports.lookupIndex(dir, paths, filename) : lookupPackage(dir + '.styl');
+ }
+ var main = require(relative(__dirname, pkg)).main;
+ if (main) {
+ found = exports.find(join(dir, main), paths, filename);
+ } else {
+ found = exports.lookupIndex(dir, paths, filename);
+ }
+ return found;
+ }
+};
+
+/**
+ * Format the given `err` with the given `options`.
+ *
+ * Options:
+ *
+ * - `filename` context filename
+ * - `context` context line count [8]
+ * - `lineno` context line number
+ * - `column` context column number
+ * - `input` input string
+ *
+ * @param {Error} err
+ * @param {Object} options
+ * @return {Error}
+ * @api private
+ */
+
+exports.formatException = function(err, options){
+ var lineno = options.lineno
+ , column = options.column
+ , filename = options.filename
+ , str = options.input
+ , context = options.context || 8
+ , context = context / 2
+ , lines = ('\n' + str).split('\n')
+ , start = Math.max(lineno - context, 1)
+ , end = Math.min(lines.length, lineno + context)
+ , pad = end.toString().length;
+
+ var context = lines.slice(start, end).map(function(line, i){
+ var curr = i + start;
+ return ' '
+ + Array(pad - curr.toString().length + 1).join(' ')
+ + curr
+ + '| '
+ + line
+ + (curr == lineno
+ ? '\n' + Array(curr.toString().length + 5 + column).join('-') + '^'
+ : '');
+ }).join('\n');
+
+ err.message = filename
+ + ':' + lineno
+ + ':' + column
+ + '\n' + context
+ + '\n\n' + err.message + '\n'
+ + (err.stylusStack ? err.stylusStack + '\n' : '');
+
+ // Don't show JS stack trace for Stylus errors
+ if (err.fromStylus) err.stack = 'Error: ' + err.message;
+
+ return err;
+};
+
+/**
+ * Assert that `node` is of the given `type`, or throw.
+ *
+ * @param {Node} node
+ * @param {Function} type
+ * @param {String} param
+ * @api public
+ */
+
+exports.assertType = function(node, type, param){
+ exports.assertPresent(node, param);
+ if (node.nodeName == type) return;
+ var actual = node.nodeName
+ , msg = 'expected '
+ + (param ? '"' + param + '" to be a ' : '')
+ + type + ', but got '
+ + actual + ':' + node;
+ throw new Error('TypeError: ' + msg);
+};
+
+/**
+ * Assert that `node` is a `String` or `Ident`.
+ *
+ * @param {Node} node
+ * @param {String} param
+ * @api public
+ */
+
+exports.assertString = function(node, param){
+ exports.assertPresent(node, param);
+ switch (node.nodeName) {
+ case 'string':
+ case 'ident':
+ case 'literal':
+ return;
+ default:
+ var actual = node.nodeName
+ , msg = 'expected string, ident or literal, but got ' + actual + ':' + node;
+ throw new Error('TypeError: ' + msg);
+ }
+};
+
+/**
+ * Assert that `node` is a `RGBA` or `HSLA`.
+ *
+ * @param {Node} node
+ * @param {String} param
+ * @api public
+ */
+
+exports.assertColor = function(node, param){
+ exports.assertPresent(node, param);
+ switch (node.nodeName) {
+ case 'rgba':
+ case 'hsla':
+ return;
+ default:
+ var actual = node.nodeName
+ , msg = 'expected rgba or hsla, but got ' + actual + ':' + node;
+ throw new Error('TypeError: ' + msg);
+ }
+};
+
+/**
+ * Assert that param `name` is given, aka the `node` is passed.
+ *
+ * @param {Node} node
+ * @param {String} name
+ * @api public
+ */
+
+exports.assertPresent = function(node, name){
+ if (node) return;
+ if (name) throw new Error('"' + name + '" argument required');
+ throw new Error('argument missing');
+};
+
+/**
+ * Unwrap `expr`.
+ *
+ * Takes an expressions with length of 1
+ * such as `((1 2 3))` and unwraps it to `(1 2 3)`.
+ *
+ * @param {Expression} expr
+ * @return {Node}
+ * @api public
+ */
+
+exports.unwrap = function(expr){
+ // explicitly preserve the expression
+ if (expr.preserve) return expr;
+ if ('arguments' != expr.nodeName && 'expression' != expr.nodeName) return expr;
+ if (1 != expr.nodes.length) return expr;
+ if ('arguments' != expr.nodes[0].nodeName && 'expression' != expr.nodes[0].nodeName) return expr;
+ return exports.unwrap(expr.nodes[0]);
+};
+
+/**
+ * Coerce JavaScript values to their Stylus equivalents.
+ *
+ * @param {Mixed} val
+ * @param {Boolean} [raw]
+ * @return {Node}
+ * @api public
+ */
+
+exports.coerce = function(val, raw){
+ switch (typeof val) {
+ case 'function':
+ return val;
+ case 'string':
+ return new nodes.String(val);
+ case 'boolean':
+ return new nodes.Boolean(val);
+ case 'number':
+ return new nodes.Unit(val);
+ default:
+ if (null == val) return nodes.null;
+ if (Array.isArray(val)) return exports.coerceArray(val, raw);
+ if (val.nodeName) return val;
+ return exports.coerceObject(val, raw);
+ }
+};
+
+/**
+ * Coerce a javascript `Array` to a Stylus `Expression`.
+ *
+ * @param {Array} val
+ * @param {Boolean} [raw]
+ * @return {Expression}
+ * @api private
+ */
+
+exports.coerceArray = function(val, raw){
+ var expr = new nodes.Expression;
+ val.forEach(function(val){
+ expr.push(exports.coerce(val, raw));
+ });
+ return expr;
+};
+
+/**
+ * Coerce a javascript object to a Stylus `Expression` or `Object`.
+ *
+ * For example `{ foo: 'bar', bar: 'baz' }` would become
+ * the expression `(foo 'bar') (bar 'baz')`. If `raw` is true
+ * given `obj` would become a Stylus hash object.
+ *
+ * @param {Object} obj
+ * @param {Boolean} [raw]
+ * @return {Expression|Object}
+ * @api public
+ */
+
+exports.coerceObject = function(obj, raw){
+ var node = raw ? new nodes.Object : new nodes.Expression
+ , val;
+
+ for (var key in obj) {
+ val = exports.coerce(obj[key], raw);
+ key = new nodes.Ident(key);
+ if (raw) {
+ node.set(key, val);
+ } else {
+ node.push(exports.coerceArray([key, val]));
+ }
+ }
+
+ return node;
+};
+
+/**
+ * Return param names for `fn`.
+ *
+ * @param {Function} fn
+ * @return {Array}
+ * @api private
+ */
+
+exports.params = function(fn){
+ return fn
+ .toString()
+ .match(/\(([^)]*)\)/)[1].split(/ *, */);
+};
+
+/**
+ * Merge object `b` with `a`.
+ *
+ * @param {Object} a
+ * @param {Object} b
+ * @param {Boolean} [deep]
+ * @return {Object} a
+ * @api private
+ */
+exports.merge = function(a, b, deep) {
+ for (var k in b) {
+ if (deep && a[k]) {
+ var nodeA = exports.unwrap(a[k]).first
+ , nodeB = exports.unwrap(b[k]).first;
+
+ if ('object' == nodeA.nodeName && 'object' == nodeB.nodeName) {
+ a[k].first.vals = exports.merge(nodeA.vals, nodeB.vals, deep);
+ } else {
+ a[k] = b[k];
+ }
+ } else {
+ a[k] = b[k];
+ }
+ }
+ return a;
+};
+
+/**
+ * Returns an array with unique values.
+ *
+ * @param {Array} arr
+ * @return {Array}
+ * @api private
+ */
+
+exports.uniq = function(arr){
+ var obj = {}
+ , ret = [];
+
+ for (var i = 0, len = arr.length; i < len; ++i) {
+ if (arr[i] in obj) continue;
+
+ obj[arr[i]] = true;
+ ret.push(arr[i]);
+ }
+ return ret;
+};
+
+/**
+ * Compile selector strings in `arr` from the bottom-up
+ * to produce the selector combinations. For example
+ * the following Stylus:
+ *
+ * ul
+ * li
+ * p
+ * a
+ * color: red
+ *
+ * Would return:
+ *
+ * [ 'ul li a', 'ul p a' ]
+ *
+ * @param {Array} arr
+ * @param {Boolean} leaveHidden
+ * @return {Array}
+ * @api private
+ */
+
+exports.compileSelectors = function(arr, leaveHidden){
+ var selectors = []
+ , Parser = require('./selector-parser')
+ , indent = (this.indent || '')
+ , buf = [];
+
+ function parse(selector, buf) {
+ var parts = [selector.val]
+ , str = new Parser(parts[0], parents, parts).parse().val
+ , parents = [];
+
+ if (buf.length) {
+ for (var i = 0, len = buf.length; i < len; ++i) {
+ parts.push(buf[i]);
+ parents.push(str);
+ var child = new Parser(buf[i], parents, parts).parse();
+
+ if (child.nested) {
+ str += ' ' + child.val;
+ } else {
+ str = child.val;
+ }
+ }
+ }
+ return str.trim();
+ }
+
+ function compile(arr, i) {
+ if (i) {
+ arr[i].forEach(function(selector){
+ if (!leaveHidden && selector.isPlaceholder) return;
+ if (selector.inherits) {
+ buf.unshift(selector.val);
+ compile(arr, i - 1);
+ buf.shift();
+ } else {
+ selectors.push(indent + parse(selector, buf));
+ }
+ });
+ } else {
+ arr[0].forEach(function(selector){
+ if (!leaveHidden && selector.isPlaceholder) return;
+ var str = parse(selector, buf);
+ if (str) selectors.push(indent + str);
+ });
+ }
+ }
+
+ compile(arr, arr.length - 1);
+
+ // Return the list with unique selectors only
+ return exports.uniq(selectors);
+};
+
+/**
+ * Attempt to parse string.
+ *
+ * @param {String} str
+ * @return {Node}
+ * @api private
+ */
+
+exports.parseString = function(str){
+ var Parser = require('./parser')
+ , parser
+ , ret;
+
+ try {
+ parser = new Parser(str);
+ parser.state.push('expression');
+ ret = new nodes.Expression();
+ ret.nodes = parser.parse().nodes;
+ } catch (e) {
+ ret = new nodes.Literal(str);
+ }
+ return ret;
+};