if ( Function.prototype.name === undefined && Object.defineProperty !== undefined ) { Object.defineProperty(Function.prototype, 'name', { get: function() { var regex = /function\s([^(]{1,})\(/, match = regex.exec(this.toString()); return match && match.length > 1 ? match[1].trim() : ''; }, }); } if (String.prototype.trimRight === undefined) { String.prototype.trimRight = function() { return String(this).replace(/\s+$/, ''); }; } var stylus = (function() { function require(p) { var path = require.resolve(p), mod = require.modules[path]; if (!mod) throw new Error('failed to require "' + p + '"'); if (!mod.exports) { mod.exports = {}; mod.call(mod.exports, mod, mod.exports, require.relative(path)); } return mod.exports; } var bifs = "called-from = ()\n\nvendors = moz webkit o ms official\n\n// stringify the given arg\n\n-string(arg)\n type(arg) + ' ' + arg\n\n// require a color\n\nrequire-color(color)\n unless color is a 'color'\n error('RGB or HSL value expected, got a ' + -string(color))\n\n// require a unit\n\nrequire-unit(n)\n unless n is a 'unit'\n error('unit expected, got a ' + -string(n))\n\n// require a string\n\nrequire-string(str)\n unless str is a 'string' or str is a 'ident'\n error('string expected, got a ' + -string(str))\n\n// Math functions\n\nabs(n) { math(n, 'abs') }\nmin(a, b) { a < b ? a : b }\nmax(a, b) { a > b ? a : b }\n\n// Trigonometrics\nPI = -math-prop('PI')\n\nradians-to-degrees(angle)\n angle * (180 / PI)\n\ndegrees-to-radians(angle)\n unit(angle * (PI / 180),'')\n\nsin(n)\n n = degrees-to-radians(n) if unit(n) == 'deg'\n round(math(n, 'sin'), 9)\n\ncos(n)\n n = degrees-to-radians(n) if unit(n) == 'deg'\n round(math(n, 'cos'), 9)\n\n// Rounding Math functions\n\nceil(n, precision = 0)\n multiplier = 10 ** precision\n math(n * multiplier, 'ceil') / multiplier\n\nfloor(n, precision = 0)\n multiplier = 10 ** precision\n math(n * multiplier, 'floor') / multiplier\n\nround(n, precision = 0)\n multiplier = 10 ** precision\n math(n * multiplier, 'round') / multiplier\n\n// return the sum of the given numbers\n\nsum(nums)\n sum = 0\n sum += n for n in nums\n\n// return the average of the given numbers\n\navg(nums)\n sum(nums) / length(nums)\n\n// return a unitless number, or pass through\n\nremove-unit(n)\n if typeof(n) is 'unit'\n unit(n, '')\n else\n n\n\n// convert a percent to a decimal, or pass through\n\npercent-to-decimal(n)\n if unit(n) is '%'\n remove-unit(n) / 100\n else\n n\n\n// check if n is an odd number\n\nodd(n)\n 1 == n % 2\n\n// check if n is an even number\n\neven(n)\n 0 == n % 2\n\n// check if color is light\n\nlight(color)\n lightness(color) >= 50%\n\n// check if color is dark\n\ndark(color)\n lightness(color) < 50%\n\n// desaturate color by amount\n\ndesaturate(color, amount)\n adjust(color, 'saturation', - amount)\n\n// saturate color by amount\n\nsaturate(color = '', amount = 100%)\n if color is a 'color'\n adjust(color, 'saturation', amount)\n else\n unquote( 'saturate(' + color + ')' )\n\n// darken by the given amount\n\ndarken(color, amount)\n adjust(color, 'lightness', - amount)\n\n// lighten by the given amount\n\nlighten(color, amount)\n adjust(color, 'lightness', amount)\n\n// decrease opacity by amount\n\nfade-out(color, amount)\n color - rgba(black, percent-to-decimal(amount))\n\n// increase opacity by amount\n\nfade-in(color, amount)\n color + rgba(black, percent-to-decimal(amount))\n\n// spin hue by a given amount\n\nspin(color, amount)\n color + unit(amount, deg)\n\n// mix two colors by a given amount\n\nmix(color1, color2, weight = 50%)\n unless weight in 0..100\n error('Weight must be between 0% and 100%')\n\n if length(color1) == 2\n weight = color1[0]\n color1 = color1[1]\n\n else if length(color2) == 2\n weight = 100 - color2[0]\n color2 = color2[1]\n\n require-color(color1)\n require-color(color2)\n\n p = unit(weight / 100, '')\n w = p * 2 - 1\n\n a = alpha(color1) - alpha(color2)\n\n w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2\n w2 = 1 - w1\n\n channels = (red(color1) red(color2)) (green(color1) green(color2)) (blue(color1) blue(color2))\n rgb = ()\n\n for pair in channels\n push(rgb, floor(pair[0] * w1 + pair[1] * w2))\n\n a1 = alpha(color1) * p\n a2 = alpha(color2) * (1 - p)\n alpha = a1 + a2\n\n rgba(rgb[0], rgb[1], rgb[2], alpha)\n\n// invert colors, leave alpha intact\n\ninvert(color = '')\n if color is a 'color'\n rgba(#fff - color, alpha(color))\n else\n unquote( 'invert(' + color + ')' )\n\n// give complement of the given color\n\ncomplement( color )\n spin( color, 180 )\n\n// give grayscale of the given color\n\ngrayscale( color = '' )\n if color is a 'color'\n desaturate( color, 100% )\n else\n unquote( 'grayscale(' + color + ')' )\n\n// mix the given color with white\n\ntint( color, percent )\n mix( white, color, percent )\n\n// mix the given color with black\n\nshade( color, percent )\n mix( black, color, percent )\n\n// return the last value in the given expr\n\nlast(expr)\n expr[length(expr) - 1]\n\n// return keys in the given pairs or object\n\nkeys(pairs)\n ret = ()\n if type(pairs) == 'object'\n for key in pairs\n push(ret, key)\n else\n for pair in pairs\n push(ret, pair[0]);\n ret\n\n// return values in the given pairs or object\n\nvalues(pairs)\n ret = ()\n if type(pairs) == 'object'\n for key, val in pairs\n push(ret, val)\n else\n for pair in pairs\n push(ret, pair[1]);\n ret\n\n// join values with the given delimiter\n\njoin(delim, vals...)\n buf = ''\n vals = vals[0] if length(vals) == 1\n for val, i in vals\n buf += i ? delim + val : val\n\n// add a CSS rule to the containing block\n\n// - This definition allows add-property to be used as a mixin\n// - It has the same effect as interpolation but allows users\n// to opt for a functional style\n\nadd-property-function = add-property\nadd-property(name, expr)\n if mixin\n {name} expr\n else\n add-property-function(name, expr)\n\nprefix-classes(prefix)\n -prefix-classes(prefix, block)\n\n// Caching mixin, use inside your functions to enable caching by extending.\n\n$stylus_mixin_cache = {}\ncache()\n $key = (current-media() or 'no-media') + '__' + called-from[0] + '__' + arguments\n if $key in $stylus_mixin_cache\n @extend {'$cache_placeholder_for_' + $stylus_mixin_cache[$key]}\n else if 'cache' in called-from\n {block}\n else\n $id = length($stylus_mixin_cache)\n\n &,\n /$cache_placeholder_for_{$id}\n $stylus_mixin_cache[$key] = $id\n {block}\n\n// Percentage function to convert a number, e.g. '.45', into a percentage, e.g. '45%'\n\npercentage(num)\n return unit(num * 100, '%')\n\n// Returns the position of a `value` within a `list`\n\nindex(list, value)\n for val, i in list\n return i if val == value\n"; require.modules = {}; require.resolve = function(path) { var orig = path, reg = path + '.js', index = path + '/index.js'; return ( (require.modules[reg] && reg) || (require.modules[index] && index) || orig ); }; require.register = function(path, fn) { require.modules[path] = fn; }; require.relative = function(parent) { return function(p) { if ('.' != p[0]) return require(p); var path = parent.split('/'), segs = p.split('/'); path.pop(); for (var i = 0; i < segs.length; i++) { var seg = segs[i]; if ('..' == seg) path.pop(); else if ('.' != seg) path.push(seg); } return require(path.join('/')); }; }; require.register('path.js', function(module, exports, require) { var isWindows = false; function normalizeArray(parts, allowAboveRoot) { var up = 0; for (var i = parts.length - 1; i >= 0; i--) { var last = parts[i]; if (last == '.') { parts.splice(i, 1); } else if (last === '..') { parts.splice(i, 1); up++; } else if (up) { parts.splice(i, 1); up--; } } if (allowAboveRoot) { for (; up--; up) { parts.unshift('..'); } } return parts; } var splitPathRe = /^([\s\S]+\/(?!$)|\/)?((?:[\s\S]+?)?(\.[^.]*)?)$/; exports.normalize = function(path) { var isAbsolute = path.charAt(0) === '/', trailingSlash = path.slice(-1) === '/'; path = normalizeArray( path.split('/').filter(function(p) { return !!p; }), !isAbsolute, ).join('/'); if (!path && !isAbsolute) { path = '.'; } if (path && trailingSlash) { path += '/'; } return (isAbsolute ? '/' : '') + path; }; exports.join = function() { var paths = Array.prototype.slice.call(arguments, 0); return exports.normalize( paths .filter(function(p, index) { return p && typeof p === 'string'; }) .join('/'), ); }; exports.relative = function(from, to) { from = exports.resolve(from).substr(1); to = exports.resolve(to).substr(1); function trim(arr) { var start = 0; for (; start < arr.length; start++) { if (arr[start] !== '') break; } var end = arr.length - 1; for (; end >= 0; end--) { if (arr[end] !== '') break; } if (start > end) return []; return arr.slice(start, end - start + 1); } var fromParts = trim(from.split('/')); var toParts = trim(to.split('/')); var length = Math.min(fromParts.length, toParts.length); var samePartsLength = length; for (var i = 0; i < length; i++) { if (fromParts[i] !== toParts[i]) { samePartsLength = i; break; } } var outputParts = []; for (var i = samePartsLength; i < fromParts.length; i++) { outputParts.push('..'); } outputParts = outputParts.concat(toParts.slice(samePartsLength)); return outputParts.join('/'); }; exports.dirname = function(path) { var dir = splitPathRe.exec(path)[1] || ''; if (!dir) { return '.'; } else if ( dir.length === 1 || (isWindows && dir.length <= 3 && dir.charAt(1) === ':') ) { return dir; } else { return dir.substring(0, dir.length - 1); } }; exports.basename = function(path, ext) { var f = splitPathRe.exec(path)[2] || ''; if (ext && f.substr(-1 * ext.length) === ext) { f = f.substr(0, f.length - ext.length); } return f; }; exports.extname = function(path) { return splitPathRe.exec(path)[3] || ''; }; }); require.register('colors.js', function(module, exports, require) { module.exports = { aliceblue: [240, 248, 255, 1], antiquewhite: [250, 235, 215, 1], aqua: [0, 255, 255, 1], aquamarine: [127, 255, 212, 1], azure: [240, 255, 255, 1], beige: [245, 245, 220, 1], bisque: [255, 228, 196, 1], black: [0, 0, 0, 1], blanchedalmond: [255, 235, 205, 1], blue: [0, 0, 255, 1], blueviolet: [138, 43, 226, 1], brown: [165, 42, 42, 1], burlywood: [222, 184, 135, 1], cadetblue: [95, 158, 160, 1], chartreuse: [127, 255, 0, 1], chocolate: [210, 105, 30, 1], coral: [255, 127, 80, 1], cornflowerblue: [100, 149, 237, 1], cornsilk: [255, 248, 220, 1], crimson: [220, 20, 60, 1], cyan: [0, 255, 255, 1], darkblue: [0, 0, 139, 1], darkcyan: [0, 139, 139, 1], darkgoldenrod: [184, 134, 11, 1], darkgray: [169, 169, 169, 1], darkgreen: [0, 100, 0, 1], darkgrey: [169, 169, 169, 1], darkkhaki: [189, 183, 107, 1], darkmagenta: [139, 0, 139, 1], darkolivegreen: [85, 107, 47, 1], darkorange: [255, 140, 0, 1], darkorchid: [153, 50, 204, 1], darkred: [139, 0, 0, 1], darksalmon: [233, 150, 122, 1], darkseagreen: [143, 188, 143, 1], darkslateblue: [72, 61, 139, 1], darkslategray: [47, 79, 79, 1], darkslategrey: [47, 79, 79, 1], darkturquoise: [0, 206, 209, 1], darkviolet: [148, 0, 211, 1], deeppink: [255, 20, 147, 1], deepskyblue: [0, 191, 255, 1], dimgray: [105, 105, 105, 1], dimgrey: [105, 105, 105, 1], dodgerblue: [30, 144, 255, 1], firebrick: [178, 34, 34, 1], floralwhite: [255, 250, 240, 1], forestgreen: [34, 139, 34, 1], fuchsia: [255, 0, 255, 1], gainsboro: [220, 220, 220, 1], ghostwhite: [248, 248, 255, 1], gold: [255, 215, 0, 1], goldenrod: [218, 165, 32, 1], gray: [128, 128, 128, 1], green: [0, 128, 0, 1], greenyellow: [173, 255, 47, 1], grey: [128, 128, 128, 1], honeydew: [240, 255, 240, 1], hotpink: [255, 105, 180, 1], indianred: [205, 92, 92, 1], indigo: [75, 0, 130, 1], ivory: [255, 255, 240, 1], khaki: [240, 230, 140, 1], lavender: [230, 230, 250, 1], lavenderblush: [255, 240, 245, 1], lawngreen: [124, 252, 0, 1], lemonchiffon: [255, 250, 205, 1], lightblue: [173, 216, 230, 1], lightcoral: [240, 128, 128, 1], lightcyan: [224, 255, 255, 1], lightgoldenrodyellow: [250, 250, 210, 1], lightgray: [211, 211, 211, 1], lightgreen: [144, 238, 144, 1], lightgrey: [211, 211, 211, 1], lightpink: [255, 182, 193, 1], lightsalmon: [255, 160, 122, 1], lightseagreen: [32, 178, 170, 1], lightskyblue: [135, 206, 250, 1], lightslategray: [119, 136, 153, 1], lightslategrey: [119, 136, 153, 1], lightsteelblue: [176, 196, 222, 1], lightyellow: [255, 255, 224, 1], lime: [0, 255, 0, 1], limegreen: [50, 205, 50, 1], linen: [250, 240, 230, 1], magenta: [255, 0, 255, 1], maroon: [128, 0, 0, 1], mediumaquamarine: [102, 205, 170, 1], mediumblue: [0, 0, 205, 1], mediumorchid: [186, 85, 211, 1], mediumpurple: [147, 112, 219, 1], mediumseagreen: [60, 179, 113, 1], mediumslateblue: [123, 104, 238, 1], mediumspringgreen: [0, 250, 154, 1], mediumturquoise: [72, 209, 204, 1], mediumvioletred: [199, 21, 133, 1], midnightblue: [25, 25, 112, 1], mintcream: [245, 255, 250, 1], mistyrose: [255, 228, 225, 1], moccasin: [255, 228, 181, 1], navajowhite: [255, 222, 173, 1], navy: [0, 0, 128, 1], oldlace: [253, 245, 230, 1], olive: [128, 128, 0, 1], olivedrab: [107, 142, 35, 1], orange: [255, 165, 0, 1], orangered: [255, 69, 0, 1], orchid: [218, 112, 214, 1], palegoldenrod: [238, 232, 170, 1], palegreen: [152, 251, 152, 1], paleturquoise: [175, 238, 238, 1], palevioletred: [219, 112, 147, 1], papayawhip: [255, 239, 213, 1], peachpuff: [255, 218, 185, 1], peru: [205, 133, 63, 1], pink: [255, 192, 203, 1], plum: [221, 160, 221, 1], powderblue: [176, 224, 230, 1], purple: [128, 0, 128, 1], red: [255, 0, 0, 1], rosybrown: [188, 143, 143, 1], royalblue: [65, 105, 225, 1], saddlebrown: [139, 69, 19, 1], salmon: [250, 128, 114, 1], sandybrown: [244, 164, 96, 1], seagreen: [46, 139, 87, 1], seashell: [255, 245, 238, 1], sienna: [160, 82, 45, 1], silver: [192, 192, 192, 1], skyblue: [135, 206, 235, 1], slateblue: [106, 90, 205, 1], slategray: [112, 128, 144, 1], slategrey: [112, 128, 144, 1], snow: [255, 250, 250, 1], springgreen: [0, 255, 127, 1], steelblue: [70, 130, 180, 1], tan: [210, 180, 140, 1], teal: [0, 128, 128, 1], thistle: [216, 191, 216, 1], tomato: [255, 99, 71, 1], transparent: [0, 0, 0, 0], turquoise: [64, 224, 208, 1], violet: [238, 130, 238, 1], wheat: [245, 222, 179, 1], white: [255, 255, 255, 1], whitesmoke: [245, 245, 245, 1], yellow: [255, 255, 0, 1], yellowgreen: [154, 205, 50, 1], rebeccapurple: [102, 51, 153, 1], }; }); require.register('errors.js', function(module, exports, require) { exports.ParseError = ParseError; exports.SyntaxError = SyntaxError; SyntaxError.prototype.__proto__ = Error.prototype; function ParseError(msg) { this.name = 'ParseError'; this.message = msg; Error.captureStackTrace(this, ParseError); } ParseError.prototype.__proto__ = Error.prototype; function SyntaxError(msg) { this.name = 'SyntaxError'; this.message = msg; Error.captureStackTrace(this, ParseError); } SyntaxError.prototype.__proto__ = Error.prototype; }); require.register('units.js', function(module, exports, require) { module.exports = [ 'em', 'ex', 'ch', 'rem', 'vw', 'vh', 'vmin', 'vmax', 'cm', 'mm', 'in', 'pt', 'pc', 'px', 'deg', 'grad', 'rad', 'turn', 's', 'ms', 'Hz', 'kHz', 'dpi', 'dpcm', 'dppx', 'x', '%', 'fr', ]; }); require.register('functions/index.js', function(module, exports, require) { exports['add-property'] = require('./add-property'); exports.adjust = require('./adjust'); exports.alpha = require('./alpha'); exports['base-convert'] = require('./base-convert'); exports.basename = require('./basename'); exports.blend = require('./blend'); exports.blue = require('./blue'); exports.clone = require('./clone'); exports.component = require('./component'); exports.contrast = require('./contrast'); exports.convert = require('./convert'); exports['current-media'] = require('./current-media'); exports.define = require('./define'); exports.dirname = require('./dirname'); exports.error = require('./error'); exports.extname = require('./extname'); exports.green = require('./green'); exports.hsl = require('./hsl'); exports.hsla = require('./hsla'); exports.hue = require('./hue'); exports.length = require('./length'); exports.lightness = require('./lightness'); exports['list-separator'] = require('./list-separator'); exports.lookup = require('./lookup'); exports.luminosity = require('./luminosity'); exports.match = require('./match'); exports.math = require('./math'); exports.merge = exports.extend = require('./merge'); exports.operate = require('./operate'); exports['opposite-position'] = require('./opposite-position'); exports.p = require('./p'); exports.pathjoin = require('./pathjoin'); exports.pop = require('./pop'); exports.push = exports.append = require('./push'); exports.range = require('./range'); exports.red = require('./red'); exports.remove = require('./remove'); exports.replace = require('./replace'); exports.rgb = require('./rgb'); exports.rgba = require('./rgba'); exports.s = require('./s'); exports.saturation = require('./saturation'); exports['selector-exists'] = require('./selector-exists'); exports.selector = require('./selector'); exports.selectors = require('./selectors'); exports.shift = require('./shift'); exports.split = require('./split'); exports.substr = require('./substr'); exports.slice = require('./slice'); exports.tan = require('./tan'); exports.trace = require('./trace'); exports.transparentify = require('./transparentify'); exports.type = exports.typeof = exports['type-of'] = require('./type'); exports.unit = require('./unit'); exports.unquote = require('./unquote'); exports.unshift = exports.prepend = require('./unshift'); exports.warn = require('./warn'); exports['-math-prop'] = require('./math-prop'); exports['-prefix-classes'] = require('./prefix-classes'); }); require.register('functions/url.js', function(module, exports, require) { var Compiler = require('../visitor/compiler'), events = require('../renderer').events, nodes = require('../nodes'), extname = require('../path').extname, utils = require('../utils'); var defaultMimes = { '.gif': 'image/gif', '.png': 'image/png', '.jpg': 'image/jpeg', '.jpeg': 'image/jpeg', '.svg': 'image/svg+xml', '.webp': 'image/webp', '.ttf': 'application/x-font-ttf', '.eot': 'application/vnd.ms-fontobject', '.woff': 'application/font-woff', '.woff2': 'application/font-woff2', }; var encodingTypes = { BASE_64: 'base64', UTF8: 'charset=utf-8' }; module.exports = function(options) { options = options || {}; var _paths = options.paths || []; var sizeLimit = null != options.limit ? options.limit : 3e4; var mimes = options.mimes || defaultMimes; function fn(url, enc) { var compiler = new Compiler(url), encoding = encodingTypes.BASE_64; compiler.isURL = true; url = url.nodes .map(function(node) { return compiler.visit(node); }) .join(''); url = parse(url); var ext = extname(url.pathname), mime = mimes[ext], hash = url.hash || '', literal = new nodes.Literal('url("' + url.href + '")'), paths = _paths.concat(this.paths), buf, result; if (!mime) return literal; if (url.protocol) return literal; var found = utils.lookup(url.pathname, paths); if (!found) { events.emit( 'file not found', 'File ' + literal + ' could not be found, literal url retained!', ); return literal; } buf = fs.readFileSync(found); if (false !== sizeLimit && buf.length > sizeLimit) return literal; if (enc && 'utf8' == enc.first.val.toLowerCase()) { encoding = encodingTypes.UTF8; result = buf .toString('utf8') .replace(/\s+/g, ' ') .replace(/[{}\|\\\^~\[\]`"<>#%]/g, function(match) { return '%' + match[0].charCodeAt(0).toString(16).toUpperCase(); }) .trim(); } else { result = buf.toString(encoding) + hash; } return new nodes.Literal( 'url("data:' + mime + ';' + encoding + ',' + result + '")', ); } fn.raw = true; return fn; }; module.exports.mimes = defaultMimes; }); require.register('functions/add-property.js', function( module, exports, require, ) { var utils = require('../utils'), nodes = require('../nodes'); (module.exports = function addProperty(name, expr) { utils.assertType(name, 'expression', 'name'); name = utils.unwrap(name).first; utils.assertString(name, 'name'); utils.assertType(expr, 'expression', 'expr'); var prop = new nodes.Property([name], expr); var block = this.closestBlock; var len = block.nodes.length, head = block.nodes.slice(0, block.index), tail = block.nodes.slice(block.index++, len); head.push(prop); block.nodes = head.concat(tail); return prop; }).raw = true; }); require.register('functions/adjust.js', function(module, exports, require) { var utils = require('../utils'); module.exports = function adjust(color, prop, amount) { utils.assertColor(color, 'color'); utils.assertString(prop, 'prop'); utils.assertType(amount, 'unit', 'amount'); var hsl = color.hsla.clone(); prop = { hue: 'h', saturation: 's', lightness: 'l' }[prop.string]; if (!prop) throw new Error('invalid adjustment property'); var val = amount.val; if ('%' == amount.type) { val = 'l' == prop && val > 0 ? (100 - hsl[prop]) * val / 100 : hsl[prop] * (val / 100); } hsl[prop] += val; return hsl.rgba; }; }); require.register('functions/alpha.js', function(module, exports, require) { var nodes = require('../nodes'), rgba = require('./rgba'); module.exports = function alpha(color, value) { color = color.rgba; if (value) { return rgba( new nodes.Unit(color.r), new nodes.Unit(color.g), new nodes.Unit(color.b), value, ); } return new nodes.Unit(color.a, ''); }; }); require.register('functions/base-convert.js', function( module, exports, require, ) { var utils = require('../utils'), nodes = require('../nodes'); (module.exports = function(num, base, width) { utils.assertPresent(num, 'number'); utils.assertPresent(base, 'base'); num = utils.unwrap(num).nodes[0].val; base = utils.unwrap(base).nodes[0].val; width = (width && utils.unwrap(width).nodes[0].val) || 2; var result = Number(num).toString(base); while (result.length < width) { result = '0' + result; } return new nodes.Literal(result); }).raw = true; }); require.register('functions/basename.js', function(module, exports, require) { var utils = require('../utils'), path = require('../path'); module.exports = function basename(p, ext) { utils.assertString(p, 'path'); return path.basename(p.val, ext && ext.val); }; }); require.register('functions/blend.js', function(module, exports, require) { var utils = require('../utils'), nodes = require('../nodes'); module.exports = function blend(top, bottom) { utils.assertColor(top); top = top.rgba; bottom = bottom || new nodes.RGBA(255, 255, 255, 1); utils.assertColor(bottom); bottom = bottom.rgba; return new nodes.RGBA( top.r * top.a + bottom.r * (1 - top.a), top.g * top.a + bottom.g * (1 - top.a), top.b * top.a + bottom.b * (1 - top.a), top.a + bottom.a - top.a * bottom.a, ); }; }); require.register('functions/blue.js', function(module, exports, require) { var nodes = require('../nodes'), rgba = require('./rgba'); module.exports = function blue(color, value) { color = color.rgba; if (value) { return rgba( new nodes.Unit(color.r), new nodes.Unit(color.g), value, new nodes.Unit(color.a), ); } return new nodes.Unit(color.b, ''); }; }); require.register('functions/clone.js', function(module, exports, require) { var utils = require('../utils'); (module.exports = function clone(expr) { utils.assertPresent(expr, 'expr'); return expr.clone(); }).raw = true; }); require.register('functions/component.js', function( module, exports, require, ) { var utils = require('../utils'), nodes = require('../nodes'); var componentMap = { red: 'r', green: 'g', blue: 'b', alpha: 'a', hue: 'h', saturation: 's', lightness: 'l', }; var unitMap = { hue: 'deg', saturation: '%', lightness: '%' }; var typeMap = { red: 'rgba', blue: 'rgba', green: 'rgba', alpha: 'rgba', hue: 'hsla', saturation: 'hsla', lightness: 'hsla', }; module.exports = function component(color, name) { utils.assertColor(color, 'color'); utils.assertString(name, 'name'); var name = name.string, unit = unitMap[name], type = typeMap[name], name = componentMap[name]; if (!name) throw new Error('invalid color component "' + name + '"'); return new nodes.Unit(color[type][name], unit); }; }); require.register('functions/contrast.js', function(module, exports, require) { var utils = require('../utils'), nodes = require('../nodes'), blend = require('./blend'), luminosity = require('./luminosity'); module.exports = function contrast(top, bottom) { if ('rgba' != top.nodeName && 'hsla' != top.nodeName) { return new nodes.Literal( 'contrast(' + (top.isNull ? '' : top.toString()) + ')', ); } var result = new nodes.Object(); top = top.rgba; bottom = bottom || new nodes.RGBA(255, 255, 255, 1); utils.assertColor(bottom); bottom = bottom.rgba; function contrast(top, bottom) { if (1 > top.a) { top = blend(top, bottom); } var l1 = luminosity(bottom).val + 0.05, l2 = luminosity(top).val + 0.05, ratio = l1 / l2; if (l2 > l1) { ratio = 1 / ratio; } return Math.round(ratio * 10) / 10; } if (1 <= bottom.a) { var resultRatio = new nodes.Unit(contrast(top, bottom)); result.set('ratio', resultRatio); result.set('error', new nodes.Unit(0)); result.set('min', resultRatio); result.set('max', resultRatio); } else { var onBlack = contrast(top, blend(bottom, new nodes.RGBA(0, 0, 0, 1))), onWhite = contrast( top, blend(bottom, new nodes.RGBA(255, 255, 255, 1)), ), max = Math.max(onBlack, onWhite); function processChannel(topChannel, bottomChannel) { return Math.min( Math.max( 0, (topChannel - bottomChannel * bottom.a) / (1 - bottom.a), ), 255, ); } var closest = new nodes.RGBA( processChannel(top.r, bottom.r), processChannel(top.g, bottom.g), processChannel(top.b, bottom.b), 1, ); var min = contrast(top, blend(bottom, closest)); result.set('ratio', new nodes.Unit(Math.round((min + max) * 50) / 100)); result.set('error', new nodes.Unit(Math.round((max - min) * 50) / 100)); result.set('min', new nodes.Unit(min)); result.set('max', new nodes.Unit(max)); } return result; }; }); require.register('functions/convert.js', function(module, exports, require) { var utils = require('../utils'); module.exports = function convert(str) { utils.assertString(str, 'str'); return utils.parseString(str.string); }; }); require.register('functions/current-media.js', function( module, exports, require, ) { var nodes = require('../nodes'); module.exports = function currentMedia() { var self = this; return new nodes.String(lookForMedia(this.closestBlock.node) || ''); function lookForMedia(node) { if ('media' == node.nodeName) { node.val = self.visit(node.val); return node.toString(); } else if (node.block.parent.node) { return lookForMedia(node.block.parent.node); } } }; }); require.register('functions/define.js', function(module, exports, require) { var utils = require('../utils'), nodes = require('../nodes'); module.exports = function define(name, expr, global) { utils.assertType(name, 'string', 'name'); expr = utils.unwrap(expr); var scope = this.currentScope; if (global && global.toBoolean().isTrue) { scope = this.global.scope; } var node = new nodes.Ident(name.val, expr); scope.add(node); return nodes.nil; }; }); require.register('functions/dirname.js', function(module, exports, require) { var utils = require('../utils'), path = require('../path'); module.exports = function dirname(p) { utils.assertString(p, 'path'); return path.dirname(p.val).replace(/\\/g, '/'); }; }); require.register('functions/error.js', function(module, exports, require) { var utils = require('../utils'); module.exports = function error(msg) { utils.assertType(msg, 'string', 'msg'); var err = new Error(msg.val); err.fromStylus = true; throw err; }; }); require.register('functions/extname.js', function(module, exports, require) { var utils = require('../utils'), path = require('../path'); module.exports = function extname(p) { utils.assertString(p, 'path'); return path.extname(p.val); }; }); require.register('functions/green.js', function(module, exports, require) { var nodes = require('../nodes'), rgba = require('./rgba'); module.exports = function green(color, value) { color = color.rgba; if (value) { return rgba( new nodes.Unit(color.r), value, new nodes.Unit(color.b), new nodes.Unit(color.a), ); } return new nodes.Unit(color.g, ''); }; }); require.register('functions/hsl.js', function(module, exports, require) { var utils = require('../utils'), nodes = require('../nodes'), hsla = require('./hsla'); module.exports = function hsl(hue, saturation, lightness) { if (1 == arguments.length) { utils.assertColor(hue, 'color'); return hue.hsla; } else { return hsla(hue, saturation, lightness, new nodes.Unit(1)); } }; }); require.register('functions/hsla.js', function(module, exports, require) { var utils = require('../utils'), nodes = require('../nodes'); module.exports = function hsla(hue, saturation, lightness, alpha) { switch (arguments.length) { case 1: utils.assertColor(hue); return hue.hsla; case 2: utils.assertColor(hue); var color = hue.hsla; utils.assertType(saturation, 'unit', 'alpha'); var alpha = saturation.clone(); if ('%' == alpha.type) alpha.val /= 100; return new nodes.HSLA(color.h, color.s, color.l, alpha.val); default: utils.assertType(hue, 'unit', 'hue'); utils.assertType(saturation, 'unit', 'saturation'); utils.assertType(lightness, 'unit', 'lightness'); utils.assertType(alpha, 'unit', 'alpha'); var alpha = alpha.clone(); if (alpha && '%' == alpha.type) alpha.val /= 100; return new nodes.HSLA( hue.val, saturation.val, lightness.val, alpha.val, ); } }; }); require.register('functions/hue.js', function(module, exports, require) { var nodes = require('../nodes'), hsla = require('./hsla'), component = require('./component'); module.exports = function hue(color, value) { if (value) { var hslaColor = color.hsla; return hsla( value, new nodes.Unit(hslaColor.s), new nodes.Unit(hslaColor.l), new nodes.Unit(hslaColor.a), ); } return component(color, new nodes.String('hue')); }; }); require.register('functions/length.js', function(module, exports, require) { var utils = require('../utils'); (module.exports = function length(expr) { if (expr) { if (expr.nodes) { var nodes = utils.unwrap(expr).nodes; if (1 == nodes.length && 'object' == nodes[0].nodeName) { return nodes[0].length; } else { return nodes.length; } } else { return 1; } } return 0; }).raw = true; }); require.register('functions/lightness.js', function( module, exports, require, ) { var nodes = require('../nodes'), hsla = require('./hsla'), component = require('./component'); module.exports = function lightness(color, value) { if (value) { var hslaColor = color.hsla; return hsla( new nodes.Unit(hslaColor.h), new nodes.Unit(hslaColor.s), value, new nodes.Unit(hslaColor.a), ); } return component(color, new nodes.String('lightness')); }; }); require.register('functions/list-separator.js', function( module, exports, require, ) { var utils = require('../utils'), nodes = require('../nodes'); (module.exports = function listSeparator(list) { list = utils.unwrap(list); return new nodes.String(list.isList ? ',' : ' '); }).raw = true; }); require.register('functions/lookup.js', function(module, exports, require) { var utils = require('../utils'), nodes = require('../nodes'); module.exports = function lookup(name) { utils.assertType(name, 'string', 'name'); var node = this.lookup(name.val); if (!node) return nodes.nil; return this.visit(node); }; }); require.register('functions/luminosity.js', function( module, exports, require, ) { var utils = require('../utils'), nodes = require('../nodes'); module.exports = function luminosity(color) { utils.assertColor(color); color = color.rgba; function processChannel(channel) { channel = channel / 255; return 0.03928 > channel ? channel / 12.92 : Math.pow((channel + 0.055) / 1.055, 2.4); } return new nodes.Unit( 0.2126 * processChannel(color.r) + 0.7152 * processChannel(color.g) + 0.0722 * processChannel(color.b), ); }; }); require.register('functions/match.js', function(module, exports, require) { var utils = require('../utils'), nodes = require('../nodes'); var VALID_FLAGS = 'igm'; module.exports = function match(pattern, val, flags) { utils.assertType(pattern, 'string', 'pattern'); utils.assertString(val, 'val'); var re = new RegExp( pattern.val, validateFlags(flags) ? flags.string : '', ); return val.string.match(re); }; function validateFlags(flags) { flags = flags && flags.string; if (flags) { return flags.split('').every(function(flag) { return ~VALID_FLAGS.indexOf(flag); }); } return false; } }); require.register('functions/math-prop.js', function( module, exports, require, ) { var nodes = require('../nodes'); module.exports = function math(prop) { return new nodes.Unit(Math[prop.string]); }; }); require.register('functions/math.js', function(module, exports, require) { var utils = require('../utils'), nodes = require('../nodes'); module.exports = function math(n, fn) { utils.assertType(n, 'unit', 'n'); utils.assertString(fn, 'fn'); return new nodes.Unit(Math[fn.string](n.val), n.type); }; }); require.register('functions/merge.js', function(module, exports, require) { var utils = require('../utils'); (module.exports = function merge(dest) { utils.assertPresent(dest, 'dest'); dest = utils.unwrap(dest).first; utils.assertType(dest, 'object', 'dest'); var last = utils.unwrap(arguments[arguments.length - 1]).first, deep = true === last.val; for (var i = 1, len = arguments.length - deep; i < len; ++i) { utils.merge(dest.vals, utils.unwrap(arguments[i]).first.vals, deep); } return dest; }).raw = true; }); require.register('functions/operate.js', function(module, exports, require) { var utils = require('../utils'); module.exports = function operate(op, left, right) { utils.assertType(op, 'string', 'op'); utils.assertPresent(left, 'left'); utils.assertPresent(right, 'right'); return left.operate(op.val, right); }; }); require.register('functions/opposite-position.js', function( module, exports, require, ) { var utils = require('../utils'), nodes = require('../nodes'); (module.exports = function oppositePosition(positions) { var expr = []; utils.unwrap(positions).nodes.forEach(function(pos, i) { utils.assertString(pos, 'position ' + i); pos = (function() { switch (pos.string) { case 'top': return 'bottom'; case 'bottom': return 'top'; case 'left': return 'right'; case 'right': return 'left'; case 'center': return 'center'; default: throw new Error('invalid position ' + pos); } })(); expr.push(new nodes.Literal(pos)); }); return expr; }).raw = true; }); require.register('functions/p.js', function(module, exports, require) { var utils = require('../utils'), nodes = require('../nodes'); (module.exports = function p() { [].slice.call(arguments).forEach(function(expr) { expr = utils.unwrap(expr); if (!expr.nodes.length) return; console.log( 'inspect: %s', expr.toString().replace(/^\(|\)$/g, ''), ); }); return nodes.nil; }).raw = true; }); require.register('functions/pathjoin.js', function(module, exports, require) { var path = require('../path'); (module.exports = function pathjoin() { var paths = [].slice.call(arguments).map(function(path) { return path.first.string; }); return path.join.apply(null, paths).replace(/\\/g, '/'); }).raw = true; }); require.register('functions/pop.js', function(module, exports, require) { var utils = require('../utils'); (module.exports = function pop(expr) { expr = utils.unwrap(expr); return expr.nodes.pop(); }).raw = true; }); require.register('functions/prefix-classes.js', function( module, exports, require, ) { var utils = require('../utils'); module.exports = function prefixClasses(prefix, block) { utils.assertString(prefix, 'prefix'); utils.assertType(block, 'block', 'block'); var _prefix = this.prefix; this.options.prefix = this.prefix = prefix.string; block = this.visit(block); this.options.prefix = this.prefix = _prefix; return block; }; }); require.register('functions/push.js', function(module, exports, require) { var utils = require('../utils'); (module.exports = function(expr) { expr = utils.unwrap(expr); for (var i = 1, len = arguments.length; i < len; ++i) { expr.nodes.push(utils.unwrap(arguments[i]).clone()); } return expr.nodes.length; }).raw = true; }); require.register('functions/range.js', function(module, exports, require) { var utils = require('../utils'), nodes = require('../nodes'); module.exports = function range(start, stop, step) { utils.assertType(start, 'unit', 'start'); utils.assertType(stop, 'unit', 'stop'); if (step) { utils.assertType(step, 'unit', 'step'); if (0 == step.val) { throw new Error('ArgumentError: "step" argument must not be zero'); } } else { step = new nodes.Unit(1); } var list = new nodes.Expression(); for (var i = start.val; i <= stop.val; i += step.val) { list.push(new nodes.Unit(i, start.type)); } return list; }; }); require.register('functions/red.js', function(module, exports, require) { var nodes = require('../nodes'), rgba = require('./rgba'); module.exports = function red(color, value) { color = color.rgba; if (value) { return rgba( value, new nodes.Unit(color.g), new nodes.Unit(color.b), new nodes.Unit(color.a), ); } return new nodes.Unit(color.r, ''); }; }); require.register('functions/remove.js', function(module, exports, require) { var utils = require('../utils'); module.exports = function remove(object, key) { utils.assertType(object, 'object', 'object'); utils.assertString(key, 'key'); delete object.vals[key.string]; return object; }; }); require.register('functions/replace.js', function(module, exports, require) { var utils = require('../utils'), nodes = require('../nodes'); module.exports = function replace(pattern, replacement, val) { utils.assertString(pattern, 'pattern'); utils.assertString(replacement, 'replacement'); utils.assertString(val, 'val'); pattern = new RegExp(pattern.string, 'g'); var res = val.string.replace(pattern, replacement.string); return val instanceof nodes.Ident ? new nodes.Ident(res) : new nodes.String(res); }; }); require.register('functions/rgb.js', function(module, exports, require) { var utils = require('../utils'), nodes = require('../nodes'), rgba = require('./rgba'); module.exports = function rgb(red, green, blue) { switch (arguments.length) { case 1: utils.assertColor(red); var color = red.rgba; return new nodes.RGBA(color.r, color.g, color.b, 1); default: return rgba(red, green, blue, new nodes.Unit(1)); } }; }); require.register('functions/rgba.js', function(module, exports, require) { var utils = require('../utils'), nodes = require('../nodes'); module.exports = function rgba(red, green, blue, alpha) { switch (arguments.length) { case 1: utils.assertColor(red); return red.rgba; case 2: utils.assertColor(red); var color = red.rgba; utils.assertType(green, 'unit', 'alpha'); alpha = green.clone(); if ('%' == alpha.type) alpha.val /= 100; return new nodes.RGBA(color.r, color.g, color.b, alpha.val); default: utils.assertType(red, 'unit', 'red'); utils.assertType(green, 'unit', 'green'); utils.assertType(blue, 'unit', 'blue'); utils.assertType(alpha, 'unit', 'alpha'); var r = '%' == red.type ? Math.round(red.val * 2.55) : red.val, g = '%' == green.type ? Math.round(green.val * 2.55) : green.val, b = '%' == blue.type ? Math.round(blue.val * 2.55) : blue.val; alpha = alpha.clone(); if (alpha && '%' == alpha.type) alpha.val /= 100; return new nodes.RGBA(r, g, b, alpha.val); } }; }); require.register('functions/s.js', function(module, exports, require) { var utils = require('../utils'), nodes = require('../nodes'), Compiler = require('../visitor/compiler'); (module.exports = function s(fmt) { fmt = utils.unwrap(fmt).nodes[0]; utils.assertString(fmt); var self = this, str = fmt.string, args = arguments, i = 1; str = str.replace(/%(s|d)/g, function(_, specifier) { var arg = args[i++] || nodes.nil; switch (specifier) { case 's': return new Compiler(arg, self.options).compile(); case 'd': arg = utils.unwrap(arg).first; if ('unit' != arg.nodeName) throw new Error('%d requires a unit'); return arg.val; } }); return new nodes.Literal(str); }).raw = true; }); require.register('functions/saturation.js', function( module, exports, require, ) { var nodes = require('../nodes'), hsla = require('./hsla'), component = require('./component'); module.exports = function saturation(color, value) { if (value) { var hslaColor = color.hsla; return hsla( new nodes.Unit(hslaColor.h), value, new nodes.Unit(hslaColor.l), new nodes.Unit(hslaColor.a), ); } return component(color, new nodes.String('saturation')); }; }); require.register('functions/selector-exists.js', function( module, exports, require, ) { var utils = require('../utils'); module.exports = function selectorExists(sel) { utils.assertString(sel, 'selector'); if (!this.__selectorsMap__) { var Normalizer = require('../visitor/normalizer'), visitor = new Normalizer(this.root.clone()); visitor.visit(visitor.root); this.__selectorsMap__ = visitor.map; } return sel.string in this.__selectorsMap__; }; }); require.register('functions/selector.js', function(module, exports, require) { var utils = require('../utils'); (module.exports = function selector() { var stack = this.selectorStack, args = [].slice.call(arguments); if (1 == args.length) { var expr = utils.unwrap(args[0]), len = expr.nodes.length; if (1 == len) { utils.assertString(expr.first, 'selector'); var SelectorParser = require('../selector-parser'), val = expr.first.string, parsed = new SelectorParser(val).parse().val; if (parsed == val) return val; stack.push(parse(val)); } else if (len > 1) { if (expr.isList) { pushToStack(expr.nodes, stack); } else { stack.push( parse( expr.nodes .map(function(node) { utils.assertString(node, 'selector'); return node.string; }) .join(' '), ), ); } } } else if (args.length > 1) { pushToStack(args, stack); } return stack.length ? utils.compileSelectors(stack).join(',') : '&'; }).raw = true; function pushToStack(selectors, stack) { selectors.forEach(function(sel) { sel = sel.first; utils.assertString(sel, 'selector'); stack.push(parse(sel.string)); }); } function parse(selector) { var Parser = new require('../parser'), parser = new Parser(selector), nodes; parser.state.push('selector-parts'); nodes = parser.selector(); nodes.forEach(function(node) { node.val = node.segments .map(function(seg) { return seg.toString(); }) .join(''); }); return nodes; } }); require.register('functions/selectors.js', function( module, exports, require, ) { var nodes = require('../nodes'), Parser = require('../selector-parser'); module.exports = function selectors() { var stack = this.selectorStack, expr = new nodes.Expression(true); if (stack.length) { for (var i = 0; i < stack.length; i++) { var group = stack[i], nested; if (group.length > 1) { expr.push( new nodes.String( group .map(function(selector) { nested = new Parser(selector.val).parse().nested; return (nested && i ? '& ' : '') + selector.val; }) .join(','), ), ); } else { var selector = group[0].val; nested = new Parser(selector).parse().nested; expr.push(new nodes.String((nested && i ? '& ' : '') + selector)); } } } else { expr.push(new nodes.String('&')); } return expr; }; }); require.register('functions/shift.js', function(module, exports, require) { var utils = require('../utils'); (module.exports = function(expr) { expr = utils.unwrap(expr); return expr.nodes.shift(); }).raw = true; }); require.register('functions/split.js', function(module, exports, require) { var utils = require('../utils'), nodes = require('../nodes'); module.exports = function split(delim, val) { utils.assertString(delim, 'delimiter'); utils.assertString(val, 'val'); var splitted = val.string.split(delim.string); var expr = new nodes.Expression(); var ItemNode = val instanceof nodes.Ident ? nodes.Ident : nodes.String; for (var i = 0, len = splitted.length; i < len; ++i) { expr.nodes.push(new ItemNode(splitted[i])); } return expr; }; }); require.register('functions/slice.js', function(module, exports, require) { var utils = require('../utils'), nodes = require('../nodes'); (module.exports = function slice(val, start, end) { start = start && start.nodes[0].val; end = end && end.nodes[0].val; val = utils.unwrap(val).nodes; if (val.length > 1) { return utils.coerce(val.slice(start, end), true); } var result = val[0].string.slice(start, end); return val[0] instanceof nodes.Ident ? new nodes.Ident(result) : new nodes.String(result); }).raw = true; }); require.register('functions/substr.js', function(module, exports, require) { var utils = require('../utils'), nodes = require('../nodes'); module.exports = function substr(val, start, length) { utils.assertString(val, 'val'); utils.assertType(start, 'unit', 'start'); length = length && length.val; var res = val.string.substr(start.val, length); return val instanceof nodes.Ident ? new nodes.Ident(res) : new nodes.String(res); }; }); require.register('functions/tan.js', function(module, exports, require) { var utils = require('../utils'), nodes = require('../nodes'); module.exports = function tan(angle) { utils.assertType(angle, 'unit', 'angle'); var radians = angle.val; if (angle.type === 'deg') { radians *= Math.PI / 180; } var m = Math.pow(10, 9); var sin = Math.round(Math.sin(radians) * m) / m, cos = Math.round(Math.cos(radians) * m) / m, tan = Math.round(m * sin / cos) / m; return new nodes.Unit(tan, ''); }; }); require.register('functions/trace.js', function(module, exports, require) { var nodes = require('../nodes'); module.exports = function trace() { console.log(this.stack); return nodes.nil; }; }); require.register('functions/transparentify.js', function( module, exports, require, ) { var utils = require('../utils'), nodes = require('../nodes'); module.exports = function transparentify(top, bottom, alpha) { utils.assertColor(top); top = top.rgba; bottom = bottom || new nodes.RGBA(255, 255, 255, 1); if (!alpha && bottom && !bottom.rgba) { alpha = bottom; bottom = new nodes.RGBA(255, 255, 255, 1); } utils.assertColor(bottom); bottom = bottom.rgba; var bestAlpha = ['r', 'g', 'b'] .map(function(channel) { return ( (top[channel] - bottom[channel]) / ((0 < top[channel] - bottom[channel] ? 255 : 0) - bottom[channel]) ); }) .sort(function(a, b) { return a < b; })[0]; if (alpha) { utils.assertType(alpha, 'unit', 'alpha'); if ('%' == alpha.type) { bestAlpha = alpha.val / 100; } else if (!alpha.type) { bestAlpha = alpha = alpha.val; } } bestAlpha = Math.max(Math.min(bestAlpha, 1), 0); function processChannel(channel) { if (0 == bestAlpha) { return bottom[channel]; } else { return bottom[channel] + (top[channel] - bottom[channel]) / bestAlpha; } } return new nodes.RGBA( processChannel('r'), processChannel('g'), processChannel('b'), Math.round(bestAlpha * 100) / 100, ); }; }); require.register('functions/type.js', function(module, exports, require) { var utils = require('../utils'); module.exports = function type(node) { utils.assertPresent(node, 'expression'); return node.nodeName; }; }); require.register('functions/unit.js', function(module, exports, require) { var utils = require('../utils'), nodes = require('../nodes'); module.exports = function unit(unit, type) { utils.assertType(unit, 'unit', 'unit'); if (type) { utils.assertString(type, 'type'); return new nodes.Unit(unit.val, type.string); } else { return unit.type || ''; } }; }); require.register('functions/unquote.js', function(module, exports, require) { var utils = require('../utils'), nodes = require('../nodes'); module.exports = function unquote(string) { utils.assertString(string, 'string'); return new nodes.Literal(string.string); }; }); require.register('functions/unshift.js', function(module, exports, require) { var utils = require('../utils'); (module.exports = function(expr) { expr = utils.unwrap(expr); for (var i = 1, len = arguments.length; i < len; ++i) { expr.nodes.unshift(utils.unwrap(arguments[i])); } return expr.nodes.length; }).raw = true; }); require.register('functions/warn.js', function(module, exports, require) { var utils = require('../utils'), nodes = require('../nodes'); module.exports = function warn(msg) { utils.assertType(msg, 'string', 'msg'); console.warn('Warning: %s', msg.val); return nodes.nil; }; }); require.register('lexer.js', function(module, exports, require) { var Token = require('./token'), nodes = require('./nodes'), errors = require('./errors'); exports = module.exports = Lexer; var alias = { and: '&&', or: '||', is: '==', isnt: '!=', 'is not': '!=', ':=': '?=', }; function Lexer(str, options) { options = options || {}; this.stash = []; this.indentStack = []; this.indentRe = null; this.lineno = 1; this.column = 1; function comment(str, val, offset, s) { var inComment = s.lastIndexOf('/*', offset) > s.lastIndexOf('*/', offset), commentIdx = s.lastIndexOf('//', offset), i = s.lastIndexOf('\n', offset), double = 0, single = 0; if (~commentIdx && commentIdx > i) { while (i != offset) { if ("'" == s[i]) single ? single-- : single++; if ('"' == s[i]) double ? double-- : double++; if ('/' == s[i] && '/' == s[i + 1]) { inComment = !single && !double; break; } ++i; } } return inComment ? str : val + '\r'; } if ('\ufeff' == str.charAt(0)) str = str.slice(1); this.str = str .replace(/\s+$/, '\n') .replace(/\r\n?/g, '\n') .replace(/\\ *\n/g, '\r') .replace( /([,(:](?!\/\/[^ ])) *(?:\/\/[^\n]*|\/\*.*?\*\/)?\n\s*/g, comment, ) .replace(/\s*\n[ \t]*([,)])/g, comment); } Lexer.prototype = { inspect: function() { var tok, tmp = this.str, buf = []; while ('eos' != (tok = this.next()).type) { buf.push(tok.inspect()); } this.str = tmp; return buf.concat(tok.inspect()).join('\n'); }, lookahead: function(n) { var fetch = n - this.stash.length; while (fetch-- > 0) this.stash.push(this.advance()); return this.stash[--n]; }, skip: function(len) { var chunk = len[0]; len = chunk ? chunk.length : len; this.str = this.str.substr(len); if (chunk) { this.move(chunk); } else { this.column += len; } }, move: function(str) { var lines = str.match(/\n/g), idx = str.lastIndexOf('\n'); if (lines) this.lineno += lines.length; this.column = ~idx ? str.length - idx : this.column + str.length; }, next: function() { var tok = this.stashed() || this.advance(); this.prev = tok; return tok; }, isPartOfSelector: function() { var tok = this.stash[this.stash.length - 1] || this.prev; switch (tok && tok.type) { case 'color': return 2 == tok.val.raw.length; case '.': case '[': return true; } return false; }, advance: function() { var column = this.column, line = this.lineno, tok = this.eos() || this.nil() || this.sep() || this.keyword() || this.urlchars() || this.comment() || this.newline() || this.escaped() || this.important() || this.literal() || this.fun() || this.anonFunc() || this.atrule() || this.brace() || this.paren() || this.color() || this.string() || this.unit() || this.namedop() || this.boolean() || this.unicode() || this.ident() || this.op() || this.eol() || this.space() || this.selector(); tok.lineno = line; tok.column = column; return tok; }, peek: function() { return this.lookahead(1); }, stashed: function() { return this.stash.shift(); }, eos: function() { if (this.str.length) return; if (this.indentStack.length) { this.indentStack.shift(); return new Token('outdent'); } else { return new Token('eos'); } }, urlchars: function() { var captures; if (!this.isURL) return; if ((captures = /^[\/:@.;?&=*!,<>#%0-9]+/.exec(this.str))) { this.skip(captures); return new Token('literal', new nodes.Literal(captures[0])); } }, sep: function() { var captures; if ((captures = /^;[ \t]*/.exec(this.str))) { this.skip(captures); return new Token(';'); } }, eol: function() { if ('\r' == this.str[0]) { ++this.lineno; this.skip(1); return this.advance(); } }, space: function() { var captures; if ((captures = /^([ \t]+)/.exec(this.str))) { this.skip(captures); return new Token('space'); } }, escaped: function() { var captures; if ((captures = /^\\(.)[ \t]*/.exec(this.str))) { var c = captures[1]; this.skip(captures); return new Token('ident', new nodes.Literal(c)); } }, literal: function() { var captures; if ((captures = /^@css[ \t]*\{/.exec(this.str))) { this.skip(captures); var c, braces = 1, css = '', node; while ((c = this.str[0])) { this.str = this.str.substr(1); switch (c) { case '{': ++braces; break; case '}': --braces; break; case '\n': case '\r': ++this.lineno; break; } css += c; if (!braces) break; } css = css.replace(/\s*}$/, ''); node = new nodes.Literal(css); node.css = true; return new Token('literal', node); } }, important: function() { var captures; if ((captures = /^!important[ \t]*/.exec(this.str))) { this.skip(captures); return new Token('ident', new nodes.Literal('!important')); } }, brace: function() { var captures; if ((captures = /^([{}])/.exec(this.str))) { this.skip(1); var brace = captures[1]; return new Token(brace, brace); } }, paren: function() { var captures; if ((captures = /^([()])([ \t]*)/.exec(this.str))) { var paren = captures[1]; this.skip(captures); if (')' == paren) this.isURL = false; var tok = new Token(paren, paren); tok.space = captures[2]; return tok; } }, nil: function() { var captures, tok; if ((captures = /^(null)\b[ \t]*/.exec(this.str))) { this.skip(captures); if (this.isPartOfSelector()) { tok = new Token('ident', new nodes.Ident(captures[0])); } else { tok = new Token('null', nodes.nil); } return tok; } }, keyword: function() { var captures, tok; if ( (captures = /^(return|if|else|unless|for|in)\b[ \t]*/.exec(this.str)) ) { var keyword = captures[1]; this.skip(captures); if (this.isPartOfSelector()) { tok = new Token('ident', new nodes.Ident(captures[0])); } else { tok = new Token(keyword, keyword); } return tok; } }, namedop: function() { var captures, tok; if ( (captures = /^(not|and|or|is a|is defined|isnt|is not|is)(?!-)\b([ \t]*)/.exec( this.str, )) ) { var op = captures[1]; this.skip(captures); if (this.isPartOfSelector()) { tok = new Token('ident', new nodes.Ident(captures[0])); } else { op = alias[op] || op; tok = new Token(op, op); } tok.space = captures[2]; return tok; } }, op: function() { var captures; if ( (captures = /^([.]{1,3}|&&|\|\||[!<>=?:]=|\*\*|[-+*\/%]=?|[,=?:!~<>&\[\]])([ \t]*)/.exec( this.str, )) ) { var op = captures[1]; this.skip(captures); op = alias[op] || op; var tok = new Token(op, op); tok.space = captures[2]; this.isURL = false; return tok; } }, anonFunc: function() { var tok; if ('@' == this.str[0] && '(' == this.str[1]) { this.skip(2); tok = new Token('function', new nodes.Ident('anonymous')); tok.anonymous = true; return tok; } }, atrule: function() { var captures; if ( (captures = /^@(?:-(\w+)-)?([a-zA-Z0-9-_]+)[ \t]*/.exec(this.str)) ) { this.skip(captures); var vendor = captures[1], type = captures[2], tok; switch (type) { case 'require': case 'import': case 'charset': case 'namespace': case 'media': case 'scope': case 'supports': return new Token(type); case 'document': return new Token('-moz-document'); case 'block': return new Token('atblock'); case 'extend': case 'extends': return new Token('extend'); case 'keyframes': return new Token(type, vendor); default: return new Token( 'atrule', vendor ? '-' + vendor + '-' + type : type, ); } } }, comment: function() { if ('/' == this.str[0] && '/' == this.str[1]) { var end = this.str.indexOf('\n'); if (-1 == end) end = this.str.length; this.skip(end); return this.advance(); } if ('/' == this.str[0] && '*' == this.str[1]) { var end = this.str.indexOf('*/'); if (-1 == end) end = this.str.length; var str = this.str.substr(0, end + 2), lines = str.split(/\n|\r/).length - 1, suppress = true, inline = false; this.lineno += lines; this.skip(end + 2); if ('!' == str[2]) { str = str.replace('*!', '*'); suppress = false; } if (this.prev && ';' == this.prev.type) inline = true; return new Token('comment', new nodes.Comment(str, suppress, inline)); } }, boolean: function() { var captures; if ((captures = /^(true|false)\b([ \t]*)/.exec(this.str))) { var val = nodes.Boolean('true' == captures[1]); this.skip(captures); var tok = new Token('boolean', val); tok.space = captures[2]; return tok; } }, unicode: function() { var captures; if ( (captures = /^u\+[0-9a-f?]{1,6}(?:-[0-9a-f]{1,6})?/i.exec(this.str)) ) { this.skip(captures); return new Token('literal', new nodes.Literal(captures[0])); } }, fun: function() { var captures; if ((captures = /^(-*[_a-zA-Z$][-\w\d$]*)\(([ \t]*)/.exec(this.str))) { var name = captures[1]; this.skip(captures); this.isURL = 'url' == name; var tok = new Token('function', new nodes.Ident(name)); tok.space = captures[2]; return tok; } }, ident: function() { var captures; if ((captures = /^-*[_a-zA-Z$][-\w\d$]*/.exec(this.str))) { this.skip(captures); return new Token('ident', new nodes.Ident(captures[0])); } }, newline: function() { var captures, re; if (this.indentRe) { captures = this.indentRe.exec(this.str); } else { re = /^\n([\t]*)[ \t]*/; captures = re.exec(this.str); if (captures && !captures[1].length) { re = /^\n([ \t]*)/; captures = re.exec(this.str); } if (captures && captures[1].length) this.indentRe = re; } if (captures) { var tok, indents = captures[1].length; this.skip(captures); if (this.str[0] === ' ' || this.str[0] === ' ') { throw new errors.SyntaxError( 'Invalid indentation. You can use tabs or spaces to indent, but not both.', ); } if ('\n' == this.str[0]) return this.advance(); if (this.indentStack.length && indents < this.indentStack[0]) { while (this.indentStack.length && this.indentStack[0] > indents) { this.stash.push(new Token('outdent')); this.indentStack.shift(); } tok = this.stash.pop(); } else if (indents && indents != this.indentStack[0]) { this.indentStack.unshift(indents); tok = new Token('indent'); } else { tok = new Token('newline'); } return tok; } }, unit: function() { var captures; if ( (captures = /^(-)?(\d+\.\d+|\d+|\.\d+)(%|[a-zA-Z]+)?[ \t]*/.exec( this.str, )) ) { this.skip(captures); var n = parseFloat(captures[2]); if ('-' == captures[1]) n = -n; var node = new nodes.Unit(n, captures[3]); node.raw = captures[0]; return new Token('unit', node); } }, string: function() { var captures; if ((captures = /^("[^"]*"|'[^']*')[ \t]*/.exec(this.str))) { var str = captures[1], quote = captures[0][0]; this.skip(captures); str = str.slice(1, -1).replace(/\\n/g, '\n'); return new Token('string', new nodes.String(str, quote)); } }, color: function() { return ( this.rrggbbaa() || this.rrggbb() || this.rgba() || this.rgb() || this.nn() || this.n() ); }, n: function() { var captures; if ((captures = /^#([a-fA-F0-9]{1})[ \t]*/.exec(this.str))) { this.skip(captures); var n = parseInt(captures[1] + captures[1], 16), color = new nodes.RGBA(n, n, n, 1); color.raw = captures[0]; return new Token('color', color); } }, nn: function() { var captures; if ((captures = /^#([a-fA-F0-9]{2})[ \t]*/.exec(this.str))) { this.skip(captures); var n = parseInt(captures[1], 16), color = new nodes.RGBA(n, n, n, 1); color.raw = captures[0]; return new Token('color', color); } }, rgb: function() { var captures; if ((captures = /^#([a-fA-F0-9]{3})[ \t]*/.exec(this.str))) { this.skip(captures); var rgb = captures[1], r = parseInt(rgb[0] + rgb[0], 16), g = parseInt(rgb[1] + rgb[1], 16), b = parseInt(rgb[2] + rgb[2], 16), color = new nodes.RGBA(r, g, b, 1); color.raw = captures[0]; return new Token('color', color); } }, rgba: function() { var captures; if ((captures = /^#([a-fA-F0-9]{4})[ \t]*/.exec(this.str))) { this.skip(captures); var rgb = captures[1], r = parseInt(rgb[0] + rgb[0], 16), g = parseInt(rgb[1] + rgb[1], 16), b = parseInt(rgb[2] + rgb[2], 16), a = parseInt(rgb[3] + rgb[3], 16), color = new nodes.RGBA(r, g, b, a / 255); color.raw = captures[0]; return new Token('color', color); } }, rrggbb: function() { var captures; if ((captures = /^#([a-fA-F0-9]{6})[ \t]*/.exec(this.str))) { this.skip(captures); var rgb = captures[1], r = parseInt(rgb.substr(0, 2), 16), g = parseInt(rgb.substr(2, 2), 16), b = parseInt(rgb.substr(4, 2), 16), color = new nodes.RGBA(r, g, b, 1); color.raw = captures[0]; return new Token('color', color); } }, rrggbbaa: function() { var captures; if ((captures = /^#([a-fA-F0-9]{8})[ \t]*/.exec(this.str))) { this.skip(captures); var rgb = captures[1], r = parseInt(rgb.substr(0, 2), 16), g = parseInt(rgb.substr(2, 2), 16), b = parseInt(rgb.substr(4, 2), 16), a = parseInt(rgb.substr(6, 2), 16), color = new nodes.RGBA(r, g, b, a / 255); color.raw = captures[0]; return new Token('color', color); } }, selector: function() { var captures; if ((captures = /^\^|.*?(?=\/\/(?![^\[]*\])|[,\n{])/.exec(this.str))) { var selector = captures[0]; this.skip(captures); return new Token('selector', selector); } }, }; }); require.register('nodes/arguments.js', function(module, exports, require) { var Node = require('./node'), nodes = require('../nodes'), utils = require('../utils'); var Arguments = (module.exports = function Arguments() { nodes.Expression.call(this); this.map = {}; }); Arguments.prototype.__proto__ = nodes.Expression.prototype; Arguments.fromExpression = function(expr) { var args = new Arguments(), len = expr.nodes.length; args.lineno = expr.lineno; args.column = expr.column; args.isList = expr.isList; for (var i = 0; i < len; ++i) { args.push(expr.nodes[i]); } return args; }; Arguments.prototype.clone = function(parent) { var clone = nodes.Expression.prototype.clone.call(this, parent); clone.map = {}; for (var key in this.map) { clone.map[key] = this.map[key].clone(parent, clone); } clone.isList = this.isList; clone.lineno = this.lineno; clone.column = this.column; clone.filename = this.filename; return clone; }; Arguments.prototype.toJSON = function() { return { __type: 'Arguments', map: this.map, isList: this.isList, preserve: this.preserve, lineno: this.lineno, column: this.column, filename: this.filename, nodes: this.nodes, }; }; }); require.register('nodes/binop.js', function(module, exports, require) { var Node = require('./node'); var BinOp = (module.exports = function BinOp(op, left, right) { Node.call(this); this.op = op; this.left = left; this.right = right; }); BinOp.prototype.__proto__ = Node.prototype; BinOp.prototype.clone = function(parent) { var clone = new BinOp(this.op); clone.left = this.left.clone(parent, clone); clone.right = this.right && this.right.clone(parent, clone); clone.lineno = this.lineno; clone.column = this.column; clone.filename = this.filename; if (this.val) clone.val = this.val.clone(parent, clone); return clone; }; BinOp.prototype.toString = function() { return this.left.toString() + ' ' + this.op + ' ' + this.right.toString(); }; BinOp.prototype.toJSON = function() { var json = { __type: 'BinOp', left: this.left, right: this.right, op: this.op, lineno: this.lineno, column: this.column, filename: this.filename, }; if (this.val) json.val = this.val; return json; }; }); require.register('nodes/block.js', function(module, exports, require) { var Node = require('./node'); var Block = (module.exports = function Block(parent, node) { Node.call(this); this.nodes = []; this.parent = parent; this.node = node; this.scope = true; }); Block.prototype.__proto__ = Node.prototype; Block.prototype.__defineGetter__('hasProperties', function() { for (var i = 0, len = this.nodes.length; i < len; ++i) { if ('property' == this.nodes[i].nodeName) { return true; } } }); Block.prototype.__defineGetter__('hasMedia', function() { for (var i = 0, len = this.nodes.length; i < len; ++i) { var nodeName = this.nodes[i].nodeName; if ('media' == nodeName) { return true; } } return false; }); Block.prototype.__defineGetter__('isEmpty', function() { return !this.nodes.length; }); Block.prototype.clone = function(parent, node) { parent = parent || this.parent; var clone = new Block(parent, node || this.node); clone.lineno = this.lineno; clone.column = this.column; clone.filename = this.filename; clone.scope = this.scope; this.nodes.forEach(function(node) { clone.push(node.clone(clone, clone)); }); return clone; }; Block.prototype.push = function(node) { this.nodes.push(node); }; Block.prototype.toJSON = function() { return { __type: 'Block', scope: this.scope, lineno: this.lineno, column: this.column, filename: this.filename, nodes: this.nodes, }; }; }); require.register('nodes/boolean.js', function(module, exports, require) { var Node = require('./node'), nodes = require('./index'); var Boolean = (module.exports = function Boolean(val) { Node.call(this); if (this.nodeName) { this.val = !!val; } else { return new Boolean(val); } }); Boolean.prototype.__proto__ = Node.prototype; Boolean.prototype.toBoolean = function() { return this; }; Boolean.prototype.__defineGetter__('isTrue', function() { return this.val; }); Boolean.prototype.__defineGetter__('isFalse', function() { return !this.val; }); Boolean.prototype.negate = function() { return new Boolean(!this.val); }; Boolean.prototype.inspect = function() { return '[Boolean ' + this.val + ']'; }; Boolean.prototype.toString = function() { return this.val ? 'true' : 'false'; }; Boolean.prototype.toJSON = function() { return { __type: 'Boolean', val: this.val }; }; }); require.register('nodes/call.js', function(module, exports, require) { var Node = require('./node'); var Call = (module.exports = function Call(name, args) { Node.call(this); this.name = name; this.args = args; }); Call.prototype.__proto__ = Node.prototype; Call.prototype.clone = function(parent) { var clone = new Call(this.name); clone.args = this.args.clone(parent, clone); if (this.block) clone.block = this.block.clone(parent, clone); clone.lineno = this.lineno; clone.column = this.column; clone.filename = this.filename; return clone; }; Call.prototype.toString = function() { var args = this.args.nodes .map(function(node) { var str = node.toString(); return str.slice(1, str.length - 1); }) .join(', '); return this.name + '(' + args + ')'; }; Call.prototype.toJSON = function() { var json = { __type: 'Call', name: this.name, args: this.args, lineno: this.lineno, column: this.column, filename: this.filename, }; if (this.block) json.block = this.block; return json; }; }); require.register('nodes/charset.js', function(module, exports, require) { var Node = require('./node'); var Charset = (module.exports = function Charset(val) { Node.call(this); this.val = val; }); Charset.prototype.__proto__ = Node.prototype; Charset.prototype.toString = function() { return '@charset ' + this.val; }; Charset.prototype.toJSON = function() { return { __type: 'Charset', val: this.val, lineno: this.lineno, column: this.column, filename: this.filename, }; }; }); require.register('nodes/namespace.js', function(module, exports, require) { var Node = require('./node'); var Namespace = (module.exports = function Namespace(val, prefix) { Node.call(this); this.val = val; this.prefix = prefix; }); Namespace.prototype.__proto__ = Node.prototype; Namespace.prototype.toString = function() { return '@namespace ' + (this.prefix ? this.prefix + ' ' : '') + this.val; }; Namespace.prototype.toJSON = function() { return { __type: 'Namespace', val: this.val, prefix: this.prefix, lineno: this.lineno, column: this.column, filename: this.filename, }; }; }); require.register('nodes/comment.js', function(module, exports, require) { var Node = require('./node'); var Comment = (module.exports = function Comment(str, suppress, inline) { Node.call(this); this.str = str; this.suppress = suppress; this.inline = inline; }); Comment.prototype.__proto__ = Node.prototype; Comment.prototype.toJSON = function() { return { __type: 'Comment', str: this.str, suppress: this.suppress, inline: this.inline, lineno: this.lineno, column: this.column, filename: this.filename, }; }; Comment.prototype.toString = function() { return this.str; }; }); require.register('nodes/each.js', function(module, exports, require) { var Node = require('./node'), nodes = require('./index'); var Each = (module.exports = function Each(val, key, expr, block) { Node.call(this); this.val = val; this.key = key; this.expr = expr; this.block = block; }); Each.prototype.__proto__ = Node.prototype; Each.prototype.clone = function(parent) { var clone = new Each(this.val, this.key); clone.expr = this.expr.clone(parent, clone); clone.block = this.block.clone(parent, clone); clone.lineno = this.lineno; clone.column = this.column; clone.filename = this.filename; return clone; }; Each.prototype.toJSON = function() { return { __type: 'Each', val: this.val, key: this.key, expr: this.expr, block: this.block, lineno: this.lineno, column: this.column, filename: this.filename, }; }; }); require.register('nodes/expression.js', function(module, exports, require) { var Node = require('./node'), nodes = require('../nodes'), utils = require('../utils'); var Expression = (module.exports = function Expression(isList) { Node.call(this); this.nodes = []; this.isList = isList; }); Expression.prototype.__defineGetter__('isEmpty', function() { return !this.nodes.length; }); Expression.prototype.__defineGetter__('first', function() { return this.nodes[0] ? this.nodes[0].first : nodes.nil; }); Expression.prototype.__defineGetter__('hash', function() { return this.nodes .map(function(node) { return node.hash; }) .join('::'); }); Expression.prototype.__proto__ = Node.prototype; Expression.prototype.clone = function(parent) { var clone = new this.constructor(this.isList); clone.preserve = this.preserve; clone.lineno = this.lineno; clone.column = this.column; clone.filename = this.filename; clone.nodes = this.nodes.map(function(node) { return node.clone(parent, clone); }); return clone; }; Expression.prototype.push = function(node) { this.nodes.push(node); }; Expression.prototype.operate = function(op, right, val) { switch (op) { case '[]=': var self = this, range = utils.unwrap(right).nodes, val = utils.unwrap(val), len, node; range.forEach(function(unit) { len = self.nodes.length; if ('unit' == unit.nodeName) { var i = unit.val < 0 ? len + unit.val : unit.val, n = i; while (i-- > len) self.nodes[i] = nodes.nil; self.nodes[n] = val; } else if (unit.string) { node = self.nodes[0]; if (node && 'object' == node.nodeName) node.set(unit.string, val.clone()); } }); return val; case '[]': var expr = new nodes.Expression(), vals = utils.unwrap(this).nodes, range = utils.unwrap(right).nodes, node; range.forEach(function(unit) { if ('unit' == unit.nodeName) { node = vals[unit.val < 0 ? vals.length + unit.val : unit.val]; } else if ('object' == vals[0].nodeName) { node = vals[0].get(unit.string); } if (node) expr.push(node); }); return expr.isEmpty ? nodes.nil : utils.unwrap(expr); case '||': return this.toBoolean().isTrue ? this : right; case 'in': return Node.prototype.operate.call(this, op, right); case '!=': return this.operate('==', right, val).negate(); case '==': var len = this.nodes.length, right = right.toExpression(), a, b; if (len != right.nodes.length) return nodes.no; for (var i = 0; i < len; ++i) { a = this.nodes[i]; b = right.nodes[i]; if (a.operate(op, b).isTrue) continue; return nodes.no; } return nodes.yes; break; default: return this.first.operate(op, right, val); } }; Expression.prototype.toBoolean = function() { if (this.nodes.length > 1) return nodes.yes; return this.first.toBoolean(); }; Expression.prototype.toString = function() { return ( '(' + this.nodes .map(function(node) { return node.toString(); }) .join(this.isList ? ', ' : ' ') + ')' ); }; Expression.prototype.toJSON = function() { return { __type: 'Expression', isList: this.isList, preserve: this.preserve, lineno: this.lineno, column: this.column, filename: this.filename, nodes: this.nodes, }; }; }); require.register('nodes/function.js', function(module, exports, require) { var Node = require('./node'); var Function = (module.exports = function Function(name, params, body) { Node.call(this); this.name = name; this.params = params; this.block = body; if ('function' == typeof params) this.fn = params; }); Function.prototype.__defineGetter__('arity', function() { return this.params.length; }); Function.prototype.__proto__ = Node.prototype; Function.prototype.__defineGetter__('hash', function() { return 'function ' + this.name; }); Function.prototype.clone = function(parent) { if (this.fn) { var clone = new Function(this.name, this.fn); } else { var clone = new Function(this.name); clone.params = this.params.clone(parent, clone); clone.block = this.block.clone(parent, clone); } clone.lineno = this.lineno; clone.column = this.column; clone.filename = this.filename; return clone; }; Function.prototype.toString = function() { if (this.fn) { return ( this.name + '(' + this.fn .toString() .match(/^function *\w*\((.*?)\)/) .slice(1) .join(', ') + ')' ); } else { return this.name + '(' + this.params.nodes.join(', ') + ')'; } }; Function.prototype.toJSON = function() { var json = { __type: 'Function', name: this.name, lineno: this.lineno, column: this.column, filename: this.filename, }; if (this.fn) { json.fn = this.fn; } else { json.params = this.params; json.block = this.block; } return json; }; }); require.register('nodes/group.js', function(module, exports, require) { var Node = require('./node'); var Group = (module.exports = function Group() { Node.call(this); this.nodes = []; this.extends = []; }); Group.prototype.__proto__ = Node.prototype; Group.prototype.push = function(selector) { this.nodes.push(selector); }; Group.prototype.__defineGetter__('block', function() { return this.nodes[0].block; }); Group.prototype.__defineSetter__('block', function(block) { for (var i = 0, len = this.nodes.length; i < len; ++i) { this.nodes[i].block = block; } }); Group.prototype.__defineGetter__('hasOnlyPlaceholders', function() { return this.nodes.every(function(selector) { return selector.isPlaceholder; }); }); Group.prototype.clone = function(parent) { var clone = new Group(); clone.lineno = this.lineno; clone.column = this.column; this.nodes.forEach(function(node) { clone.push(node.clone(parent, clone)); }); clone.filename = this.filename; clone.block = this.block.clone(parent, clone); return clone; }; Group.prototype.toJSON = function() { return { __type: 'Group', nodes: this.nodes, block: this.block, lineno: this.lineno, column: this.column, filename: this.filename, }; }; }); require.register('nodes/hsla.js', function(module, exports, require) { var Node = require('./node'), nodes = require('./index'); var HSLA = (exports = module.exports = function HSLA(h, s, l, a) { Node.call(this); this.h = clampDegrees(h); this.s = clampPercentage(s); this.l = clampPercentage(l); this.a = clampAlpha(a); this.hsla = this; }); HSLA.prototype.__proto__ = Node.prototype; HSLA.prototype.toString = function() { return ( 'hsla(' + this.h + ',' + this.s.toFixed(0) + '%,' + this.l.toFixed(0) + '%,' + this.a + ')' ); }; HSLA.prototype.clone = function(parent) { var clone = new HSLA(this.h, this.s, this.l, this.a); clone.lineno = this.lineno; clone.column = this.column; clone.filename = this.filename; return clone; }; HSLA.prototype.toJSON = function() { return { __type: 'HSLA', h: this.h, s: this.s, l: this.l, a: this.a, lineno: this.lineno, column: this.column, filename: this.filename, }; }; HSLA.prototype.__defineGetter__('rgba', function() { return nodes.RGBA.fromHSLA(this); }); HSLA.prototype.__defineGetter__('hash', function() { return this.rgba.toString(); }); HSLA.prototype.add = function(h, s, l) { return new HSLA(this.h + h, this.s + s, this.l + l, this.a); }; HSLA.prototype.sub = function(h, s, l) { return this.add(-h, -s, -l); }; HSLA.prototype.operate = function(op, right) { switch (op) { case '==': case '!=': case '<=': case '>=': case '<': case '>': case 'is a': case '||': case '&&': return this.rgba.operate(op, right); default: return this.rgba.operate(op, right).hsla; } }; exports.fromRGBA = function(rgba) { var r = rgba.r / 255, g = rgba.g / 255, b = rgba.b / 255, a = rgba.a; var min = Math.min(r, g, b), max = Math.max(r, g, b), l = (max + min) / 2, d = max - min, h, s; switch (max) { case min: h = 0; break; case r: h = 60 * (g - b) / d; break; case g: h = 60 * (b - r) / d + 120; break; case b: h = 60 * (r - g) / d + 240; break; } if (max == min) { s = 0; } else if (l < 0.5) { s = d / (2 * l); } else { s = d / (2 - 2 * l); } h %= 360; s *= 100; l *= 100; return new HSLA(h, s, l, a); }; HSLA.prototype.adjustLightness = function(percent) { this.l = clampPercentage(this.l + this.l * (percent / 100)); return this; }; HSLA.prototype.adjustHue = function(deg) { this.h = clampDegrees(this.h + deg); return this; }; function clampDegrees(n) { n = n % 360; return n >= 0 ? n : 360 + n; } function clampPercentage(n) { return Math.max(0, Math.min(n, 100)); } function clampAlpha(n) { return Math.max(0, Math.min(n, 1)); } }); require.register('nodes/ident.js', function(module, exports, require) { var Node = require('./node'), nodes = require('./index'); var Ident = (module.exports = function Ident(name, val, mixin) { Node.call(this); this.name = name; this.string = name; this.val = val || nodes.nil; this.mixin = !!mixin; }); Ident.prototype.__defineGetter__('isEmpty', function() { return undefined == this.val; }); Ident.prototype.__defineGetter__('hash', function() { return this.name; }); Ident.prototype.__proto__ = Node.prototype; Ident.prototype.clone = function(parent) { var clone = new Ident(this.name); clone.val = this.val.clone(parent, clone); clone.mixin = this.mixin; clone.lineno = this.lineno; clone.column = this.column; clone.filename = this.filename; clone.property = this.property; clone.rest = this.rest; return clone; }; Ident.prototype.toJSON = function() { return { __type: 'Ident', name: this.name, val: this.val, mixin: this.mixin, property: this.property, rest: this.rest, lineno: this.lineno, column: this.column, filename: this.filename, }; }; Ident.prototype.toString = function() { return this.name; }; Ident.prototype.coerce = function(other) { switch (other.nodeName) { case 'ident': case 'string': case 'literal': return new Ident(other.string); case 'unit': return new Ident(other.toString()); default: return Node.prototype.coerce.call(this, other); } }; Ident.prototype.operate = function(op, right) { var val = right.first; switch (op) { case '-': if ('unit' == val.nodeName) { var expr = new nodes.Expression(); val = val.clone(); val.val = -val.val; expr.push(this); expr.push(val); return expr; } case '+': return new nodes.Ident(this.string + this.coerce(val).string); } return Node.prototype.operate.call(this, op, right); }; }); require.register('nodes/if.js', function(module, exports, require) { var Node = require('./node'); var If = (module.exports = function If(cond, negate) { Node.call(this); this.cond = cond; this.elses = []; if (negate && negate.nodeName) { this.block = negate; } else { this.negate = negate; } }); If.prototype.__proto__ = Node.prototype; If.prototype.clone = function(parent) { var clone = new If(); clone.cond = this.cond.clone(parent, clone); clone.block = this.block.clone(parent, clone); clone.elses = this.elses.map(function(node) { return node.clone(parent, clone); }); clone.negate = this.negate; clone.postfix = this.postfix; clone.lineno = this.lineno; clone.column = this.column; clone.filename = this.filename; return clone; }; If.prototype.toJSON = function() { return { __type: 'If', cond: this.cond, block: this.block, elses: this.elses, negate: this.negate, postfix: this.postfix, lineno: this.lineno, column: this.column, filename: this.filename, }; }; }); require.register('nodes/import.js', function(module, exports, require) { var Node = require('./node'); var Import = (module.exports = function Import(expr, once) { Node.call(this); this.path = expr; this.once = once || false; }); Import.prototype.__proto__ = Node.prototype; Import.prototype.clone = function(parent) { var clone = new Import(); clone.path = this.path.nodeName ? this.path.clone(parent, clone) : this.path; clone.once = this.once; clone.mtime = this.mtime; clone.lineno = this.lineno; clone.column = this.column; clone.filename = this.filename; return clone; }; Import.prototype.toJSON = function() { return { __type: 'Import', path: this.path, once: this.once, mtime: this.mtime, lineno: this.lineno, column: this.column, filename: this.filename, }; }; }); require.register('nodes/extend.js', function(module, exports, require) { var Node = require('./node'); var Extend = (module.exports = function Extend(selectors) { Node.call(this); this.selectors = selectors; }); Extend.prototype.__proto__ = Node.prototype; Extend.prototype.clone = function() { return new Extend(this.selectors); }; Extend.prototype.toString = function() { return '@extend ' + this.selectors.join(', '); }; Extend.prototype.toJSON = function() { return { __type: 'Extend', selectors: this.selectors, lineno: this.lineno, column: this.column, filename: this.filename, }; }; }); require.register('nodes/index.js', function(module, exports, require) { exports.Node = require('./node'); exports.Root = require('./root'); exports.Null = require('./null'); exports.Each = require('./each'); exports.If = require('./if'); exports.Call = require('./call'); exports.UnaryOp = require('./unaryop'); exports.BinOp = require('./binop'); exports.Ternary = require('./ternary'); exports.Block = require('./block'); exports.Unit = require('./unit'); exports.String = require('./string'); exports.HSLA = require('./hsla'); exports.RGBA = require('./rgba'); exports.Ident = require('./ident'); exports.Group = require('./group'); exports.Literal = require('./literal'); exports.Boolean = require('./boolean'); exports.Return = require('./return'); exports.Media = require('./media'); exports.QueryList = require('./query-list'); exports.Query = require('./query'); exports.Feature = require('./feature'); exports.Params = require('./params'); exports.Comment = require('./comment'); exports.Keyframes = require('./keyframes'); exports.Member = require('./member'); exports.Charset = require('./charset'); exports.Namespace = require('./namespace'); exports.Import = require('./import'); exports.Extend = require('./extend'); exports.Object = require('./object'); exports.Function = require('./function'); exports.Property = require('./property'); exports.Selector = require('./selector'); exports.Expression = require('./expression'); exports.Arguments = require('./arguments'); exports.Atblock = require('./atblock'); exports.Atrule = require('./atrule'); exports.Supports = require('./supports'); exports.yes = new exports.Boolean(true); exports.no = new exports.Boolean(false); exports.nil = new exports.Null(); }); require.register('nodes/keyframes.js', function(module, exports, require) { var Atrule = require('./atrule'); var Keyframes = (module.exports = function Keyframes(segs, prefix) { Atrule.call(this, 'keyframes'); this.segments = segs; this.prefix = prefix || 'official'; }); Keyframes.prototype.__proto__ = Atrule.prototype; Keyframes.prototype.clone = function(parent) { var clone = new Keyframes(); clone.lineno = this.lineno; clone.column = this.column; clone.filename = this.filename; clone.segments = this.segments.map(function(node) { return node.clone(parent, clone); }); clone.prefix = this.prefix; clone.block = this.block.clone(parent, clone); return clone; }; Keyframes.prototype.toJSON = function() { return { __type: 'Keyframes', segments: this.segments, prefix: this.prefix, block: this.block, lineno: this.lineno, column: this.column, filename: this.filename, }; }; Keyframes.prototype.toString = function() { return '@keyframes ' + this.segments.join(''); }; }); require.register('nodes/literal.js', function(module, exports, require) { var Node = require('./node'), nodes = require('./index'); var Literal = (module.exports = function Literal(str) { Node.call(this); this.val = str; this.string = str; this.prefixed = false; }); Literal.prototype.__proto__ = Node.prototype; Literal.prototype.__defineGetter__('hash', function() { return this.val; }); Literal.prototype.toString = function() { return this.val; }; Literal.prototype.coerce = function(other) { switch (other.nodeName) { case 'ident': case 'string': case 'literal': return new Literal(other.string); default: return Node.prototype.coerce.call(this, other); } }; Literal.prototype.operate = function(op, right) { var val = right.first; switch (op) { case '+': return new nodes.Literal(this.string + this.coerce(val).string); default: return Node.prototype.operate.call(this, op, right); } }; Literal.prototype.toJSON = function() { return { __type: 'Literal', val: this.val, string: this.string, prefixed: this.prefixed, lineno: this.lineno, column: this.column, filename: this.filename, }; }; }); require.register('nodes/media.js', function(module, exports, require) { var Atrule = require('./atrule'); var Media = (module.exports = function Media(val) { Atrule.call(this, 'media'); this.val = val; }); Media.prototype.__proto__ = Atrule.prototype; Media.prototype.clone = function(parent) { var clone = new Media(); clone.val = this.val.clone(parent, clone); clone.block = this.block.clone(parent, clone); clone.lineno = this.lineno; clone.column = this.column; clone.filename = this.filename; return clone; }; Media.prototype.toJSON = function() { return { __type: 'Media', val: this.val, block: this.block, lineno: this.lineno, column: this.column, filename: this.filename, }; }; Media.prototype.toString = function() { return '@media ' + this.val; }; }); require.register('nodes/query-list.js', function(module, exports, require) { var Node = require('./node'); var QueryList = (module.exports = function QueryList() { Node.call(this); this.nodes = []; }); QueryList.prototype.__proto__ = Node.prototype; QueryList.prototype.clone = function(parent) { var clone = new QueryList(); clone.lineno = this.lineno; clone.column = this.column; clone.filename = this.filename; for (var i = 0; i < this.nodes.length; ++i) { clone.push(this.nodes[i].clone(parent, clone)); } return clone; }; QueryList.prototype.push = function(node) { this.nodes.push(node); }; QueryList.prototype.merge = function(other) { var list = new QueryList(), merged; this.nodes.forEach(function(query) { for (var i = 0, len = other.nodes.length; i < len; ++i) { merged = query.merge(other.nodes[i]); if (merged) list.push(merged); } }); return list; }; QueryList.prototype.toString = function() { return ( '(' + this.nodes .map(function(node) { return node.toString(); }) .join(', ') + ')' ); }; QueryList.prototype.toJSON = function() { return { __type: 'QueryList', nodes: this.nodes, lineno: this.lineno, column: this.column, filename: this.filename, }; }; }); require.register('nodes/query.js', function(module, exports, require) { var Node = require('./node'); var Query = (module.exports = function Query() { Node.call(this); this.nodes = []; this.type = ''; this.predicate = ''; }); Query.prototype.__proto__ = Node.prototype; Query.prototype.clone = function(parent) { var clone = new Query(); clone.predicate = this.predicate; clone.type = this.type; for (var i = 0, len = this.nodes.length; i < len; ++i) { clone.push(this.nodes[i].clone(parent, clone)); } clone.lineno = this.lineno; clone.column = this.column; clone.filename = this.filename; return clone; }; Query.prototype.push = function(feature) { this.nodes.push(feature); }; Query.prototype.__defineGetter__('resolvedType', function() { if (this.type) { return this.type.nodeName ? this.type.string : this.type; } }); Query.prototype.__defineGetter__('resolvedPredicate', function() { if (this.predicate) { return this.predicate.nodeName ? this.predicate.string : this.predicate; } }); Query.prototype.merge = function(other) { var query = new Query(), p1 = this.resolvedPredicate, p2 = other.resolvedPredicate, t1 = this.resolvedType, t2 = other.resolvedType, type, pred; t1 = t1 || t2; t2 = t2 || t1; if (('not' == p1) ^ ('not' == p2)) { if (t1 == t2) return; type = 'not' == p1 ? t2 : t1; pred = 'not' == p1 ? p2 : p1; } else if ('not' == p1 && 'not' == p2) { if (t1 != t2) return; type = t1; pred = 'not'; } else if (t1 != t2) { return; } else { type = t1; pred = p1 || p2; } query.predicate = pred; query.type = type; query.nodes = this.nodes.concat(other.nodes); return query; }; Query.prototype.toString = function() { var pred = this.predicate ? this.predicate + ' ' : '', type = this.type || '', len = this.nodes.length, str = pred + type; if (len) { str += (type && ' and ') + this.nodes .map(function(expr) { return expr.toString(); }) .join(' and '); } return str; }; Query.prototype.toJSON = function() { return { __type: 'Query', predicate: this.predicate, type: this.type, nodes: this.nodes, lineno: this.lineno, column: this.column, filename: this.filename, }; }; }); require.register('nodes/feature.js', function(module, exports, require) { var Node = require('./node'); var Feature = (module.exports = function Feature(segs) { Node.call(this); this.segments = segs; this.expr = null; }); Feature.prototype.__proto__ = Node.prototype; Feature.prototype.clone = function(parent) { var clone = new Feature(); clone.segments = this.segments.map(function(node) { return node.clone(parent, clone); }); if (this.expr) clone.expr = this.expr.clone(parent, clone); if (this.name) clone.name = this.name; clone.lineno = this.lineno; clone.column = this.column; clone.filename = this.filename; return clone; }; Feature.prototype.toString = function() { if (this.expr) { return '(' + this.segments.join('') + ': ' + this.expr.toString() + ')'; } else { return this.segments.join(''); } }; Feature.prototype.toJSON = function() { var json = { __type: 'Feature', segments: this.segments, lineno: this.lineno, column: this.column, filename: this.filename, }; if (this.expr) json.expr = this.expr; if (this.name) json.name = this.name; return json; }; }); require.register('nodes/node.js', function(module, exports, require) { var Evaluator = require('../visitor/evaluator'), utils = require('../utils'), nodes = require('./index'); function CoercionError(msg) { this.name = 'CoercionError'; this.message = msg; Error.captureStackTrace(this, CoercionError); } CoercionError.prototype.__proto__ = Error.prototype; var Node = (module.exports = function Node() { this.lineno = nodes.lineno || 1; this.column = nodes.column || 1; this.filename = nodes.filename; }); Node.prototype = { constructor: Node, get first() { return this; }, get hash() { return this.val; }, get nodeName() { return this.constructor.name.toLowerCase(); }, clone: function() { return this; }, toJSON: function() { return { lineno: this.lineno, column: this.column, filename: this.filename, }; }, eval: function() { return new Evaluator(this).evaluate(); }, toBoolean: function() { return nodes.yes; }, toExpression: function() { if ('expression' == this.nodeName) return this; var expr = new nodes.Expression(); expr.push(this); return expr; }, shouldCoerce: function(op) { switch (op) { case 'is a': case 'in': case '||': case '&&': return false; default: return true; } }, operate: function(op, right) { switch (op) { case 'is a': if ('string' == right.first.nodeName) { return nodes.Boolean(this.nodeName == right.val); } else { throw new Error( '"is a" expects a string, got ' + right.toString(), ); } case '==': return nodes.Boolean(this.hash == right.hash); case '!=': return nodes.Boolean(this.hash != right.hash); case '>=': return nodes.Boolean(this.hash >= right.hash); case '<=': return nodes.Boolean(this.hash <= right.hash); case '>': return nodes.Boolean(this.hash > right.hash); case '<': return nodes.Boolean(this.hash < right.hash); case '||': return this.toBoolean().isTrue ? this : right; case 'in': var vals = utils.unwrap(right).nodes, len = vals && vals.length, hash = this.hash; if (!vals) throw new Error( '"in" given invalid right-hand operand, expecting an expression', ); if (1 == len && 'object' == vals[0].nodeName) { return nodes.Boolean(vals[0].has(this.hash)); } for (var i = 0; i < len; ++i) { if (hash == vals[i].hash) { return nodes.yes; } } return nodes.no; case '&&': var a = this.toBoolean(), b = right.toBoolean(); return a.isTrue && b.isTrue ? right : a.isFalse ? this : right; default: if ('[]' == op) { var msg = 'cannot perform ' + this + '[' + right + ']'; } else { var msg = 'cannot perform' + ' ' + this + ' ' + op + ' ' + right; } throw new Error(msg); } }, coerce: function(other) { if (other.nodeName == this.nodeName) return other; throw new CoercionError( 'cannot coerce ' + other + ' to ' + this.nodeName, ); }, }; }); require.register('nodes/null.js', function(module, exports, require) { var Node = require('./node'), nodes = require('./index'); var Null = (module.exports = function Null() {}); Null.prototype.__proto__ = Node.prototype; Null.prototype.inspect = Null.prototype.toString = function() { return 'null'; }; Null.prototype.toBoolean = function() { return nodes.no; }; Null.prototype.__defineGetter__('isNull', function() { return true; }); Null.prototype.__defineGetter__('hash', function() { return null; }); Null.prototype.toJSON = function() { return { __type: 'Null', lineno: this.lineno, column: this.column, filename: this.filename, }; }; }); require.register('nodes/params.js', function(module, exports, require) { var Node = require('./node'); var Params = (module.exports = function Params() { Node.call(this); this.nodes = []; }); Params.prototype.__defineGetter__('length', function() { return this.nodes.length; }); Params.prototype.__proto__ = Node.prototype; Params.prototype.push = function(node) { this.nodes.push(node); }; Params.prototype.clone = function(parent) { var clone = new Params(); clone.lineno = this.lineno; clone.column = this.column; clone.filename = this.filename; this.nodes.forEach(function(node) { clone.push(node.clone(parent, clone)); }); return clone; }; Params.prototype.toJSON = function() { return { __type: 'Params', nodes: this.nodes, lineno: this.lineno, column: this.column, filename: this.filename, }; }; }); require.register('nodes/property.js', function(module, exports, require) { var Node = require('./node'); var Property = (module.exports = function Property(segs, expr) { Node.call(this); this.segments = segs; this.expr = expr; }); Property.prototype.__proto__ = Node.prototype; Property.prototype.clone = function(parent) { var clone = new Property(this.segments); clone.name = this.name; if (this.literal) clone.literal = this.literal; clone.lineno = this.lineno; clone.column = this.column; clone.filename = this.filename; clone.segments = this.segments.map(function(node) { return node.clone(parent, clone); }); if (this.expr) clone.expr = this.expr.clone(parent, clone); return clone; }; Property.prototype.toJSON = function() { var json = { __type: 'Property', segments: this.segments, name: this.name, lineno: this.lineno, column: this.column, filename: this.filename, }; if (this.expr) json.expr = this.expr; if (this.literal) json.literal = this.literal; return json; }; Property.prototype.toString = function() { return 'property(' + this.segments.join('') + ', ' + this.expr + ')'; }; Property.prototype.operate = function(op, right, val) { return this.expr.operate(op, right, val); }; }); require.register('nodes/return.js', function(module, exports, require) { var Node = require('./node'), nodes = require('./index'); var Return = (module.exports = function Return(expr) { this.expr = expr || nodes.nil; }); Return.prototype.__proto__ = Node.prototype; Return.prototype.clone = function(parent) { var clone = new Return(); clone.expr = this.expr.clone(parent, clone); clone.lineno = this.lineno; clone.column = this.column; clone.filename = this.filename; return clone; }; Return.prototype.toJSON = function() { return { __type: 'Return', expr: this.expr, lineno: this.lineno, column: this.column, filename: this.filename, }; }; }); require.register('nodes/rgba.js', function(module, exports, require) { var Node = require('./node'), HSLA = require('./hsla'), functions = require('../functions'), adjust = functions.adjust, nodes = require('./index'); var RGBA = (exports = module.exports = function RGBA(r, g, b, a) { Node.call(this); this.r = clamp(r); this.g = clamp(g); this.b = clamp(b); this.a = clampAlpha(a); this.name = ''; this.rgba = this; }); RGBA.prototype.__proto__ = Node.prototype; RGBA.withoutClamping = function(r, g, b, a) { var rgba = new RGBA(0, 0, 0, 0); rgba.r = r; rgba.g = g; rgba.b = b; rgba.a = a; return rgba; }; RGBA.prototype.clone = function() { var clone = new RGBA(this.r, this.g, this.b, this.a); clone.raw = this.raw; clone.name = this.name; clone.lineno = this.lineno; clone.column = this.column; clone.filename = this.filename; return clone; }; RGBA.prototype.toJSON = function() { return { __type: 'RGBA', r: this.r, g: this.g, b: this.b, a: this.a, raw: this.raw, name: this.name, lineno: this.lineno, column: this.column, filename: this.filename, }; }; RGBA.prototype.toBoolean = function() { return nodes.yes; }; RGBA.prototype.__defineGetter__('hsla', function() { return HSLA.fromRGBA(this); }); RGBA.prototype.__defineGetter__('hash', function() { return this.toString(); }); RGBA.prototype.add = function(r, g, b, a) { return new RGBA(this.r + r, this.g + g, this.b + b, this.a + a); }; RGBA.prototype.sub = function(r, g, b, a) { return new RGBA( this.r - r, this.g - g, this.b - b, a == 1 ? this.a : this.a - a, ); }; RGBA.prototype.multiply = function(n) { return new RGBA(this.r * n, this.g * n, this.b * n, this.a); }; RGBA.prototype.divide = function(n) { return new RGBA(this.r / n, this.g / n, this.b / n, this.a); }; RGBA.prototype.operate = function(op, right) { if ('in' != op) right = right.first; switch (op) { case 'is a': if ('string' == right.nodeName && 'color' == right.string) { return nodes.yes; } break; case '+': switch (right.nodeName) { case 'unit': var n = right.val; switch (right.type) { case '%': return adjust(this, new nodes.String('lightness'), right); case 'deg': return this.hsla.adjustHue(n).rgba; default: return this.add(n, n, n, 0); } case 'rgba': return this.add(right.r, right.g, right.b, right.a); case 'hsla': return this.hsla.add(right.h, right.s, right.l); } break; case '-': switch (right.nodeName) { case 'unit': var n = right.val; switch (right.type) { case '%': return adjust( this, new nodes.String('lightness'), new nodes.Unit(-n, '%'), ); case 'deg': return this.hsla.adjustHue(-n).rgba; default: return this.sub(n, n, n, 0); } case 'rgba': return this.sub(right.r, right.g, right.b, right.a); case 'hsla': return this.hsla.sub(right.h, right.s, right.l); } break; case '*': switch (right.nodeName) { case 'unit': return this.multiply(right.val); } break; case '/': switch (right.nodeName) { case 'unit': return this.divide(right.val); } break; } return Node.prototype.operate.call(this, op, right); }; RGBA.prototype.toString = function() { function pad(n) { return n < 16 ? '0' + n.toString(16) : n.toString(16); } if ('transparent' == this.name) return this.name; if (1 == this.a) { var r = pad(this.r), g = pad(this.g), b = pad(this.b); if (r[0] == r[1] && g[0] == g[1] && b[0] == b[1]) { return '#' + r[0] + g[0] + b[0]; } else { return '#' + r + g + b; } } else { return ( 'rgba(' + this.r + ',' + this.g + ',' + this.b + ',' + +this.a.toFixed(3) + ')' ); } }; exports.fromHSLA = function(hsla) { var h = hsla.h / 360, s = hsla.s / 100, l = hsla.l / 100, a = hsla.a; var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s, m1 = l * 2 - m2; var r = hue(h + 1 / 3) * 255, g = hue(h) * 255, b = hue(h - 1 / 3) * 255; function hue(h) { if (h < 0) ++h; if (h > 1) --h; if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; if (h * 2 < 1) return m2; if (h * 3 < 2) return m1 + (m2 - m1) * (2 / 3 - h) * 6; return m1; } return new RGBA(r, g, b, a); }; function clamp(n) { return Math.max(0, Math.min(n.toFixed(0), 255)); } function clampAlpha(n) { return Math.max(0, Math.min(n, 1)); } }); require.register('nodes/root.js', function(module, exports, require) { var Node = require('./node'); var Root = (module.exports = function Root() { this.nodes = []; }); Root.prototype.__proto__ = Node.prototype; Root.prototype.push = function(node) { this.nodes.push(node); }; Root.prototype.unshift = function(node) { this.nodes.unshift(node); }; Root.prototype.clone = function() { var clone = new Root(); clone.lineno = this.lineno; clone.column = this.column; clone.filename = this.filename; this.nodes.forEach(function(node) { clone.push(node.clone(clone, clone)); }); return clone; }; Root.prototype.toString = function() { return '[Root]'; }; Root.prototype.toJSON = function() { return { __type: 'Root', nodes: this.nodes, lineno: this.lineno, column: this.column, filename: this.filename, }; }; }); require.register('nodes/selector.js', function(module, exports, require) { var Block = require('./block'), Node = require('./node'); var Selector = (module.exports = function Selector(segs) { Node.call(this); this.inherits = true; this.segments = segs; this.optional = false; }); Selector.prototype.__proto__ = Node.prototype; Selector.prototype.toString = function() { return this.segments.join('') + (this.optional ? ' !optional' : ''); }; Selector.prototype.__defineGetter__('isPlaceholder', function() { return this.val && ~this.val.substr(0, 2).indexOf('$'); }); Selector.prototype.clone = function(parent) { var clone = new Selector(); clone.lineno = this.lineno; clone.column = this.column; clone.filename = this.filename; clone.inherits = this.inherits; clone.val = this.val; clone.segments = this.segments.map(function(node) { return node.clone(parent, clone); }); clone.optional = this.optional; return clone; }; Selector.prototype.toJSON = function() { return { __type: 'Selector', inherits: this.inherits, segments: this.segments, optional: this.optional, val: this.val, lineno: this.lineno, column: this.column, filename: this.filename, }; }; }); require.register('nodes/string.js', function(module, exports, require) { var Node = require('./node'), sprintf = require('../functions').s, utils = require('../utils'), nodes = require('./index'); var String = (module.exports = function String(val, quote) { Node.call(this); this.val = val; this.string = val; this.prefixed = false; if (typeof quote !== 'string') { this.quote = "'"; } else { this.quote = quote; } }); String.prototype.__proto__ = Node.prototype; String.prototype.toString = function() { return this.quote + this.val + this.quote; }; String.prototype.clone = function() { var clone = new String(this.val, this.quote); clone.lineno = this.lineno; clone.column = this.column; clone.filename = this.filename; return clone; }; String.prototype.toJSON = function() { return { __type: 'String', val: this.val, quote: this.quote, lineno: this.lineno, column: this.column, filename: this.filename, }; }; String.prototype.toBoolean = function() { return nodes.Boolean(this.val.length); }; String.prototype.coerce = function(other) { switch (other.nodeName) { case 'string': return other; case 'expression': return new String( other.nodes .map(function(node) { return this.coerce(node).val; }, this) .join(' '), ); default: return new String(other.toString()); } }; String.prototype.operate = function(op, right) { switch (op) { case '%': var expr = new nodes.Expression(); expr.push(this); var args = 'expression' == right.nodeName ? utils.unwrap(right).nodes : [right]; return sprintf.apply(null, [expr].concat(args)); case '+': var expr = new nodes.Expression(); expr.push(new String(this.val + this.coerce(right).val)); return expr; default: return Node.prototype.operate.call(this, op, right); } }; }); require.register('nodes/ternary.js', function(module, exports, require) { var Node = require('./node'); var Ternary = (module.exports = function Ternary( cond, trueExpr, falseExpr, ) { Node.call(this); this.cond = cond; this.trueExpr = trueExpr; this.falseExpr = falseExpr; }); Ternary.prototype.__proto__ = Node.prototype; Ternary.prototype.clone = function(parent) { var clone = new Ternary(); clone.cond = this.cond.clone(parent, clone); clone.trueExpr = this.trueExpr.clone(parent, clone); clone.falseExpr = this.falseExpr.clone(parent, clone); clone.lineno = this.lineno; clone.column = this.column; clone.filename = this.filename; return clone; }; Ternary.prototype.toJSON = function() { return { __type: 'Ternary', cond: this.cond, trueExpr: this.trueExpr, falseExpr: this.falseExpr, lineno: this.lineno, column: this.column, filename: this.filename, }; }; }); require.register('nodes/unaryop.js', function(module, exports, require) { var Node = require('./node'); var UnaryOp = (module.exports = function UnaryOp(op, expr) { Node.call(this); this.op = op; this.expr = expr; }); UnaryOp.prototype.__proto__ = Node.prototype; UnaryOp.prototype.clone = function(parent) { var clone = new UnaryOp(this.op); clone.expr = this.expr.clone(parent, clone); clone.lineno = this.lineno; clone.column = this.column; clone.filename = this.filename; return clone; }; UnaryOp.prototype.toJSON = function() { return { __type: 'UnaryOp', op: this.op, expr: this.expr, lineno: this.lineno, column: this.column, filename: this.filename, }; }; }); require.register('nodes/unit.js', function(module, exports, require) { var Node = require('./node'), nodes = require('./index'); var FACTOR_TABLE = { mm: { val: 1, label: 'mm' }, cm: { val: 10, label: 'mm' }, in: { val: 25.4, label: 'mm' }, pt: { val: 25.4 / 72, label: 'mm' }, ms: { val: 1, label: 'ms' }, s: { val: 1e3, label: 'ms' }, Hz: { val: 1, label: 'Hz' }, kHz: { val: 1e3, label: 'Hz' }, }; var Unit = (module.exports = function Unit(val, type) { Node.call(this); this.val = val; this.type = type; }); Unit.prototype.__proto__ = Node.prototype; Unit.prototype.toBoolean = function() { return nodes.Boolean(this.type ? true : this.val); }; Unit.prototype.toString = function() { return this.val + (this.type || ''); }; Unit.prototype.clone = function() { var clone = new Unit(this.val, this.type); clone.lineno = this.lineno; clone.column = this.column; clone.filename = this.filename; return clone; }; Unit.prototype.toJSON = function() { return { __type: 'Unit', val: this.val, type: this.type, lineno: this.lineno, column: this.column, filename: this.filename, }; }; Unit.prototype.operate = function(op, right) { var type = this.type || right.first.type; if ('rgba' == right.nodeName || 'hsla' == right.nodeName) { return right.operate(op, this); } if (this.shouldCoerce(op)) { right = right.first; if ('%' != this.type && ('-' == op || '+' == op) && '%' == right.type) { right = new Unit(this.val * (right.val / 100), '%'); } else { right = this.coerce(right); } switch (op) { case '-': return new Unit(this.val - right.val, type); case '+': type = type || (right.type == '%' && right.type); return new Unit(this.val + right.val, type); case '/': return new Unit(this.val / right.val, type); case '*': return new Unit(this.val * right.val, type); case '%': return new Unit(this.val % right.val, type); case '**': return new Unit(Math.pow(this.val, right.val), type); case '..': case '...': var start = this.val, end = right.val, expr = new nodes.Expression(), inclusive = '..' == op; if (start < end) { do { expr.push(new nodes.Unit(start)); } while (inclusive ? ++start <= end : ++start < end); } else { do { expr.push(new nodes.Unit(start)); } while (inclusive ? --start >= end : --start > end); } return expr; } } return Node.prototype.operate.call(this, op, right); }; Unit.prototype.coerce = function(other) { if ('unit' == other.nodeName) { var a = this, b = other, factorA = FACTOR_TABLE[a.type], factorB = FACTOR_TABLE[b.type]; if (factorA && factorB && factorA.label == factorB.label) { var bVal = b.val * (factorB.val / factorA.val); return new nodes.Unit(bVal, a.type); } else { return new nodes.Unit(b.val, a.type); } } else if ('string' == other.nodeName) { if ('%' == other.val) return new nodes.Unit(0, '%'); var val = parseFloat(other.val); if (isNaN(val)) Node.prototype.coerce.call(this, other); return new nodes.Unit(val); } else { return Node.prototype.coerce.call(this, other); } }; }); require.register('nodes/object.js', function(module, exports, require) { var Node = require('./node'), nodes = require('./index'), nativeObj = {}.constructor; var Object = (module.exports = function Object() { Node.call(this); this.vals = {}; }); Object.prototype.__proto__ = Node.prototype; Object.prototype.set = function(key, val) { this.vals[key] = val; return this; }; Object.prototype.__defineGetter__('length', function() { return nativeObj.keys(this.vals).length; }); Object.prototype.get = function(key) { return this.vals[key] || nodes.nil; }; Object.prototype.has = function(key) { return key in this.vals; }; Object.prototype.operate = function(op, right) { switch (op) { case '.': case '[]': return this.get(right.hash); case '==': var vals = this.vals, a, b; if ('object' != right.nodeName || this.length != right.length) return nodes.no; for (var key in vals) { a = vals[key]; b = right.vals[key]; if (a.operate(op, b).isFalse) return nodes.no; } return nodes.yes; case '!=': return this.operate('==', right).negate(); default: return Node.prototype.operate.call(this, op, right); } }; Object.prototype.toBoolean = function() { return nodes.Boolean(this.length); }; Object.prototype.toBlock = function() { var str = '{', key, val; for (key in this.vals) { val = this.get(key); if ('object' == val.first.nodeName) { str += key + ' ' + val.first.toBlock(); } else { switch (key) { case '@charset': str += key + ' ' + val.first.toString() + ';'; break; default: str += key + ':' + toString(val) + ';'; } } } str += '}'; return str; function toString(node) { if (node.nodes) { return node.nodes.map(toString).join(node.isList ? ',' : ' '); } else if ('literal' == node.nodeName && ',' == node.val) { return '\\,'; } return node.toString(); } }; Object.prototype.clone = function(parent) { var clone = new Object(); clone.lineno = this.lineno; clone.column = this.column; clone.filename = this.filename; for (var key in this.vals) { clone.vals[key] = this.vals[key].clone(parent, clone); } return clone; }; Object.prototype.toJSON = function() { return { __type: 'Object', vals: this.vals, lineno: this.lineno, column: this.column, filename: this.filename, }; }; Object.prototype.toString = function() { var obj = {}; for (var prop in this.vals) { obj[prop] = this.vals[prop].toString(); } return JSON.stringify(obj); }; }); require.register('nodes/supports.js', function(module, exports, require) { var Atrule = require('./atrule'); var Supports = (module.exports = function Supports(condition) { Atrule.call(this, 'supports'); this.condition = condition; }); Supports.prototype.__proto__ = Atrule.prototype; Supports.prototype.clone = function(parent) { var clone = new Supports(); clone.condition = this.condition.clone(parent, clone); clone.block = this.block.clone(parent, clone); clone.lineno = this.lineno; clone.column = this.column; clone.filename = this.filename; return clone; }; Supports.prototype.toJSON = function() { return { __type: 'Supports', condition: this.condition, block: this.block, lineno: this.lineno, column: this.column, filename: this.filename, }; }; Supports.prototype.toString = function() { return '@supports ' + this.condition; }; }); require.register('nodes/member.js', function(module, exports, require) { var Node = require('./node'); var Member = (module.exports = function Member(left, right) { Node.call(this); this.left = left; this.right = right; }); Member.prototype.__proto__ = Node.prototype; Member.prototype.clone = function(parent) { var clone = new Member(); clone.left = this.left.clone(parent, clone); clone.right = this.right.clone(parent, clone); if (this.val) clone.val = this.val.clone(parent, clone); clone.lineno = this.lineno; clone.column = this.column; clone.filename = this.filename; return clone; }; Member.prototype.toJSON = function() { var json = { __type: 'Member', left: this.left, right: this.right, lineno: this.lineno, column: this.column, filename: this.filename, }; if (this.val) json.val = this.val; return json; }; Member.prototype.toString = function() { return this.left.toString() + '.' + this.right.toString(); }; }); require.register('nodes/atblock.js', function(module, exports, require) { var Node = require('./node'); var Atblock = (module.exports = function Atblock() { Node.call(this); }); Atblock.prototype.__defineGetter__('nodes', function() { return this.block.nodes; }); Atblock.prototype.__proto__ = Node.prototype; Atblock.prototype.clone = function(parent) { var clone = new Atblock(); clone.block = this.block.clone(parent, clone); clone.lineno = this.lineno; clone.column = this.column; clone.filename = this.filename; return clone; }; Atblock.prototype.toString = function() { return '@block'; }; Atblock.prototype.toJSON = function() { return { __type: 'Atblock', block: this.block, lineno: this.lineno, column: this.column, fileno: this.fileno, }; }; }); require.register('nodes/atrule.js', function(module, exports, require) { var Node = require('./node'); var Atrule = (module.exports = function Atrule(type) { Node.call(this); this.type = type; }); Atrule.prototype.__proto__ = Node.prototype; Atrule.prototype.__defineGetter__('hasOnlyProperties', function() { if (!this.block) return false; var nodes = this.block.nodes; for (var i = 0, len = nodes.length; i < len; ++i) { var nodeName = nodes[i].nodeName; switch (nodes[i].nodeName) { case 'property': case 'expression': case 'comment': continue; default: return false; } } return true; }); Atrule.prototype.clone = function(parent) { var clone = new Atrule(this.type); if (this.block) clone.block = this.block.clone(parent, clone); clone.segments = this.segments.map(function(node) { return node.clone(parent, clone); }); clone.lineno = this.lineno; clone.column = this.column; clone.filename = this.filename; return clone; }; Atrule.prototype.toJSON = function() { var json = { __type: 'Atrule', type: this.type, segments: this.segments, lineno: this.lineno, column: this.column, filename: this.filename, }; if (this.block) json.block = this.block; return json; }; Atrule.prototype.toString = function() { return '@' + this.type; }; Atrule.prototype.__defineGetter__('hasOutput', function() { return !!this.block && hasOutput(this.block); }); function hasOutput(block) { var nodes = block.nodes; if ( nodes.every(function(node) { return 'group' == node.nodeName && node.hasOnlyPlaceholders; }) ) return false; return nodes.some(function(node) { switch (node.nodeName) { case 'property': case 'literal': case 'import': return true; case 'block': return hasOutput(node); default: if (node.block) return hasOutput(node.block); } }); } }); require.register('parser.js', function(module, exports, require) { var Lexer = require('./lexer'), nodes = require('./nodes'), Token = require('./token'), units = require('./units'), errors = require('./errors'); var selectorTokens = [ 'ident', 'string', 'selector', 'function', 'comment', 'boolean', 'space', 'color', 'unit', 'for', 'in', '[', ']', '(', ')', '+', '-', '*', '*=', '<', '>', '=', ':', '&', '&&', '~', '{', '}', '.', '..', '/', ]; var pseudoSelectors = [ 'matches', 'not', 'dir', 'lang', 'any-link', 'link', 'visited', 'local-link', 'target', 'scope', 'hover', 'active', 'focus', 'drop', 'current', 'past', 'future', 'enabled', 'disabled', 'read-only', 'read-write', 'placeholder-shown', 'checked', 'indeterminate', 'valid', 'invalid', 'in-range', 'out-of-range', 'required', 'optional', 'user-error', 'root', 'empty', 'blank', 'nth-child', 'nth-last-child', 'first-child', 'last-child', 'only-child', 'nth-of-type', 'nth-last-of-type', 'first-of-type', 'last-of-type', 'only-of-type', 'nth-match', 'nth-last-match', 'nth-column', 'nth-last-column', 'first-line', 'first-letter', 'before', 'after', 'selection', ]; var Parser = (module.exports = function Parser(str, options) { var self = this; options = options || {}; this.lexer = new Lexer(str, options); this.prefix = options.prefix || ''; this.root = options.root || new nodes.Root(); this.state = ['root']; this.stash = []; this.parens = 0; this.css = 0; this.state.pop = function() { self.prevState = [].pop.call(this); }; }); Parser.prototype = { constructor: Parser, currentState: function() { return this.state[this.state.length - 1]; }, previousState: function() { return this.state[this.state.length - 2]; }, parse: function() { var block = (this.parent = this.root); while ('eos' != this.peek().type) { this.skipWhitespace(); if ('eos' == this.peek().type) break; var stmt = this.statement(); this.accept(';'); if (!stmt) this.error( 'unexpected token {peek}, not allowed at the root level', ); block.push(stmt); } return block; }, error: function(msg) { var type = this.peek().type, val = undefined == this.peek().val ? '' : ' ' + this.peek().toString(); if (val.trim() == type.trim()) val = ''; throw new errors.ParseError( msg.replace('{peek}', '"' + type + val + '"'), ); }, accept: function(type) { if (type == this.peek().type) { return this.next(); } }, expect: function(type) { if (type != this.peek().type) { this.error('expected "' + type + '", got {peek}'); } return this.next(); }, next: function() { var tok = this.stash.length ? this.stash.pop() : this.lexer.next(), line = tok.lineno, column = tok.column || 1; if (tok.val && tok.val.nodeName) { tok.val.lineno = line; tok.val.column = column; } nodes.lineno = line; nodes.column = column; return tok; }, peek: function() { return this.lexer.peek(); }, lookahead: function(n) { return this.lexer.lookahead(n); }, isSelectorToken: function(n) { var la = this.lookahead(n).type; switch (la) { case 'for': return this.bracketed; case '[': this.bracketed = true; return true; case ']': this.bracketed = false; return true; default: return ~selectorTokens.indexOf(la); } }, isPseudoSelector: function(n) { var val = this.lookahead(n).val; return val && ~pseudoSelectors.indexOf(val.name); }, lineContains: function(type) { var i = 1, la; while ((la = this.lookahead(i++))) { if (~['indent', 'outdent', 'newline', 'eos'].indexOf(la.type)) return; if (type == la.type) return true; } }, selectorToken: function() { if (this.isSelectorToken(1)) { if ('{' == this.peek().type) { if (!this.lineContains('}')) return; var i = 0, la; while ((la = this.lookahead(++i))) { if ('}' == la.type) { if (i == 2 || (i == 3 && this.lookahead(i - 1).type == 'space')) return; break; } if (':' == la.type) return; } } return this.next(); } }, skip: function(tokens) { while (~tokens.indexOf(this.peek().type)) this.next(); }, skipWhitespace: function() { this.skip(['space', 'indent', 'outdent', 'newline']); }, skipNewlines: function() { while ('newline' == this.peek().type) this.next(); }, skipSpaces: function() { while ('space' == this.peek().type) this.next(); }, skipSpacesAndComments: function() { while ('space' == this.peek().type || 'comment' == this.peek().type) this.next(); }, looksLikeFunctionDefinition: function(i) { return ( 'indent' == this.lookahead(i).type || '{' == this.lookahead(i).type ); }, looksLikeSelector: function(fromProperty) { var i = 1, brace; if ( fromProperty && ':' == this.lookahead(i + 1).type && (this.lookahead(i + 1).space || 'indent' == this.lookahead(i + 2).type) ) return false; while ( 'ident' == this.lookahead(i).type && ('newline' == this.lookahead(i + 1).type || ',' == this.lookahead(i + 1).type) ) i += 2; while (this.isSelectorToken(i) || ',' == this.lookahead(i).type) { if ('selector' == this.lookahead(i).type) return true; if ('&' == this.lookahead(i + 1).type) return true; if ( '.' == this.lookahead(i).type && 'ident' == this.lookahead(i + 1).type ) return true; if ( '*' == this.lookahead(i).type && 'newline' == this.lookahead(i + 1).type ) return true; if ( ':' == this.lookahead(i).type && ':' == this.lookahead(i + 1).type ) return true; if ( 'color' == this.lookahead(i).type && 'newline' == this.lookahead(i - 1).type ) return true; if (this.looksLikeAttributeSelector(i)) return true; if ( ('=' == this.lookahead(i).type || 'function' == this.lookahead(i).type) && '{' == this.lookahead(i + 1).type ) return false; if ( ':' == this.lookahead(i).type && !this.isPseudoSelector(i + 1) && this.lineContains('.') ) return false; if ('{' == this.lookahead(i).type) brace = true; else if ('}' == this.lookahead(i).type) brace = false; if (brace && ':' == this.lookahead(i).type) return true; if ( 'space' == this.lookahead(i).type && '{' == this.lookahead(i + 1).type ) return true; if ( ':' == this.lookahead(i++).type && !this.lookahead(i - 1).space && this.isPseudoSelector(i) ) return true; if ( 'space' == this.lookahead(i).type && 'newline' == this.lookahead(i + 1).type && '{' == this.lookahead(i + 2).type ) return true; if ( ',' == this.lookahead(i).type && 'newline' == this.lookahead(i + 1).type ) return true; } if ( ',' == this.lookahead(i).type && 'newline' == this.lookahead(i + 1).type ) return true; if ( '{' == this.lookahead(i).type && 'newline' == this.lookahead(i + 1).type ) return true; if (this.css) { if ( ';' == this.lookahead(i).type || '}' == this.lookahead(i - 1).type ) return false; } while ( !~[ 'indent', 'outdent', 'newline', 'for', 'if', ';', '}', 'eos', ].indexOf(this.lookahead(i).type) ) ++i; if ('indent' == this.lookahead(i).type) return true; }, looksLikeAttributeSelector: function(n) { var type = this.lookahead(n).type; if ('=' == type && this.bracketed) return true; return ( ('ident' == type || 'string' == type) && ']' == this.lookahead(n + 1).type && ('newline' == this.lookahead(n + 2).type || this.isSelectorToken(n + 2)) && !this.lineContains(':') && !this.lineContains('=') ); }, looksLikeKeyframe: function() { var i = 2, type; switch (this.lookahead(i).type) { case '{': case 'indent': case ',': return true; case 'newline': while ( 'unit' == this.lookahead(++i).type || 'newline' == this.lookahead(i).type ); type = this.lookahead(i).type; return 'indent' == type || '{' == type; } }, stateAllowsSelector: function() { switch (this.currentState()) { case 'root': case 'atblock': case 'selector': case 'conditional': case 'function': case 'atrule': case 'for': return true; } }, assignAtblock: function(expr) { try { expr.push(this.atblock(expr)); } catch (err) { this.error( 'invalid right-hand side operand in assignment, got {peek}', ); } }, statement: function() { var stmt = this.stmt(), state = this.prevState, block, op; if (this.allowPostfix) { this.allowPostfix = false; state = 'expression'; } switch (state) { case 'assignment': case 'expression': case 'function arguments': while ( (op = this.accept('if') || this.accept('unless') || this.accept('for')) ) { switch (op.type) { case 'if': case 'unless': stmt = new nodes.If(this.expression(), stmt); stmt.postfix = true; stmt.negate = 'unless' == op.type; this.accept(';'); break; case 'for': var key, val = this.id().name; if (this.accept(',')) key = this.id().name; this.expect('in'); var each = new nodes.Each(val, key, this.expression()); block = new nodes.Block(this.parent, each); block.push(stmt); each.block = block; stmt = each; } } } return stmt; }, stmt: function() { var type = this.peek().type; switch (type) { case 'keyframes': return this.keyframes(); case '-moz-document': return this.mozdocument(); case 'comment': case 'selector': case 'extend': case 'literal': case 'charset': case 'namespace': case 'require': case 'extend': case 'media': case 'atrule': case 'ident': case 'scope': case 'supports': case 'unless': return this[type](); case 'function': return this.fun(); case 'import': return this.atimport(); case 'if': return this.ifstmt(); case 'for': return this.forin(); case 'return': return this.ret(); case '{': return this.property(); default: if (this.stateAllowsSelector()) { switch (type) { case 'color': case '~': case '>': case '<': case ':': case '&': case '&&': case '[': case '.': case '/': return this.selector(); case '..': if ('/' == this.lookahead(2).type) return this.selector(); case '+': return 'function' == this.lookahead(2).type ? this.functionCall() : this.selector(); case '*': return this.property(); case 'unit': if (this.looksLikeKeyframe()) return this.selector(); case '-': if ('{' == this.lookahead(2).type) return this.property(); } } var expr = this.expression(); if (expr.isEmpty) this.error('unexpected {peek}'); return expr; } }, block: function(node, scope) { var delim, stmt, next, block = (this.parent = new nodes.Block(this.parent, node)); if (false === scope) block.scope = false; this.accept('newline'); if (this.accept('{')) { this.css++; delim = '}'; this.skipWhitespace(); } else { delim = 'outdent'; this.expect('indent'); } while (delim != this.peek().type) { if (this.css) { if (this.accept('newline') || this.accept('indent')) continue; stmt = this.statement(); this.accept(';'); this.skipWhitespace(); } else { if (this.accept('newline')) continue; next = this.lookahead(2).type; if ( 'indent' == this.peek().type && ~['outdent', 'newline', 'comment'].indexOf(next) ) { this.skip(['indent', 'outdent']); continue; } if ('eos' == this.peek().type) return block; stmt = this.statement(); this.accept(';'); } if (!stmt) this.error('unexpected token {peek} in block'); block.push(stmt); } if (this.css) { this.skipWhitespace(); this.expect('}'); this.skipSpaces(); this.css--; } else { this.expect('outdent'); } this.parent = block.parent; return block; }, comment: function() { var node = this.next().val; this.skipSpaces(); return node; }, forin: function() { this.expect('for'); var key, val = this.id().name; if (this.accept(',')) key = this.id().name; this.expect('in'); this.state.push('for'); this.cond = true; var each = new nodes.Each(val, key, this.expression()); this.cond = false; each.block = this.block(each, false); this.state.pop(); return each; }, ret: function() { this.expect('return'); var expr = this.expression(); return expr.isEmpty ? new nodes.Return() : new nodes.Return(expr); }, unless: function() { this.expect('unless'); this.state.push('conditional'); this.cond = true; var node = new nodes.If(this.expression(), true); this.cond = false; node.block = this.block(node, false); this.state.pop(); return node; }, ifstmt: function() { this.expect('if'); this.state.push('conditional'); this.cond = true; var node = new nodes.If(this.expression()), cond, block; this.cond = false; node.block = this.block(node, false); this.skip(['newline', 'comment']); while (this.accept('else')) { if (this.accept('if')) { this.cond = true; cond = this.expression(); this.cond = false; block = this.block(node, false); node.elses.push(new nodes.If(cond, block)); } else { node.elses.push(this.block(node, false)); break; } this.skip(['newline', 'comment']); } this.state.pop(); return node; }, atblock: function(node) { if (!node) this.expect('atblock'); node = new nodes.Atblock(); this.state.push('atblock'); node.block = this.block(node, false); this.state.pop(); return node; }, atrule: function() { var type = this.expect('atrule').val, node = new nodes.Atrule(type), tok; this.skipSpacesAndComments(); node.segments = this.selectorParts(); this.skipSpacesAndComments(); tok = this.peek().type; if ( 'indent' == tok || '{' == tok || ('newline' == tok && '{' == this.lookahead(2).type) ) { this.state.push('atrule'); node.block = this.block(node); this.state.pop(); } return node; }, scope: function() { this.expect('scope'); var selector = this.selectorParts() .map(function(selector) { return selector.val; }) .join(''); this.selectorScope = selector.trim(); return nodes.nil; }, supports: function() { this.expect('supports'); var node = new nodes.Supports(this.supportsCondition()); this.state.push('atrule'); node.block = this.block(node); this.state.pop(); return node; }, supportsCondition: function() { var node = this.supportsNegation() || this.supportsOp(); if (!node) { this.cond = true; node = this.expression(); this.cond = false; } return node; }, supportsNegation: function() { if (this.accept('not')) { var node = new nodes.Expression(); node.push(new nodes.Literal('not')); node.push(this.supportsFeature()); return node; } }, supportsOp: function() { var feature = this.supportsFeature(), op, expr; if (feature) { expr = new nodes.Expression(); expr.push(feature); while ((op = this.accept('&&') || this.accept('||'))) { expr.push(new nodes.Literal('&&' == op.val ? 'and' : 'or')); expr.push(this.supportsFeature()); } return expr; } }, supportsFeature: function() { this.skipSpacesAndComments(); if ('(' == this.peek().type) { var la = this.lookahead(2).type; if ('ident' == la || '{' == la) { return this.feature(); } else { this.expect('('); var node = new nodes.Expression(); node.push(new nodes.Literal('(')); node.push(this.supportsCondition()); this.expect(')'); node.push(new nodes.Literal(')')); this.skipSpacesAndComments(); return node; } } }, extend: function() { var tok = this.expect('extend'), selectors = [], sel, node, arr; do { arr = this.selectorParts(); if (!arr.length) continue; sel = new nodes.Selector(arr); selectors.push(sel); if ('!' !== this.peek().type) continue; tok = this.lookahead(2); if ('ident' !== tok.type || 'optional' !== tok.val.name) continue; this.skip(['!', 'ident']); sel.optional = true; } while (this.accept(',')); node = new nodes.Extend(selectors); node.lineno = tok.lineno; node.column = tok.column; return node; }, media: function() { this.expect('media'); this.state.push('atrule'); var media = new nodes.Media(this.queries()); media.block = this.block(media); this.state.pop(); return media; }, queries: function() { var queries = new nodes.QueryList(), skip = ['comment', 'newline', 'space']; do { this.skip(skip); queries.push(this.query()); this.skip(skip); } while (this.accept(',')); return queries; }, query: function() { var query = new nodes.Query(), expr, pred, id; if ( 'ident' == this.peek().type && ('.' == this.lookahead(2).type || '[' == this.lookahead(2).type) ) { this.cond = true; expr = this.expression(); this.cond = false; query.push(new nodes.Feature(expr.nodes)); return query; } if ((pred = this.accept('ident') || this.accept('not'))) { pred = new nodes.Literal(pred.val.string || pred.val); this.skipSpacesAndComments(); if ((id = this.accept('ident'))) { query.type = id.val; query.predicate = pred; } else { query.type = pred; } this.skipSpacesAndComments(); if (!this.accept('&&')) return query; } do { query.push(this.feature()); } while (this.accept('&&')); return query; }, feature: function() { this.skipSpacesAndComments(); this.expect('('); this.skipSpacesAndComments(); var node = new nodes.Feature(this.interpolate()); this.skipSpacesAndComments(); this.accept(':'); this.skipSpacesAndComments(); this.inProperty = true; node.expr = this.list(); this.inProperty = false; this.skipSpacesAndComments(); this.expect(')'); this.skipSpacesAndComments(); return node; }, mozdocument: function() { this.expect('-moz-document'); var mozdocument = new nodes.Atrule('-moz-document'), calls = []; do { this.skipSpacesAndComments(); calls.push(this.functionCall()); this.skipSpacesAndComments(); } while (this.accept(',')); mozdocument.segments = [new nodes.Literal(calls.join(', '))]; this.state.push('atrule'); mozdocument.block = this.block(mozdocument, false); this.state.pop(); return mozdocument; }, atimport: function() { this.expect('import'); this.allowPostfix = true; return new nodes.Import(this.expression(), false); }, require: function() { this.expect('require'); this.allowPostfix = true; return new nodes.Import(this.expression(), true); }, charset: function() { this.expect('charset'); var str = this.expect('string').val; this.allowPostfix = true; return new nodes.Charset(str); }, namespace: function() { var str, prefix; this.expect('namespace'); this.skipSpacesAndComments(); if ((prefix = this.accept('ident'))) { prefix = prefix.val; } this.skipSpacesAndComments(); str = this.accept('string') || this.url(); this.allowPostfix = true; return new nodes.Namespace(str, prefix); }, keyframes: function() { var tok = this.expect('keyframes'), keyframes; this.skipSpacesAndComments(); keyframes = new nodes.Keyframes(this.selectorParts(), tok.val); this.skipSpacesAndComments(); this.state.push('atrule'); keyframes.block = this.block(keyframes); this.state.pop(); return keyframes; }, literal: function() { return this.expect('literal').val; }, id: function() { var tok = this.expect('ident'); this.accept('space'); return tok.val; }, ident: function() { var i = 2, la = this.lookahead(i).type; while ('space' == la) la = this.lookahead(++i).type; switch (la) { case '=': case '?=': case '-=': case '+=': case '*=': case '/=': case '%=': return this.assignment(); case '.': if ('space' == this.lookahead(i - 1).type) return this.selector(); if (this._ident == this.peek()) return this.id(); while ( '=' != this.lookahead(++i).type && !~['[', ',', 'newline', 'indent', 'eos'].indexOf( this.lookahead(i).type, ) ); if ('=' == this.lookahead(i).type) { this._ident = this.peek(); return this.expression(); } else if (this.looksLikeSelector() && this.stateAllowsSelector()) { return this.selector(); } case '[': if (this._ident == this.peek()) return this.id(); while ( ']' != this.lookahead(i++).type && 'selector' != this.lookahead(i).type && 'eos' != this.lookahead(i).type ); if ('=' == this.lookahead(i).type) { this._ident = this.peek(); return this.expression(); } else if (this.looksLikeSelector() && this.stateAllowsSelector()) { return this.selector(); } case '-': case '+': case '/': case '*': case '%': case '**': case '&&': case '||': case '>': case '<': case '>=': case '<=': case '!=': case '==': case '?': case 'in': case 'is a': case 'is defined': if (this._ident == this.peek()) { return this.id(); } else { this._ident = this.peek(); switch (this.currentState()) { case 'for': case 'selector': return this.property(); case 'root': case 'atblock': case 'atrule': return '[' == la ? this.subscript() : this.selector(); case 'function': case 'conditional': return this.looksLikeSelector() ? this.selector() : this.expression(); default: return this.operand ? this.id() : this.expression(); } } default: switch (this.currentState()) { case 'root': return this.selector(); case 'for': case 'selector': case 'function': case 'conditional': case 'atblock': case 'atrule': return this.property(); default: var id = this.id(); if ('interpolation' == this.previousState()) id.mixin = true; return id; } } }, interpolate: function() { var node, segs = [], star; star = this.accept('*'); if (star) segs.push(new nodes.Literal('*')); while (true) { if (this.accept('{')) { this.state.push('interpolation'); segs.push(this.expression()); this.expect('}'); this.state.pop(); } else if ((node = this.accept('-'))) { segs.push(new nodes.Literal('-')); } else if ((node = this.accept('ident'))) { segs.push(node.val); } else { break; } } if (!segs.length) this.expect('ident'); return segs; }, property: function() { if (this.looksLikeSelector(true)) return this.selector(); var ident = this.interpolate(), prop = new nodes.Property(ident), ret = prop; this.accept('space'); if (this.accept(':')) this.accept('space'); this.state.push('property'); this.inProperty = true; prop.expr = this.list(); if (prop.expr.isEmpty) ret = ident[0]; this.inProperty = false; this.allowPostfix = true; this.state.pop(); this.accept(';'); return ret; }, selector: function() { var arr, group = new nodes.Group(), scope = this.selectorScope, isRoot = 'root' == this.currentState(), selector; do { this.accept('newline'); arr = this.selectorParts(); if (isRoot && scope) arr.unshift(new nodes.Literal(scope + ' ')); if (arr.length) { selector = new nodes.Selector(arr); selector.lineno = arr[0].lineno; selector.column = arr[0].column; group.push(selector); } } while (this.accept(',') || this.accept('newline')); if ('selector-parts' == this.currentState()) return group.nodes; this.state.push('selector'); group.block = this.block(group); this.state.pop(); return group; }, selectorParts: function() { var tok, arr = []; while ((tok = this.selectorToken())) { switch (tok.type) { case '{': this.skipSpaces(); var expr = this.expression(); this.skipSpaces(); this.expect('}'); arr.push(expr); break; case this.prefix && '.': var literal = new nodes.Literal(tok.val + this.prefix); literal.prefixed = true; arr.push(literal); break; case 'comment': break; case 'color': case 'unit': arr.push(new nodes.Literal(tok.val.raw)); break; case 'space': arr.push(new nodes.Literal(' ')); break; case 'function': arr.push(new nodes.Literal(tok.val.name + '(')); break; case 'ident': arr.push(new nodes.Literal(tok.val.name || tok.val.string)); break; default: arr.push(new nodes.Literal(tok.val)); if (tok.space) arr.push(new nodes.Literal(' ')); } } return arr; }, assignment: function() { var op, node, name = this.id().name; if ( (op = this.accept('=') || this.accept('?=') || this.accept('+=') || this.accept('-=') || this.accept('*=') || this.accept('/=') || this.accept('%=')) ) { this.state.push('assignment'); var expr = this.list(); if (expr.isEmpty) this.assignAtblock(expr); node = new nodes.Ident(name, expr); this.state.pop(); switch (op.type) { case '?=': var defined = new nodes.BinOp('is defined', node), lookup = new nodes.Expression(); lookup.push(new nodes.Ident(name)); node = new nodes.Ternary(defined, lookup, node); break; case '+=': case '-=': case '*=': case '/=': case '%=': node.val = new nodes.BinOp( op.type[0], new nodes.Ident(name), expr, ); break; } } return node; }, fun: function() { var parens = 1, i = 2, tok; out: while ((tok = this.lookahead(i++))) { switch (tok.type) { case 'function': case '(': ++parens; break; case ')': if (!--parens) break out; break; case 'eos': this.error('failed to find closing paren ")"'); } } switch (this.currentState()) { case 'expression': return this.functionCall(); default: return this.looksLikeFunctionDefinition(i) ? this.functionDefinition() : this.expression(); } }, url: function() { this.expect('function'); this.state.push('function arguments'); var args = this.args(); this.expect(')'); this.state.pop(); return new nodes.Call('url', args); }, functionCall: function() { var withBlock = this.accept('+'); if ('url' == this.peek().val.name) return this.url(); var name = this.expect('function').val.name; this.state.push('function arguments'); this.parens++; var args = this.args(); this.expect(')'); this.parens--; this.state.pop(); var call = new nodes.Call(name, args); if (withBlock) { this.state.push('function'); call.block = this.block(call); this.state.pop(); } return call; }, functionDefinition: function() { var name = this.expect('function').val.name; this.state.push('function params'); this.skipWhitespace(); var params = this.params(); this.skipWhitespace(); this.expect(')'); this.state.pop(); this.state.push('function'); var fn = new nodes.Function(name, params); fn.block = this.block(fn); this.state.pop(); return new nodes.Ident(name, fn); }, params: function() { var tok, node, params = new nodes.Params(); while ((tok = this.accept('ident'))) { this.accept('space'); params.push((node = tok.val)); if (this.accept('...')) { node.rest = true; } else if (this.accept('=')) { node.val = this.expression(); } this.skipWhitespace(); this.accept(','); this.skipWhitespace(); } return params; }, args: function() { var args = new nodes.Arguments(), keyword; do { if ('ident' == this.peek().type && ':' == this.lookahead(2).type) { keyword = this.next().val.string; this.expect(':'); args.map[keyword] = this.expression(); } else { args.push(this.expression()); } } while (this.accept(',')); return args; }, list: function() { var node = this.expression(); while (this.accept(',')) { if (node.isList) { list.push(this.expression()); } else { var list = new nodes.Expression(true); list.push(node); list.push(this.expression()); node = list; } } return node; }, expression: function() { var node, expr = new nodes.Expression(); this.state.push('expression'); while ((node = this.negation())) { if (!node) this.error('unexpected token {peek} in expression'); expr.push(node); } this.state.pop(); if (expr.nodes.length) { expr.lineno = expr.nodes[0].lineno; expr.column = expr.nodes[0].column; } return expr; }, negation: function() { if (this.accept('not')) { return new nodes.UnaryOp('!', this.negation()); } return this.ternary(); }, ternary: function() { var node = this.logical(); if (this.accept('?')) { var trueExpr = this.expression(); this.expect(':'); var falseExpr = this.expression(); node = new nodes.Ternary(node, trueExpr, falseExpr); } return node; }, logical: function() { var op, node = this.typecheck(); while ((op = this.accept('&&') || this.accept('||'))) { node = new nodes.BinOp(op.type, node, this.typecheck()); } return node; }, typecheck: function() { var op, node = this.equality(); while ((op = this.accept('is a'))) { this.operand = true; if (!node) this.error('illegal unary "' + op + '", missing left-hand operand'); node = new nodes.BinOp(op.type, node, this.equality()); this.operand = false; } return node; }, equality: function() { var op, node = this.inop(); while ((op = this.accept('==') || this.accept('!='))) { this.operand = true; if (!node) this.error('illegal unary "' + op + '", missing left-hand operand'); node = new nodes.BinOp(op.type, node, this.inop()); this.operand = false; } return node; }, inop: function() { var node = this.relational(); while (this.accept('in')) { this.operand = true; if (!node) this.error('illegal unary "in", missing left-hand operand'); node = new nodes.BinOp('in', node, this.relational()); this.operand = false; } return node; }, relational: function() { var op, node = this.range(); while ( (op = this.accept('>=') || this.accept('<=') || this.accept('<') || this.accept('>')) ) { this.operand = true; if (!node) this.error('illegal unary "' + op + '", missing left-hand operand'); node = new nodes.BinOp(op.type, node, this.range()); this.operand = false; } return node; }, range: function() { var op, node = this.additive(); if ((op = this.accept('...') || this.accept('..'))) { this.operand = true; if (!node) this.error('illegal unary "' + op + '", missing left-hand operand'); node = new nodes.BinOp(op.val, node, this.additive()); this.operand = false; } return node; }, additive: function() { var op, node = this.multiplicative(); while ((op = this.accept('+') || this.accept('-'))) { this.operand = true; node = new nodes.BinOp(op.type, node, this.multiplicative()); this.operand = false; } return node; }, multiplicative: function() { var op, node = this.defined(); while ( (op = this.accept('**') || this.accept('*') || this.accept('/') || this.accept('%')) ) { this.operand = true; if ('/' == op && this.inProperty && !this.parens) { this.stash.push(new Token('literal', new nodes.Literal('/'))); this.operand = false; return node; } else { if (!node) this.error( 'illegal unary "' + op + '", missing left-hand operand', ); node = new nodes.BinOp(op.type, node, this.defined()); this.operand = false; } } return node; }, defined: function() { var node = this.unary(); if (this.accept('is defined')) { if (!node) this.error('illegal unary "is defined", missing left-hand operand'); node = new nodes.BinOp('is defined', node); } return node; }, unary: function() { var op, node; if ( (op = this.accept('!') || this.accept('~') || this.accept('+') || this.accept('-')) ) { this.operand = true; node = this.unary(); if (!node) this.error('illegal unary "' + op + '"'); node = new nodes.UnaryOp(op.type, node); this.operand = false; return node; } return this.subscript(); }, subscript: function() { var node = this.member(), id; while (this.accept('[')) { node = new nodes.BinOp('[]', node, this.expression()); this.expect(']'); } if (this.accept('=')) { node.op += '='; node.val = this.list(); if (node.val.isEmpty) this.assignAtblock(node.val); } return node; }, member: function() { var node = this.primary(); if (node) { while (this.accept('.')) { var id = new nodes.Ident(this.expect('ident').val.string); node = new nodes.Member(node, id); } this.skipSpaces(); if (this.accept('=')) { node.val = this.list(); if (node.val.isEmpty) this.assignAtblock(node.val); } } return node; }, object: function() { var obj = new nodes.Object(), id, val, comma; this.expect('{'); this.skipWhitespace(); while (!this.accept('}')) { if (this.accept('comment') || this.accept('newline')) continue; if (!comma) this.accept(','); id = this.accept('ident') || this.accept('string'); if (!id) this.error('expected "ident" or "string", got {peek}'); id = id.val.hash; this.skipSpacesAndComments(); this.expect(':'); val = this.expression(); obj.set(id, val); comma = this.accept(','); this.skipWhitespace(); } return obj; }, primary: function() { var tok; this.skipSpaces(); if (this.accept('(')) { ++this.parens; var expr = this.expression(), paren = this.expect(')'); --this.parens; if (this.accept('%')) expr.push(new nodes.Ident('%')); tok = this.peek(); if ( !paren.space && 'ident' == tok.type && ~units.indexOf(tok.val.string) ) { expr.push(new nodes.Ident(tok.val.string)); this.next(); } return expr; } tok = this.peek(); switch (tok.type) { case 'null': case 'unit': case 'color': case 'string': case 'literal': case 'boolean': case 'comment': return this.next().val; case !this.cond && '{': return this.object(); case 'atblock': return this.atblock(); case 'atrule': var id = new nodes.Ident(this.next().val); id.property = true; return id; case 'ident': return this.ident(); case 'function': return tok.anonymous ? this.functionDefinition() : this.functionCall(); } }, }; }); require.register('renderer.js', function(module, exports, require) { var Parser = require('./parser'), Evaluator = require('./visitor/evaluator'), Normalizer = require('./visitor/normalizer'), utils = require('./utils'), nodes = require('./nodes'), join = require('./path').join; module.exports = Renderer; function Renderer(str, options) { options = options || {}; options.globals = options.globals || {}; options.functions = options.functions || {}; options.use = options.use || []; options.use = Array.isArray(options.use) ? options.use : [options.use]; options.imports = []; options.paths = options.paths || []; options.filename = options.filename || 'stylus'; options.Evaluator = options.Evaluator || Evaluator; this.options = options; this.str = str; } Renderer.prototype.render = function(fn) { var parser = (this.parser = new Parser(this.str, this.options)); for (var i = 0, len = this.options.use.length; i < len; i++) { this.use(this.options.use[i]); } try { nodes.filename = this.options.filename; var ast = parser.parse(); this.evaluator = new this.options.Evaluator(ast, this.options); this.nodes = nodes; this.evaluator.renderer = this; ast = this.evaluator.evaluate(); var normalizer = new Normalizer(ast, this.options); ast = normalizer.normalize(); var compiler = this.options.sourcemap ? new (require('./visitor/sourcemapper'))(ast, this.options) : new (require('./visitor/compiler'))(ast, this.options), css = compiler.compile(); if (this.options.sourcemap) this.sourcemap = compiler.map.toJSON(); } catch (err) { var options = {}; options.input = err.input || this.str; options.filename = err.filename || this.options.filename; options.lineno = err.lineno || parser.lexer.lineno; options.column = err.column || parser.lexer.column; if (!fn) throw utils.formatException(err, options); return fn(utils.formatException(err, options)); } if (!fn) return css; fn(null, css); }; Renderer.prototype.deps = function(filename) { var opts = utils.merge({ cache: false }, this.options); if (filename) opts.filename = filename; var DepsResolver = require('./visitor/deps-resolver'), parser = new Parser(this.str, opts); try { nodes.filename = opts.filename; var ast = parser.parse(), resolver = new DepsResolver(ast, opts); return resolver.resolve(); } catch (err) { var options = {}; options.input = err.input || this.str; options.filename = err.filename || opts.filename; options.lineno = err.lineno || parser.lexer.lineno; options.column = err.column || parser.lexer.column; throw utils.formatException(err, options); } }; Renderer.prototype.set = function(key, val) { this.options[key] = val; return this; }; Renderer.prototype.get = function(key) { return this.options[key]; }; Renderer.prototype.include = function(path) { this.options.paths.push(path); return this; }; Renderer.prototype.use = function(fn) { fn.call(this, this); return this; }; Renderer.prototype.define = function(name, fn, raw) { fn = utils.coerce(fn, raw); if (fn.nodeName) { this.options.globals[name] = fn; return this; } this.options.functions[name] = fn; if (undefined != raw) fn.raw = raw; return this; }; }); require.register('selector-parser.js', function(module, exports, require) { var COMBINATORS = ['>', '+', '~']; var SelectorParser = (module.exports = function SelectorParser( str, stack, parts, ) { this.str = str; this.stack = stack || []; this.parts = parts || []; this.pos = 0; this.level = 2; this.nested = true; this.ignore = false; }); SelectorParser.prototype.skip = function(len) { this.str = this.str.substr(len); this.pos += len; }; SelectorParser.prototype.skipSpaces = function() { while (' ' == this.str[0]) this.skip(1); }; SelectorParser.prototype.advance = function() { return ( this.root() || this.relative() || this.initial() || this.escaped() || this.parent() || this.partial() || this.char() ); }; SelectorParser.prototype.root = function() { if (!this.pos && '/' == this.str[0] && 'deep' != this.str.slice(1, 5)) { this.nested = false; this.skip(1); } }; SelectorParser.prototype.relative = function(multi) { if ((!this.pos || multi) && '../' == this.str.slice(0, 3)) { this.nested = false; this.skip(3); while (this.relative(true)) this.level++; if (!this.raw) { var ret = this.stack[this.stack.length - this.level]; if (ret) { return ret; } else { this.ignore = true; } } } }; SelectorParser.prototype.initial = function() { if (!this.pos && '~' == this.str[0] && '/' == this.str[1]) { this.nested = false; this.skip(2); return this.stack[0]; } }; SelectorParser.prototype.escaped = function() { if ('\\' == this.str[0]) { var char = this.str[1]; if ('&' == char || '^' == char) { this.skip(2); return char; } } }; SelectorParser.prototype.parent = function() { if ('&' == this.str[0]) { this.nested = false; if (!this.pos && (!this.stack.length || this.raw)) { var i = 0; while (' ' == this.str[++i]); if (~COMBINATORS.indexOf(this.str[i])) { this.skip(i + 1); return; } } this.skip(1); if (!this.raw) return this.stack[this.stack.length - 1]; } }; SelectorParser.prototype.partial = function() { if ('^' == this.str[0] && '[' == this.str[1]) { this.skip(2); this.skipSpaces(); var ret = this.range(); this.skipSpaces(); if (']' != this.str[0]) return '^['; this.nested = false; this.skip(1); if (ret) { return ret; } else { this.ignore = true; } } }; SelectorParser.prototype.number = function() { var i = 0, ret = ''; if ('-' == this.str[i]) ret += this.str[i++]; while (this.str.charCodeAt(i) >= 48 && this.str.charCodeAt(i) <= 57) ret += this.str[i++]; if (ret) { this.skip(i); return Number(ret); } }; SelectorParser.prototype.range = function() { var start = this.number(), ret; if ('..' == this.str.slice(0, 2)) { this.skip(2); var end = this.number(), len = this.parts.length; if (start < 0) start = len + start - 1; if (end < 0) end = len + end - 1; if (start > end) { var tmp = start; start = end; end = tmp; } if (end < len - 1) { ret = this.parts .slice(start, end + 1) .map(function(part) { var selector = new SelectorParser(part, this.stack, this.parts); selector.raw = true; return selector.parse(); }, this) .map(function(selector) { return (selector.nested ? ' ' : '') + selector.val; }) .join('') .trim(); } } else { ret = this.stack[start < 0 ? this.stack.length + start - 1 : start]; } if (ret) { return ret; } else { this.ignore = true; } }; SelectorParser.prototype.char = function() { var char = this.str[0]; this.skip(1); return char; }; SelectorParser.prototype.parse = function() { var val = ''; while (this.str.length) { val += this.advance() || ''; if (this.ignore) { val = ''; break; } } return { val: val.trimRight(), nested: this.nested }; }; }); require.register('stack/index.js', function(module, exports, require) { var Stack = (module.exports = function Stack() { Array.apply(this, arguments); }); Stack.prototype.__proto__ = Array.prototype; Stack.prototype.push = function(frame) { frame.stack = this; frame.parent = this.currentFrame; return [].push.apply(this, arguments); }; Stack.prototype.__defineGetter__('currentFrame', function() { return this[this.length - 1]; }); Stack.prototype.getBlockFrame = function(block) { for (var i = 0; i < this.length; ++i) { if (block == this[i].block) { return this[i]; } } }; Stack.prototype.lookup = function(name) { var block = this.currentFrame.block, val, ret; do { var frame = this.getBlockFrame(block); if (frame && (val = frame.lookup(name))) { return val; } } while ((block = block.parent)); }; Stack.prototype.inspect = function() { return this.reverse() .map(function(frame) { return frame.inspect(); }) .join('\n'); }; Stack.prototype.toString = function() { var block, node, buf = [], location, len = this.length; while (len--) { block = this[len].block; if ((node = block.node)) { location = '(' + node.filename + ':' + (node.lineno + 1) + ':' + node.column + ')'; switch (node.nodeName) { case 'function': buf.push(' at ' + node.name + '() ' + location); break; case 'group': buf.push(' at "' + node.nodes[0].val + '" ' + location); break; } } } return buf.join('\n'); }; }); require.register('stack/frame.js', function(module, exports, require) { var Scope = require('./scope'); var Frame = (module.exports = function Frame(block) { this._scope = false === block.scope ? null : new Scope(); this.block = block; }); Frame.prototype.__defineGetter__('scope', function() { return this._scope || this.parent.scope; }); Frame.prototype.lookup = function(name) { return this.scope.lookup(name); }; Frame.prototype.inspect = function() { return ( '[Frame ' + (false === this.block.scope ? 'scope-less' : this.scope.inspect()) + ']' ); }; }); require.register('stack/scope.js', function(module, exports, require) { var Scope = (module.exports = function Scope() { this.locals = {}; }); Scope.prototype.add = function(ident) { this.locals[ident.name] = ident.val; }; Scope.prototype.lookup = function(name) { return this.locals[name]; }; Scope.prototype.inspect = function() { var keys = Object.keys(this.locals).map(function(key) { return '@' + key; }); return '[Scope' + (keys.length ? ' ' + keys.join(', ') : '') + ']'; }; }); require.register('stylus.js', function(module, exports, require) { var Renderer = require('./renderer'), nodes = require('./nodes'), utils = require('./utils'); exports = module.exports = render; exports.version = '0.54.5'; exports.nodes = nodes; exports.functions = require('./functions'); exports.utils = require('./utils'); exports.Visitor = require('./visitor'); exports.Parser = require('./parser'); exports.Evaluator = require('./visitor/evaluator'); exports.Normalizer = require('./visitor/normalizer'); exports.Compiler = require('./visitor/compiler'); exports.render = function(str, options, fn) { if ('function' == typeof options) (fn = options), (options = {}); if (bifs) str = bifs + str; return new Renderer(str, options).render(fn); }; function render(str, options) { if (bifs) str = bifs + str; return new Renderer(str, options); } exports.url = require('./functions/url'); }); require.register('token.js', function(module, exports, require) { var Token = (exports = module.exports = function Token(type, val) { this.type = type; this.val = val; }); Token.prototype.inspect = function() { var val = ' ' + this.val; return ( '[Token:' + this.lineno + ':' + this.column + ' ' + '' + this.type + '' + '' + (this.val ? val : '') + '' + ']' ); }; Token.prototype.toString = function() { return (undefined === this.val ? this.type : this.val).toString(); }; }); require.register('utils.js', function(module, exports, require) { var nodes = require('./nodes'), join = require('./path').join, isAbsolute = require('./path').isAbsolute; exports.absolute = isAbsolute || function(path) { return ( path.substr(0, 2) == '\\\\' || '/' === path.charAt(0) || /^[a-z]:[\\\/]/i.test(path) ); }; exports.lookup = function(path, paths, ignore) { var lookup, i = paths.length; if (exports.absolute(path)) { try { return path; } catch (err) {} } while (i--) { try { lookup = join(paths[i], path); if (ignore == lookup) continue; return lookup; } catch (err) {} } }; exports.find = function(path, paths, ignore) { var lookup, found, i = paths.length; if (exports.absolute(path)) { if ((found = glob.sync(path)).length) { return found; } } while (i--) { lookup = join(paths[i], path); if (ignore == lookup) continue; if ((found = glob.sync(lookup)).length) { return found; } } }; exports.lookupIndex = function(name, paths, filename) { var found = exports.find(join(name, 'index.styl'), paths, filename); if (!found) { found = exports.find( join(name, basename(name).replace(/\.styl/i, '') + '.styl'), paths, filename, ); } if (!found && !~name.indexOf('node_modules')) { 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; } }; 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' : ''); if (err.fromStylus) err.stack = 'Error: ' + err.message; return err; }; 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); }; 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); } }; 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); } }; exports.assertPresent = function(node, name) { if (node) return; if (name) throw new Error('"' + name + '" argument required'); throw new Error('argument missing'); }; exports.unwrap = function(expr) { 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]); }; 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.nil; if (Array.isArray(val)) return exports.coerceArray(val, raw); if (val.nodeName) return val; return exports.coerceObject(val, raw); } }; exports.coerceArray = function(val, raw) { var expr = new nodes.Expression(); val.forEach(function(val) { expr.push(exports.coerce(val, raw)); }); return expr; }; 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; }; exports.params = function(fn) { return fn.toString().match(/\(([^)]*)\)/)[1].split(/ *, */); }; 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; }; 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; }; 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 exports.uniq(selectors); }; 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; }; }); require.register('visitor/index.js', function(module, exports, require) { var Visitor = (module.exports = function Visitor(root) { this.root = root; }); Visitor.prototype.visit = function(node, fn) { var method = 'visit' + node.constructor.name; if (this[method]) return this[method](node); return node; }; }); require.register('visitor/compiler.js', function(module, exports, require) { var Visitor = require('./index'), utils = require('../utils'); var Compiler = (module.exports = function Compiler(root, options) { options = options || {}; this.compress = options.compress; this.firebug = options.firebug; this.linenos = options.linenos; this.spaces = options['indent spaces'] || 2; this.indents = 1; Visitor.call(this, root); this.stack = []; }); Compiler.prototype.__proto__ = Visitor.prototype; Compiler.prototype.compile = function() { return this.visit(this.root); }; Compiler.prototype.out = function(str, node) { return str; }; Compiler.prototype.__defineGetter__('indent', function() { if (this.compress) return ''; return new Array(this.indents).join(Array(this.spaces + 1).join(' ')); }); Compiler.prototype.needBrackets = function(node) { return ( 1 == this.indents || 'atrule' != node.nodeName || node.hasOnlyProperties ); }; Compiler.prototype.visitRoot = function(block) { this.buf = ''; for (var i = 0, len = block.nodes.length; i < len; ++i) { var node = block.nodes[i]; if (this.linenos || this.firebug) this.debugInfo(node); var ret = this.visit(node); if (ret) this.buf += this.out(ret + '\n', node); } return this.buf; }; Compiler.prototype.visitBlock = function(block) { var node, separator = this.compress ? '' : '\n', needBrackets; if (block.hasProperties && !block.lacksRenderedSelectors) { needBrackets = this.needBrackets(block.node); if (needBrackets) { this.buf += this.out(this.compress ? '{' : ' {\n'); ++this.indents; } for (var i = 0, len = block.nodes.length; i < len; ++i) { this.last = len - 1 == i; node = block.nodes[i]; switch (node.nodeName) { case 'null': case 'expression': case 'function': case 'group': case 'block': case 'unit': case 'media': case 'keyframes': case 'atrule': case 'supports': continue; case !this.compress && node.inline && 'comment': this.buf = this.buf.slice(0, -1); this.buf += this.out(' ' + this.visit(node) + '\n', node); break; case 'property': var ret = this.visit(node) + separator; this.buf += this.compress ? ret : this.out(ret, node); break; default: this.buf += this.out(this.visit(node) + separator, node); } } if (needBrackets) { --this.indents; this.buf += this.out(this.indent + '}' + separator); } } for (var i = 0, len = block.nodes.length; i < len; ++i) { node = block.nodes[i]; switch (node.nodeName) { case 'group': case 'block': case 'keyframes': if (this.linenos || this.firebug) this.debugInfo(node); this.visit(node); break; case 'media': case 'import': case 'atrule': case 'supports': this.visit(node); break; case 'comment': if (!node.suppress) { this.buf += this.out(this.indent + this.visit(node) + '\n', node); } break; case 'charset': case 'literal': case 'namespace': this.buf += this.out(this.visit(node) + '\n', node); break; } } }; Compiler.prototype.visitKeyframes = function(node) { if (!node.frames) return; var prefix = 'official' == node.prefix ? '' : '-' + node.prefix + '-'; this.buf += this.out( '@' + prefix + 'keyframes ' + this.visit(node.val) + (this.compress ? '{' : ' {\n'), node, ); this.keyframe = true; ++this.indents; this.visit(node.block); --this.indents; this.keyframe = false; this.buf += this.out('}' + (this.compress ? '' : '\n')); }; Compiler.prototype.visitMedia = function(media) { var val = media.val; if (!media.hasOutput || !val.nodes.length) return; this.buf += this.out('@media ', media); this.visit(val); this.buf += this.out(this.compress ? '{' : ' {\n'); ++this.indents; this.visit(media.block); --this.indents; this.buf += this.out('}' + (this.compress ? '' : '\n')); }; Compiler.prototype.visitQueryList = function(queries) { for (var i = 0, len = queries.nodes.length; i < len; ++i) { this.visit(queries.nodes[i]); if (len - 1 != i) this.buf += this.out(',' + (this.compress ? '' : ' ')); } }; Compiler.prototype.visitQuery = function(node) { var len = node.nodes.length; if (node.predicate) this.buf += this.out(node.predicate + ' '); if (node.type) this.buf += this.out(node.type + (len ? ' and ' : '')); for (var i = 0; i < len; ++i) { this.buf += this.out(this.visit(node.nodes[i])); if (len - 1 != i) this.buf += this.out(' and '); } }; Compiler.prototype.visitFeature = function(node) { if (!node.expr) { return node.name; } else if (node.expr.isEmpty) { return '(' + node.name + ')'; } else { return ( '(' + node.name + ':' + (this.compress ? '' : ' ') + this.visit(node.expr) + ')' ); } }; Compiler.prototype.visitImport = function(imported) { this.buf += this.out( '@import ' + this.visit(imported.path) + ';\n', imported, ); }; Compiler.prototype.visitAtrule = function(atrule) { var newline = this.compress ? '' : '\n'; this.buf += this.out(this.indent + '@' + atrule.type, atrule); if (atrule.val) this.buf += this.out(' ' + atrule.val.trim()); if (atrule.block) { if (atrule.hasOnlyProperties) { this.visit(atrule.block); } else { this.buf += this.out(this.compress ? '{' : ' {\n'); ++this.indents; this.visit(atrule.block); --this.indents; this.buf += this.out(this.indent + '}' + newline); } } else { this.buf += this.out(';' + newline); } }; (Compiler.prototype.visitSupports = function(node) { if (!node.hasOutput) return; this.buf += this.out(this.indent + '@supports ', node); this.isCondition = true; this.buf += this.out(this.visit(node.condition)); this.isCondition = false; this.buf += this.out(this.compress ? '{' : ' {\n'); ++this.indents; this.visit(node.block); --this.indents; this.buf += this.out(this.indent + '}' + (this.compress ? '' : '\n')); }), (Compiler.prototype.visitComment = function(comment) { return this.compress ? comment.suppress ? '' : comment.str : comment.str; }); Compiler.prototype.visitFunction = function(fn) { return fn.name; }; Compiler.prototype.visitCharset = function(charset) { return '@charset ' + this.visit(charset.val) + ';'; }; Compiler.prototype.visitNamespace = function(namespace) { return ( '@namespace ' + (namespace.prefix ? this.visit(namespace.prefix) + ' ' : '') + this.visit(namespace.val) + ';' ); }; Compiler.prototype.visitLiteral = function(lit) { var val = lit.val; if (lit.css) val = val.replace(/^ /gm, ''); return val; }; Compiler.prototype.visitBoolean = function(bool) { return bool.toString(); }; Compiler.prototype.visitRGBA = function(rgba) { return rgba.toString(); }; Compiler.prototype.visitHSLA = function(hsla) { return hsla.rgba.toString(); }; Compiler.prototype.visitUnit = function(unit) { var type = unit.type || '', n = unit.val, float = n != (n | 0); if (this.compress) { if ('%' != type && 's' != type && 'ms' != type && 0 == n) return '0'; if (float && n < 1 && n > -1) { return n.toString().replace('0.', '.') + type; } } return (float ? parseFloat(n.toFixed(15)) : n).toString() + type; }; Compiler.prototype.visitGroup = function(group) { var stack = this.keyframe ? [] : this.stack, comma = this.compress ? ',' : ',\n'; stack.push(group.nodes); if (group.block.hasProperties) { var selectors = utils.compileSelectors.call(this, stack), len = selectors.length; if (len) { if (this.keyframe) comma = this.compress ? ',' : ', '; for (var i = 0; i < len; ++i) { var selector = selectors[i], last = i == len - 1; if (this.keyframe) selector = i ? selector.trim() : selector; this.buf += this.out( selector + (last ? '' : comma), group.nodes[i], ); } } else { group.block.lacksRenderedSelectors = true; } } this.visit(group.block); stack.pop(); }; Compiler.prototype.visitIdent = function(ident) { return ident.name; }; Compiler.prototype.visitString = function(string) { return this.isURL ? string.val : string.toString(); }; Compiler.prototype.visitNull = function(node) { return ''; }; Compiler.prototype.visitCall = function(call) { this.isURL = 'url' == call.name; var args = call.args.nodes .map(function(arg) { return this.visit(arg); }, this) .join(this.compress ? ',' : ', '); if (this.isURL) args = '"' + args + '"'; this.isURL = false; return call.name + '(' + args + ')'; }; Compiler.prototype.visitExpression = function(expr) { var buf = [], self = this, len = expr.nodes.length, nodes = expr.nodes.map(function(node) { return self.visit(node); }); nodes.forEach(function(node, i) { var last = i == len - 1; buf.push(node); if ('/' == nodes[i + 1] || '/' == node) return; if (last) return; var space = self.isURL || (self.isCondition && (')' == nodes[i + 1] || '(' == node)) ? '' : ' '; buf.push(expr.isList ? (self.compress ? ',' : ', ') : space); }); return buf.join(''); }; Compiler.prototype.visitArguments = Compiler.prototype.visitExpression; Compiler.prototype.visitProperty = function(prop) { var val = this.visit(prop.expr).trim(), name = prop.name || prop.segments.join(''), arr = []; arr.push( this.out(this.indent), this.out(name + (this.compress ? ':' : ': '), prop), this.out(val, prop.expr), this.out(this.compress ? (this.last ? '' : ';') : ';'), ); return arr.join(''); }; Compiler.prototype.debugInfo = function(node) { var path = node.filename == 'stdin' ? 'stdin' : fs.realpathSync(node.filename), line = (node.nodes && node.nodes.length ? node.nodes[0].lineno : node.lineno) || 1; if (this.linenos) { this.buf += '\n/* ' + 'line ' + line + ' : ' + path + ' */\n'; } if (this.firebug) { path = 'file\\:\\/\\/' + path.replace(/([.:\/\\])/g, function(m) { return '\\' + (m === '\\' ? '/' : m); }); line = '\\00003' + line; this.buf += '\n@media -stylus-debug-info' + '{filename{font-family:' + path + '}line{font-family:' + line + '}}\n'; } }; }); require.register('visitor/evaluator.js', function(module, exports, require) { var Visitor = require('./index'), nodes = require('../nodes'), Stack = require('../stack'), Frame = require('../stack/frame'), utils = require('../utils'), bifs = require('../functions'), dirname = require('../path').dirname, colors = require('../colors'), units = require('../units'); function cloneNode(node) { if (node.block && node.block.node) { node.block.node = node.block.node.clone(); } if (node.nodes && node.nodes.length) { node.nodes.map(cloneNode); } return node; } function importFile(node, file, literal) { var importStack = this.importStack, Parser = require('../parser'), stat; if (node.once) { if (this.requireHistory[file]) return nodes.nil; this.requireHistory[file] = true; if (literal && !this.includeCSS) { return node; } } if (~importStack.indexOf(file)) throw new Error('import loop has been found'); var str = fs.readFileSync(file, 'utf8'); if (!str.trim()) return nodes.nil; node.path = file; node.dirname = dirname(file); stat = fs.statSync(file); node.mtime = stat.mtime; this.paths.push(node.dirname); if (this.options._imports) this.options._imports.push(node.clone()); importStack.push(file); nodes.filename = file; if (literal) { literal = new nodes.Literal(str.replace(/\r\n?/g, '\n')); literal.lineno = literal.column = 1; if (!this.resolveURL) return literal; } var block = new nodes.Block(), parser = new Parser(str, utils.merge({ root: block }, this.options)); try { block = parser.parse(); } catch (err) { var line = parser.lexer.lineno, column = parser.lexer.column; if (literal && this.includeCSS && this.resolveURL) { this.warn( 'ParseError: ' + file + ':' + line + ':' + column + '. This file included as-is', ); return literal; } else { err.filename = file; err.lineno = line; err.column = column; err.input = str; throw err; } } block = block.clone(this.currentBlock); block.parent = this.currentBlock; block.scope = false; var ret = this.visit(block); importStack.pop(); if (!this.resolveURL || this.resolveURL.nocheck) this.paths.pop(); return ret; } var Evaluator = (module.exports = function Evaluator(root, options) { options = options || {}; Visitor.call(this, root); var functions = (this.functions = options.functions || {}); this.stack = new Stack(); this.imports = options.imports || []; this.globals = options.globals || {}; this.paths = options.paths || []; this.prefix = options.prefix || ''; this.filename = options.filename; this.includeCSS = options['include css']; this.resolveURL = functions.url && 'resolver' == functions.url.name && functions.url.options; this.paths.push(dirname(options.filename || '.')); this.stack.push((this.global = new Frame(root))); this.warnings = options.warn; this.options = options; this.calling = []; this.importStack = []; this.ret = 0; this.requireHistory = {}; }); Evaluator.prototype.__proto__ = Visitor.prototype; var visit = Visitor.prototype.visit; Evaluator.prototype.visit = function(node) { try { return visit.call(this, node); } catch (err) { if (err.filename) throw err; err.lineno = node.lineno; err.column = node.column; err.filename = node.filename; err.stylusStack = this.stack.toString(); try { } catch (err) {} throw err; } }; Evaluator.prototype.setup = function() { var root = this.root; var imports = []; this.populateGlobalScope(); this.imports.forEach(function(file) { var expr = new nodes.Expression(); expr.push(new nodes.String(file)); imports.push(new nodes.Import(expr)); }, this); root.nodes = imports.concat(root.nodes); }; Evaluator.prototype.populateGlobalScope = function() { var scope = this.global.scope; Object.keys(colors).forEach(function(name) { var color = colors[name], rgba = new nodes.RGBA(color[0], color[1], color[2], color[3]), node = new nodes.Ident(name, rgba); rgba.name = name; scope.add(node); }); scope.add( new nodes.Ident( 'embedurl', new nodes.Function( 'embedurl', require('../functions/url')({ limit: false }), ), ), ); var globals = this.globals; Object.keys(globals).forEach(function(name) { var val = globals[name]; if (!val.nodeName) val = new nodes.Literal(val); scope.add(new nodes.Ident(name, val)); }); }; Evaluator.prototype.evaluate = function() { this.setup(); return this.visit(this.root); }; Evaluator.prototype.visitGroup = function(group) { group.nodes = group.nodes.map(function(selector) { selector.val = this.interpolate(selector); return selector; }, this); group.block = this.visit(group.block); return group; }; Evaluator.prototype.visitReturn = function(ret) { ret.expr = this.visit(ret.expr); throw ret; }; Evaluator.prototype.visitMedia = function(media) { media.block = this.visit(media.block); media.val = this.visit(media.val); return media; }; Evaluator.prototype.visitQueryList = function(queries) { var val, query; queries.nodes.forEach(this.visit, this); if (1 == queries.nodes.length) { query = queries.nodes[0]; if ((val = this.lookup(query.type))) { val = val.first.string; if (!val) return queries; var Parser = require('../parser'), parser = new Parser(val, this.options); queries = this.visit(parser.queries()); } } return queries; }; Evaluator.prototype.visitQuery = function(node) { node.predicate = this.visit(node.predicate); node.type = this.visit(node.type); node.nodes.forEach(this.visit, this); return node; }; Evaluator.prototype.visitFeature = function(node) { node.name = this.interpolate(node); if (node.expr) { this.ret++; node.expr = this.visit(node.expr); this.ret--; } return node; }; Evaluator.prototype.visitObject = function(obj) { for (var key in obj.vals) { obj.vals[key] = this.visit(obj.vals[key]); } return obj; }; Evaluator.prototype.visitMember = function(node) { var left = node.left, right = node.right, obj = this.visit(left).first; if ('object' != obj.nodeName) { throw new Error(left.toString() + ' has no property .' + right); } if (node.val) { this.ret++; obj.set(right.name, this.visit(node.val)); this.ret--; } return obj.get(right.name); }; Evaluator.prototype.visitKeyframes = function(keyframes) { var val; if (keyframes.fabricated) return keyframes; keyframes.val = this.interpolate(keyframes).trim(); if ((val = this.lookup(keyframes.val))) { keyframes.val = val.first.string || val.first.name; } keyframes.block = this.visit(keyframes.block); if ('official' != keyframes.prefix) return keyframes; this.vendors.forEach(function(prefix) { if ('ms' == prefix) return; var node = keyframes.clone(); node.val = keyframes.val; node.prefix = prefix; node.block = keyframes.block; node.fabricated = true; this.currentBlock.push(node); }, this); return nodes.nil; }; Evaluator.prototype.visitFunction = function(fn) { var local = this.stack.currentFrame.scope.lookup(fn.name); if (local) this.warn( 'local ' + local.nodeName + ' "' + fn.name + '" previously defined in this scope', ); var user = this.functions[fn.name]; if (user) this.warn('user-defined function "' + fn.name + '" is already defined'); var bif = bifs[fn.name]; if (bif) this.warn('built-in function "' + fn.name + '" is already defined'); return fn; }; Evaluator.prototype.visitEach = function(each) { this.ret++; var expr = utils.unwrap(this.visit(each.expr)), len = expr.nodes.length, val = new nodes.Ident(each.val), key = new nodes.Ident(each.key || '__index__'), scope = this.currentScope, block = this.currentBlock, vals = [], self = this, body, obj; this.ret--; each.block.scope = false; function visitBody(key, val) { scope.add(val); scope.add(key); body = self.visit(each.block.clone()); vals = vals.concat(body.nodes); } if (1 == len && 'object' == expr.nodes[0].nodeName) { obj = expr.nodes[0]; for (var prop in obj.vals) { val.val = new nodes.String(prop); key.val = obj.get(prop); visitBody(key, val); } } else { for (var i = 0; i < len; ++i) { val.val = expr.nodes[i]; key.val = new nodes.Unit(i); visitBody(key, val); } } this.mixin(vals, block); return vals[vals.length - 1] || nodes.nil; }; Evaluator.prototype.visitCall = function(call) { var fn = this.lookup(call.name), literal, ret; this.ignoreColors = 'url' == call.name; if (fn && 'expression' == fn.nodeName) { fn = fn.nodes[0]; } if (fn && 'function' != fn.nodeName) { fn = this.lookupFunction(call.name); } if (!fn || fn.nodeName != 'function') { if ('calc' == this.unvendorize(call.name)) { literal = call.args.nodes && call.args.nodes[0]; if (literal) ret = new nodes.Literal(call.name + literal); } else { ret = this.literalCall(call); } this.ignoreColors = false; return ret; } this.calling.push(call.name); if (this.calling.length > 200) { throw new RangeError('Maximum stylus call stack size exceeded'); } if ('expression' == fn.nodeName) fn = fn.first; this.ret++; var args = this.visit(call.args); for (var key in args.map) { args.map[key] = this.visit(args.map[key].clone()); } this.ret--; if (fn.fn) { ret = this.invokeBuiltin(fn.fn, args); } else if ('function' == fn.nodeName) { if (call.block) call.block = this.visit(call.block); ret = this.invokeFunction(fn, args, call.block); } this.calling.pop(); this.ignoreColors = false; return ret; }; Evaluator.prototype.visitIdent = function(ident) { var prop; if (ident.property) { if ((prop = this.lookupProperty(ident.name))) { return this.visit(prop.expr.clone()); } return nodes.nil; } else if (ident.val.isNull) { var val = this.lookup(ident.name); if (val && ident.mixin) this.mixinNode(val); return val ? this.visit(val) : ident; } else { this.ret++; ident.val = this.visit(ident.val); this.ret--; this.currentScope.add(ident); return ident.val; } }; Evaluator.prototype.visitBinOp = function(binop) { if ('is defined' == binop.op) return this.isDefined(binop.left); this.ret++; var op = binop.op, left = this.visit(binop.left), right = '||' == op || '&&' == op ? binop.right : this.visit(binop.right); var val = binop.val ? this.visit(binop.val) : null; this.ret--; try { return this.visit(left.operate(op, right, val)); } catch (err) { if ('CoercionError' == err.name) { switch (op) { case '==': return nodes.no; case '!=': return nodes.yes; } } throw err; } }; Evaluator.prototype.visitUnaryOp = function(unary) { var op = unary.op, node = this.visit(unary.expr); if ('!' != op) { node = node.first.clone(); utils.assertType(node, 'unit'); } switch (op) { case '-': node.val = -node.val; break; case '+': node.val = +node.val; break; case '~': node.val = ~node.val; break; case '!': return node.toBoolean().negate(); } return node; }; Evaluator.prototype.visitTernary = function(ternary) { var ok = this.visit(ternary.cond).toBoolean(); return ok.isTrue ? this.visit(ternary.trueExpr) : this.visit(ternary.falseExpr); }; Evaluator.prototype.visitExpression = function(expr) { for (var i = 0, len = expr.nodes.length; i < len; ++i) { expr.nodes[i] = this.visit(expr.nodes[i]); } if (this.castable(expr)) expr = this.cast(expr); return expr; }; Evaluator.prototype.visitArguments = Evaluator.prototype.visitExpression; Evaluator.prototype.visitProperty = function(prop) { var name = this.interpolate(prop), fn = this.lookup(name), call = fn && 'function' == fn.first.nodeName, literal = ~this.calling.indexOf(name), _prop = this.property; if (call && !literal && !prop.literal) { var args = nodes.Arguments.fromExpression( utils.unwrap(prop.expr.clone()), ); prop.name = name; this.property = prop; this.ret++; this.property.expr = this.visit(prop.expr); this.ret--; var ret = this.visit(new nodes.Call(name, args)); this.property = _prop; return ret; } else { this.ret++; prop.name = name; prop.literal = true; this.property = prop; prop.expr = this.visit(prop.expr); this.property = _prop; this.ret--; return prop; } }; Evaluator.prototype.visitRoot = function(block) { if (block != this.root) { block.constructor = nodes.Block; return this.visit(block); } for (var i = 0; i < block.nodes.length; ++i) { block.index = i; block.nodes[i] = this.visit(block.nodes[i]); } return block; }; Evaluator.prototype.visitBlock = function(block) { this.stack.push(new Frame(block)); for (block.index = 0; block.index < block.nodes.length; ++block.index) { try { block.nodes[block.index] = this.visit(block.nodes[block.index]); } catch (err) { if ('return' == err.nodeName) { if (this.ret) { this.stack.pop(); throw err; } else { block.nodes[block.index] = err; break; } } else { throw err; } } } this.stack.pop(); return block; }; Evaluator.prototype.visitAtblock = function(atblock) { atblock.block = this.visit(atblock.block); return atblock; }; Evaluator.prototype.visitAtrule = function(atrule) { atrule.val = this.interpolate(atrule); if (atrule.block) atrule.block = this.visit(atrule.block); return atrule; }; Evaluator.prototype.visitSupports = function(node) { var condition = node.condition, val; this.ret++; node.condition = this.visit(condition); this.ret--; val = condition.first; if (1 == condition.nodes.length && 'string' == val.nodeName) { node.condition = val.string; } node.block = this.visit(node.block); return node; }; Evaluator.prototype.visitIf = function(node) { var ret, block = this.currentBlock, negate = node.negate; this.ret++; var ok = this.visit(node.cond).first.toBoolean(); this.ret--; node.block.scope = node.block.hasMedia; if (negate) { if (ok.isFalse) { ret = this.visit(node.block); } } else { if (ok.isTrue) { ret = this.visit(node.block); } else if (node.elses.length) { var elses = node.elses, len = elses.length, cond; for (var i = 0; i < len; ++i) { if (elses[i].cond) { elses[i].block.scope = elses[i].block.hasMedia; this.ret++; cond = this.visit(elses[i].cond).first.toBoolean(); this.ret--; if (cond.isTrue) { ret = this.visit(elses[i].block); break; } } else { elses[i].scope = elses[i].hasMedia; ret = this.visit(elses[i]); } } } } if ( ret && !node.postfix && block.node && ~['group', 'atrule', 'media', 'supports', 'keyframes'].indexOf( block.node.nodeName, ) ) { this.mixin(ret.nodes, block); return nodes.nil; } return ret || nodes.nil; }; Evaluator.prototype.visitExtend = function(extend) { var block = this.currentBlock; if ('group' != block.node.nodeName) block = this.closestGroup; extend.selectors.forEach(function(selector) { block.node.extends.push({ selector: this.interpolate(selector.clone()).trim(), optional: selector.optional, lineno: selector.lineno, column: selector.column, }); }, this); return nodes.nil; }; Evaluator.prototype.visitImport = function(imported) { this.ret++; var path = this.visit(imported.path).first, nodeName = imported.once ? 'require' : 'import', found, literal; this.ret--; if ('url' == path.name) { if (imported.once) throw new Error('You cannot @require a url'); return imported; } if (!path.string) throw new Error('@' + nodeName + ' string expected'); var name = (path = path.string); if (/(?:url\s*\(\s*)?['"]?(?:#|(?:https?:)?\/\/)/i.test(path)) { if (imported.once) throw new Error('You cannot @require a url'); return imported; } if (/\.css(?:"|$)/.test(path)) { literal = true; if (!imported.once && !this.includeCSS) { return imported; } } if (!literal && !/\.styl$/i.test(path)) path += '.styl'; found = utils.find(path, this.paths, this.filename); if (!found) { found = utils.lookupIndex(name, this.paths, this.filename); } 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)); } return block; }; Evaluator.prototype.invokeFunction = function(fn, args, content) { var block = new nodes.Block(fn.block.parent); var body = fn.block.clone(block); var mixinBlock = this.stack.currentFrame.block; this.stack.push(new Frame(block)); var scope = this.currentScope; if ('arguments' != args.nodeName) { var expr = new nodes.Expression(); expr.push(args); args = nodes.Arguments.fromExpression(expr); } scope.add(new nodes.Ident('arguments', args)); scope.add( new nodes.Ident( 'mixin', this.ret ? nodes.no : new nodes.String(mixinBlock.nodeName), ), ); if (this.property) { var prop = this.propertyExpression(this.property, fn.name); scope.add(new nodes.Ident('current-property', prop)); } else { scope.add(new nodes.Ident('current-property', nodes.nil)); } var expr = new nodes.Expression(); for (var i = this.calling.length - 1; i--; ) { expr.push(new nodes.Literal(this.calling[i])); } scope.add(new nodes.Ident('called-from', expr)); var i = 0, len = args.nodes.length; fn.params.nodes.forEach(function(node) { if (node.rest) { node.val = new nodes.Expression(); for (; i < len; ++i) node.val.push(args.nodes[i]); node.val.preserve = true; node.val.isList = args.isList; } else { var arg = args.map[node.name] || args.nodes[i++]; node = node.clone(); if (arg) { arg.isEmpty ? (args.nodes[i - 1] = this.visit(node)) : (node.val = arg); } else { args.push(node.val); } if (node.val.isNull) { throw new Error('argument "' + node + '" required for ' + fn); } } scope.add(node); }, this); if (content) scope.add(new nodes.Ident('block', content, true)); return this.invoke(body, true, fn.filename); }; Evaluator.prototype.invokeBuiltin = function(fn, args) { if (fn.raw) { args = args.nodes; } else { args = utils.params(fn).reduce(function(ret, param) { var arg = args.map[param] || args.nodes.shift(); if (arg) { arg = utils.unwrap(arg); var len = arg.nodes.length; if (len > 1) { for (var i = 0; i < len; ++i) { ret.push(utils.unwrap(arg.nodes[i].first)); } } else { ret.push(arg.first); } } return ret; }, []); } var body = utils.coerce(fn.apply(this, args)); var expr = new nodes.Expression(); expr.push(body); body = expr; return this.invoke(body); }; Evaluator.prototype.invoke = function(body, stack, filename) { var self = this, ret; if (filename) this.paths.push(dirname(filename)); if (this.ret) { ret = this.eval(body.nodes); if (stack) this.stack.pop(); } else { body = this.visit(body); if (stack) this.stack.pop(); this.mixin(body.nodes, this.currentBlock); ret = nodes.nil; } if (filename) this.paths.pop(); return ret; }; Evaluator.prototype.mixin = function(nodes, block) { if (!nodes.length) return; var len = block.nodes.length, head = block.nodes.slice(0, block.index), tail = block.nodes.slice(block.index + 1, len); this._mixin(nodes, head, block); block.index = 0; block.nodes = head.concat(tail); }; Evaluator.prototype._mixin = function(items, dest, block) { var node, len = items.length; for (var i = 0; i < len; ++i) { switch ((node = items[i]).nodeName) { case 'return': return; case 'block': this._mixin(node.nodes, dest, block); break; case 'media': var parentNode = node.block.parent.node; if (parentNode && 'call' != parentNode.nodeName) { node.block.parent = block; } case 'property': var val = node.expr; if (node.literal && 'block' == val.first.name) { val = utils.unwrap(val); val.nodes[0] = new nodes.Literal('block'); } default: dest.push(node); } } }; Evaluator.prototype.mixinNode = function(node) { node = this.visit(node.first); switch (node.nodeName) { case 'object': this.mixinObject(node); return nodes.nil; case 'block': case 'atblock': this.mixin(node.nodes, this.currentBlock); return nodes.nil; } }; Evaluator.prototype.mixinObject = function(object) { var Parser = require('../parser'), root = this.root, str = '$block ' + object.toBlock(), parser = new Parser(str, utils.merge({ root: block }, this.options)), block; try { block = parser.parse(); } catch (err) { err.filename = this.filename; err.lineno = parser.lexer.lineno; err.column = parser.lexer.column; err.input = str; throw err; } block.parent = root; block.scope = false; var ret = this.visit(block), vals = ret.first.nodes; for (var i = 0, len = vals.length; i < len; ++i) { if (vals[i].block) { this.mixin(vals[i].block.nodes, this.currentBlock); break; } } }; Evaluator.prototype.eval = function(vals) { if (!vals) return nodes.nil; var len = vals.length, node = nodes.nil; try { for (var i = 0; i < len; ++i) { node = vals[i]; switch (node.nodeName) { case 'if': if ('block' != node.block.nodeName) { node = this.visit(node); break; } case 'each': case 'block': node = this.visit(node); if (node.nodes) node = this.eval(node.nodes); break; default: node = this.visit(node); } } } catch (err) { if ('return' == err.nodeName) { return err.expr; } else { throw err; } } return node; }; Evaluator.prototype.literalCall = function(call) { call.args = this.visit(call.args); return call; }; Evaluator.prototype.lookupProperty = function(name) { var i = this.stack.length, index = this.currentBlock.index, top = i, nodes, block, len, other; while (i--) { block = this.stack[i].block; if (!block.node) continue; switch (block.node.nodeName) { case 'group': case 'function': case 'if': case 'each': case 'atrule': case 'media': case 'atblock': case 'call': nodes = block.nodes; if (i + 1 == top) { while (index--) { if (this.property == nodes[index]) continue; other = this.interpolate(nodes[index]); if (name == other) return nodes[index].clone(); } } else { len = nodes.length; while (len--) { if ( 'property' != nodes[len].nodeName || this.property == nodes[len] ) continue; other = this.interpolate(nodes[len]); if (name == other) return nodes[len].clone(); } } break; } } return nodes.nil; }; Evaluator.prototype.__defineGetter__('closestBlock', function() { var i = this.stack.length, block; while (i--) { block = this.stack[i].block; if (block.node) { switch (block.node.nodeName) { case 'group': case 'keyframes': case 'atrule': case 'atblock': case 'media': case 'call': return block; } } } }); Evaluator.prototype.__defineGetter__('closestGroup', function() { var i = this.stack.length, block; while (i--) { block = this.stack[i].block; if (block.node && 'group' == block.node.nodeName) { return block; } } }); Evaluator.prototype.__defineGetter__('selectorStack', function() { var block, stack = []; for (var i = 0, len = this.stack.length; i < len; ++i) { block = this.stack[i].block; if (block.node && 'group' == block.node.nodeName) { block.node.nodes.forEach(function(selector) { if (!selector.val) selector.val = this.interpolate(selector); }, this); stack.push(block.node.nodes); } } return stack; }); Evaluator.prototype.lookup = function(name) { var val; if (this.ignoreColors && name in colors) return; if ((val = this.stack.lookup(name))) { return utils.unwrap(val); } else { return this.lookupFunction(name); } }; Evaluator.prototype.interpolate = function(node) { var self = this, isSelector = 'selector' == node.nodeName; function toString(node) { switch (node.nodeName) { case 'function': case 'ident': return node.name; case 'literal': case 'string': if (self.prefix && !node.prefixed && !node.val.nodeName) { node.val = node.val.replace(/\./g, '.' + self.prefix); node.prefixed = true; } return node.val; case 'unit': return '%' == node.type ? node.val + '%' : node.val; case 'member': return toString(self.visit(node)); case 'expression': if ( self.calling && ~self.calling.indexOf('selector') && self._selector ) return self._selector; self.ret++; var ret = toString(self.visit(node).first); self.ret--; if (isSelector) self._selector = ret; return ret; } } if (node.segments) { return node.segments.map(toString).join(''); } else { return toString(node); } }; Evaluator.prototype.lookupFunction = function(name) { var fn = this.functions[name] || bifs[name]; if (fn) return new nodes.Function(name, fn); }; Evaluator.prototype.isDefined = function(node) { if ('ident' == node.nodeName) { return nodes.Boolean(this.lookup(node.name)); } else { throw new Error('invalid "is defined" check on non-variable ' + node); } }; Evaluator.prototype.propertyExpression = function(prop, name) { var expr = new nodes.Expression(), val = prop.expr.clone(); expr.push(new nodes.String(prop.name)); function replace(node) { if ('call' == node.nodeName && name == node.name) { return new nodes.Literal('__CALL__'); } if (node.nodes) node.nodes = node.nodes.map(replace); return node; } replace(val); expr.push(val); return expr; }; Evaluator.prototype.cast = function(expr) { return new nodes.Unit(expr.first.val, expr.nodes[1].name); }; Evaluator.prototype.castable = function(expr) { return ( 2 == expr.nodes.length && 'unit' == expr.first.nodeName && ~units.indexOf(expr.nodes[1].name) ); }; Evaluator.prototype.warn = function(msg) { if (!this.warnings) return; console.warn('Warning: ' + msg); }; Evaluator.prototype.__defineGetter__('currentBlock', function() { return this.stack.currentFrame.block; }); Evaluator.prototype.__defineGetter__('vendors', function() { return this.lookup('vendors').nodes.map(function(node) { return node.string; }); }); Evaluator.prototype.unvendorize = function(prop) { for (var i = 0, len = this.vendors.length; i < len; i++) { if ('official' != this.vendors[i]) { var vendor = '-' + this.vendors[i] + '-'; if (~prop.indexOf(vendor)) return prop.replace(vendor, ''); } } return prop; }; Evaluator.prototype.__defineGetter__('currentScope', function() { return this.stack.currentFrame.scope; }); Evaluator.prototype.__defineGetter__('currentFrame', function() { return this.stack.currentFrame; }); }); require.register('visitor/normalizer.js', function(module, exports, require) { var Visitor = require('./index'), nodes = require('../nodes/index'), utils = require('../utils'); var Normalizer = (module.exports = function Normalizer(root, options) { options = options || {}; Visitor.call(this, root); this.hoist = options['hoist atrules']; this.stack = []; this.map = {}; this.imports = []; }); Normalizer.prototype.__proto__ = Visitor.prototype; Normalizer.prototype.normalize = function() { var ret = this.visit(this.root); if (this.hoist) { if (this.imports.length) ret.nodes = this.imports.concat(ret.nodes); if (this.charset) ret.nodes = [this.charset].concat(ret.nodes); } return ret; }; Normalizer.prototype.bubble = function(node) { var props = [], other = [], self = this; function filterProps(block) { block.nodes.forEach(function(node) { node = self.visit(node); switch (node.nodeName) { case 'property': props.push(node); break; case 'block': filterProps(node); break; default: other.push(node); } }); } filterProps(node.block); if (props.length) { var selector = new nodes.Selector([new nodes.Literal('&')]); selector.lineno = node.lineno; selector.column = node.column; selector.filename = node.filename; selector.val = '&'; var group = new nodes.Group(); group.lineno = node.lineno; group.column = node.column; group.filename = node.filename; var block = new nodes.Block(node.block, group); block.lineno = node.lineno; block.column = node.column; block.filename = node.filename; props.forEach(function(prop) { block.push(prop); }); group.push(selector); group.block = block; node.block.nodes = []; node.block.push(group); other.forEach(function(n) { node.block.push(n); }); var group = this.closestGroup(node.block); if (group) node.group = group.clone(); node.bubbled = true; } }; Normalizer.prototype.closestGroup = function(block) { var parent = block.parent, node; while (parent && (node = parent.node)) { if ('group' == node.nodeName) return node; parent = node.block && node.block.parent; } }; Normalizer.prototype.visitRoot = function(block) { var ret = new nodes.Root(), node; for (var i = 0; i < block.nodes.length; ++i) { node = block.nodes[i]; switch (node.nodeName) { case 'null': case 'expression': case 'function': case 'unit': case 'atblock': continue; default: this.rootIndex = i; ret.push(this.visit(node)); } } return ret; }; Normalizer.prototype.visitProperty = function(prop) { this.visit(prop.expr); return prop; }; Normalizer.prototype.visitExpression = function(expr) { expr.nodes = expr.nodes.map(function(node) { if ('block' == node.nodeName) { var literal = new nodes.Literal('block'); literal.lineno = expr.lineno; literal.column = expr.column; return literal; } return node; }); return expr; }; Normalizer.prototype.visitBlock = function(block) { var node; if (block.hasProperties) { for (var i = 0, len = block.nodes.length; i < len; ++i) { node = block.nodes[i]; switch (node.nodeName) { case 'null': case 'expression': case 'function': case 'group': case 'unit': case 'atblock': continue; default: block.nodes[i] = this.visit(node); } } } for (var i = 0, len = block.nodes.length; i < len; ++i) { node = block.nodes[i]; block.nodes[i] = this.visit(node); } return block; }; Normalizer.prototype.visitGroup = function(group) { var stack = this.stack, map = this.map, parts; group.nodes.forEach(function(selector, i) { if (!~selector.val.indexOf(',')) return; if (~selector.val.indexOf('\\,')) { selector.val = selector.val.replace(/\\,/g, ','); return; } parts = selector.val.split(','); var root = '/' == selector.val.charAt(0), part, s; for (var k = 0, len = parts.length; k < len; ++k) { part = parts[k].trim(); if (root && k > 0 && !~part.indexOf('&')) { part = '/' + part; } s = new nodes.Selector([new nodes.Literal(part)]); s.val = part; s.block = group.block; group.nodes[i++] = s; } }); stack.push(group.nodes); var selectors = utils.compileSelectors(stack, true); selectors.forEach(function(selector) { map[selector] = map[selector] || []; map[selector].push(group); }); this.extend(group, selectors); stack.pop(); return group; }; Normalizer.prototype.visitFunction = function() { return nodes.nil; }; Normalizer.prototype.visitMedia = function(media) { var medias = [], group = this.closestGroup(media.block), parent; function mergeQueries(block) { block.nodes.forEach(function(node, i) { switch (node.nodeName) { case 'media': node.val = media.val.merge(node.val); medias.push(node); block.nodes[i] = nodes.nil; break; case 'block': mergeQueries(node); break; default: if (node.block && node.block.nodes) mergeQueries(node.block); } }); } mergeQueries(media.block); this.bubble(media); if (medias.length) { medias.forEach(function(node) { if (group) { group.block.push(node); } else { this.root.nodes.splice(++this.rootIndex, 0, node); } node = this.visit(node); parent = node.block.parent; if (node.bubbled && (!group || 'group' == parent.node.nodeName)) { node.group.block = node.block.nodes[0].block; node.block.nodes[0] = node.group; } }, this); } return media; }; Normalizer.prototype.visitSupports = function(node) { this.bubble(node); return node; }; Normalizer.prototype.visitAtrule = function(node) { if (node.block) node.block = this.visit(node.block); return node; }; Normalizer.prototype.visitKeyframes = function(node) { var frames = node.block.nodes.filter(function(frame) { return frame.block && frame.block.hasProperties; }); node.frames = frames.length; return node; }; Normalizer.prototype.visitImport = function(node) { this.imports.push(node); return this.hoist ? nodes.nil : node; }; Normalizer.prototype.visitCharset = function(node) { this.charset = node; return this.hoist ? nodes.nil : node; }; Normalizer.prototype.extend = function(group, selectors) { var map = this.map, self = this, parent = this.closestGroup(group.block); group.extends.forEach(function(extend) { var groups = map[extend.selector]; if (!groups) { if (extend.optional) return; var err = new Error('Failed to @extend "' + extend.selector + '"'); err.lineno = extend.lineno; err.column = extend.column; throw err; } selectors.forEach(function(selector) { var node = new nodes.Selector(); node.val = selector; node.inherits = false; groups.forEach(function(group) { if (!parent || parent != group) self.extend(group, selectors); group.push(node); }); }); }); group.block = this.visit(group.block); }; }); return require('stylus'); })();