fix attribute
[roojs1] / buildSDK / less.js
1 /*!
2  * Less - Leaner CSS v2.7.3
3  * http://lesscss.org
4  *
5  * Copyright (c) 2009-2017, Alexis Sellier <self@cloudhead.net>
6  * Licensed under the Apache-2.0 License.
7  *
8  */
9
10  /** * @license Apache-2.0
11  */
12
13 (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.less = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
14 var addDataAttr = require("./utils").addDataAttr,
15     browser = require("./browser");
16
17 module.exports = function(window, options) {
18
19     // use options from the current script tag data attribues
20     addDataAttr(options, browser.currentScript(window));
21
22     if (options.isFileProtocol === undefined) {
23         options.isFileProtocol = /^(file|(chrome|safari)(-extension)?|resource|qrc|app):/.test(window.location.protocol);
24     }
25
26     // Load styles asynchronously (default: false)
27     //
28     // This is set to `false` by default, so that the body
29     // doesn't start loading before the stylesheets are parsed.
30     // Setting this to `true` can result in flickering.
31     //
32     options.async = options.async || false;
33     options.fileAsync = options.fileAsync || false;
34
35     // Interval between watch polls
36     options.poll = options.poll || (options.isFileProtocol ? 1000 : 1500);
37
38     options.env = options.env || (window.location.hostname == '127.0.0.1' ||
39         window.location.hostname == '0.0.0.0'   ||
40         window.location.hostname == 'localhost' ||
41         (window.location.port &&
42             window.location.port.length > 0)      ||
43         options.isFileProtocol                   ? 'development'
44         : 'production');
45
46     var dumpLineNumbers = /!dumpLineNumbers:(comments|mediaquery|all)/.exec(window.location.hash);
47     if (dumpLineNumbers) {
48         options.dumpLineNumbers = dumpLineNumbers[1];
49     }
50
51     if (options.useFileCache === undefined) {
52         options.useFileCache = true;
53     }
54
55     if (options.onReady === undefined) {
56         options.onReady = true;
57     }
58
59 };
60
61 },{"./browser":3,"./utils":10}],2:[function(require,module,exports){
62 /**
63  * Kicks off less and compiles any stylesheets
64  * used in the browser distributed version of less
65  * to kick-start less using the browser api
66  */
67 /*global window, document */
68
69 // shim Promise if required
70 require('promise/polyfill.js');
71
72 var options = window.less || {};
73 require("./add-default-options")(window, options);
74
75 var less = module.exports = require("./index")(window, options);
76
77 window.less = less;
78
79 var css, head, style;
80
81 // Always restore page visibility
82 function resolveOrReject(data) {
83     if (data.filename) {
84         console.warn(data);
85     }
86     if (!options.async) {
87         head.removeChild(style);
88     }
89 }
90
91 if (options.onReady) {
92     if (/!watch/.test(window.location.hash)) {
93         less.watch();
94     }
95     // Simulate synchronous stylesheet loading by blocking page rendering
96     if (!options.async) {
97         css = 'body { display: none !important }';
98         head = document.head || document.getElementsByTagName('head')[0];
99         style = document.createElement('style');
100
101         style.type = 'text/css';
102         if (style.styleSheet) {
103             style.styleSheet.cssText = css;
104         } else {
105             style.appendChild(document.createTextNode(css));
106         }
107
108         head.appendChild(style);
109     }
110     less.registerStylesheetsImmediately();
111     less.pageLoadFinished = less.refresh(less.env === 'development').then(resolveOrReject, resolveOrReject);
112 }
113
114 },{"./add-default-options":1,"./index":8,"promise/polyfill.js":97}],3:[function(require,module,exports){
115 var utils = require("./utils");
116 module.exports = {
117     createCSS: function (document, styles, sheet) {
118         // Strip the query-string
119         var href = sheet.href || '';
120
121         // If there is no title set, use the filename, minus the extension
122         var id = 'less:' + (sheet.title || utils.extractId(href));
123
124         // If this has already been inserted into the DOM, we may need to replace it
125         var oldStyleNode = document.getElementById(id);
126         var keepOldStyleNode = false;
127
128         // Create a new stylesheet node for insertion or (if necessary) replacement
129         var styleNode = document.createElement('style');
130         styleNode.setAttribute('type', 'text/css');
131         if (sheet.media) {
132             styleNode.setAttribute('media', sheet.media);
133         }
134         styleNode.id = id;
135
136         if (!styleNode.styleSheet) {
137             styleNode.appendChild(document.createTextNode(styles));
138
139             // If new contents match contents of oldStyleNode, don't replace oldStyleNode
140             keepOldStyleNode = (oldStyleNode !== null && oldStyleNode.childNodes.length > 0 && styleNode.childNodes.length > 0 &&
141                 oldStyleNode.firstChild.nodeValue === styleNode.firstChild.nodeValue);
142         }
143
144         var head = document.getElementsByTagName('head')[0];
145
146         // If there is no oldStyleNode, just append; otherwise, only append if we need
147         // to replace oldStyleNode with an updated stylesheet
148         if (oldStyleNode === null || keepOldStyleNode === false) {
149             var nextEl = sheet && sheet.nextSibling || null;
150             if (nextEl) {
151                 nextEl.parentNode.insertBefore(styleNode, nextEl);
152             } else {
153                 head.appendChild(styleNode);
154             }
155         }
156         if (oldStyleNode && keepOldStyleNode === false) {
157             oldStyleNode.parentNode.removeChild(oldStyleNode);
158         }
159
160         // For IE.
161         // This needs to happen *after* the style element is added to the DOM, otherwise IE 7 and 8 may crash.
162         // See http://social.msdn.microsoft.com/Forums/en-US/7e081b65-878a-4c22-8e68-c10d39c2ed32/internet-explorer-crashes-appending-style-element-to-head
163         if (styleNode.styleSheet) {
164             try {
165                 styleNode.styleSheet.cssText = styles;
166             } catch (e) {
167                 throw new Error("Couldn't reassign styleSheet.cssText.");
168             }
169         }
170     },
171     currentScript: function(window) {
172         var document = window.document;
173         return document.currentScript || (function() {
174             var scripts = document.getElementsByTagName("script");
175             return scripts[scripts.length - 1];
176         })();
177     }
178 };
179
180 },{"./utils":10}],4:[function(require,module,exports){
181 // Cache system is a bit outdated and could do with work
182
183 module.exports = function(window, options, logger) {
184     var cache = null;
185     if (options.env !== 'development') {
186         try {
187             cache = (typeof window.localStorage === 'undefined') ? null : window.localStorage;
188         } catch (_) {}
189     }
190     return {
191         setCSS: function(path, lastModified, modifyVars, styles) {
192             if (cache) {
193                 logger.info('saving ' + path + ' to cache.');
194                 try {
195                     cache.setItem(path, styles);
196                     cache.setItem(path + ':timestamp', lastModified);
197                     if (modifyVars) {
198                         cache.setItem(path + ':vars', JSON.stringify(modifyVars));
199                     }
200                 } catch(e) {
201                     //TODO - could do with adding more robust error handling
202                     logger.error('failed to save "' + path + '" to local storage for caching.');
203                 }
204             }
205         },
206         getCSS: function(path, webInfo, modifyVars) {
207             var css       = cache && cache.getItem(path),
208                 timestamp = cache && cache.getItem(path + ':timestamp'),
209                 vars      = cache && cache.getItem(path + ':vars');
210
211             modifyVars = modifyVars || {};
212
213             if (timestamp && webInfo.lastModified &&
214                 (new Date(webInfo.lastModified).valueOf() ===
215                     new Date(timestamp).valueOf()) &&
216                 (!modifyVars && !vars || JSON.stringify(modifyVars) === vars)) {
217                 // Use local copy
218                 return css;
219             }
220         }
221     };
222 };
223
224 },{}],5:[function(require,module,exports){
225 var utils = require("./utils"),
226     browser = require("./browser");
227
228 module.exports = function(window, less, options) {
229
230     function errorHTML(e, rootHref) {
231         var id = 'less-error-message:' + utils.extractId(rootHref || "");
232         var template = '<li><label>{line}</label><pre class="{class}">{content}</pre></li>';
233         var elem = window.document.createElement('div'), timer, content, errors = [];
234         var filename = e.filename || rootHref;
235         var filenameNoPath = filename.match(/([^\/]+(\?.*)?)$/)[1];
236
237         elem.id        = id;
238         elem.className = "less-error-message";
239
240         content = '<h3>'  + (e.type || "Syntax") + "Error: " + (e.message || 'There is an error in your .less file') +
241             '</h3>' + '<p>in <a href="' + filename   + '">' + filenameNoPath + "</a> ";
242
243         var errorline = function (e, i, classname) {
244             if (e.extract[i] !== undefined) {
245                 errors.push(template.replace(/\{line\}/, (parseInt(e.line, 10) || 0) + (i - 1))
246                     .replace(/\{class\}/, classname)
247                     .replace(/\{content\}/, e.extract[i]));
248             }
249         };
250
251         if (e.extract) {
252             errorline(e, 0, '');
253             errorline(e, 1, 'line');
254             errorline(e, 2, '');
255             content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':</p>' +
256                 '<ul>' + errors.join('') + '</ul>';
257         }
258         if (e.stack && (e.extract || options.logLevel >= 4)) {
259             content += '<br/>Stack Trace</br />' + e.stack.split('\n').slice(1).join('<br/>');
260         }
261         elem.innerHTML = content;
262
263         // CSS for error messages
264         browser.createCSS(window.document, [
265             '.less-error-message ul, .less-error-message li {',
266             'list-style-type: none;',
267             'margin-right: 15px;',
268             'padding: 4px 0;',
269             'margin: 0;',
270             '}',
271             '.less-error-message label {',
272             'font-size: 12px;',
273             'margin-right: 15px;',
274             'padding: 4px 0;',
275             'color: #cc7777;',
276             '}',
277             '.less-error-message pre {',
278             'color: #dd6666;',
279             'padding: 4px 0;',
280             'margin: 0;',
281             'display: inline-block;',
282             '}',
283             '.less-error-message pre.line {',
284             'color: #ff0000;',
285             '}',
286             '.less-error-message h3 {',
287             'font-size: 20px;',
288             'font-weight: bold;',
289             'padding: 15px 0 5px 0;',
290             'margin: 0;',
291             '}',
292             '.less-error-message a {',
293             'color: #10a',
294             '}',
295             '.less-error-message .error {',
296             'color: red;',
297             'font-weight: bold;',
298             'padding-bottom: 2px;',
299             'border-bottom: 1px dashed red;',
300             '}'
301         ].join('\n'), { title: 'error-message' });
302
303         elem.style.cssText = [
304             "font-family: Arial, sans-serif",
305             "border: 1px solid #e00",
306             "background-color: #eee",
307             "border-radius: 5px",
308             "-webkit-border-radius: 5px",
309             "-moz-border-radius: 5px",
310             "color: #e00",
311             "padding: 15px",
312             "margin-bottom: 15px"
313         ].join(';');
314
315         if (options.env === 'development') {
316             timer = setInterval(function () {
317                 var document = window.document,
318                     body = document.body;
319                 if (body) {
320                     if (document.getElementById(id)) {
321                         body.replaceChild(elem, document.getElementById(id));
322                     } else {
323                         body.insertBefore(elem, body.firstChild);
324                     }
325                     clearInterval(timer);
326                 }
327             }, 10);
328         }
329     }
330
331     function removeErrorHTML(path) {
332         var node = window.document.getElementById('less-error-message:' + utils.extractId(path));
333         if (node) {
334             node.parentNode.removeChild(node);
335         }
336     }
337
338     function removeErrorConsole(path) {
339         //no action
340     }
341
342     function removeError(path) {
343         if (!options.errorReporting || options.errorReporting === "html") {
344             removeErrorHTML(path);
345         } else if (options.errorReporting === "console") {
346             removeErrorConsole(path);
347         } else if (typeof options.errorReporting === 'function') {
348             options.errorReporting("remove", path);
349         }
350     }
351
352     function errorConsole(e, rootHref) {
353         var template = '{line} {content}';
354         var filename = e.filename || rootHref;
355         var errors = [];
356         var content = (e.type || "Syntax") + "Error: " + (e.message || 'There is an error in your .less file') +
357             " in " + filename + " ";
358
359         var errorline = function (e, i, classname) {
360             if (e.extract[i] !== undefined) {
361                 errors.push(template.replace(/\{line\}/, (parseInt(e.line, 10) || 0) + (i - 1))
362                     .replace(/\{class\}/, classname)
363                     .replace(/\{content\}/, e.extract[i]));
364             }
365         };
366
367         if (e.extract) {
368             errorline(e, 0, '');
369             errorline(e, 1, 'line');
370             errorline(e, 2, '');
371             content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':\n' +
372                 errors.join('\n');
373         }
374         if (e.stack && (e.extract || options.logLevel >= 4)) {
375             content += '\nStack Trace\n' + e.stack;
376         }
377         less.logger.error(content);
378     }
379
380     function error(e, rootHref) {
381         if (!options.errorReporting || options.errorReporting === "html") {
382             errorHTML(e, rootHref);
383         } else if (options.errorReporting === "console") {
384             errorConsole(e, rootHref);
385         } else if (typeof options.errorReporting === 'function') {
386             options.errorReporting("add", e, rootHref);
387         }
388     }
389
390     return {
391         add: error,
392         remove: removeError
393     };
394 };
395
396 },{"./browser":3,"./utils":10}],6:[function(require,module,exports){
397 /*global window, XMLHttpRequest */
398
399 module.exports = function(options, logger) {
400
401     var AbstractFileManager = require("../less/environment/abstract-file-manager.js");
402
403     var fileCache = {};
404
405     //TODOS - move log somewhere. pathDiff and doing something similar in node. use pathDiff in the other browser file for the initial load
406
407     function getXMLHttpRequest() {
408         if (window.XMLHttpRequest && (window.location.protocol !== "file:" || !("ActiveXObject" in window))) {
409             return new XMLHttpRequest();
410         } else {
411             try {
412                 /*global ActiveXObject */
413                 return new ActiveXObject("Microsoft.XMLHTTP");
414             } catch (e) {
415                 logger.error("browser doesn't support AJAX.");
416                 return null;
417             }
418         }
419     }
420
421     var FileManager = function() {
422     };
423
424     FileManager.prototype = new AbstractFileManager();
425
426     FileManager.prototype.alwaysMakePathsAbsolute = function alwaysMakePathsAbsolute() {
427         return true;
428     };
429     FileManager.prototype.join = function join(basePath, laterPath) {
430         if (!basePath) {
431             return laterPath;
432         }
433         return this.extractUrlParts(laterPath, basePath).path;
434     };
435     FileManager.prototype.doXHR = function doXHR(url, type, callback, errback) {
436
437         var xhr = getXMLHttpRequest();
438         var async = options.isFileProtocol ? options.fileAsync : true;
439
440         if (typeof xhr.overrideMimeType === 'function') {
441             xhr.overrideMimeType('text/css');
442         }
443         logger.debug("XHR: Getting '" + url + "'");
444         xhr.open('GET', url, async);
445         xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5');
446         xhr.send(null);
447
448         function handleResponse(xhr, callback, errback) {
449             if (xhr.status >= 200 && xhr.status < 300) {
450                 callback(xhr.responseText,
451                     xhr.getResponseHeader("Last-Modified"));
452             } else if (typeof errback === 'function') {
453                 errback(xhr.status, url);
454             }
455         }
456
457         if (options.isFileProtocol && !options.fileAsync) {
458             if (xhr.status === 0 || (xhr.status >= 200 && xhr.status < 300)) {
459                 callback(xhr.responseText);
460             } else {
461                 errback(xhr.status, url);
462             }
463         } else if (async) {
464             xhr.onreadystatechange = function () {
465                 if (xhr.readyState == 4) {
466                     handleResponse(xhr, callback, errback);
467                 }
468             };
469         } else {
470             handleResponse(xhr, callback, errback);
471         }
472     };
473     FileManager.prototype.supports = function(filename, currentDirectory, options, environment) {
474         return true;
475     };
476
477     FileManager.prototype.clearFileCache = function() {
478         fileCache = {};
479     };
480
481     FileManager.prototype.loadFile = function loadFile(filename, currentDirectory, options, environment, callback) {
482         if (currentDirectory && !this.isPathAbsolute(filename)) {
483             filename = currentDirectory + filename;
484         }
485
486         options = options || {};
487
488         // sheet may be set to the stylesheet for the initial load or a collection of properties including
489         // some context variables for imports
490         var hrefParts = this.extractUrlParts(filename, window.location.href);
491         var href      = hrefParts.url;
492
493         if (options.useFileCache && fileCache[href]) {
494             try {
495                 var lessText = fileCache[href];
496                 callback(null, { contents: lessText, filename: href, webInfo: { lastModified: new Date() }});
497             } catch (e) {
498                 callback({filename: href, message: "Error loading file " + href + " error was " + e.message});
499             }
500             return;
501         }
502
503         this.doXHR(href, options.mime, function doXHRCallback(data, lastModified) {
504             // per file cache
505             fileCache[href] = data;
506
507             // Use remote copy (re-parse)
508             callback(null, { contents: data, filename: href, webInfo: { lastModified: lastModified }});
509         }, function doXHRError(status, url) {
510             callback({ type: 'File', message: "'" + url + "' wasn't found (" + status + ")", href: href });
511         });
512     };
513
514     return FileManager;
515 };
516
517 },{"../less/environment/abstract-file-manager.js":15}],7:[function(require,module,exports){
518 module.exports = function() {
519
520     var functionRegistry = require("./../less/functions/function-registry");
521
522     function imageSize() {
523         throw {
524             type: "Runtime",
525             message: "Image size functions are not supported in browser version of less"
526         };
527     }
528
529     var imageFunctions = {
530         "image-size": function(filePathNode) {
531             imageSize(this, filePathNode);
532             return -1;
533         },
534         "image-width": function(filePathNode) {
535             imageSize(this, filePathNode);
536             return -1;
537         },
538         "image-height": function(filePathNode) {
539             imageSize(this, filePathNode);
540             return -1;
541         }
542     };
543
544     functionRegistry.addMultiple(imageFunctions);
545 };
546
547 },{"./../less/functions/function-registry":22}],8:[function(require,module,exports){
548 //
549 // index.js
550 // Should expose the additional browser functions on to the less object
551 //
552 var addDataAttr = require("./utils").addDataAttr,
553     browser = require("./browser");
554
555 module.exports = function(window, options) {
556     var document = window.document;
557     var less = require('../less')();
558
559     //module.exports = less;
560     less.options = options;
561     var environment = less.environment,
562         FileManager = require("./file-manager")(options, less.logger),
563         fileManager = new FileManager();
564     environment.addFileManager(fileManager);
565     less.FileManager = FileManager;
566
567     require("./log-listener")(less, options);
568     var errors = require("./error-reporting")(window, less, options);
569     var cache = less.cache = options.cache || require("./cache")(window, options, less.logger);
570     require('./image-size')(less.environment);
571
572     //Setup user functions
573     if (options.functions) {
574         less.functions.functionRegistry.addMultiple(options.functions);
575     }
576
577     var typePattern = /^text\/(x-)?less$/;
578
579     function postProcessCSS(styles) { // deprecated, use a plugin for postprocesstasks
580         if (options.postProcessor && typeof options.postProcessor === 'function') {
581             styles = options.postProcessor.call(styles, styles) || styles;
582         }
583         return styles;
584     }
585
586     function clone(obj) {
587         var cloned = {};
588         for (var prop in obj) {
589             if (obj.hasOwnProperty(prop)) {
590                 cloned[prop] = obj[prop];
591             }
592         }
593         return cloned;
594     }
595
596     // only really needed for phantom
597     function bind(func, thisArg) {
598         var curryArgs = Array.prototype.slice.call(arguments, 2);
599         return function() {
600             var args = curryArgs.concat(Array.prototype.slice.call(arguments, 0));
601             return func.apply(thisArg, args);
602         };
603     }
604
605     function loadStyles(modifyVars) {
606         var styles = document.getElementsByTagName('style'),
607             style;
608
609         for (var i = 0; i < styles.length; i++) {
610             style = styles[i];
611             if (style.type.match(typePattern)) {
612                 var instanceOptions = clone(options);
613                 instanceOptions.modifyVars = modifyVars;
614                 var lessText = style.innerHTML || '';
615                 instanceOptions.filename = document.location.href.replace(/#.*$/, '');
616
617                 /*jshint loopfunc:true */
618                 // use closure to store current style
619                 less.render(lessText, instanceOptions,
620                         bind(function(style, e, result) {
621                             if (e) {
622                                 errors.add(e, "inline");
623                             } else {
624                                 style.type = 'text/css';
625                                 if (style.styleSheet) {
626                                     style.styleSheet.cssText = result.css;
627                                 } else {
628                                     style.innerHTML = result.css;
629                                 }
630                             }
631                         }, null, style));
632             }
633         }
634     }
635
636     function loadStyleSheet(sheet, callback, reload, remaining, modifyVars) {
637
638         var instanceOptions = clone(options);
639         addDataAttr(instanceOptions, sheet);
640         instanceOptions.mime = sheet.type;
641
642         if (modifyVars) {
643             instanceOptions.modifyVars = modifyVars;
644         }
645
646         function loadInitialFileCallback(loadedFile) {
647
648             var data = loadedFile.contents,
649                 path = loadedFile.filename,
650                 webInfo = loadedFile.webInfo;
651
652             var newFileInfo = {
653                 currentDirectory: fileManager.getPath(path),
654                 filename: path,
655                 rootFilename: path,
656                 relativeUrls: instanceOptions.relativeUrls};
657
658             newFileInfo.entryPath = newFileInfo.currentDirectory;
659             newFileInfo.rootpath = instanceOptions.rootpath || newFileInfo.currentDirectory;
660
661             if (webInfo) {
662                 webInfo.remaining = remaining;
663
664                 var css = cache.getCSS(path, webInfo, instanceOptions.modifyVars);
665                 if (!reload && css) {
666                     webInfo.local = true;
667                     callback(null, css, data, sheet, webInfo, path);
668                     return;
669                 }
670
671             }
672
673             //TODO add tests around how this behaves when reloading
674             errors.remove(path);
675
676             instanceOptions.rootFileInfo = newFileInfo;
677             less.render(data, instanceOptions, function(e, result) {
678                 if (e) {
679                     e.href = path;
680                     callback(e);
681                 } else {
682                     result.css = postProcessCSS(result.css);
683                     cache.setCSS(sheet.href, webInfo.lastModified, instanceOptions.modifyVars, result.css);
684                     callback(null, result.css, data, sheet, webInfo, path);
685                 }
686             });
687         }
688
689         fileManager.loadFile(sheet.href, null, instanceOptions, environment, function(e, loadedFile) {
690             if (e) {
691                 callback(e);
692                 return;
693             }
694             loadInitialFileCallback(loadedFile);
695         });
696     }
697
698     function loadStyleSheets(callback, reload, modifyVars) {
699         for (var i = 0; i < less.sheets.length; i++) {
700             loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1), modifyVars);
701         }
702     }
703
704     function initRunningMode() {
705         if (less.env === 'development') {
706             less.watchTimer = setInterval(function () {
707                 if (less.watchMode) {
708                     fileManager.clearFileCache();
709                     loadStyleSheets(function (e, css, _, sheet, webInfo) {
710                         if (e) {
711                             errors.add(e, e.href || sheet.href);
712                         } else if (css) {
713                             browser.createCSS(window.document, css, sheet);
714                         }
715                     });
716                 }
717             }, options.poll);
718         }
719     }
720
721     //
722     // Watch mode
723     //
724     less.watch   = function () {
725         if (!less.watchMode ) {
726             less.env = 'development';
727             initRunningMode();
728         }
729         this.watchMode = true;
730         return true;
731     };
732
733     less.unwatch = function () {clearInterval(less.watchTimer); this.watchMode = false; return false; };
734
735     //
736     // Synchronously get all <link> tags with the 'rel' attribute set to
737     // "stylesheet/less".
738     //
739     less.registerStylesheetsImmediately = function() {
740         var links = document.getElementsByTagName('link');
741         less.sheets = [];
742
743         for (var i = 0; i < links.length; i++) {
744             if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) &&
745                 (links[i].type.match(typePattern)))) {
746                 less.sheets.push(links[i]);
747             }
748         }
749     };
750
751     //
752     // Asynchronously get all <link> tags with the 'rel' attribute set to
753     // "stylesheet/less", returning a Promise.
754     //
755     less.registerStylesheets = function() {
756         return new Promise(function(resolve, reject) {
757             less.registerStylesheetsImmediately();
758             resolve();
759         });
760     };
761
762     //
763     // With this function, it's possible to alter variables and re-render
764     // CSS without reloading less-files
765     //
766     less.modifyVars = function(record) {
767         return less.refresh(true, record, false);
768     };
769
770     less.refresh = function (reload, modifyVars, clearFileCache) {
771         if ((reload || clearFileCache) && clearFileCache !== false) {
772             fileManager.clearFileCache();
773         }
774         return new Promise(function (resolve, reject) {
775             var startTime, endTime, totalMilliseconds, remainingSheets;
776             startTime = endTime = new Date();
777
778             // Set counter for remaining unprocessed sheets
779             remainingSheets = less.sheets.length;
780
781             if (remainingSheets === 0) {
782
783                 endTime = new Date();
784                 totalMilliseconds = endTime - startTime;
785                 less.logger.info("Less has finished and no sheets were loaded.");
786                 resolve({
787                     startTime: startTime,
788                     endTime: endTime,
789                     totalMilliseconds: totalMilliseconds,
790                     sheets: less.sheets.length
791                 });
792
793             } else {
794                 // Relies on less.sheets array, callback seems to be guaranteed to be called for every element of the array
795                 loadStyleSheets(function (e, css, _, sheet, webInfo) {
796                     if (e) {
797                         errors.add(e, e.href || sheet.href);
798                         reject(e);
799                         return;
800                     }
801                     if (webInfo.local) {
802                         less.logger.info("Loading " + sheet.href + " from cache.");
803                     } else {
804                         less.logger.info("Rendered " + sheet.href + " successfully.");
805                     }
806                     browser.createCSS(window.document, css, sheet);
807                     less.logger.info("CSS for " + sheet.href + " generated in " + (new Date() - endTime) + 'ms');
808
809                     // Count completed sheet
810                     remainingSheets--;
811
812                     // Check if the last remaining sheet was processed and then call the promise
813                     if (remainingSheets === 0) {
814                         totalMilliseconds = new Date() - startTime;
815                         less.logger.info("Less has finished. CSS generated in " + totalMilliseconds + 'ms');
816                         resolve({
817                             startTime: startTime,
818                             endTime: endTime,
819                             totalMilliseconds: totalMilliseconds,
820                             sheets: less.sheets.length
821                         });
822                     }
823                     endTime = new Date();
824                 }, reload, modifyVars);
825             }
826
827             loadStyles(modifyVars);
828         });
829     };
830
831     less.refreshStyles = loadStyles;
832     return less;
833 };
834
835 },{"../less":31,"./browser":3,"./cache":4,"./error-reporting":5,"./file-manager":6,"./image-size":7,"./log-listener":9,"./utils":10}],9:[function(require,module,exports){
836 module.exports = function(less, options) {
837
838     var logLevel_debug = 4,
839         logLevel_info = 3,
840         logLevel_warn = 2,
841         logLevel_error = 1;
842
843     // The amount of logging in the javascript console.
844     // 3 - Debug, information and errors
845     // 2 - Information and errors
846     // 1 - Errors
847     // 0 - None
848     // Defaults to 2
849     options.logLevel = typeof options.logLevel !== 'undefined' ? options.logLevel : (options.env === 'development' ?  logLevel_info : logLevel_error);
850
851     if (!options.loggers) {
852         options.loggers = [{
853             debug: function(msg) {
854                 if (options.logLevel >= logLevel_debug) {
855                     console.log(msg);
856                 }
857             },
858             info: function(msg) {
859                 if (options.logLevel >= logLevel_info) {
860                     console.log(msg);
861                 }
862             },
863             warn: function(msg) {
864                 if (options.logLevel >= logLevel_warn) {
865                     console.warn(msg);
866                 }
867             },
868             error: function(msg) {
869                 if (options.logLevel >= logLevel_error) {
870                     console.error(msg);
871                 }
872             }
873         }];
874     }
875     for (var i = 0; i < options.loggers.length; i++) {
876         less.logger.addListener(options.loggers[i]);
877     }
878 };
879
880 },{}],10:[function(require,module,exports){
881 module.exports = {
882     extractId: function(href) {
883         return href.replace(/^[a-z-]+:\/+?[^\/]+/, '')  // Remove protocol & domain
884             .replace(/[\?\&]livereload=\w+/, '')        // Remove LiveReload cachebuster
885             .replace(/^\//, '')                         // Remove root /
886             .replace(/\.[a-zA-Z]+$/, '')                // Remove simple extension
887             .replace(/[^\.\w-]+/g, '-')                 // Replace illegal characters
888             .replace(/\./g, ':');                       // Replace dots with colons(for valid id)
889     },
890     addDataAttr: function(options, tag) {
891         for (var opt in tag.dataset) {
892             if (tag.dataset.hasOwnProperty(opt)) {
893                 if (opt === "env" || opt === "dumpLineNumbers" || opt === "rootpath" || opt === "errorReporting") {
894                     options[opt] = tag.dataset[opt];
895                 } else {
896                     try {
897                         options[opt] = JSON.parse(tag.dataset[opt]);
898                     }
899                     catch(_) {}
900                 }
901             }
902         }
903     }
904 };
905
906 },{}],11:[function(require,module,exports){
907 var contexts = {};
908 module.exports = contexts;
909
910 var copyFromOriginal = function copyFromOriginal(original, destination, propertiesToCopy) {
911     if (!original) { return; }
912
913     for (var i = 0; i < propertiesToCopy.length; i++) {
914         if (original.hasOwnProperty(propertiesToCopy[i])) {
915             destination[propertiesToCopy[i]] = original[propertiesToCopy[i]];
916         }
917     }
918 };
919
920 /*
921  parse is used whilst parsing
922  */
923 var parseCopyProperties = [
924     // options
925     'paths',            // option - unmodified - paths to search for imports on
926     'relativeUrls',     // option - whether to adjust URL's to be relative
927     'rootpath',         // option - rootpath to append to URL's
928     'strictImports',    // option -
929     'insecure',         // option - whether to allow imports from insecure ssl hosts
930     'dumpLineNumbers',  // option - whether to dump line numbers
931     'compress',         // option - whether to compress
932     'syncImport',       // option - whether to import synchronously
933     'chunkInput',       // option - whether to chunk input. more performant but causes parse issues.
934     'mime',             // browser only - mime type for sheet import
935     'useFileCache',     // browser only - whether to use the per file session cache
936     // context
937     'processImports',   // option & context - whether to process imports. if false then imports will not be imported.
938                         // Used by the import manager to stop multiple import visitors being created.
939     'pluginManager'     // Used as the plugin manager for the session
940 ];
941
942 contexts.Parse = function(options) {
943     copyFromOriginal(options, this, parseCopyProperties);
944
945     if (typeof this.paths === "string") { this.paths = [this.paths]; }
946 };
947
948 var evalCopyProperties = [
949     'paths',          // additional include paths
950     'compress',       // whether to compress
951     'ieCompat',       // whether to enforce IE compatibility (IE8 data-uri)
952     'strictMath',     // whether math has to be within parenthesis
953     'strictUnits',    // whether units need to evaluate correctly
954     'sourceMap',      // whether to output a source map
955     'importMultiple', // whether we are currently importing multiple copies
956     'urlArgs',        // whether to add args into url tokens
957     'javascriptEnabled',// option - whether JavaScript is enabled. if undefined, defaults to true
958     'pluginManager',  // Used as the plugin manager for the session
959     'importantScope'  // used to bubble up !important statements
960     ];
961
962 contexts.Eval = function(options, frames) {
963     copyFromOriginal(options, this, evalCopyProperties);
964
965     if (typeof this.paths === "string") { this.paths = [this.paths]; }
966
967     this.frames = frames || [];
968     this.importantScope = this.importantScope || [];
969 };
970
971 contexts.Eval.prototype.inParenthesis = function () {
972     if (!this.parensStack) {
973         this.parensStack = [];
974     }
975     this.parensStack.push(true);
976 };
977
978 contexts.Eval.prototype.outOfParenthesis = function () {
979     this.parensStack.pop();
980 };
981
982 contexts.Eval.prototype.isMathOn = function () {
983     return this.strictMath ? (this.parensStack && this.parensStack.length) : true;
984 };
985
986 contexts.Eval.prototype.isPathRelative = function (path) {
987     return !/^(?:[a-z-]+:|\/|#)/i.test(path);
988 };
989
990 contexts.Eval.prototype.normalizePath = function( path ) {
991     var
992       segments = path.split("/").reverse(),
993       segment;
994
995     path = [];
996     while (segments.length !== 0 ) {
997         segment = segments.pop();
998         switch( segment ) {
999             case ".":
1000                 break;
1001             case "..":
1002                 if ((path.length === 0) || (path[path.length - 1] === "..")) {
1003                     path.push( segment );
1004                 } else {
1005                     path.pop();
1006                 }
1007                 break;
1008             default:
1009                 path.push( segment );
1010                 break;
1011         }
1012     }
1013
1014     return path.join("/");
1015 };
1016
1017 //todo - do the same for the toCSS ?
1018
1019 },{}],12:[function(require,module,exports){
1020 module.exports = {
1021     'aliceblue':'#f0f8ff',
1022     'antiquewhite':'#faebd7',
1023     'aqua':'#00ffff',
1024     'aquamarine':'#7fffd4',
1025     'azure':'#f0ffff',
1026     'beige':'#f5f5dc',
1027     'bisque':'#ffe4c4',
1028     'black':'#000000',
1029     'blanchedalmond':'#ffebcd',
1030     'blue':'#0000ff',
1031     'blueviolet':'#8a2be2',
1032     'brown':'#a52a2a',
1033     'burlywood':'#deb887',
1034     'cadetblue':'#5f9ea0',
1035     'chartreuse':'#7fff00',
1036     'chocolate':'#d2691e',
1037     'coral':'#ff7f50',
1038     'cornflowerblue':'#6495ed',
1039     'cornsilk':'#fff8dc',
1040     'crimson':'#dc143c',
1041     'cyan':'#00ffff',
1042     'darkblue':'#00008b',
1043     'darkcyan':'#008b8b',
1044     'darkgoldenrod':'#b8860b',
1045     'darkgray':'#a9a9a9',
1046     'darkgrey':'#a9a9a9',
1047     'darkgreen':'#006400',
1048     'darkkhaki':'#bdb76b',
1049     'darkmagenta':'#8b008b',
1050     'darkolivegreen':'#556b2f',
1051     'darkorange':'#ff8c00',
1052     'darkorchid':'#9932cc',
1053     'darkred':'#8b0000',
1054     'darksalmon':'#e9967a',
1055     'darkseagreen':'#8fbc8f',
1056     'darkslateblue':'#483d8b',
1057     'darkslategray':'#2f4f4f',
1058     'darkslategrey':'#2f4f4f',
1059     'darkturquoise':'#00ced1',
1060     'darkviolet':'#9400d3',
1061     'deeppink':'#ff1493',
1062     'deepskyblue':'#00bfff',
1063     'dimgray':'#696969',
1064     'dimgrey':'#696969',
1065     'dodgerblue':'#1e90ff',
1066     'firebrick':'#b22222',
1067     'floralwhite':'#fffaf0',
1068     'forestgreen':'#228b22',
1069     'fuchsia':'#ff00ff',
1070     'gainsboro':'#dcdcdc',
1071     'ghostwhite':'#f8f8ff',
1072     'gold':'#ffd700',
1073     'goldenrod':'#daa520',
1074     'gray':'#808080',
1075     'grey':'#808080',
1076     'green':'#008000',
1077     'greenyellow':'#adff2f',
1078     'honeydew':'#f0fff0',
1079     'hotpink':'#ff69b4',
1080     'indianred':'#cd5c5c',
1081     'indigo':'#4b0082',
1082     'ivory':'#fffff0',
1083     'khaki':'#f0e68c',
1084     'lavender':'#e6e6fa',
1085     'lavenderblush':'#fff0f5',
1086     'lawngreen':'#7cfc00',
1087     'lemonchiffon':'#fffacd',
1088     'lightblue':'#add8e6',
1089     'lightcoral':'#f08080',
1090     'lightcyan':'#e0ffff',
1091     'lightgoldenrodyellow':'#fafad2',
1092     'lightgray':'#d3d3d3',
1093     'lightgrey':'#d3d3d3',
1094     'lightgreen':'#90ee90',
1095     'lightpink':'#ffb6c1',
1096     'lightsalmon':'#ffa07a',
1097     'lightseagreen':'#20b2aa',
1098     'lightskyblue':'#87cefa',
1099     'lightslategray':'#778899',
1100     'lightslategrey':'#778899',
1101     'lightsteelblue':'#b0c4de',
1102     'lightyellow':'#ffffe0',
1103     'lime':'#00ff00',
1104     'limegreen':'#32cd32',
1105     'linen':'#faf0e6',
1106     'magenta':'#ff00ff',
1107     'maroon':'#800000',
1108     'mediumaquamarine':'#66cdaa',
1109     'mediumblue':'#0000cd',
1110     'mediumorchid':'#ba55d3',
1111     'mediumpurple':'#9370d8',
1112     'mediumseagreen':'#3cb371',
1113     'mediumslateblue':'#7b68ee',
1114     'mediumspringgreen':'#00fa9a',
1115     'mediumturquoise':'#48d1cc',
1116     'mediumvioletred':'#c71585',
1117     'midnightblue':'#191970',
1118     'mintcream':'#f5fffa',
1119     'mistyrose':'#ffe4e1',
1120     'moccasin':'#ffe4b5',
1121     'navajowhite':'#ffdead',
1122     'navy':'#000080',
1123     'oldlace':'#fdf5e6',
1124     'olive':'#808000',
1125     'olivedrab':'#6b8e23',
1126     'orange':'#ffa500',
1127     'orangered':'#ff4500',
1128     'orchid':'#da70d6',
1129     'palegoldenrod':'#eee8aa',
1130     'palegreen':'#98fb98',
1131     'paleturquoise':'#afeeee',
1132     'palevioletred':'#d87093',
1133     'papayawhip':'#ffefd5',
1134     'peachpuff':'#ffdab9',
1135     'peru':'#cd853f',
1136     'pink':'#ffc0cb',
1137     'plum':'#dda0dd',
1138     'powderblue':'#b0e0e6',
1139     'purple':'#800080',
1140     'rebeccapurple':'#663399',
1141     'red':'#ff0000',
1142     'rosybrown':'#bc8f8f',
1143     'royalblue':'#4169e1',
1144     'saddlebrown':'#8b4513',
1145     'salmon':'#fa8072',
1146     'sandybrown':'#f4a460',
1147     'seagreen':'#2e8b57',
1148     'seashell':'#fff5ee',
1149     'sienna':'#a0522d',
1150     'silver':'#c0c0c0',
1151     'skyblue':'#87ceeb',
1152     'slateblue':'#6a5acd',
1153     'slategray':'#708090',
1154     'slategrey':'#708090',
1155     'snow':'#fffafa',
1156     'springgreen':'#00ff7f',
1157     'steelblue':'#4682b4',
1158     'tan':'#d2b48c',
1159     'teal':'#008080',
1160     'thistle':'#d8bfd8',
1161     'tomato':'#ff6347',
1162     'turquoise':'#40e0d0',
1163     'violet':'#ee82ee',
1164     'wheat':'#f5deb3',
1165     'white':'#ffffff',
1166     'whitesmoke':'#f5f5f5',
1167     'yellow':'#ffff00',
1168     'yellowgreen':'#9acd32'
1169 };
1170 },{}],13:[function(require,module,exports){
1171 module.exports = {
1172     colors: require("./colors"),
1173     unitConversions: require("./unit-conversions")
1174 };
1175
1176 },{"./colors":12,"./unit-conversions":14}],14:[function(require,module,exports){
1177 module.exports = {
1178     length: {
1179         'm': 1,
1180         'cm': 0.01,
1181         'mm': 0.001,
1182         'in': 0.0254,
1183         'px': 0.0254 / 96,
1184         'pt': 0.0254 / 72,
1185         'pc': 0.0254 / 72 * 12
1186     },
1187     duration: {
1188         's': 1,
1189         'ms': 0.001
1190     },
1191     angle: {
1192         'rad': 1 / (2 * Math.PI),
1193         'deg': 1 / 360,
1194         'grad': 1 / 400,
1195         'turn': 1
1196     }
1197 };
1198 },{}],15:[function(require,module,exports){
1199 var abstractFileManager = function() {
1200 };
1201
1202 abstractFileManager.prototype.getPath = function (filename) {
1203     var j = filename.lastIndexOf('?');
1204     if (j > 0) {
1205         filename = filename.slice(0, j);
1206     }
1207     j = filename.lastIndexOf('/');
1208     if (j < 0) {
1209         j = filename.lastIndexOf('\\');
1210     }
1211     if (j < 0) {
1212         return "";
1213     }
1214     return filename.slice(0, j + 1);
1215 };
1216
1217 abstractFileManager.prototype.tryAppendExtension = function(path, ext) {
1218     return /(\.[a-z]*$)|([\?;].*)$/.test(path) ? path : path + ext;
1219 };
1220
1221 abstractFileManager.prototype.tryAppendLessExtension = function(path) {
1222     return this.tryAppendExtension(path, '.less');
1223 };
1224
1225 abstractFileManager.prototype.supportsSync = function() {
1226     return false;
1227 };
1228
1229 abstractFileManager.prototype.alwaysMakePathsAbsolute = function() {
1230     return false;
1231 };
1232
1233 abstractFileManager.prototype.isPathAbsolute = function(filename) {
1234     return (/^(?:[a-z-]+:|\/|\\|#)/i).test(filename);
1235 };
1236
1237 abstractFileManager.prototype.join = function(basePath, laterPath) {
1238     if (!basePath) {
1239         return laterPath;
1240     }
1241     return basePath + laterPath;
1242 };
1243 abstractFileManager.prototype.pathDiff = function pathDiff(url, baseUrl) {
1244     // diff between two paths to create a relative path
1245
1246     var urlParts = this.extractUrlParts(url),
1247         baseUrlParts = this.extractUrlParts(baseUrl),
1248         i, max, urlDirectories, baseUrlDirectories, diff = "";
1249     if (urlParts.hostPart !== baseUrlParts.hostPart) {
1250         return "";
1251     }
1252     max = Math.max(baseUrlParts.directories.length, urlParts.directories.length);
1253     for (i = 0; i < max; i++) {
1254         if (baseUrlParts.directories[i] !== urlParts.directories[i]) { break; }
1255     }
1256     baseUrlDirectories = baseUrlParts.directories.slice(i);
1257     urlDirectories = urlParts.directories.slice(i);
1258     for (i = 0; i < baseUrlDirectories.length - 1; i++) {
1259         diff += "../";
1260     }
1261     for (i = 0; i < urlDirectories.length - 1; i++) {
1262         diff += urlDirectories[i] + "/";
1263     }
1264     return diff;
1265 };
1266 // helper function, not part of API
1267 abstractFileManager.prototype.extractUrlParts = function extractUrlParts(url, baseUrl) {
1268     // urlParts[1] = protocol://hostname/ OR /
1269     // urlParts[2] = / if path relative to host base
1270     // urlParts[3] = directories
1271     // urlParts[4] = filename
1272     // urlParts[5] = parameters
1273
1274     var urlPartsRegex = /^((?:[a-z-]+:)?\/{2}(?:[^\/\?#]*\/)|([\/\\]))?((?:[^\/\\\?#]*[\/\\])*)([^\/\\\?#]*)([#\?].*)?$/i,
1275         urlParts = url.match(urlPartsRegex),
1276         returner = {}, directories = [], i, baseUrlParts;
1277
1278     if (!urlParts) {
1279         throw new Error("Could not parse sheet href - '" + url + "'");
1280     }
1281
1282     // Stylesheets in IE don't always return the full path
1283     if (baseUrl && (!urlParts[1] || urlParts[2])) {
1284         baseUrlParts = baseUrl.match(urlPartsRegex);
1285         if (!baseUrlParts) {
1286             throw new Error("Could not parse page url - '" + baseUrl + "'");
1287         }
1288         urlParts[1] = urlParts[1] || baseUrlParts[1] || "";
1289         if (!urlParts[2]) {
1290             urlParts[3] = baseUrlParts[3] + urlParts[3];
1291         }
1292     }
1293
1294     if (urlParts[3]) {
1295         directories = urlParts[3].replace(/\\/g, "/").split("/");
1296
1297         // extract out . before .. so .. doesn't absorb a non-directory
1298         for (i = 0; i < directories.length; i++) {
1299             if (directories[i] === ".") {
1300                 directories.splice(i, 1);
1301                 i -= 1;
1302             }
1303         }
1304
1305         for (i = 0; i < directories.length; i++) {
1306             if (directories[i] === ".." && i > 0) {
1307                 directories.splice(i - 1, 2);
1308                 i -= 2;
1309             }
1310         }
1311     }
1312
1313     returner.hostPart = urlParts[1];
1314     returner.directories = directories;
1315     returner.path = (urlParts[1] || "") + directories.join("/");
1316     returner.fileUrl = returner.path + (urlParts[4] || "");
1317     returner.url = returner.fileUrl + (urlParts[5] || "");
1318     return returner;
1319 };
1320
1321 module.exports = abstractFileManager;
1322
1323 },{}],16:[function(require,module,exports){
1324 var logger = require("../logger");
1325 var environment = function(externalEnvironment, fileManagers) {
1326     this.fileManagers = fileManagers || [];
1327     externalEnvironment = externalEnvironment || {};
1328
1329     var optionalFunctions = ["encodeBase64", "mimeLookup", "charsetLookup", "getSourceMapGenerator"],
1330         requiredFunctions = [],
1331         functions = requiredFunctions.concat(optionalFunctions);
1332
1333     for (var i = 0; i < functions.length; i++) {
1334         var propName = functions[i],
1335             environmentFunc = externalEnvironment[propName];
1336         if (environmentFunc) {
1337             this[propName] = environmentFunc.bind(externalEnvironment);
1338         } else if (i < requiredFunctions.length) {
1339             this.warn("missing required function in environment - " + propName);
1340         }
1341     }
1342 };
1343
1344 environment.prototype.getFileManager = function (filename, currentDirectory, options, environment, isSync) {
1345
1346     if (!filename) {
1347         logger.warn("getFileManager called with no filename.. Please report this issue. continuing.");
1348     }
1349     if (currentDirectory == null) {
1350         logger.warn("getFileManager called with null directory.. Please report this issue. continuing.");
1351     }
1352
1353     var fileManagers = this.fileManagers;
1354     if (options.pluginManager) {
1355         fileManagers = [].concat(fileManagers).concat(options.pluginManager.getFileManagers());
1356     }
1357     for (var i = fileManagers.length - 1; i >= 0 ; i--) {
1358         var fileManager = fileManagers[i];
1359         if (fileManager[isSync ? "supportsSync" : "supports"](filename, currentDirectory, options, environment)) {
1360             return fileManager;
1361         }
1362     }
1363     return null;
1364 };
1365
1366 environment.prototype.addFileManager = function (fileManager) {
1367     this.fileManagers.push(fileManager);
1368 };
1369
1370 environment.prototype.clearFileManagers = function () {
1371     this.fileManagers = [];
1372 };
1373
1374 module.exports = environment;
1375
1376 },{"../logger":33}],17:[function(require,module,exports){
1377 var Color = require("../tree/color"),
1378     functionRegistry = require("./function-registry");
1379
1380 // Color Blending
1381 // ref: http://www.w3.org/TR/compositing-1
1382
1383 function colorBlend(mode, color1, color2) {
1384     var ab = color1.alpha, cb, // backdrop
1385         as = color2.alpha, cs, // source
1386         ar, cr, r = [];        // result
1387
1388     ar = as + ab * (1 - as);
1389     for (var i = 0; i < 3; i++) {
1390         cb = color1.rgb[i] / 255;
1391         cs = color2.rgb[i] / 255;
1392         cr = mode(cb, cs);
1393         if (ar) {
1394             cr = (as * cs + ab * (cb -
1395                   as * (cb + cs - cr))) / ar;
1396         }
1397         r[i] = cr * 255;
1398     }
1399
1400     return new Color(r, ar);
1401 }
1402
1403 var colorBlendModeFunctions = {
1404     multiply: function(cb, cs) {
1405         return cb * cs;
1406     },
1407     screen: function(cb, cs) {
1408         return cb + cs - cb * cs;
1409     },
1410     overlay: function(cb, cs) {
1411         cb *= 2;
1412         return (cb <= 1) ?
1413             colorBlendModeFunctions.multiply(cb, cs) :
1414             colorBlendModeFunctions.screen(cb - 1, cs);
1415     },
1416     softlight: function(cb, cs) {
1417         var d = 1, e = cb;
1418         if (cs > 0.5) {
1419             e = 1;
1420             d = (cb > 0.25) ? Math.sqrt(cb)
1421                 : ((16 * cb - 12) * cb + 4) * cb;
1422         }
1423         return cb - (1 - 2 * cs) * e * (d - cb);
1424     },
1425     hardlight: function(cb, cs) {
1426         return colorBlendModeFunctions.overlay(cs, cb);
1427     },
1428     difference: function(cb, cs) {
1429         return Math.abs(cb - cs);
1430     },
1431     exclusion: function(cb, cs) {
1432         return cb + cs - 2 * cb * cs;
1433     },
1434
1435     // non-w3c functions:
1436     average: function(cb, cs) {
1437         return (cb + cs) / 2;
1438     },
1439     negation: function(cb, cs) {
1440         return 1 - Math.abs(cb + cs - 1);
1441     }
1442 };
1443
1444 for (var f in colorBlendModeFunctions) {
1445     if (colorBlendModeFunctions.hasOwnProperty(f)) {
1446         colorBlend[f] = colorBlend.bind(null, colorBlendModeFunctions[f]);
1447     }
1448 }
1449
1450 functionRegistry.addMultiple(colorBlend);
1451
1452 },{"../tree/color":50,"./function-registry":22}],18:[function(require,module,exports){
1453 var Dimension = require("../tree/dimension"),
1454     Color = require("../tree/color"),
1455     Quoted = require("../tree/quoted"),
1456     Anonymous = require("../tree/anonymous"),
1457     functionRegistry = require("./function-registry"),
1458     colorFunctions;
1459
1460 function clamp(val) {
1461     return Math.min(1, Math.max(0, val));
1462 }
1463 function hsla(color) {
1464     return colorFunctions.hsla(color.h, color.s, color.l, color.a);
1465 }
1466 function number(n) {
1467     if (n instanceof Dimension) {
1468         return parseFloat(n.unit.is('%') ? n.value / 100 : n.value);
1469     } else if (typeof n === 'number') {
1470         return n;
1471     } else {
1472         throw {
1473             type: "Argument",
1474             message: "color functions take numbers as parameters"
1475         };
1476     }
1477 }
1478 function scaled(n, size) {
1479     if (n instanceof Dimension && n.unit.is('%')) {
1480         return parseFloat(n.value * size / 100);
1481     } else {
1482         return number(n);
1483     }
1484 }
1485 colorFunctions = {
1486     rgb: function (r, g, b) {
1487         return colorFunctions.rgba(r, g, b, 1.0);
1488     },
1489     rgba: function (r, g, b, a) {
1490         var rgb = [r, g, b].map(function (c) { return scaled(c, 255); });
1491         a = number(a);
1492         return new Color(rgb, a);
1493     },
1494     hsl: function (h, s, l) {
1495         return colorFunctions.hsla(h, s, l, 1.0);
1496     },
1497     hsla: function (h, s, l, a) {
1498
1499         var m1, m2;
1500
1501         function hue(h) {
1502             h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h);
1503             if (h * 6 < 1) {
1504                 return m1 + (m2 - m1) * h * 6;
1505             }
1506             else if (h * 2 < 1) {
1507                 return m2;
1508             }
1509             else if (h * 3 < 2) {
1510                 return m1 + (m2 - m1) * (2 / 3 - h) * 6;
1511             }
1512             else {
1513                 return m1;
1514             }
1515         }
1516
1517         h = (number(h) % 360) / 360;
1518         s = clamp(number(s)); l = clamp(number(l)); a = clamp(number(a));
1519
1520         m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s;
1521         m1 = l * 2 - m2;
1522
1523         return colorFunctions.rgba(hue(h + 1 / 3) * 255,
1524             hue(h)       * 255,
1525             hue(h - 1 / 3) * 255,
1526             a);
1527     },
1528
1529     hsv: function(h, s, v) {
1530         return colorFunctions.hsva(h, s, v, 1.0);
1531     },
1532
1533     hsva: function(h, s, v, a) {
1534         h = ((number(h) % 360) / 360) * 360;
1535         s = number(s); v = number(v); a = number(a);
1536
1537         var i, f;
1538         i = Math.floor((h / 60) % 6);
1539         f = (h / 60) - i;
1540
1541         var vs = [v,
1542             v * (1 - s),
1543             v * (1 - f * s),
1544             v * (1 - (1 - f) * s)];
1545         var perm = [[0, 3, 1],
1546             [2, 0, 1],
1547             [1, 0, 3],
1548             [1, 2, 0],
1549             [3, 1, 0],
1550             [0, 1, 2]];
1551
1552         return colorFunctions.rgba(vs[perm[i][0]] * 255,
1553             vs[perm[i][1]] * 255,
1554             vs[perm[i][2]] * 255,
1555             a);
1556     },
1557
1558     hue: function (color) {
1559         return new Dimension(color.toHSL().h);
1560     },
1561     saturation: function (color) {
1562         return new Dimension(color.toHSL().s * 100, '%');
1563     },
1564     lightness: function (color) {
1565         return new Dimension(color.toHSL().l * 100, '%');
1566     },
1567     hsvhue: function(color) {
1568         return new Dimension(color.toHSV().h);
1569     },
1570     hsvsaturation: function (color) {
1571         return new Dimension(color.toHSV().s * 100, '%');
1572     },
1573     hsvvalue: function (color) {
1574         return new Dimension(color.toHSV().v * 100, '%');
1575     },
1576     red: function (color) {
1577         return new Dimension(color.rgb[0]);
1578     },
1579     green: function (color) {
1580         return new Dimension(color.rgb[1]);
1581     },
1582     blue: function (color) {
1583         return new Dimension(color.rgb[2]);
1584     },
1585     alpha: function (color) {
1586         return new Dimension(color.toHSL().a);
1587     },
1588     luma: function (color) {
1589         return new Dimension(color.luma() * color.alpha * 100, '%');
1590     },
1591     luminance: function (color) {
1592         var luminance =
1593             (0.2126 * color.rgb[0] / 255) +
1594                 (0.7152 * color.rgb[1] / 255) +
1595                 (0.0722 * color.rgb[2] / 255);
1596
1597         return new Dimension(luminance * color.alpha * 100, '%');
1598     },
1599     saturate: function (color, amount, method) {
1600         // filter: saturate(3.2);
1601         // should be kept as is, so check for color
1602         if (!color.rgb) {
1603             return null;
1604         }
1605         var hsl = color.toHSL();
1606
1607         if (typeof method !== "undefined" && method.value === "relative") {
1608             hsl.s +=  hsl.s * amount.value / 100;
1609         }
1610         else {
1611             hsl.s += amount.value / 100;
1612         }
1613         hsl.s = clamp(hsl.s);
1614         return hsla(hsl);
1615     },
1616     desaturate: function (color, amount, method) {
1617         var hsl = color.toHSL();
1618
1619         if (typeof method !== "undefined" && method.value === "relative") {
1620             hsl.s -=  hsl.s * amount.value / 100;
1621         }
1622         else {
1623             hsl.s -= amount.value / 100;
1624         }
1625         hsl.s = clamp(hsl.s);
1626         return hsla(hsl);
1627     },
1628     lighten: function (color, amount, method) {
1629         var hsl = color.toHSL();
1630
1631         if (typeof method !== "undefined" && method.value === "relative") {
1632             hsl.l +=  hsl.l * amount.value / 100;
1633         }
1634         else {
1635             hsl.l += amount.value / 100;
1636         }
1637         hsl.l = clamp(hsl.l);
1638         return hsla(hsl);
1639     },
1640     darken: function (color, amount, method) {
1641         var hsl = color.toHSL();
1642
1643         if (typeof method !== "undefined" && method.value === "relative") {
1644             hsl.l -=  hsl.l * amount.value / 100;
1645         }
1646         else {
1647             hsl.l -= amount.value / 100;
1648         }
1649         hsl.l = clamp(hsl.l);
1650         return hsla(hsl);
1651     },
1652     fadein: function (color, amount, method) {
1653         var hsl = color.toHSL();
1654
1655         if (typeof method !== "undefined" && method.value === "relative") {
1656             hsl.a +=  hsl.a * amount.value / 100;
1657         }
1658         else {
1659             hsl.a += amount.value / 100;
1660         }
1661         hsl.a = clamp(hsl.a);
1662         return hsla(hsl);
1663     },
1664     fadeout: function (color, amount, method) {
1665         var hsl = color.toHSL();
1666
1667         if (typeof method !== "undefined" && method.value === "relative") {
1668             hsl.a -=  hsl.a * amount.value / 100;
1669         }
1670         else {
1671             hsl.a -= amount.value / 100;
1672         }
1673         hsl.a = clamp(hsl.a);
1674         return hsla(hsl);
1675     },
1676     fade: function (color, amount) {
1677         var hsl = color.toHSL();
1678
1679         hsl.a = amount.value / 100;
1680         hsl.a = clamp(hsl.a);
1681         return hsla(hsl);
1682     },
1683     spin: function (color, amount) {
1684         var hsl = color.toHSL();
1685         var hue = (hsl.h + amount.value) % 360;
1686
1687         hsl.h = hue < 0 ? 360 + hue : hue;
1688
1689         return hsla(hsl);
1690     },
1691     //
1692     // Copyright (c) 2006-2009 Hampton Catlin, Natalie Weizenbaum, and Chris Eppstein
1693     // http://sass-lang.com
1694     //
1695     mix: function (color1, color2, weight) {
1696         if (!color1.toHSL || !color2.toHSL) {
1697             console.log(color2.type);
1698             console.dir(color2);
1699         }
1700         if (!weight) {
1701             weight = new Dimension(50);
1702         }
1703         var p = weight.value / 100.0;
1704         var w = p * 2 - 1;
1705         var a = color1.toHSL().a - color2.toHSL().a;
1706
1707         var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0;
1708         var w2 = 1 - w1;
1709
1710         var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2,
1711             color1.rgb[1] * w1 + color2.rgb[1] * w2,
1712             color1.rgb[2] * w1 + color2.rgb[2] * w2];
1713
1714         var alpha = color1.alpha * p + color2.alpha * (1 - p);
1715
1716         return new Color(rgb, alpha);
1717     },
1718     greyscale: function (color) {
1719         return colorFunctions.desaturate(color, new Dimension(100));
1720     },
1721     contrast: function (color, dark, light, threshold) {
1722         // filter: contrast(3.2);
1723         // should be kept as is, so check for color
1724         if (!color.rgb) {
1725             return null;
1726         }
1727         if (typeof light === 'undefined') {
1728             light = colorFunctions.rgba(255, 255, 255, 1.0);
1729         }
1730         if (typeof dark === 'undefined') {
1731             dark = colorFunctions.rgba(0, 0, 0, 1.0);
1732         }
1733         //Figure out which is actually light and dark!
1734         if (dark.luma() > light.luma()) {
1735             var t = light;
1736             light = dark;
1737             dark = t;
1738         }
1739         if (typeof threshold === 'undefined') {
1740             threshold = 0.43;
1741         } else {
1742             threshold = number(threshold);
1743         }
1744         if (color.luma() < threshold) {
1745             return light;
1746         } else {
1747             return dark;
1748         }
1749     },
1750     argb: function (color) {
1751         return new Anonymous(color.toARGB());
1752     },
1753     color: function(c) {
1754         if ((c instanceof Quoted) &&
1755             (/^#([a-f0-9]{6}|[a-f0-9]{3})$/i.test(c.value))) {
1756             return new Color(c.value.slice(1));
1757         }
1758         if ((c instanceof Color) || (c = Color.fromKeyword(c.value))) {
1759             c.value = undefined;
1760             return c;
1761         }
1762         throw {
1763             type:    "Argument",
1764             message: "argument must be a color keyword or 3/6 digit hex e.g. #FFF"
1765         };
1766     },
1767     tint: function(color, amount) {
1768         return colorFunctions.mix(colorFunctions.rgb(255, 255, 255), color, amount);
1769     },
1770     shade: function(color, amount) {
1771         return colorFunctions.mix(colorFunctions.rgb(0, 0, 0), color, amount);
1772     }
1773 };
1774 functionRegistry.addMultiple(colorFunctions);
1775
1776 },{"../tree/anonymous":46,"../tree/color":50,"../tree/dimension":56,"../tree/quoted":73,"./function-registry":22}],19:[function(require,module,exports){
1777 module.exports = function(environment) {
1778     var Quoted = require("../tree/quoted"),
1779         URL = require("../tree/url"),
1780         functionRegistry = require("./function-registry"),
1781         fallback = function(functionThis, node) {
1782             return new URL(node, functionThis.index, functionThis.currentFileInfo).eval(functionThis.context);
1783         },
1784         logger = require('../logger');
1785
1786     functionRegistry.add("data-uri", function(mimetypeNode, filePathNode) {
1787
1788         if (!filePathNode) {
1789             filePathNode = mimetypeNode;
1790             mimetypeNode = null;
1791         }
1792
1793         var mimetype = mimetypeNode && mimetypeNode.value;
1794         var filePath = filePathNode.value;
1795         var currentFileInfo = this.currentFileInfo;
1796         var currentDirectory = currentFileInfo.relativeUrls ?
1797             currentFileInfo.currentDirectory : currentFileInfo.entryPath;
1798
1799         var fragmentStart = filePath.indexOf('#');
1800         var fragment = '';
1801         if (fragmentStart !== -1) {
1802             fragment = filePath.slice(fragmentStart);
1803             filePath = filePath.slice(0, fragmentStart);
1804         }
1805
1806         var fileManager = environment.getFileManager(filePath, currentDirectory, this.context, environment, true);
1807
1808         if (!fileManager) {
1809             return fallback(this, filePathNode);
1810         }
1811
1812         var useBase64 = false;
1813
1814         // detect the mimetype if not given
1815         if (!mimetypeNode) {
1816
1817             mimetype = environment.mimeLookup(filePath);
1818
1819             if (mimetype === "image/svg+xml") {
1820                 useBase64 = false;
1821             } else {
1822                 // use base 64 unless it's an ASCII or UTF-8 format
1823                 var charset = environment.charsetLookup(mimetype);
1824                 useBase64 = ['US-ASCII', 'UTF-8'].indexOf(charset) < 0;
1825             }
1826             if (useBase64) { mimetype += ';base64'; }
1827         }
1828         else {
1829             useBase64 = /;base64$/.test(mimetype);
1830         }
1831
1832         var fileSync = fileManager.loadFileSync(filePath, currentDirectory, this.context, environment);
1833         if (!fileSync.contents) {
1834             logger.warn("Skipped data-uri embedding of " + filePath + " because file not found");
1835             return fallback(this, filePathNode || mimetypeNode);
1836         }
1837         var buf = fileSync.contents;
1838         if (useBase64 && !environment.encodeBase64) {
1839             return fallback(this, filePathNode);
1840         }
1841
1842         buf = useBase64 ? environment.encodeBase64(buf) : encodeURIComponent(buf);
1843
1844         var uri = "data:" + mimetype + ',' + buf + fragment;
1845
1846         // IE8 cannot handle a data-uri larger than 32,768 characters. If this is exceeded
1847         // and the --ieCompat flag is enabled, return a normal url() instead.
1848         var DATA_URI_MAX = 32768;
1849         if (uri.length >= DATA_URI_MAX) {
1850
1851             if (this.context.ieCompat !== false) {
1852                 logger.warn("Skipped data-uri embedding of " + filePath + " because its size (" + uri.length +
1853                     " characters) exceeds IE8-safe " + DATA_URI_MAX + " characters!");
1854
1855                 return fallback(this, filePathNode || mimetypeNode);
1856             }
1857         }
1858
1859         return new URL(new Quoted('"' + uri + '"', uri, false, this.index, this.currentFileInfo), this.index, this.currentFileInfo);
1860     });
1861 };
1862
1863 },{"../logger":33,"../tree/quoted":73,"../tree/url":80,"./function-registry":22}],20:[function(require,module,exports){
1864 var Keyword = require("../tree/keyword"),
1865     functionRegistry = require("./function-registry");
1866
1867 var defaultFunc = {
1868     eval: function () {
1869         var v = this.value_, e = this.error_;
1870         if (e) {
1871             throw e;
1872         }
1873         if (v != null) {
1874             return v ? Keyword.True : Keyword.False;
1875         }
1876     },
1877     value: function (v) {
1878         this.value_ = v;
1879     },
1880     error: function (e) {
1881         this.error_ = e;
1882     },
1883     reset: function () {
1884         this.value_ = this.error_ = null;
1885     }
1886 };
1887
1888 functionRegistry.add("default", defaultFunc.eval.bind(defaultFunc));
1889
1890 module.exports = defaultFunc;
1891
1892 },{"../tree/keyword":65,"./function-registry":22}],21:[function(require,module,exports){
1893 var Expression = require("../tree/expression");
1894
1895 var functionCaller = function(name, context, index, currentFileInfo) {
1896     this.name = name.toLowerCase();
1897     this.index = index;
1898     this.context = context;
1899     this.currentFileInfo = currentFileInfo;
1900
1901     this.func = context.frames[0].functionRegistry.get(this.name);
1902 };
1903 functionCaller.prototype.isValid = function() {
1904     return Boolean(this.func);
1905 };
1906 functionCaller.prototype.call = function(args) {
1907
1908     // This code is terrible and should be replaced as per this issue...
1909     // https://github.com/less/less.js/issues/2477
1910     if (Array.isArray(args)) {
1911         args = args.filter(function (item) {
1912             if (item.type === "Comment") {
1913                 return false;
1914             }
1915             return true;
1916         })
1917         .map(function(item) {
1918             if (item.type === "Expression") {
1919                 var subNodes = item.value.filter(function (item) {
1920                     if (item.type === "Comment") {
1921                         return false;
1922                     }
1923                     return true;
1924                 });
1925                 if (subNodes.length === 1) {
1926                     return subNodes[0];
1927                 } else {
1928                     return new Expression(subNodes);
1929                 }
1930             }
1931             return item;
1932         });
1933     }
1934
1935     return this.func.apply(this, args);
1936 };
1937
1938 module.exports = functionCaller;
1939
1940 },{"../tree/expression":59}],22:[function(require,module,exports){
1941 function makeRegistry( base ) {
1942     return {
1943         _data: {},
1944         add: function(name, func) {
1945             // precautionary case conversion, as later querying of
1946             // the registry by function-caller uses lower case as well.
1947             name = name.toLowerCase();
1948
1949             if (this._data.hasOwnProperty(name)) {
1950                 //TODO warn
1951             }
1952             this._data[name] = func;
1953         },
1954         addMultiple: function(functions) {
1955             Object.keys(functions).forEach(
1956                 function(name) {
1957                     this.add(name, functions[name]);
1958                 }.bind(this));
1959         },
1960         get: function(name) {
1961             return this._data[name] || ( base && base.get( name ));
1962         },
1963         inherit : function() {
1964             return makeRegistry( this );
1965         }
1966     };
1967 }
1968
1969 module.exports = makeRegistry( null );
1970 },{}],23:[function(require,module,exports){
1971 module.exports = function(environment) {
1972     var functions = {
1973         functionRegistry: require("./function-registry"),
1974         functionCaller: require("./function-caller")
1975     };
1976
1977     //register functions
1978     require("./default");
1979     require("./color");
1980     require("./color-blending");
1981     require("./data-uri")(environment);
1982     require("./math");
1983     require("./number");
1984     require("./string");
1985     require("./svg")(environment);
1986     require("./types");
1987
1988     return functions;
1989 };
1990
1991 },{"./color":18,"./color-blending":17,"./data-uri":19,"./default":20,"./function-caller":21,"./function-registry":22,"./math":25,"./number":26,"./string":27,"./svg":28,"./types":29}],24:[function(require,module,exports){
1992 var Dimension = require("../tree/dimension");
1993
1994 var MathHelper = function() {
1995 };
1996 MathHelper._math = function (fn, unit, n) {
1997     if (!(n instanceof Dimension)) {
1998         throw { type: "Argument", message: "argument must be a number" };
1999     }
2000     if (unit == null) {
2001         unit = n.unit;
2002     } else {
2003         n = n.unify();
2004     }
2005     return new Dimension(fn(parseFloat(n.value)), unit);
2006 };
2007 module.exports = MathHelper;
2008 },{"../tree/dimension":56}],25:[function(require,module,exports){
2009 var functionRegistry = require("./function-registry"),
2010     mathHelper = require("./math-helper.js");
2011
2012 var mathFunctions = {
2013     // name,  unit
2014     ceil:  null,
2015     floor: null,
2016     sqrt:  null,
2017     abs:   null,
2018     tan:   "",
2019     sin:   "",
2020     cos:   "",
2021     atan:  "rad",
2022     asin:  "rad",
2023     acos:  "rad"
2024 };
2025
2026 for (var f in mathFunctions) {
2027     if (mathFunctions.hasOwnProperty(f)) {
2028         mathFunctions[f] = mathHelper._math.bind(null, Math[f], mathFunctions[f]);
2029     }
2030 }
2031
2032 mathFunctions.round = function (n, f) {
2033     var fraction = typeof f === "undefined" ? 0 : f.value;
2034     return mathHelper._math(function(num) { return num.toFixed(fraction); }, null, n);
2035 };
2036
2037 functionRegistry.addMultiple(mathFunctions);
2038
2039 },{"./function-registry":22,"./math-helper.js":24}],26:[function(require,module,exports){
2040 var Dimension = require("../tree/dimension"),
2041     Anonymous = require("../tree/anonymous"),
2042     functionRegistry = require("./function-registry"),
2043     mathHelper = require("./math-helper.js");
2044
2045 var minMax = function (isMin, args) {
2046     args = Array.prototype.slice.call(args);
2047     switch(args.length) {
2048         case 0: throw { type: "Argument", message: "one or more arguments required" };
2049     }
2050     var i, j, current, currentUnified, referenceUnified, unit, unitStatic, unitClone,
2051         order  = [], // elems only contains original argument values.
2052         values = {}; // key is the unit.toString() for unified Dimension values,
2053     // value is the index into the order array.
2054     for (i = 0; i < args.length; i++) {
2055         current = args[i];
2056         if (!(current instanceof Dimension)) {
2057             if (Array.isArray(args[i].value)) {
2058                 Array.prototype.push.apply(args, Array.prototype.slice.call(args[i].value));
2059             }
2060             continue;
2061         }
2062         currentUnified = current.unit.toString() === "" && unitClone !== undefined ? new Dimension(current.value, unitClone).unify() : current.unify();
2063         unit = currentUnified.unit.toString() === "" && unitStatic !== undefined ? unitStatic : currentUnified.unit.toString();
2064         unitStatic = unit !== "" && unitStatic === undefined || unit !== "" && order[0].unify().unit.toString() === "" ? unit : unitStatic;
2065         unitClone = unit !== "" && unitClone === undefined ? current.unit.toString() : unitClone;
2066         j = values[""] !== undefined && unit !== "" && unit === unitStatic ? values[""] : values[unit];
2067         if (j === undefined) {
2068             if (unitStatic !== undefined && unit !== unitStatic) {
2069                 throw{ type: "Argument", message: "incompatible types" };
2070             }
2071             values[unit] = order.length;
2072             order.push(current);
2073             continue;
2074         }
2075         referenceUnified = order[j].unit.toString() === "" && unitClone !== undefined ? new Dimension(order[j].value, unitClone).unify() : order[j].unify();
2076         if ( isMin && currentUnified.value < referenceUnified.value ||
2077             !isMin && currentUnified.value > referenceUnified.value) {
2078             order[j] = current;
2079         }
2080     }
2081     if (order.length == 1) {
2082         return order[0];
2083     }
2084     args = order.map(function (a) { return a.toCSS(this.context); }).join(this.context.compress ? "," : ", ");
2085     return new Anonymous((isMin ? "min" : "max") + "(" + args + ")");
2086 };
2087 functionRegistry.addMultiple({
2088     min: function () {
2089         return minMax(true, arguments);
2090     },
2091     max: function () {
2092         return minMax(false, arguments);
2093     },
2094     convert: function (val, unit) {
2095         return val.convertTo(unit.value);
2096     },
2097     pi: function () {
2098         return new Dimension(Math.PI);
2099     },
2100     mod: function(a, b) {
2101         return new Dimension(a.value % b.value, a.unit);
2102     },
2103     pow: function(x, y) {
2104         if (typeof x === "number" && typeof y === "number") {
2105             x = new Dimension(x);
2106             y = new Dimension(y);
2107         } else if (!(x instanceof Dimension) || !(y instanceof Dimension)) {
2108             throw { type: "Argument", message: "arguments must be numbers" };
2109         }
2110
2111         return new Dimension(Math.pow(x.value, y.value), x.unit);
2112     },
2113     percentage: function (n) {
2114         var result = mathHelper._math(function(num) {
2115             return num * 100;
2116         }, '%', n);
2117
2118         return result;
2119     }
2120 });
2121
2122 },{"../tree/anonymous":46,"../tree/dimension":56,"./function-registry":22,"./math-helper.js":24}],27:[function(require,module,exports){
2123 var Quoted = require("../tree/quoted"),
2124     Anonymous = require("../tree/anonymous"),
2125     JavaScript = require("../tree/javascript"),
2126     functionRegistry = require("./function-registry");
2127
2128 functionRegistry.addMultiple({
2129     e: function (str) {
2130         return new Anonymous(str instanceof JavaScript ? str.evaluated : str.value);
2131     },
2132     escape: function (str) {
2133         return new Anonymous(
2134             encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B")
2135                 .replace(/\(/g, "%28").replace(/\)/g, "%29"));
2136     },
2137     replace: function (string, pattern, replacement, flags) {
2138         var result = string.value;
2139         replacement = (replacement.type === "Quoted") ?
2140             replacement.value : replacement.toCSS();
2141         result = result.replace(new RegExp(pattern.value, flags ? flags.value : ''), replacement);
2142         return new Quoted(string.quote || '', result, string.escaped);
2143     },
2144     '%': function (string /* arg, arg, ...*/) {
2145         var args = Array.prototype.slice.call(arguments, 1),
2146             result = string.value;
2147
2148         for (var i = 0; i < args.length; i++) {
2149             /*jshint loopfunc:true */
2150             result = result.replace(/%[sda]/i, function(token) {
2151                 var value = ((args[i].type === "Quoted") &&
2152                     token.match(/s/i)) ? args[i].value : args[i].toCSS();
2153                 return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value;
2154             });
2155         }
2156         result = result.replace(/%%/g, '%');
2157         return new Quoted(string.quote || '', result, string.escaped);
2158     }
2159 });
2160
2161 },{"../tree/anonymous":46,"../tree/javascript":63,"../tree/quoted":73,"./function-registry":22}],28:[function(require,module,exports){
2162 module.exports = function(environment) {
2163     var Dimension = require("../tree/dimension"),
2164         Color = require("../tree/color"),
2165         Expression = require("../tree/expression"),
2166         Quoted = require("../tree/quoted"),
2167         URL = require("../tree/url"),
2168         functionRegistry = require("./function-registry");
2169
2170     functionRegistry.add("svg-gradient", function(direction) {
2171
2172         var stops,
2173             gradientDirectionSvg,
2174             gradientType = "linear",
2175             rectangleDimension = 'x="0" y="0" width="1" height="1"',
2176             renderEnv = {compress: false},
2177             returner,
2178             directionValue = direction.toCSS(renderEnv),
2179                         i, color, position, positionValue, alpha;
2180
2181         function throwArgumentDescriptor() {
2182             throw { type: "Argument",
2183                                         message: "svg-gradient expects direction, start_color [start_position], [color position,]...," +
2184                                                         " end_color [end_position] or direction, color list" };
2185         }
2186
2187         if (arguments.length == 2) {
2188             if (arguments[1].value.length < 2) {
2189                 throwArgumentDescriptor();
2190             }
2191             stops = arguments[1].value;
2192         } else if (arguments.length < 3) {
2193             throwArgumentDescriptor();
2194         } else {
2195             stops = Array.prototype.slice.call(arguments, 1);
2196         }
2197
2198         switch (directionValue) {
2199             case "to bottom":
2200                 gradientDirectionSvg = 'x1="0%" y1="0%" x2="0%" y2="100%"';
2201                 break;
2202             case "to right":
2203                 gradientDirectionSvg = 'x1="0%" y1="0%" x2="100%" y2="0%"';
2204                 break;
2205             case "to bottom right":
2206                 gradientDirectionSvg = 'x1="0%" y1="0%" x2="100%" y2="100%"';
2207                 break;
2208             case "to top right":
2209                 gradientDirectionSvg = 'x1="0%" y1="100%" x2="100%" y2="0%"';
2210                 break;
2211             case "ellipse":
2212             case "ellipse at center":
2213                 gradientType = "radial";
2214                 gradientDirectionSvg = 'cx="50%" cy="50%" r="75%"';
2215                 rectangleDimension = 'x="-50" y="-50" width="101" height="101"';
2216                 break;
2217             default:
2218                 throw { type: "Argument", message: "svg-gradient direction must be 'to bottom', 'to right'," +
2219                     " 'to bottom right', 'to top right' or 'ellipse at center'" };
2220         }
2221         returner = '<?xml version="1.0" ?>' +
2222             '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100%" height="100%" viewBox="0 0 1 1" preserveAspectRatio="none">' +
2223             '<' + gradientType + 'Gradient id="gradient" gradientUnits="userSpaceOnUse" ' + gradientDirectionSvg + '>';
2224
2225         for (i = 0; i < stops.length; i+= 1) {
2226             if (stops[i] instanceof Expression) {
2227                 color = stops[i].value[0];
2228                 position = stops[i].value[1];
2229             } else {
2230                 color = stops[i];
2231                 position = undefined;
2232             }
2233
2234             if (!(color instanceof Color) || (!((i === 0 || i + 1 === stops.length) && position === undefined) && !(position instanceof Dimension))) {
2235                 throwArgumentDescriptor();
2236             }
2237             positionValue = position ? position.toCSS(renderEnv) : i === 0 ? "0%" : "100%";
2238             alpha = color.alpha;
2239             returner += '<stop offset="' + positionValue + '" stop-color="' + color.toRGB() + '"' + (alpha < 1 ? ' stop-opacity="' + alpha + '"' : '') + '/>';
2240         }
2241         returner += '</' + gradientType + 'Gradient>' +
2242             '<rect ' + rectangleDimension + ' fill="url(#gradient)" /></svg>';
2243
2244         returner = encodeURIComponent(returner);
2245
2246         returner = "data:image/svg+xml," + returner;
2247         return new URL(new Quoted("'" + returner + "'", returner, false, this.index, this.currentFileInfo), this.index, this.currentFileInfo);
2248     });
2249 };
2250
2251 },{"../tree/color":50,"../tree/dimension":56,"../tree/expression":59,"../tree/quoted":73,"../tree/url":80,"./function-registry":22}],29:[function(require,module,exports){
2252 var Keyword = require("../tree/keyword"),
2253     DetachedRuleset = require("../tree/detached-ruleset"),
2254     Dimension = require("../tree/dimension"),
2255     Color = require("../tree/color"),
2256     Quoted = require("../tree/quoted"),
2257     Anonymous = require("../tree/anonymous"),
2258     URL = require("../tree/url"),
2259     Operation = require("../tree/operation"),
2260     functionRegistry = require("./function-registry");
2261
2262 var isa = function (n, Type) {
2263         return (n instanceof Type) ? Keyword.True : Keyword.False;
2264     },
2265     isunit = function (n, unit) {
2266         if (unit === undefined) {
2267             throw { type: "Argument", message: "missing the required second argument to isunit." };
2268         }
2269         unit = typeof unit.value === "string" ? unit.value : unit;
2270         if (typeof unit !== "string") {
2271             throw { type: "Argument", message: "Second argument to isunit should be a unit or a string." };
2272         }
2273         return (n instanceof Dimension) && n.unit.is(unit) ? Keyword.True : Keyword.False;
2274     },
2275     getItemsFromNode = function(node) {
2276         // handle non-array values as an array of length 1
2277         // return 'undefined' if index is invalid
2278         var items = Array.isArray(node.value) ?
2279             node.value : Array(node);
2280
2281         return items;
2282     };
2283 functionRegistry.addMultiple({
2284     isruleset: function (n) {
2285         return isa(n, DetachedRuleset);
2286     },
2287     iscolor: function (n) {
2288         return isa(n, Color);
2289     },
2290     isnumber: function (n) {
2291         return isa(n, Dimension);
2292     },
2293     isstring: function (n) {
2294         return isa(n, Quoted);
2295     },
2296     iskeyword: function (n) {
2297         return isa(n, Keyword);
2298     },
2299     isurl: function (n) {
2300         return isa(n, URL);
2301     },
2302     ispixel: function (n) {
2303         return isunit(n, 'px');
2304     },
2305     ispercentage: function (n) {
2306         return isunit(n, '%');
2307     },
2308     isem: function (n) {
2309         return isunit(n, 'em');
2310     },
2311     isunit: isunit,
2312     unit: function (val, unit) {
2313         if (!(val instanceof Dimension)) {
2314             throw { type: "Argument",
2315                 message: "the first argument to unit must be a number" +
2316                     (val instanceof Operation ? ". Have you forgotten parenthesis?" : "") };
2317         }
2318         if (unit) {
2319             if (unit instanceof Keyword) {
2320                 unit = unit.value;
2321             } else {
2322                 unit = unit.toCSS();
2323             }
2324         } else {
2325             unit = "";
2326         }
2327         return new Dimension(val.value, unit);
2328     },
2329     "get-unit": function (n) {
2330         return new Anonymous(n.unit);
2331     },
2332     extract: function(values, index) {
2333         index = index.value - 1; // (1-based index)
2334
2335         return getItemsFromNode(values)[index];
2336     },
2337     length: function(values) {
2338         return new Dimension(getItemsFromNode(values).length);
2339     }
2340 });
2341
2342 },{"../tree/anonymous":46,"../tree/color":50,"../tree/detached-ruleset":55,"../tree/dimension":56,"../tree/keyword":65,"../tree/operation":71,"../tree/quoted":73,"../tree/url":80,"./function-registry":22}],30:[function(require,module,exports){
2343 var contexts = require("./contexts"),
2344     Parser = require('./parser/parser'),
2345     FunctionImporter = require('./plugins/function-importer');
2346
2347 module.exports = function(environment) {
2348
2349     // FileInfo = {
2350     //  'relativeUrls' - option - whether to adjust URL's to be relative
2351     //  'filename' - full resolved filename of current file
2352     //  'rootpath' - path to append to normal URLs for this node
2353     //  'currentDirectory' - path to the current file, absolute
2354     //  'rootFilename' - filename of the base file
2355     //  'entryPath' - absolute path to the entry file
2356     //  'reference' - whether the file should not be output and only output parts that are referenced
2357
2358     var ImportManager = function(context, rootFileInfo) {
2359         this.rootFilename = rootFileInfo.filename;
2360         this.paths = context.paths || [];  // Search paths, when importing
2361         this.contents = {};             // map - filename to contents of all the files
2362         this.contentsIgnoredChars = {}; // map - filename to lines at the beginning of each file to ignore
2363         this.mime = context.mime;
2364         this.error = null;
2365         this.context = context;
2366         // Deprecated? Unused outside of here, could be useful.
2367         this.queue = [];        // Files which haven't been imported yet
2368         this.files = {};        // Holds the imported parse trees.
2369     };
2370     /**
2371      * Add an import to be imported
2372      * @param path - the raw path
2373      * @param tryAppendLessExtension - whether to try appending the less extension (if the path has no extension)
2374      * @param currentFileInfo - the current file info (used for instance to work out relative paths)
2375      * @param importOptions - import options
2376      * @param callback - callback for when it is imported
2377      */
2378     ImportManager.prototype.push = function (path, tryAppendLessExtension, currentFileInfo, importOptions, callback) {
2379         var importManager = this;
2380         this.queue.push(path);
2381
2382         var fileParsedFunc = function (e, root, fullPath) {
2383             importManager.queue.splice(importManager.queue.indexOf(path), 1); // Remove the path from the queue
2384
2385             var importedEqualsRoot = fullPath === importManager.rootFilename;
2386             if (importOptions.optional && e) {
2387                 callback(null, {rules:[]}, false, null);
2388             }
2389             else {
2390                 importManager.files[fullPath] = root;
2391                 if (e && !importManager.error) { importManager.error = e; }
2392                 callback(e, root, importedEqualsRoot, fullPath);
2393             }
2394         };
2395
2396         var newFileInfo = {
2397             relativeUrls: this.context.relativeUrls,
2398             entryPath: currentFileInfo.entryPath,
2399             rootpath: currentFileInfo.rootpath,
2400             rootFilename: currentFileInfo.rootFilename
2401         };
2402
2403         var fileManager = environment.getFileManager(path, currentFileInfo.currentDirectory, this.context, environment);
2404
2405         if (!fileManager) {
2406             fileParsedFunc({ message: "Could not find a file-manager for " + path });
2407             return;
2408         }
2409
2410         if (tryAppendLessExtension) {
2411             path = fileManager.tryAppendExtension(path, importOptions.plugin ? ".js" : ".less");
2412         }
2413
2414         var loadFileCallback = function(loadedFile) {
2415             var resolvedFilename = loadedFile.filename,
2416                 contents = loadedFile.contents.replace(/^\uFEFF/, '');
2417
2418             // Pass on an updated rootpath if path of imported file is relative and file
2419             // is in a (sub|sup) directory
2420             //
2421             // Examples:
2422             // - If path of imported file is 'module/nav/nav.less' and rootpath is 'less/',
2423             //   then rootpath should become 'less/module/nav/'
2424             // - If path of imported file is '../mixins.less' and rootpath is 'less/',
2425             //   then rootpath should become 'less/../'
2426             newFileInfo.currentDirectory = fileManager.getPath(resolvedFilename);
2427             if (newFileInfo.relativeUrls) {
2428                 newFileInfo.rootpath = fileManager.join(
2429                     (importManager.context.rootpath || ""),
2430                     fileManager.pathDiff(newFileInfo.currentDirectory, newFileInfo.entryPath));
2431
2432                 if (!fileManager.isPathAbsolute(newFileInfo.rootpath) && fileManager.alwaysMakePathsAbsolute()) {
2433                     newFileInfo.rootpath = fileManager.join(newFileInfo.entryPath, newFileInfo.rootpath);
2434                 }
2435             }
2436             newFileInfo.filename = resolvedFilename;
2437
2438             var newEnv = new contexts.Parse(importManager.context);
2439
2440             newEnv.processImports = false;
2441             importManager.contents[resolvedFilename] = contents;
2442
2443             if (currentFileInfo.reference || importOptions.reference) {
2444                 newFileInfo.reference = true;
2445             }
2446
2447             if (importOptions.plugin) {
2448                 new FunctionImporter(newEnv, newFileInfo).eval(contents, function (e, root) {
2449                     fileParsedFunc(e, root, resolvedFilename);
2450                 });
2451             } else if (importOptions.inline) {
2452                 fileParsedFunc(null, contents, resolvedFilename);
2453             } else {
2454                 new Parser(newEnv, importManager, newFileInfo).parse(contents, function (e, root) {
2455                     fileParsedFunc(e, root, resolvedFilename);
2456                 });
2457             }
2458         };
2459
2460         var promise = fileManager.loadFile(path, currentFileInfo.currentDirectory, this.context, environment,
2461             function(err, loadedFile) {
2462             if (err) {
2463                 fileParsedFunc(err);
2464             } else {
2465                 loadFileCallback(loadedFile);
2466             }
2467         });
2468         if (promise) {
2469             promise.then(loadFileCallback, fileParsedFunc);
2470         }
2471     };
2472     return ImportManager;
2473 };
2474
2475 },{"./contexts":11,"./parser/parser":38,"./plugins/function-importer":40}],31:[function(require,module,exports){
2476 module.exports = function(environment, fileManagers) {
2477     var SourceMapOutput, SourceMapBuilder, ParseTree, ImportManager, Environment;
2478
2479     var less = {
2480         version: [2, 7, 3],
2481         data: require('./data'),
2482         tree: require('./tree'),
2483         Environment: (Environment = require("./environment/environment")),
2484         AbstractFileManager: require("./environment/abstract-file-manager"),
2485         environment: (environment = new Environment(environment, fileManagers)),
2486         visitors: require('./visitors'),
2487         Parser: require('./parser/parser'),
2488         functions: require('./functions')(environment),
2489         contexts: require("./contexts"),
2490         SourceMapOutput: (SourceMapOutput = require('./source-map-output')(environment)),
2491         SourceMapBuilder: (SourceMapBuilder = require('./source-map-builder')(SourceMapOutput, environment)),
2492         ParseTree: (ParseTree = require('./parse-tree')(SourceMapBuilder)),
2493         ImportManager: (ImportManager = require('./import-manager')(environment)),
2494         render: require("./render")(environment, ParseTree, ImportManager),
2495         parse: require("./parse")(environment, ParseTree, ImportManager),
2496         LessError: require('./less-error'),
2497         transformTree: require('./transform-tree'),
2498         utils: require('./utils'),
2499         PluginManager: require('./plugin-manager'),
2500         logger: require('./logger')
2501     };
2502
2503     return less;
2504 };
2505
2506 },{"./contexts":11,"./data":13,"./environment/abstract-file-manager":15,"./environment/environment":16,"./functions":23,"./import-manager":30,"./less-error":32,"./logger":33,"./parse":35,"./parse-tree":34,"./parser/parser":38,"./plugin-manager":39,"./render":41,"./source-map-builder":42,"./source-map-output":43,"./transform-tree":44,"./tree":62,"./utils":83,"./visitors":87}],32:[function(require,module,exports){
2507 var utils = require("./utils");
2508
2509 var LessError = module.exports = function LessError(e, importManager, currentFilename) {
2510
2511     Error.call(this);
2512
2513     var filename = e.filename || currentFilename;
2514
2515     if (importManager && filename) {
2516         var input = importManager.contents[filename],
2517             loc = utils.getLocation(e.index, input),
2518             line = loc.line,
2519             col  = loc.column,
2520             callLine = e.call && utils.getLocation(e.call, input).line,
2521             lines = input.split('\n');
2522
2523         this.type = e.type || 'Syntax';
2524         this.filename = filename;
2525         this.index = e.index;
2526         this.line = typeof line === 'number' ? line + 1 : null;
2527         this.callLine = callLine + 1;
2528         this.callExtract = lines[callLine];
2529         this.column = col;
2530         this.extract = [
2531             lines[line - 1],
2532             lines[line],
2533             lines[line + 1]
2534         ];
2535     }
2536     this.message = e.message;
2537     this.stack = e.stack;
2538 };
2539
2540 if (typeof Object.create === 'undefined') {
2541     var F = function () {};
2542     F.prototype = Error.prototype;
2543     LessError.prototype = new F();
2544 } else {
2545     LessError.prototype = Object.create(Error.prototype);
2546 }
2547
2548 LessError.prototype.constructor = LessError;
2549
2550 },{"./utils":83}],33:[function(require,module,exports){
2551 module.exports = {
2552     error: function(msg) {
2553         this._fireEvent("error", msg);
2554     },
2555     warn: function(msg) {
2556         this._fireEvent("warn", msg);
2557     },
2558     info: function(msg) {
2559         this._fireEvent("info", msg);
2560     },
2561     debug: function(msg) {
2562         this._fireEvent("debug", msg);
2563     },
2564     addListener: function(listener) {
2565         this._listeners.push(listener);
2566     },
2567     removeListener: function(listener) {
2568         for (var i = 0; i < this._listeners.length; i++) {
2569             if (this._listeners[i] === listener) {
2570                 this._listeners.splice(i, 1);
2571                 return;
2572             }
2573         }
2574     },
2575     _fireEvent: function(type, msg) {
2576         for (var i = 0; i < this._listeners.length; i++) {
2577             var logFunction = this._listeners[i][type];
2578             if (logFunction) {
2579                 logFunction(msg);
2580             }
2581         }
2582     },
2583     _listeners: []
2584 };
2585
2586 },{}],34:[function(require,module,exports){
2587 var LessError = require('./less-error'),
2588     transformTree = require("./transform-tree"),
2589     logger = require("./logger");
2590
2591 module.exports = function(SourceMapBuilder) {
2592     var ParseTree = function(root, imports) {
2593         this.root = root;
2594         this.imports = imports;
2595     };
2596
2597     ParseTree.prototype.toCSS = function(options) {
2598         var evaldRoot, result = {}, sourceMapBuilder;
2599         try {
2600             evaldRoot = transformTree(this.root, options);
2601         } catch (e) {
2602             throw new LessError(e, this.imports);
2603         }
2604
2605         try {
2606             var compress = Boolean(options.compress);
2607             if (compress) {
2608                 logger.warn("The compress option has been deprecated. We recommend you use a dedicated css minifier, for instance see less-plugin-clean-css.");
2609             }
2610
2611             var toCSSOptions = {
2612                 compress: compress,
2613                 dumpLineNumbers: options.dumpLineNumbers,
2614                 strictUnits: Boolean(options.strictUnits),
2615                 numPrecision: 8};
2616
2617             if (options.sourceMap) {
2618                 sourceMapBuilder = new SourceMapBuilder(options.sourceMap);
2619                 result.css = sourceMapBuilder.toCSS(evaldRoot, toCSSOptions, this.imports);
2620             } else {
2621                 result.css = evaldRoot.toCSS(toCSSOptions);
2622             }
2623         } catch (e) {
2624             throw new LessError(e, this.imports);
2625         }
2626
2627         if (options.pluginManager) {
2628             var postProcessors = options.pluginManager.getPostProcessors();
2629             for (var i = 0; i < postProcessors.length; i++) {
2630                 result.css = postProcessors[i].process(result.css, { sourceMap: sourceMapBuilder, options: options, imports: this.imports });
2631             }
2632         }
2633         if (options.sourceMap) {
2634             result.map = sourceMapBuilder.getExternalSourceMap();
2635         }
2636
2637         result.imports = [];
2638         for (var file in this.imports.files) {
2639             if (this.imports.files.hasOwnProperty(file) && file !== this.imports.rootFilename) {
2640                 result.imports.push(file);
2641             }
2642         }
2643         return result;
2644     };
2645     return ParseTree;
2646 };
2647
2648 },{"./less-error":32,"./logger":33,"./transform-tree":44}],35:[function(require,module,exports){
2649 var PromiseConstructor,
2650     contexts = require("./contexts"),
2651     Parser = require('./parser/parser'),
2652     PluginManager = require('./plugin-manager');
2653
2654 module.exports = function(environment, ParseTree, ImportManager) {
2655     var parse = function (input, options, callback) {
2656         options = options || {};
2657
2658         if (typeof options === 'function') {
2659             callback = options;
2660             options = {};
2661         }
2662
2663         if (!callback) {
2664             if (!PromiseConstructor) {
2665                 PromiseConstructor = typeof Promise === 'undefined' ? require('promise') : Promise;
2666             }
2667             var self = this;
2668             return new PromiseConstructor(function (resolve, reject) {
2669                 parse.call(self, input, options, function(err, output) {
2670                     if (err) {
2671                         reject(err);
2672                     } else {
2673                         resolve(output);
2674                     }
2675                 });
2676             });
2677         } else {
2678             var context,
2679                 rootFileInfo,
2680                 pluginManager = new PluginManager(this);
2681
2682             pluginManager.addPlugins(options.plugins);
2683             options.pluginManager = pluginManager;
2684
2685             context = new contexts.Parse(options);
2686
2687             if (options.rootFileInfo) {
2688                 rootFileInfo = options.rootFileInfo;
2689             } else {
2690                 var filename = options.filename || "input";
2691                 var entryPath = filename.replace(/[^\/\\]*$/, "");
2692                 rootFileInfo = {
2693                     filename: filename,
2694                     relativeUrls: context.relativeUrls,
2695                     rootpath: context.rootpath || "",
2696                     currentDirectory: entryPath,
2697                     entryPath: entryPath,
2698                     rootFilename: filename
2699                 };
2700                 // add in a missing trailing slash
2701                 if (rootFileInfo.rootpath && rootFileInfo.rootpath.slice(-1) !== "/") {
2702                     rootFileInfo.rootpath += "/";
2703                 }
2704             }
2705
2706             var imports = new ImportManager(context, rootFileInfo);
2707
2708             new Parser(context, imports, rootFileInfo)
2709                 .parse(input, function (e, root) {
2710                 if (e) { return callback(e); }
2711                 callback(null, root, imports, options);
2712             }, options);
2713         }
2714     };
2715     return parse;
2716 };
2717
2718 },{"./contexts":11,"./parser/parser":38,"./plugin-manager":39,"promise":undefined}],36:[function(require,module,exports){
2719 // Split the input into chunks.
2720 module.exports = function (input, fail) {
2721     var len = input.length, level = 0, parenLevel = 0,
2722         lastOpening, lastOpeningParen, lastMultiComment, lastMultiCommentEndBrace,
2723         chunks = [], emitFrom = 0,
2724         chunkerCurrentIndex, currentChunkStartIndex, cc, cc2, matched;
2725
2726     function emitChunk(force) {
2727         var len = chunkerCurrentIndex - emitFrom;
2728         if (((len < 512) && !force) || !len) {
2729             return;
2730         }
2731         chunks.push(input.slice(emitFrom, chunkerCurrentIndex + 1));
2732         emitFrom = chunkerCurrentIndex + 1;
2733     }
2734
2735     for (chunkerCurrentIndex = 0; chunkerCurrentIndex < len; chunkerCurrentIndex++) {
2736         cc = input.charCodeAt(chunkerCurrentIndex);
2737         if (((cc >= 97) && (cc <= 122)) || (cc < 34)) {
2738             // a-z or whitespace
2739             continue;
2740         }
2741
2742         switch (cc) {
2743             case 40:                        // (
2744                 parenLevel++;
2745                 lastOpeningParen = chunkerCurrentIndex;
2746                 continue;
2747             case 41:                        // )
2748                 if (--parenLevel < 0) {
2749                     return fail("missing opening `(`", chunkerCurrentIndex);
2750                 }
2751                 continue;
2752             case 59:                        // ;
2753                 if (!parenLevel) { emitChunk(); }
2754                 continue;
2755             case 123:                       // {
2756                 level++;
2757                 lastOpening = chunkerCurrentIndex;
2758                 continue;
2759             case 125:                       // }
2760                 if (--level < 0) {
2761                     return fail("missing opening `{`", chunkerCurrentIndex);
2762                 }
2763                 if (!level && !parenLevel) { emitChunk(); }
2764                 continue;
2765             case 92:                        // \
2766                 if (chunkerCurrentIndex < len - 1) { chunkerCurrentIndex++; continue; }
2767                 return fail("unescaped `\\`", chunkerCurrentIndex);
2768             case 34:
2769             case 39:
2770             case 96:                        // ", ' and `
2771                 matched = 0;
2772                 currentChunkStartIndex = chunkerCurrentIndex;
2773                 for (chunkerCurrentIndex = chunkerCurrentIndex + 1; chunkerCurrentIndex < len; chunkerCurrentIndex++) {
2774                     cc2 = input.charCodeAt(chunkerCurrentIndex);
2775                     if (cc2 > 96) { continue; }
2776                     if (cc2 == cc) { matched = 1; break; }
2777                     if (cc2 == 92) {        // \
2778                         if (chunkerCurrentIndex == len - 1) {
2779                             return fail("unescaped `\\`", chunkerCurrentIndex);
2780                         }
2781                         chunkerCurrentIndex++;
2782                     }
2783                 }
2784                 if (matched) { continue; }
2785                 return fail("unmatched `" + String.fromCharCode(cc) + "`", currentChunkStartIndex);
2786             case 47:                        // /, check for comment
2787                 if (parenLevel || (chunkerCurrentIndex == len - 1)) { continue; }
2788                 cc2 = input.charCodeAt(chunkerCurrentIndex + 1);
2789                 if (cc2 == 47) {
2790                     // //, find lnfeed
2791                     for (chunkerCurrentIndex = chunkerCurrentIndex + 2; chunkerCurrentIndex < len; chunkerCurrentIndex++) {
2792                         cc2 = input.charCodeAt(chunkerCurrentIndex);
2793                         if ((cc2 <= 13) && ((cc2 == 10) || (cc2 == 13))) { break; }
2794                     }
2795                 } else if (cc2 == 42) {
2796                     // /*, find */
2797                     lastMultiComment = currentChunkStartIndex = chunkerCurrentIndex;
2798                     for (chunkerCurrentIndex = chunkerCurrentIndex + 2; chunkerCurrentIndex < len - 1; chunkerCurrentIndex++) {
2799                         cc2 = input.charCodeAt(chunkerCurrentIndex);
2800                         if (cc2 == 125) { lastMultiCommentEndBrace = chunkerCurrentIndex; }
2801                         if (cc2 != 42) { continue; }
2802                         if (input.charCodeAt(chunkerCurrentIndex + 1) == 47) { break; }
2803                     }
2804                     if (chunkerCurrentIndex == len - 1) {
2805                         return fail("missing closing `*/`", currentChunkStartIndex);
2806                     }
2807                     chunkerCurrentIndex++;
2808                 }
2809                 continue;
2810             case 42:                       // *, check for unmatched */
2811                 if ((chunkerCurrentIndex < len - 1) && (input.charCodeAt(chunkerCurrentIndex + 1) == 47)) {
2812                     return fail("unmatched `/*`", chunkerCurrentIndex);
2813                 }
2814                 continue;
2815         }
2816     }
2817
2818     if (level !== 0) {
2819         if ((lastMultiComment > lastOpening) && (lastMultiCommentEndBrace > lastMultiComment)) {
2820             return fail("missing closing `}` or `*/`", lastOpening);
2821         } else {
2822             return fail("missing closing `}`", lastOpening);
2823         }
2824     } else if (parenLevel !== 0) {
2825         return fail("missing closing `)`", lastOpeningParen);
2826     }
2827
2828     emitChunk(true);
2829     return chunks;
2830 };
2831
2832 },{}],37:[function(require,module,exports){
2833 var chunker = require('./chunker');
2834
2835 module.exports = function() {
2836     var input,       // LeSS input string
2837         j,           // current chunk
2838         saveStack = [],   // holds state for backtracking
2839         furthest,    // furthest index the parser has gone to
2840         furthestPossibleErrorMessage,// if this is furthest we got to, this is the probably cause
2841         chunks,      // chunkified input
2842         current,     // current chunk
2843         currentPos,  // index of current chunk, in `input`
2844         parserInput = {};
2845
2846     var CHARCODE_SPACE = 32,
2847         CHARCODE_TAB = 9,
2848         CHARCODE_LF = 10,
2849         CHARCODE_CR = 13,
2850         CHARCODE_PLUS = 43,
2851         CHARCODE_COMMA = 44,
2852         CHARCODE_FORWARD_SLASH = 47,
2853         CHARCODE_9 = 57;
2854
2855     function skipWhitespace(length) {
2856         var oldi = parserInput.i, oldj = j,
2857             curr = parserInput.i - currentPos,
2858             endIndex = parserInput.i + current.length - curr,
2859             mem = (parserInput.i += length),
2860             inp = input,
2861             c, nextChar, comment;
2862
2863         for (; parserInput.i < endIndex; parserInput.i++) {
2864             c = inp.charCodeAt(parserInput.i);
2865
2866             if (parserInput.autoCommentAbsorb && c === CHARCODE_FORWARD_SLASH) {
2867                 nextChar = inp.charAt(parserInput.i + 1);
2868                 if (nextChar === '/') {
2869                     comment = {index: parserInput.i, isLineComment: true};
2870                     var nextNewLine = inp.indexOf("\n", parserInput.i + 2);
2871                     if (nextNewLine < 0) {
2872                         nextNewLine = endIndex;
2873                     }
2874                     parserInput.i = nextNewLine;
2875                     comment.text = inp.substr(comment.index, parserInput.i - comment.index);
2876                     parserInput.commentStore.push(comment);
2877                     continue;
2878                 } else if (nextChar === '*') {
2879                     var nextStarSlash = inp.indexOf("*/", parserInput.i + 2);
2880                     if (nextStarSlash >= 0) {
2881                         comment = {
2882                             index: parserInput.i,
2883                             text: inp.substr(parserInput.i, nextStarSlash + 2 - parserInput.i),
2884                             isLineComment: false
2885                         };
2886                         parserInput.i += comment.text.length - 1;
2887                         parserInput.commentStore.push(comment);
2888                         continue;
2889                     }
2890                 }
2891                 break;
2892             }
2893
2894             if ((c !== CHARCODE_SPACE) && (c !== CHARCODE_LF) && (c !== CHARCODE_TAB) && (c !== CHARCODE_CR)) {
2895                 break;
2896             }
2897         }
2898
2899         current = current.slice(length + parserInput.i - mem + curr);
2900         currentPos = parserInput.i;
2901
2902         if (!current.length) {
2903             if (j < chunks.length - 1) {
2904                 current = chunks[++j];
2905                 skipWhitespace(0); // skip space at the beginning of a chunk
2906                 return true; // things changed
2907             }
2908             parserInput.finished = true;
2909         }
2910
2911         return oldi !== parserInput.i || oldj !== j;
2912     }
2913
2914     parserInput.save = function() {
2915         currentPos = parserInput.i;
2916         saveStack.push( { current: current, i: parserInput.i, j: j });
2917     };
2918     parserInput.restore = function(possibleErrorMessage) {
2919
2920         if (parserInput.i > furthest || (parserInput.i === furthest && possibleErrorMessage && !furthestPossibleErrorMessage)) {
2921             furthest = parserInput.i;
2922             furthestPossibleErrorMessage = possibleErrorMessage;
2923         }
2924         var state = saveStack.pop();
2925         current = state.current;
2926         currentPos = parserInput.i = state.i;
2927         j = state.j;
2928     };
2929     parserInput.forget = function() {
2930         saveStack.pop();
2931     };
2932     parserInput.isWhitespace = function (offset) {
2933         var pos = parserInput.i + (offset || 0),
2934             code = input.charCodeAt(pos);
2935         return (code === CHARCODE_SPACE || code === CHARCODE_CR || code === CHARCODE_TAB || code === CHARCODE_LF);
2936     };
2937
2938     // Specialization of $(tok)
2939     parserInput.$re = function(tok) {
2940         if (parserInput.i > currentPos) {
2941             current = current.slice(parserInput.i - currentPos);
2942             currentPos = parserInput.i;
2943         }
2944
2945         var m = tok.exec(current);
2946         if (!m) {
2947             return null;
2948         }
2949
2950         skipWhitespace(m[0].length);
2951         if (typeof m === "string") {
2952             return m;
2953         }
2954
2955         return m.length === 1 ? m[0] : m;
2956     };
2957
2958     parserInput.$char = function(tok) {
2959         if (input.charAt(parserInput.i) !== tok) {
2960             return null;
2961         }
2962         skipWhitespace(1);
2963         return tok;
2964     };
2965
2966     parserInput.$str = function(tok) {
2967         var tokLength = tok.length;
2968
2969         // https://jsperf.com/string-startswith/21
2970         for (var i = 0; i < tokLength; i++) {
2971             if (input.charAt(parserInput.i + i) !== tok.charAt(i)) {
2972                 return null;
2973             }
2974         }
2975
2976         skipWhitespace(tokLength);
2977         return tok;
2978     };
2979
2980     parserInput.$quoted = function() {
2981
2982         var startChar = input.charAt(parserInput.i);
2983         if (startChar !== "'" && startChar !== '"') {
2984             return;
2985         }
2986         var length = input.length,
2987             currentPosition = parserInput.i;
2988
2989         for (var i = 1; i + currentPosition < length; i++) {
2990             var nextChar = input.charAt(i + currentPosition);
2991             switch(nextChar) {
2992                 case "\\":
2993                     i++;
2994                     continue;
2995                 case "\r":
2996                 case "\n":
2997                     break;
2998                 case startChar:
2999                     var str = input.substr(currentPosition, i + 1);
3000                     skipWhitespace(i + 1);
3001                     return str;
3002                 default:
3003             }
3004         }
3005         return null;
3006     };
3007
3008     parserInput.autoCommentAbsorb = true;
3009     parserInput.commentStore = [];
3010     parserInput.finished = false;
3011
3012     // Same as $(), but don't change the state of the parser,
3013     // just return the match.
3014     parserInput.peek = function(tok) {
3015         if (typeof tok === 'string') {
3016             // https://jsperf.com/string-startswith/21
3017             for (var i = 0; i < tok.length; i++) {
3018                 if (input.charAt(parserInput.i + i) !== tok.charAt(i)) {
3019                     return false;
3020                 }
3021             }
3022             return true;
3023         } else {
3024             return tok.test(current);
3025         }
3026     };
3027
3028     // Specialization of peek()
3029     // TODO remove or change some currentChar calls to peekChar
3030     parserInput.peekChar = function(tok) {
3031         return input.charAt(parserInput.i) === tok;
3032     };
3033
3034     parserInput.currentChar = function() {
3035         return input.charAt(parserInput.i);
3036     };
3037
3038     parserInput.getInput = function() {
3039         return input;
3040     };
3041
3042     parserInput.peekNotNumeric = function() {
3043         var c = input.charCodeAt(parserInput.i);
3044         //Is the first char of the dimension 0-9, '.', '+' or '-'
3045         return (c > CHARCODE_9 || c < CHARCODE_PLUS) || c === CHARCODE_FORWARD_SLASH || c === CHARCODE_COMMA;
3046     };
3047
3048     parserInput.start = function(str, chunkInput, failFunction) {
3049         input = str;
3050         parserInput.i = j = currentPos = furthest = 0;
3051
3052         // chunking apparently makes things quicker (but my tests indicate
3053         // it might actually make things slower in node at least)
3054         // and it is a non-perfect parse - it can't recognise
3055         // unquoted urls, meaning it can't distinguish comments
3056         // meaning comments with quotes or {}() in them get 'counted'
3057         // and then lead to parse errors.
3058         // In addition if the chunking chunks in the wrong place we might
3059         // not be able to parse a parser statement in one go
3060         // this is officially deprecated but can be switched on via an option
3061         // in the case it causes too much performance issues.
3062         if (chunkInput) {
3063             chunks = chunker(str, failFunction);
3064         } else {
3065             chunks = [str];
3066         }
3067
3068         current = chunks[0];
3069
3070         skipWhitespace(0);
3071     };
3072
3073     parserInput.end = function() {
3074         var message,
3075             isFinished = parserInput.i >= input.length;
3076
3077         if (parserInput.i < furthest) {
3078             message = furthestPossibleErrorMessage;
3079             parserInput.i = furthest;
3080         }
3081         return {
3082             isFinished: isFinished,
3083             furthest: parserInput.i,
3084             furthestPossibleErrorMessage: message,
3085             furthestReachedEnd: parserInput.i >= input.length - 1,
3086             furthestChar: input[parserInput.i]
3087         };
3088     };
3089
3090     return parserInput;
3091 };
3092
3093 },{"./chunker":36}],38:[function(require,module,exports){
3094 var LessError = require('../less-error'),
3095     tree = require("../tree"),
3096     visitors = require("../visitors"),
3097     getParserInput = require("./parser-input"),
3098     utils = require("../utils");
3099
3100 //
3101 // less.js - parser
3102 //
3103 //    A relatively straight-forward predictive parser.
3104 //    There is no tokenization/lexing stage, the input is parsed
3105 //    in one sweep.
3106 //
3107 //    To make the parser fast enough to run in the browser, several
3108 //    optimization had to be made:
3109 //
3110 //    - Matching and slicing on a huge input is often cause of slowdowns.
3111 //      The solution is to chunkify the input into smaller strings.
3112 //      The chunks are stored in the `chunks` var,
3113 //      `j` holds the current chunk index, and `currentPos` holds
3114 //      the index of the current chunk in relation to `input`.
3115 //      This gives us an almost 4x speed-up.
3116 //
3117 //    - In many cases, we don't need to match individual tokens;
3118 //      for example, if a value doesn't hold any variables, operations
3119 //      or dynamic references, the parser can effectively 'skip' it,
3120 //      treating it as a literal.
3121 //      An example would be '1px solid #000' - which evaluates to itself,
3122 //      we don't need to know what the individual components are.
3123 //      The drawback, of course is that you don't get the benefits of
3124 //      syntax-checking on the CSS. This gives us a 50% speed-up in the parser,
3125 //      and a smaller speed-up in the code-gen.
3126 //
3127 //
3128 //    Token matching is done with the `$` function, which either takes
3129 //    a terminal string or regexp, or a non-terminal function to call.
3130 //    It also takes care of moving all the indices forwards.
3131 //`
3132 //
3133 var Parser = function Parser(context, imports, fileInfo) {
3134     var parsers,
3135         parserInput = getParserInput();
3136
3137     function error(msg, type) {
3138         throw new LessError(
3139             {
3140                 index: parserInput.i,
3141                 filename: fileInfo.filename,
3142                 type: type || 'Syntax',
3143                 message: msg
3144             },
3145             imports
3146         );
3147     }
3148
3149     function expect(arg, msg, index) {
3150         // some older browsers return typeof 'function' for RegExp
3151         var result = (arg instanceof Function) ? arg.call(parsers) : parserInput.$re(arg);
3152         if (result) {
3153             return result;
3154         }
3155         error(msg || (typeof arg === 'string' ? "expected '" + arg + "' got '" + parserInput.currentChar() + "'"
3156                                                : "unexpected token"));
3157     }
3158
3159     // Specialization of expect()
3160     function expectChar(arg, msg) {
3161         if (parserInput.$char(arg)) {
3162             return arg;
3163         }
3164         error(msg || "expected '" + arg + "' got '" + parserInput.currentChar() + "'");
3165     }
3166
3167     function getDebugInfo(index) {
3168         var filename = fileInfo.filename;
3169
3170         return {
3171             lineNumber: utils.getLocation(index, parserInput.getInput()).line + 1,
3172             fileName: filename
3173         };
3174     }
3175
3176     //
3177     // The Parser
3178     //
3179     return {
3180
3181         //
3182         // Parse an input string into an abstract syntax tree,
3183         // @param str A string containing 'less' markup
3184         // @param callback call `callback` when done.
3185         // @param [additionalData] An optional map which can contains vars - a map (key, value) of variables to apply
3186         //
3187         parse: function (str, callback, additionalData) {
3188             var root, error = null, globalVars, modifyVars, ignored, preText = "";
3189
3190             globalVars = (additionalData && additionalData.globalVars) ? Parser.serializeVars(additionalData.globalVars) + '\n' : '';
3191             modifyVars = (additionalData && additionalData.modifyVars) ? '\n' + Parser.serializeVars(additionalData.modifyVars) : '';
3192
3193             if (context.pluginManager) {
3194                 var preProcessors = context.pluginManager.getPreProcessors();
3195                 for (var i = 0; i < preProcessors.length; i++) {
3196                     str = preProcessors[i].process(str, { context: context, imports: imports, fileInfo: fileInfo });
3197                 }
3198             }
3199
3200             if (globalVars || (additionalData && additionalData.banner)) {
3201                 preText = ((additionalData && additionalData.banner) ? additionalData.banner : "") + globalVars;
3202                 ignored = imports.contentsIgnoredChars;
3203                 ignored[fileInfo.filename] = ignored[fileInfo.filename] || 0;
3204                 ignored[fileInfo.filename] += preText.length;
3205             }
3206
3207             str = str.replace(/\r\n?/g, '\n');
3208             // Remove potential UTF Byte Order Mark
3209             str = preText + str.replace(/^\uFEFF/, '') + modifyVars;
3210             imports.contents[fileInfo.filename] = str;
3211
3212             // Start with the primary rule.
3213             // The whole syntax tree is held under a Ruleset node,
3214             // with the `root` property set to true, so no `{}` are
3215             // output. The callback is called when the input is parsed.
3216             try {
3217                 parserInput.start(str, context.chunkInput, function fail(msg, index) {
3218                     throw new LessError({
3219                         index: index,
3220                         type: 'Parse',
3221                         message: msg,
3222                         filename: fileInfo.filename
3223                     }, imports);
3224                 });
3225
3226                 root = new(tree.Ruleset)(null, this.parsers.primary());
3227                 root.root = true;
3228                 root.firstRoot = true;
3229             } catch (e) {
3230                 return callback(new LessError(e, imports, fileInfo.filename));
3231             }
3232
3233             // If `i` is smaller than the `input.length - 1`,
3234             // it means the parser wasn't able to parse the whole
3235             // string, so we've got a parsing error.
3236             //
3237             // We try to extract a \n delimited string,
3238             // showing the line where the parse error occurred.
3239             // We split it up into two parts (the part which parsed,
3240             // and the part which didn't), so we can color them differently.
3241             var endInfo = parserInput.end();
3242             if (!endInfo.isFinished) {
3243
3244                 var message = endInfo.furthestPossibleErrorMessage;
3245
3246                 if (!message) {
3247                     message = "Unrecognised input";
3248                     if (endInfo.furthestChar === '}') {
3249                         message += ". Possibly missing opening '{'";
3250                     } else if (endInfo.furthestChar === ')') {
3251                         message += ". Possibly missing opening '('";
3252                     } else if (endInfo.furthestReachedEnd) {
3253                         message += ". Possibly missing something";
3254                     }
3255                 }
3256
3257                 error = new LessError({
3258                     type: "Parse",
3259                     message: message,
3260                     index: endInfo.furthest,
3261                     filename: fileInfo.filename
3262                 }, imports);
3263             }
3264
3265             var finish = function (e) {
3266                 e = error || e || imports.error;
3267
3268                 if (e) {
3269                     if (!(e instanceof LessError)) {
3270                         e = new LessError(e, imports, fileInfo.filename);
3271                     }
3272
3273                     return callback(e);
3274                 }
3275                 else {
3276                     return callback(null, root);
3277                 }
3278             };
3279
3280             if (context.processImports !== false) {
3281                 new visitors.ImportVisitor(imports, finish)
3282                     .run(root);
3283             } else {
3284                 return finish();
3285             }
3286         },
3287
3288         //
3289         // Here in, the parsing rules/functions
3290         //
3291         // The basic structure of the syntax tree generated is as follows:
3292         //
3293         //   Ruleset ->  Rule -> Value -> Expression -> Entity
3294         //
3295         // Here's some Less code:
3296         //
3297         //    .class {
3298         //      color: #fff;
3299         //      border: 1px solid #000;
3300         //      width: @w + 4px;
3301         //      > .child {...}
3302         //    }
3303         //
3304         // And here's what the parse tree might look like:
3305         //
3306         //     Ruleset (Selector '.class', [
3307         //         Rule ("color",  Value ([Expression [Color #fff]]))
3308         //         Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]]))
3309         //         Rule ("width",  Value ([Expression [Operation " + " [Variable "@w"][Dimension 4px]]]))
3310         //         Ruleset (Selector [Element '>', '.child'], [...])
3311         //     ])
3312         //
3313         //  In general, most rules will try to parse a token with the `$re()` function, and if the return
3314         //  value is truly, will return a new node, of the relevant type. Sometimes, we need to check
3315         //  first, before parsing, that's when we use `peek()`.
3316         //
3317         parsers: parsers = {
3318             //
3319             // The `primary` rule is the *entry* and *exit* point of the parser.
3320             // The rules here can appear at any level of the parse tree.
3321             //
3322             // The recursive nature of the grammar is an interplay between the `block`
3323             // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule,
3324             // as represented by this simplified grammar:
3325             //
3326             //     primary  â†’  (ruleset | rule)+
3327             //     ruleset  â†’  selector+ block
3328             //     block    â†’  '{' primary '}'
3329             //
3330             // Only at one point is the primary rule not called from the
3331             // block rule: at the root level.
3332             //
3333             primary: function () {
3334                 var mixin = this.mixin, root = [], node;
3335
3336                 while (true) {
3337                     while (true) {
3338                         node = this.comment();
3339                         if (!node) { break; }
3340                         root.push(node);
3341                     }
3342                     // always process comments before deciding if finished
3343                     if (parserInput.finished) {
3344                         break;
3345                     }
3346                     if (parserInput.peek('}')) {
3347                         break;
3348                     }
3349
3350                     node = this.extendRule();
3351                     if (node) {
3352                         root = root.concat(node);
3353                         continue;
3354                     }
3355
3356                     node = mixin.definition() || this.rule() || this.ruleset() ||
3357                         mixin.call() || this.rulesetCall() || this.entities.call() || this.directive();
3358                     if (node) {
3359                         root.push(node);
3360                     } else {
3361                         var foundSemiColon = false;
3362                         while (parserInput.$char(";")) {
3363                             foundSemiColon = true;
3364                         }
3365                         if (!foundSemiColon) {
3366                             break;
3367                         }
3368                     }
3369                 }
3370
3371                 return root;
3372             },
3373
3374             // comments are collected by the main parsing mechanism and then assigned to nodes
3375             // where the current structure allows it
3376             comment: function () {
3377                 if (parserInput.commentStore.length) {
3378                     var comment = parserInput.commentStore.shift();
3379                     return new(tree.Comment)(comment.text, comment.isLineComment, comment.index, fileInfo);
3380                 }
3381             },
3382
3383             //
3384             // Entities are tokens which can be found inside an Expression
3385             //
3386             entities: {
3387                 //
3388                 // A string, which supports escaping " and '
3389                 //
3390                 //     "milky way" 'he\'s the one!'
3391                 //
3392                 quoted: function () {
3393                     var str, index = parserInput.i, isEscaped = false;
3394
3395                     parserInput.save();
3396                     if (parserInput.$char("~")) {
3397                         isEscaped = true;
3398                     }
3399                     str = parserInput.$quoted();
3400                     if (!str) {
3401                         parserInput.restore();
3402                         return;
3403                     }
3404                     parserInput.forget();
3405
3406                     return new(tree.Quoted)(str.charAt(0), str.substr(1, str.length - 2), isEscaped, index, fileInfo);
3407                 },
3408
3409                 //
3410                 // A catch-all word, such as:
3411                 //
3412                 //     black border-collapse
3413                 //
3414                 keyword: function () {
3415                     var k = parserInput.$char("%") || parserInput.$re(/^[_A-Za-z-][_A-Za-z0-9-]*/);
3416                     if (k) {
3417                         return tree.Color.fromKeyword(k) || new(tree.Keyword)(k);
3418                     }
3419                 },
3420
3421                 //
3422                 // A function call
3423                 //
3424                 //     rgb(255, 0, 255)
3425                 //
3426                 // We also try to catch IE's `alpha()`, but let the `alpha` parser
3427                 // deal with the details.
3428                 //
3429                 // The arguments are parsed with the `entities.arguments` parser.
3430                 //
3431                 call: function () {
3432                     var name, nameLC, args, alpha, index = parserInput.i;
3433
3434                     // http://jsperf.com/case-insensitive-regex-vs-strtolower-then-regex/18
3435                     if (parserInput.peek(/^url\(/i)) {
3436                         return;
3437                     }
3438
3439                     parserInput.save();
3440
3441                     name = parserInput.$re(/^([\w-]+|%|progid:[\w\.]+)\(/);
3442                     if (!name) { parserInput.forget(); return; }
3443
3444                     name = name[1];
3445                     nameLC = name.toLowerCase();
3446
3447                     if (nameLC === 'alpha') {
3448                         alpha = parsers.alpha();
3449                         if (alpha) {
3450                             parserInput.forget();
3451                             return alpha;
3452                         }
3453                     }
3454
3455                     args = this.arguments();
3456
3457                     if (! parserInput.$char(')')) {
3458                         parserInput.restore("Could not parse call arguments or missing ')'");
3459                         return;
3460                     }
3461
3462                     parserInput.forget();
3463                     return new(tree.Call)(name, args, index, fileInfo);
3464                 },
3465                 arguments: function () {
3466                     var argsSemiColon = [], argsComma = [],
3467                         expressions = [],
3468                         isSemiColonSeparated, value, arg;
3469
3470                     parserInput.save();
3471
3472                     while (true) {
3473
3474                         arg = parsers.detachedRuleset() || this.assignment() || parsers.expression();
3475
3476                         if (!arg) {
3477                             break;
3478                         }
3479
3480                         value = arg;
3481
3482                         if (arg.value && arg.value.length == 1) {
3483                             value = arg.value[0];
3484                         }
3485
3486                         if (value) {
3487                             expressions.push(value);
3488                         }
3489
3490                         argsComma.push(value);
3491
3492                         if (parserInput.$char(',')) {
3493                             continue;
3494                         }
3495
3496                         if (parserInput.$char(';') || isSemiColonSeparated) {
3497
3498                             isSemiColonSeparated = true;
3499
3500                             if (expressions.length > 1) {
3501                                 value = new(tree.Value)(expressions);
3502                             }
3503                             argsSemiColon.push(value);
3504
3505                             expressions = [];
3506                         }
3507                     }
3508
3509                     parserInput.forget();
3510                     return isSemiColonSeparated ? argsSemiColon : argsComma;
3511                 },
3512                 literal: function () {
3513                     return this.dimension() ||
3514                            this.color() ||
3515                            this.quoted() ||
3516                            this.unicodeDescriptor();
3517                 },
3518
3519                 // Assignments are argument entities for calls.
3520                 // They are present in ie filter properties as shown below.
3521                 //
3522                 //     filter: progid:DXImageTransform.Microsoft.Alpha( *opacity=50* )
3523                 //
3524
3525                 assignment: function () {
3526                     var key, value;
3527                     parserInput.save();
3528                     key = parserInput.$re(/^\w+(?=\s?=)/i);
3529                     if (!key) {
3530                         parserInput.restore();
3531                         return;
3532                     }
3533                     if (!parserInput.$char('=')) {
3534                         parserInput.restore();
3535                         return;
3536                     }
3537                     value = parsers.entity();
3538                     if (value) {
3539                         parserInput.forget();
3540                         return new(tree.Assignment)(key, value);
3541                     } else {
3542                         parserInput.restore();
3543                     }
3544                 },
3545
3546                 //
3547                 // Parse url() tokens
3548                 //
3549                 // We use a specific rule for urls, because they don't really behave like
3550                 // standard function calls. The difference is that the argument doesn't have
3551                 // to be enclosed within a string, so it can't be parsed as an Expression.
3552                 //
3553                 url: function () {
3554                     var value, index = parserInput.i;
3555
3556                     parserInput.autoCommentAbsorb = false;
3557
3558                     if (!parserInput.$str("url(")) {
3559                         parserInput.autoCommentAbsorb = true;
3560                         return;
3561                     }
3562
3563                     value = this.quoted() || this.variable() ||
3564                             parserInput.$re(/^(?:(?:\\[\(\)'"])|[^\(\)'"])+/) || "";
3565
3566                     parserInput.autoCommentAbsorb = true;
3567
3568                     expectChar(')');
3569
3570                     return new(tree.URL)((value.value != null || value instanceof tree.Variable) ?
3571                                         value : new(tree.Anonymous)(value), index, fileInfo);
3572                 },
3573
3574                 //
3575                 // A Variable entity, such as `@fink`, in
3576                 //
3577                 //     width: @fink + 2px
3578                 //
3579                 // We use a different parser for variable definitions,
3580                 // see `parsers.variable`.
3581                 //
3582                 variable: function () {
3583                     var name, index = parserInput.i;
3584
3585                     if (parserInput.currentChar() === '@' && (name = parserInput.$re(/^@@?[\w-]+/))) {
3586                         return new(tree.Variable)(name, index, fileInfo);
3587                     }
3588                 },
3589
3590                 // A variable entity using the protective {} e.g. @{var}
3591                 variableCurly: function () {
3592                     var curly, index = parserInput.i;
3593
3594                     if (parserInput.currentChar() === '@' && (curly = parserInput.$re(/^@\{([\w-]+)\}/))) {
3595                         return new(tree.Variable)("@" + curly[1], index, fileInfo);
3596                     }
3597                 },
3598
3599                 //
3600                 // A Hexadecimal color
3601                 //
3602                 //     #4F3C2F
3603                 //
3604                 // `rgb` and `hsl` colors are parsed through the `entities.call` parser.
3605                 //
3606                 color: function () {
3607                     var rgb;
3608
3609                     if (parserInput.currentChar() === '#' && (rgb = parserInput.$re(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/))) {
3610                         // strip colons, brackets, whitespaces and other characters that should not
3611                         // definitely be part of color string
3612                         var colorCandidateString = rgb.input.match(/^#([\w]+).*/);
3613                         colorCandidateString = colorCandidateString[1];
3614                         if (!colorCandidateString.match(/^[A-Fa-f0-9]+$/)) { // verify if candidate consists only of allowed HEX characters
3615                             error("Invalid HEX color code");
3616                         }
3617                         return new(tree.Color)(rgb[1], undefined, '#' + colorCandidateString);
3618                     }
3619                 },
3620
3621                 colorKeyword: function () {
3622                     parserInput.save();
3623                     var autoCommentAbsorb = parserInput.autoCommentAbsorb;
3624                     parserInput.autoCommentAbsorb = false;
3625                     var k = parserInput.$re(/^[_A-Za-z-][_A-Za-z0-9-]+/);
3626                     parserInput.autoCommentAbsorb = autoCommentAbsorb;
3627                     if (!k) {
3628                         parserInput.forget();
3629                         return;
3630                     }
3631                     parserInput.restore();
3632                     var color = tree.Color.fromKeyword(k);
3633                     if (color) {
3634                         parserInput.$str(k);
3635                         return color;
3636                     }
3637                 },
3638
3639                 //
3640                 // A Dimension, that is, a number and a unit
3641                 //
3642                 //     0.5em 95%
3643                 //
3644                 dimension: function () {
3645                     if (parserInput.peekNotNumeric()) {
3646                         return;
3647                     }
3648
3649                     var value = parserInput.$re(/^([+-]?\d*\.?\d+)(%|[a-z_]+)?/i);
3650                     if (value) {
3651                         return new(tree.Dimension)(value[1], value[2]);
3652                     }
3653                 },
3654
3655                 //
3656                 // A unicode descriptor, as is used in unicode-range
3657                 //
3658                 // U+0??  or U+00A1-00A9
3659                 //
3660                 unicodeDescriptor: function () {
3661                     var ud;
3662
3663                     ud = parserInput.$re(/^U\+[0-9a-fA-F?]+(\-[0-9a-fA-F?]+)?/);
3664                     if (ud) {
3665                         return new(tree.UnicodeDescriptor)(ud[0]);
3666                     }
3667                 },
3668
3669                 //
3670                 // JavaScript code to be evaluated
3671                 //
3672                 //     `window.location.href`
3673                 //
3674                 javascript: function () {
3675                     var js, index = parserInput.i;
3676
3677                     parserInput.save();
3678
3679                     var escape = parserInput.$char("~");
3680                     var jsQuote = parserInput.$char("`");
3681
3682                     if (!jsQuote) {
3683                         parserInput.restore();
3684                         return;
3685                     }
3686
3687                     js = parserInput.$re(/^[^`]*`/);
3688                     if (js) {
3689                         parserInput.forget();
3690                         return new(tree.JavaScript)(js.substr(0, js.length - 1), Boolean(escape), index, fileInfo);
3691                     }
3692                     parserInput.restore("invalid javascript definition");
3693                 }
3694             },
3695
3696             //
3697             // The variable part of a variable definition. Used in the `rule` parser
3698             //
3699             //     @fink:
3700             //
3701             variable: function () {
3702                 var name;
3703
3704                 if (parserInput.currentChar() === '@' && (name = parserInput.$re(/^(@[\w-]+)\s*:/))) { return name[1]; }
3705             },
3706
3707             //
3708             // The variable part of a variable definition. Used in the `rule` parser
3709             //
3710             //     @fink();
3711             //
3712             rulesetCall: function () {
3713                 var name;
3714
3715                 if (parserInput.currentChar() === '@' && (name = parserInput.$re(/^(@[\w-]+)\(\s*\)\s*;/))) {
3716                     return new tree.RulesetCall(name[1]);
3717                 }
3718             },
3719
3720             //
3721             // extend syntax - used to extend selectors
3722             //
3723             extend: function(isRule) {
3724                 var elements, e, index = parserInput.i, option, extendList, extend;
3725
3726                 if (!parserInput.$str(isRule ? "&:extend(" : ":extend(")) {
3727                     return;
3728                 }
3729
3730                 do {
3731                     option = null;
3732                     elements = null;
3733                     while (! (option = parserInput.$re(/^(all)(?=\s*(\)|,))/))) {
3734                         e = this.element();
3735                         if (!e) {
3736                             break;
3737                         }
3738                         if (elements) {
3739                             elements.push(e);
3740                         } else {
3741                             elements = [ e ];
3742                         }
3743                     }
3744
3745                     option = option && option[1];
3746                     if (!elements) {
3747                         error("Missing target selector for :extend().");
3748                     }
3749                     extend = new(tree.Extend)(new(tree.Selector)(elements), option, index, fileInfo);
3750                     if (extendList) {
3751                         extendList.push(extend);
3752                     } else {
3753                         extendList = [ extend ];
3754                     }
3755                 } while (parserInput.$char(","));
3756
3757                 expect(/^\)/);
3758
3759                 if (isRule) {
3760                     expect(/^;/);
3761                 }
3762
3763                 return extendList;
3764             },
3765
3766             //
3767             // extendRule - used in a rule to extend all the parent selectors
3768             //
3769             extendRule: function() {
3770                 return this.extend(true);
3771             },
3772
3773             //
3774             // Mixins
3775             //
3776             mixin: {
3777                 //
3778                 // A Mixin call, with an optional argument list
3779                 //
3780                 //     #mixins > .square(#fff);
3781                 //     .rounded(4px, black);
3782                 //     .button;
3783                 //
3784                 // The `while` loop is there because mixins can be
3785                 // namespaced, but we only support the child and descendant
3786                 // selector for now.
3787                 //
3788                 call: function () {
3789                     var s = parserInput.currentChar(), important = false, index = parserInput.i, elemIndex,
3790                         elements, elem, e, c, args;
3791
3792                     if (s !== '.' && s !== '#') { return; }
3793
3794                     parserInput.save(); // stop us absorbing part of an invalid selector
3795
3796                     while (true) {
3797                         elemIndex = parserInput.i;
3798                         e = parserInput.$re(/^[#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/);
3799                         if (!e) {
3800                             break;
3801                         }
3802                         elem = new(tree.Element)(c, e, elemIndex, fileInfo);
3803                         if (elements) {
3804                             elements.push(elem);
3805                         } else {
3806                             elements = [ elem ];
3807                         }
3808                         c = parserInput.$char('>');
3809                     }
3810
3811                     if (elements) {
3812                         if (parserInput.$char('(')) {
3813                             args = this.args(true).args;
3814                             expectChar(')');
3815                         }
3816
3817                         if (parsers.important()) {
3818                             important = true;
3819                         }
3820
3821                         if (parsers.end()) {
3822                             parserInput.forget();
3823                             return new(tree.mixin.Call)(elements, args, index, fileInfo, important);
3824                         }
3825                     }
3826
3827                     parserInput.restore();
3828                 },
3829                 args: function (isCall) {
3830                     var entities = parsers.entities,
3831                         returner = { args:null, variadic: false },
3832                         expressions = [], argsSemiColon = [], argsComma = [],
3833                         isSemiColonSeparated, expressionContainsNamed, name, nameLoop,
3834                         value, arg, expand;
3835
3836                     parserInput.save();
3837
3838                     while (true) {
3839                         if (isCall) {
3840                             arg = parsers.detachedRuleset() || parsers.expression();
3841                         } else {
3842                             parserInput.commentStore.length = 0;
3843                             if (parserInput.$str("...")) {
3844                                 returner.variadic = true;
3845                                 if (parserInput.$char(";") && !isSemiColonSeparated) {
3846                                     isSemiColonSeparated = true;
3847                                 }
3848                                 (isSemiColonSeparated ? argsSemiColon : argsComma)
3849                                     .push({ variadic: true });
3850                                 break;
3851                             }
3852                             arg = entities.variable() || entities.literal() || entities.keyword();
3853                         }
3854
3855                         if (!arg) {
3856                             break;
3857                         }
3858
3859                         nameLoop = null;
3860                         if (arg.throwAwayComments) {
3861                             arg.throwAwayComments();
3862                         }
3863                         value = arg;
3864                         var val = null;
3865
3866                         if (isCall) {
3867                             // Variable
3868                             if (arg.value && arg.value.length == 1) {
3869                                 val = arg.value[0];
3870                             }
3871                         } else {
3872                             val = arg;
3873                         }
3874
3875                         if (val && val instanceof tree.Variable) {
3876                             if (parserInput.$char(':')) {
3877                                 if (expressions.length > 0) {
3878                                     if (isSemiColonSeparated) {
3879                                         error("Cannot mix ; and , as delimiter types");
3880                                     }
3881                                     expressionContainsNamed = true;
3882                                 }
3883
3884                                 value = parsers.detachedRuleset() || parsers.expression();
3885
3886                                 if (!value) {
3887                                     if (isCall) {
3888                                         error("could not understand value for named argument");
3889                                     } else {
3890                                         parserInput.restore();
3891                                         returner.args = [];
3892                                         return returner;
3893                                     }
3894                                 }
3895                                 nameLoop = (name = val.name);
3896                             } else if (parserInput.$str("...")) {
3897                                 if (!isCall) {
3898                                     returner.variadic = true;
3899                                     if (parserInput.$char(";") && !isSemiColonSeparated) {
3900                                         isSemiColonSeparated = true;
3901                                     }
3902                                     (isSemiColonSeparated ? argsSemiColon : argsComma)
3903                                         .push({ name: arg.name, variadic: true });
3904                                     break;
3905                                 } else {
3906                                     expand = true;
3907                                 }
3908                             } else if (!isCall) {
3909                                 name = nameLoop = val.name;
3910                                 value = null;
3911                             }
3912                         }
3913
3914                         if (value) {
3915                             expressions.push(value);
3916                         }
3917
3918                         argsComma.push({ name:nameLoop, value:value, expand:expand });
3919
3920                         if (parserInput.$char(',')) {
3921                             continue;
3922                         }
3923
3924                         if (parserInput.$char(';') || isSemiColonSeparated) {
3925
3926                             if (expressionContainsNamed) {
3927                                 error("Cannot mix ; and , as delimiter types");
3928                             }
3929
3930                             isSemiColonSeparated = true;
3931
3932                             if (expressions.length > 1) {
3933                                 value = new(tree.Value)(expressions);
3934                             }
3935                             argsSemiColon.push({ name:name, value:value, expand:expand });
3936
3937                             name = null;
3938                             expressions = [];
3939                             expressionContainsNamed = false;
3940                         }
3941                     }
3942
3943                     parserInput.forget();
3944                     returner.args = isSemiColonSeparated ? argsSemiColon : argsComma;
3945                     return returner;
3946                 },
3947                 //
3948                 // A Mixin definition, with a list of parameters
3949                 //
3950                 //     .rounded (@radius: 2px, @color) {
3951                 //        ...
3952                 //     }
3953                 //
3954                 // Until we have a finer grained state-machine, we have to
3955                 // do a look-ahead, to make sure we don't have a mixin call.
3956                 // See the `rule` function for more information.
3957                 //
3958                 // We start by matching `.rounded (`, and then proceed on to
3959                 // the argument list, which has optional default values.
3960                 // We store the parameters in `params`, with a `value` key,
3961                 // if there is a value, such as in the case of `@radius`.
3962                 //
3963                 // Once we've got our params list, and a closing `)`, we parse
3964                 // the `{...}` block.
3965                 //
3966                 definition: function () {
3967                     var name, params = [], match, ruleset, cond, variadic = false;
3968                     if ((parserInput.currentChar() !== '.' && parserInput.currentChar() !== '#') ||
3969                         parserInput.peek(/^[^{]*\}/)) {
3970                         return;
3971                     }
3972
3973                     parserInput.save();
3974
3975                     match = parserInput.$re(/^([#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+)\s*\(/);
3976                     if (match) {
3977                         name = match[1];
3978
3979                         var argInfo = this.args(false);
3980                         params = argInfo.args;
3981                         variadic = argInfo.variadic;
3982
3983                         // .mixincall("@{a}");
3984                         // looks a bit like a mixin definition..
3985                         // also
3986                         // .mixincall(@a: {rule: set;});
3987                         // so we have to be nice and restore
3988                         if (!parserInput.$char(')')) {
3989                             parserInput.restore("Missing closing ')'");
3990                             return;
3991                         }
3992
3993                         parserInput.commentStore.length = 0;
3994
3995                         if (parserInput.$str("when")) { // Guard
3996                             cond = expect(parsers.conditions, 'expected condition');
3997                         }
3998
3999                         ruleset = parsers.block();
4000
4001                         if (ruleset) {
4002                             parserInput.forget();
4003                             return new(tree.mixin.Definition)(name, params, ruleset, cond, variadic);
4004                         } else {
4005                             parserInput.restore();
4006                         }
4007                     } else {
4008                         parserInput.forget();
4009                     }
4010                 }
4011             },
4012
4013             //
4014             // Entities are the smallest recognized token,
4015             // and can be found inside a rule's value.
4016             //
4017             entity: function () {
4018                 var entities = this.entities;
4019
4020                 return this.comment() || entities.literal() || entities.variable() || entities.url() ||
4021                        entities.call()    || entities.keyword()  || entities.javascript();
4022             },
4023
4024             //
4025             // A Rule terminator. Note that we use `peek()` to check for '}',
4026             // because the `block` rule will be expecting it, but we still need to make sure
4027             // it's there, if ';' was omitted.
4028             //
4029             end: function () {
4030                 return parserInput.$char(';') || parserInput.peek('}');
4031             },
4032
4033             //
4034             // IE's alpha function
4035             //
4036             //     alpha(opacity=88)
4037             //
4038             alpha: function () {
4039                 var value;
4040
4041                 // http://jsperf.com/case-insensitive-regex-vs-strtolower-then-regex/18
4042                 if (! parserInput.$re(/^opacity=/i)) { return; }
4043                 value = parserInput.$re(/^\d+/);
4044                 if (!value) {
4045                     value = expect(this.entities.variable, "Could not parse alpha");
4046                 }
4047                 expectChar(')');
4048                 return new(tree.Alpha)(value);
4049             },
4050
4051             //
4052             // A Selector Element
4053             //
4054             //     div
4055             //     + h1
4056             //     #socks
4057             //     input[type="text"]
4058             //
4059             // Elements are the building blocks for Selectors,
4060             // they are made out of a `Combinator` (see combinator rule),
4061             // and an element name, such as a tag a class, or `*`.
4062             //
4063             element: function () {
4064                 var e, c, v, index = parserInput.i;
4065
4066                 c = this.combinator();
4067
4068                 e = parserInput.$re(/^(?:\d+\.\d+|\d+)%/) ||
4069                     parserInput.$re(/^(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/) ||
4070                     parserInput.$char('*') || parserInput.$char('&') || this.attribute() ||
4071                     parserInput.$re(/^\([^&()@]+\)/) ||  parserInput.$re(/^[\.#:](?=@)/) ||
4072                     this.entities.variableCurly();
4073
4074                 if (! e) {
4075                     parserInput.save();
4076                     if (parserInput.$char('(')) {
4077                         if ((v = this.selector()) && parserInput.$char(')')) {
4078                             e = new(tree.Paren)(v);
4079                             parserInput.forget();
4080                         } else {
4081                             parserInput.restore("Missing closing ')'");
4082                         }
4083                     } else {
4084                         parserInput.forget();
4085                     }
4086                 }
4087
4088                 if (e) { return new(tree.Element)(c, e, index, fileInfo); }
4089             },
4090
4091             //
4092             // Combinators combine elements together, in a Selector.
4093             //
4094             // Because our parser isn't white-space sensitive, special care
4095             // has to be taken, when parsing the descendant combinator, ` `,
4096             // as it's an empty space. We have to check the previous character
4097             // in the input, to see if it's a ` ` character. More info on how
4098             // we deal with this in *combinator.js*.
4099             //
4100             combinator: function () {
4101                 var c = parserInput.currentChar();
4102
4103                 if (c === '/') {
4104                     parserInput.save();
4105                     var slashedCombinator = parserInput.$re(/^\/[a-z]+\//i);
4106                     if (slashedCombinator) {
4107                         parserInput.forget();
4108                         return new(tree.Combinator)(slashedCombinator);
4109                     }
4110                     parserInput.restore();
4111                 }
4112
4113                 if (c === '>' || c === '+' || c === '~' || c === '|' || c === '^') {
4114                     parserInput.i++;
4115                     if (c === '^' && parserInput.currentChar() === '^') {
4116                         c = '^^';
4117                         parserInput.i++;
4118                     }
4119                     while (parserInput.isWhitespace()) { parserInput.i++; }
4120                     return new(tree.Combinator)(c);
4121                 } else if (parserInput.isWhitespace(-1)) {
4122                     return new(tree.Combinator)(" ");
4123                 } else {
4124                     return new(tree.Combinator)(null);
4125                 }
4126             },
4127             //
4128             // A CSS selector (see selector below)
4129             // with less extensions e.g. the ability to extend and guard
4130             //
4131             lessSelector: function () {
4132                 return this.selector(true);
4133             },
4134             //
4135             // A CSS Selector
4136             //
4137             //     .class > div + h1
4138             //     li a:hover
4139             //
4140             // Selectors are made out of one or more Elements, see above.
4141             //
4142             selector: function (isLess) {
4143                 var index = parserInput.i, elements, extendList, c, e, allExtends, when, condition;
4144
4145                 while ((isLess && (extendList = this.extend())) || (isLess && (when = parserInput.$str("when"))) || (e = this.element())) {
4146                     if (when) {
4147                         condition = expect(this.conditions, 'expected condition');
4148                     } else if (condition) {
4149                         error("CSS guard can only be used at the end of selector");
4150                     } else if (extendList) {
4151                         if (allExtends) {
4152                             allExtends = allExtends.concat(extendList);
4153                         } else {
4154                             allExtends = extendList;
4155                         }
4156                     } else {
4157                         if (allExtends) { error("Extend can only be used at the end of selector"); }
4158                         c = parserInput.currentChar();
4159                         if (elements) {
4160                             elements.push(e);
4161                         } else {
4162                             elements = [ e ];
4163                         }
4164                         e = null;
4165                     }
4166                     if (c === '{' || c === '}' || c === ';' || c === ',' || c === ')') {
4167                         break;
4168                     }
4169                 }
4170
4171                 if (elements) { return new(tree.Selector)(elements, allExtends, condition, index, fileInfo); }
4172                 if (allExtends) { error("Extend must be used to extend a selector, it cannot be used on its own"); }
4173             },
4174             attribute: function () {
4175                 if (! parserInput.$char('[')) { return; }
4176
4177                 var entities = this.entities,
4178                     key, val, op;
4179
4180                 if (!(key = entities.variableCurly())) {
4181                     key = expect(/^(?:[_A-Za-z0-9-\*]*\|)?(?:[_A-Za-z0-9-]|\\.)+/);
4182                 }
4183
4184                 op = parserInput.$re(/^[|~*$^]?=/);
4185                 if (op) {
4186                     val = entities.quoted() || parserInput.$re(/^[0-9]+%/) || parserInput.$re(/^[\w-]+/) || entities.variableCurly();
4187                 }
4188
4189                 expectChar(']');
4190
4191                 return new(tree.Attribute)(key, op, val);
4192             },
4193
4194             //
4195             // The `block` rule is used by `ruleset` and `mixin.definition`.
4196             // It's a wrapper around the `primary` rule, with added `{}`.
4197             //
4198             block: function () {
4199                 var content;
4200                 if (parserInput.$char('{') && (content = this.primary()) && parserInput.$char('}')) {
4201                     return content;
4202                 }
4203             },
4204
4205             blockRuleset: function() {
4206                 var block = this.block();
4207
4208                 if (block) {
4209                     block = new tree.Ruleset(null, block);
4210                 }
4211                 return block;
4212             },
4213
4214             detachedRuleset: function() {
4215                 var blockRuleset = this.blockRuleset();
4216                 if (blockRuleset) {
4217                     return new tree.DetachedRuleset(blockRuleset);
4218                 }
4219             },
4220
4221             //
4222             // div, .class, body > p {...}
4223             //
4224             ruleset: function () {
4225                 var selectors, s, rules, debugInfo;
4226
4227                 parserInput.save();
4228
4229                 if (context.dumpLineNumbers) {
4230                     debugInfo = getDebugInfo(parserInput.i);
4231                 }
4232
4233                 while (true) {
4234                     s = this.lessSelector();
4235                     if (!s) {
4236                         break;
4237                     }
4238                     if (selectors) {
4239                         selectors.push(s);
4240                     } else {
4241                         selectors = [ s ];
4242                     }
4243                     parserInput.commentStore.length = 0;
4244                     if (s.condition && selectors.length > 1) {
4245                         error("Guards are only currently allowed on a single selector.");
4246                     }
4247                     if (! parserInput.$char(',')) { break; }
4248                     if (s.condition) {
4249                         error("Guards are only currently allowed on a single selector.");
4250                     }
4251                     parserInput.commentStore.length = 0;
4252                 }
4253
4254                 if (selectors && (rules = this.block())) {
4255                     parserInput.forget();
4256                     var ruleset = new(tree.Ruleset)(selectors, rules, context.strictImports);
4257                     if (context.dumpLineNumbers) {
4258                         ruleset.debugInfo = debugInfo;
4259                     }
4260                     return ruleset;
4261                 } else {
4262                     parserInput.restore();
4263                 }
4264             },
4265             rule: function (tryAnonymous) {
4266                 var name, value, startOfRule = parserInput.i, c = parserInput.currentChar(), important, merge, isVariable;
4267
4268                 if (c === '.' || c === '#' || c === '&' || c === ':') { return; }
4269
4270                 parserInput.save();
4271
4272                 name = this.variable() || this.ruleProperty();
4273                 if (name) {
4274                     isVariable = typeof name === "string";
4275
4276                     if (isVariable) {
4277                         value = this.detachedRuleset();
4278                     }
4279
4280                     parserInput.commentStore.length = 0;
4281                     if (!value) {
4282                         // a name returned by this.ruleProperty() is always an array of the form:
4283                         // [string-1, ..., string-n, ""] or [string-1, ..., string-n, "+"]
4284                         // where each item is a tree.Keyword or tree.Variable
4285                         merge = !isVariable && name.length > 1 && name.pop().value;
4286
4287                         // prefer to try to parse first if its a variable or we are compressing
4288                         // but always fallback on the other one
4289                         var tryValueFirst = !tryAnonymous && (context.compress || isVariable);
4290
4291                         if (tryValueFirst) {
4292                             value = this.value();
4293                         }
4294                         if (!value) {
4295                             value = this.anonymousValue();
4296                             if (value) {
4297                                 parserInput.forget();
4298                                 // anonymous values absorb the end ';' which is required for them to work
4299                                 return new (tree.Rule)(name, value, false, merge, startOfRule, fileInfo);
4300                             }
4301                         }
4302                         if (!tryValueFirst && !value) {
4303                             value = this.value();
4304                         }
4305
4306                         important = this.important();
4307                     }
4308
4309                     if (value && this.end()) {
4310                         parserInput.forget();
4311                         return new (tree.Rule)(name, value, important, merge, startOfRule, fileInfo);
4312                     } else {
4313                         parserInput.restore();
4314                         if (value && !tryAnonymous) {
4315                             return this.rule(true);
4316                         }
4317                     }
4318                 } else {
4319                     parserInput.forget();
4320                 }
4321             },
4322             anonymousValue: function () {
4323                 var match = parserInput.$re(/^([^@+\/'"*`(;{}-]*);/);
4324                 if (match) {
4325                     return new(tree.Anonymous)(match[1]);
4326                 }
4327             },
4328
4329             //
4330             // An @import directive
4331             //
4332             //     @import "lib";
4333             //
4334             // Depending on our environment, importing is done differently:
4335             // In the browser, it's an XHR request, in Node, it would be a
4336             // file-system operation. The function used for importing is
4337             // stored in `import`, which we pass to the Import constructor.
4338             //
4339             "import": function () {
4340                 var path, features, index = parserInput.i;
4341
4342                 var dir = parserInput.$re(/^@import?\s+/);
4343
4344                 if (dir) {
4345                     var options = (dir ? this.importOptions() : null) || {};
4346
4347                     if ((path = this.entities.quoted() || this.entities.url())) {
4348                         features = this.mediaFeatures();
4349
4350                         if (!parserInput.$char(';')) {
4351                             parserInput.i = index;
4352                             error("missing semi-colon or unrecognised media features on import");
4353                         }
4354                         features = features && new(tree.Value)(features);
4355                         return new(tree.Import)(path, features, options, index, fileInfo);
4356                     }
4357                     else {
4358                         parserInput.i = index;
4359                         error("malformed import statement");
4360                     }
4361                 }
4362             },
4363
4364             importOptions: function() {
4365                 var o, options = {}, optionName, value;
4366
4367                 // list of options, surrounded by parens
4368                 if (! parserInput.$char('(')) { return null; }
4369                 do {
4370                     o = this.importOption();
4371                     if (o) {
4372                         optionName = o;
4373                         value = true;
4374                         switch(optionName) {
4375                             case "css":
4376                                 optionName = "less";
4377                                 value = false;
4378                                 break;
4379                             case "once":
4380                                 optionName = "multiple";
4381                                 value = false;
4382                                 break;
4383                         }
4384                         options[optionName] = value;
4385                         if (! parserInput.$char(',')) { break; }
4386                     }
4387                 } while (o);
4388                 expectChar(')');
4389                 return options;
4390             },
4391
4392             importOption: function() {
4393                 var opt = parserInput.$re(/^(less|css|multiple|once|inline|reference|optional)/);
4394                 if (opt) {
4395                     return opt[1];
4396                 }
4397             },
4398
4399             mediaFeature: function () {
4400                 var entities = this.entities, nodes = [], e, p;
4401                 parserInput.save();
4402                 do {
4403                     e = entities.keyword() || entities.variable();
4404                     if (e) {
4405                         nodes.push(e);
4406                     } else if (parserInput.$char('(')) {
4407                         p = this.property();
4408                         e = this.value();
4409                         if (parserInput.$char(')')) {
4410                             if (p && e) {
4411                                 nodes.push(new(tree.Paren)(new(tree.Rule)(p, e, null, null, parserInput.i, fileInfo, true)));
4412                             } else if (e) {
4413                                 nodes.push(new(tree.Paren)(e));
4414                             } else {
4415                                 error("badly formed media feature definition");
4416                             }
4417                         } else {
4418                             error("Missing closing ')'", "Parse");
4419                         }
4420                     }
4421                 } while (e);
4422
4423                 parserInput.forget();
4424                 if (nodes.length > 0) {
4425                     return new(tree.Expression)(nodes);
4426                 }
4427             },
4428
4429             mediaFeatures: function () {
4430                 var entities = this.entities, features = [], e;
4431                 do {
4432                     e = this.mediaFeature();
4433                     if (e) {
4434                         features.push(e);
4435                         if (! parserInput.$char(',')) { break; }
4436                     } else {
4437                         e = entities.variable();
4438                         if (e) {
4439                             features.push(e);
4440                             if (! parserInput.$char(',')) { break; }
4441                         }
4442                     }
4443                 } while (e);
4444
4445                 return features.length > 0 ? features : null;
4446             },
4447
4448             media: function () {
4449                 var features, rules, media, debugInfo, index = parserInput.i;
4450
4451                 if (context.dumpLineNumbers) {
4452                     debugInfo = getDebugInfo(index);
4453                 }
4454
4455                 parserInput.save();
4456
4457                 if (parserInput.$str("@media")) {
4458                     features = this.mediaFeatures();
4459
4460                     rules = this.block();
4461
4462                     if (!rules) {
4463                         error("media definitions require block statements after any features");
4464                     }
4465
4466                     parserInput.forget();
4467
4468                     media = new(tree.Media)(rules, features, index, fileInfo);
4469                     if (context.dumpLineNumbers) {
4470                         media.debugInfo = debugInfo;
4471                     }
4472
4473                     return media;
4474                 }
4475
4476                 parserInput.restore();
4477             },
4478
4479             //
4480             // A @plugin directive, used to import compiler extensions dynamically.
4481             //
4482             //     @plugin "lib";
4483             //
4484             // Depending on our environment, importing is done differently:
4485             // In the browser, it's an XHR request, in Node, it would be a
4486             // file-system operation. The function used for importing is
4487             // stored in `import`, which we pass to the Import constructor.
4488             //
4489             plugin: function () {
4490                 var path,
4491                     index = parserInput.i,
4492                     dir   = parserInput.$re(/^@plugin?\s+/);
4493
4494                 if (dir) {
4495                     var options = { plugin : true };
4496
4497                     if ((path = this.entities.quoted() || this.entities.url())) {
4498
4499                         if (!parserInput.$char(';')) {
4500                             parserInput.i = index;
4501                             error("missing semi-colon on plugin");
4502                         }
4503
4504                         return new(tree.Import)(path, null, options, index, fileInfo);
4505                     }
4506                     else {
4507                         parserInput.i = index;
4508                         error("malformed plugin statement");
4509                     }
4510                 }
4511             },
4512
4513             //
4514             // A CSS Directive
4515             //
4516             //     @charset "utf-8";
4517             //
4518             directive: function () {
4519                 var index = parserInput.i, name, value, rules, nonVendorSpecificName,
4520                     hasIdentifier, hasExpression, hasUnknown, hasBlock = true, isRooted = true;
4521
4522                 if (parserInput.currentChar() !== '@') { return; }
4523
4524                 value = this['import']() || this.plugin() || this.media();
4525                 if (value) {
4526                     return value;
4527                 }
4528
4529                 parserInput.save();
4530
4531                 name = parserInput.$re(/^@[a-z-]+/);
4532
4533                 if (!name) { return; }
4534
4535                 nonVendorSpecificName = name;
4536                 if (name.charAt(1) == '-' && name.indexOf('-', 2) > 0) {
4537                     nonVendorSpecificName = "@" + name.slice(name.indexOf('-', 2) + 1);
4538                 }
4539
4540                 switch(nonVendorSpecificName) {
4541                     case "@charset":
4542                         hasIdentifier = true;
4543                         hasBlock = false;
4544                         break;
4545                     case "@namespace":
4546                         hasExpression = true;
4547                         hasBlock = false;
4548                         break;
4549                     case "@keyframes":
4550                     case "@counter-style":
4551                         hasIdentifier = true;
4552                         break;
4553                     case "@document":
4554                     case "@supports":
4555                         hasUnknown = true;
4556                         isRooted = false;
4557                         break;
4558                     default:
4559                         hasUnknown = true;
4560                         break;
4561                 }
4562
4563                 parserInput.commentStore.length = 0;
4564
4565                 if (hasIdentifier) {
4566                     value = this.entity();
4567                     if (!value) {
4568                         error("expected " + name + " identifier");
4569                     }
4570                 } else if (hasExpression) {
4571                     value = this.expression();
4572                     if (!value) {
4573                         error("expected " + name + " expression");
4574                     }
4575                 } else if (hasUnknown) {
4576                     value = (parserInput.$re(/^[^{;]+/) || '').trim();
4577                     hasBlock = (parserInput.currentChar() == '{');
4578                     if (value) {
4579                         value = new(tree.Anonymous)(value);
4580                     }
4581                 }
4582
4583                 if (hasBlock) {
4584                     rules = this.blockRuleset();
4585                 }
4586
4587                 if (rules || (!hasBlock && value && parserInput.$char(';'))) {
4588                     parserInput.forget();
4589                     return new (tree.Directive)(name, value, rules, index, fileInfo,
4590                         context.dumpLineNumbers ? getDebugInfo(index) : null,
4591                         isRooted
4592                     );
4593                 }
4594
4595                 parserInput.restore("directive options not recognised");
4596             },
4597
4598             //
4599             // A Value is a comma-delimited list of Expressions
4600             //
4601             //     font-family: Baskerville, Georgia, serif;
4602             //
4603             // In a Rule, a Value represents everything after the `:`,
4604             // and before the `;`.
4605             //
4606             value: function () {
4607                 var e, expressions = [];
4608
4609                 do {
4610                     e = this.expression();
4611                     if (e) {
4612                         expressions.push(e);
4613                         if (! parserInput.$char(',')) { break; }
4614                     }
4615                 } while (e);
4616
4617                 if (expressions.length > 0) {
4618                     return new(tree.Value)(expressions);
4619                 }
4620             },
4621             important: function () {
4622                 if (parserInput.currentChar() === '!') {
4623                     return parserInput.$re(/^! *important/);
4624                 }
4625             },
4626             sub: function () {
4627                 var a, e;
4628
4629                 parserInput.save();
4630                 if (parserInput.$char('(')) {
4631                     a = this.addition();
4632                     if (a && parserInput.$char(')')) {
4633                         parserInput.forget();
4634                         e = new(tree.Expression)([a]);
4635                         e.parens = true;
4636                         return e;
4637                     }
4638                     parserInput.restore("Expected ')'");
4639                     return;
4640                 }
4641                 parserInput.restore();
4642             },
4643             multiplication: function () {
4644                 var m, a, op, operation, isSpaced;
4645                 m = this.operand();
4646                 if (m) {
4647                     isSpaced = parserInput.isWhitespace(-1);
4648                     while (true) {
4649                         if (parserInput.peek(/^\/[*\/]/)) {
4650                             break;
4651                         }
4652
4653                         parserInput.save();
4654
4655                         op = parserInput.$char('/') || parserInput.$char('*');
4656
4657                         if (!op) { parserInput.forget(); break; }
4658
4659                         a = this.operand();
4660
4661                         if (!a) { parserInput.restore(); break; }
4662                         parserInput.forget();
4663
4664                         m.parensInOp = true;
4665                         a.parensInOp = true;
4666                         operation = new(tree.Operation)(op, [operation || m, a], isSpaced);
4667                         isSpaced = parserInput.isWhitespace(-1);
4668                     }
4669                     return operation || m;
4670                 }
4671             },
4672             addition: function () {
4673                 var m, a, op, operation, isSpaced;
4674                 m = this.multiplication();
4675                 if (m) {
4676                     isSpaced = parserInput.isWhitespace(-1);
4677                     while (true) {
4678                         op = parserInput.$re(/^[-+]\s+/) || (!isSpaced && (parserInput.$char('+') || parserInput.$char('-')));
4679                         if (!op) {
4680                             break;
4681                         }
4682                         a = this.multiplication();
4683                         if (!a) {
4684                             break;
4685                         }
4686
4687                         m.parensInOp = true;
4688                         a.parensInOp = true;
4689                         operation = new(tree.Operation)(op, [operation || m, a], isSpaced);
4690                         isSpaced = parserInput.isWhitespace(-1);
4691                     }
4692                     return operation || m;
4693                 }
4694             },
4695             conditions: function () {
4696                 var a, b, index = parserInput.i, condition;
4697
4698                 a = this.condition();
4699                 if (a) {
4700                     while (true) {
4701                         if (!parserInput.peek(/^,\s*(not\s*)?\(/) || !parserInput.$char(',')) {
4702                             break;
4703                         }
4704                         b = this.condition();
4705                         if (!b) {
4706                             break;
4707                         }
4708                         condition = new(tree.Condition)('or', condition || a, b, index);
4709                     }
4710                     return condition || a;
4711                 }
4712             },
4713             condition: function () {
4714                 var result, logical, next;
4715                 function or() {
4716                     return parserInput.$str("or");
4717                 }
4718
4719                 result = this.conditionAnd(this);
4720                 if (!result) {
4721                     return ;
4722                 }
4723                 logical = or();
4724                 if (logical) {
4725                     next = this.condition();
4726                     if (next) {
4727                         result = new(tree.Condition)(logical, result, next);
4728                     } else {
4729                         return ;
4730                     }
4731                 }
4732                 return result;
4733             },
4734             conditionAnd: function () {
4735                 var result, logical, next;
4736                 function insideCondition(me) {
4737                     return me.negatedCondition() || me.parenthesisCondition();
4738                 }
4739                 function and() {
4740                     return parserInput.$str("and");
4741                 }
4742
4743                 result = insideCondition(this);
4744                 if (!result) {
4745                     return ;
4746                 }
4747                 logical = and();
4748                 if (logical) {
4749                     next = this.conditionAnd();
4750                     if (next) {
4751                         result = new(tree.Condition)(logical, result, next);
4752                     } else {
4753                         return ;
4754                     }
4755                 }
4756                 return result;
4757             },
4758             negatedCondition: function () {
4759                 if (parserInput.$str("not")) {
4760                     var result = this.parenthesisCondition();
4761                     if (result) {
4762                         result.negate = !result.negate;
4763                     }
4764                     return result;
4765                 }
4766             },
4767             parenthesisCondition: function () {
4768                 function tryConditionFollowedByParenthesis(me) {
4769                     var body;
4770                     parserInput.save();
4771                     body = me.condition();
4772                     if (!body) {
4773                         parserInput.restore();
4774                         return ;
4775                     }
4776                     if (!parserInput.$char(')')) {
4777                         parserInput.restore();
4778                         return ;
4779                     }
4780                     parserInput.forget();
4781                     return body;
4782                 }
4783
4784                 var body;
4785                 parserInput.save();
4786                 if (!parserInput.$str("(")) {
4787                     parserInput.restore();
4788                     return ;
4789                 }
4790                 body = tryConditionFollowedByParenthesis(this);
4791                 if (body) {
4792                     parserInput.forget();
4793                     return body;
4794                 }
4795
4796                 body = this.atomicCondition();
4797                 if (!body) {
4798                     parserInput.restore();
4799                     return ;
4800                 }
4801                 if (!parserInput.$char(')')) {
4802                     parserInput.restore("expected ')' got '" + parserInput.currentChar() + "'");
4803                     return ;
4804                 }
4805                 parserInput.forget();
4806                 return body;
4807             },
4808             atomicCondition: function () {
4809                 var entities = this.entities, index = parserInput.i, a, b, c, op;
4810
4811                 a = this.addition() || entities.keyword() || entities.quoted();
4812                 if (a) {
4813                     if (parserInput.$char('>')) {
4814                         if (parserInput.$char('=')) {
4815                             op = ">=";
4816                         } else {
4817                             op = '>';
4818                         }
4819                     } else
4820                     if (parserInput.$char('<')) {
4821                         if (parserInput.$char('=')) {
4822                             op = "<=";
4823                         } else {
4824                             op = '<';
4825                         }
4826                     } else
4827                     if (parserInput.$char('=')) {
4828                         if (parserInput.$char('>')) {
4829                             op = "=>";
4830                         } else if (parserInput.$char('<')) {
4831                             op = '=<';
4832                         } else {
4833                             op = '=';
4834                         }
4835                     }
4836                     if (op) {
4837                         b = this.addition() || entities.keyword() || entities.quoted();
4838                         if (b) {
4839                             c = new(tree.Condition)(op, a, b, index, false);
4840                         } else {
4841                             error('expected expression');
4842                         }
4843                     } else {
4844                         c = new(tree.Condition)('=', a, new(tree.Keyword)('true'), index, false);
4845                     }
4846                     return c;
4847                 }
4848             },
4849
4850             //
4851             // An operand is anything that can be part of an operation,
4852             // such as a Color, or a Variable
4853             //
4854             operand: function () {
4855                 var entities = this.entities, negate;
4856
4857                 if (parserInput.peek(/^-[@\(]/)) {
4858                     negate = parserInput.$char('-');
4859                 }
4860
4861                 var o = this.sub() || entities.dimension() ||
4862                         entities.color() || entities.variable() ||
4863                         entities.call() || entities.colorKeyword();
4864
4865                 if (negate) {
4866                     o.parensInOp = true;
4867                     o = new(tree.Negative)(o);
4868                 }
4869
4870                 return o;
4871             },
4872
4873             //
4874             // Expressions either represent mathematical operations,
4875             // or white-space delimited Entities.
4876             //
4877             //     1px solid black
4878             //     @var * 2
4879             //
4880             expression: function () {
4881                 var entities = [], e, delim;
4882
4883                 do {
4884                     e = this.comment();
4885                     if (e) {
4886                         entities.push(e);
4887                         continue;
4888                     }
4889                     e = this.addition() || this.entity();
4890                     if (e) {
4891                         entities.push(e);
4892                         // operations do not allow keyword "/" dimension (e.g. small/20px) so we support that here
4893                         if (!parserInput.peek(/^\/[\/*]/)) {
4894                             delim = parserInput.$char('/');
4895                             if (delim) {
4896                                 entities.push(new(tree.Anonymous)(delim));
4897                             }
4898                         }
4899                     }
4900                 } while (e);
4901                 if (entities.length > 0) {
4902                     return new(tree.Expression)(entities);
4903                 }
4904             },
4905             property: function () {
4906                 var name = parserInput.$re(/^(\*?-?[_a-zA-Z0-9-]+)\s*:/);
4907                 if (name) {
4908                     return name[1];
4909                 }
4910             },
4911             ruleProperty: function () {
4912                 var name = [], index = [], s, k;
4913
4914                 parserInput.save();
4915
4916                 var simpleProperty = parserInput.$re(/^([_a-zA-Z0-9-]+)\s*:/);
4917                 if (simpleProperty) {
4918                     name = [new(tree.Keyword)(simpleProperty[1])];
4919                     parserInput.forget();
4920                     return name;
4921                 }
4922
4923                 function match(re) {
4924                     var i = parserInput.i,
4925                         chunk = parserInput.$re(re);
4926                     if (chunk) {
4927                         index.push(i);
4928                         return name.push(chunk[1]);
4929                     }
4930                 }
4931
4932                 match(/^(\*?)/);
4933                 while (true) {
4934                     if (!match(/^((?:[\w-]+)|(?:@\{[\w-]+\}))/)) {
4935                         break;
4936                     }
4937                 }
4938
4939                 if ((name.length > 1) && match(/^((?:\+_|\+)?)\s*:/)) {
4940                     parserInput.forget();
4941
4942                     // at last, we have the complete match now. move forward,
4943                     // convert name particles to tree objects and return:
4944                     if (name[0] === '') {
4945                         name.shift();
4946                         index.shift();
4947                     }
4948                     for (k = 0; k < name.length; k++) {
4949                         s = name[k];
4950                         name[k] = (s.charAt(0) !== '@') ?
4951                             new(tree.Keyword)(s) :
4952                             new(tree.Variable)('@' + s.slice(2, -1),
4953                                 index[k], fileInfo);
4954                     }
4955                     return name;
4956                 }
4957                 parserInput.restore();
4958             }
4959         }
4960     };
4961 };
4962 Parser.serializeVars = function(vars) {
4963     var s = '';
4964
4965     for (var name in vars) {
4966         if (Object.hasOwnProperty.call(vars, name)) {
4967             var value = vars[name];
4968             s += ((name[0] === '@') ? '' : '@') + name + ': ' + value +
4969                 ((String(value).slice(-1) === ';') ? '' : ';');
4970         }
4971     }
4972
4973     return s;
4974 };
4975
4976 module.exports = Parser;
4977
4978 },{"../less-error":32,"../tree":62,"../utils":83,"../visitors":87,"./parser-input":37}],39:[function(require,module,exports){
4979 /**
4980  * Plugin Manager
4981  */
4982 var PluginManager = function(less) {
4983     this.less = less;
4984     this.visitors = [];
4985     this.preProcessors = [];
4986     this.postProcessors = [];
4987     this.installedPlugins = [];
4988     this.fileManagers = [];
4989 };
4990 /**
4991  * Adds all the plugins in the array
4992  * @param {Array} plugins
4993  */
4994 PluginManager.prototype.addPlugins = function(plugins) {
4995     if (plugins) {
4996         for (var i = 0; i < plugins.length; i++) {
4997             this.addPlugin(plugins[i]);
4998         }
4999     }
5000 };
5001 /**
5002  *
5003  * @param plugin
5004  */
5005 PluginManager.prototype.addPlugin = function(plugin) {
5006     this.installedPlugins.push(plugin);
5007     plugin.install(this.less, this);
5008 };
5009 /**
5010  * Adds a visitor. The visitor object has options on itself to determine
5011  * when it should run.
5012  * @param visitor
5013  */
5014 PluginManager.prototype.addVisitor = function(visitor) {
5015     this.visitors.push(visitor);
5016 };
5017 /**
5018  * Adds a pre processor object
5019  * @param {object} preProcessor
5020  * @param {number} priority - guidelines 1 = before import, 1000 = import, 2000 = after import
5021  */
5022 PluginManager.prototype.addPreProcessor = function(preProcessor, priority) {
5023     var indexToInsertAt;
5024     for (indexToInsertAt = 0; indexToInsertAt < this.preProcessors.length; indexToInsertAt++) {
5025         if (this.preProcessors[indexToInsertAt].priority >= priority) {
5026             break;
5027         }
5028     }
5029     this.preProcessors.splice(indexToInsertAt, 0, {preProcessor: preProcessor, priority: priority});
5030 };
5031 /**
5032  * Adds a post processor object
5033  * @param {object} postProcessor
5034  * @param {number} priority - guidelines 1 = before compression, 1000 = compression, 2000 = after compression
5035  */
5036 PluginManager.prototype.addPostProcessor = function(postProcessor, priority) {
5037     var indexToInsertAt;
5038     for (indexToInsertAt = 0; indexToInsertAt < this.postProcessors.length; indexToInsertAt++) {
5039         if (this.postProcessors[indexToInsertAt].priority >= priority) {
5040             break;
5041         }
5042     }
5043     this.postProcessors.splice(indexToInsertAt, 0, {postProcessor: postProcessor, priority: priority});
5044 };
5045 /**
5046  *
5047  * @param manager
5048  */
5049 PluginManager.prototype.addFileManager = function(manager) {
5050     this.fileManagers.push(manager);
5051 };
5052 /**
5053  *
5054  * @returns {Array}
5055  * @private
5056  */
5057 PluginManager.prototype.getPreProcessors = function() {
5058     var preProcessors = [];
5059     for (var i = 0; i < this.preProcessors.length; i++) {
5060         preProcessors.push(this.preProcessors[i].preProcessor);
5061     }
5062     return preProcessors;
5063 };
5064 /**
5065  *
5066  * @returns {Array}
5067  * @private
5068  */
5069 PluginManager.prototype.getPostProcessors = function() {
5070     var postProcessors = [];
5071     for (var i = 0; i < this.postProcessors.length; i++) {
5072         postProcessors.push(this.postProcessors[i].postProcessor);
5073     }
5074     return postProcessors;
5075 };
5076 /**
5077  *
5078  * @returns {Array}
5079  * @private
5080  */
5081 PluginManager.prototype.getVisitors = function() {
5082     return this.visitors;
5083 };
5084 /**
5085  *
5086  * @returns {Array}
5087  * @private
5088  */
5089 PluginManager.prototype.getFileManagers = function() {
5090     return this.fileManagers;
5091 };
5092 module.exports = PluginManager;
5093
5094 },{}],40:[function(require,module,exports){
5095 var LessError = require('../less-error'),
5096     tree = require("../tree");
5097
5098 var FunctionImporter = module.exports = function FunctionImporter(context, fileInfo) {
5099     this.fileInfo = fileInfo;
5100 };
5101
5102 FunctionImporter.prototype.eval = function(contents, callback) {
5103     var loaded = {},
5104         loader,
5105         registry;
5106
5107     registry = {
5108         add: function(name, func) {
5109             loaded[name] = func;
5110         },
5111         addMultiple: function(functions) {
5112             Object.keys(functions).forEach(function(name) {
5113                 loaded[name] = functions[name];
5114             });
5115         }
5116     };
5117
5118     try {
5119         loader = new Function("functions", "tree", "fileInfo", contents);
5120         loader(registry, tree, this.fileInfo);
5121     } catch(e) {
5122         callback(new LessError({
5123             message: "Plugin evaluation error: '" + e.name + ': ' + e.message.replace(/["]/g, "'") + "'" ,
5124             filename: this.fileInfo.filename
5125         }), null );
5126     }
5127
5128     callback(null, { functions: loaded });
5129 };
5130
5131 },{"../less-error":32,"../tree":62}],41:[function(require,module,exports){
5132 var PromiseConstructor;
5133
5134 module.exports = function(environment, ParseTree, ImportManager) {
5135     var render = function (input, options, callback) {
5136         if (typeof options === 'function') {
5137             callback = options;
5138             options = {};
5139         }
5140
5141         if (!callback) {
5142             if (!PromiseConstructor) {
5143                 PromiseConstructor = typeof Promise === 'undefined' ? require('promise') : Promise;
5144             }
5145             var self = this;
5146             return new PromiseConstructor(function (resolve, reject) {
5147                 render.call(self, input, options, function(err, output) {
5148                     if (err) {
5149                         reject(err);
5150                     } else {
5151                         resolve(output);
5152                     }
5153                 });
5154             });
5155         } else {
5156             this.parse(input, options, function(err, root, imports, options) {
5157                 if (err) { return callback(err); }
5158
5159                 var result;
5160                 try {
5161                     var parseTree = new ParseTree(root, imports);
5162                     result = parseTree.toCSS(options);
5163                 }
5164                 catch (err) { return callback(err); }
5165
5166                 callback(null, result);
5167             });
5168         }
5169     };
5170
5171     return render;
5172 };
5173
5174 },{"promise":undefined}],42:[function(require,module,exports){
5175 module.exports = function (SourceMapOutput, environment) {
5176
5177     var SourceMapBuilder = function (options) {
5178         this.options = options;
5179     };
5180
5181     SourceMapBuilder.prototype.toCSS = function(rootNode, options, imports) {
5182         var sourceMapOutput = new SourceMapOutput(
5183             {
5184                 contentsIgnoredCharsMap: imports.contentsIgnoredChars,
5185                 rootNode: rootNode,
5186                 contentsMap: imports.contents,
5187                 sourceMapFilename: this.options.sourceMapFilename,
5188                 sourceMapURL: this.options.sourceMapURL,
5189                 outputFilename: this.options.sourceMapOutputFilename,
5190                 sourceMapBasepath: this.options.sourceMapBasepath,
5191                 sourceMapRootpath: this.options.sourceMapRootpath,
5192                 outputSourceFiles: this.options.outputSourceFiles,
5193                 sourceMapGenerator: this.options.sourceMapGenerator,
5194                 sourceMapFileInline: this.options.sourceMapFileInline
5195             });
5196
5197         var css = sourceMapOutput.toCSS(options);
5198         this.sourceMap = sourceMapOutput.sourceMap;
5199         this.sourceMapURL = sourceMapOutput.sourceMapURL;
5200         if (this.options.sourceMapInputFilename) {
5201             this.sourceMapInputFilename = sourceMapOutput.normalizeFilename(this.options.sourceMapInputFilename);
5202         }
5203         return css + this.getCSSAppendage();
5204     };
5205
5206     SourceMapBuilder.prototype.getCSSAppendage = function() {
5207
5208         var sourceMapURL = this.sourceMapURL;
5209         if (this.options.sourceMapFileInline) {
5210             if (this.sourceMap === undefined) {
5211                 return "";
5212             }
5213             sourceMapURL = "data:application/json;base64," + environment.encodeBase64(this.sourceMap);
5214         }
5215
5216         if (sourceMapURL) {
5217             return "/*# sourceMappingURL=" + sourceMapURL + " */";
5218         }
5219         return "";
5220     };
5221
5222     SourceMapBuilder.prototype.getExternalSourceMap = function() {
5223         return this.sourceMap;
5224     };
5225     SourceMapBuilder.prototype.setExternalSourceMap = function(sourceMap) {
5226         this.sourceMap = sourceMap;
5227     };
5228
5229     SourceMapBuilder.prototype.isInline = function() {
5230         return this.options.sourceMapFileInline;
5231     };
5232     SourceMapBuilder.prototype.getSourceMapURL = function() {
5233         return this.sourceMapURL;
5234     };
5235     SourceMapBuilder.prototype.getOutputFilename = function() {
5236         return this.options.sourceMapOutputFilename;
5237     };
5238     SourceMapBuilder.prototype.getInputFilename = function() {
5239         return this.sourceMapInputFilename;
5240     };
5241
5242     return SourceMapBuilder;
5243 };
5244
5245 },{}],43:[function(require,module,exports){
5246 module.exports = function (environment) {
5247
5248     var SourceMapOutput = function (options) {
5249         this._css = [];
5250         this._rootNode = options.rootNode;
5251         this._contentsMap = options.contentsMap;
5252         this._contentsIgnoredCharsMap = options.contentsIgnoredCharsMap;
5253         if (options.sourceMapFilename) {
5254             this._sourceMapFilename = options.sourceMapFilename.replace(/\\/g, '/');
5255         }
5256         this._outputFilename = options.outputFilename;
5257         this.sourceMapURL = options.sourceMapURL;
5258         if (options.sourceMapBasepath) {
5259             this._sourceMapBasepath = options.sourceMapBasepath.replace(/\\/g, '/');
5260         }
5261         if (options.sourceMapRootpath) {
5262             this._sourceMapRootpath = options.sourceMapRootpath.replace(/\\/g, '/');
5263             if (this._sourceMapRootpath.charAt(this._sourceMapRootpath.length - 1) !== '/') {
5264                 this._sourceMapRootpath += '/';
5265             }
5266         } else {
5267             this._sourceMapRootpath = "";
5268         }
5269         this._outputSourceFiles = options.outputSourceFiles;
5270         this._sourceMapGeneratorConstructor = environment.getSourceMapGenerator();
5271
5272         this._lineNumber = 0;
5273         this._column = 0;
5274     };
5275
5276     SourceMapOutput.prototype.normalizeFilename = function(filename) {
5277         filename = filename.replace(/\\/g, '/');
5278
5279         if (this._sourceMapBasepath && filename.indexOf(this._sourceMapBasepath) === 0) {
5280             filename = filename.substring(this._sourceMapBasepath.length);
5281             if (filename.charAt(0) === '\\' || filename.charAt(0) === '/') {
5282                 filename = filename.substring(1);
5283             }
5284         }
5285         return (this._sourceMapRootpath || "") + filename;
5286     };
5287
5288     SourceMapOutput.prototype.add = function(chunk, fileInfo, index, mapLines) {
5289
5290         //ignore adding empty strings
5291         if (!chunk) {
5292             return;
5293         }
5294
5295         var lines,
5296             sourceLines,
5297             columns,
5298             sourceColumns,
5299             i;
5300
5301         if (fileInfo) {
5302             var inputSource = this._contentsMap[fileInfo.filename];
5303
5304             // remove vars/banner added to the top of the file
5305             if (this._contentsIgnoredCharsMap[fileInfo.filename]) {
5306                 // adjust the index
5307                 index -= this._contentsIgnoredCharsMap[fileInfo.filename];
5308                 if (index < 0) { index = 0; }
5309                 // adjust the source
5310                 inputSource = inputSource.slice(this._contentsIgnoredCharsMap[fileInfo.filename]);
5311             }
5312             inputSource = inputSource.substring(0, index);
5313             sourceLines = inputSource.split("\n");
5314             sourceColumns = sourceLines[sourceLines.length - 1];
5315         }
5316
5317         lines = chunk.split("\n");
5318         columns = lines[lines.length - 1];
5319
5320         if (fileInfo) {
5321             if (!mapLines) {
5322                 this._sourceMapGenerator.addMapping({ generated: { line: this._lineNumber + 1, column: this._column},
5323                     original: { line: sourceLines.length, column: sourceColumns.length},
5324                     source: this.normalizeFilename(fileInfo.filename)});
5325             } else {
5326                 for (i = 0; i < lines.length; i++) {
5327                     this._sourceMapGenerator.addMapping({ generated: { line: this._lineNumber + i + 1, column: i === 0 ? this._column : 0},
5328                         original: { line: sourceLines.length + i, column: i === 0 ? sourceColumns.length : 0},
5329                         source: this.normalizeFilename(fileInfo.filename)});
5330                 }
5331             }
5332         }
5333
5334         if (lines.length === 1) {
5335             this._column += columns.length;
5336         } else {
5337             this._lineNumber += lines.length - 1;
5338             this._column = columns.length;
5339         }
5340
5341         this._css.push(chunk);
5342     };
5343
5344     SourceMapOutput.prototype.isEmpty = function() {
5345         return this._css.length === 0;
5346     };
5347
5348     SourceMapOutput.prototype.toCSS = function(context) {
5349         this._sourceMapGenerator = new this._sourceMapGeneratorConstructor({ file: this._outputFilename, sourceRoot: null });
5350
5351         if (this._outputSourceFiles) {
5352             for (var filename in this._contentsMap) {
5353                 if (this._contentsMap.hasOwnProperty(filename)) {
5354                     var source = this._contentsMap[filename];
5355                     if (this._contentsIgnoredCharsMap[filename]) {
5356                         source = source.slice(this._contentsIgnoredCharsMap[filename]);
5357                     }
5358                     this._sourceMapGenerator.setSourceContent(this.normalizeFilename(filename), source);
5359                 }
5360             }
5361         }
5362
5363         this._rootNode.genCSS(context, this);
5364
5365         if (this._css.length > 0) {
5366             var sourceMapURL,
5367                 sourceMapContent = JSON.stringify(this._sourceMapGenerator.toJSON());
5368
5369             if (this.sourceMapURL) {
5370                 sourceMapURL = this.sourceMapURL;
5371             } else if (this._sourceMapFilename) {
5372                 sourceMapURL = this._sourceMapFilename;
5373             }
5374             this.sourceMapURL = sourceMapURL;
5375
5376             this.sourceMap = sourceMapContent;
5377         }
5378
5379         return this._css.join('');
5380     };
5381
5382     return SourceMapOutput;
5383 };
5384
5385 },{}],44:[function(require,module,exports){
5386 var contexts = require("./contexts"),
5387     visitor = require("./visitors"),
5388     tree = require("./tree");
5389
5390 module.exports = function(root, options) {
5391     options = options || {};
5392     var evaldRoot,
5393         variables = options.variables,
5394         evalEnv = new contexts.Eval(options);
5395
5396     //
5397     // Allows setting variables with a hash, so:
5398     //
5399     //   `{ color: new tree.Color('#f01') }` will become:
5400     //
5401     //   new tree.Rule('@color',
5402     //     new tree.Value([
5403     //       new tree.Expression([
5404     //         new tree.Color('#f01')
5405     //       ])
5406     //     ])
5407     //   )
5408     //
5409     if (typeof variables === 'object' && !Array.isArray(variables)) {
5410         variables = Object.keys(variables).map(function (k) {
5411             var value = variables[k];
5412
5413             if (! (value instanceof tree.Value)) {
5414                 if (! (value instanceof tree.Expression)) {
5415                     value = new tree.Expression([value]);
5416                 }
5417                 value = new tree.Value([value]);
5418             }
5419             return new tree.Rule('@' + k, value, false, null, 0);
5420         });
5421         evalEnv.frames = [new tree.Ruleset(null, variables)];
5422     }
5423
5424     var preEvalVisitors = [],
5425         visitors = [
5426             new visitor.JoinSelectorVisitor(),
5427             new visitor.MarkVisibleSelectorsVisitor(true),
5428             new visitor.ExtendVisitor(),
5429             new visitor.ToCSSVisitor({compress: Boolean(options.compress)})
5430         ], i;
5431
5432     if (options.pluginManager) {
5433         var pluginVisitors = options.pluginManager.getVisitors();
5434         for (i = 0; i < pluginVisitors.length; i++) {
5435             var pluginVisitor = pluginVisitors[i];
5436             if (pluginVisitor.isPreEvalVisitor) {
5437                 preEvalVisitors.push(pluginVisitor);
5438             } else {
5439                 if (pluginVisitor.isPreVisitor) {
5440                     visitors.splice(0, 0, pluginVisitor);
5441                 } else {
5442                     visitors.push(pluginVisitor);
5443                 }
5444             }
5445         }
5446     }
5447
5448     for (i = 0; i < preEvalVisitors.length; i++) {
5449         preEvalVisitors[i].run(root);
5450     }
5451
5452     evaldRoot = root.eval(evalEnv);
5453
5454     for (i = 0; i < visitors.length; i++) {
5455         visitors[i].run(evaldRoot);
5456     }
5457
5458     return evaldRoot;
5459 };
5460
5461 },{"./contexts":11,"./tree":62,"./visitors":87}],45:[function(require,module,exports){
5462 var Node = require("./node");
5463
5464 var Alpha = function (val) {
5465     this.value = val;
5466 };
5467 Alpha.prototype = new Node();
5468 Alpha.prototype.type = "Alpha";
5469
5470 Alpha.prototype.accept = function (visitor) {
5471     this.value = visitor.visit(this.value);
5472 };
5473 Alpha.prototype.eval = function (context) {
5474     if (this.value.eval) { return new Alpha(this.value.eval(context)); }
5475     return this;
5476 };
5477 Alpha.prototype.genCSS = function (context, output) {
5478     output.add("alpha(opacity=");
5479
5480     if (this.value.genCSS) {
5481         this.value.genCSS(context, output);
5482     } else {
5483         output.add(this.value);
5484     }
5485
5486     output.add(")");
5487 };
5488
5489 module.exports = Alpha;
5490
5491 },{"./node":70}],46:[function(require,module,exports){
5492 var Node = require("./node");
5493
5494 var Anonymous = function (value, index, currentFileInfo, mapLines, rulesetLike, visibilityInfo) {
5495     this.value = value;
5496     this.index = index;
5497     this.mapLines = mapLines;
5498     this.currentFileInfo = currentFileInfo;
5499     this.rulesetLike = (typeof rulesetLike === 'undefined') ? false : rulesetLike;
5500     this.allowRoot = true;
5501     this.copyVisibilityInfo(visibilityInfo);
5502 };
5503 Anonymous.prototype = new Node();
5504 Anonymous.prototype.type = "Anonymous";
5505 Anonymous.prototype.eval = function () {
5506     return new Anonymous(this.value, this.index, this.currentFileInfo, this.mapLines, this.rulesetLike, this.visibilityInfo());
5507 };
5508 Anonymous.prototype.compare = function (other) {
5509     return other.toCSS && this.toCSS() === other.toCSS() ? 0 : undefined;
5510 };
5511 Anonymous.prototype.isRulesetLike = function() {
5512     return this.rulesetLike;
5513 };
5514 Anonymous.prototype.genCSS = function (context, output) {
5515     output.add(this.value, this.currentFileInfo, this.index, this.mapLines);
5516 };
5517 module.exports = Anonymous;
5518
5519 },{"./node":70}],47:[function(require,module,exports){
5520 var Node = require("./node");
5521
5522 var Assignment = function (key, val) {
5523     this.key = key;
5524     this.value = val;
5525 };
5526
5527 Assignment.prototype = new Node();
5528 Assignment.prototype.type = "Assignment";
5529 Assignment.prototype.accept = function (visitor) {
5530     this.value = visitor.visit(this.value);
5531 };
5532 Assignment.prototype.eval = function (context) {
5533     if (this.value.eval) {
5534         return new Assignment(this.key, this.value.eval(context));
5535     }
5536     return this;
5537 };
5538 Assignment.prototype.genCSS = function (context, output) {
5539     output.add(this.key + '=');
5540     if (this.value.genCSS) {
5541         this.value.genCSS(context, output);
5542     } else {
5543         output.add(this.value);
5544     }
5545 };
5546 module.exports = Assignment;
5547
5548 },{"./node":70}],48:[function(require,module,exports){
5549 var Node = require("./node");
5550
5551 var Attribute = function (key, op, value) {
5552     this.key = key;
5553     this.op = op;
5554     this.value = value;
5555 };
5556 Attribute.prototype = new Node();
5557 Attribute.prototype.type = "Attribute";
5558 Attribute.prototype.eval = function (context) {
5559     return new Attribute(this.key.eval ? this.key.eval(context) : this.key,
5560         this.op, (this.value && this.value.eval) ? this.value.eval(context) : this.value);
5561 };
5562 Attribute.prototype.genCSS = function (context, output) {
5563     output.add(this.toCSS(context));
5564 };
5565 Attribute.prototype.toCSS = function (context) {
5566     var value = this.key.toCSS ? this.key.toCSS(context) : this.key;
5567
5568     if (this.op) {
5569         value += this.op;
5570         value += (this.value.toCSS ? this.value.toCSS(context) : this.value);
5571     }
5572
5573     return '[' + value + ']';
5574 };
5575 module.exports = Attribute;
5576
5577 },{"./node":70}],49:[function(require,module,exports){
5578 var Node = require("./node"),
5579     FunctionCaller = require("../functions/function-caller");
5580 //
5581 // A function call node.
5582 //
5583 var Call = function (name, args, index, currentFileInfo) {
5584     this.name = name;
5585     this.args = args;
5586     this.index = index;
5587     this.currentFileInfo = currentFileInfo;
5588 };
5589 Call.prototype = new Node();
5590 Call.prototype.type = "Call";
5591 Call.prototype.accept = function (visitor) {
5592     if (this.args) {
5593         this.args = visitor.visitArray(this.args);
5594     }
5595 };
5596 //
5597 // When evaluating a function call,
5598 // we either find the function in the functionRegistry,
5599 // in which case we call it, passing the  evaluated arguments,
5600 // if this returns null or we cannot find the function, we
5601 // simply print it out as it appeared originally [2].
5602 //
5603 // The reason why we evaluate the arguments, is in the case where
5604 // we try to pass a variable to a function, like: `saturate(@color)`.
5605 // The function should receive the value, not the variable.
5606 //
5607 Call.prototype.eval = function (context) {
5608     var args = this.args.map(function (a) { return a.eval(context); }),
5609         result, funcCaller = new FunctionCaller(this.name, context, this.index, this.currentFileInfo);
5610
5611     if (funcCaller.isValid()) {
5612         try {
5613             result = funcCaller.call(args);
5614         } catch (e) {
5615             throw { type: e.type || "Runtime",
5616                     message: "error evaluating function `" + this.name + "`" +
5617                              (e.message ? ': ' + e.message : ''),
5618                     index: this.index, filename: this.currentFileInfo.filename };
5619         }
5620
5621         if (result != null) {
5622             result.index = this.index;
5623             result.currentFileInfo = this.currentFileInfo;
5624             return result;
5625         }
5626     }
5627
5628     return new Call(this.name, args, this.index, this.currentFileInfo);
5629 };
5630 Call.prototype.genCSS = function (context, output) {
5631     output.add(this.name + "(", this.currentFileInfo, this.index);
5632
5633     for (var i = 0; i < this.args.length; i++) {
5634         this.args[i].genCSS(context, output);
5635         if (i + 1 < this.args.length) {
5636             output.add(", ");
5637         }
5638     }
5639
5640     output.add(")");
5641 };
5642 module.exports = Call;
5643
5644 },{"../functions/function-caller":21,"./node":70}],50:[function(require,module,exports){
5645 var Node = require("./node"),
5646     colors = require("../data/colors");
5647
5648 //
5649 // RGB Colors - #ff0014, #eee
5650 //
5651 var Color = function (rgb, a, originalForm) {
5652     //
5653     // The end goal here, is to parse the arguments
5654     // into an integer triplet, such as `128, 255, 0`
5655     //
5656     // This facilitates operations and conversions.
5657     //
5658     if (Array.isArray(rgb)) {
5659         this.rgb = rgb;
5660     } else if (rgb.length == 6) {
5661         this.rgb = rgb.match(/.{2}/g).map(function (c) {
5662             return parseInt(c, 16);
5663         });
5664     } else {
5665         this.rgb = rgb.split('').map(function (c) {
5666             return parseInt(c + c, 16);
5667         });
5668     }
5669     this.alpha = typeof a === 'number' ? a : 1;
5670     if (typeof originalForm !== 'undefined') {
5671         this.value = originalForm;
5672     }
5673 };
5674
5675 Color.prototype = new Node();
5676 Color.prototype.type = "Color";
5677
5678 function clamp(v, max) {
5679     return Math.min(Math.max(v, 0), max);
5680 }
5681
5682 function toHex(v) {
5683     return '#' + v.map(function (c) {
5684         c = clamp(Math.round(c), 255);
5685         return (c < 16 ? '0' : '') + c.toString(16);
5686     }).join('');
5687 }
5688
5689 Color.prototype.luma = function () {
5690     var r = this.rgb[0] / 255,
5691         g = this.rgb[1] / 255,
5692         b = this.rgb[2] / 255;
5693
5694     r = (r <= 0.03928) ? r / 12.92 : Math.pow(((r + 0.055) / 1.055), 2.4);
5695     g = (g <= 0.03928) ? g / 12.92 : Math.pow(((g + 0.055) / 1.055), 2.4);
5696     b = (b <= 0.03928) ? b / 12.92 : Math.pow(((b + 0.055) / 1.055), 2.4);
5697
5698     return 0.2126 * r + 0.7152 * g + 0.0722 * b;
5699 };
5700 Color.prototype.genCSS = function (context, output) {
5701     output.add(this.toCSS(context));
5702 };
5703 Color.prototype.toCSS = function (context, doNotCompress) {
5704     var compress = context && context.compress && !doNotCompress, color, alpha;
5705
5706     // `value` is set if this color was originally
5707     // converted from a named color string so we need
5708     // to respect this and try to output named color too.
5709     if (this.value) {
5710         return this.value;
5711     }
5712
5713     // If we have some transparency, the only way to represent it
5714     // is via `rgba`. Otherwise, we use the hex representation,
5715     // which has better compatibility with older browsers.
5716     // Values are capped between `0` and `255`, rounded and zero-padded.
5717     alpha = this.fround(context, this.alpha);
5718     if (alpha < 1) {
5719         return "rgba(" + this.rgb.map(function (c) {
5720             return clamp(Math.round(c), 255);
5721         }).concat(clamp(alpha, 1))
5722             .join(',' + (compress ? '' : ' ')) + ")";
5723     }
5724
5725     color = this.toRGB();
5726
5727     if (compress) {
5728         var splitcolor = color.split('');
5729
5730         // Convert color to short format
5731         if (splitcolor[1] === splitcolor[2] && splitcolor[3] === splitcolor[4] && splitcolor[5] === splitcolor[6]) {
5732             color = '#' + splitcolor[1] + splitcolor[3] + splitcolor[5];
5733         }
5734     }
5735
5736     return color;
5737 };
5738
5739 //
5740 // Operations have to be done per-channel, if not,
5741 // channels will spill onto each other. Once we have
5742 // our result, in the form of an integer triplet,
5743 // we create a new Color node to hold the result.
5744 //
5745 Color.prototype.operate = function (context, op, other) {
5746     var rgb = [];
5747     var alpha = this.alpha * (1 - other.alpha) + other.alpha;
5748     for (var c = 0; c < 3; c++) {
5749         rgb[c] = this._operate(context, op, this.rgb[c], other.rgb[c]);
5750     }
5751     return new Color(rgb, alpha);
5752 };
5753 Color.prototype.toRGB = function () {
5754     return toHex(this.rgb);
5755 };
5756 Color.prototype.toHSL = function () {
5757     var r = this.rgb[0] / 255,
5758         g = this.rgb[1] / 255,
5759         b = this.rgb[2] / 255,
5760         a = this.alpha;
5761
5762     var max = Math.max(r, g, b), min = Math.min(r, g, b);
5763     var h, s, l = (max + min) / 2, d = max - min;
5764
5765     if (max === min) {
5766         h = s = 0;
5767     } else {
5768         s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
5769
5770         switch (max) {
5771             case r: h = (g - b) / d + (g < b ? 6 : 0); break;
5772             case g: h = (b - r) / d + 2;               break;
5773             case b: h = (r - g) / d + 4;               break;
5774         }
5775         h /= 6;
5776     }
5777     return { h: h * 360, s: s, l: l, a: a };
5778 };
5779 //Adapted from http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript
5780 Color.prototype.toHSV = function () {
5781     var r = this.rgb[0] / 255,
5782         g = this.rgb[1] / 255,
5783         b = this.rgb[2] / 255,
5784         a = this.alpha;
5785
5786     var max = Math.max(r, g, b), min = Math.min(r, g, b);
5787     var h, s, v = max;
5788
5789     var d = max - min;
5790     if (max === 0) {
5791         s = 0;
5792     } else {
5793         s = d / max;
5794     }
5795
5796     if (max === min) {
5797         h = 0;
5798     } else {
5799         switch(max) {
5800             case r: h = (g - b) / d + (g < b ? 6 : 0); break;
5801             case g: h = (b - r) / d + 2; break;
5802             case b: h = (r - g) / d + 4; break;
5803         }
5804         h /= 6;
5805     }
5806     return { h: h * 360, s: s, v: v, a: a };
5807 };
5808 Color.prototype.toARGB = function () {
5809     return toHex([this.alpha * 255].concat(this.rgb));
5810 };
5811 Color.prototype.compare = function (x) {
5812     return (x.rgb &&
5813         x.rgb[0] === this.rgb[0] &&
5814         x.rgb[1] === this.rgb[1] &&
5815         x.rgb[2] === this.rgb[2] &&
5816         x.alpha  === this.alpha) ? 0 : undefined;
5817 };
5818
5819 Color.fromKeyword = function(keyword) {
5820     var c, key = keyword.toLowerCase();
5821     if (colors.hasOwnProperty(key)) {
5822         c = new Color(colors[key].slice(1));
5823     }
5824     else if (key === "transparent") {
5825         c = new Color([0, 0, 0], 0);
5826     }
5827
5828     if (c) {
5829         c.value = keyword;
5830         return c;
5831     }
5832 };
5833 module.exports = Color;
5834
5835 },{"../data/colors":12,"./node":70}],51:[function(require,module,exports){
5836 var Node = require("./node");
5837
5838 var Combinator = function (value) {
5839     if (value === ' ') {
5840         this.value = ' ';
5841         this.emptyOrWhitespace = true;
5842     } else {
5843         this.value = value ? value.trim() : "";
5844         this.emptyOrWhitespace = this.value === "";
5845     }
5846 };
5847 Combinator.prototype = new Node();
5848 Combinator.prototype.type = "Combinator";
5849 var _noSpaceCombinators = {
5850     '': true,
5851     ' ': true,
5852     '|': true
5853 };
5854 Combinator.prototype.genCSS = function (context, output) {
5855     var spaceOrEmpty = (context.compress || _noSpaceCombinators[this.value]) ? '' : ' ';
5856     output.add(spaceOrEmpty + this.value + spaceOrEmpty);
5857 };
5858 module.exports = Combinator;
5859
5860 },{"./node":70}],52:[function(require,module,exports){
5861 var Node = require("./node"),
5862     getDebugInfo = require("./debug-info");
5863
5864 var Comment = function (value, isLineComment, index, currentFileInfo) {
5865     this.value = value;
5866     this.isLineComment = isLineComment;
5867     this.index = index;
5868     this.currentFileInfo = currentFileInfo;
5869     this.allowRoot = true;
5870 };
5871 Comment.prototype = new Node();
5872 Comment.prototype.type = "Comment";
5873 Comment.prototype.genCSS = function (context, output) {
5874     if (this.debugInfo) {
5875         output.add(getDebugInfo(context, this), this.currentFileInfo, this.index);
5876     }
5877     output.add(this.value);
5878 };
5879 Comment.prototype.isSilent = function(context) {
5880     var isCompressed = context.compress && this.value[2] !== "!";
5881     return this.isLineComment || isCompressed;
5882 };
5883 module.exports = Comment;
5884
5885 },{"./debug-info":54,"./node":70}],53:[function(require,module,exports){
5886 var Node = require("./node");
5887
5888 var Condition = function (op, l, r, i, negate) {
5889     this.op = op.trim();
5890     this.lvalue = l;
5891     this.rvalue = r;
5892     this.index = i;
5893     this.negate = negate;
5894 };
5895 Condition.prototype = new Node();
5896 Condition.prototype.type = "Condition";
5897 Condition.prototype.accept = function (visitor) {
5898     this.lvalue = visitor.visit(this.lvalue);
5899     this.rvalue = visitor.visit(this.rvalue);
5900 };
5901 Condition.prototype.eval = function (context) {
5902     var result = (function (op, a, b) {
5903         switch (op) {
5904             case 'and': return a && b;
5905             case 'or':  return a || b;
5906             default:
5907                 switch (Node.compare(a, b)) {
5908                     case -1:
5909                         return op === '<' || op === '=<' || op === '<=';
5910                     case 0:
5911                         return op === '=' || op === '>=' || op === '=<' || op === '<=';
5912                     case 1:
5913                         return op === '>' || op === '>=';
5914                     default:
5915                         return false;
5916                 }
5917         }
5918     })(this.op, this.lvalue.eval(context), this.rvalue.eval(context));
5919
5920     return this.negate ? !result : result;
5921 };
5922 module.exports = Condition;
5923
5924 },{"./node":70}],54:[function(require,module,exports){
5925 var debugInfo = function(context, ctx, lineSeparator) {
5926     var result = "";
5927     if (context.dumpLineNumbers && !context.compress) {
5928         switch(context.dumpLineNumbers) {
5929             case 'comments':
5930                 result = debugInfo.asComment(ctx);
5931                 break;
5932             case 'mediaquery':
5933                 result = debugInfo.asMediaQuery(ctx);
5934                 break;
5935             case 'all':
5936                 result = debugInfo.asComment(ctx) + (lineSeparator || "") + debugInfo.asMediaQuery(ctx);
5937                 break;
5938         }
5939     }
5940     return result;
5941 };
5942
5943 debugInfo.asComment = function(ctx) {
5944     return '/* line ' + ctx.debugInfo.lineNumber + ', ' + ctx.debugInfo.fileName + ' */\n';
5945 };
5946
5947 debugInfo.asMediaQuery = function(ctx) {
5948     var filenameWithProtocol = ctx.debugInfo.fileName;
5949     if (!/^[a-z]+:\/\//i.test(filenameWithProtocol)) {
5950         filenameWithProtocol = 'file://' + filenameWithProtocol;
5951     }
5952     return '@media -sass-debug-info{filename{font-family:' +
5953         filenameWithProtocol.replace(/([.:\/\\])/g, function (a) {
5954             if (a == '\\') {
5955                 a = '\/';
5956             }
5957             return '\\' + a;
5958         }) +
5959         '}line{font-family:\\00003' + ctx.debugInfo.lineNumber + '}}\n';
5960 };
5961
5962 module.exports = debugInfo;
5963
5964 },{}],55:[function(require,module,exports){
5965 var Node = require("./node"),
5966     contexts = require("../contexts");
5967
5968 var DetachedRuleset = function (ruleset, frames) {
5969     this.ruleset = ruleset;
5970     this.frames = frames;
5971 };
5972 DetachedRuleset.prototype = new Node();
5973 DetachedRuleset.prototype.type = "DetachedRuleset";
5974 DetachedRuleset.prototype.evalFirst = true;
5975 DetachedRuleset.prototype.accept = function (visitor) {
5976     this.ruleset = visitor.visit(this.ruleset);
5977 };
5978 DetachedRuleset.prototype.eval = function (context) {
5979     var frames = this.frames || context.frames.slice(0);
5980     return new DetachedRuleset(this.ruleset, frames);
5981 };
5982 DetachedRuleset.prototype.callEval = function (context) {
5983     return this.ruleset.eval(this.frames ? new contexts.Eval(context, this.frames.concat(context.frames)) : context);
5984 };
5985 module.exports = DetachedRuleset;
5986
5987 },{"../contexts":11,"./node":70}],56:[function(require,module,exports){
5988 var Node = require("./node"),
5989     unitConversions = require("../data/unit-conversions"),
5990     Unit = require("./unit"),
5991     Color = require("./color");
5992
5993 //
5994 // A number with a unit
5995 //
5996 var Dimension = function (value, unit) {
5997     this.value = parseFloat(value);
5998     this.unit = (unit && unit instanceof Unit) ? unit :
5999       new Unit(unit ? [unit] : undefined);
6000 };
6001
6002 Dimension.prototype = new Node();
6003 Dimension.prototype.type = "Dimension";
6004 Dimension.prototype.accept = function (visitor) {
6005     this.unit = visitor.visit(this.unit);
6006 };
6007 Dimension.prototype.eval = function (context) {
6008     return this;
6009 };
6010 Dimension.prototype.toColor = function () {
6011     return new Color([this.value, this.value, this.value]);
6012 };
6013 Dimension.prototype.genCSS = function (context, output) {
6014     if ((context && context.strictUnits) && !this.unit.isSingular()) {
6015         throw new Error("Multiple units in dimension. Correct the units or use the unit function. Bad unit: " + this.unit.toString());
6016     }
6017
6018     var value = this.fround(context, this.value),
6019         strValue = String(value);
6020
6021     if (value !== 0 && value < 0.000001 && value > -0.000001) {
6022         // would be output 1e-6 etc.
6023         strValue = value.toFixed(20).replace(/0+$/, "");
6024     }
6025
6026     if (context && context.compress) {
6027         // Zero values doesn't need a unit
6028         if (value === 0 && this.unit.isLength()) {
6029             output.add(strValue);
6030             return;
6031         }
6032
6033         // Float values doesn't need a leading zero
6034         if (value > 0 && value < 1) {
6035             strValue = (strValue).substr(1);
6036         }
6037     }
6038
6039     output.add(strValue);
6040     this.unit.genCSS(context, output);
6041 };
6042
6043 // In an operation between two Dimensions,
6044 // we default to the first Dimension's unit,
6045 // so `1px + 2` will yield `3px`.
6046 Dimension.prototype.operate = function (context, op, other) {
6047     /*jshint noempty:false */
6048     var value = this._operate(context, op, this.value, other.value),
6049         unit = this.unit.clone();
6050
6051     if (op === '+' || op === '-') {
6052         if (unit.numerator.length === 0 && unit.denominator.length === 0) {
6053             unit = other.unit.clone();
6054             if (this.unit.backupUnit) {
6055                 unit.backupUnit = this.unit.backupUnit;
6056             }
6057         } else if (other.unit.numerator.length === 0 && unit.denominator.length === 0) {
6058             // do nothing
6059         } else {
6060             other = other.convertTo(this.unit.usedUnits());
6061
6062             if (context.strictUnits && other.unit.toString() !== unit.toString()) {
6063                 throw new Error("Incompatible units. Change the units or use the unit function. Bad units: '" + unit.toString() +
6064                     "' and '" + other.unit.toString() + "'.");
6065             }
6066
6067             value = this._operate(context, op, this.value, other.value);
6068         }
6069     } else if (op === '*') {
6070         unit.numerator = unit.numerator.concat(other.unit.numerator).sort();
6071         unit.denominator = unit.denominator.concat(other.unit.denominator).sort();
6072         unit.cancel();
6073     } else if (op === '/') {
6074         unit.numerator = unit.numerator.concat(other.unit.denominator).sort();
6075         unit.denominator = unit.denominator.concat(other.unit.numerator).sort();
6076         unit.cancel();
6077     }
6078     return new Dimension(value, unit);
6079 };
6080 Dimension.prototype.compare = function (other) {
6081     var a, b;
6082
6083     if (!(other instanceof Dimension)) {
6084         return undefined;
6085     }
6086
6087     if (this.unit.isEmpty() || other.unit.isEmpty()) {
6088         a = this;
6089         b = other;
6090     } else {
6091         a = this.unify();
6092         b = other.unify();
6093         if (a.unit.compare(b.unit) !== 0) {
6094             return undefined;
6095         }
6096     }
6097
6098     return Node.numericCompare(a.value, b.value);
6099 };
6100 Dimension.prototype.unify = function () {
6101     return this.convertTo({ length: 'px', duration: 's', angle: 'rad' });
6102 };
6103 Dimension.prototype.convertTo = function (conversions) {
6104     var value = this.value, unit = this.unit.clone(),
6105         i, groupName, group, targetUnit, derivedConversions = {}, applyUnit;
6106
6107     if (typeof conversions === 'string') {
6108         for (i in unitConversions) {
6109             if (unitConversions[i].hasOwnProperty(conversions)) {
6110                 derivedConversions = {};
6111                 derivedConversions[i] = conversions;
6112             }
6113         }
6114         conversions = derivedConversions;
6115     }
6116     applyUnit = function (atomicUnit, denominator) {
6117         /* jshint loopfunc:true */
6118         if (group.hasOwnProperty(atomicUnit)) {
6119             if (denominator) {
6120                 value = value / (group[atomicUnit] / group[targetUnit]);
6121             } else {
6122                 value = value * (group[atomicUnit] / group[targetUnit]);
6123             }
6124
6125             return targetUnit;
6126         }
6127
6128         return atomicUnit;
6129     };
6130
6131     for (groupName in conversions) {
6132         if (conversions.hasOwnProperty(groupName)) {
6133             targetUnit = conversions[groupName];
6134             group = unitConversions[groupName];
6135
6136             unit.map(applyUnit);
6137         }
6138     }
6139
6140     unit.cancel();
6141
6142     return new Dimension(value, unit);
6143 };
6144 module.exports = Dimension;
6145
6146 },{"../data/unit-conversions":14,"./color":50,"./node":70,"./unit":79}],57:[function(require,module,exports){
6147 var Node = require("./node"),
6148     Selector = require("./selector"),
6149     Ruleset = require("./ruleset");
6150
6151 var Directive = function (name, value, rules, index, currentFileInfo, debugInfo, isRooted, visibilityInfo) {
6152     var i;
6153
6154     this.name  = name;
6155     this.value = value;
6156     if (rules) {
6157         if (Array.isArray(rules)) {
6158             this.rules = rules;
6159         } else {
6160             this.rules = [rules];
6161             this.rules[0].selectors = (new Selector([], null, null, this.index, currentFileInfo)).createEmptySelectors();
6162         }
6163         for (i = 0; i < this.rules.length; i++) {
6164             this.rules[i].allowImports = true;
6165         }
6166     }
6167     this.index = index;
6168     this.currentFileInfo = currentFileInfo;
6169     this.debugInfo = debugInfo;
6170     this.isRooted = isRooted || false;
6171     this.copyVisibilityInfo(visibilityInfo);
6172     this.allowRoot = true;
6173 };
6174
6175 Directive.prototype = new Node();
6176 Directive.prototype.type = "Directive";
6177 Directive.prototype.accept = function (visitor) {
6178     var value = this.value, rules = this.rules;
6179     if (rules) {
6180         this.rules = visitor.visitArray(rules);
6181     }
6182     if (value) {
6183         this.value = visitor.visit(value);
6184     }
6185 };
6186 Directive.prototype.isRulesetLike = function() {
6187     return this.rules || !this.isCharset();
6188 };
6189 Directive.prototype.isCharset = function() {
6190     return "@charset" === this.name;
6191 };
6192 Directive.prototype.genCSS = function (context, output) {
6193     var value = this.value, rules = this.rules;
6194     output.add(this.name, this.currentFileInfo, this.index);
6195     if (value) {
6196         output.add(' ');
6197         value.genCSS(context, output);
6198     }
6199     if (rules) {
6200         this.outputRuleset(context, output, rules);
6201     } else {
6202         output.add(';');
6203     }
6204 };
6205 Directive.prototype.eval = function (context) {
6206     var mediaPathBackup, mediaBlocksBackup, value = this.value, rules = this.rules;
6207
6208     //media stored inside other directive should not bubble over it
6209     //backpup media bubbling information
6210     mediaPathBackup = context.mediaPath;
6211     mediaBlocksBackup = context.mediaBlocks;
6212     //deleted media bubbling information
6213     context.mediaPath = [];
6214     context.mediaBlocks = [];
6215
6216     if (value) {
6217         value = value.eval(context);
6218     }
6219     if (rules) {
6220         // assuming that there is only one rule at this point - that is how parser constructs the rule
6221         rules = [rules[0].eval(context)];
6222         rules[0].root = true;
6223     }
6224     //restore media bubbling information
6225     context.mediaPath = mediaPathBackup;
6226     context.mediaBlocks = mediaBlocksBackup;
6227
6228     return new Directive(this.name, value, rules,
6229         this.index, this.currentFileInfo, this.debugInfo, this.isRooted, this.visibilityInfo());
6230 };
6231 Directive.prototype.variable = function (name) {
6232     if (this.rules) {
6233         // assuming that there is only one rule at this point - that is how parser constructs the rule
6234         return Ruleset.prototype.variable.call(this.rules[0], name);
6235     }
6236 };
6237 Directive.prototype.find = function () {
6238     if (this.rules) {
6239         // assuming that there is only one rule at this point - that is how parser constructs the rule
6240         return Ruleset.prototype.find.apply(this.rules[0], arguments);
6241     }
6242 };
6243 Directive.prototype.rulesets = function () {
6244     if (this.rules) {
6245         // assuming that there is only one rule at this point - that is how parser constructs the rule
6246         return Ruleset.prototype.rulesets.apply(this.rules[0]);
6247     }
6248 };
6249 Directive.prototype.outputRuleset = function (context, output, rules) {
6250     var ruleCnt = rules.length, i;
6251     context.tabLevel = (context.tabLevel | 0) + 1;
6252
6253     // Compressed
6254     if (context.compress) {
6255         output.add('{');
6256         for (i = 0; i < ruleCnt; i++) {
6257             rules[i].genCSS(context, output);
6258         }
6259         output.add('}');
6260         context.tabLevel--;
6261         return;
6262     }
6263
6264     // Non-compressed
6265     var tabSetStr = '\n' + Array(context.tabLevel).join("  "), tabRuleStr = tabSetStr + "  ";
6266     if (!ruleCnt) {
6267         output.add(" {" + tabSetStr + '}');
6268     } else {
6269         output.add(" {" + tabRuleStr);
6270         rules[0].genCSS(context, output);
6271         for (i = 1; i < ruleCnt; i++) {
6272             output.add(tabRuleStr);
6273             rules[i].genCSS(context, output);
6274         }
6275         output.add(tabSetStr + '}');
6276     }
6277
6278     context.tabLevel--;
6279 };
6280 module.exports = Directive;
6281
6282 },{"./node":70,"./ruleset":76,"./selector":77}],58:[function(require,module,exports){
6283 var Node = require("./node"),
6284     Paren = require("./paren"),
6285     Combinator = require("./combinator");
6286
6287 var Element = function (combinator, value, index, currentFileInfo, info) {
6288     this.combinator = combinator instanceof Combinator ?
6289                       combinator : new Combinator(combinator);
6290
6291     if (typeof value === 'string') {
6292         this.value = value.trim();
6293     } else if (value) {
6294         this.value = value;
6295     } else {
6296         this.value = "";
6297     }
6298     this.index = index;
6299     this.currentFileInfo = currentFileInfo;
6300     this.copyVisibilityInfo(info);
6301 };
6302 Element.prototype = new Node();
6303 Element.prototype.type = "Element";
6304 Element.prototype.accept = function (visitor) {
6305     var value = this.value;
6306     this.combinator = visitor.visit(this.combinator);
6307     if (typeof value === "object") {
6308         this.value = visitor.visit(value);
6309     }
6310 };
6311 Element.prototype.eval = function (context) {
6312     return new Element(this.combinator,
6313                              this.value.eval ? this.value.eval(context) : this.value,
6314                              this.index,
6315                              this.currentFileInfo, this.visibilityInfo());
6316 };
6317 Element.prototype.clone = function () {
6318     return new Element(this.combinator,
6319         this.value,
6320         this.index,
6321         this.currentFileInfo, this.visibilityInfo());
6322 };
6323 Element.prototype.genCSS = function (context, output) {
6324     output.add(this.toCSS(context), this.currentFileInfo, this.index);
6325 };
6326 Element.prototype.toCSS = function (context) {
6327     context = context || {};
6328     var value = this.value, firstSelector = context.firstSelector;
6329     if (value instanceof Paren) {
6330         // selector in parens should not be affected by outer selector
6331         // flags (breaks only interpolated selectors - see #1973)
6332         context.firstSelector = true;
6333     }
6334     value = value.toCSS ? value.toCSS(context) : value;
6335     context.firstSelector = firstSelector;
6336     if (value === '' && this.combinator.value.charAt(0) === '&') {
6337         return '';
6338     } else {
6339         return this.combinator.toCSS(context) + value;
6340     }
6341 };
6342 module.exports = Element;
6343
6344 },{"./combinator":51,"./node":70,"./paren":72}],59:[function(require,module,exports){
6345 var Node = require("./node"),
6346     Paren = require("./paren"),
6347     Comment = require("./comment");
6348
6349 var Expression = function (value) {
6350     this.value = value;
6351     if (!value) {
6352         throw new Error("Expression requires an array parameter");
6353     }
6354 };
6355 Expression.prototype = new Node();
6356 Expression.prototype.type = "Expression";
6357 Expression.prototype.accept = function (visitor) {
6358     this.value = visitor.visitArray(this.value);
6359 };
6360 Expression.prototype.eval = function (context) {
6361     var returnValue,
6362         inParenthesis = this.parens && !this.parensInOp,
6363         doubleParen = false;
6364     if (inParenthesis) {
6365         context.inParenthesis();
6366     }
6367     if (this.value.length > 1) {
6368         returnValue = new Expression(this.value.map(function (e) {
6369             return e.eval(context);
6370         }));
6371     } else if (this.value.length === 1) {
6372         if (this.value[0].parens && !this.value[0].parensInOp) {
6373             doubleParen = true;
6374         }
6375         returnValue = this.value[0].eval(context);
6376     } else {
6377         returnValue = this;
6378     }
6379     if (inParenthesis) {
6380         context.outOfParenthesis();
6381     }
6382     if (this.parens && this.parensInOp && !(context.isMathOn()) && !doubleParen) {
6383         returnValue = new Paren(returnValue);
6384     }
6385     return returnValue;
6386 };
6387 Expression.prototype.genCSS = function (context, output) {
6388     for (var i = 0; i < this.value.length; i++) {
6389         this.value[i].genCSS(context, output);
6390         if (i + 1 < this.value.length) {
6391             output.add(" ");
6392         }
6393     }
6394 };
6395 Expression.prototype.throwAwayComments = function () {
6396     this.value = this.value.filter(function(v) {
6397         return !(v instanceof Comment);
6398     });
6399 };
6400 module.exports = Expression;
6401
6402 },{"./comment":52,"./node":70,"./paren":72}],60:[function(require,module,exports){
6403 var Node = require("./node"),
6404     Selector = require("./selector");
6405
6406 var Extend = function Extend(selector, option, index, currentFileInfo, visibilityInfo) {
6407     this.selector = selector;
6408     this.option = option;
6409     this.index = index;
6410     this.object_id = Extend.next_id++;
6411     this.parent_ids = [this.object_id];
6412     this.currentFileInfo = currentFileInfo || {};
6413     this.copyVisibilityInfo(visibilityInfo);
6414     this.allowRoot = true;
6415
6416     switch(option) {
6417         case "all":
6418             this.allowBefore = true;
6419             this.allowAfter = true;
6420             break;
6421         default:
6422             this.allowBefore = false;
6423             this.allowAfter = false;
6424             break;
6425     }
6426 };
6427 Extend.next_id = 0;
6428
6429 Extend.prototype = new Node();
6430 Extend.prototype.type = "Extend";
6431 Extend.prototype.accept = function (visitor) {
6432     this.selector = visitor.visit(this.selector);
6433 };
6434 Extend.prototype.eval = function (context) {
6435     return new Extend(this.selector.eval(context), this.option, this.index, this.currentFileInfo, this.visibilityInfo());
6436 };
6437 Extend.prototype.clone = function (context) {
6438     return new Extend(this.selector, this.option, this.index, this.currentFileInfo, this.visibilityInfo());
6439 };
6440 //it concatenates (joins) all selectors in selector array
6441 Extend.prototype.findSelfSelectors = function (selectors) {
6442     var selfElements = [],
6443         i,
6444         selectorElements;
6445
6446     for (i = 0; i < selectors.length; i++) {
6447         selectorElements = selectors[i].elements;
6448         // duplicate the logic in genCSS function inside the selector node.
6449         // future TODO - move both logics into the selector joiner visitor
6450         if (i > 0 && selectorElements.length && selectorElements[0].combinator.value === "") {
6451             selectorElements[0].combinator.value = ' ';
6452         }
6453         selfElements = selfElements.concat(selectors[i].elements);
6454     }
6455
6456     this.selfSelectors = [new Selector(selfElements)];
6457     this.selfSelectors[0].copyVisibilityInfo(this.visibilityInfo());
6458 };
6459 module.exports = Extend;
6460
6461 },{"./node":70,"./selector":77}],61:[function(require,module,exports){
6462 var Node = require("./node"),
6463     Media = require("./media"),
6464     URL = require("./url"),
6465     Quoted = require("./quoted"),
6466     Ruleset = require("./ruleset"),
6467     Anonymous = require("./anonymous");
6468
6469 //
6470 // CSS @import node
6471 //
6472 // The general strategy here is that we don't want to wait
6473 // for the parsing to be completed, before we start importing
6474 // the file. That's because in the context of a browser,
6475 // most of the time will be spent waiting for the server to respond.
6476 //
6477 // On creation, we push the import path to our import queue, though
6478 // `import,push`, we also pass it a callback, which it'll call once
6479 // the file has been fetched, and parsed.
6480 //
6481 var Import = function (path, features, options, index, currentFileInfo, visibilityInfo) {
6482     this.options = options;
6483     this.index = index;
6484     this.path = path;
6485     this.features = features;
6486     this.currentFileInfo = currentFileInfo;
6487     this.allowRoot = true;
6488
6489     if (this.options.less !== undefined || this.options.inline) {
6490         this.css = !this.options.less || this.options.inline;
6491     } else {
6492         var pathValue = this.getPath();
6493         if (pathValue && /[#\.\&\?\/]css([\?;].*)?$/.test(pathValue)) {
6494             this.css = true;
6495         }
6496     }
6497     this.copyVisibilityInfo(visibilityInfo);
6498 };
6499
6500 //
6501 // The actual import node doesn't return anything, when converted to CSS.
6502 // The reason is that it's used at the evaluation stage, so that the rules
6503 // it imports can be treated like any other rules.
6504 //
6505 // In `eval`, we make sure all Import nodes get evaluated, recursively, so
6506 // we end up with a flat structure, which can easily be imported in the parent
6507 // ruleset.
6508 //
6509 Import.prototype = new Node();
6510 Import.prototype.type = "Import";
6511 Import.prototype.accept = function (visitor) {
6512     if (this.features) {
6513         this.features = visitor.visit(this.features);
6514     }
6515     this.path = visitor.visit(this.path);
6516     if (!this.options.plugin && !this.options.inline && this.root) {
6517         this.root = visitor.visit(this.root);
6518     }
6519 };
6520 Import.prototype.genCSS = function (context, output) {
6521     if (this.css && this.path.currentFileInfo.reference === undefined) {
6522         output.add("@import ", this.currentFileInfo, this.index);
6523         this.path.genCSS(context, output);
6524         if (this.features) {
6525             output.add(" ");
6526             this.features.genCSS(context, output);
6527         }
6528         output.add(';');
6529     }
6530 };
6531 Import.prototype.getPath = function () {
6532     return (this.path instanceof URL) ?
6533         this.path.value.value : this.path.value;
6534 };
6535 Import.prototype.isVariableImport = function () {
6536     var path = this.path;
6537     if (path instanceof URL) {
6538         path = path.value;
6539     }
6540     if (path instanceof Quoted) {
6541         return path.containsVariables();
6542     }
6543
6544     return true;
6545 };
6546 Import.prototype.evalForImport = function (context) {
6547     var path = this.path;
6548
6549     if (path instanceof URL) {
6550         path = path.value;
6551     }
6552
6553     return new Import(path.eval(context), this.features, this.options, this.index, this.currentFileInfo, this.visibilityInfo());
6554 };
6555 Import.prototype.evalPath = function (context) {
6556     var path = this.path.eval(context);
6557     var rootpath = this.currentFileInfo && this.currentFileInfo.rootpath;
6558
6559     if (!(path instanceof URL)) {
6560         if (rootpath) {
6561             var pathValue = path.value;
6562             // Add the base path if the import is relative
6563             if (pathValue && context.isPathRelative(pathValue)) {
6564                 path.value = rootpath + pathValue;
6565             }
6566         }
6567         path.value = context.normalizePath(path.value);
6568     }
6569
6570     return path;
6571 };
6572 Import.prototype.eval = function (context) {
6573     var result = this.doEval(context);
6574     if (this.options.reference || this.blocksVisibility()) {
6575         if (result.length || result.length === 0) {
6576             result.forEach(function (node) {
6577                     node.addVisibilityBlock();
6578                 }
6579             );
6580         } else {
6581             result.addVisibilityBlock();
6582         }
6583     }
6584     return result;
6585 };
6586 Import.prototype.doEval = function (context) {
6587     var ruleset, registry,
6588         features = this.features && this.features.eval(context);
6589
6590     if (this.options.plugin) {
6591         registry = context.frames[0] && context.frames[0].functionRegistry;
6592         if ( registry && this.root && this.root.functions ) {
6593             registry.addMultiple( this.root.functions );
6594         }
6595         return [];
6596     }
6597
6598     if (this.skip) {
6599         if (typeof this.skip === "function") {
6600             this.skip = this.skip();
6601         }
6602         if (this.skip) {
6603             return [];
6604         }
6605     }
6606     if (this.options.inline) {
6607         var contents = new Anonymous(this.root, 0,
6608           {
6609               filename: this.importedFilename,
6610               reference: this.path.currentFileInfo && this.path.currentFileInfo.reference
6611           }, true, true);
6612
6613         return this.features ? new Media([contents], this.features.value) : [contents];
6614     } else if (this.css) {
6615         var newImport = new Import(this.evalPath(context), features, this.options, this.index);
6616         if (!newImport.css && this.error) {
6617             throw this.error;
6618         }
6619         return newImport;
6620     } else {
6621         ruleset = new Ruleset(null, this.root.rules.slice(0));
6622         ruleset.evalImports(context);
6623
6624         return this.features ? new Media(ruleset.rules, this.features.value) : ruleset.rules;
6625     }
6626 };
6627 module.exports = Import;
6628
6629 },{"./anonymous":46,"./media":66,"./node":70,"./quoted":73,"./ruleset":76,"./url":80}],62:[function(require,module,exports){
6630 var tree = {};
6631
6632 tree.Node = require('./node');
6633 tree.Alpha = require('./alpha');
6634 tree.Color = require('./color');
6635 tree.Directive = require('./directive');
6636 tree.DetachedRuleset = require('./detached-ruleset');
6637 tree.Operation = require('./operation');
6638 tree.Dimension = require('./dimension');
6639 tree.Unit = require('./unit');
6640 tree.Keyword = require('./keyword');
6641 tree.Variable = require('./variable');
6642 tree.Ruleset = require('./ruleset');
6643 tree.Element = require('./element');
6644 tree.Attribute = require('./attribute');
6645 tree.Combinator = require('./combinator');
6646 tree.Selector = require('./selector');
6647 tree.Quoted = require('./quoted');
6648 tree.Expression = require('./expression');
6649 tree.Rule = require('./rule');
6650 tree.Call = require('./call');
6651 tree.URL = require('./url');
6652 tree.Import = require('./import');
6653 tree.mixin = {
6654     Call: require('./mixin-call'),
6655     Definition: require('./mixin-definition')
6656 };
6657 tree.Comment = require('./comment');
6658 tree.Anonymous = require('./anonymous');
6659 tree.Value = require('./value');
6660 tree.JavaScript = require('./javascript');
6661 tree.Assignment = require('./assignment');
6662 tree.Condition = require('./condition');
6663 tree.Paren = require('./paren');
6664 tree.Media = require('./media');
6665 tree.UnicodeDescriptor = require('./unicode-descriptor');
6666 tree.Negative = require('./negative');
6667 tree.Extend = require('./extend');
6668 tree.RulesetCall = require('./ruleset-call');
6669
6670 module.exports = tree;
6671
6672 },{"./alpha":45,"./anonymous":46,"./assignment":47,"./attribute":48,"./call":49,"./color":50,"./combinator":51,"./comment":52,"./condition":53,"./detached-ruleset":55,"./dimension":56,"./directive":57,"./element":58,"./expression":59,"./extend":60,"./import":61,"./javascript":63,"./keyword":65,"./media":66,"./mixin-call":67,"./mixin-definition":68,"./negative":69,"./node":70,"./operation":71,"./paren":72,"./quoted":73,"./rule":74,"./ruleset":76,"./ruleset-call":75,"./selector":77,"./unicode-descriptor":78,"./unit":79,"./url":80,"./value":81,"./variable":82}],63:[function(require,module,exports){
6673 var JsEvalNode = require("./js-eval-node"),
6674     Dimension = require("./dimension"),
6675     Quoted = require("./quoted"),
6676     Anonymous = require("./anonymous");
6677
6678 var JavaScript = function (string, escaped, index, currentFileInfo) {
6679     this.escaped = escaped;
6680     this.expression = string;
6681     this.index = index;
6682     this.currentFileInfo = currentFileInfo;
6683 };
6684 JavaScript.prototype = new JsEvalNode();
6685 JavaScript.prototype.type = "JavaScript";
6686 JavaScript.prototype.eval = function(context) {
6687     var result = this.evaluateJavaScript(this.expression, context);
6688
6689     if (typeof result === 'number') {
6690         return new Dimension(result);
6691     } else if (typeof result === 'string') {
6692         return new Quoted('"' + result + '"', result, this.escaped, this.index);
6693     } else if (Array.isArray(result)) {
6694         return new Anonymous(result.join(', '));
6695     } else {
6696         return new Anonymous(result);
6697     }
6698 };
6699
6700 module.exports = JavaScript;
6701
6702 },{"./anonymous":46,"./dimension":56,"./js-eval-node":64,"./quoted":73}],64:[function(require,module,exports){
6703 var Node = require("./node"),
6704     Variable = require("./variable");
6705
6706 var JsEvalNode = function() {
6707 };
6708 JsEvalNode.prototype = new Node();
6709
6710 JsEvalNode.prototype.evaluateJavaScript = function (expression, context) {
6711     var result,
6712         that = this,
6713         evalContext = {};
6714
6715     if (context.javascriptEnabled !== undefined && !context.javascriptEnabled) {
6716         throw { message: "You are using JavaScript, which has been disabled.",
6717             filename: this.currentFileInfo.filename,
6718             index: this.index };
6719     }
6720
6721     expression = expression.replace(/@\{([\w-]+)\}/g, function (_, name) {
6722         return that.jsify(new Variable('@' + name, that.index, that.currentFileInfo).eval(context));
6723     });
6724
6725     try {
6726         expression = new Function('return (' + expression + ')');
6727     } catch (e) {
6728         throw { message: "JavaScript evaluation error: " + e.message + " from `" + expression + "`" ,
6729             filename: this.currentFileInfo.filename,
6730             index: this.index };
6731     }
6732
6733     var variables = context.frames[0].variables();
6734     for (var k in variables) {
6735         if (variables.hasOwnProperty(k)) {
6736             /*jshint loopfunc:true */
6737             evalContext[k.slice(1)] = {
6738                 value: variables[k].value,
6739                 toJS: function () {
6740                     return this.value.eval(context).toCSS();
6741                 }
6742             };
6743         }
6744     }
6745
6746     try {
6747         result = expression.call(evalContext);
6748     } catch (e) {
6749         throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message.replace(/["]/g, "'") + "'" ,
6750             filename: this.currentFileInfo.filename,
6751             index: this.index };
6752     }
6753     return result;
6754 };
6755 JsEvalNode.prototype.jsify = function (obj) {
6756     if (Array.isArray(obj.value) && (obj.value.length > 1)) {
6757         return '[' + obj.value.map(function (v) { return v.toCSS(); }).join(', ') + ']';
6758     } else {
6759         return obj.toCSS();
6760     }
6761 };
6762
6763 module.exports = JsEvalNode;
6764
6765 },{"./node":70,"./variable":82}],65:[function(require,module,exports){
6766 var Node = require("./node");
6767
6768 var Keyword = function (value) { this.value = value; };
6769 Keyword.prototype = new Node();
6770 Keyword.prototype.type = "Keyword";
6771 Keyword.prototype.genCSS = function (context, output) {
6772     if (this.value === '%') { throw { type: "Syntax", message: "Invalid % without number" }; }
6773     output.add(this.value);
6774 };
6775
6776 Keyword.True = new Keyword('true');
6777 Keyword.False = new Keyword('false');
6778
6779 module.exports = Keyword;
6780
6781 },{"./node":70}],66:[function(require,module,exports){
6782 var Ruleset = require("./ruleset"),
6783     Value = require("./value"),
6784     Selector = require("./selector"),
6785     Anonymous = require("./anonymous"),
6786     Expression = require("./expression"),
6787     Directive = require("./directive");
6788
6789 var Media = function (value, features, index, currentFileInfo, visibilityInfo) {
6790     this.index = index;
6791     this.currentFileInfo = currentFileInfo;
6792
6793     var selectors = (new Selector([], null, null, this.index, this.currentFileInfo)).createEmptySelectors();
6794
6795     this.features = new Value(features);
6796     this.rules = [new Ruleset(selectors, value)];
6797     this.rules[0].allowImports = true;
6798     this.copyVisibilityInfo(visibilityInfo);
6799     this.allowRoot = true;
6800 };
6801 Media.prototype = new Directive();
6802 Media.prototype.type = "Media";
6803 Media.prototype.isRulesetLike = true;
6804 Media.prototype.accept = function (visitor) {
6805     if (this.features) {
6806         this.features = visitor.visit(this.features);
6807     }
6808     if (this.rules) {
6809         this.rules = visitor.visitArray(this.rules);
6810     }
6811 };
6812 Media.prototype.genCSS = function (context, output) {
6813     output.add('@media ', this.currentFileInfo, this.index);
6814     this.features.genCSS(context, output);
6815     this.outputRuleset(context, output, this.rules);
6816 };
6817 Media.prototype.eval = function (context) {
6818     if (!context.mediaBlocks) {
6819         context.mediaBlocks = [];
6820         context.mediaPath = [];
6821     }
6822
6823     var media = new Media(null, [], this.index, this.currentFileInfo, this.visibilityInfo());
6824     if (this.debugInfo) {
6825         this.rules[0].debugInfo = this.debugInfo;
6826         media.debugInfo = this.debugInfo;
6827     }
6828     var strictMathBypass = false;
6829     if (!context.strictMath) {
6830         strictMathBypass = true;
6831         context.strictMath = true;
6832     }
6833     try {
6834         media.features = this.features.eval(context);
6835     }
6836     finally {
6837         if (strictMathBypass) {
6838             context.strictMath = false;
6839         }
6840     }
6841
6842     context.mediaPath.push(media);
6843     context.mediaBlocks.push(media);
6844
6845     this.rules[0].functionRegistry = context.frames[0].functionRegistry.inherit();
6846     context.frames.unshift(this.rules[0]);
6847     media.rules = [this.rules[0].eval(context)];
6848     context.frames.shift();
6849
6850     context.mediaPath.pop();
6851
6852     return context.mediaPath.length === 0 ? media.evalTop(context) :
6853                 media.evalNested(context);
6854 };
6855 Media.prototype.evalTop = function (context) {
6856     var result = this;
6857
6858     // Render all dependent Media blocks.
6859     if (context.mediaBlocks.length > 1) {
6860         var selectors = (new Selector([], null, null, this.index, this.currentFileInfo)).createEmptySelectors();
6861         result = new Ruleset(selectors, context.mediaBlocks);
6862         result.multiMedia = true;
6863         result.copyVisibilityInfo(this.visibilityInfo());
6864     }
6865
6866     delete context.mediaBlocks;
6867     delete context.mediaPath;
6868
6869     return result;
6870 };
6871 Media.prototype.evalNested = function (context) {
6872     var i, value,
6873         path = context.mediaPath.concat([this]);
6874
6875     // Extract the media-query conditions separated with `,` (OR).
6876     for (i = 0; i < path.length; i++) {
6877         value = path[i].features instanceof Value ?
6878                     path[i].features.value : path[i].features;
6879         path[i] = Array.isArray(value) ? value : [value];
6880     }
6881
6882     // Trace all permutations to generate the resulting media-query.
6883     //
6884     // (a, b and c) with nested (d, e) ->
6885     //    a and d
6886     //    a and e
6887     //    b and c and d
6888     //    b and c and e
6889     this.features = new Value(this.permute(path).map(function (path) {
6890         path = path.map(function (fragment) {
6891             return fragment.toCSS ? fragment : new Anonymous(fragment);
6892         });
6893
6894         for (i = path.length - 1; i > 0; i--) {
6895             path.splice(i, 0, new Anonymous("and"));
6896         }
6897
6898         return new Expression(path);
6899     }));
6900
6901     // Fake a tree-node that doesn't output anything.
6902     return new Ruleset([], []);
6903 };
6904 Media.prototype.permute = function (arr) {
6905     if (arr.length === 0) {
6906         return [];
6907     } else if (arr.length === 1) {
6908         return arr[0];
6909     } else {
6910         var result = [];
6911         var rest = this.permute(arr.slice(1));
6912         for (var i = 0; i < rest.length; i++) {
6913             for (var j = 0; j < arr[0].length; j++) {
6914                 result.push([arr[0][j]].concat(rest[i]));
6915             }
6916         }
6917         return result;
6918     }
6919 };
6920 Media.prototype.bubbleSelectors = function (selectors) {
6921     if (!selectors) {
6922         return;
6923     }
6924     this.rules = [new Ruleset(selectors.slice(0), [this.rules[0]])];
6925 };
6926 module.exports = Media;
6927
6928 },{"./anonymous":46,"./directive":57,"./expression":59,"./ruleset":76,"./selector":77,"./value":81}],67:[function(require,module,exports){
6929 var Node = require("./node"),
6930     Selector = require("./selector"),
6931     MixinDefinition = require("./mixin-definition"),
6932     defaultFunc = require("../functions/default");
6933
6934 var MixinCall = function (elements, args, index, currentFileInfo, important) {
6935     this.selector = new Selector(elements);
6936     this.arguments = args || [];
6937     this.index = index;
6938     this.currentFileInfo = currentFileInfo;
6939     this.important = important;
6940     this.allowRoot = true;
6941 };
6942 MixinCall.prototype = new Node();
6943 MixinCall.prototype.type = "MixinCall";
6944 MixinCall.prototype.accept = function (visitor) {
6945     if (this.selector) {
6946         this.selector = visitor.visit(this.selector);
6947     }
6948     if (this.arguments.length) {
6949         this.arguments = visitor.visitArray(this.arguments);
6950     }
6951 };
6952 MixinCall.prototype.eval = function (context) {
6953     var mixins, mixin, mixinPath, args = [], arg, argValue,
6954         rules = [], match = false, i, m, f, isRecursive, isOneFound,
6955         candidates = [], candidate, conditionResult = [], defaultResult, defFalseEitherCase = -1,
6956         defNone = 0, defTrue = 1, defFalse = 2, count, originalRuleset, noArgumentsFilter;
6957
6958     function calcDefGroup(mixin, mixinPath) {
6959         var f, p, namespace;
6960
6961         for (f = 0; f < 2; f++) {
6962             conditionResult[f] = true;
6963             defaultFunc.value(f);
6964             for (p = 0; p < mixinPath.length && conditionResult[f]; p++) {
6965                 namespace = mixinPath[p];
6966                 if (namespace.matchCondition) {
6967                     conditionResult[f] = conditionResult[f] && namespace.matchCondition(null, context);
6968                 }
6969             }
6970             if (mixin.matchCondition) {
6971                 conditionResult[f] = conditionResult[f] && mixin.matchCondition(args, context);
6972             }
6973         }
6974         if (conditionResult[0] || conditionResult[1]) {
6975             if (conditionResult[0] != conditionResult[1]) {
6976                 return conditionResult[1] ?
6977                     defTrue : defFalse;
6978             }
6979
6980             return defNone;
6981         }
6982         return defFalseEitherCase;
6983     }
6984
6985     for (i = 0; i < this.arguments.length; i++) {
6986         arg = this.arguments[i];
6987         argValue = arg.value.eval(context);
6988         if (arg.expand && Array.isArray(argValue.value)) {
6989             argValue = argValue.value;
6990             for (m = 0; m < argValue.length; m++) {
6991                 args.push({value: argValue[m]});
6992             }
6993         } else {
6994             args.push({name: arg.name, value: argValue});
6995         }
6996     }
6997
6998     noArgumentsFilter = function(rule) {return rule.matchArgs(null, context);};
6999
7000     for (i = 0; i < context.frames.length; i++) {
7001         if ((mixins = context.frames[i].find(this.selector, null, noArgumentsFilter)).length > 0) {
7002             isOneFound = true;
7003
7004             // To make `default()` function independent of definition order we have two "subpasses" here.
7005             // At first we evaluate each guard *twice* (with `default() == true` and `default() == false`),
7006             // and build candidate list with corresponding flags. Then, when we know all possible matches,
7007             // we make a final decision.
7008
7009             for (m = 0; m < mixins.length; m++) {
7010                 mixin = mixins[m].rule;
7011                 mixinPath = mixins[m].path;
7012                 isRecursive = false;
7013                 for (f = 0; f < context.frames.length; f++) {
7014                     if ((!(mixin instanceof MixinDefinition)) && mixin === (context.frames[f].originalRuleset || context.frames[f])) {
7015                         isRecursive = true;
7016                         break;
7017                     }
7018                 }
7019                 if (isRecursive) {
7020                     continue;
7021                 }
7022
7023                 if (mixin.matchArgs(args, context)) {
7024                     candidate = {mixin: mixin, group: calcDefGroup(mixin, mixinPath)};
7025
7026                     if (candidate.group !== defFalseEitherCase) {
7027                         candidates.push(candidate);
7028                     }
7029
7030                     match = true;
7031                 }
7032             }
7033
7034             defaultFunc.reset();
7035
7036             count = [0, 0, 0];
7037             for (m = 0; m < candidates.length; m++) {
7038                 count[candidates[m].group]++;
7039             }
7040
7041             if (count[defNone] > 0) {
7042                 defaultResult = defFalse;
7043             } else {
7044                 defaultResult = defTrue;
7045                 if ((count[defTrue] + count[defFalse]) > 1) {
7046                     throw { type: 'Runtime',
7047                         message: 'Ambiguous use of `default()` found when matching for `' + this.format(args) + '`',
7048                         index: this.index, filename: this.currentFileInfo.filename };
7049                 }
7050             }
7051
7052             for (m = 0; m < candidates.length; m++) {
7053                 candidate = candidates[m].group;
7054                 if ((candidate === defNone) || (candidate === defaultResult)) {
7055                     try {
7056                         mixin = candidates[m].mixin;
7057                         if (!(mixin instanceof MixinDefinition)) {
7058                             originalRuleset = mixin.originalRuleset || mixin;
7059                             mixin = new MixinDefinition("", [], mixin.rules, null, false, null, originalRuleset.visibilityInfo());
7060                             mixin.originalRuleset = originalRuleset;
7061                         }
7062                         var newRules = mixin.evalCall(context, args, this.important).rules;
7063                         this._setVisibilityToReplacement(newRules);
7064                         Array.prototype.push.apply(rules, newRules);
7065                     } catch (e) {
7066                         throw { message: e.message, index: this.index, filename: this.currentFileInfo.filename, stack: e.stack };
7067                     }
7068                 }
7069             }
7070
7071             if (match) {
7072                 return rules;
7073             }
7074         }
7075     }
7076     if (isOneFound) {
7077         throw { type:    'Runtime',
7078             message: 'No matching definition was found for `' + this.format(args) + '`',
7079             index:   this.index, filename: this.currentFileInfo.filename };
7080     } else {
7081         throw { type:    'Name',
7082             message: this.selector.toCSS().trim() + " is undefined",
7083             index:   this.index, filename: this.currentFileInfo.filename };
7084     }
7085 };
7086
7087 MixinCall.prototype._setVisibilityToReplacement = function (replacement) {
7088     var i, rule;
7089     if (this.blocksVisibility()) {
7090         for (i = 0; i < replacement.length; i++) {
7091             rule = replacement[i];
7092             rule.addVisibilityBlock();
7093         }
7094     }
7095 };
7096 MixinCall.prototype.format = function (args) {
7097     return this.selector.toCSS().trim() + '(' +
7098         (args ? args.map(function (a) {
7099             var argValue = "";
7100             if (a.name) {
7101                 argValue += a.name + ":";
7102             }
7103             if (a.value.toCSS) {
7104                 argValue += a.value.toCSS();
7105             } else {
7106                 argValue += "???";
7107             }
7108             return argValue;
7109         }).join(', ') : "") + ")";
7110 };
7111 module.exports = MixinCall;
7112
7113 },{"../functions/default":20,"./mixin-definition":68,"./node":70,"./selector":77}],68:[function(require,module,exports){
7114 var Selector = require("./selector"),
7115     Element = require("./element"),
7116     Ruleset = require("./ruleset"),
7117     Rule = require("./rule"),
7118     Expression = require("./expression"),
7119     contexts = require("../contexts");
7120
7121 var Definition = function (name, params, rules, condition, variadic, frames, visibilityInfo) {
7122     this.name = name;
7123     this.selectors = [new Selector([new Element(null, name, this.index, this.currentFileInfo)])];
7124     this.params = params;
7125     this.condition = condition;
7126     this.variadic = variadic;
7127     this.arity = params.length;
7128     this.rules = rules;
7129     this._lookups = {};
7130     var optionalParameters = [];
7131     this.required = params.reduce(function (count, p) {
7132         if (!p.name || (p.name && !p.value)) {
7133             return count + 1;
7134         }
7135         else {
7136             optionalParameters.push(p.name);
7137             return count;
7138         }
7139     }, 0);
7140     this.optionalParameters = optionalParameters;
7141     this.frames = frames;
7142     this.copyVisibilityInfo(visibilityInfo);
7143     this.allowRoot = true;
7144 };
7145 Definition.prototype = new Ruleset();
7146 Definition.prototype.type = "MixinDefinition";
7147 Definition.prototype.evalFirst = true;
7148 Definition.prototype.accept = function (visitor) {
7149     if (this.params && this.params.length) {
7150         this.params = visitor.visitArray(this.params);
7151     }
7152     this.rules = visitor.visitArray(this.rules);
7153     if (this.condition) {
7154         this.condition = visitor.visit(this.condition);
7155     }
7156 };
7157 Definition.prototype.evalParams = function (context, mixinEnv, args, evaldArguments) {
7158     /*jshint boss:true */
7159     var frame = new Ruleset(null, null),
7160         varargs, arg,
7161         params = this.params.slice(0),
7162         i, j, val, name, isNamedFound, argIndex, argsLength = 0;
7163
7164     if (mixinEnv.frames && mixinEnv.frames[0] && mixinEnv.frames[0].functionRegistry) {
7165         frame.functionRegistry = mixinEnv.frames[0].functionRegistry.inherit();
7166     }
7167     mixinEnv = new contexts.Eval(mixinEnv, [frame].concat(mixinEnv.frames));
7168
7169     if (args) {
7170         args = args.slice(0);
7171         argsLength = args.length;
7172
7173         for (i = 0; i < argsLength; i++) {
7174             arg = args[i];
7175             if (name = (arg && arg.name)) {
7176                 isNamedFound = false;
7177                 for (j = 0; j < params.length; j++) {
7178                     if (!evaldArguments[j] && name === params[j].name) {
7179                         evaldArguments[j] = arg.value.eval(context);
7180                         frame.prependRule(new Rule(name, arg.value.eval(context)));
7181                         isNamedFound = true;
7182                         break;
7183                     }
7184                 }
7185                 if (isNamedFound) {
7186                     args.splice(i, 1);
7187                     i--;
7188                     continue;
7189                 } else {
7190                     throw { type: 'Runtime', message: "Named argument for " + this.name +
7191                         ' ' + args[i].name + ' not found' };
7192                 }
7193             }
7194         }
7195     }
7196     argIndex = 0;
7197     for (i = 0; i < params.length; i++) {
7198         if (evaldArguments[i]) { continue; }
7199
7200         arg = args && args[argIndex];
7201
7202         if (name = params[i].name) {
7203             if (params[i].variadic) {
7204                 varargs = [];
7205                 for (j = argIndex; j < argsLength; j++) {
7206                     varargs.push(args[j].value.eval(context));
7207                 }
7208                 frame.prependRule(new Rule(name, new Expression(varargs).eval(context)));
7209             } else {
7210                 val = arg && arg.value;
7211                 if (val) {
7212                     val = val.eval(context);
7213                 } else if (params[i].value) {
7214                     val = params[i].value.eval(mixinEnv);
7215                     frame.resetCache();
7216                 } else {
7217                     throw { type: 'Runtime', message: "wrong number of arguments for " + this.name +
7218                         ' (' + argsLength + ' for ' + this.arity + ')' };
7219                 }
7220
7221                 frame.prependRule(new Rule(name, val));
7222                 evaldArguments[i] = val;
7223             }
7224         }
7225
7226         if (params[i].variadic && args) {
7227             for (j = argIndex; j < argsLength; j++) {
7228                 evaldArguments[j] = args[j].value.eval(context);
7229             }
7230         }
7231         argIndex++;
7232     }
7233
7234     return frame;
7235 };
7236 Definition.prototype.makeImportant = function() {
7237     var rules = !this.rules ? this.rules : this.rules.map(function (r) {
7238         if (r.makeImportant) {
7239             return r.makeImportant(true);
7240         } else {
7241             return r;
7242         }
7243     });
7244     var result = new Definition(this.name, this.params, rules, this.condition, this.variadic, this.frames);
7245     return result;
7246 };
7247 Definition.prototype.eval = function (context) {
7248     return new Definition(this.name, this.params, this.rules, this.condition, this.variadic, this.frames || context.frames.slice(0));
7249 };
7250 Definition.prototype.evalCall = function (context, args, important) {
7251     var _arguments = [],
7252         mixinFrames = this.frames ? this.frames.concat(context.frames) : context.frames,
7253         frame = this.evalParams(context, new contexts.Eval(context, mixinFrames), args, _arguments),
7254         rules, ruleset;
7255
7256     frame.prependRule(new Rule('@arguments', new Expression(_arguments).eval(context)));
7257
7258     rules = this.rules.slice(0);
7259
7260     ruleset = new Ruleset(null, rules);
7261     ruleset.originalRuleset = this;
7262     ruleset = ruleset.eval(new contexts.Eval(context, [this, frame].concat(mixinFrames)));
7263     if (important) {
7264         ruleset = ruleset.makeImportant();
7265     }
7266     return ruleset;
7267 };
7268 Definition.prototype.matchCondition = function (args, context) {
7269     if (this.condition && !this.condition.eval(
7270         new contexts.Eval(context,
7271             [this.evalParams(context, /* the parameter variables*/
7272                 new contexts.Eval(context, this.frames ? this.frames.concat(context.frames) : context.frames), args, [])]
7273             .concat(this.frames || []) // the parent namespace/mixin frames
7274             .concat(context.frames)))) { // the current environment frames
7275         return false;
7276     }
7277     return true;
7278 };
7279 Definition.prototype.matchArgs = function (args, context) {
7280     var allArgsCnt = (args && args.length) || 0, len, optionalParameters = this.optionalParameters;
7281     var requiredArgsCnt = !args ? 0 : args.reduce(function (count, p) {
7282         if (optionalParameters.indexOf(p.name) < 0) {
7283             return count + 1;
7284         } else {
7285             return count;
7286         }
7287     }, 0);
7288
7289     if (! this.variadic) {
7290         if (requiredArgsCnt < this.required) {
7291             return false;
7292         }
7293         if (allArgsCnt > this.params.length) {
7294             return false;
7295         }
7296     } else {
7297         if (requiredArgsCnt < (this.required - 1)) {
7298             return false;
7299         }
7300     }
7301
7302     // check patterns
7303     len = Math.min(requiredArgsCnt, this.arity);
7304
7305     for (var i = 0; i < len; i++) {
7306         if (!this.params[i].name && !this.params[i].variadic) {
7307             if (args[i].value.eval(context).toCSS() != this.params[i].value.eval(context).toCSS()) {
7308                 return false;
7309             }
7310         }
7311     }
7312     return true;
7313 };
7314 module.exports = Definition;
7315
7316 },{"../contexts":11,"./element":58,"./expression":59,"./rule":74,"./ruleset":76,"./selector":77}],69:[function(require,module,exports){
7317 var Node = require("./node"),
7318     Operation = require("./operation"),
7319     Dimension = require("./dimension");
7320
7321 var Negative = function (node) {
7322     this.value = node;
7323 };
7324 Negative.prototype = new Node();
7325 Negative.prototype.type = "Negative";
7326 Negative.prototype.genCSS = function (context, output) {
7327     output.add('-');
7328     this.value.genCSS(context, output);
7329 };
7330 Negative.prototype.eval = function (context) {
7331     if (context.isMathOn()) {
7332         return (new Operation('*', [new Dimension(-1), this.value])).eval(context);
7333     }
7334     return new Negative(this.value.eval(context));
7335 };
7336 module.exports = Negative;
7337
7338 },{"./dimension":56,"./node":70,"./operation":71}],70:[function(require,module,exports){
7339 var Node = function() {
7340 };
7341 Node.prototype.toCSS = function (context) {
7342     var strs = [];
7343     this.genCSS(context, {
7344         add: function(chunk, fileInfo, index) {
7345             strs.push(chunk);
7346         },
7347         isEmpty: function () {
7348             return strs.length === 0;
7349         }
7350     });
7351     return strs.join('');
7352 };
7353 Node.prototype.genCSS = function (context, output) {
7354     output.add(this.value);
7355 };
7356 Node.prototype.accept = function (visitor) {
7357     this.value = visitor.visit(this.value);
7358 };
7359 Node.prototype.eval = function () { return this; };
7360 Node.prototype._operate = function (context, op, a, b) {
7361     switch (op) {
7362         case '+': return a + b;
7363         case '-': return a - b;
7364         case '*': return a * b;
7365         case '/': return a / b;
7366     }
7367 };
7368 Node.prototype.fround = function(context, value) {
7369     var precision = context && context.numPrecision;
7370     //add "epsilon" to ensure numbers like 1.000000005 (represented as 1.000000004999....) are properly rounded...
7371     return (precision == null) ? value : Number((value + 2e-16).toFixed(precision));
7372 };
7373 Node.compare = function (a, b) {
7374     /* returns:
7375      -1: a < b
7376      0: a = b
7377      1: a > b
7378      and *any* other value for a != b (e.g. undefined, NaN, -2 etc.) */
7379
7380     if ((a.compare) &&
7381         // for "symmetric results" force toCSS-based comparison
7382         // of Quoted or Anonymous if either value is one of those
7383         !(b.type === "Quoted" || b.type === "Anonymous")) {
7384         return a.compare(b);
7385     } else if (b.compare) {
7386         return -b.compare(a);
7387     } else if (a.type !== b.type) {
7388         return undefined;
7389     }
7390
7391     a = a.value;
7392     b = b.value;
7393     if (!Array.isArray(a)) {
7394         return a === b ? 0 : undefined;
7395     }
7396     if (a.length !== b.length) {
7397         return undefined;
7398     }
7399     for (var i = 0; i < a.length; i++) {
7400         if (Node.compare(a[i], b[i]) !== 0) {
7401             return undefined;
7402         }
7403     }
7404     return 0;
7405 };
7406
7407 Node.numericCompare = function (a, b) {
7408     return a  <  b ? -1
7409         : a === b ?  0
7410         : a  >  b ?  1 : undefined;
7411 };
7412 // Returns true if this node represents root of ast imported by reference
7413 Node.prototype.blocksVisibility = function () {
7414     if (this.visibilityBlocks == null) {
7415         this.visibilityBlocks = 0;
7416     }
7417     return this.visibilityBlocks !== 0;
7418 };
7419 Node.prototype.addVisibilityBlock = function () {
7420     if (this.visibilityBlocks == null) {
7421         this.visibilityBlocks = 0;
7422     }
7423     this.visibilityBlocks = this.visibilityBlocks + 1;
7424 };
7425 Node.prototype.removeVisibilityBlock = function () {
7426     if (this.visibilityBlocks == null) {
7427         this.visibilityBlocks = 0;
7428     }
7429     this.visibilityBlocks = this.visibilityBlocks - 1;
7430 };
7431 //Turns on node visibility - if called node will be shown in output regardless
7432 //of whether it comes from import by reference or not
7433 Node.prototype.ensureVisibility = function () {
7434     this.nodeVisible = true;
7435 };
7436 //Turns off node visibility - if called node will NOT be shown in output regardless
7437 //of whether it comes from import by reference or not
7438 Node.prototype.ensureInvisibility = function () {
7439     this.nodeVisible = false;
7440 };
7441 // return values:
7442 // false - the node must not be visible
7443 // true - the node must be visible
7444 // undefined or null - the node has the same visibility as its parent
7445 Node.prototype.isVisible = function () {
7446     return this.nodeVisible;
7447 };
7448 Node.prototype.visibilityInfo = function() {
7449     return {
7450         visibilityBlocks: this.visibilityBlocks,
7451         nodeVisible: this.nodeVisible
7452     };
7453 };
7454 Node.prototype.copyVisibilityInfo = function(info) {
7455     if (!info) {
7456         return;
7457     }
7458     this.visibilityBlocks = info.visibilityBlocks;
7459     this.nodeVisible = info.nodeVisible;
7460 };
7461 module.exports = Node;
7462
7463 },{}],71:[function(require,module,exports){
7464 var Node = require("./node"),
7465     Color = require("./color"),
7466     Dimension = require("./dimension");
7467
7468 var Operation = function (op, operands, isSpaced) {
7469     this.op = op.trim();
7470     this.operands = operands;
7471     this.isSpaced = isSpaced;
7472 };
7473 Operation.prototype = new Node();
7474 Operation.prototype.type = "Operation";
7475 Operation.prototype.accept = function (visitor) {
7476     this.operands = visitor.visit(this.operands);
7477 };
7478 Operation.prototype.eval = function (context) {
7479     var a = this.operands[0].eval(context),
7480         b = this.operands[1].eval(context);
7481
7482     if (context.isMathOn()) {
7483         if (a instanceof Dimension && b instanceof Color) {
7484             a = a.toColor();
7485         }
7486         if (b instanceof Dimension && a instanceof Color) {
7487             b = b.toColor();
7488         }
7489         if (!a.operate) {
7490             throw { type: "Operation",
7491                     message: "Operation on an invalid type" };
7492         }
7493
7494         return a.operate(context, this.op, b);
7495     } else {
7496         return new Operation(this.op, [a, b], this.isSpaced);
7497     }
7498 };
7499 Operation.prototype.genCSS = function (context, output) {
7500     this.operands[0].genCSS(context, output);
7501     if (this.isSpaced) {
7502         output.add(" ");
7503     }
7504     output.add(this.op);
7505     if (this.isSpaced) {
7506         output.add(" ");
7507     }
7508     this.operands[1].genCSS(context, output);
7509 };
7510
7511 module.exports = Operation;
7512
7513 },{"./color":50,"./dimension":56,"./node":70}],72:[function(require,module,exports){
7514 var Node = require("./node");
7515
7516 var Paren = function (node) {
7517     this.value = node;
7518 };
7519 Paren.prototype = new Node();
7520 Paren.prototype.type = "Paren";
7521 Paren.prototype.genCSS = function (context, output) {
7522     output.add('(');
7523     this.value.genCSS(context, output);
7524     output.add(')');
7525 };
7526 Paren.prototype.eval = function (context) {
7527     return new Paren(this.value.eval(context));
7528 };
7529 module.exports = Paren;
7530
7531 },{"./node":70}],73:[function(require,module,exports){
7532 var Node = require("./node"),
7533     JsEvalNode = require("./js-eval-node"),
7534     Variable = require("./variable");
7535
7536 var Quoted = function (str, content, escaped, index, currentFileInfo) {
7537     this.escaped = (escaped == null) ? true : escaped;
7538     this.value = content || '';
7539     this.quote = str.charAt(0);
7540     this.index = index;
7541     this.currentFileInfo = currentFileInfo;
7542 };
7543 Quoted.prototype = new JsEvalNode();
7544 Quoted.prototype.type = "Quoted";
7545 Quoted.prototype.genCSS = function (context, output) {
7546     if (!this.escaped) {
7547         output.add(this.quote, this.currentFileInfo, this.index);
7548     }
7549     output.add(this.value);
7550     if (!this.escaped) {
7551         output.add(this.quote);
7552     }
7553 };
7554 Quoted.prototype.containsVariables = function() {
7555     return this.value.match(/(`([^`]+)`)|@\{([\w-]+)\}/);
7556 };
7557 Quoted.prototype.eval = function (context) {
7558     var that = this, value = this.value;
7559     var javascriptReplacement = function (_, exp) {
7560         return String(that.evaluateJavaScript(exp, context));
7561     };
7562     var interpolationReplacement = function (_, name) {
7563         var v = new Variable('@' + name, that.index, that.currentFileInfo).eval(context, true);
7564         return (v instanceof Quoted) ? v.value : v.toCSS();
7565     };
7566     function iterativeReplace(value, regexp, replacementFnc) {
7567         var evaluatedValue = value;
7568         do {
7569             value = evaluatedValue;
7570             evaluatedValue = value.replace(regexp, replacementFnc);
7571         } while (value !== evaluatedValue);
7572         return evaluatedValue;
7573     }
7574     value = iterativeReplace(value, /`([^`]+)`/g, javascriptReplacement);
7575     value = iterativeReplace(value, /@\{([\w-]+)\}/g, interpolationReplacement);
7576     return new Quoted(this.quote + value + this.quote, value, this.escaped, this.index, this.currentFileInfo);
7577 };
7578 Quoted.prototype.compare = function (other) {
7579     // when comparing quoted strings allow the quote to differ
7580     if (other.type === "Quoted" && !this.escaped && !other.escaped) {
7581         return Node.numericCompare(this.value, other.value);
7582     } else {
7583         return other.toCSS && this.toCSS() === other.toCSS() ? 0 : undefined;
7584     }
7585 };
7586 module.exports = Quoted;
7587
7588 },{"./js-eval-node":64,"./node":70,"./variable":82}],74:[function(require,module,exports){
7589 var Node = require("./node"),
7590     Value = require("./value"),
7591     Keyword = require("./keyword");
7592
7593 var Rule = function (name, value, important, merge, index, currentFileInfo, inline, variable) {
7594     this.name = name;
7595     this.value = (value instanceof Node) ? value : new Value([value]); //value instanceof tree.Value || value instanceof tree.Ruleset ??
7596     this.important = important ? ' ' + important.trim() : '';
7597     this.merge = merge;
7598     this.index = index;
7599     this.currentFileInfo = currentFileInfo;
7600     this.inline = inline || false;
7601     this.variable = (variable !== undefined) ? variable
7602         : (name.charAt && (name.charAt(0) === '@'));
7603     this.allowRoot = true;
7604 };
7605
7606 function evalName(context, name) {
7607     var value = "", i, n = name.length,
7608         output = {add: function (s) {value += s;}};
7609     for (i = 0; i < n; i++) {
7610         name[i].eval(context).genCSS(context, output);
7611     }
7612     return value;
7613 }
7614
7615 Rule.prototype = new Node();
7616 Rule.prototype.type = "Rule";
7617 Rule.prototype.genCSS = function (context, output) {
7618     output.add(this.name + (context.compress ? ':' : ': '), this.currentFileInfo, this.index);
7619     try {
7620         this.value.genCSS(context, output);
7621     }
7622     catch(e) {
7623         e.index = this.index;
7624         e.filename = this.currentFileInfo.filename;
7625         throw e;
7626     }
7627     output.add(this.important + ((this.inline || (context.lastRule && context.compress)) ? "" : ";"), this.currentFileInfo, this.index);
7628 };
7629 Rule.prototype.eval = function (context) {
7630     var strictMathBypass = false, name = this.name, evaldValue, variable = this.variable;
7631     if (typeof name !== "string") {
7632         // expand 'primitive' name directly to get
7633         // things faster (~10% for benchmark.less):
7634         name = (name.length === 1) && (name[0] instanceof Keyword) ?
7635                 name[0].value : evalName(context, name);
7636         variable = false; // never treat expanded interpolation as new variable name
7637     }
7638     if (name === "font" && !context.strictMath) {
7639         strictMathBypass = true;
7640         context.strictMath = true;
7641     }
7642     try {
7643         context.importantScope.push({});
7644         evaldValue = this.value.eval(context);
7645
7646         if (!this.variable && evaldValue.type === "DetachedRuleset") {
7647             throw { message: "Rulesets cannot be evaluated on a property.",
7648                     index: this.index, filename: this.currentFileInfo.filename };
7649         }
7650         var important = this.important,
7651             importantResult = context.importantScope.pop();
7652         if (!important && importantResult.important) {
7653             important = importantResult.important;
7654         }
7655
7656         return new Rule(name,
7657                           evaldValue,
7658                           important,
7659                           this.merge,
7660                           this.index, this.currentFileInfo, this.inline,
7661                               variable);
7662     }
7663     catch(e) {
7664         if (typeof e.index !== 'number') {
7665             e.index = this.index;
7666             e.filename = this.currentFileInfo.filename;
7667         }
7668         throw e;
7669     }
7670     finally {
7671         if (strictMathBypass) {
7672             context.strictMath = false;
7673         }
7674     }
7675 };
7676 Rule.prototype.makeImportant = function () {
7677     return new Rule(this.name,
7678                           this.value,
7679                           "!important",
7680                           this.merge,
7681                           this.index, this.currentFileInfo, this.inline);
7682 };
7683
7684 module.exports = Rule;
7685 },{"./keyword":65,"./node":70,"./value":81}],75:[function(require,module,exports){
7686 var Node = require("./node"),
7687     Variable = require("./variable");
7688
7689 var RulesetCall = function (variable) {
7690     this.variable = variable;
7691     this.allowRoot = true;
7692 };
7693 RulesetCall.prototype = new Node();
7694 RulesetCall.prototype.type = "RulesetCall";
7695 RulesetCall.prototype.eval = function (context) {
7696     var detachedRuleset = new Variable(this.variable).eval(context);
7697     return detachedRuleset.callEval(context);
7698 };
7699 module.exports = RulesetCall;
7700
7701 },{"./node":70,"./variable":82}],76:[function(require,module,exports){
7702 var Node = require("./node"),
7703     Rule = require("./rule"),
7704     Selector = require("./selector"),
7705     Element = require("./element"),
7706     Paren = require("./paren"),
7707     contexts = require("../contexts"),
7708     globalFunctionRegistry = require("../functions/function-registry"),
7709     defaultFunc = require("../functions/default"),
7710     getDebugInfo = require("./debug-info");
7711
7712 var Ruleset = function (selectors, rules, strictImports, visibilityInfo) {
7713     this.selectors = selectors;
7714     this.rules = rules;
7715     this._lookups = {};
7716     this.strictImports = strictImports;
7717     this.copyVisibilityInfo(visibilityInfo);
7718     this.allowRoot = true;
7719 };
7720 Ruleset.prototype = new Node();
7721 Ruleset.prototype.type = "Ruleset";
7722 Ruleset.prototype.isRuleset = true;
7723 Ruleset.prototype.isRulesetLike = true;
7724 Ruleset.prototype.accept = function (visitor) {
7725     if (this.paths) {
7726         this.paths = visitor.visitArray(this.paths, true);
7727     } else if (this.selectors) {
7728         this.selectors = visitor.visitArray(this.selectors);
7729     }
7730     if (this.rules && this.rules.length) {
7731         this.rules = visitor.visitArray(this.rules);
7732     }
7733 };
7734 Ruleset.prototype.eval = function (context) {
7735     var thisSelectors = this.selectors, selectors,
7736         selCnt, selector, i, hasOnePassingSelector = false;
7737
7738     if (thisSelectors && (selCnt = thisSelectors.length)) {
7739         selectors = [];
7740         defaultFunc.error({
7741             type: "Syntax",
7742             message: "it is currently only allowed in parametric mixin guards,"
7743         });
7744         for (i = 0; i < selCnt; i++) {
7745             selector = thisSelectors[i].eval(context);
7746             selectors.push(selector);
7747             if (selector.evaldCondition) {
7748                 hasOnePassingSelector = true;
7749             }
7750         }
7751         defaultFunc.reset();
7752     } else {
7753         hasOnePassingSelector = true;
7754     }
7755
7756     var rules = this.rules ? this.rules.slice(0) : null,
7757         ruleset = new Ruleset(selectors, rules, this.strictImports, this.visibilityInfo()),
7758         rule, subRule;
7759
7760     ruleset.originalRuleset = this;
7761     ruleset.root = this.root;
7762     ruleset.firstRoot = this.firstRoot;
7763     ruleset.allowImports = this.allowImports;
7764
7765     if (this.debugInfo) {
7766         ruleset.debugInfo = this.debugInfo;
7767     }
7768
7769     if (!hasOnePassingSelector) {
7770         rules.length = 0;
7771     }
7772
7773     // inherit a function registry from the frames stack when possible;
7774     // otherwise from the global registry
7775     ruleset.functionRegistry = (function (frames) {
7776         var i = 0,
7777             n = frames.length,
7778             found;
7779         for ( ; i !== n ; ++i ) {
7780             found = frames[ i ].functionRegistry;
7781             if ( found ) { return found; }
7782         }
7783         return globalFunctionRegistry;
7784     }(context.frames)).inherit();
7785
7786     // push the current ruleset to the frames stack
7787     var ctxFrames = context.frames;
7788     ctxFrames.unshift(ruleset);
7789
7790     // currrent selectors
7791     var ctxSelectors = context.selectors;
7792     if (!ctxSelectors) {
7793         context.selectors = ctxSelectors = [];
7794     }
7795     ctxSelectors.unshift(this.selectors);
7796
7797     // Evaluate imports
7798     if (ruleset.root || ruleset.allowImports || !ruleset.strictImports) {
7799         ruleset.evalImports(context);
7800     }
7801
7802     // Store the frames around mixin definitions,
7803     // so they can be evaluated like closures when the time comes.
7804     var rsRules = ruleset.rules, rsRuleCnt = rsRules ? rsRules.length : 0;
7805     for (i = 0; i < rsRuleCnt; i++) {
7806         if (rsRules[i].evalFirst) {
7807             rsRules[i] = rsRules[i].eval(context);
7808         }
7809     }
7810
7811     var mediaBlockCount = (context.mediaBlocks && context.mediaBlocks.length) || 0;
7812
7813     // Evaluate mixin calls.
7814     for (i = 0; i < rsRuleCnt; i++) {
7815         if (rsRules[i].type === "MixinCall") {
7816             /*jshint loopfunc:true */
7817             rules = rsRules[i].eval(context).filter(function(r) {
7818                 if ((r instanceof Rule) && r.variable) {
7819                     // do not pollute the scope if the variable is
7820                     // already there. consider returning false here
7821                     // but we need a way to "return" variable from mixins
7822                     return !(ruleset.variable(r.name));
7823                 }
7824                 return true;
7825             });
7826             rsRules.splice.apply(rsRules, [i, 1].concat(rules));
7827             rsRuleCnt += rules.length - 1;
7828             i += rules.length - 1;
7829             ruleset.resetCache();
7830         } else if (rsRules[i].type === "RulesetCall") {
7831             /*jshint loopfunc:true */
7832             rules = rsRules[i].eval(context).rules.filter(function(r) {
7833                 if ((r instanceof Rule) && r.variable) {
7834                     // do not pollute the scope at all
7835                     return false;
7836                 }
7837                 return true;
7838             });
7839             rsRules.splice.apply(rsRules, [i, 1].concat(rules));
7840             rsRuleCnt += rules.length - 1;
7841             i += rules.length - 1;
7842             ruleset.resetCache();
7843         }
7844     }
7845
7846     // Evaluate everything else
7847     for (i = 0; i < rsRules.length; i++) {
7848         rule = rsRules[i];
7849         if (!rule.evalFirst) {
7850             rsRules[i] = rule = rule.eval ? rule.eval(context) : rule;
7851         }
7852     }
7853
7854     // Evaluate everything else
7855     for (i = 0; i < rsRules.length; i++) {
7856         rule = rsRules[i];
7857         // for rulesets, check if it is a css guard and can be removed
7858         if (rule instanceof Ruleset && rule.selectors && rule.selectors.length === 1) {
7859             // check if it can be folded in (e.g. & where)
7860             if (rule.selectors[0].isJustParentSelector()) {
7861                 rsRules.splice(i--, 1);
7862
7863                 for (var j = 0; j < rule.rules.length; j++) {
7864                     subRule = rule.rules[j];
7865                     subRule.copyVisibilityInfo(rule.visibilityInfo());
7866                     if (!(subRule instanceof Rule) || !subRule.variable) {
7867                         rsRules.splice(++i, 0, subRule);
7868                     }
7869                 }
7870             }
7871         }
7872     }
7873
7874     // Pop the stack
7875     ctxFrames.shift();
7876     ctxSelectors.shift();
7877
7878     if (context.mediaBlocks) {
7879         for (i = mediaBlockCount; i < context.mediaBlocks.length; i++) {
7880             context.mediaBlocks[i].bubbleSelectors(selectors);
7881         }
7882     }
7883
7884     return ruleset;
7885 };
7886 Ruleset.prototype.evalImports = function(context) {
7887     var rules = this.rules, i, importRules;
7888     if (!rules) { return; }
7889
7890     for (i = 0; i < rules.length; i++) {
7891         if (rules[i].type === "Import") {
7892             importRules = rules[i].eval(context);
7893             if (importRules && (importRules.length || importRules.length === 0)) {
7894                 rules.splice.apply(rules, [i, 1].concat(importRules));
7895                 i+= importRules.length - 1;
7896             } else {
7897                 rules.splice(i, 1, importRules);
7898             }
7899             this.resetCache();
7900         }
7901     }
7902 };
7903 Ruleset.prototype.makeImportant = function() {
7904     var result = new Ruleset(this.selectors, this.rules.map(function (r) {
7905         if (r.makeImportant) {
7906             return r.makeImportant();
7907         } else {
7908             return r;
7909         }
7910     }), this.strictImports, this.visibilityInfo());
7911
7912     return result;
7913 };
7914 Ruleset.prototype.matchArgs = function (args) {
7915     return !args || args.length === 0;
7916 };
7917 // lets you call a css selector with a guard
7918 Ruleset.prototype.matchCondition = function (args, context) {
7919     var lastSelector = this.selectors[this.selectors.length - 1];
7920     if (!lastSelector.evaldCondition) {
7921         return false;
7922     }
7923     if (lastSelector.condition &&
7924         !lastSelector.condition.eval(
7925             new contexts.Eval(context,
7926                 context.frames))) {
7927         return false;
7928     }
7929     return true;
7930 };
7931 Ruleset.prototype.resetCache = function () {
7932     this._rulesets = null;
7933     this._variables = null;
7934     this._lookups = {};
7935 };
7936 Ruleset.prototype.variables = function () {
7937     if (!this._variables) {
7938         this._variables = !this.rules ? {} : this.rules.reduce(function (hash, r) {
7939             if (r instanceof Rule && r.variable === true) {
7940                 hash[r.name] = r;
7941             }
7942             // when evaluating variables in an import statement, imports have not been eval'd
7943             // so we need to go inside import statements.
7944             // guard against root being a string (in the case of inlined less)
7945             if (r.type === "Import" && r.root && r.root.variables) {
7946                 var vars = r.root.variables();
7947                 for (var name in vars) {
7948                     if (vars.hasOwnProperty(name)) {
7949                         hash[name] = vars[name];
7950                     }
7951                 }
7952             }
7953             return hash;
7954         }, {});
7955     }
7956     return this._variables;
7957 };
7958 Ruleset.prototype.variable = function (name) {
7959     return this.variables()[name];
7960 };
7961 Ruleset.prototype.rulesets = function () {
7962     if (!this.rules) { return []; }
7963
7964     var filtRules = [], rules = this.rules, cnt = rules.length,
7965         i, rule;
7966
7967     for (i = 0; i < cnt; i++) {
7968         rule = rules[i];
7969         if (rule.isRuleset) {
7970             filtRules.push(rule);
7971         }
7972     }
7973
7974     return filtRules;
7975 };
7976 Ruleset.prototype.prependRule = function (rule) {
7977     var rules = this.rules;
7978     if (rules) {
7979         rules.unshift(rule);
7980     } else {
7981         this.rules = [ rule ];
7982     }
7983 };
7984 Ruleset.prototype.find = function (selector, self, filter) {
7985     self = self || this;
7986     var rules = [], match, foundMixins,
7987         key = selector.toCSS();
7988
7989     if (key in this._lookups) { return this._lookups[key]; }
7990
7991     this.rulesets().forEach(function (rule) {
7992         if (rule !== self) {
7993             for (var j = 0; j < rule.selectors.length; j++) {
7994                 match = selector.match(rule.selectors[j]);
7995                 if (match) {
7996                     if (selector.elements.length > match) {
7997                         if (!filter || filter(rule)) {
7998                             foundMixins = rule.find(new Selector(selector.elements.slice(match)), self, filter);
7999                             for (var i = 0; i < foundMixins.length; ++i) {
8000                                 foundMixins[i].path.push(rule);
8001                             }
8002                             Array.prototype.push.apply(rules, foundMixins);
8003                         }
8004                     } else {
8005                         rules.push({ rule: rule, path: []});
8006                     }
8007                     break;
8008                 }
8009             }
8010         }
8011     });
8012     this._lookups[key] = rules;
8013     return rules;
8014 };
8015 Ruleset.prototype.genCSS = function (context, output) {
8016     var i, j,
8017         charsetRuleNodes = [],
8018         ruleNodes = [],
8019         debugInfo,     // Line number debugging
8020         rule,
8021         path;
8022
8023     context.tabLevel = (context.tabLevel || 0);
8024
8025     if (!this.root) {
8026         context.tabLevel++;
8027     }
8028
8029     var tabRuleStr = context.compress ? '' : Array(context.tabLevel + 1).join("  "),
8030         tabSetStr = context.compress ? '' : Array(context.tabLevel).join("  "),
8031         sep;
8032
8033     function isRulesetLikeNode(rule) {
8034         // if it has nested rules, then it should be treated like a ruleset
8035         // medias and comments do not have nested rules, but should be treated like rulesets anyway
8036         // some directives and anonymous nodes are ruleset like, others are not
8037         if (typeof rule.isRulesetLike === "boolean") {
8038             return rule.isRulesetLike;
8039         } else if (typeof rule.isRulesetLike === "function") {
8040             return rule.isRulesetLike();
8041         }
8042
8043         //anything else is assumed to be a rule
8044         return false;
8045     }
8046
8047     var charsetNodeIndex = 0;
8048     var importNodeIndex = 0;
8049     for (i = 0; i < this.rules.length; i++) {
8050         rule = this.rules[i];
8051         if (rule.type === "Comment") {
8052             if (importNodeIndex === i) {
8053                 importNodeIndex++;
8054             }
8055             ruleNodes.push(rule);
8056         } else if (rule.isCharset && rule.isCharset()) {
8057             ruleNodes.splice(charsetNodeIndex, 0, rule);
8058             charsetNodeIndex++;
8059             importNodeIndex++;
8060         } else if (rule.type === "Import") {
8061             ruleNodes.splice(importNodeIndex, 0, rule);
8062             importNodeIndex++;
8063         } else {
8064             ruleNodes.push(rule);
8065         }
8066     }
8067     ruleNodes = charsetRuleNodes.concat(ruleNodes);
8068
8069     // If this is the root node, we don't render
8070     // a selector, or {}.
8071     if (!this.root) {
8072         debugInfo = getDebugInfo(context, this, tabSetStr);
8073
8074         if (debugInfo) {
8075             output.add(debugInfo);
8076             output.add(tabSetStr);
8077         }
8078
8079         var paths = this.paths, pathCnt = paths.length,
8080             pathSubCnt;
8081
8082         sep = context.compress ? ',' : (',\n' + tabSetStr);
8083
8084         for (i = 0; i < pathCnt; i++) {
8085             path = paths[i];
8086             if (!(pathSubCnt = path.length)) { continue; }
8087             if (i > 0) { output.add(sep); }
8088
8089             context.firstSelector = true;
8090             path[0].genCSS(context, output);
8091
8092             context.firstSelector = false;
8093             for (j = 1; j < pathSubCnt; j++) {
8094                 path[j].genCSS(context, output);
8095             }
8096         }
8097
8098         output.add((context.compress ? '{' : ' {\n') + tabRuleStr);
8099     }
8100
8101     // Compile rules and rulesets
8102     for (i = 0; i < ruleNodes.length; i++) {
8103         rule = ruleNodes[i];
8104
8105         if (i + 1 === ruleNodes.length) {
8106             context.lastRule = true;
8107         }
8108
8109         var currentLastRule = context.lastRule;
8110         if (isRulesetLikeNode(rule)) {
8111             context.lastRule = false;
8112         }
8113
8114         if (rule.genCSS) {
8115             rule.genCSS(context, output);
8116         } else if (rule.value) {
8117             output.add(rule.value.toString());
8118         }
8119
8120         context.lastRule = currentLastRule;
8121
8122         if (!context.lastRule) {
8123             output.add(context.compress ? '' : ('\n' + tabRuleStr));
8124         } else {
8125             context.lastRule = false;
8126         }
8127     }
8128
8129     if (!this.root) {
8130         output.add((context.compress ? '}' : '\n' + tabSetStr + '}'));
8131         context.tabLevel--;
8132     }
8133
8134     if (!output.isEmpty() && !context.compress && this.firstRoot) {
8135         output.add('\n');
8136     }
8137 };
8138
8139 Ruleset.prototype.joinSelectors = function (paths, context, selectors) {
8140     for (var s = 0; s < selectors.length; s++) {
8141         this.joinSelector(paths, context, selectors[s]);
8142     }
8143 };
8144
8145 Ruleset.prototype.joinSelector = function (paths, context, selector) {
8146
8147     function createParenthesis(elementsToPak, originalElement) {
8148         var replacementParen, j;
8149         if (elementsToPak.length === 0) {
8150             replacementParen = new Paren(elementsToPak[0]);
8151         } else {
8152             var insideParent = [];
8153             for (j = 0; j < elementsToPak.length; j++) {
8154                 insideParent.push(new Element(null, elementsToPak[j], originalElement.index, originalElement.currentFileInfo));
8155             }
8156             replacementParen = new Paren(new Selector(insideParent));
8157         }
8158         return replacementParen;
8159     }
8160
8161     function createSelector(containedElement, originalElement) {
8162         var element, selector;
8163         element = new Element(null, containedElement, originalElement.index, originalElement.currentFileInfo);
8164         selector = new Selector([element]);
8165         return selector;
8166     }
8167
8168     // joins selector path from `beginningPath` with selector path in `addPath`
8169     // `replacedElement` contains element that is being replaced by `addPath`
8170     // returns concatenated path
8171     function addReplacementIntoPath(beginningPath, addPath, replacedElement, originalSelector) {
8172         var newSelectorPath, lastSelector, newJoinedSelector;
8173         // our new selector path
8174         newSelectorPath = [];
8175
8176         //construct the joined selector - if & is the first thing this will be empty,
8177         // if not newJoinedSelector will be the last set of elements in the selector
8178         if (beginningPath.length > 0) {
8179             newSelectorPath = beginningPath.slice(0);
8180             lastSelector = newSelectorPath.pop();
8181             newJoinedSelector = originalSelector.createDerived(lastSelector.elements.slice(0));
8182         }
8183         else {
8184             newJoinedSelector = originalSelector.createDerived([]);
8185         }
8186
8187         if (addPath.length > 0) {
8188             // /deep/ is a combinator that is valid without anything in front of it
8189             // so if the & does not have a combinator that is "" or " " then
8190             // and there is a combinator on the parent, then grab that.
8191             // this also allows + a { & .b { .a & { ... though not sure why you would want to do that
8192             var combinator = replacedElement.combinator, parentEl = addPath[0].elements[0];
8193             if (combinator.emptyOrWhitespace && !parentEl.combinator.emptyOrWhitespace) {
8194                 combinator = parentEl.combinator;
8195             }
8196             // join the elements so far with the first part of the parent
8197             newJoinedSelector.elements.push(new Element(combinator, parentEl.value, replacedElement.index, replacedElement.currentFileInfo));
8198             newJoinedSelector.elements = newJoinedSelector.elements.concat(addPath[0].elements.slice(1));
8199         }
8200
8201         // now add the joined selector - but only if it is not empty
8202         if (newJoinedSelector.elements.length !== 0) {
8203             newSelectorPath.push(newJoinedSelector);
8204         }
8205
8206         //put together the parent selectors after the join (e.g. the rest of the parent)
8207         if (addPath.length > 1) {
8208             var restOfPath = addPath.slice(1);
8209             restOfPath = restOfPath.map(function (selector) {
8210                 return selector.createDerived(selector.elements, []);
8211             });
8212             newSelectorPath = newSelectorPath.concat(restOfPath);
8213         }
8214         return newSelectorPath;
8215     }
8216
8217     // joins selector path from `beginningPath` with every selector path in `addPaths` array
8218     // `replacedElement` contains element that is being replaced by `addPath`
8219     // returns array with all concatenated paths
8220     function addAllReplacementsIntoPath( beginningPath, addPaths, replacedElement, originalSelector, result) {
8221         var j;
8222         for (j = 0; j < beginningPath.length; j++) {
8223             var newSelectorPath = addReplacementIntoPath(beginningPath[j], addPaths, replacedElement, originalSelector);
8224             result.push(newSelectorPath);
8225         }
8226         return result;
8227     }
8228
8229     function mergeElementsOnToSelectors(elements, selectors) {
8230         var i, sel;
8231
8232         if (elements.length === 0) {
8233             return ;
8234         }
8235         if (selectors.length === 0) {
8236             selectors.push([ new Selector(elements) ]);
8237             return;
8238         }
8239
8240         for (i = 0; i < selectors.length; i++) {
8241             sel = selectors[i];
8242
8243             // if the previous thing in sel is a parent this needs to join on to it
8244             if (sel.length > 0) {
8245                 sel[sel.length - 1] = sel[sel.length - 1].createDerived(sel[sel.length - 1].elements.concat(elements));
8246             }
8247             else {
8248                 sel.push(new Selector(elements));
8249             }
8250         }
8251     }
8252
8253     // replace all parent selectors inside `inSelector` by content of `context` array
8254     // resulting selectors are returned inside `paths` array
8255     // returns true if `inSelector` contained at least one parent selector
8256     function replaceParentSelector(paths, context, inSelector) {
8257         // The paths are [[Selector]]
8258         // The first list is a list of comma separated selectors
8259         // The inner list is a list of inheritance separated selectors
8260         // e.g.
8261         // .a, .b {
8262         //   .c {
8263         //   }
8264         // }
8265         // == [[.a] [.c]] [[.b] [.c]]
8266         //
8267         var i, j, k, currentElements, newSelectors, selectorsMultiplied, sel, el, hadParentSelector = false, length, lastSelector;
8268         function findNestedSelector(element) {
8269             var maybeSelector;
8270             if (element.value.type !== 'Paren') {
8271                 return null;
8272             }
8273
8274             maybeSelector = element.value.value;
8275             if (maybeSelector.type !== 'Selector') {
8276                 return null;
8277             }
8278
8279             return maybeSelector;
8280         }
8281
8282         // the elements from the current selector so far
8283         currentElements = [];
8284         // the current list of new selectors to add to the path.
8285         // We will build it up. We initiate it with one empty selector as we "multiply" the new selectors
8286         // by the parents
8287         newSelectors = [
8288             []
8289         ];
8290
8291         for (i = 0; i < inSelector.elements.length; i++) {
8292             el = inSelector.elements[i];
8293             // non parent reference elements just get added
8294             if (el.value !== "&") {
8295                 var nestedSelector = findNestedSelector(el);
8296                 if (nestedSelector != null) {
8297                     // merge the current list of non parent selector elements
8298                     // on to the current list of selectors to add
8299                     mergeElementsOnToSelectors(currentElements, newSelectors);
8300
8301                     var nestedPaths = [], replaced, replacedNewSelectors = [];
8302                     replaced = replaceParentSelector(nestedPaths, context, nestedSelector);
8303                     hadParentSelector = hadParentSelector || replaced;
8304                     //the nestedPaths array should have only one member - replaceParentSelector does not multiply selectors
8305                     for (k = 0; k < nestedPaths.length; k++) {
8306                         var replacementSelector = createSelector(createParenthesis(nestedPaths[k], el), el);
8307                         addAllReplacementsIntoPath(newSelectors, [replacementSelector], el, inSelector, replacedNewSelectors);
8308                     }
8309                     newSelectors = replacedNewSelectors;
8310                     currentElements = [];
8311
8312                 } else {
8313                     currentElements.push(el);
8314                 }
8315
8316             } else {
8317                 hadParentSelector = true;
8318                 // the new list of selectors to add
8319                 selectorsMultiplied = [];
8320
8321                 // merge the current list of non parent selector elements
8322                 // on to the current list of selectors to add
8323                 mergeElementsOnToSelectors(currentElements, newSelectors);
8324
8325                 // loop through our current selectors
8326                 for (j = 0; j < newSelectors.length; j++) {
8327                     sel = newSelectors[j];
8328                     // if we don't have any parent paths, the & might be in a mixin so that it can be used
8329                     // whether there are parents or not
8330                     if (context.length === 0) {
8331                         // the combinator used on el should now be applied to the next element instead so that
8332                         // it is not lost
8333                         if (sel.length > 0) {
8334                             sel[0].elements.push(new Element(el.combinator, '', el.index, el.currentFileInfo));
8335                         }
8336                         selectorsMultiplied.push(sel);
8337                     }
8338                     else {
8339                         // and the parent selectors
8340                         for (k = 0; k < context.length; k++) {
8341                             // We need to put the current selectors
8342                             // then join the last selector's elements on to the parents selectors
8343                             var newSelectorPath = addReplacementIntoPath(sel, context[k], el, inSelector);
8344                             // add that to our new set of selectors
8345                             selectorsMultiplied.push(newSelectorPath);
8346                         }
8347                     }
8348                 }
8349
8350                 // our new selectors has been multiplied, so reset the state
8351                 newSelectors = selectorsMultiplied;
8352                 currentElements = [];
8353             }
8354         }
8355
8356         // if we have any elements left over (e.g. .a& .b == .b)
8357         // add them on to all the current selectors
8358         mergeElementsOnToSelectors(currentElements, newSelectors);
8359
8360         for (i = 0; i < newSelectors.length; i++) {
8361             length = newSelectors[i].length;
8362             if (length > 0) {
8363                 paths.push(newSelectors[i]);
8364                 lastSelector = newSelectors[i][length - 1];
8365                 newSelectors[i][length - 1] = lastSelector.createDerived(lastSelector.elements, inSelector.extendList);
8366                 //newSelectors[i][length - 1].copyVisibilityInfo(inSelector.visibilityInfo());
8367             }
8368         }
8369
8370         return hadParentSelector;
8371     }
8372
8373     function deriveSelector(visibilityInfo, deriveFrom) {
8374         var newSelector = deriveFrom.createDerived(deriveFrom.elements, deriveFrom.extendList, deriveFrom.evaldCondition);
8375         newSelector.copyVisibilityInfo(visibilityInfo);
8376         return newSelector;
8377     }
8378
8379     // joinSelector code follows
8380     var i, newPaths, hadParentSelector;
8381
8382     newPaths = [];
8383     hadParentSelector = replaceParentSelector(newPaths, context, selector);
8384
8385     if (!hadParentSelector) {
8386         if (context.length > 0) {
8387             newPaths = [];
8388             for (i = 0; i < context.length; i++) {
8389                 //var concatenated = [];
8390                 //context[i].forEach(function(entry) {
8391                 //    var newEntry = entry.createDerived(entry.elements, entry.extendList, entry.evaldCondition);
8392                 //    newEntry.copyVisibilityInfo(selector.visibilityInfo());
8393                 //    concatenated.push(newEntry);
8394                 //}, this);
8395                 var concatenated = context[i].map(deriveSelector.bind(this, selector.visibilityInfo()));
8396
8397                 concatenated.push(selector);
8398                 newPaths.push(concatenated);
8399             }
8400         }
8401         else {
8402             newPaths = [[selector]];
8403         }
8404     }
8405
8406     for (i = 0; i < newPaths.length; i++) {
8407         paths.push(newPaths[i]);
8408     }
8409
8410 };
8411 module.exports = Ruleset;
8412
8413 },{"../contexts":11,"../functions/default":20,"../functions/function-registry":22,"./debug-info":54,"./element":58,"./node":70,"./paren":72,"./rule":74,"./selector":77}],77:[function(require,module,exports){
8414 var Node = require("./node"),
8415     Element = require("./element");
8416
8417 var Selector = function (elements, extendList, condition, index, currentFileInfo, visibilityInfo) {
8418     this.elements = elements;
8419     this.extendList = extendList;
8420     this.condition = condition;
8421     this.currentFileInfo = currentFileInfo || {};
8422     if (!condition) {
8423         this.evaldCondition = true;
8424     }
8425     this.copyVisibilityInfo(visibilityInfo);
8426 };
8427 Selector.prototype = new Node();
8428 Selector.prototype.type = "Selector";
8429 Selector.prototype.accept = function (visitor) {
8430     if (this.elements) {
8431         this.elements = visitor.visitArray(this.elements);
8432     }
8433     if (this.extendList) {
8434         this.extendList = visitor.visitArray(this.extendList);
8435     }
8436     if (this.condition) {
8437         this.condition = visitor.visit(this.condition);
8438     }
8439 };
8440 Selector.prototype.createDerived = function(elements, extendList, evaldCondition) {
8441     var info = this.visibilityInfo();
8442     evaldCondition = (evaldCondition != null) ? evaldCondition : this.evaldCondition;
8443     var newSelector = new Selector(elements, extendList || this.extendList, null, this.index, this.currentFileInfo, info);
8444     newSelector.evaldCondition = evaldCondition;
8445     newSelector.mediaEmpty = this.mediaEmpty;
8446     return newSelector;
8447 };
8448 Selector.prototype.createEmptySelectors = function() {
8449     var el = new Element('', '&', this.index, this.currentFileInfo),
8450         sels = [new Selector([el], null, null, this.index, this.currentFileInfo)];
8451     sels[0].mediaEmpty = true;
8452     return sels;
8453 };
8454 Selector.prototype.match = function (other) {
8455     var elements = this.elements,
8456         len = elements.length,
8457         olen, i;
8458
8459     other.CacheElements();
8460
8461     olen = other._elements.length;
8462     if (olen === 0 || len < olen) {
8463         return 0;
8464     } else {
8465         for (i = 0; i < olen; i++) {
8466             if (elements[i].value !== other._elements[i]) {
8467                 return 0;
8468             }
8469         }
8470     }
8471
8472     return olen; // return number of matched elements
8473 };
8474 Selector.prototype.CacheElements = function() {
8475     if (this._elements) {
8476         return;
8477     }
8478
8479     var elements = this.elements.map( function(v) {
8480         return v.combinator.value + (v.value.value || v.value);
8481     }).join("").match(/[,&#\*\.\w-]([\w-]|(\\.))*/g);
8482
8483     if (elements) {
8484         if (elements[0] === "&") {
8485             elements.shift();
8486         }
8487     } else {
8488         elements = [];
8489     }
8490
8491     this._elements = elements;
8492 };
8493 Selector.prototype.isJustParentSelector = function() {
8494     return !this.mediaEmpty &&
8495         this.elements.length === 1 &&
8496         this.elements[0].value === '&' &&
8497         (this.elements[0].combinator.value === ' ' || this.elements[0].combinator.value === '');
8498 };
8499 Selector.prototype.eval = function (context) {
8500     var evaldCondition = this.condition && this.condition.eval(context),
8501         elements = this.elements, extendList = this.extendList;
8502
8503     elements = elements && elements.map(function (e) { return e.eval(context); });
8504     extendList = extendList && extendList.map(function(extend) { return extend.eval(context); });
8505
8506     return this.createDerived(elements, extendList, evaldCondition);
8507 };
8508 Selector.prototype.genCSS = function (context, output) {
8509     var i, element;
8510     if ((!context || !context.firstSelector) && this.elements[0].combinator.value === "") {
8511         output.add(' ', this.currentFileInfo, this.index);
8512     }
8513     if (!this._css) {
8514         //TODO caching? speed comparison?
8515         for (i = 0; i < this.elements.length; i++) {
8516             element = this.elements[i];
8517             element.genCSS(context, output);
8518         }
8519     }
8520 };
8521 Selector.prototype.getIsOutput = function() {
8522     return this.evaldCondition;
8523 };
8524 module.exports = Selector;
8525
8526 },{"./element":58,"./node":70}],78:[function(require,module,exports){
8527 var Node = require("./node");
8528
8529 var UnicodeDescriptor = function (value) {
8530     this.value = value;
8531 };
8532 UnicodeDescriptor.prototype = new Node();
8533 UnicodeDescriptor.prototype.type = "UnicodeDescriptor";
8534
8535 module.exports = UnicodeDescriptor;
8536
8537 },{"./node":70}],79:[function(require,module,exports){
8538 var Node = require("./node"),
8539     unitConversions = require("../data/unit-conversions");
8540
8541 var Unit = function (numerator, denominator, backupUnit) {
8542     this.numerator = numerator ? numerator.slice(0).sort() : [];
8543     this.denominator = denominator ? denominator.slice(0).sort() : [];
8544     if (backupUnit) {
8545         this.backupUnit = backupUnit;
8546     } else if (numerator && numerator.length) {
8547         this.backupUnit = numerator[0];
8548     }
8549 };
8550
8551 Unit.prototype = new Node();
8552 Unit.prototype.type = "Unit";
8553 Unit.prototype.clone = function () {
8554     return new Unit(this.numerator.slice(0), this.denominator.slice(0), this.backupUnit);
8555 };
8556 Unit.prototype.genCSS = function (context, output) {
8557     // Dimension checks the unit is singular and throws an error if in strict math mode.
8558     var strictUnits = context && context.strictUnits;
8559     if (this.numerator.length === 1) {
8560         output.add(this.numerator[0]); // the ideal situation
8561     } else if (!strictUnits && this.backupUnit) {
8562         output.add(this.backupUnit);
8563     } else if (!strictUnits && this.denominator.length) {
8564         output.add(this.denominator[0]);
8565     }
8566 };
8567 Unit.prototype.toString = function () {
8568     var i, returnStr = this.numerator.join("*");
8569     for (i = 0; i < this.denominator.length; i++) {
8570         returnStr += "/" + this.denominator[i];
8571     }
8572     return returnStr;
8573 };
8574 Unit.prototype.compare = function (other) {
8575     return this.is(other.toString()) ? 0 : undefined;
8576 };
8577 Unit.prototype.is = function (unitString) {
8578     return this.toString().toUpperCase() === unitString.toUpperCase();
8579 };
8580 Unit.prototype.isLength = function () {
8581     return Boolean(this.toCSS().match(/px|em|%|in|cm|mm|pc|pt|ex/));
8582 };
8583 Unit.prototype.isEmpty = function () {
8584     return this.numerator.length === 0 && this.denominator.length === 0;
8585 };
8586 Unit.prototype.isSingular = function() {
8587     return this.numerator.length <= 1 && this.denominator.length === 0;
8588 };
8589 Unit.prototype.map = function(callback) {
8590     var i;
8591
8592     for (i = 0; i < this.numerator.length; i++) {
8593         this.numerator[i] = callback(this.numerator[i], false);
8594     }
8595
8596     for (i = 0; i < this.denominator.length; i++) {
8597         this.denominator[i] = callback(this.denominator[i], true);
8598     }
8599 };
8600 Unit.prototype.usedUnits = function() {
8601     var group, result = {}, mapUnit, groupName;
8602
8603     mapUnit = function (atomicUnit) {
8604         /*jshint loopfunc:true */
8605         if (group.hasOwnProperty(atomicUnit) && !result[groupName]) {
8606             result[groupName] = atomicUnit;
8607         }
8608
8609         return atomicUnit;
8610     };
8611
8612     for (groupName in unitConversions) {
8613         if (unitConversions.hasOwnProperty(groupName)) {
8614             group = unitConversions[groupName];
8615
8616             this.map(mapUnit);
8617         }
8618     }
8619
8620     return result;
8621 };
8622 Unit.prototype.cancel = function () {
8623     var counter = {}, atomicUnit, i;
8624
8625     for (i = 0; i < this.numerator.length; i++) {
8626         atomicUnit = this.numerator[i];
8627         counter[atomicUnit] = (counter[atomicUnit] || 0) + 1;
8628     }
8629
8630     for (i = 0; i < this.denominator.length; i++) {
8631         atomicUnit = this.denominator[i];
8632         counter[atomicUnit] = (counter[atomicUnit] || 0) - 1;
8633     }
8634
8635     this.numerator = [];
8636     this.denominator = [];
8637
8638     for (atomicUnit in counter) {
8639         if (counter.hasOwnProperty(atomicUnit)) {
8640             var count = counter[atomicUnit];
8641
8642             if (count > 0) {
8643                 for (i = 0; i < count; i++) {
8644                     this.numerator.push(atomicUnit);
8645                 }
8646             } else if (count < 0) {
8647                 for (i = 0; i < -count; i++) {
8648                     this.denominator.push(atomicUnit);
8649                 }
8650             }
8651         }
8652     }
8653
8654     this.numerator.sort();
8655     this.denominator.sort();
8656 };
8657 module.exports = Unit;
8658
8659 },{"../data/unit-conversions":14,"./node":70}],80:[function(require,module,exports){
8660 var Node = require("./node");
8661
8662 var URL = function (val, index, currentFileInfo, isEvald) {
8663     this.value = val;
8664     this.currentFileInfo = currentFileInfo;
8665     this.index = index;
8666     this.isEvald = isEvald;
8667 };
8668 URL.prototype = new Node();
8669 URL.prototype.type = "Url";
8670 URL.prototype.accept = function (visitor) {
8671     this.value = visitor.visit(this.value);
8672 };
8673 URL.prototype.genCSS = function (context, output) {
8674     output.add("url(");
8675     this.value.genCSS(context, output);
8676     output.add(")");
8677 };
8678 URL.prototype.eval = function (context) {
8679     var val = this.value.eval(context),
8680         rootpath;
8681
8682     if (!this.isEvald) {
8683         // Add the base path if the URL is relative
8684         rootpath = this.currentFileInfo && this.currentFileInfo.rootpath;
8685         if (rootpath &&
8686             typeof val.value === "string" &&
8687             context.isPathRelative(val.value)) {
8688
8689             if (!val.quote) {
8690                 rootpath = rootpath.replace(/[\(\)'"\s]/g, function(match) { return "\\" + match; });
8691             }
8692             val.value = rootpath + val.value;
8693         }
8694
8695         val.value = context.normalizePath(val.value);
8696
8697         // Add url args if enabled
8698         if (context.urlArgs) {
8699             if (!val.value.match(/^\s*data:/)) {
8700                 var delimiter = val.value.indexOf('?') === -1 ? '?' : '&';
8701                 var urlArgs = delimiter + context.urlArgs;
8702                 if (val.value.indexOf('#') !== -1) {
8703                     val.value = val.value.replace('#', urlArgs + '#');
8704                 } else {
8705                     val.value += urlArgs;
8706                 }
8707             }
8708         }
8709     }
8710
8711     return new URL(val, this.index, this.currentFileInfo, true);
8712 };
8713 module.exports = URL;
8714
8715 },{"./node":70}],81:[function(require,module,exports){
8716 var Node = require("./node");
8717
8718 var Value = function (value) {
8719     this.value = value;
8720     if (!value) {
8721         throw new Error("Value requires an array argument");
8722     }
8723 };
8724 Value.prototype = new Node();
8725 Value.prototype.type = "Value";
8726 Value.prototype.accept = function (visitor) {
8727     if (this.value) {
8728         this.value = visitor.visitArray(this.value);
8729     }
8730 };
8731 Value.prototype.eval = function (context) {
8732     if (this.value.length === 1) {
8733         return this.value[0].eval(context);
8734     } else {
8735         return new Value(this.value.map(function (v) {
8736             return v.eval(context);
8737         }));
8738     }
8739 };
8740 Value.prototype.genCSS = function (context, output) {
8741     var i;
8742     for (i = 0; i < this.value.length; i++) {
8743         this.value[i].genCSS(context, output);
8744         if (i + 1 < this.value.length) {
8745             output.add((context && context.compress) ? ',' : ', ');
8746         }
8747     }
8748 };
8749 module.exports = Value;
8750
8751 },{"./node":70}],82:[function(require,module,exports){
8752 var Node = require("./node");
8753
8754 var Variable = function (name, index, currentFileInfo) {
8755     this.name = name;
8756     this.index = index;
8757     this.currentFileInfo = currentFileInfo || {};
8758 };
8759 Variable.prototype = new Node();
8760 Variable.prototype.type = "Variable";
8761 Variable.prototype.eval = function (context) {
8762     var variable, name = this.name;
8763
8764     if (name.indexOf('@@') === 0) {
8765         name = '@' + new Variable(name.slice(1), this.index, this.currentFileInfo).eval(context).value;
8766     }
8767
8768     if (this.evaluating) {
8769         throw { type: 'Name',
8770                 message: "Recursive variable definition for " + name,
8771                 filename: this.currentFileInfo.filename,
8772                 index: this.index };
8773     }
8774
8775     this.evaluating = true;
8776
8777     variable = this.find(context.frames, function (frame) {
8778         var v = frame.variable(name);
8779         if (v) {
8780             if (v.important) {
8781                 var importantScope = context.importantScope[context.importantScope.length - 1];
8782                 importantScope.important = v.important;
8783             }
8784             return v.value.eval(context);
8785         }
8786     });
8787     if (variable) {
8788         this.evaluating = false;
8789         return variable;
8790     } else {
8791         throw { type: 'Name',
8792                 message: "variable " + name + " is undefined",
8793                 filename: this.currentFileInfo.filename,
8794                 index: this.index };
8795     }
8796 };
8797 Variable.prototype.find = function (obj, fun) {
8798     for (var i = 0, r; i < obj.length; i++) {
8799         r = fun.call(obj, obj[i]);
8800         if (r) { return r; }
8801     }
8802     return null;
8803 };
8804 module.exports = Variable;
8805
8806 },{"./node":70}],83:[function(require,module,exports){
8807 module.exports = {
8808     getLocation: function(index, inputStream) {
8809         var n = index + 1,
8810             line = null,
8811             column = -1;
8812
8813         while (--n >= 0 && inputStream.charAt(n) !== '\n') {
8814             column++;
8815         }
8816
8817         if (typeof index === 'number') {
8818             line = (inputStream.slice(0, index).match(/\n/g) || "").length;
8819         }
8820
8821         return {
8822             line: line,
8823             column: column
8824         };
8825     }
8826 };
8827
8828 },{}],84:[function(require,module,exports){
8829 var tree = require("../tree"),
8830     Visitor = require("./visitor"),
8831     logger = require("../logger");
8832
8833 /*jshint loopfunc:true */
8834
8835 var ExtendFinderVisitor = function() {
8836     this._visitor = new Visitor(this);
8837     this.contexts = [];
8838     this.allExtendsStack = [[]];
8839 };
8840
8841 ExtendFinderVisitor.prototype = {
8842     run: function (root) {
8843         root = this._visitor.visit(root);
8844         root.allExtends = this.allExtendsStack[0];
8845         return root;
8846     },
8847     visitRule: function (ruleNode, visitArgs) {
8848         visitArgs.visitDeeper = false;
8849     },
8850     visitMixinDefinition: function (mixinDefinitionNode, visitArgs) {
8851         visitArgs.visitDeeper = false;
8852     },
8853     visitRuleset: function (rulesetNode, visitArgs) {
8854         if (rulesetNode.root) {
8855             return;
8856         }
8857
8858         var i, j, extend, allSelectorsExtendList = [], extendList;
8859
8860         // get &:extend(.a); rules which apply to all selectors in this ruleset
8861         var rules = rulesetNode.rules, ruleCnt = rules ? rules.length : 0;
8862         for (i = 0; i < ruleCnt; i++) {
8863             if (rulesetNode.rules[i] instanceof tree.Extend) {
8864                 allSelectorsExtendList.push(rules[i]);
8865                 rulesetNode.extendOnEveryPath = true;
8866             }
8867         }
8868
8869         // now find every selector and apply the extends that apply to all extends
8870         // and the ones which apply to an individual extend
8871         var paths = rulesetNode.paths;
8872         for (i = 0; i < paths.length; i++) {
8873             var selectorPath = paths[i],
8874                 selector = selectorPath[selectorPath.length - 1],
8875                 selExtendList = selector.extendList;
8876
8877             extendList = selExtendList ? selExtendList.slice(0).concat(allSelectorsExtendList)
8878                                        : allSelectorsExtendList;
8879
8880             if (extendList) {
8881                 extendList = extendList.map(function(allSelectorsExtend) {
8882                     return allSelectorsExtend.clone();
8883                 });
8884             }
8885
8886             for (j = 0; j < extendList.length; j++) {
8887                 this.foundExtends = true;
8888                 extend = extendList[j];
8889                 extend.findSelfSelectors(selectorPath);
8890                 extend.ruleset = rulesetNode;
8891                 if (j === 0) { extend.firstExtendOnThisSelectorPath = true; }
8892                 this.allExtendsStack[this.allExtendsStack.length - 1].push(extend);
8893             }
8894         }
8895
8896         this.contexts.push(rulesetNode.selectors);
8897     },
8898     visitRulesetOut: function (rulesetNode) {
8899         if (!rulesetNode.root) {
8900             this.contexts.length = this.contexts.length - 1;
8901         }
8902     },
8903     visitMedia: function (mediaNode, visitArgs) {
8904         mediaNode.allExtends = [];
8905         this.allExtendsStack.push(mediaNode.allExtends);
8906     },
8907     visitMediaOut: function (mediaNode) {
8908         this.allExtendsStack.length = this.allExtendsStack.length - 1;
8909     },
8910     visitDirective: function (directiveNode, visitArgs) {
8911         directiveNode.allExtends = [];
8912         this.allExtendsStack.push(directiveNode.allExtends);
8913     },
8914     visitDirectiveOut: function (directiveNode) {
8915         this.allExtendsStack.length = this.allExtendsStack.length - 1;
8916     }
8917 };
8918
8919 var ProcessExtendsVisitor = function() {
8920     this._visitor = new Visitor(this);
8921 };
8922
8923 ProcessExtendsVisitor.prototype = {
8924     run: function(root) {
8925         var extendFinder = new ExtendFinderVisitor();
8926         this.extendIndices = {};
8927         extendFinder.run(root);
8928         if (!extendFinder.foundExtends) { return root; }
8929         root.allExtends = root.allExtends.concat(this.doExtendChaining(root.allExtends, root.allExtends));
8930         this.allExtendsStack = [root.allExtends];
8931         var newRoot = this._visitor.visit(root);
8932         this.checkExtendsForNonMatched(root.allExtends);
8933         return newRoot;
8934     },
8935     checkExtendsForNonMatched: function(extendList) {
8936         var indices = this.extendIndices;
8937         extendList.filter(function(extend) {
8938             return !extend.hasFoundMatches && extend.parent_ids.length == 1;
8939         }).forEach(function(extend) {
8940                 var selector = "_unknown_";
8941                 try {
8942                     selector = extend.selector.toCSS({});
8943                 }
8944                 catch(_) {}
8945
8946                 if (!indices[extend.index + ' ' + selector]) {
8947                     indices[extend.index + ' ' + selector] = true;
8948                     logger.warn("extend '" + selector + "' has no matches");
8949                 }
8950             });
8951     },
8952     doExtendChaining: function (extendsList, extendsListTarget, iterationCount) {
8953         //
8954         // chaining is different from normal extension.. if we extend an extend then we are not just copying, altering
8955         // and pasting the selector we would do normally, but we are also adding an extend with the same target selector
8956         // this means this new extend can then go and alter other extends
8957         //
8958         // this method deals with all the chaining work - without it, extend is flat and doesn't work on other extend selectors
8959         // this is also the most expensive.. and a match on one selector can cause an extension of a selector we had already
8960         // processed if we look at each selector at a time, as is done in visitRuleset
8961
8962         var extendIndex, targetExtendIndex, matches, extendsToAdd = [], newSelector, extendVisitor = this, selectorPath,
8963             extend, targetExtend, newExtend;
8964
8965         iterationCount = iterationCount || 0;
8966
8967         //loop through comparing every extend with every target extend.
8968         // a target extend is the one on the ruleset we are looking at copy/edit/pasting in place
8969         // e.g.  .a:extend(.b) {}  and .b:extend(.c) {} then the first extend extends the second one
8970         // and the second is the target.
8971         // the separation into two lists allows us to process a subset of chains with a bigger set, as is the
8972         // case when processing media queries
8973         for (extendIndex = 0; extendIndex < extendsList.length; extendIndex++) {
8974             for (targetExtendIndex = 0; targetExtendIndex < extendsListTarget.length; targetExtendIndex++) {
8975
8976                 extend = extendsList[extendIndex];
8977                 targetExtend = extendsListTarget[targetExtendIndex];
8978
8979                 // look for circular references
8980                 if ( extend.parent_ids.indexOf( targetExtend.object_id ) >= 0 ) { continue; }
8981
8982                 // find a match in the target extends self selector (the bit before :extend)
8983                 selectorPath = [targetExtend.selfSelectors[0]];
8984                 matches = extendVisitor.findMatch(extend, selectorPath);
8985
8986                 if (matches.length) {
8987                     extend.hasFoundMatches = true;
8988
8989                     // we found a match, so for each self selector..
8990                     extend.selfSelectors.forEach(function(selfSelector) {
8991                         var info = targetExtend.visibilityInfo();
8992
8993                         // process the extend as usual
8994                         newSelector = extendVisitor.extendSelector(matches, selectorPath, selfSelector, extend.isVisible());
8995
8996                         // but now we create a new extend from it
8997                         newExtend = new(tree.Extend)(targetExtend.selector, targetExtend.option, 0, targetExtend.currentFileInfo, info);
8998                         newExtend.selfSelectors = newSelector;
8999
9000                         // add the extend onto the list of extends for that selector
9001                         newSelector[newSelector.length - 1].extendList = [newExtend];
9002
9003                         // record that we need to add it.
9004                         extendsToAdd.push(newExtend);
9005                         newExtend.ruleset = targetExtend.ruleset;
9006
9007                         //remember its parents for circular references
9008                         newExtend.parent_ids = newExtend.parent_ids.concat(targetExtend.parent_ids, extend.parent_ids);
9009
9010                         // only process the selector once.. if we have :extend(.a,.b) then multiple
9011                         // extends will look at the same selector path, so when extending
9012                         // we know that any others will be duplicates in terms of what is added to the css
9013                         if (targetExtend.firstExtendOnThisSelectorPath) {
9014                             newExtend.firstExtendOnThisSelectorPath = true;
9015                             targetExtend.ruleset.paths.push(newSelector);
9016                         }
9017                     });
9018                 }
9019             }
9020         }
9021
9022         if (extendsToAdd.length) {
9023             // try to detect circular references to stop a stack overflow.
9024             // may no longer be needed.
9025             this.extendChainCount++;
9026             if (iterationCount > 100) {
9027                 var selectorOne = "{unable to calculate}";
9028                 var selectorTwo = "{unable to calculate}";
9029                 try {
9030                     selectorOne = extendsToAdd[0].selfSelectors[0].toCSS();
9031                     selectorTwo = extendsToAdd[0].selector.toCSS();
9032                 }
9033                 catch(e) {}
9034                 throw { message: "extend circular reference detected. One of the circular extends is currently:" +
9035                     selectorOne + ":extend(" + selectorTwo + ")"};
9036             }
9037
9038             // now process the new extends on the existing rules so that we can handle a extending b extending c extending
9039             // d extending e...
9040             return extendsToAdd.concat(extendVisitor.doExtendChaining(extendsToAdd, extendsListTarget, iterationCount + 1));
9041         } else {
9042             return extendsToAdd;
9043         }
9044     },
9045     visitRule: function (ruleNode, visitArgs) {
9046         visitArgs.visitDeeper = false;
9047     },
9048     visitMixinDefinition: function (mixinDefinitionNode, visitArgs) {
9049         visitArgs.visitDeeper = false;
9050     },
9051     visitSelector: function (selectorNode, visitArgs) {
9052         visitArgs.visitDeeper = false;
9053     },
9054     visitRuleset: function (rulesetNode, visitArgs) {
9055         if (rulesetNode.root) {
9056             return;
9057         }
9058         var matches, pathIndex, extendIndex, allExtends = this.allExtendsStack[this.allExtendsStack.length - 1],
9059             selectorsToAdd = [], extendVisitor = this, selectorPath;
9060
9061         // look at each selector path in the ruleset, find any extend matches and then copy, find and replace
9062
9063         for (extendIndex = 0; extendIndex < allExtends.length; extendIndex++) {
9064             for (pathIndex = 0; pathIndex < rulesetNode.paths.length; pathIndex++) {
9065                 selectorPath = rulesetNode.paths[pathIndex];
9066
9067                 // extending extends happens initially, before the main pass
9068                 if (rulesetNode.extendOnEveryPath) { continue; }
9069                 var extendList = selectorPath[selectorPath.length - 1].extendList;
9070                 if (extendList && extendList.length) { continue; }
9071
9072                 matches = this.findMatch(allExtends[extendIndex], selectorPath);
9073
9074                 if (matches.length) {
9075                     allExtends[extendIndex].hasFoundMatches = true;
9076
9077                     allExtends[extendIndex].selfSelectors.forEach(function(selfSelector) {
9078                         var extendedSelectors;
9079                         extendedSelectors = extendVisitor.extendSelector(matches, selectorPath, selfSelector, allExtends[extendIndex].isVisible());
9080                         selectorsToAdd.push(extendedSelectors);
9081                     });
9082                 }
9083             }
9084         }
9085         rulesetNode.paths = rulesetNode.paths.concat(selectorsToAdd);
9086     },
9087     findMatch: function (extend, haystackSelectorPath) {
9088         //
9089         // look through the haystack selector path to try and find the needle - extend.selector
9090         // returns an array of selector matches that can then be replaced
9091         //
9092         var haystackSelectorIndex, hackstackSelector, hackstackElementIndex, haystackElement,
9093             targetCombinator, i,
9094             extendVisitor = this,
9095             needleElements = extend.selector.elements,
9096             potentialMatches = [], potentialMatch, matches = [];
9097
9098         // loop through the haystack elements
9099         for (haystackSelectorIndex = 0; haystackSelectorIndex < haystackSelectorPath.length; haystackSelectorIndex++) {
9100             hackstackSelector = haystackSelectorPath[haystackSelectorIndex];
9101
9102             for (hackstackElementIndex = 0; hackstackElementIndex < hackstackSelector.elements.length; hackstackElementIndex++) {
9103
9104                 haystackElement = hackstackSelector.elements[hackstackElementIndex];
9105
9106                 // if we allow elements before our match we can add a potential match every time. otherwise only at the first element.
9107                 if (extend.allowBefore || (haystackSelectorIndex === 0 && hackstackElementIndex === 0)) {
9108                     potentialMatches.push({pathIndex: haystackSelectorIndex, index: hackstackElementIndex, matched: 0,
9109                         initialCombinator: haystackElement.combinator});
9110                 }
9111
9112                 for (i = 0; i < potentialMatches.length; i++) {
9113                     potentialMatch = potentialMatches[i];
9114
9115                     // selectors add " " onto the first element. When we use & it joins the selectors together, but if we don't
9116                     // then each selector in haystackSelectorPath has a space before it added in the toCSS phase. so we need to
9117                     // work out what the resulting combinator will be
9118                     targetCombinator = haystackElement.combinator.value;
9119                     if (targetCombinator === '' && hackstackElementIndex === 0) {
9120                         targetCombinator = ' ';
9121                     }
9122
9123                     // if we don't match, null our match to indicate failure
9124                     if (!extendVisitor.isElementValuesEqual(needleElements[potentialMatch.matched].value, haystackElement.value) ||
9125                         (potentialMatch.matched > 0 && needleElements[potentialMatch.matched].combinator.value !== targetCombinator)) {
9126                         potentialMatch = null;
9127                     } else {
9128                         potentialMatch.matched++;
9129                     }
9130
9131                     // if we are still valid and have finished, test whether we have elements after and whether these are allowed
9132                     if (potentialMatch) {
9133                         potentialMatch.finished = potentialMatch.matched === needleElements.length;
9134                         if (potentialMatch.finished &&
9135                             (!extend.allowAfter &&
9136                                 (hackstackElementIndex + 1 < hackstackSelector.elements.length || haystackSelectorIndex + 1 < haystackSelectorPath.length))) {
9137                             potentialMatch = null;
9138                         }
9139                     }
9140                     // if null we remove, if not, we are still valid, so either push as a valid match or continue
9141                     if (potentialMatch) {
9142                         if (potentialMatch.finished) {
9143                             potentialMatch.length = needleElements.length;
9144                             potentialMatch.endPathIndex = haystackSelectorIndex;
9145                             potentialMatch.endPathElementIndex = hackstackElementIndex + 1; // index after end of match
9146                             potentialMatches.length = 0; // we don't allow matches to overlap, so start matching again
9147                             matches.push(potentialMatch);
9148                         }
9149                     } else {
9150                         potentialMatches.splice(i, 1);
9151                         i--;
9152                     }
9153                 }
9154             }
9155         }
9156         return matches;
9157     },
9158     isElementValuesEqual: function(elementValue1, elementValue2) {
9159         if (typeof elementValue1 === "string" || typeof elementValue2 === "string") {
9160             return elementValue1 === elementValue2;
9161         }
9162         if (elementValue1 instanceof tree.Attribute) {
9163             if (elementValue1.op !== elementValue2.op || elementValue1.key !== elementValue2.key) {
9164                 return false;
9165             }
9166             if (!elementValue1.value || !elementValue2.value) {
9167                 if (elementValue1.value || elementValue2.value) {
9168                     return false;
9169                 }
9170                 return true;
9171             }
9172             elementValue1 = elementValue1.value.value || elementValue1.value;
9173             elementValue2 = elementValue2.value.value || elementValue2.value;
9174             return elementValue1 === elementValue2;
9175         }
9176         elementValue1 = elementValue1.value;
9177         elementValue2 = elementValue2.value;
9178         if (elementValue1 instanceof tree.Selector) {
9179             if (!(elementValue2 instanceof tree.Selector) || elementValue1.elements.length !== elementValue2.elements.length) {
9180                 return false;
9181             }
9182             for (var i = 0; i  < elementValue1.elements.length; i++) {
9183                 if (elementValue1.elements[i].combinator.value !== elementValue2.elements[i].combinator.value) {
9184                     if (i !== 0 || (elementValue1.elements[i].combinator.value || ' ') !== (elementValue2.elements[i].combinator.value || ' ')) {
9185                         return false;
9186                     }
9187                 }
9188                 if (!this.isElementValuesEqual(elementValue1.elements[i].value, elementValue2.elements[i].value)) {
9189                     return false;
9190                 }
9191             }
9192             return true;
9193         }
9194         return false;
9195     },
9196     extendSelector:function (matches, selectorPath, replacementSelector, isVisible) {
9197
9198         //for a set of matches, replace each match with the replacement selector
9199
9200         var currentSelectorPathIndex = 0,
9201             currentSelectorPathElementIndex = 0,
9202             path = [],
9203             matchIndex,
9204             selector,
9205             firstElement,
9206             match,
9207             newElements;
9208
9209         for (matchIndex = 0; matchIndex < matches.length; matchIndex++) {
9210             match = matches[matchIndex];
9211             selector = selectorPath[match.pathIndex];
9212             firstElement = new tree.Element(
9213                 match.initialCombinator,
9214                 replacementSelector.elements[0].value,
9215                 replacementSelector.elements[0].index,
9216                 replacementSelector.elements[0].currentFileInfo
9217             );
9218
9219             if (match.pathIndex > currentSelectorPathIndex && currentSelectorPathElementIndex > 0) {
9220                 path[path.length - 1].elements = path[path.length - 1]
9221                     .elements.concat(selectorPath[currentSelectorPathIndex].elements.slice(currentSelectorPathElementIndex));
9222                 currentSelectorPathElementIndex = 0;
9223                 currentSelectorPathIndex++;
9224             }
9225
9226             newElements = selector.elements
9227                 .slice(currentSelectorPathElementIndex, match.index)
9228                 .concat([firstElement])
9229                 .concat(replacementSelector.elements.slice(1));
9230
9231             if (currentSelectorPathIndex === match.pathIndex && matchIndex > 0) {
9232                 path[path.length - 1].elements =
9233                     path[path.length - 1].elements.concat(newElements);
9234             } else {
9235                 path = path.concat(selectorPath.slice(currentSelectorPathIndex, match.pathIndex));
9236
9237                 path.push(new tree.Selector(
9238                     newElements
9239                 ));
9240             }
9241             currentSelectorPathIndex = match.endPathIndex;
9242             currentSelectorPathElementIndex = match.endPathElementIndex;
9243             if (currentSelectorPathElementIndex >= selectorPath[currentSelectorPathIndex].elements.length) {
9244                 currentSelectorPathElementIndex = 0;
9245                 currentSelectorPathIndex++;
9246             }
9247         }
9248
9249         if (currentSelectorPathIndex < selectorPath.length && currentSelectorPathElementIndex > 0) {
9250             path[path.length - 1].elements = path[path.length - 1]
9251                 .elements.concat(selectorPath[currentSelectorPathIndex].elements.slice(currentSelectorPathElementIndex));
9252             currentSelectorPathIndex++;
9253         }
9254
9255         path = path.concat(selectorPath.slice(currentSelectorPathIndex, selectorPath.length));
9256         path = path.map(function (currentValue) {
9257             // we can re-use elements here, because the visibility property matters only for selectors
9258             var derived = currentValue.createDerived(currentValue.elements);
9259             if (isVisible) {
9260                 derived.ensureVisibility();
9261             } else {
9262                 derived.ensureInvisibility();
9263             }
9264             return derived;
9265         });
9266         return path;
9267     },
9268     visitMedia: function (mediaNode, visitArgs) {
9269         var newAllExtends = mediaNode.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length - 1]);
9270         newAllExtends = newAllExtends.concat(this.doExtendChaining(newAllExtends, mediaNode.allExtends));
9271         this.allExtendsStack.push(newAllExtends);
9272     },
9273     visitMediaOut: function (mediaNode) {
9274         var lastIndex = this.allExtendsStack.length - 1;
9275         this.allExtendsStack.length = lastIndex;
9276     },
9277     visitDirective: function (directiveNode, visitArgs) {
9278         var newAllExtends = directiveNode.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length - 1]);
9279         newAllExtends = newAllExtends.concat(this.doExtendChaining(newAllExtends, directiveNode.allExtends));
9280         this.allExtendsStack.push(newAllExtends);
9281     },
9282     visitDirectiveOut: function (directiveNode) {
9283         var lastIndex = this.allExtendsStack.length - 1;
9284         this.allExtendsStack.length = lastIndex;
9285     }
9286 };
9287
9288 module.exports = ProcessExtendsVisitor;
9289
9290 },{"../logger":33,"../tree":62,"./visitor":91}],85:[function(require,module,exports){
9291 function ImportSequencer(onSequencerEmpty) {
9292     this.imports = [];
9293     this.variableImports = [];
9294     this._onSequencerEmpty = onSequencerEmpty;
9295     this._currentDepth = 0;
9296 }
9297
9298 ImportSequencer.prototype.addImport = function(callback) {
9299     var importSequencer = this,
9300         importItem = {
9301             callback: callback,
9302             args: null,
9303             isReady: false
9304         };
9305     this.imports.push(importItem);
9306     return function() {
9307         importItem.args = Array.prototype.slice.call(arguments, 0);
9308         importItem.isReady = true;
9309         importSequencer.tryRun();
9310     };
9311 };
9312
9313 ImportSequencer.prototype.addVariableImport = function(callback) {
9314     this.variableImports.push(callback);
9315 };
9316
9317 ImportSequencer.prototype.tryRun = function() {
9318     this._currentDepth++;
9319     try {
9320         while (true) {
9321             while (this.imports.length > 0) {
9322                 var importItem = this.imports[0];
9323                 if (!importItem.isReady) {
9324                     return;
9325                 }
9326                 this.imports = this.imports.slice(1);
9327                 importItem.callback.apply(null, importItem.args);
9328             }
9329             if (this.variableImports.length === 0) {
9330                 break;
9331             }
9332             var variableImport = this.variableImports[0];
9333             this.variableImports = this.variableImports.slice(1);
9334             variableImport();
9335         }
9336     } finally {
9337         this._currentDepth--;
9338     }
9339     if (this._currentDepth === 0 && this._onSequencerEmpty) {
9340         this._onSequencerEmpty();
9341     }
9342 };
9343
9344 module.exports = ImportSequencer;
9345
9346 },{}],86:[function(require,module,exports){
9347 var contexts = require("../contexts"),
9348     Visitor = require("./visitor"),
9349     ImportSequencer = require("./import-sequencer");
9350
9351 var ImportVisitor = function(importer, finish) {
9352
9353     this._visitor = new Visitor(this);
9354     this._importer = importer;
9355     this._finish = finish;
9356     this.context = new contexts.Eval();
9357     this.importCount = 0;
9358     this.onceFileDetectionMap = {};
9359     this.recursionDetector = {};
9360     this._sequencer = new ImportSequencer(this._onSequencerEmpty.bind(this));
9361 };
9362
9363 ImportVisitor.prototype = {
9364     isReplacing: false,
9365     run: function (root) {
9366         try {
9367             // process the contents
9368             this._visitor.visit(root);
9369         }
9370         catch(e) {
9371             this.error = e;
9372         }
9373
9374         this.isFinished = true;
9375         this._sequencer.tryRun();
9376     },
9377     _onSequencerEmpty: function() {
9378         if (!this.isFinished) {
9379             return;
9380         }
9381         this._finish(this.error);
9382     },
9383     visitImport: function (importNode, visitArgs) {
9384         var inlineCSS = importNode.options.inline;
9385
9386         if (!importNode.css || inlineCSS) {
9387
9388             var context = new contexts.Eval(this.context, this.context.frames.slice(0));
9389             var importParent = context.frames[0];
9390
9391             this.importCount++;
9392             if (importNode.isVariableImport()) {
9393                 this._sequencer.addVariableImport(this.processImportNode.bind(this, importNode, context, importParent));
9394             } else {
9395                 this.processImportNode(importNode, context, importParent);
9396             }
9397         }
9398         visitArgs.visitDeeper = false;
9399     },
9400     processImportNode: function(importNode, context, importParent) {
9401         var evaldImportNode,
9402             inlineCSS = importNode.options.inline;
9403
9404         try {
9405             evaldImportNode = importNode.evalForImport(context);
9406         } catch(e) {
9407             if (!e.filename) { e.index = importNode.index; e.filename = importNode.currentFileInfo.filename; }
9408             // attempt to eval properly and treat as css
9409             importNode.css = true;
9410             // if that fails, this error will be thrown
9411             importNode.error = e;
9412         }
9413
9414         if (evaldImportNode && (!evaldImportNode.css || inlineCSS)) {
9415
9416             if (evaldImportNode.options.multiple) {
9417                 context.importMultiple = true;
9418             }
9419
9420             // try appending if we haven't determined if it is css or not
9421             var tryAppendLessExtension = evaldImportNode.css === undefined;
9422
9423             for (var i = 0; i < importParent.rules.length; i++) {
9424                 if (importParent.rules[i] === importNode) {
9425                     importParent.rules[i] = evaldImportNode;
9426                     break;
9427                 }
9428             }
9429
9430             var onImported = this.onImported.bind(this, evaldImportNode, context),
9431                 sequencedOnImported = this._sequencer.addImport(onImported);
9432
9433             this._importer.push(evaldImportNode.getPath(), tryAppendLessExtension, evaldImportNode.currentFileInfo,
9434                 evaldImportNode.options, sequencedOnImported);
9435         } else {
9436             this.importCount--;
9437             if (this.isFinished) {
9438                 this._sequencer.tryRun();
9439             }
9440         }
9441     },
9442     onImported: function (importNode, context, e, root, importedAtRoot, fullPath) {
9443         if (e) {
9444             if (!e.filename) {
9445                 e.index = importNode.index; e.filename = importNode.currentFileInfo.filename;
9446             }
9447             this.error = e;
9448         }
9449
9450         var importVisitor = this,
9451             inlineCSS = importNode.options.inline,
9452             isPlugin = importNode.options.plugin,
9453             isOptional = importNode.options.optional,
9454             duplicateImport = importedAtRoot || fullPath in importVisitor.recursionDetector;
9455
9456         if (!context.importMultiple) {
9457             if (duplicateImport) {
9458                 importNode.skip = true;
9459             } else {
9460                 importNode.skip = function() {
9461                     if (fullPath in importVisitor.onceFileDetectionMap) {
9462                         return true;
9463                     }
9464                     importVisitor.onceFileDetectionMap[fullPath] = true;
9465                     return false;
9466                 };
9467             }
9468         }
9469
9470         if (!fullPath && isOptional) {
9471             importNode.skip = true;
9472         }
9473
9474         if (root) {
9475             importNode.root = root;
9476             importNode.importedFilename = fullPath;
9477
9478             if (!inlineCSS && !isPlugin && (context.importMultiple || !duplicateImport)) {
9479                 importVisitor.recursionDetector[fullPath] = true;
9480
9481                 var oldContext = this.context;
9482                 this.context = context;
9483                 try {
9484                     this._visitor.visit(root);
9485                 } catch (e) {
9486                     this.error = e;
9487                 }
9488                 this.context = oldContext;
9489             }
9490         }
9491
9492         importVisitor.importCount--;
9493
9494         if (importVisitor.isFinished) {
9495             importVisitor._sequencer.tryRun();
9496         }
9497     },
9498     visitRule: function (ruleNode, visitArgs) {
9499         if (ruleNode.value.type === "DetachedRuleset") {
9500             this.context.frames.unshift(ruleNode);
9501         } else {
9502             visitArgs.visitDeeper = false;
9503         }
9504     },
9505     visitRuleOut : function(ruleNode) {
9506         if (ruleNode.value.type === "DetachedRuleset") {
9507             this.context.frames.shift();
9508         }
9509     },
9510     visitDirective: function (directiveNode, visitArgs) {
9511         this.context.frames.unshift(directiveNode);
9512     },
9513     visitDirectiveOut: function (directiveNode) {
9514         this.context.frames.shift();
9515     },
9516     visitMixinDefinition: function (mixinDefinitionNode, visitArgs) {
9517         this.context.frames.unshift(mixinDefinitionNode);
9518     },
9519     visitMixinDefinitionOut: function (mixinDefinitionNode) {
9520         this.context.frames.shift();
9521     },
9522     visitRuleset: function (rulesetNode, visitArgs) {
9523         this.context.frames.unshift(rulesetNode);
9524     },
9525     visitRulesetOut: function (rulesetNode) {
9526         this.context.frames.shift();
9527     },
9528     visitMedia: function (mediaNode, visitArgs) {
9529         this.context.frames.unshift(mediaNode.rules[0]);
9530     },
9531     visitMediaOut: function (mediaNode) {
9532         this.context.frames.shift();
9533     }
9534 };
9535 module.exports = ImportVisitor;
9536
9537 },{"../contexts":11,"./import-sequencer":85,"./visitor":91}],87:[function(require,module,exports){
9538 var visitors = {
9539     Visitor: require("./visitor"),
9540     ImportVisitor: require('./import-visitor'),
9541     MarkVisibleSelectorsVisitor: require("./set-tree-visibility-visitor"),
9542     ExtendVisitor: require('./extend-visitor'),
9543     JoinSelectorVisitor: require('./join-selector-visitor'),
9544     ToCSSVisitor: require('./to-css-visitor')
9545 };
9546
9547 module.exports = visitors;
9548
9549 },{"./extend-visitor":84,"./import-visitor":86,"./join-selector-visitor":88,"./set-tree-visibility-visitor":89,"./to-css-visitor":90,"./visitor":91}],88:[function(require,module,exports){
9550 var Visitor = require("./visitor");
9551
9552 var JoinSelectorVisitor = function() {
9553     this.contexts = [[]];
9554     this._visitor = new Visitor(this);
9555 };
9556
9557 JoinSelectorVisitor.prototype = {
9558     run: function (root) {
9559         return this._visitor.visit(root);
9560     },
9561     visitRule: function (ruleNode, visitArgs) {
9562         visitArgs.visitDeeper = false;
9563     },
9564     visitMixinDefinition: function (mixinDefinitionNode, visitArgs) {
9565         visitArgs.visitDeeper = false;
9566     },
9567
9568     visitRuleset: function (rulesetNode, visitArgs) {
9569         var context = this.contexts[this.contexts.length - 1],
9570             paths = [], selectors;
9571
9572         this.contexts.push(paths);
9573
9574         if (! rulesetNode.root) {
9575             selectors = rulesetNode.selectors;
9576             if (selectors) {
9577                 selectors = selectors.filter(function(selector) { return selector.getIsOutput(); });
9578                 rulesetNode.selectors = selectors.length ? selectors : (selectors = null);
9579                 if (selectors) { rulesetNode.joinSelectors(paths, context, selectors); }
9580             }
9581             if (!selectors) { rulesetNode.rules = null; }
9582             rulesetNode.paths = paths;
9583         }
9584     },
9585     visitRulesetOut: function (rulesetNode) {
9586         this.contexts.length = this.contexts.length - 1;
9587     },
9588     visitMedia: function (mediaNode, visitArgs) {
9589         var context = this.contexts[this.contexts.length - 1];
9590         mediaNode.rules[0].root = (context.length === 0 || context[0].multiMedia);
9591     },
9592     visitDirective: function (directiveNode, visitArgs) {
9593         var context = this.contexts[this.contexts.length - 1];
9594         if (directiveNode.rules && directiveNode.rules.length) {
9595             directiveNode.rules[0].root = (directiveNode.isRooted || context.length === 0 || null);
9596         }
9597     }
9598 };
9599
9600 module.exports = JoinSelectorVisitor;
9601
9602 },{"./visitor":91}],89:[function(require,module,exports){
9603 var SetTreeVisibilityVisitor = function(visible) {
9604     this.visible = visible;
9605 };
9606 SetTreeVisibilityVisitor.prototype.run = function(root) {
9607     this.visit(root);
9608 };
9609 SetTreeVisibilityVisitor.prototype.visitArray = function(nodes) {
9610     if (!nodes) {
9611         return nodes;
9612     }
9613
9614     var cnt = nodes.length, i;
9615     for (i = 0; i < cnt; i++) {
9616         this.visit(nodes[i]);
9617     }
9618     return nodes;
9619 };
9620 SetTreeVisibilityVisitor.prototype.visit = function(node) {
9621     if (!node) {
9622         return node;
9623     }
9624     if (node.constructor === Array) {
9625         return this.visitArray(node);
9626     }
9627
9628     if (!node.blocksVisibility || node.blocksVisibility()) {
9629         return node;
9630     }
9631     if (this.visible) {
9632         node.ensureVisibility();
9633     } else {
9634         node.ensureInvisibility();
9635     }
9636
9637     node.accept(this);
9638     return node;
9639 };
9640 module.exports = SetTreeVisibilityVisitor;
9641 },{}],90:[function(require,module,exports){
9642 var tree = require("../tree"),
9643     Visitor = require("./visitor");
9644
9645 var CSSVisitorUtils = function(context) {
9646     this._visitor = new Visitor(this);
9647     this._context = context;
9648 };
9649
9650 CSSVisitorUtils.prototype = {
9651     containsSilentNonBlockedChild: function(bodyRules) {
9652         var rule;
9653         if (bodyRules == null) {
9654             return false;
9655         }
9656         for (var r = 0; r < bodyRules.length; r++) {
9657             rule = bodyRules[r];
9658             if (rule.isSilent && rule.isSilent(this._context) && !rule.blocksVisibility()) {
9659                 //the directive contains something that was referenced (likely by extend)
9660                 //therefore it needs to be shown in output too
9661                 return true;
9662             }
9663         }
9664         return false;
9665     },
9666
9667     keepOnlyVisibleChilds: function(owner) {
9668         if (owner == null || owner.rules == null) {
9669             return ;
9670         }
9671
9672         owner.rules = owner.rules.filter(function(thing) {
9673                 return thing.isVisible();
9674             }
9675         );
9676     },
9677
9678     isEmpty: function(owner) {
9679         if (owner == null || owner.rules == null) {
9680             return true;
9681         }
9682         return owner.rules.length === 0;
9683     },
9684
9685     hasVisibleSelector: function(rulesetNode) {
9686         if (rulesetNode == null || rulesetNode.paths == null) {
9687             return false;
9688         }
9689         return rulesetNode.paths.length > 0;
9690     },
9691
9692     resolveVisibility: function (node, originalRules) {
9693         if (!node.blocksVisibility()) {
9694             if (this.isEmpty(node) && !this.containsSilentNonBlockedChild(originalRules)) {
9695                 return ;
9696             }
9697
9698             return node;
9699         }
9700
9701         var compiledRulesBody = node.rules[0];
9702         this.keepOnlyVisibleChilds(compiledRulesBody);
9703
9704         if (this.isEmpty(compiledRulesBody)) {
9705             return ;
9706         }
9707
9708         node.ensureVisibility();
9709         node.removeVisibilityBlock();
9710
9711         return node;
9712     },
9713
9714     isVisibleRuleset: function(rulesetNode) {
9715         if (rulesetNode.firstRoot) {
9716             return true;
9717         }
9718
9719         if (this.isEmpty(rulesetNode)) {
9720             return false;
9721         }
9722
9723         if (!rulesetNode.root && !this.hasVisibleSelector(rulesetNode)) {
9724             return false;
9725         }
9726
9727         return true;
9728     }
9729
9730 };
9731
9732 var ToCSSVisitor = function(context) {
9733     this._visitor = new Visitor(this);
9734     this._context = context;
9735     this.utils = new CSSVisitorUtils(context);
9736 };
9737
9738 ToCSSVisitor.prototype = {
9739     isReplacing: true,
9740     run: function (root) {
9741         return this._visitor.visit(root);
9742     },
9743
9744     visitRule: function (ruleNode, visitArgs) {
9745         if (ruleNode.blocksVisibility() || ruleNode.variable) {
9746             return;
9747         }
9748         return ruleNode;
9749     },
9750
9751     visitMixinDefinition: function (mixinNode, visitArgs) {
9752         // mixin definitions do not get eval'd - this means they keep state
9753         // so we have to clear that state here so it isn't used if toCSS is called twice
9754         mixinNode.frames = [];
9755     },
9756
9757     visitExtend: function (extendNode, visitArgs) {
9758     },
9759
9760     visitComment: function (commentNode, visitArgs) {
9761         if (commentNode.blocksVisibility() || commentNode.isSilent(this._context)) {
9762             return;
9763         }
9764         return commentNode;
9765     },
9766
9767     visitMedia: function(mediaNode, visitArgs) {
9768         var originalRules = mediaNode.rules[0].rules;
9769         mediaNode.accept(this._visitor);
9770         visitArgs.visitDeeper = false;
9771
9772         return this.utils.resolveVisibility(mediaNode, originalRules);
9773     },
9774
9775     visitImport: function (importNode, visitArgs) {
9776         if (importNode.blocksVisibility()) {
9777             return ;
9778         }
9779         return importNode;
9780     },
9781
9782     visitDirective: function(directiveNode, visitArgs) {
9783         if (directiveNode.rules && directiveNode.rules.length) {
9784             return this.visitDirectiveWithBody(directiveNode, visitArgs);
9785         } else {
9786             return this.visitDirectiveWithoutBody(directiveNode, visitArgs);
9787         }
9788     },
9789
9790     visitDirectiveWithBody: function(directiveNode, visitArgs) {
9791         //if there is only one nested ruleset and that one has no path, then it is
9792         //just fake ruleset
9793         function hasFakeRuleset(directiveNode) {
9794             var bodyRules = directiveNode.rules;
9795             return bodyRules.length === 1 && (!bodyRules[0].paths || bodyRules[0].paths.length === 0);
9796         }
9797         function getBodyRules(directiveNode) {
9798             var nodeRules = directiveNode.rules;
9799             if (hasFakeRuleset(directiveNode)) {
9800                 return nodeRules[0].rules;
9801             }
9802
9803             return nodeRules;
9804         }
9805         //it is still true that it is only one ruleset in array
9806         //this is last such moment
9807         //process childs
9808         var originalRules = getBodyRules(directiveNode);
9809         directiveNode.accept(this._visitor);
9810         visitArgs.visitDeeper = false;
9811
9812         if (!this.utils.isEmpty(directiveNode)) {
9813             this._mergeRules(directiveNode.rules[0].rules);
9814         }
9815
9816         return this.utils.resolveVisibility(directiveNode, originalRules);
9817     },
9818
9819     visitDirectiveWithoutBody: function(directiveNode, visitArgs) {
9820         if (directiveNode.blocksVisibility()) {
9821             return;
9822         }
9823
9824         if (directiveNode.name === "@charset") {
9825             // Only output the debug info together with subsequent @charset definitions
9826             // a comment (or @media statement) before the actual @charset directive would
9827             // be considered illegal css as it has to be on the first line
9828             if (this.charset) {
9829                 if (directiveNode.debugInfo) {
9830                     var comment = new tree.Comment("/* " + directiveNode.toCSS(this._context).replace(/\n/g, "") + " */\n");
9831                     comment.debugInfo = directiveNode.debugInfo;
9832                     return this._visitor.visit(comment);
9833                 }
9834                 return;
9835             }
9836             this.charset = true;
9837         }
9838
9839         return directiveNode;
9840     },
9841
9842     checkValidNodes: function(rules, isRoot) {
9843         if (!rules) {
9844             return;
9845         }
9846
9847         for (var i = 0; i < rules.length; i++) {
9848             var ruleNode = rules[i];
9849             if (isRoot && ruleNode instanceof tree.Rule && !ruleNode.variable) {
9850                 throw { message: "Properties must be inside selector blocks. They cannot be in the root",
9851                     index: ruleNode.index, filename: ruleNode.currentFileInfo && ruleNode.currentFileInfo.filename};
9852             }
9853             if (ruleNode instanceof tree.Call) {
9854                 throw { message: "Function '" + ruleNode.name + "' is undefined",
9855                     index: ruleNode.index, filename: ruleNode.currentFileInfo && ruleNode.currentFileInfo.filename};
9856             }
9857             if (ruleNode.type && !ruleNode.allowRoot) {
9858                 throw { message: ruleNode.type + " node returned by a function is not valid here",
9859                     index: ruleNode.index, filename: ruleNode.currentFileInfo && ruleNode.currentFileInfo.filename};
9860             }
9861         }
9862     },
9863
9864     visitRuleset: function (rulesetNode, visitArgs) {
9865         //at this point rulesets are nested into each other
9866         var rule, rulesets = [];
9867
9868         this.checkValidNodes(rulesetNode.rules, rulesetNode.firstRoot);
9869
9870         if (! rulesetNode.root) {
9871             //remove invisible paths
9872             this._compileRulesetPaths(rulesetNode);
9873
9874             // remove rulesets from this ruleset body and compile them separately
9875             var nodeRules = rulesetNode.rules, nodeRuleCnt = nodeRules ? nodeRules.length : 0;
9876             for (var i = 0; i < nodeRuleCnt; ) {
9877                 rule = nodeRules[i];
9878                 if (rule && rule.rules) {
9879                     // visit because we are moving them out from being a child
9880                     rulesets.push(this._visitor.visit(rule));
9881                     nodeRules.splice(i, 1);
9882                     nodeRuleCnt--;
9883                     continue;
9884                 }
9885                 i++;
9886             }
9887             // accept the visitor to remove rules and refactor itself
9888             // then we can decide nogw whether we want it or not
9889             // compile body
9890             if (nodeRuleCnt > 0) {
9891                 rulesetNode.accept(this._visitor);
9892             } else {
9893                 rulesetNode.rules = null;
9894             }
9895             visitArgs.visitDeeper = false;
9896
9897         } else { //if (! rulesetNode.root) {
9898             rulesetNode.accept(this._visitor);
9899             visitArgs.visitDeeper = false;
9900         }
9901
9902         if (rulesetNode.rules) {
9903             this._mergeRules(rulesetNode.rules);
9904             this._removeDuplicateRules(rulesetNode.rules);
9905         }
9906
9907         //now decide whether we keep the ruleset
9908         if (this.utils.isVisibleRuleset(rulesetNode)) {
9909             rulesetNode.ensureVisibility();
9910             rulesets.splice(0, 0, rulesetNode);
9911         }
9912
9913         if (rulesets.length === 1) {
9914             return rulesets[0];
9915         }
9916         return rulesets;
9917     },
9918
9919     _compileRulesetPaths: function(rulesetNode) {
9920         if (rulesetNode.paths) {
9921             rulesetNode.paths = rulesetNode.paths
9922                 .filter(function(p) {
9923                     var i;
9924                     if (p[0].elements[0].combinator.value === ' ') {
9925                         p[0].elements[0].combinator = new(tree.Combinator)('');
9926                     }
9927                     for (i = 0; i < p.length; i++) {
9928                         if (p[i].isVisible() && p[i].getIsOutput()) {
9929                             return true;
9930                         }
9931                     }
9932                     return false;
9933                 });
9934         }
9935     },
9936
9937     _removeDuplicateRules: function(rules) {
9938         if (!rules) { return; }
9939
9940         // remove duplicates
9941         var ruleCache = {},
9942             ruleList, rule, i;
9943
9944         for (i = rules.length - 1; i >= 0 ; i--) {
9945             rule = rules[i];
9946             if (rule instanceof tree.Rule) {
9947                 if (!ruleCache[rule.name]) {
9948                     ruleCache[rule.name] = rule;
9949                 } else {
9950                     ruleList = ruleCache[rule.name];
9951                     if (ruleList instanceof tree.Rule) {
9952                         ruleList = ruleCache[rule.name] = [ruleCache[rule.name].toCSS(this._context)];
9953                     }
9954                     var ruleCSS = rule.toCSS(this._context);
9955                     if (ruleList.indexOf(ruleCSS) !== -1) {
9956                         rules.splice(i, 1);
9957                     } else {
9958                         ruleList.push(ruleCSS);
9959                     }
9960                 }
9961             }
9962         }
9963     },
9964
9965     _mergeRules: function (rules) {
9966         if (!rules) { return; }
9967
9968         var groups = {},
9969             parts,
9970             rule,
9971             key;
9972
9973         for (var i = 0; i < rules.length; i++) {
9974             rule = rules[i];
9975
9976             if ((rule instanceof tree.Rule) && rule.merge) {
9977                 key = [rule.name,
9978                     rule.important ? "!" : ""].join(",");
9979
9980                 if (!groups[key]) {
9981                     groups[key] = [];
9982                 } else {
9983                     rules.splice(i--, 1);
9984                 }
9985
9986                 groups[key].push(rule);
9987             }
9988         }
9989
9990         Object.keys(groups).map(function (k) {
9991
9992             function toExpression(values) {
9993                 return new (tree.Expression)(values.map(function (p) {
9994                     return p.value;
9995                 }));
9996             }
9997
9998             function toValue(values) {
9999                 return new (tree.Value)(values.map(function (p) {
10000                     return p;
10001                 }));
10002             }
10003
10004             parts = groups[k];
10005
10006             if (parts.length > 1) {
10007                 rule = parts[0];
10008                 var spacedGroups = [];
10009                 var lastSpacedGroup = [];
10010                 parts.map(function (p) {
10011                     if (p.merge === "+") {
10012                         if (lastSpacedGroup.length > 0) {
10013                             spacedGroups.push(toExpression(lastSpacedGroup));
10014                         }
10015                         lastSpacedGroup = [];
10016                     }
10017                     lastSpacedGroup.push(p);
10018                 });
10019                 spacedGroups.push(toExpression(lastSpacedGroup));
10020                 rule.value = toValue(spacedGroups);
10021             }
10022         });
10023     },
10024
10025     visitAnonymous: function(anonymousNode, visitArgs) {
10026         if (anonymousNode.blocksVisibility()) {
10027             return ;
10028         }
10029         anonymousNode.accept(this._visitor);
10030         return anonymousNode;
10031     }
10032 };
10033
10034 module.exports = ToCSSVisitor;
10035
10036 },{"../tree":62,"./visitor":91}],91:[function(require,module,exports){
10037 var tree = require("../tree");
10038
10039 var _visitArgs = { visitDeeper: true },
10040     _hasIndexed = false;
10041
10042 function _noop(node) {
10043     return node;
10044 }
10045
10046 function indexNodeTypes(parent, ticker) {
10047     // add .typeIndex to tree node types for lookup table
10048     var key, child;
10049     for (key in parent) {
10050         if (parent.hasOwnProperty(key)) {
10051             child = parent[key];
10052             switch (typeof child) {
10053                 case "function":
10054                     // ignore bound functions directly on tree which do not have a prototype
10055                     // or aren't nodes
10056                     if (child.prototype && child.prototype.type) {
10057                         child.prototype.typeIndex = ticker++;
10058                     }
10059                     break;
10060                 case "object":
10061                     ticker = indexNodeTypes(child, ticker);
10062                     break;
10063             }
10064         }
10065     }
10066     return ticker;
10067 }
10068
10069 var Visitor = function(implementation) {
10070     this._implementation = implementation;
10071     this._visitFnCache = [];
10072
10073     if (!_hasIndexed) {
10074         indexNodeTypes(tree, 1);
10075         _hasIndexed = true;
10076     }
10077 };
10078
10079 Visitor.prototype = {
10080     visit: function(node) {
10081         if (!node) {
10082             return node;
10083         }
10084
10085         var nodeTypeIndex = node.typeIndex;
10086         if (!nodeTypeIndex) {
10087             return node;
10088         }
10089
10090         var visitFnCache = this._visitFnCache,
10091             impl = this._implementation,
10092             aryIndx = nodeTypeIndex << 1,
10093             outAryIndex = aryIndx | 1,
10094             func = visitFnCache[aryIndx],
10095             funcOut = visitFnCache[outAryIndex],
10096             visitArgs = _visitArgs,
10097             fnName;
10098
10099         visitArgs.visitDeeper = true;
10100
10101         if (!func) {
10102             fnName = "visit" + node.type;
10103             func = impl[fnName] || _noop;
10104             funcOut = impl[fnName + "Out"] || _noop;
10105             visitFnCache[aryIndx] = func;
10106             visitFnCache[outAryIndex] = funcOut;
10107         }
10108
10109         if (func !== _noop) {
10110             var newNode = func.call(impl, node, visitArgs);
10111             if (impl.isReplacing) {
10112                 node = newNode;
10113             }
10114         }
10115
10116         if (visitArgs.visitDeeper && node && node.accept) {
10117             node.accept(this);
10118         }
10119
10120         if (funcOut != _noop) {
10121             funcOut.call(impl, node);
10122         }
10123
10124         return node;
10125     },
10126     visitArray: function(nodes, nonReplacing) {
10127         if (!nodes) {
10128             return nodes;
10129         }
10130
10131         var cnt = nodes.length, i;
10132
10133         // Non-replacing
10134         if (nonReplacing || !this._implementation.isReplacing) {
10135             for (i = 0; i < cnt; i++) {
10136                 this.visit(nodes[i]);
10137             }
10138             return nodes;
10139         }
10140
10141         // Replacing
10142         var out = [];
10143         for (i = 0; i < cnt; i++) {
10144             var evald = this.visit(nodes[i]);
10145             if (evald === undefined) { continue; }
10146             if (!evald.splice) {
10147                 out.push(evald);
10148             } else if (evald.length) {
10149                 this.flatten(evald, out);
10150             }
10151         }
10152         return out;
10153     },
10154     flatten: function(arr, out) {
10155         if (!out) {
10156             out = [];
10157         }
10158
10159         var cnt, i, item,
10160             nestedCnt, j, nestedItem;
10161
10162         for (i = 0, cnt = arr.length; i < cnt; i++) {
10163             item = arr[i];
10164             if (item === undefined) {
10165                 continue;
10166             }
10167             if (!item.splice) {
10168                 out.push(item);
10169                 continue;
10170             }
10171
10172             for (j = 0, nestedCnt = item.length; j < nestedCnt; j++) {
10173                 nestedItem = item[j];
10174                 if (nestedItem === undefined) {
10175                     continue;
10176                 }
10177                 if (!nestedItem.splice) {
10178                     out.push(nestedItem);
10179                 } else if (nestedItem.length) {
10180                     this.flatten(nestedItem, out);
10181                 }
10182             }
10183         }
10184
10185         return out;
10186     }
10187 };
10188 module.exports = Visitor;
10189
10190 },{"../tree":62}],92:[function(require,module,exports){
10191 "use strict";
10192
10193 // rawAsap provides everything we need except exception management.
10194 var rawAsap = require("./raw");
10195 // RawTasks are recycled to reduce GC churn.
10196 var freeTasks = [];
10197 // We queue errors to ensure they are thrown in right order (FIFO).
10198 // Array-as-queue is good enough here, since we are just dealing with exceptions.
10199 var pendingErrors = [];
10200 var requestErrorThrow = rawAsap.makeRequestCallFromTimer(throwFirstError);
10201
10202 function throwFirstError() {
10203     if (pendingErrors.length) {
10204         throw pendingErrors.shift();
10205     }
10206 }
10207
10208 /**
10209  * Calls a task as soon as possible after returning, in its own event, with priority
10210  * over other events like animation, reflow, and repaint. An error thrown from an
10211  * event will not interrupt, nor even substantially slow down the processing of
10212  * other events, but will be rather postponed to a lower priority event.
10213  * @param {{call}} task A callable object, typically a function that takes no
10214  * arguments.
10215  */
10216 module.exports = asap;
10217 function asap(task) {
10218     var rawTask;
10219     if (freeTasks.length) {
10220         rawTask = freeTasks.pop();
10221     } else {
10222         rawTask = new RawTask();
10223     }
10224     rawTask.task = task;
10225     rawAsap(rawTask);
10226 }
10227
10228 // We wrap tasks with recyclable task objects.  A task object implements
10229 // `call`, just like a function.
10230 function RawTask() {
10231     this.task = null;
10232 }
10233
10234 // The sole purpose of wrapping the task is to catch the exception and recycle
10235 // the task object after its single use.
10236 RawTask.prototype.call = function () {
10237     try {
10238         this.task.call();
10239     } catch (error) {
10240         if (asap.onerror) {
10241             // This hook exists purely for testing purposes.
10242             // Its name will be periodically randomized to break any code that
10243             // depends on its existence.
10244             asap.onerror(error);
10245         } else {
10246             // In a web browser, exceptions are not fatal. However, to avoid
10247             // slowing down the queue of pending tasks, we rethrow the error in a
10248             // lower priority turn.
10249             pendingErrors.push(error);
10250             requestErrorThrow();
10251         }
10252     } finally {
10253         this.task = null;
10254         freeTasks[freeTasks.length] = this;
10255     }
10256 };
10257
10258 },{"./raw":93}],93:[function(require,module,exports){
10259 (function (global){
10260 "use strict";
10261
10262 // Use the fastest means possible to execute a task in its own turn, with
10263 // priority over other events including IO, animation, reflow, and redraw
10264 // events in browsers.
10265 //
10266 // An exception thrown by a task will permanently interrupt the processing of
10267 // subsequent tasks. The higher level `asap` function ensures that if an
10268 // exception is thrown by a task, that the task queue will continue flushing as
10269 // soon as possible, but if you use `rawAsap` directly, you are responsible to
10270 // either ensure that no exceptions are thrown from your task, or to manually
10271 // call `rawAsap.requestFlush` if an exception is thrown.
10272 module.exports = rawAsap;
10273 function rawAsap(task) {
10274     if (!queue.length) {
10275         requestFlush();
10276         flushing = true;
10277     }
10278     // Equivalent to push, but avoids a function call.
10279     queue[queue.length] = task;
10280 }
10281
10282 var queue = [];
10283 // Once a flush has been requested, no further calls to `requestFlush` are
10284 // necessary until the next `flush` completes.
10285 var flushing = false;
10286 // `requestFlush` is an implementation-specific method that attempts to kick
10287 // off a `flush` event as quickly as possible. `flush` will attempt to exhaust
10288 // the event queue before yielding to the browser's own event loop.
10289 var requestFlush;
10290 // The position of the next task to execute in the task queue. This is
10291 // preserved between calls to `flush` so that it can be resumed if
10292 // a task throws an exception.
10293 var index = 0;
10294 // If a task schedules additional tasks recursively, the task queue can grow
10295 // unbounded. To prevent memory exhaustion, the task queue will periodically
10296 // truncate already-completed tasks.
10297 var capacity = 1024;
10298
10299 // The flush function processes all tasks that have been scheduled with
10300 // `rawAsap` unless and until one of those tasks throws an exception.
10301 // If a task throws an exception, `flush` ensures that its state will remain
10302 // consistent and will resume where it left off when called again.
10303 // However, `flush` does not make any arrangements to be called again if an
10304 // exception is thrown.
10305 function flush() {
10306     while (index < queue.length) {
10307         var currentIndex = index;
10308         // Advance the index before calling the task. This ensures that we will
10309         // begin flushing on the next task the task throws an error.
10310         index = index + 1;
10311         queue[currentIndex].call();
10312         // Prevent leaking memory for long chains of recursive calls to `asap`.
10313         // If we call `asap` within tasks scheduled by `asap`, the queue will
10314         // grow, but to avoid an O(n) walk for every task we execute, we don't
10315         // shift tasks off the queue after they have been executed.
10316         // Instead, we periodically shift 1024 tasks off the queue.
10317         if (index > capacity) {
10318             // Manually shift all values starting at the index back to the
10319             // beginning of the queue.
10320             for (var scan = 0, newLength = queue.length - index; scan < newLength; scan++) {
10321                 queue[scan] = queue[scan + index];
10322             }
10323             queue.length -= index;
10324             index = 0;
10325         }
10326     }
10327     queue.length = 0;
10328     index = 0;
10329     flushing = false;
10330 }
10331
10332 // `requestFlush` is implemented using a strategy based on data collected from
10333 // every available SauceLabs Selenium web driver worker at time of writing.
10334 // https://docs.google.com/spreadsheets/d/1mG-5UYGup5qxGdEMWkhP6BWCz053NUb2E1QoUTU16uA/edit#gid=783724593
10335
10336 // Safari 6 and 6.1 for desktop, iPad, and iPhone are the only browsers that
10337 // have WebKitMutationObserver but not un-prefixed MutationObserver.
10338 // Must use `global` or `self` instead of `window` to work in both frames and web
10339 // workers. `global` is a provision of Browserify, Mr, Mrs, or Mop.
10340
10341 /* globals self */
10342 var scope = typeof global !== "undefined" ? global : self;
10343 var BrowserMutationObserver = scope.MutationObserver || scope.WebKitMutationObserver;
10344
10345 // MutationObservers are desirable because they have high priority and work
10346 // reliably everywhere they are implemented.
10347 // They are implemented in all modern browsers.
10348 //
10349 // - Android 4-4.3
10350 // - Chrome 26-34
10351 // - Firefox 14-29
10352 // - Internet Explorer 11
10353 // - iPad Safari 6-7.1
10354 // - iPhone Safari 7-7.1
10355 // - Safari 6-7
10356 if (typeof BrowserMutationObserver === "function") {
10357     requestFlush = makeRequestCallFromMutationObserver(flush);
10358
10359 // MessageChannels are desirable because they give direct access to the HTML
10360 // task queue, are implemented in Internet Explorer 10, Safari 5.0-1, and Opera
10361 // 11-12, and in web workers in many engines.
10362 // Although message channels yield to any queued rendering and IO tasks, they
10363 // would be better than imposing the 4ms delay of timers.
10364 // However, they do not work reliably in Internet Explorer or Safari.
10365
10366 // Internet Explorer 10 is the only browser that has setImmediate but does
10367 // not have MutationObservers.
10368 // Although setImmediate yields to the browser's renderer, it would be
10369 // preferrable to falling back to setTimeout since it does not have
10370 // the minimum 4ms penalty.
10371 // Unfortunately there appears to be a bug in Internet Explorer 10 Mobile (and
10372 // Desktop to a lesser extent) that renders both setImmediate and
10373 // MessageChannel useless for the purposes of ASAP.
10374 // https://github.com/kriskowal/q/issues/396
10375
10376 // Timers are implemented universally.
10377 // We fall back to timers in workers in most engines, and in foreground
10378 // contexts in the following browsers.
10379 // However, note that even this simple case requires nuances to operate in a
10380 // broad spectrum of browsers.
10381 //
10382 // - Firefox 3-13
10383 // - Internet Explorer 6-9
10384 // - iPad Safari 4.3
10385 // - Lynx 2.8.7
10386 } else {
10387     requestFlush = makeRequestCallFromTimer(flush);
10388 }
10389
10390 // `requestFlush` requests that the high priority event queue be flushed as
10391 // soon as possible.
10392 // This is useful to prevent an error thrown in a task from stalling the event
10393 // queue if the exception handled by Node.js’s
10394 // `process.on("uncaughtException")` or by a domain.
10395 rawAsap.requestFlush = requestFlush;
10396
10397 // To request a high priority event, we induce a mutation observer by toggling
10398 // the text of a text node between "1" and "-1".
10399 function makeRequestCallFromMutationObserver(callback) {
10400     var toggle = 1;
10401     var observer = new BrowserMutationObserver(callback);
10402     var node = document.createTextNode("");
10403     observer.observe(node, {characterData: true});
10404     return function requestCall() {
10405         toggle = -toggle;
10406         node.data = toggle;
10407     };
10408 }
10409
10410 // The message channel technique was discovered by Malte Ubl and was the
10411 // original foundation for this library.
10412 // http://www.nonblocking.io/2011/06/windownexttick.html
10413
10414 // Safari 6.0.5 (at least) intermittently fails to create message ports on a
10415 // page's first load. Thankfully, this version of Safari supports
10416 // MutationObservers, so we don't need to fall back in that case.
10417
10418 // function makeRequestCallFromMessageChannel(callback) {
10419 //     var channel = new MessageChannel();
10420 //     channel.port1.onmessage = callback;
10421 //     return function requestCall() {
10422 //         channel.port2.postMessage(0);
10423 //     };
10424 // }
10425
10426 // For reasons explained above, we are also unable to use `setImmediate`
10427 // under any circumstances.
10428 // Even if we were, there is another bug in Internet Explorer 10.
10429 // It is not sufficient to assign `setImmediate` to `requestFlush` because
10430 // `setImmediate` must be called *by name* and therefore must be wrapped in a
10431 // closure.
10432 // Never forget.
10433
10434 // function makeRequestCallFromSetImmediate(callback) {
10435 //     return function requestCall() {
10436 //         setImmediate(callback);
10437 //     };
10438 // }
10439
10440 // Safari 6.0 has a problem where timers will get lost while the user is
10441 // scrolling. This problem does not impact ASAP because Safari 6.0 supports
10442 // mutation observers, so that implementation is used instead.
10443 // However, if we ever elect to use timers in Safari, the prevalent work-around
10444 // is to add a scroll event listener that calls for a flush.
10445
10446 // `setTimeout` does not call the passed callback if the delay is less than
10447 // approximately 7 in web workers in Firefox 8 through 18, and sometimes not
10448 // even then.
10449
10450 function makeRequestCallFromTimer(callback) {
10451     return function requestCall() {
10452         // We dispatch a timeout with a specified delay of 0 for engines that
10453         // can reliably accommodate that request. This will usually be snapped
10454         // to a 4 milisecond delay, but once we're flushing, there's no delay
10455         // between events.
10456         var timeoutHandle = setTimeout(handleTimer, 0);
10457         // However, since this timer gets frequently dropped in Firefox
10458         // workers, we enlist an interval handle that will try to fire
10459         // an event 20 times per second until it succeeds.
10460         var intervalHandle = setInterval(handleTimer, 50);
10461
10462         function handleTimer() {
10463             // Whichever timer succeeds will cancel both timers and
10464             // execute the callback.
10465             clearTimeout(timeoutHandle);
10466             clearInterval(intervalHandle);
10467             callback();
10468         }
10469     };
10470 }
10471
10472 // This is for `asap.js` only.
10473 // Its name will be periodically randomized to break any code that depends on
10474 // its existence.
10475 rawAsap.makeRequestCallFromTimer = makeRequestCallFromTimer;
10476
10477 // ASAP was originally a nextTick shim included in Q. This was factored out
10478 // into this ASAP package. It was later adapted to RSVP which made further
10479 // amendments. These decisions, particularly to marginalize MessageChannel and
10480 // to capture the MutationObserver implementation in a closure, were integrated
10481 // back into ASAP proper.
10482 // https://github.com/tildeio/rsvp.js/blob/cddf7232546a9cf858524b75cde6f9edf72620a7/lib/rsvp/asap.js
10483
10484 }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
10485 },{}],94:[function(require,module,exports){
10486 'use strict';
10487
10488 var asap = require('asap/raw');
10489
10490 function noop() {}
10491
10492 // States:
10493 //
10494 // 0 - pending
10495 // 1 - fulfilled with _value
10496 // 2 - rejected with _value
10497 // 3 - adopted the state of another promise, _value
10498 //
10499 // once the state is no longer pending (0) it is immutable
10500
10501 // All `_` prefixed properties will be reduced to `_{random number}`
10502 // at build time to obfuscate them and discourage their use.
10503 // We don't use symbols or Object.defineProperty to fully hide them
10504 // because the performance isn't good enough.
10505
10506
10507 // to avoid using try/catch inside critical functions, we
10508 // extract them to here.
10509 var LAST_ERROR = null;
10510 var IS_ERROR = {};
10511 function getThen(obj) {
10512   try {
10513     return obj.then;
10514   } catch (ex) {
10515     LAST_ERROR = ex;
10516     return IS_ERROR;
10517   }
10518 }
10519
10520 function tryCallOne(fn, a) {
10521   try {
10522     return fn(a);
10523   } catch (ex) {
10524     LAST_ERROR = ex;
10525     return IS_ERROR;
10526   }
10527 }
10528 function tryCallTwo(fn, a, b) {
10529   try {
10530     fn(a, b);
10531   } catch (ex) {
10532     LAST_ERROR = ex;
10533     return IS_ERROR;
10534   }
10535 }
10536
10537 module.exports = Promise;
10538
10539 function Promise(fn) {
10540   if (typeof this !== 'object') {
10541     throw new TypeError('Promises must be constructed via new');
10542   }
10543   if (typeof fn !== 'function') {
10544     throw new TypeError('Promise constructor\'s argument is not a function');
10545   }
10546   this._40 = 0;
10547   this._65 = 0;
10548   this._55 = null;
10549   this._72 = null;
10550   if (fn === noop) return;
10551   doResolve(fn, this);
10552 }
10553 Promise._37 = null;
10554 Promise._87 = null;
10555 Promise._61 = noop;
10556
10557 Promise.prototype.then = function(onFulfilled, onRejected) {
10558   if (this.constructor !== Promise) {
10559     return safeThen(this, onFulfilled, onRejected);
10560   }
10561   var res = new Promise(noop);
10562   handle(this, new Handler(onFulfilled, onRejected, res));
10563   return res;
10564 };
10565
10566 function safeThen(self, onFulfilled, onRejected) {
10567   return new self.constructor(function (resolve, reject) {
10568     var res = new Promise(noop);
10569     res.then(resolve, reject);
10570     handle(self, new Handler(onFulfilled, onRejected, res));
10571   });
10572 }
10573 function handle(self, deferred) {
10574   while (self._65 === 3) {
10575     self = self._55;
10576   }
10577   if (Promise._37) {
10578     Promise._37(self);
10579   }
10580   if (self._65 === 0) {
10581     if (self._40 === 0) {
10582       self._40 = 1;
10583       self._72 = deferred;
10584       return;
10585     }
10586     if (self._40 === 1) {
10587       self._40 = 2;
10588       self._72 = [self._72, deferred];
10589       return;
10590     }
10591     self._72.push(deferred);
10592     return;
10593   }
10594   handleResolved(self, deferred);
10595 }
10596
10597 function handleResolved(self, deferred) {
10598   asap(function() {
10599     var cb = self._65 === 1 ? deferred.onFulfilled : deferred.onRejected;
10600     if (cb === null) {
10601       if (self._65 === 1) {
10602         resolve(deferred.promise, self._55);
10603       } else {
10604         reject(deferred.promise, self._55);
10605       }
10606       return;
10607     }
10608     var ret = tryCallOne(cb, self._55);
10609     if (ret === IS_ERROR) {
10610       reject(deferred.promise, LAST_ERROR);
10611     } else {
10612       resolve(deferred.promise, ret);
10613     }
10614   });
10615 }
10616 function resolve(self, newValue) {
10617   // Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure
10618   if (newValue === self) {
10619     return reject(
10620       self,
10621       new TypeError('A promise cannot be resolved with itself.')
10622     );
10623   }
10624   if (
10625     newValue &&
10626     (typeof newValue === 'object' || typeof newValue === 'function')
10627   ) {
10628     var then = getThen(newValue);
10629     if (then === IS_ERROR) {
10630       return reject(self, LAST_ERROR);
10631     }
10632     if (
10633       then === self.then &&
10634       newValue instanceof Promise
10635     ) {
10636       self._65 = 3;
10637       self._55 = newValue;
10638       finale(self);
10639       return;
10640     } else if (typeof then === 'function') {
10641       doResolve(then.bind(newValue), self);
10642       return;
10643     }
10644   }
10645   self._65 = 1;
10646   self._55 = newValue;
10647   finale(self);
10648 }
10649
10650 function reject(self, newValue) {
10651   self._65 = 2;
10652   self._55 = newValue;
10653   if (Promise._87) {
10654     Promise._87(self, newValue);
10655   }
10656   finale(self);
10657 }
10658 function finale(self) {
10659   if (self._40 === 1) {
10660     handle(self, self._72);
10661     self._72 = null;
10662   }
10663   if (self._40 === 2) {
10664     for (var i = 0; i < self._72.length; i++) {
10665       handle(self, self._72[i]);
10666     }
10667     self._72 = null;
10668   }
10669 }
10670
10671 function Handler(onFulfilled, onRejected, promise){
10672   this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null;
10673   this.onRejected = typeof onRejected === 'function' ? onRejected : null;
10674   this.promise = promise;
10675 }
10676
10677 /**
10678  * Take a potentially misbehaving resolver function and make sure
10679  * onFulfilled and onRejected are only called once.
10680  *
10681  * Makes no guarantees about asynchrony.
10682  */
10683 function doResolve(fn, promise) {
10684   var done = false;
10685   var res = tryCallTwo(fn, function (value) {
10686     if (done) return;
10687     done = true;
10688     resolve(promise, value);
10689   }, function (reason) {
10690     if (done) return;
10691     done = true;
10692     reject(promise, reason);
10693   });
10694   if (!done && res === IS_ERROR) {
10695     done = true;
10696     reject(promise, LAST_ERROR);
10697   }
10698 }
10699
10700 },{"asap/raw":93}],95:[function(require,module,exports){
10701 'use strict';
10702
10703 //This file contains the ES6 extensions to the core Promises/A+ API
10704
10705 var Promise = require('./core.js');
10706
10707 module.exports = Promise;
10708
10709 /* Static Functions */
10710
10711 var TRUE = valuePromise(true);
10712 var FALSE = valuePromise(false);
10713 var NULL = valuePromise(null);
10714 var UNDEFINED = valuePromise(undefined);
10715 var ZERO = valuePromise(0);
10716 var EMPTYSTRING = valuePromise('');
10717
10718 function valuePromise(value) {
10719   var p = new Promise(Promise._61);
10720   p._65 = 1;
10721   p._55 = value;
10722   return p;
10723 }
10724 Promise.resolve = function (value) {
10725   if (value instanceof Promise) return value;
10726
10727   if (value === null) return NULL;
10728   if (value === undefined) return UNDEFINED;
10729   if (value === true) return TRUE;
10730   if (value === false) return FALSE;
10731   if (value === 0) return ZERO;
10732   if (value === '') return EMPTYSTRING;
10733
10734   if (typeof value === 'object' || typeof value === 'function') {
10735     try {
10736       var then = value.then;
10737       if (typeof then === 'function') {
10738         return new Promise(then.bind(value));
10739       }
10740     } catch (ex) {
10741       return new Promise(function (resolve, reject) {
10742         reject(ex);
10743       });
10744     }
10745   }
10746   return valuePromise(value);
10747 };
10748
10749 Promise.all = function (arr) {
10750   var args = Array.prototype.slice.call(arr);
10751
10752   return new Promise(function (resolve, reject) {
10753     if (args.length === 0) return resolve([]);
10754     var remaining = args.length;
10755     function res(i, val) {
10756       if (val && (typeof val === 'object' || typeof val === 'function')) {
10757         if (val instanceof Promise && val.then === Promise.prototype.then) {
10758           while (val._65 === 3) {
10759             val = val._55;
10760           }
10761           if (val._65 === 1) return res(i, val._55);
10762           if (val._65 === 2) reject(val._55);
10763           val.then(function (val) {
10764             res(i, val);
10765           }, reject);
10766           return;
10767         } else {
10768           var then = val.then;
10769           if (typeof then === 'function') {
10770             var p = new Promise(then.bind(val));
10771             p.then(function (val) {
10772               res(i, val);
10773             }, reject);
10774             return;
10775           }
10776         }
10777       }
10778       args[i] = val;
10779       if (--remaining === 0) {
10780         resolve(args);
10781       }
10782     }
10783     for (var i = 0; i < args.length; i++) {
10784       res(i, args[i]);
10785     }
10786   });
10787 };
10788
10789 Promise.reject = function (value) {
10790   return new Promise(function (resolve, reject) {
10791     reject(value);
10792   });
10793 };
10794
10795 Promise.race = function (values) {
10796   return new Promise(function (resolve, reject) {
10797     values.forEach(function(value){
10798       Promise.resolve(value).then(resolve, reject);
10799     });
10800   });
10801 };
10802
10803 /* Prototype Methods */
10804
10805 Promise.prototype['catch'] = function (onRejected) {
10806   return this.then(null, onRejected);
10807 };
10808
10809 },{"./core.js":94}],96:[function(require,module,exports){
10810 // should work in any browser without browserify
10811
10812 if (typeof Promise.prototype.done !== 'function') {
10813   Promise.prototype.done = function (onFulfilled, onRejected) {
10814     var self = arguments.length ? this.then.apply(this, arguments) : this
10815     self.then(null, function (err) {
10816       setTimeout(function () {
10817         throw err
10818       }, 0)
10819     })
10820   }
10821 }
10822 },{}],97:[function(require,module,exports){
10823 // not "use strict" so we can declare global "Promise"
10824
10825 var asap = require('asap');
10826
10827 if (typeof Promise === 'undefined') {
10828   Promise = require('./lib/core.js')
10829   require('./lib/es6-extensions.js')
10830 }
10831
10832 require('./polyfill-done.js');
10833
10834 },{"./lib/core.js":94,"./lib/es6-extensions.js":95,"./polyfill-done.js":96,"asap":92}]},{},[2])(2)
10835 });