From 26105034da4fcce7ac883c899d781f016559310d Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 8 Nov 2018 00:38:48 +0800 Subject: switch to vuepress --- node_modules/stylus/lib/utils.js | 526 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 526 insertions(+) create mode 100644 node_modules/stylus/lib/utils.js (limited to 'node_modules/stylus/lib/utils.js') 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 + * 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; +}; -- cgit v1.2.3