diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 000000000..9ddce209c --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,88 @@ +{ + "env": { + "node": true + }, + "globals": {}, + "rules": { + "no-eval": 2, + "no-use-before-define": [ + 2, + { + "functions": false + } + ], + "no-undef": 0, + "no-unused-vars": 1, + "no-caller": 2, + "no-eq-null": 1, + "guard-for-in": 2, + "no-implicit-coercion": [ + 2, + { + "boolean": false, + "string": true, + "number": true + } + ], + "no-with": 2, + "no-mixed-spaces-and-tabs": 2, + "no-multiple-empty-lines": 2, + "dot-location": [ + 2, + "property" + ], + "operator-linebreak": [ + 0, + "after" + ], + "keyword-spacing": [ + 2, + {} + ], + "space-unary-ops": [ + 2, + { + "words": false, + "nonwords": false + } + ], + "no-spaced-func": 2, + "space-before-function-paren": [ + 1, + { + "anonymous": "ignore", + "named": "never" + } + ], + "comma-dangle": [ + 2, + "never" + ], + "no-trailing-spaces": 0, + "max-len": [ + 2, + 160 + ], + "comma-style": [ + 2, + "last" + ], + "curly": [ + 2, + "all" + ], + "space-infix-ops": 2, + "spaced-comment": 1, + "space-before-blocks": [ + 2, + "always" + ], + "indent": [ + 2, + 4, + { + "SwitchCase": 1 + } + ] + } +} diff --git a/.github/stale.yml b/.github/stale.yml new file mode 100644 index 000000000..329d49feb --- /dev/null +++ b/.github/stale.yml @@ -0,0 +1,17 @@ +# Number of days of inactivity before an issue becomes stale +daysUntilStale: 120 +# Number of days of inactivity before a stale issue is closed +daysUntilClose: 14 +# Issues with these labels will never be considered stale +exemptLabels: + - up-for-grabs + - bug +# Label to use when marking an issue as stale +staleLabel: stale +# Comment to post when marking an issue as stale. Set to `false` to disable +markComment: > + This issue has been automatically marked as stale because it has not had + recent activity. It will be closed if no further activity occurs. Thank you + for your contributions. +# Comment to post when closing a stale issue. Set to `false` to disable +closeComment: false diff --git a/.jscsrc b/.jscsrc deleted file mode 100644 index a576705f2..000000000 --- a/.jscsrc +++ /dev/null @@ -1,73 +0,0 @@ -{ - "disallowImplicitTypeConversion": ["numeric", "boolean", "binary", "string"], - "disallowKeywords": ["with"], - "disallowMixedSpacesAndTabs": true, - "disallowMultipleLineBreaks": true, - "disallowOperatorBeforeLineBreak": ["."], - "disallowSpaceAfterKeywords": [ - "void"//, - //"typeof" - ], - "disallowSpaceAfterPrefixUnaryOperators": ["++", "--", "+", "-", "~"], - "disallowSpaceBeforePostfixUnaryOperators": ["++", "--"], - "disallowSpacesInCallExpression": true, - "disallowSpacesInNamedFunctionExpression": { - "beforeOpeningRoundBrace": true}, - "disallowTrailingComma": true, - "disallowTrailingWhitespace": true, - "maximumLineLength": 160, - "requireCommaBeforeLineBreak": true, - "requireCurlyBraces": [ "if", - "else", - "for", - "while", - "do", - "try", - "catch"], - "requireOperatorBeforeLineBreak": [ "?", - "=", - "+", - "-", - "/", - "*", - "==", - "===", - "!=", - "!==", - ">", - ">=", - "<", - "<="], - "requireSpaceAfterBinaryOperators": true, - "requireSpaceAfterKeywords": [ - "else", - "case", - "try", - "typeof", - "return", - "if", - "for", - "while", - "do" - ], - "requireSpaceBeforeBlockStatements": true, - "requireSpaceBeforeBinaryOperators": [ - "=", - "+", - "-", - "/", - "*", - "==", - "===", - "!=", - "!==" - ], - "requireSpaceBeforeBlockStatements": true, - "requireSpaceBetweenArguments": true, - "requireSpacesInConditionalExpression": true, - "requireSpacesInForStatement": true, - "requireSpacesInNamedFunctionExpression": { - "beforeOpeningCurlyBrace": true - }, - "validateIndentation": 4 -} \ No newline at end of file diff --git a/.jshintrc b/.jshintrc deleted file mode 100644 index c189e87dc..000000000 --- a/.jshintrc +++ /dev/null @@ -1,11 +0,0 @@ -{ - "evil": true, - "latedef": true, - "node": true, - "undef": true, - "unused": "vars", - "noarg": true, - "eqnull": true, - "forin": true, - "predef": ["Promise"] -} diff --git a/.travis.yml b/.travis.yml index 238fb88d7..b8b97f75f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,12 +1,31 @@ language: node_js +cache: + directories: + - travis-phantomjs node_js: + - "9" + - "8" - "6" - "4" - - "0.12" - - "0.10" +before_install: + # from https://github.com/travis-ci/travis-ci/issues/3225#issuecomment-177592725 + # and also from https://github.com/travis-ci/travis-ci/issues/3225#issuecomment-200965782 + - phantomjs --version + - export PATH=$PWD/travis-phantomjs/phantomjs-2.1.1-linux-x86_64/bin:$PATH + - phantomjs --version + # Clear cache and download new copy of PhantomJS if the current version doesn't match 2.1.1. + - "if [ $(phantomjs --version) != '2.1.1' ]; then rm -rf $PWD/travis-phantomjs; mkdir -p $PWD/travis-phantomjs; fi" + - "if [ $(phantomjs --version) != '2.1.1' ]; then wget https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-2.1.1-linux-x86_64.tar.bz2 -O $PWD/travis-phantomjs/phantomjs-2.1.1-linux-x86_64.tar.bz2; fi" + - "if [ $(phantomjs --version) != '2.1.1' ]; then tar -xvf $PWD/travis-phantomjs/phantomjs-2.1.1-linux-x86_64.tar.bz2 -C $PWD/travis-phantomjs; fi" + - phantomjs --version install: - npm install -g grunt-cli - - npm install + # node 0.10 & 0.12 have race condition issues when running custom install scripts + # this can cause phantomjs-prebuilt install script to fail with the error: + # + # Seems related to: https://github.com/npm/npm/issues/8152 + # using solves this. + - travis_retry npm install env: global: - PHANTOMJS_CDNURL=http://cnpmjs.org/downloads diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c0ef7a7c..93d80656b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,29 @@ -# 2.7.2 +# 3.0.0 +2018-02-04 + - Fix `calc()` function to not do math operations on compile + - Rename Directive -> AtRule & Rule -> Declaration + - Cross-platform `@plugin` loading! (Node & Browser) + - Numerous changes / improvements to plugin architecture + - Simplified API calls in plugins (`less.atrule()` vs `new less.tree.AtRule()`) + - Property accessors (`$width` to refer to `width: 300px` value) + - Inline JavaScript disabled by default for security reasons (use `@plugin`) + - Improvements in Less error reporting + - Added feature: returning `null` / `false` from Less functions will remove that line + - Simple `boolean()` and `if()` functions added + - Bug fixes + - Removal of unnecessary nodes from API (like IE's `alpha()`) + +# 2.7.3 +2017-10-23 + + - Bump `request` dependency +# 2.7.2 2017-01-04 - - Revert changes to contrast() function in 2.7.0 + - Revert breaking changes to contrast() function + - Fix error reporting of lessc executable + - Changed octals to hex for ES6 strict mode # 2.7.1 HOTFIX diff --git a/Gruntfile.js b/Gruntfile.js index 5c2d00ad0..9af870a6b 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -2,10 +2,154 @@ module.exports = function (grunt) { + + grunt.option('stack', true) + // Report the elapsed execution time of tasks. require('time-grunt')(grunt); - var COMPRESS_FOR_TESTS = true; + var COMPRESS_FOR_TESTS = false; + var git = require('git-rev'); + + // Sauce Labs browser + var browsers = [ + // Desktop browsers + { + browserName: "chrome", + version: 'latest', + platform: 'Windows 7' + }, + { + browserName: "firefox", + version: 'latest', + platform: 'Linux' + }, + { + browserName: 'safari', + version: '9', + platform: 'OS X 10.11' + }, + { + browserName: "internet explorer", + version: '8', + platform: 'Windows XP' + }, + { + browserName: "internet explorer", + version: '11', + platform: 'Windows 8.1' + }, + { + browserName: "edge", + version: '13', + platform: 'Windows 10' + }, + // Mobile browsers + { + browserName: 'ipad', + deviceName: 'iPad Air Simulator', + deviceOrientation: 'portrait', + version: '8.4', + platform: 'OS X 10.9' + }, + { + browserName: 'iphone', + deviceName: 'iPhone 5 Simulator', + deviceOrientation: 'portrait', + version: '9.3', + platform: 'OS X 10.11' + }, + { + browserName: 'android', + deviceName: 'Google Nexus 7 HD Emulator', + deviceOrientation: 'portrait', + version: '4.4', + platform: 'Linux' + } + ]; + + var sauceJobs = {}; + + var browserTests = [ "filemanager-plugin", + "visitor-plugin", + "global-vars", + "modify-vars", + "production", + "rootpath-relative", + "rootpath", + "relative-urls", + "browser", + "no-js-errors", + "legacy" + ]; + + function makeJob(testName) { + sauceJobs[testName] = { + options: { + urls: testName === 'all' ? + browserTests.map(function(name) { + return "http://localhost:8081/tmp/browser/test-runner-" + name + ".html"; + }) : + ["http://localhost:8081/tmp/browser/test-runner-" + testName + ".html"], + testname: testName === 'all' ? 'Unit Tests for Less.js' : testName, + browsers: browsers, + public: 'public', + recordVideo: false, + videoUploadOnPass: false, + recordScreenshots: process.env.TRAVIS_BRANCH !== "master", + build: process.env.TRAVIS_BRANCH === "master" ? process.env.TRAVIS_JOB_ID : undefined, + tags: [process.env.TRAVIS_BUILD_NUMBER, process.env.TRAVIS_PULL_REQUEST, process.env.TRAVIS_BRANCH], + statusCheckAttempts: -1, + sauceConfig: { + 'idle-timeout': 100 + }, + throttled: 5, + onTestComplete: function(result, callback) { + // Called after a unit test is done, per page, per browser + // 'result' param is the object returned by the test framework's reporter + // 'callback' is a Node.js style callback function. You must invoke it after you + // finish your work. + // Pass a non-null value as the callback's first parameter if you want to throw an + // exception. If your function is synchronous you can also throw exceptions + // directly. + // Passing true or false as the callback's second parameter passes or fails the + // test. Passing undefined does not alter the test result. Please note that this + // only affects the grunt task's result. You have to explicitly update the Sauce + // Labs job's status via its REST API, if you want so. + + // This should be the encrypted value in Travis + var user = process.env.SAUCE_USERNAME; + var pass = process.env.SAUCE_ACCESS_KEY; + + git.short(function(hash) { + require('phin')({ + method: 'PUT', + url: ['https://saucelabs.com/rest/v1', user, 'jobs', result.job_id].join('/'), + auth: { user: user, pass: pass }, + data: { + passed: result.passed, + build: 'build-' + hash + } + }, function (error, response) { + if (error) { + console.log(error); + callback(error); + } else if (response.statusCode !== 200) { + console.log(response); + callback(new Error('Unexpected response status')); + } else { + callback(null, result.passed); + } + }); + }); + + } + } + }; + } + + // Make the SauceLabs jobs + (['all'].concat(browserTests)).map(makeJob); // Project configuration. grunt.initConfig({ @@ -29,9 +173,15 @@ module.exports = function (grunt) { }, shell: { - options: {stdout: true, failOnError: true}, + options: { + stdout: true, + failOnError: true, + execOptions: { + maxBuffer: Infinity + } + }, test: { - command: 'node test' + command: 'node test/index.js' }, benchmark: { command: 'node benchmark/index.js' @@ -107,24 +257,16 @@ module.exports = function (grunt) { } }, - jshint: { - options: {jshintrc: '.jshintrc'}, - files: { - src: [ - 'Gruntfile.js', - 'lib/less/**/*.js', - 'lib/less-node/**/*.js', - 'lib/less-browser/**/*.js', - 'lib/less-rhino/**/*.js', - 'bin/lessc' - ] - } - }, - - jscs: { - src: ["test/**/*.js", "lib/less*/**/*.js", "bin/lessc"], + eslint: { + target: ["Gruntfile.js", + "test/**/*.js", + "lib/less*/**/*.js", + "bin/lessc", + "!test/browser/jasmine-jsreporter.js", + "!test/less/errors/plugin/plugin-error.js" + ], options: { - config: ".jscsrc" + configFile: ".eslintrc.json" } }, @@ -145,7 +287,15 @@ module.exports = function (grunt) { }, main: { // src is used to build list of less files to compile - src: ['test/less/*.less', '!test/less/javascript.less', '!test/less/urls.less', '!test/less/empty.less'], + src: [ + 'test/less/*.less', + // Don't test NPM import, obviously + '!test/less/plugin-module.less', + '!test/less/import-module.less', + '!test/less/javascript.less', + '!test/less/urls.less', + '!test/less/empty.less' + ], options: { helpers: 'test/browser/runner-main-options.js', specs: 'test/browser/runner-main-spec.js', @@ -186,7 +336,7 @@ module.exports = function (grunt) { } }, browser: { - src: ['test/browser/less/*.less'], + src: ['test/browser/less/*.less', 'test/browser/less/plugin/*.less'], options: { helpers: 'test/browser/runner-browser-options.js', specs: 'test/browser/runner-browser-spec.js', @@ -241,14 +391,6 @@ module.exports = function (grunt) { outfile: 'tmp/browser/test-runner-global-vars.html' } }, - postProcessor: { - src: ['test/browser/less/postProcessor/*.less'], - options: { - helpers: 'test/browser/runner-postProcessor-options.js', - specs: 'test/browser/runner-postProcessor.js', - outfile: 'tmp/browser/test-runner-post-processor.html' - } - }, postProcessorPlugin: { src: ['test/less/postProcessorPlugin/*.less'], options: { @@ -283,62 +425,8 @@ module.exports = function (grunt) { } }, - 'saucelabs-jasmine': { - all: { - options: { - urls: ["filemanager-plugin","visitor-plugin","pre-processor-plugin","post-processor-plugin","post-processor", "global-vars", "modify-vars", "production", "rootpath-relative", - "rootpath", "relative-urls", "browser", "no-js-errors", "legacy", "strict-units" - ].map(function(testName) { - return "http://localhost:8081/tmp/browser/test-runner-" + testName + ".html"; - }), - testname: 'Sauce Unit Test for less.js', - browsers: [{ - browserName: "chrome", - version: '', - platform: 'Windows 8' - }, - { - browserName: "firefox", - version: '33', - platform: 'Linux' - }, - { - browserName: "iPad", - version: '8.0', - platform: 'OS X 10.9', - 'device-orientation': 'portrait' - }, - { - browserName: "internet explorer", - version: '8', - platform: 'Windows XP' - }, - { - browserName: "internet explorer", - version: '9', - platform: 'Windows 7' - }, - { - browserName: "internet explorer", - version: '10', - platform: 'Windows 7' - }, - { - browserName: "internet explorer", - version: '11', - platform: 'Windows 8.1' - }], - sauceConfig: { - 'record-video': process.env.TRAVIS_BRANCH !== "master", - 'record-screenshots': process.env.TRAVIS_BRANCH !== "master", - 'idle-timeout': 100, 'max-duration': 120, - build: process.env.TRAVIS_BRANCH === "master" ? process.env.TRAVIS_JOB_ID : undefined, - tags: [process.env.TRAVIS_BUILD_NUMBER, process.env.TRAVIS_PULL_REQUEST, process.env.TRAVIS_BRANCH] - }, - throttled: 3 - } - } - }, + 'saucelabs-jasmine': sauceJobs, + // Clean the version of less built for the tests clean: { @@ -349,6 +437,8 @@ module.exports = function (grunt) { }); // Load these plugins to provide the necessary tasks + grunt.loadNpmTasks('grunt-saucelabs'); + require('jit-grunt')(grunt); // Actually load this plugin's task(s). @@ -366,7 +456,7 @@ module.exports = function (grunt) { 'uglify:dist' ]); - // Release Rhino Version + // Release Rhino Version (UNSUPPORTED) grunt.registerTask('rhino', [ 'browserify:rhino', 'concat:rhino', @@ -415,23 +505,26 @@ module.exports = function (grunt) { 'sauce-after-setup' ]); - // setup a web server to run the browser tests in a browser rather than phantom + // var sauceTests = []; + // browserTests.map(function(testName) { + // sauceTests.push('saucelabs-jasmine:' + testName); + // }); + grunt.registerTask('sauce-after-setup', [ - 'saucelabs-jasmine', + 'saucelabs-jasmine:all', 'clean:sauce_log' ]); var testTasks = [ 'clean', - 'jshint', - 'jscs', + 'eslint', 'shell:test', 'browsertest' ]; if (isNaN(Number(process.env.TRAVIS_PULL_REQUEST, 10)) && - Number(process.env.TRAVIS_NODE_VERSION) === 0.11 && - (process.env.TRAVIS_BRANCH === "master" || process.env.TRAVIS_BRANCH === "sauce")) { + Number(process.env.TRAVIS_NODE_VERSION) === 4 && + (process.env.TRAVIS_BRANCH === "master" || process.env.TRAVIS_BRANCH === "3.x")) { testTasks.push("force:on"); testTasks.push("sauce-after-setup"); testTasks.push("force:off"); @@ -441,7 +534,7 @@ module.exports = function (grunt) { grunt.registerTask('test', testTasks); // Run all tests - grunt.registerTask('quicktest', testTasks.slice(0, testTasks.length -1)); + grunt.registerTask('quicktest', testTasks.slice(0, -1)); // generate a good test environment for testing sourcemaps grunt.registerTask('sourcemap-test', [ diff --git a/README.md b/README.md index aab0a0d09..d99eefb46 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,9 @@ -[![npm version](https://badge.fury.io/js/less.svg)](http://badge.fury.io/js/less) [![Build Status](https://travis-ci.org/less/less.js.svg?branch=master)](https://travis-ci.org/less/less.js) -[![Dependencies](https://david-dm.org/less/less.js.svg)](https://david-dm.org/less/less.js) [![devDependency Status](https://david-dm.org/less/less.js/dev-status.svg)](https://david-dm.org/less/less.js#info=devDependencies) [![optionalDependency Status](https://david-dm.org/less/less.js/optional-status.svg)](https://david-dm.org/less/less.js#info=optionalDependencies) -[![Sauce Test Status](https://saucelabs.com/browser-matrix/less.svg)](https://saucelabs.com/u/less) [![Build status](https://ci.appveyor.com/api/projects/status/bx2qspy3qbuxpl9q/branch/master?svg=true)](https://ci.appveyor.com/project/lukeapage/less-js/branch/master) +### This is the Less 3.0 Edge branch. For the stable (2.x) branch of Less, go [here](https://github.com/less/less.js/tree/master). + + +[![npm version](https://badge.fury.io/js/less.svg)](http://badge.fury.io/js/less) [![Build Status](https://travis-ci.org/less/less.js.svg?branch=master)](https://travis-ci.org/less/less.js) [![Build status](https://ci.appveyor.com/api/projects/status/bx2qspy3qbuxpl9q/branch/3.x?svg=true)](https://ci.appveyor.com/project/lukeapage/less-js/branch/3.x) [![Dependencies](https://david-dm.org/less/less.js.svg)](https://david-dm.org/less/less.js) [![devDependency Status](https://david-dm.org/less/less.js/dev-status.svg)](https://david-dm.org/less/less.js#info=devDependencies) [![optionalDependency Status](https://david-dm.org/less/less.js/optional-status.svg)](https://david-dm.org/less/less.js#info=optionalDependencies) [![Twitter Follow](https://img.shields.io/twitter/follow/lesstocss.svg?style=flat-square)](https://twitter.com/lesstocss) [![Join the chat at https://gitter.im/less/less.js](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/less/less.js?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) Chat with Less.js users + +[![Sauce Test Status](https://saucelabs.com/browser-matrix/less.svg)](https://saucelabs.com/u/less) # [Less.js](http://lesscss.org) @@ -8,8 +11,6 @@ This is the JavaScript, official, stable version of Less. -###### :point_right: [![Join the chat at https://gitter.im/less/less.js](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/less/less.js?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) Chat with Less.js users - ## Getting Started @@ -47,7 +48,7 @@ See the [changelog](CHANGELOG.md) ## [License](LICENSE) -Copyright (c) 2009-2016 [Alexis Sellier](http://cloudhead.io) & The Core Less Team +Copyright (c) 2009-2017 [Alexis Sellier](http://cloudhead.io) & The Core Less Team Licensed under the [Apache License](LICENSE). diff --git a/appveyor.yml b/appveyor.yml index 5739f95cf..e0bbf24cc 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,21 +1,20 @@ # Test against these versions of Node.js. environment: matrix: - - nodejs_version: "0.10" - - nodejs_version: "0.12" - nodejs_version: "4" - nodejs_version: "6" + - nodejs_version: "8" + - nodejs_version: "9" # Install scripts. (runs after repo cloning) install: - # Get the latest stable version of Node 0.STABLE.latest - - ps: Install-Product node $env:nodejs_version - # Use npm v2 - - npm -g install npm@2 - - set PATH=%APPDATA%\npm;%PATH% - - npm -v - # Typical npm stuff. - - npm install + # node 0.10 & 0.12 have race condition issues when running custom install scripts + # this can cause phantomjs-prebuilt install script to fail with the error: + # + # Seems related to: https://github.com/npm/npm/issues/8152 + # using solves this. + - appveyor-retry call npm install + # Grunt-specific stuff. - npm install -g grunt-cli diff --git a/benchmark/index.js b/benchmark/index.js index f73c151d0..87b3da770 100644 --- a/benchmark/index.js +++ b/benchmark/index.js @@ -1,5 +1,6 @@ var path = require('path'), - fs = require('fs'); + fs = require('fs'), + now = require("performance-now"); var less = require('../lib/less-node'); var file = path.join(__dirname, 'benchmark.less'); @@ -7,49 +8,86 @@ var file = path.join(__dirname, 'benchmark.less'); if (process.argv[2]) { file = path.join(process.cwd(), process.argv[2]) } fs.readFile(file, 'utf8', function (e, data) { - var start, end, total; + var start, total; console.log("Benchmarking...\n", path.basename(file) + " (" + parseInt(data.length / 1024) + " KB)", ""); - var benchMarkData = []; + var renderBenchmark = [] + , parserBenchmark = [] + , evalBenchmark = []; - var totalruns = 100; - var ignoreruns = 30; + var totalruns = 30; + var ignoreruns = 5; - for(var i = 0; i < totalruns; i++) { - start = new Date(); + var i = 0; - less.render(data, function (err) { - end = new Date(); + nextRun(); - benchMarkData.push(end - start); + function nextRun() { + var start, renderEnd, parserEnd; + start = now(); + + less.parse(data, {}, function(err, root, imports, options) { if (err) { less.writeError(err); process.exit(3); } + parserEnd = now(); + + var tree, result; + tree = new less.ParseTree(root, imports); + result = tree.toCSS(options); + + renderEnd = now(); + + renderBenchmark.push(renderEnd - start); + parserBenchmark.push(parserEnd - start); + evalBenchmark.push(renderEnd - parserEnd); + + i += 1; + //console.log('Less Run #: ' + i); + if(i < totalruns) { + nextRun(); + } + else { + finish(); + } }); } - var totalTime = 0; - var mintime = Infinity; - var maxtime = 0; - for(var i = ignoreruns; i < totalruns; i++) { - totalTime += benchMarkData[i]; - mintime = Math.min(mintime, benchMarkData[i]); - maxtime = Math.max(maxtime, benchMarkData[i]); + function finish() { + function analyze(benchmark, benchMarkData) { + console.log('----------------------'); + console.log(benchmark); + console.log('----------------------'); + var totalTime = 0; + var mintime = Infinity; + var maxtime = 0; + for(var i = ignoreruns; i < totalruns; i++) { + totalTime += benchMarkData[i]; + mintime = Math.min(mintime, benchMarkData[i]); + maxtime = Math.max(maxtime, benchMarkData[i]); + } + var avgtime = totalTime / (totalruns - ignoreruns); + var variation = maxtime - mintime; + var variationperc = (variation / avgtime) * 100; + + console.log("Min. Time: " + Math.round(mintime) + " ms"); + console.log("Max. Time: " + Math.round(maxtime) + " ms"); + console.log("Total Average Time: " + Math.round(avgtime) + " ms (" + + parseInt(1000 / avgtime * + data.length / 1024) + " KB\/s)"); + console.log("+/- " + Math.round(variationperc) + "%"); + console.log(""); + } + + analyze('Parsing', parserBenchmark); + analyze('Evaluation', evalBenchmark); + analyze('Render Time', renderBenchmark); + } - var avgtime = totalTime / (totalruns - ignoreruns); - var variation = maxtime - mintime; - var variationperc = (variation / avgtime) * 100; - - console.log("Min. Time: "+mintime + " ms"); - console.log("Max. Time: "+maxtime + " ms"); - console.log("Total Average Time: " + avgtime + " ms (" + - parseInt(1000 / avgtime * - data.length / 1024) + " KB\/s)"); - console.log("+/- " + variationperc + "%"); }); diff --git a/bin/lessc b/bin/lessc index 2684217e5..057902542 100755 --- a/bin/lessc +++ b/bin/lessc @@ -14,31 +14,15 @@ try { var less = require('../lib/less-node'), pluginLoader = new less.PluginLoader(less), - plugin, - plugins = []; - -var args = process.argv.slice(1); -var silent = false, + plugins = [], + queuePlugins = [], + args = process.argv.slice(1), + silent = false, verbose = false, - options = { - depends: false, - compress: false, - max_line_len: -1, - lint: false, - paths: [], - color: true, - strictImports: false, - insecure: false, - rootpath: '', - relativeUrls: false, - ieCompat: true, - strictMath: false, - strictUnits: false, - globalVars: null, - modifyVars: null, - urlArgs: '', - plugins: plugins -}; + options = less.options; + +options.plugins = plugins; + var sourceMapOptions = {}; var continueProcessing = true; @@ -94,194 +78,7 @@ function printUsage() { pluginLoader.printUsage(plugins); continueProcessing = false; } - -// self executing function so we can return -(function() { - args = args.filter(function (arg) { - var match; - - match = arg.match(/^-I(.+)$/); - if (match) { - options.paths.push(match[1]); - return false; - } - - match = arg.match(/^--?([a-z][0-9a-z-]*)(?:=(.*))?$/i); - if (match) { - arg = match[1]; - } else { - return arg; - } - - switch (arg) { - case 'v': - case 'version': - console.log("lessc " + less.version.join('.') + " (Less Compiler) [JavaScript]"); - continueProcessing = false; - break; - case 'verbose': - verbose = true; - break; - case 's': - case 'silent': - silent = true; - break; - case 'l': - case 'lint': - options.lint = true; - break; - case 'strict-imports': - options.strictImports = true; - break; - case 'h': - case 'help': - printUsage(); - break; - case 'x': - case 'compress': - options.compress = true; - break; - case 'insecure': - options.insecure = true; - break; - case 'M': - case 'depends': - options.depends = true; - break; - case 'max-line-len': - if (checkArgFunc(arg, match[2])) { - options.maxLineLen = parseInt(match[2], 10); - if (options.maxLineLen <= 0) { - options.maxLineLen = -1; - } - } - break; - case 'no-color': - options.color = false; - break; - case 'no-ie-compat': - options.ieCompat = false; - break; - case 'no-js': - options.javascriptEnabled = false; - break; - case 'include-path': - if (checkArgFunc(arg, match[2])) { - // ; supported on windows. - // : supported on windows and linux, excluding a drive letter like C:\ so C:\file:D:\file parses to 2 - options.paths = match[2] - .split(os.type().match(/Windows/) ? /:(?!\\)|;/ : ':') - .map(function(p) { - if (p) { - return path.resolve(process.cwd(), p); - } - }); - } - break; - case 'line-numbers': - if (checkArgFunc(arg, match[2])) { - options.dumpLineNumbers = match[2]; - } - break; - case 'source-map': - options.sourceMap = true; - if (match[2]) { - sourceMapOptions.sourceMapFullFilename = match[2]; - } - break; - case 'source-map-rootpath': - if (checkArgFunc(arg, match[2])) { - sourceMapOptions.sourceMapRootpath = match[2]; - } - break; - case 'source-map-basepath': - if (checkArgFunc(arg, match[2])) { - sourceMapOptions.sourceMapBasepath = match[2]; - } - break; - case 'source-map-map-inline': - sourceMapFileInline = true; - options.sourceMap = true; - break; - case 'source-map-less-inline': - sourceMapOptions.outputSourceFiles = true; - break; - case 'source-map-url': - if (checkArgFunc(arg, match[2])) { - sourceMapOptions.sourceMapURL = match[2]; - } - break; - case 'rp': - case 'rootpath': - if (checkArgFunc(arg, match[2])) { - options.rootpath = match[2].replace(/\\/g, '/'); - } - break; - case "ru": - case "relative-urls": - options.relativeUrls = true; - break; - case "sm": - case "strict-math": - if (checkArgFunc(arg, match[2])) { - options.strictMath = checkBooleanArg(match[2]); - } - break; - case "su": - case "strict-units": - if (checkArgFunc(arg, match[2])) { - options.strictUnits = checkBooleanArg(match[2]); - } - break; - case "global-var": - if (checkArgFunc(arg, match[2])) { - if (!options.globalVars) { - options.globalVars = {}; - } - parseVariableOption(match[2], options.globalVars); - } - break; - case "modify-var": - if (checkArgFunc(arg, match[2])) { - if (!options.modifyVars) { - options.modifyVars = {}; - } - - parseVariableOption(match[2], options.modifyVars); - } - break; - case 'url-args': - if (checkArgFunc(arg, match[2])) { - options.urlArgs = match[2]; - } - break; - case 'plugin': - var splitupArg = match[2].match(/^([^=]+)(=(.*))?/), - name = splitupArg[1], - pluginOptions = splitupArg[3]; - - plugin = pluginLoader.tryLoadPlugin(name, pluginOptions); - if (plugin) { - plugins.push(plugin); - } else { - console.error("Unable to load plugin " + name + - " please make sure that it is installed under or at the same level as less"); - process.exitCode = 1; - } - break; - default: - plugin = pluginLoader.tryLoadPlugin("less-plugin-" + arg, match[2]); - if (plugin) { - plugins.push(plugin); - } else { - console.error("Unable to interpret argument " + arg + - " - if it is a plugin (less-plugin-" + arg + "), make sure that it is installed under or at" + - " the same level as less"); - process.exitCode = 1; - } - break; - } - }); +function render() { if (!continueProcessing) { return; @@ -340,7 +137,7 @@ function printUsage() { sourceMapOptions.sourceMapRootpath = path.relative(pathToMap, pathToInput); } - if (! input) { + if (!input) { console.error("lessc: no input files"); console.error(""); printUsage(); @@ -355,7 +152,7 @@ function printUsage() { if (!existsSync(dir)) { if (mkdirp === undefined) { try {mkdirp = require('mkdirp');} - catch(e) { mkdirp = null; } + catch (e) { mkdirp = null; } } cmd = mkdirp && mkdirp.sync || fs.mkdirSync; cmd(dir); @@ -489,7 +286,11 @@ function printUsage() { } }, function(err) { - less.writeError(err, options); + if (!options.silent) { + console.error(err.toString({ + stylize: options.color && less.lesscHelper.stylize + })); + } process.exitCode = 1; }); }; @@ -509,4 +310,222 @@ function printUsage() { parseLessFile(false, buffer); }); } +} + +function processPluginQueue() { + var x = 0; + + function pluginError(name) { + console.error("Unable to load plugin " + name + + " please make sure that it is installed under or at the same level as less"); + process.exitCode = 1; + } + function pluginFinished(plugin) { + x++; + plugins.push(plugin); + if (x === queuePlugins.length) { + render(); + } + } + queuePlugins.forEach(function(queue) { + pluginLoader.tryLoadPlugin(queue.name, function(err, data) { + if (err) { + pluginError(queue.name); + } + else { + pluginFinished({ + fileContent: data.contents, + filename: data.filename, + options: queue.options + }); + } + }); + }); +} + +// self executing function so we can return +(function() { + args = args.filter(function (arg) { + var match; + + match = arg.match(/^-I(.+)$/); + if (match) { + options.paths.push(match[1]); + return false; + } + + match = arg.match(/^--?([a-z][0-9a-z-]*)(?:=(.*))?$/i); + if (match) { + arg = match[1]; + } else { + return arg; + } + + switch (arg) { + case 'v': + case 'version': + console.log("lessc " + less.version.join('.') + " (Less Compiler) [JavaScript]"); + continueProcessing = false; + break; + case 'verbose': + verbose = true; + break; + case 's': + case 'silent': + silent = true; + break; + case 'l': + case 'lint': + options.lint = true; + break; + case 'strict-imports': + options.strictImports = true; + break; + case 'h': + case 'help': + printUsage(); + break; + case 'x': + case 'compress': + options.compress = true; + break; + case 'insecure': + options.insecure = true; + break; + case 'M': + case 'depends': + options.depends = true; + break; + case 'max-line-len': + if (checkArgFunc(arg, match[2])) { + options.maxLineLen = parseInt(match[2], 10); + if (options.maxLineLen <= 0) { + options.maxLineLen = -1; + } + } + break; + case 'no-color': + options.color = false; + break; + case 'ie-compat': + options.ieCompat = true; + break; + case 'js': + options.javascriptEnabled = true; + break; + case 'no-js': + console.error('The "--no-js" argument is deprecated, as inline JavaScript ' + + 'is disabled by default. Use "--js" to enable inline JavaScript (not recommended).'); + break; + case 'include-path': + if (checkArgFunc(arg, match[2])) { + // ; supported on windows. + // : supported on windows and linux, excluding a drive letter like C:\ so C:\file:D:\file parses to 2 + options.paths = match[2] + .split(os.type().match(/Windows/) ? /:(?!\\)|;/ : ':') + .map(function(p) { + if (p) { + return path.resolve(process.cwd(), p); + } + }); + } + break; + case 'line-numbers': + if (checkArgFunc(arg, match[2])) { + options.dumpLineNumbers = match[2]; + } + break; + case 'source-map': + options.sourceMap = true; + if (match[2]) { + sourceMapOptions.sourceMapFullFilename = match[2]; + } + break; + case 'source-map-rootpath': + if (checkArgFunc(arg, match[2])) { + sourceMapOptions.sourceMapRootpath = match[2]; + } + break; + case 'source-map-basepath': + if (checkArgFunc(arg, match[2])) { + sourceMapOptions.sourceMapBasepath = match[2]; + } + break; + case 'source-map-inline': + case 'source-map-map-inline': + sourceMapFileInline = true; + options.sourceMap = true; + break; + case 'source-map-include-source': + case 'source-map-less-inline': + sourceMapOptions.outputSourceFiles = true; + break; + case 'source-map-url': + if (checkArgFunc(arg, match[2])) { + sourceMapOptions.sourceMapURL = match[2]; + } + break; + case 'rp': + case 'rootpath': + if (checkArgFunc(arg, match[2])) { + options.rootpath = match[2].replace(/\\/g, '/'); + } + break; + case "ru": + case "relative-urls": + options.relativeUrls = true; + break; + case "sm": + case "strict-math": + if (checkArgFunc(arg, match[2])) { + options.strictMath = checkBooleanArg(match[2]); + } + break; + case "su": + case "strict-units": + if (checkArgFunc(arg, match[2])) { + options.strictUnits = checkBooleanArg(match[2]); + } + break; + case "global-var": + if (checkArgFunc(arg, match[2])) { + if (!options.globalVars) { + options.globalVars = {}; + } + parseVariableOption(match[2], options.globalVars); + } + break; + case "modify-var": + if (checkArgFunc(arg, match[2])) { + if (!options.modifyVars) { + options.modifyVars = {}; + } + + parseVariableOption(match[2], options.modifyVars); + } + break; + case 'url-args': + if (checkArgFunc(arg, match[2])) { + options.urlArgs = match[2]; + } + break; + case 'plugin': + var splitupArg = match[2].match(/^([^=]+)(=(.*))?/), + name = splitupArg[1], + pluginOptions = splitupArg[3]; + queuePlugins.push({ name: name, options: pluginOptions }); + break; + default: + queuePlugins.push({ name: arg, options: match[2], default: true }); + break; + } + }); + + if (queuePlugins.length > 0) { + processPluginQueue(); + } + else { + render(); + } + })(); diff --git a/dist/less.js b/dist/less.js index 98c00a7f7..17d34f139 100644 --- a/dist/less.js +++ b/dist/less.js @@ -1,8 +1,8 @@ /*! - * Less - Leaner CSS v2.7.3 + * Less - Leaner CSS v3.0.0 * http://lesscss.org * - * Copyright (c) 2009-2017, Alexis Sellier + * Copyright (c) 2009-2018, Alexis Sellier * Licensed under the Apache-2.0 License. * */ @@ -56,22 +56,40 @@ module.exports = function(window, options) { options.onReady = true; } + options.javascriptEnabled = (options.javascriptEnabled || options.inlineJavaScript) ? true : false; + }; -},{"./browser":3,"./utils":10}],2:[function(require,module,exports){ +},{"./browser":3,"./utils":11}],2:[function(require,module,exports){ /** * Kicks off less and compiles any stylesheets * used in the browser distributed version of less * to kick-start less using the browser api */ -/*global window, document */ +/* global window, document */ + +// TODO - consider switching this out for a recommendation for this polyfill? +// +// Browsers have good Promise support +require("promise/polyfill"); -// shim Promise if required -require('promise/polyfill.js'); +var options = require('../less/default-options')(); -var options = window.less || {}; +if (window.less) { + for (key in window.less) { + if (window.less.hasOwnProperty(key)) { + options[key] = window.less[key]; + } + } +} require("./add-default-options")(window, options); +options.plugins = options.plugins || []; + +if (window.LESS_PLUGINS) { + options.plugins = options.plugins.concat(window.LESS_PLUGINS); +} + var less = module.exports = require("./index")(window, options); window.less = less; @@ -92,7 +110,7 @@ if (options.onReady) { if (/!watch/.test(window.location.hash)) { less.watch(); } - // Simulate synchronous stylesheet loading by blocking page rendering + // Simulate synchronous stylesheet loading by hiding page rendering if (!options.async) { css = 'body { display: none !important }'; head = document.head || document.getElementsByTagName('head')[0]; @@ -111,7 +129,7 @@ if (options.onReady) { less.pageLoadFinished = less.refresh(less.env === 'development').then(resolveOrReject, resolveOrReject); } -},{"./add-default-options":1,"./index":8,"promise/polyfill.js":97}],3:[function(require,module,exports){ +},{"../less/default-options":16,"./add-default-options":1,"./index":8,"promise/polyfill":100}],3:[function(require,module,exports){ var utils = require("./utils"); module.exports = { createCSS: function (document, styles, sheet) { @@ -177,7 +195,7 @@ module.exports = { } }; -},{"./utils":10}],4:[function(require,module,exports){ +},{"./utils":11}],4:[function(require,module,exports){ // Cache system is a bit outdated and could do with work module.exports = function(window, options, logger) { @@ -197,8 +215,8 @@ module.exports = function(window, options, logger) { if (modifyVars) { cache.setItem(path + ':vars', JSON.stringify(modifyVars)); } - } catch(e) { - //TODO - could do with adding more robust error handling + } catch (e) { + // TODO - could do with adding more robust error handling logger.error('failed to save "' + path + '" to local storage for caching.'); } } @@ -248,7 +266,7 @@ module.exports = function(window, less, options) { } }; - if (e.extract) { + if (e.line) { errorline(e, 0, ''); errorline(e, 1, 'line'); errorline(e, 2, ''); @@ -336,7 +354,7 @@ module.exports = function(window, less, options) { } function removeErrorConsole(path) { - //no action + // no action } function removeError(path) { @@ -354,7 +372,7 @@ module.exports = function(window, less, options) { var filename = e.filename || rootHref; var errors = []; var content = (e.type || "Syntax") + "Error: " + (e.message || 'There is an error in your .less file') + - " in " + filename + " "; + " in " + filename; var errorline = function (e, i, classname) { if (e.extract[i] !== undefined) { @@ -364,11 +382,11 @@ module.exports = function(window, less, options) { } }; - if (e.extract) { + if (e.line) { errorline(e, 0, ''); errorline(e, 1, 'line'); errorline(e, 2, ''); - content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':\n' + + content += ' on line ' + e.line + ', column ' + (e.column + 1) + ':\n' + errors.join('\n'); } if (e.stack && (e.extract || options.logLevel >= 4)) { @@ -393,8 +411,8 @@ module.exports = function(window, less, options) { }; }; -},{"./browser":3,"./utils":10}],6:[function(require,module,exports){ -/*global window, XMLHttpRequest */ +},{"./browser":3,"./utils":11}],6:[function(require,module,exports){ +/* global window, XMLHttpRequest */ module.exports = function(options, logger) { @@ -402,22 +420,7 @@ module.exports = function(options, logger) { var fileCache = {}; - //TODOS - move log somewhere. pathDiff and doing something similar in node. use pathDiff in the other browser file for the initial load - - function getXMLHttpRequest() { - if (window.XMLHttpRequest && (window.location.protocol !== "file:" || !("ActiveXObject" in window))) { - return new XMLHttpRequest(); - } else { - try { - /*global ActiveXObject */ - return new ActiveXObject("Microsoft.XMLHTTP"); - } catch (e) { - logger.error("browser doesn't support AJAX."); - return null; - } - } - } - + // TODOS - move log somewhere. pathDiff and doing something similar in node. use pathDiff in the other browser file for the initial load var FileManager = function() { }; @@ -434,7 +437,7 @@ module.exports = function(options, logger) { }; FileManager.prototype.doXHR = function doXHR(url, type, callback, errback) { - var xhr = getXMLHttpRequest(); + var xhr = new XMLHttpRequest(); var async = options.isFileProtocol ? options.fileAsync : true; if (typeof xhr.overrideMimeType === 'function') { @@ -478,43 +481,50 @@ module.exports = function(options, logger) { fileCache = {}; }; - FileManager.prototype.loadFile = function loadFile(filename, currentDirectory, options, environment, callback) { + FileManager.prototype.loadFile = function loadFile(filename, currentDirectory, options, environment) { + // TODO: Add prefix support like less-node? + // What about multiple paths? + if (currentDirectory && !this.isPathAbsolute(filename)) { filename = currentDirectory + filename; } + filename = options.ext ? this.tryAppendExtension(filename, options.ext) : filename; + options = options || {}; // sheet may be set to the stylesheet for the initial load or a collection of properties including // some context variables for imports var hrefParts = this.extractUrlParts(filename, window.location.href); var href = hrefParts.url; - - if (options.useFileCache && fileCache[href]) { - try { - var lessText = fileCache[href]; - callback(null, { contents: lessText, filename: href, webInfo: { lastModified: new Date() }}); - } catch (e) { - callback({filename: href, message: "Error loading file " + href + " error was " + e.message}); + var self = this; + + return new Promise(function(resolve, reject) { + if (options.useFileCache && fileCache[href]) { + try { + var lessText = fileCache[href]; + return resolve({ contents: lessText, filename: href, webInfo: { lastModified: new Date() }}); + } catch (e) { + return reject({ filename: href, message: "Error loading file " + href + " error was " + e.message }); + } } - return; - } - this.doXHR(href, options.mime, function doXHRCallback(data, lastModified) { - // per file cache - fileCache[href] = data; + self.doXHR(href, options.mime, function doXHRCallback(data, lastModified) { + // per file cache + fileCache[href] = data; - // Use remote copy (re-parse) - callback(null, { contents: data, filename: href, webInfo: { lastModified: lastModified }}); - }, function doXHRError(status, url) { - callback({ type: 'File', message: "'" + url + "' wasn't found (" + status + ")", href: href }); + // Use remote copy (re-parse) + resolve({ contents: data, filename: href, webInfo: { lastModified: lastModified }}); + }, function doXHRError(status, url) { + reject({ type: 'File', message: "'" + url + "' wasn't found (" + status + ")", href: href }); + }); }); }; return FileManager; }; -},{"../less/environment/abstract-file-manager.js":15}],7:[function(require,module,exports){ +},{"../less/environment/abstract-file-manager.js":17}],7:[function(require,module,exports){ module.exports = function() { var functionRegistry = require("./../less/functions/function-registry"); @@ -544,7 +554,7 @@ module.exports = function() { functionRegistry.addMultiple(imageFunctions); }; -},{"./../less/functions/function-registry":22}],8:[function(require,module,exports){ +},{"./../less/functions/function-registry":26}],8:[function(require,module,exports){ // // index.js // Should expose the additional browser functions on to the less object @@ -555,42 +565,29 @@ var addDataAttr = require("./utils").addDataAttr, module.exports = function(window, options) { var document = window.document; var less = require('../less')(); - - //module.exports = less; + less.options = options; var environment = less.environment, FileManager = require("./file-manager")(options, less.logger), fileManager = new FileManager(); environment.addFileManager(fileManager); less.FileManager = FileManager; + less.PluginLoader = require("./plugin-loader"); require("./log-listener")(less, options); var errors = require("./error-reporting")(window, less, options); var cache = less.cache = options.cache || require("./cache")(window, options, less.logger); require('./image-size')(less.environment); - //Setup user functions + // Setup user functions - Deprecate? if (options.functions) { less.functions.functionRegistry.addMultiple(options.functions); } var typePattern = /^text\/(x-)?less$/; - function postProcessCSS(styles) { // deprecated, use a plugin for postprocesstasks - if (options.postProcessor && typeof options.postProcessor === 'function') { - styles = options.postProcessor.call(styles, styles) || styles; - } - return styles; - } - function clone(obj) { - var cloned = {}; - for (var prop in obj) { - if (obj.hasOwnProperty(prop)) { - cloned[prop] = obj[prop]; - } - } - return cloned; + return JSON.parse(JSON.stringify(obj || {})); } // only really needed for phantom @@ -614,7 +611,7 @@ module.exports = function(window, options) { var lessText = style.innerHTML || ''; instanceOptions.filename = document.location.href.replace(/#.*$/, ''); - /*jshint loopfunc:true */ + /* jshint loopfunc:true */ // use closure to store current style less.render(lessText, instanceOptions, bind(function(style, e, result) { @@ -670,7 +667,7 @@ module.exports = function(window, options) { } - //TODO add tests around how this behaves when reloading + // TODO add tests around how this behaves when reloading errors.remove(path); instanceOptions.rootFileInfo = newFileInfo; @@ -679,20 +676,20 @@ module.exports = function(window, options) { e.href = path; callback(e); } else { - result.css = postProcessCSS(result.css); cache.setCSS(sheet.href, webInfo.lastModified, instanceOptions.modifyVars, result.css); callback(null, result.css, data, sheet, webInfo, path); } }); } - fileManager.loadFile(sheet.href, null, instanceOptions, environment, function(e, loadedFile) { - if (e) { - callback(e); - return; - } - loadInitialFileCallback(loadedFile); - }); + fileManager.loadFile(sheet.href, null, instanceOptions, environment) + .then(function(loadedFile) { + loadInitialFileCallback(loadedFile); + }).catch(function(err) { + console.log(err); + callback(err); + }); + } function loadStyleSheets(callback, reload, modifyVars) { @@ -832,7 +829,7 @@ module.exports = function(window, options) { return less; }; -},{"../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){ +},{"../less":35,"./browser":3,"./cache":4,"./error-reporting":5,"./file-manager":6,"./image-size":7,"./log-listener":9,"./plugin-loader":10,"./utils":11}],9:[function(require,module,exports){ module.exports = function(less, options) { var logLevel_debug = 4, @@ -878,6 +875,33 @@ module.exports = function(less, options) { }; },{}],10:[function(require,module,exports){ +// TODO: Add tests for browser @plugin +/*global window */ + +var AbstractPluginLoader = require("../less/environment/abstract-plugin-loader.js"); + +/** + * Browser Plugin Loader + */ +var PluginLoader = function(less) { + this.less = less; + // shim for browser require? + this.require = require; +}; + +PluginLoader.prototype = new AbstractPluginLoader(); + +PluginLoader.prototype.loadPlugin = function(filename, basePath, context, environment, fileManager) { + return new Promise(function(fulfill, reject) { + fileManager.loadFile(filename, basePath, context, environment) + .then(fulfill).catch(reject); + }); +}; + +module.exports = PluginLoader; + + +},{"../less/environment/abstract-plugin-loader.js":18}],11:[function(require,module,exports){ module.exports = { extractId: function(href) { return href.replace(/^[a-z-]+:\/+?[^\/]+/, '') // Remove protocol & domain @@ -896,14 +920,14 @@ module.exports = { try { options[opt] = JSON.parse(tag.dataset[opt]); } - catch(_) {} + catch (_) {} } } } } }; -},{}],11:[function(require,module,exports){ +},{}],12:[function(require,module,exports){ var contexts = {}; module.exports = contexts; @@ -946,18 +970,18 @@ contexts.Parse = function(options) { }; var evalCopyProperties = [ - 'paths', // additional include paths - 'compress', // whether to compress - 'ieCompat', // whether to enforce IE compatibility (IE8 data-uri) - 'strictMath', // whether math has to be within parenthesis - 'strictUnits', // whether units need to evaluate correctly - 'sourceMap', // whether to output a source map - 'importMultiple', // whether we are currently importing multiple copies - 'urlArgs', // whether to add args into url tokens - 'javascriptEnabled',// option - whether JavaScript is enabled. if undefined, defaults to true - 'pluginManager', // Used as the plugin manager for the session - 'importantScope' // used to bubble up !important statements - ]; + 'paths', // additional include paths + 'compress', // whether to compress + 'ieCompat', // whether to enforce IE compatibility (IE8 data-uri) + 'strictMath', // whether math has to be within parenthesis + 'strictUnits', // whether units need to evaluate correctly + 'sourceMap', // whether to output a source map + 'importMultiple', // whether we are currently importing multiple copies + 'urlArgs', // whether to add args into url tokens + 'javascriptEnabled', // option - whether Inline JavaScript is enabled. if undefined, defaults to false + 'pluginManager', // Used as the plugin manager for the session + 'importantScope' // used to bubble up !important statements +]; contexts.Eval = function(options, frames) { copyFromOriginal(options, this, evalCopyProperties); @@ -979,7 +1003,11 @@ contexts.Eval.prototype.outOfParenthesis = function () { this.parensStack.pop(); }; +contexts.Eval.prototype.mathOn = true; contexts.Eval.prototype.isMathOn = function () { + if (!this.mathOn) { + return false; + } return this.strictMath ? (this.parensStack && this.parensStack.length) : true; }; @@ -989,13 +1017,13 @@ contexts.Eval.prototype.isPathRelative = function (path) { contexts.Eval.prototype.normalizePath = function( path ) { var - segments = path.split("/").reverse(), - segment; + segments = path.split("/").reverse(), + segment; path = []; while (segments.length !== 0 ) { segment = segments.pop(); - switch( segment ) { + switch ( segment ) { case ".": break; case "..": @@ -1014,9 +1042,9 @@ contexts.Eval.prototype.normalizePath = function( path ) { return path.join("/"); }; -//todo - do the same for the toCSS ? +// todo - do the same for the toCSS ? -},{}],12:[function(require,module,exports){ +},{}],13:[function(require,module,exports){ module.exports = { 'aliceblue':'#f0f8ff', 'antiquewhite':'#faebd7', @@ -1167,13 +1195,13 @@ module.exports = { 'yellow':'#ffff00', 'yellowgreen':'#9acd32' }; -},{}],13:[function(require,module,exports){ +},{}],14:[function(require,module,exports){ module.exports = { colors: require("./colors"), unitConversions: require("./unit-conversions") }; -},{"./colors":12,"./unit-conversions":14}],14:[function(require,module,exports){ +},{"./colors":13,"./unit-conversions":15}],15:[function(require,module,exports){ module.exports = { length: { 'm': 1, @@ -1195,7 +1223,73 @@ module.exports = { 'turn': 1 } }; -},{}],15:[function(require,module,exports){ +},{}],16:[function(require,module,exports){ +// Export a new default each time +module.exports = function() { + return { + /* Outputs a makefile import dependency list to stdout. */ + depends: false, + + /* Compress using less built-in compression. + * This does an okay job but does not utilise all the tricks of + * dedicated css compression. */ + compress: false, + + /* Runs the less parser and just reports errors without any output. */ + lint: false, + + /* Sets available include paths. + * If the file in an @import rule does not exist at that exact location, + * less will look for it at the location(s) passed to this option. + * You might use this for instance to specify a path to a library which + * you want to be referenced simply and relatively in the less files. */ + paths: [], + + /* color output in the terminal */ + color: true, + + /* The strictImports controls whether the compiler will allow an @import inside of either + * @media blocks or (a later addition) other selector blocks. + * See: https://github.com/less/less.js/issues/656 */ + strictImports: false, + + /* Allow Imports from Insecure HTTPS Hosts */ + insecure: false, + + /* Allows you to add a path to every generated import and url in your css. + * This does not affect less import statements that are processed, just ones + * that are left in the output css. */ + rootpath: '', + + /* By default URLs are kept as-is, so if you import a file in a sub-directory + * that references an image, exactly the same URL will be output in the css. + * This option allows you to re-write URL's in imported files so that the + * URL is always relative to the base imported file */ + relativeUrls: false, + + /* Compatibility with IE8. Used for limiting data-uri length */ + ieCompat: false, // true until 3.0 + + /* Without this option on, Less will try and process all math in your css */ + strictMath: false, + + /* Without this option, less attempts to guess at the output unit when it does maths. */ + strictUnits: false, + + /* Effectively the declaration is put at the top of your base Less file, + * meaning it can be used but it also can be overridden if this variable + * is defined in the file. */ + globalVars: null, + + /* As opposed to the global variable option, this puts the declaration at the + * end of your base file, meaning it will override anything defined in your Less file. */ + modifyVars: null, + + /* This option allows you to specify a argument to go on to every URL. */ + urlArgs: '' + } +} +},{}],17:[function(require,module,exports){ var abstractFileManager = function() { }; @@ -1233,13 +1327,14 @@ abstractFileManager.prototype.alwaysMakePathsAbsolute = function() { abstractFileManager.prototype.isPathAbsolute = function(filename) { return (/^(?:[a-z-]+:|\/|\\|#)/i).test(filename); }; - +// TODO: pull out / replace? abstractFileManager.prototype.join = function(basePath, laterPath) { if (!basePath) { return laterPath; } return basePath + laterPath; }; + abstractFileManager.prototype.pathDiff = function pathDiff(url, baseUrl) { // diff between two paths to create a relative path @@ -1273,7 +1368,7 @@ abstractFileManager.prototype.extractUrlParts = function extractUrlParts(url, ba var urlPartsRegex = /^((?:[a-z-]+:)?\/{2}(?:[^\/\?#]*\/)|([\/\\]))?((?:[^\/\\\?#]*[\/\\])*)([^\/\\\?#]*)([#\?].*)?$/i, urlParts = url.match(urlPartsRegex), - returner = {}, directories = [], i, baseUrlParts; + returner = {}, rawDirectories = [], directories = [], i, baseUrlParts; if (!urlParts) { throw new Error("Could not parse sheet href - '" + url + "'"); @@ -1292,27 +1387,26 @@ abstractFileManager.prototype.extractUrlParts = function extractUrlParts(url, ba } if (urlParts[3]) { - directories = urlParts[3].replace(/\\/g, "/").split("/"); + rawDirectories = urlParts[3].replace(/\\/g, "/").split("/"); - // extract out . before .. so .. doesn't absorb a non-directory - for (i = 0; i < directories.length; i++) { - if (directories[i] === ".") { - directories.splice(i, 1); - i -= 1; - } - } + // collapse '..' and skip '.' + for (i = 0; i < rawDirectories.length; i++) { - for (i = 0; i < directories.length; i++) { - if (directories[i] === ".." && i > 0) { - directories.splice(i - 1, 2); - i -= 2; + if (rawDirectories[i] === "..") { + directories.pop(); } + else if (rawDirectories[i] !== ".") { + directories.push(rawDirectories[i]); + } + } } returner.hostPart = urlParts[1]; returner.directories = directories; + returner.rawPath = (urlParts[1] || "") + rawDirectories.join("/"); returner.path = (urlParts[1] || "") + directories.join("/"); + returner.filename = urlParts[4]; returner.fileUrl = returner.path + (urlParts[4] || ""); returner.url = returner.fileUrl + (urlParts[5] || ""); return returner; @@ -1320,7 +1414,178 @@ abstractFileManager.prototype.extractUrlParts = function extractUrlParts(url, ba module.exports = abstractFileManager; -},{}],16:[function(require,module,exports){ +},{}],18:[function(require,module,exports){ +var functionRegistry = require("../functions/function-registry"), + LessError = require('../less-error'); + +var AbstractPluginLoader = function() { +}; + +function error(msg, type) { + throw new LessError( + { + type: type || 'Syntax', + message: msg + } + ); +} +AbstractPluginLoader.prototype.evalPlugin = function(contents, context, imports, pluginOptions, fileInfo) { + + var loader, + registry, + pluginObj, + localModule, + pluginManager, + filename; + + pluginManager = context.pluginManager; + + if (fileInfo) { + if (typeof fileInfo === "string") { + filename = fileInfo; + } + else { + filename = fileInfo.filename; + } + } + var shortname = (new this.less.FileManager()).extractUrlParts(filename).filename; + + if (filename) { + pluginObj = pluginManager.get(filename); + + if (pluginObj) { + this.trySetOptions(pluginObj, filename, shortname, pluginOptions); + try { + if (pluginObj.use) { + pluginObj.use.call(this.context, pluginObj); + } + } + catch (e) { + e.message = 'Error during @plugin call'; + return new this.less.LessError(e, imports, filename); + } + return pluginObj; + } + } + localModule = { + exports: {}, + pluginManager: pluginManager, + fileInfo: fileInfo + }; + registry = functionRegistry.create(); + + var registerPlugin = function(obj) { + pluginObj = obj; + }; + + try { + loader = new Function("module", "require", "registerPlugin", "functions", "tree", "less", "fileInfo", contents); + loader(localModule, this.require, registerPlugin, registry, this.less.tree, this.less, fileInfo); + } catch (e) { + return new this.less.LessError(e, imports, filename); + } + + if (!pluginObj) { + pluginObj = localModule.exports; + } + pluginObj = this.validatePlugin(pluginObj, filename, shortname); + + if (pluginObj) { + // Run on first load + pluginManager.addPlugin(pluginObj, fileInfo.filename, registry); + pluginObj.functions = registry.getLocalFunctions(); + pluginObj.imports = imports; + pluginObj.filename = filename; + + this.trySetOptions(pluginObj, filename, shortname, pluginOptions); + + // Run every @plugin call + try { + if (pluginObj.use) { + pluginObj.use.call(this.context, pluginObj); + } + } + catch (e) { + e.message = 'Error during @plugin call'; + return new this.less.LessError(e, imports, filename); + } + + } + else { + return new this.less.LessError({ message: "Not a valid plugin" }); + } + + return pluginObj; + +}; + +AbstractPluginLoader.prototype.trySetOptions = function(plugin, filename, name, options) { + if (options) { + if (!plugin.setOptions) { + error("Options have been provided but the plugin " + name + " does not support any options."); + return null; + } + try { + plugin.setOptions(options); + } + catch (e) { + error("Error setting options on plugin " + name + '\n' + e.message); + return null; + } + } +}; + +AbstractPluginLoader.prototype.validatePlugin = function(plugin, filename, name) { + if (plugin) { + // support plugins being a function + // so that the plugin can be more usable programmatically + if (typeof plugin === "function") { + plugin = new plugin(); + } + + if (plugin.minVersion) { + if (this.compareVersion(plugin.minVersion, this.less.version) < 0) { + error("Plugin " + name + " requires version " + this.versionToString(plugin.minVersion)); + return null; + } + } + return plugin; + } + return null; +}; + +AbstractPluginLoader.prototype.compareVersion = function(aVersion, bVersion) { + if (typeof aVersion === "string") { + aVersion = aVersion.match(/^(\d+)\.?(\d+)?\.?(\d+)?/); + aVersion.shift(); + } + for (var i = 0; i < aVersion.length; i++) { + if (aVersion[i] !== bVersion[i]) { + return parseInt(aVersion[i]) > parseInt(bVersion[i]) ? -1 : 1; + } + } + return 0; +}; +AbstractPluginLoader.prototype.versionToString = function(version) { + var versionString = ""; + for (var i = 0; i < version.length; i++) { + versionString += (versionString ? "." : "") + version[i]; + } + return versionString; +}; +AbstractPluginLoader.prototype.printUsage = function(plugins) { + for (var i = 0; i < plugins.length; i++) { + var plugin = plugins[i]; + if (plugin.printUsage) { + plugin.printUsage(); + } + } +}; + +module.exports = AbstractPluginLoader; + + +},{"../functions/function-registry":26,"../less-error":36}],19:[function(require,module,exports){ var logger = require("../logger"); var environment = function(externalEnvironment, fileManagers) { this.fileManagers = fileManagers || []; @@ -1373,7 +1638,24 @@ environment.prototype.clearFileManagers = function () { module.exports = environment; -},{"../logger":33}],17:[function(require,module,exports){ +},{"../logger":37}],20:[function(require,module,exports){ + +var functionRegistry = require("./function-registry"), + Anonymous = require("../tree/anonymous"), + Keyword = require("../tree/keyword"); + +functionRegistry.addMultiple({ + boolean: function(condition) { + return condition ? Keyword.True : Keyword.False; + }, + + 'if': function(condition, trueValue, falseValue) { + return condition ? trueValue + : (falseValue || new Anonymous); + } +}); + +},{"../tree/anonymous":48,"../tree/keyword":68,"./function-registry":26}],21:[function(require,module,exports){ var Color = require("../tree/color"), functionRegistry = require("./function-registry"); @@ -1449,7 +1731,7 @@ for (var f in colorBlendModeFunctions) { functionRegistry.addMultiple(colorBlend); -},{"../tree/color":50,"./function-registry":22}],18:[function(require,module,exports){ +},{"../tree/color":53,"./function-registry":26}],22:[function(require,module,exports){ var Dimension = require("../tree/dimension"), Color = require("../tree/color"), Quoted = require("../tree/quoted"), @@ -1730,7 +2012,7 @@ colorFunctions = { if (typeof dark === 'undefined') { dark = colorFunctions.rgba(0, 0, 0, 1.0); } - //Figure out which is actually light and dark! + // Figure out which is actually light and dark: if (dark.luma() > light.luma()) { var t = light; light = dark; @@ -1747,6 +2029,44 @@ colorFunctions = { return dark; } }, + // Changes made in 2.7.0 - Reverted in 3.0.0 + // contrast: function (color, color1, color2, threshold) { + // // Return which of `color1` and `color2` has the greatest contrast with `color` + // // according to the standard WCAG contrast ratio calculation. + // // http://www.w3.org/TR/WCAG20/#contrast-ratiodef + // // The threshold param is no longer used, in line with SASS. + // // filter: contrast(3.2); + // // should be kept as is, so check for color + // if (!color.rgb) { + // return null; + // } + // if (typeof color1 === 'undefined') { + // color1 = colorFunctions.rgba(0, 0, 0, 1.0); + // } + // if (typeof color2 === 'undefined') { + // color2 = colorFunctions.rgba(255, 255, 255, 1.0); + // } + // var contrast1, contrast2; + // var luma = color.luma(); + // var luma1 = color1.luma(); + // var luma2 = color2.luma(); + // // Calculate contrast ratios for each color + // if (luma > luma1) { + // contrast1 = (luma + 0.05) / (luma1 + 0.05); + // } else { + // contrast1 = (luma1 + 0.05) / (luma + 0.05); + // } + // if (luma > luma2) { + // contrast2 = (luma + 0.05) / (luma2 + 0.05); + // } else { + // contrast2 = (luma2 + 0.05) / (luma + 0.05); + // } + // if (contrast1 > contrast2) { + // return color1; + // } else { + // return color2; + // } + // }, argb: function (color) { return new Anonymous(color.toARGB()); }, @@ -1773,10 +2093,11 @@ colorFunctions = { }; functionRegistry.addMultiple(colorFunctions); -},{"../tree/anonymous":46,"../tree/color":50,"../tree/dimension":56,"../tree/quoted":73,"./function-registry":22}],19:[function(require,module,exports){ +},{"../tree/anonymous":48,"../tree/color":53,"../tree/dimension":60,"../tree/quoted":77,"./function-registry":26}],23:[function(require,module,exports){ module.exports = function(environment) { var Quoted = require("../tree/quoted"), URL = require("../tree/url"), + utils = require('../utils'), functionRegistry = require("./function-registry"), fallback = function(functionThis, node) { return new URL(node, functionThis.index, functionThis.currentFileInfo).eval(functionThis.context); @@ -1802,8 +2123,10 @@ module.exports = function(environment) { fragment = filePath.slice(fragmentStart); filePath = filePath.slice(0, fragmentStart); } + var context = utils.clone(this.context); + context.rawBuffer = true; - var fileManager = environment.getFileManager(filePath, currentDirectory, this.context, environment, true); + var fileManager = environment.getFileManager(filePath, currentDirectory, context, environment, true); if (!fileManager) { return fallback(this, filePathNode); @@ -1829,7 +2152,7 @@ module.exports = function(environment) { useBase64 = /;base64$/.test(mimetype); } - var fileSync = fileManager.loadFileSync(filePath, currentDirectory, this.context, environment); + var fileSync = fileManager.loadFileSync(filePath, currentDirectory, context, environment); if (!fileSync.contents) { logger.warn("Skipped data-uri embedding of " + filePath + " because file not found"); return fallback(this, filePathNode || mimetypeNode); @@ -1860,7 +2183,7 @@ module.exports = function(environment) { }); }; -},{"../logger":33,"../tree/quoted":73,"../tree/url":80,"./function-registry":22}],20:[function(require,module,exports){ +},{"../logger":37,"../tree/quoted":77,"../tree/url":82,"../utils":86,"./function-registry":26}],24:[function(require,module,exports){ var Keyword = require("../tree/keyword"), functionRegistry = require("./function-registry"); @@ -1889,7 +2212,7 @@ functionRegistry.add("default", defaultFunc.eval.bind(defaultFunc)); module.exports = defaultFunc; -},{"../tree/keyword":65,"./function-registry":22}],21:[function(require,module,exports){ +},{"../tree/keyword":68,"./function-registry":26}],25:[function(require,module,exports){ var Expression = require("../tree/expression"); var functionCaller = function(name, context, index, currentFileInfo) { @@ -1903,8 +2226,8 @@ var functionCaller = function(name, context, index, currentFileInfo) { functionCaller.prototype.isValid = function() { return Boolean(this.func); }; -functionCaller.prototype.call = function(args) { +functionCaller.prototype.call = function(args) { // This code is terrible and should be replaced as per this issue... // https://github.com/less/less.js/issues/2477 if (Array.isArray(args)) { @@ -1937,7 +2260,7 @@ functionCaller.prototype.call = function(args) { module.exports = functionCaller; -},{"../tree/expression":59}],22:[function(require,module,exports){ +},{"../tree/expression":62}],26:[function(require,module,exports){ function makeRegistry( base ) { return { _data: {}, @@ -1947,7 +2270,7 @@ function makeRegistry( base ) { name = name.toLowerCase(); if (this._data.hasOwnProperty(name)) { - //TODO warn + // TODO warn } this._data[name] = func; }, @@ -1960,21 +2283,28 @@ function makeRegistry( base ) { get: function(name) { return this._data[name] || ( base && base.get( name )); }, - inherit : function() { + getLocalFunctions: function() { + return this._data; + }, + inherit: function() { return makeRegistry( this ); + }, + create: function(base) { + return makeRegistry(base); } }; } module.exports = makeRegistry( null ); -},{}],23:[function(require,module,exports){ +},{}],27:[function(require,module,exports){ module.exports = function(environment) { var functions = { functionRegistry: require("./function-registry"), functionCaller: require("./function-caller") }; - //register functions + // register functions + require("./boolean"); require("./default"); require("./color"); require("./color-blending"); @@ -1988,7 +2318,7 @@ module.exports = function(environment) { return functions; }; -},{"./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){ +},{"./boolean":20,"./color":22,"./color-blending":21,"./data-uri":23,"./default":24,"./function-caller":25,"./function-registry":26,"./math":29,"./number":30,"./string":31,"./svg":32,"./types":33}],28:[function(require,module,exports){ var Dimension = require("../tree/dimension"); var MathHelper = function() { @@ -2005,7 +2335,7 @@ MathHelper._math = function (fn, unit, n) { return new Dimension(fn(parseFloat(n.value)), unit); }; module.exports = MathHelper; -},{"../tree/dimension":56}],25:[function(require,module,exports){ +},{"../tree/dimension":60}],29:[function(require,module,exports){ var functionRegistry = require("./function-registry"), mathHelper = require("./math-helper.js"); @@ -2036,7 +2366,7 @@ mathFunctions.round = function (n, f) { functionRegistry.addMultiple(mathFunctions); -},{"./function-registry":22,"./math-helper.js":24}],26:[function(require,module,exports){ +},{"./function-registry":26,"./math-helper.js":28}],30:[function(require,module,exports){ var Dimension = require("../tree/dimension"), Anonymous = require("../tree/anonymous"), functionRegistry = require("./function-registry"), @@ -2044,7 +2374,7 @@ var Dimension = require("../tree/dimension"), var minMax = function (isMin, args) { args = Array.prototype.slice.call(args); - switch(args.length) { + switch (args.length) { case 0: throw { type: "Argument", message: "one or more arguments required" }; } var i, j, current, currentUnified, referenceUnified, unit, unitStatic, unitClone, @@ -2066,7 +2396,7 @@ var minMax = function (isMin, args) { j = values[""] !== undefined && unit !== "" && unit === unitStatic ? values[""] : values[unit]; if (j === undefined) { if (unitStatic !== undefined && unit !== unitStatic) { - throw{ type: "Argument", message: "incompatible types" }; + throw { type: "Argument", message: "incompatible types" }; } values[unit] = order.length; order.push(current); @@ -2119,7 +2449,7 @@ functionRegistry.addMultiple({ } }); -},{"../tree/anonymous":46,"../tree/dimension":56,"./function-registry":22,"./math-helper.js":24}],27:[function(require,module,exports){ +},{"../tree/anonymous":48,"../tree/dimension":60,"./function-registry":26,"./math-helper.js":28}],31:[function(require,module,exports){ var Quoted = require("../tree/quoted"), Anonymous = require("../tree/anonymous"), JavaScript = require("../tree/javascript"), @@ -2141,12 +2471,12 @@ functionRegistry.addMultiple({ result = result.replace(new RegExp(pattern.value, flags ? flags.value : ''), replacement); return new Quoted(string.quote || '', result, string.escaped); }, - '%': function (string /* arg, arg, ...*/) { + '%': function (string /* arg, arg, ... */) { var args = Array.prototype.slice.call(arguments, 1), result = string.value; for (var i = 0; i < args.length; i++) { - /*jshint loopfunc:true */ + /* jshint loopfunc:true */ result = result.replace(/%[sda]/i, function(token) { var value = ((args[i].type === "Quoted") && token.match(/s/i)) ? args[i].value : args[i].toCSS(); @@ -2158,7 +2488,7 @@ functionRegistry.addMultiple({ } }); -},{"../tree/anonymous":46,"../tree/javascript":63,"../tree/quoted":73,"./function-registry":22}],28:[function(require,module,exports){ +},{"../tree/anonymous":48,"../tree/javascript":66,"../tree/quoted":77,"./function-registry":26}],32:[function(require,module,exports){ module.exports = function(environment) { var Dimension = require("../tree/dimension"), Color = require("../tree/color"), @@ -2176,12 +2506,12 @@ module.exports = function(environment) { renderEnv = {compress: false}, returner, directionValue = direction.toCSS(renderEnv), - i, color, position, positionValue, alpha; + i, color, position, positionValue, alpha; function throwArgumentDescriptor() { throw { type: "Argument", - message: "svg-gradient expects direction, start_color [start_position], [color position,]...," + - " end_color [end_position] or direction, color list" }; + message: "svg-gradient expects direction, start_color [start_position], [color position,]...," + + " end_color [end_position] or direction, color list" }; } if (arguments.length == 2) { @@ -2222,7 +2552,7 @@ module.exports = function(environment) { '' + '<' + gradientType + 'Gradient id="gradient" gradientUnits="userSpaceOnUse" ' + gradientDirectionSvg + '>'; - for (i = 0; i < stops.length; i+= 1) { + for (i = 0; i < stops.length; i += 1) { if (stops[i] instanceof Expression) { color = stops[i].value[0]; position = stops[i].value[1]; @@ -2248,7 +2578,7 @@ module.exports = function(environment) { }); }; -},{"../tree/color":50,"../tree/dimension":56,"../tree/expression":59,"../tree/quoted":73,"../tree/url":80,"./function-registry":22}],29:[function(require,module,exports){ +},{"../tree/color":53,"../tree/dimension":60,"../tree/expression":62,"../tree/quoted":77,"../tree/url":82,"./function-registry":26}],33:[function(require,module,exports){ var Keyword = require("../tree/keyword"), DetachedRuleset = require("../tree/detached-ruleset"), Dimension = require("../tree/dimension"), @@ -2339,10 +2669,12 @@ functionRegistry.addMultiple({ } }); -},{"../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){ +},{"../tree/anonymous":48,"../tree/color":53,"../tree/detached-ruleset":59,"../tree/dimension":60,"../tree/keyword":68,"../tree/operation":74,"../tree/quoted":77,"../tree/url":82,"./function-registry":26}],34:[function(require,module,exports){ var contexts = require("./contexts"), Parser = require('./parser/parser'), - FunctionImporter = require('./plugins/function-importer'); + LessError = require('./less-error'), + utils = require('./utils'), + PromiseConstructor = typeof Promise === 'undefined' ? require('promise') : Promise; module.exports = function(environment) { @@ -2355,7 +2687,8 @@ module.exports = function(environment) { // 'entryPath' - absolute path to the entry file // 'reference' - whether the file should not be output and only output parts that are referenced - var ImportManager = function(context, rootFileInfo) { + var ImportManager = function(less, context, rootFileInfo) { + this.less = less; this.rootFilename = rootFileInfo.filename; this.paths = context.paths || []; // Search paths, when importing this.contents = {}; // map - filename to contents of all the files @@ -2367,16 +2700,19 @@ module.exports = function(environment) { this.queue = []; // Files which haven't been imported yet this.files = {}; // Holds the imported parse trees. }; + /** * Add an import to be imported * @param path - the raw path - * @param tryAppendLessExtension - whether to try appending the less extension (if the path has no extension) + * @param tryAppendExtension - whether to try appending a file extension (.less or .js if the path has no extension) * @param currentFileInfo - the current file info (used for instance to work out relative paths) * @param importOptions - import options * @param callback - callback for when it is imported */ - ImportManager.prototype.push = function (path, tryAppendLessExtension, currentFileInfo, importOptions, callback) { - var importManager = this; + ImportManager.prototype.push = function (path, tryAppendExtension, currentFileInfo, importOptions, callback) { + var importManager = this, + pluginLoader = this.context.pluginManager.Loader; + this.queue.push(path); var fileParsedFunc = function (e, root, fullPath) { @@ -2387,7 +2723,9 @@ module.exports = function(environment) { callback(null, {rules:[]}, false, null); } else { - importManager.files[fullPath] = root; + if (!importManager.files[fullPath]) { + importManager.files[fullPath] = { root: root, options: importOptions }; + } if (e && !importManager.error) { importManager.error = e; } callback(e, root, importedEqualsRoot, fullPath); } @@ -2407,12 +2745,9 @@ module.exports = function(environment) { return; } - if (tryAppendLessExtension) { - path = fileManager.tryAppendExtension(path, importOptions.plugin ? ".js" : ".less"); - } - var loadFileCallback = function(loadedFile) { - var resolvedFilename = loadedFile.filename, + var plugin, + resolvedFilename = loadedFile.filename, contents = loadedFile.contents.replace(/^\uFEFF/, ''); // Pass on an updated rootpath if path of imported file is relative and file @@ -2444,44 +2779,71 @@ module.exports = function(environment) { newFileInfo.reference = true; } - if (importOptions.plugin) { - new FunctionImporter(newEnv, newFileInfo).eval(contents, function (e, root) { - fileParsedFunc(e, root, resolvedFilename); - }); + if (importOptions.isPlugin) { + plugin = pluginLoader.evalPlugin(contents, newEnv, importManager, importOptions.pluginArgs, newFileInfo); + if (plugin instanceof LessError) { + fileParsedFunc(plugin, null, resolvedFilename); + } + else { + fileParsedFunc(null, plugin, resolvedFilename); + } } else if (importOptions.inline) { fileParsedFunc(null, contents, resolvedFilename); } else { - new Parser(newEnv, importManager, newFileInfo).parse(contents, function (e, root) { - fileParsedFunc(e, root, resolvedFilename); - }); + + // import (multiple) parse trees apparently get altered and can't be cached. + // TODO: investigate why this is + if (importManager.files[resolvedFilename] + && !importManager.files[resolvedFilename].options.multiple + && !importOptions.multiple) { + + fileParsedFunc(null, importManager.files[resolvedFilename].root, resolvedFilename); + } + else { + new Parser(newEnv, importManager, newFileInfo).parse(contents, function (e, root) { + fileParsedFunc(e, root, resolvedFilename); + }); + } } }; + var promise, context = utils.clone(this.context); - var promise = fileManager.loadFile(path, currentFileInfo.currentDirectory, this.context, environment, - function(err, loadedFile) { - if (err) { - fileParsedFunc(err); - } else { - loadFileCallback(loadedFile); - } - }); + if (tryAppendExtension) { + context.ext = importOptions.isPlugin ? ".js" : ".less"; + } + + if (importOptions.isPlugin) { + promise = pluginLoader.loadPlugin(path, currentFileInfo.currentDirectory, context, environment, fileManager); + } + else { + promise = fileManager.loadFile(path, currentFileInfo.currentDirectory, context, environment, + function(err, loadedFile) { + if (err) { + fileParsedFunc(err); + } else { + loadFileCallback(loadedFile); + } + }); + } if (promise) { promise.then(loadFileCallback, fileParsedFunc); } + }; return ImportManager; }; -},{"./contexts":11,"./parser/parser":38,"./plugins/function-importer":40}],31:[function(require,module,exports){ +},{"./contexts":12,"./less-error":36,"./parser/parser":42,"./utils":86,"promise":undefined}],35:[function(require,module,exports){ module.exports = function(environment, fileManagers) { var SourceMapOutput, SourceMapBuilder, ParseTree, ImportManager, Environment; - var less = { - version: [2, 7, 3], + var initial = { + version: [3, 0, 0], data: require('./data'), tree: require('./tree'), Environment: (Environment = require("./environment/environment")), AbstractFileManager: require("./environment/abstract-file-manager"), + AbstractPluginLoader: require("./environment/abstract-plugin-loader"), environment: (environment = new Environment(environment, fileManagers)), visitors: require('./visitors'), Parser: require('./parser/parser'), @@ -2500,18 +2862,66 @@ module.exports = function(environment, fileManagers) { logger: require('./logger') }; - return less; -}; + // Create a public API -},{"./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){ -var utils = require("./utils"); + var ctor = function(t) { + return function() { + var obj = Object.create(t.prototype); + t.apply(obj, Array.prototype.slice.call(arguments, 0)); + return obj; + }; + }; + var t, api = Object.create(initial); + for (var n in initial.tree) { + /* eslint guard-for-in: 0 */ + t = initial.tree[n]; + if (typeof t === "function") { + api[n.toLowerCase()] = ctor(t); + } + else { + api[n] = Object.create(null); + for (var o in t) { + /* eslint guard-for-in: 0 */ + api[n][o.toLowerCase()] = ctor(t[o]); + } + } + } -var LessError = module.exports = function LessError(e, importManager, currentFilename) { + return api; +}; +},{"./contexts":12,"./data":14,"./environment/abstract-file-manager":17,"./environment/abstract-plugin-loader":18,"./environment/environment":19,"./functions":27,"./import-manager":34,"./less-error":36,"./logger":37,"./parse":39,"./parse-tree":38,"./parser/parser":42,"./plugin-manager":43,"./render":44,"./source-map-builder":45,"./source-map-output":46,"./transform-tree":47,"./tree":65,"./utils":86,"./visitors":90}],36:[function(require,module,exports){ +var utils = require('./utils'); +/** + * This is a centralized class of any error that could be thrown internally (mostly by the parser). + * Besides standard .message it keeps some additional data like a path to the file where the error + * occurred along with line and column numbers. + * + * @class + * @extends Error + * @type {module.LessError} + * + * @prop {string} type + * @prop {string} filename + * @prop {number} index + * @prop {number} line + * @prop {number} column + * @prop {number} callLine + * @prop {number} callExtract + * @prop {string[]} extract + * + * @param {Object} e - An error object to wrap around or just a descriptive object + * @param {Object} importManager - An instance of ImportManager (see import-manager.js) + * @param {string} [currentFilename] + */ +var LessError = module.exports = function LessError(e, importManager, currentFilename) { Error.call(this); var filename = e.filename || currentFilename; + this.message = e.message; + this.stack = e.stack; + if (importManager && filename) { var input = importManager.contents[filename], loc = utils.getLocation(e.index, input), @@ -2524,17 +2934,32 @@ var LessError = module.exports = function LessError(e, importManager, currentFil this.filename = filename; this.index = e.index; this.line = typeof line === 'number' ? line + 1 : null; + this.column = col; + + if (!this.line && this.stack) { + var found = this.stack.match(/(|Function):(\d+):(\d+)/); + + if (found) { + if (found[2]) { + this.line = parseInt(found[2]) - 2; + } + if (found[3]) { + this.column = parseInt(found[3]); + } + } + } + this.callLine = callLine + 1; this.callExtract = lines[callLine]; - this.column = col; + this.extract = [ - lines[line - 1], - lines[line], - lines[line + 1] + lines[this.line - 2], + lines[this.line - 1], + lines[this.line] ]; + } - this.message = e.message; - this.stack = e.stack; + }; if (typeof Object.create === 'undefined') { @@ -2547,26 +2972,87 @@ if (typeof Object.create === 'undefined') { LessError.prototype.constructor = LessError; -},{"./utils":83}],33:[function(require,module,exports){ -module.exports = { - error: function(msg) { - this._fireEvent("error", msg); - }, - warn: function(msg) { - this._fireEvent("warn", msg); - }, - info: function(msg) { - this._fireEvent("info", msg); - }, - debug: function(msg) { - this._fireEvent("debug", msg); - }, - addListener: function(listener) { - this._listeners.push(listener); - }, - removeListener: function(listener) { - for (var i = 0; i < this._listeners.length; i++) { - if (this._listeners[i] === listener) { +/** + * An overridden version of the default Object.prototype.toString + * which uses additional information to create a helpful message. + * + * @param {Object} options + * @returns {string} + */ +LessError.prototype.toString = function(options) { + options = options || {}; + + var message = ''; + var extract = this.extract || []; + var error = []; + var stylize = function (str) { return str; }; + if (options.stylize) { + var type = typeof options.stylize; + if (type !== 'function') { + throw Error('options.stylize should be a function, got a ' + type + '!'); + } + stylize = options.stylize; + } + + if (this.line !== null) { + if (typeof extract[0] === 'string') { + error.push(stylize((this.line - 1) + ' ' + extract[0], 'grey')); + } + + if (typeof extract[1] === 'string') { + var errorTxt = this.line + ' '; + if (extract[1]) { + errorTxt += extract[1].slice(0, this.column) + + stylize(stylize(stylize(extract[1].substr(this.column, 1), 'bold') + + extract[1].slice(this.column + 1), 'red'), 'inverse'); + } + error.push(errorTxt); + } + + if (typeof extract[2] === 'string') { + error.push(stylize((this.line + 1) + ' ' + extract[2], 'grey')); + } + error = error.join('\n') + stylize('', 'reset') + '\n'; + } + + message += stylize(this.type + 'Error: ' + this.message, 'red'); + if (this.filename) { + message += stylize(' in ', 'red') + this.filename; + } + if (this.line) { + message += stylize(' on line ' + this.line + ', column ' + (this.column + 1) + ':', 'grey'); + } + + message += '\n' + error; + + if (this.callLine) { + message += stylize('from ', 'red') + (this.filename || '') + '/n'; + message += stylize(this.callLine, 'grey') + ' ' + this.callExtract + '/n'; + } + + return message; +}; + +},{"./utils":86}],37:[function(require,module,exports){ +module.exports = { + error: function(msg) { + this._fireEvent("error", msg); + }, + warn: function(msg) { + this._fireEvent("warn", msg); + }, + info: function(msg) { + this._fireEvent("info", msg); + }, + debug: function(msg) { + this._fireEvent("debug", msg); + }, + addListener: function(listener) { + this._listeners.push(listener); + }, + removeListener: function(listener) { + for (var i = 0; i < this._listeners.length; i++) { + if (this._listeners[i] === listener) { this._listeners.splice(i, 1); return; } @@ -2583,7 +3069,7 @@ module.exports = { _listeners: [] }; -},{}],34:[function(require,module,exports){ +},{}],38:[function(require,module,exports){ var LessError = require('./less-error'), transformTree = require("./transform-tree"), logger = require("./logger"); @@ -2645,19 +3131,23 @@ module.exports = function(SourceMapBuilder) { return ParseTree; }; -},{"./less-error":32,"./logger":33,"./transform-tree":44}],35:[function(require,module,exports){ +},{"./less-error":36,"./logger":37,"./transform-tree":47}],39:[function(require,module,exports){ var PromiseConstructor, contexts = require("./contexts"), Parser = require('./parser/parser'), - PluginManager = require('./plugin-manager'); + PluginManager = require('./plugin-manager'), + LessError = require('./less-error'), + utils = require('./utils'); module.exports = function(environment, ParseTree, ImportManager) { var parse = function (input, options, callback) { - options = options || {}; if (typeof options === 'function') { callback = options; - options = {}; + options = utils.defaults(this.options, {}); + } + else { + options = utils.defaults(this.options, options || {}); } if (!callback) { @@ -2677,9 +3167,8 @@ module.exports = function(environment, ParseTree, ImportManager) { } else { var context, rootFileInfo, - pluginManager = new PluginManager(this); + pluginManager = new PluginManager(this, true); - pluginManager.addPlugins(options.plugins); options.pluginManager = pluginManager; context = new contexts.Parse(options); @@ -2703,19 +3192,39 @@ module.exports = function(environment, ParseTree, ImportManager) { } } - var imports = new ImportManager(context, rootFileInfo); + var imports = new ImportManager(this, context, rootFileInfo); + this.importManager = imports; + // TODO: allow the plugins to be just a list of paths or names + // Do an async plugin queue like lessc + + if (options.plugins) { + options.plugins.forEach(function(plugin) { + var evalResult, contents; + if (plugin.fileContent) { + contents = plugin.fileContent.replace(/^\uFEFF/, ''); + evalResult = pluginManager.Loader.evalPlugin(contents, context, imports, plugin.options, plugin.filename); + if (evalResult instanceof LessError) { + return callback(evalResult); + } + } + else { + pluginManager.addPlugin(plugin); + } + }); + } + new Parser(context, imports, rootFileInfo) .parse(input, function (e, root) { - if (e) { return callback(e); } - callback(null, root, imports, options); - }, options); + if (e) { return callback(e); } + callback(null, root, imports, options); + }, options); } }; return parse; }; -},{"./contexts":11,"./parser/parser":38,"./plugin-manager":39,"promise":undefined}],36:[function(require,module,exports){ +},{"./contexts":12,"./less-error":36,"./parser/parser":42,"./plugin-manager":43,"./utils":86,"promise":undefined}],40:[function(require,module,exports){ // Split the input into chunks. module.exports = function (input, fail) { var len = input.length, level = 0, parenLevel = 0, @@ -2829,15 +3338,15 @@ module.exports = function (input, fail) { return chunks; }; -},{}],37:[function(require,module,exports){ +},{}],41:[function(require,module,exports){ var chunker = require('./chunker'); module.exports = function() { - var input, // LeSS input string + var input, // Less input string j, // current chunk saveStack = [], // holds state for backtracking furthest, // furthest index the parser has gone to - furthestPossibleErrorMessage,// if this is furthest we got to, this is the probably cause + furthestPossibleErrorMessage, // if this is furthest we got to, this is the probably cause chunks, // chunkified input current, // current chunk currentPos, // index of current chunk, in `input` @@ -2988,7 +3497,7 @@ module.exports = function() { for (var i = 1; i + currentPosition < length; i++) { var nextChar = input.charAt(i + currentPosition); - switch(nextChar) { + switch (nextChar) { case "\\": i++; continue; @@ -3041,7 +3550,7 @@ module.exports = function() { parserInput.peekNotNumeric = function() { var c = input.charCodeAt(parserInput.i); - //Is the first char of the dimension 0-9, '.', '+' or '-' + // Is the first char of the dimension 0-9, '.', '+' or '-' return (c > CHARCODE_9 || c < CHARCODE_PLUS) || c === CHARCODE_FORWARD_SLASH || c === CHARCODE_COMMA; }; @@ -3090,12 +3599,13 @@ module.exports = function() { return parserInput; }; -},{"./chunker":36}],38:[function(require,module,exports){ +},{"./chunker":40}],42:[function(require,module,exports){ var LessError = require('../less-error'), tree = require("../tree"), visitors = require("../visitors"), getParserInput = require("./parser-input"), - utils = require("../utils"); + utils = require("../utils"), + functionRegistry = require('../functions/function-registry'); // // less.js - parser @@ -3128,8 +3638,8 @@ var LessError = require('../less-error'), // Token matching is done with the `$` function, which either takes // a terminal string or regexp, or a non-terminal function to call. // It also takes care of moving all the indices forwards. -//` // + var Parser = function Parser(context, imports, fileInfo) { var parsers, parserInput = getParserInput(); @@ -3173,11 +3683,61 @@ var Parser = function Parser(context, imports, fileInfo) { }; } + /** + * Used after initial parsing to create nodes on the fly + * + * @param {String} str - string to parse + * @param {Array} parseList - array of parsers to run input through e.g. ["value", "important"] + * @param {Number} currentIndex - start number to begin indexing + * @param {Object} fileInfo - fileInfo to attach to created nodes + */ + function parseNode(str, parseList, currentIndex, fileInfo, callback) { + var result, returnNodes = []; + var parser = parserInput; + + try { + parser.start(str, false, function fail(msg, index) { + callback({ + message: msg, + index: index + currentIndex + }); + }); + for (var x = 0, p, i; (p = parseList[x]); x++) { + i = parser.i; + result = parsers[p](); + if (result) { + result._index = i + currentIndex; + result._fileInfo = fileInfo; + returnNodes.push(result); + } + else { + returnNodes.push(null); + } + } + + var endInfo = parser.end(); + if (endInfo.isFinished) { + callback(null, returnNodes); + } + else { + callback(true, null); + } + } catch (e) { + throw new LessError({ + index: e.index + currentIndex, + message: e.message + }, imports, fileInfo.filename); + } + } + // // The Parser // return { - + parserInput: parserInput, + imports: imports, + fileInfo: fileInfo, + parseNode: parseNode, // // Parse an input string into an abstract syntax tree, // @param str A string containing 'less' markup @@ -3223,9 +3783,13 @@ var Parser = function Parser(context, imports, fileInfo) { }, imports); }); - root = new(tree.Ruleset)(null, this.parsers.primary()); + tree.Node.prototype.parse = this; + root = new tree.Ruleset(null, this.parsers.primary()); + tree.Node.prototype.rootNode = root; root.root = true; root.firstRoot = true; + root.functionRegistry = functionRegistry.inherit(); + } catch (e) { return callback(new LessError(e, imports, fileInfo.filename)); } @@ -3290,7 +3854,7 @@ var Parser = function Parser(context, imports, fileInfo) { // // The basic structure of the syntax tree generated is as follows: // - // Ruleset -> Rule -> Value -> Expression -> Entity + // Ruleset -> Declaration -> Value -> Expression -> Entity // // Here's some Less code: // @@ -3304,9 +3868,9 @@ var Parser = function Parser(context, imports, fileInfo) { // And here's what the parse tree might look like: // // Ruleset (Selector '.class', [ - // Rule ("color", Value ([Expression [Color #fff]])) - // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) - // Rule ("width", Value ([Expression [Operation " + " [Variable "@w"][Dimension 4px]]])) + // Declaration ("color", Value ([Expression [Color #fff]])) + // Declaration ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) + // Declaration ("width", Value ([Expression [Operation " + " [Variable "@w"][Dimension 4px]]])) // Ruleset (Selector [Element '>', '.child'], [...]) // ]) // @@ -3323,7 +3887,7 @@ var Parser = function Parser(context, imports, fileInfo) { // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, // as represented by this simplified grammar: // - // primary → (ruleset | rule)+ + // primary → (ruleset | declaration)+ // ruleset → selector+ block // block → '{' primary '}' // @@ -3353,8 +3917,8 @@ var Parser = function Parser(context, imports, fileInfo) { continue; } - node = mixin.definition() || this.rule() || this.ruleset() || - mixin.call() || this.rulesetCall() || this.entities.call() || this.directive(); + node = mixin.definition() || this.declaration() || this.ruleset() || + mixin.call() || this.variableCall() || this.entities.call() || this.atrule(); if (node) { root.push(node); } else { @@ -3412,7 +3976,7 @@ var Parser = function Parser(context, imports, fileInfo) { // black border-collapse // keyword: function () { - var k = parserInput.$char("%") || parserInput.$re(/^[_A-Za-z-][_A-Za-z0-9-]*/); + var k = parserInput.$char("%") || parserInput.$re(/^\[?[_A-Za-z-][_A-Za-z0-9-]*\]?/); if (k) { return tree.Color.fromKeyword(k) || new(tree.Keyword)(k); } @@ -3423,13 +3987,10 @@ var Parser = function Parser(context, imports, fileInfo) { // // rgb(255, 0, 255) // - // We also try to catch IE's `alpha()`, but let the `alpha` parser - // deal with the details. - // // The arguments are parsed with the `entities.arguments` parser. // call: function () { - var name, nameLC, args, alpha, index = parserInput.i; + var name, args, func, index = parserInput.i; // http://jsperf.com/case-insensitive-regex-vs-strtolower-then-regex/18 if (parserInput.peek(/^url\(/i)) { @@ -3439,70 +4000,98 @@ var Parser = function Parser(context, imports, fileInfo) { parserInput.save(); name = parserInput.$re(/^([\w-]+|%|progid:[\w\.]+)\(/); - if (!name) { parserInput.forget(); return; } + if (!name) { + parserInput.forget(); + return; + } name = name[1]; - nameLC = name.toLowerCase(); - - if (nameLC === 'alpha') { - alpha = parsers.alpha(); - if (alpha) { + func = this.customFuncCall(name); + if (func) { + args = func.parse(); + if (args && func.stop) { parserInput.forget(); - return alpha; + return args; } } - args = this.arguments(); + args = this.arguments(args); - if (! parserInput.$char(')')) { + if (!parserInput.$char(')')) { parserInput.restore("Could not parse call arguments or missing ')'"); return; } parserInput.forget(); + return new(tree.Call)(name, args, index, fileInfo); }, - arguments: function () { - var argsSemiColon = [], argsComma = [], - expressions = [], - isSemiColonSeparated, value, arg; - - parserInput.save(); + + // + // Parsing rules for functions with non-standard args, e.g.: + // + // boolean(not(2 > 1)) + // + // This is a quick prototype, to be modified/improved when + // more custom-parsed funcs come (e.g. `selector(...)`) + // - while (true) { + customFuncCall: function (name) { + /* Ideally the table is to be moved out of here for faster perf., + but it's quite tricky since it relies on all these `parsers` + and `expect` available only here */ + return { + alpha: f(parsers.ieAlpha, true), + boolean: f(condition), + 'if': f(condition) + }[name.toLowerCase()]; + + function f(parse, stop) { + return { + parse: parse, // parsing function + stop: stop // when true - stop after parse() and return its result, + // otherwise continue for plain args + }; + } + + function condition() { + return [expect(parsers.condition, 'expected condition')]; + } + }, - arg = parsers.detachedRuleset() || this.assignment() || parsers.expression(); + arguments: function (prevArgs) { + var argsComma = prevArgs || [], + argsSemiColon = [], + isSemiColonSeparated, value; - if (!arg) { - break; - } + parserInput.save(); - value = arg; + while (true) { + if (prevArgs) { + prevArgs = false; + } else { + value = parsers.detachedRuleset() || this.assignment() || parsers.expression(); + if (!value) { + break; + } - if (arg.value && arg.value.length == 1) { - value = arg.value[0]; - } + if (value.value && value.value.length == 1) { + value = value.value[0]; + } - if (value) { - expressions.push(value); + argsComma.push(value); } - argsComma.push(value); - if (parserInput.$char(',')) { continue; } if (parserInput.$char(';') || isSemiColonSeparated) { - isSemiColonSeparated = true; - - if (expressions.length > 1) { - value = new(tree.Value)(expressions); - } + value = (argsComma.length < 1) ? argsComma[0] + : new tree.Value(argsComma); argsSemiColon.push(value); - - expressions = []; + argsComma = []; } } @@ -3560,15 +4149,17 @@ var Parser = function Parser(context, imports, fileInfo) { return; } - value = this.quoted() || this.variable() || + value = this.quoted() || this.variable() || this.property() || parserInput.$re(/^(?:(?:\\[\(\)'"])|[^\(\)'"])+/) || ""; parserInput.autoCommentAbsorb = true; expectChar(')'); - return new(tree.URL)((value.value != null || value instanceof tree.Variable) ? - value : new(tree.Anonymous)(value), index, fileInfo); + return new(tree.URL)((value.value != null || + value instanceof tree.Variable || + value instanceof tree.Property) ? + value : new(tree.Anonymous)(value, index), index, fileInfo); }, // @@ -3595,7 +4186,27 @@ var Parser = function Parser(context, imports, fileInfo) { return new(tree.Variable)("@" + curly[1], index, fileInfo); } }, + // + // A Property accessor, such as `$color`, in + // + // background-color: $color + // + property: function () { + var name, index = parserInput.i; + + if (parserInput.currentChar() === '$' && (name = parserInput.$re(/^\$[\w-]+/))) { + return new(tree.Property)(name, index, fileInfo); + } + }, + + // A property entity useing the protective {} e.g. ${prop} + propertyCurly: function () { + var curly, index = parserInput.i; + if (parserInput.currentChar() === '$' && (curly = parserInput.$re(/^\$\{([\w-]+)\}/))) { + return new(tree.Property)("$" + curly[1], index, fileInfo); + } + }, // // A Hexadecimal color // @@ -3705,15 +4316,17 @@ var Parser = function Parser(context, imports, fileInfo) { }, // - // The variable part of a variable definition. Used in the `rule` parser + // Call a variable value // - // @fink(); + // @fink() // - rulesetCall: function () { + variableCall: function () { var name; - if (parserInput.currentChar() === '@' && (name = parserInput.$re(/^(@[\w-]+)\(\s*\)\s*;/))) { - return new tree.RulesetCall(name[1]); + if (parserInput.currentChar() === '@' + && (name = parserInput.$re(/^(@[\w-]+)\(\s*\)/)) + && parsers.end()) { + return new tree.VariableCall(name[1]); } }, @@ -3730,7 +4343,7 @@ var Parser = function Parser(context, imports, fileInfo) { do { option = null; elements = null; - while (! (option = parserInput.$re(/^(all)(?=\s*(\)|,))/))) { + while (!(option = parserInput.$re(/^(all)(?=\s*(\)|,))/))) { e = this.element(); if (!e) { break; @@ -3849,7 +4462,7 @@ var Parser = function Parser(context, imports, fileInfo) { .push({ variadic: true }); break; } - arg = entities.variable() || entities.literal() || entities.keyword(); + arg = entities.variable() || entities.property() || entities.literal() || entities.keyword(); } if (!arg) { @@ -3872,7 +4485,7 @@ var Parser = function Parser(context, imports, fileInfo) { val = arg; } - if (val && val instanceof tree.Variable) { + if (val && (val instanceof tree.Variable || val instanceof tree.Property)) { if (parserInput.$char(':')) { if (expressions.length > 0) { if (isSemiColonSeparated) { @@ -4018,11 +4631,11 @@ var Parser = function Parser(context, imports, fileInfo) { var entities = this.entities; return this.comment() || entities.literal() || entities.variable() || entities.url() || - entities.call() || entities.keyword() || entities.javascript(); + entities.property() || entities.call() || entities.keyword() || entities.javascript(); }, // - // A Rule terminator. Note that we use `peek()` to check for '}', + // A Declaration terminator. Note that we use `peek()` to check for '}', // because the `block` rule will be expecting it, but we still need to make sure // it's there, if ';' was omitted. // @@ -4035,17 +4648,18 @@ var Parser = function Parser(context, imports, fileInfo) { // // alpha(opacity=88) // - alpha: function () { + ieAlpha: function () { var value; // http://jsperf.com/case-insensitive-regex-vs-strtolower-then-regex/18 - if (! parserInput.$re(/^opacity=/i)) { return; } + if (!parserInput.$re(/^opacity=/i)) { return; } value = parserInput.$re(/^\d+/); if (!value) { - value = expect(this.entities.variable, "Could not parse alpha"); + value = expect(parsers.entities.variable, "Could not parse alpha"); + value = '@{' + value.name.slice(1) + '}'; } expectChar(')'); - return new(tree.Alpha)(value); + return new tree.Quoted('', 'alpha(opacity=' + value + ')'); }, // @@ -4071,10 +4685,10 @@ var Parser = function Parser(context, imports, fileInfo) { parserInput.$re(/^\([^&()@]+\)/) || parserInput.$re(/^[\.#:](?=@)/) || this.entities.variableCurly(); - if (! e) { + if (!e) { parserInput.save(); if (parserInput.$char('(')) { - if ((v = this.selector()) && parserInput.$char(')')) { + if ((v = this.selector(false)) && parserInput.$char(')')) { e = new(tree.Paren)(v); parserInput.forget(); } else { @@ -4125,14 +4739,8 @@ var Parser = function Parser(context, imports, fileInfo) { } }, // - // A CSS selector (see selector below) - // with less extensions e.g. the ability to extend and guard - // - lessSelector: function () { - return this.selector(true); - }, - // // A CSS Selector + // with less extensions e.g. the ability to extend and guard // // .class > div + h1 // li a:hover @@ -4141,7 +4749,7 @@ var Parser = function Parser(context, imports, fileInfo) { // selector: function (isLess) { var index = parserInput.i, elements, extendList, c, e, allExtends, when, condition; - + isLess = isLess !== false; while ((isLess && (extendList = this.extend())) || (isLess && (when = parserInput.$str("when"))) || (e = this.element())) { if (when) { condition = expect(this.conditions, 'expected condition'); @@ -4172,7 +4780,7 @@ var Parser = function Parser(context, imports, fileInfo) { if (allExtends) { error("Extend must be used to extend a selector, it cannot be used on its own"); } }, attribute: function () { - if (! parserInput.$char('[')) { return; } + if (!parserInput.$char('[')) { return; } var entities = this.entities, key, val, op; @@ -4231,7 +4839,7 @@ var Parser = function Parser(context, imports, fileInfo) { } while (true) { - s = this.lessSelector(); + s = this.selector(); if (!s) { break; } @@ -4244,7 +4852,7 @@ var Parser = function Parser(context, imports, fileInfo) { if (s.condition && selectors.length > 1) { error("Guards are only currently allowed on a single selector."); } - if (! parserInput.$char(',')) { break; } + if (!parserInput.$char(',')) { break; } if (s.condition) { error("Guards are only currently allowed on a single selector."); } @@ -4262,7 +4870,7 @@ var Parser = function Parser(context, imports, fileInfo) { parserInput.restore(); } }, - rule: function (tryAnonymous) { + declaration: function () { var name, value, startOfRule = parserInput.i, c = parserInput.currentChar(), important, merge, isVariable; if (c === '.' || c === '#' || c === '&' || c === ':') { return; } @@ -4284,22 +4892,16 @@ var Parser = function Parser(context, imports, fileInfo) { // where each item is a tree.Keyword or tree.Variable merge = !isVariable && name.length > 1 && name.pop().value; - // prefer to try to parse first if its a variable or we are compressing - // but always fallback on the other one - var tryValueFirst = !tryAnonymous && (context.compress || isVariable); - - if (tryValueFirst) { - value = this.value(); + // Try to store values as anonymous + // If we need the value later we'll re-parse it in ruleset.parseValue + value = this.anonymousValue(); + if (value) { + parserInput.forget(); + // anonymous values absorb the end ';' which is required for them to work + return new (tree.Declaration)(name, value, false, merge, startOfRule, fileInfo); } + if (!value) { - value = this.anonymousValue(); - if (value) { - parserInput.forget(); - // anonymous values absorb the end ';' which is required for them to work - return new (tree.Rule)(name, value, false, merge, startOfRule, fileInfo); - } - } - if (!tryValueFirst && !value) { value = this.value(); } @@ -4308,26 +4910,25 @@ var Parser = function Parser(context, imports, fileInfo) { if (value && this.end()) { parserInput.forget(); - return new (tree.Rule)(name, value, important, merge, startOfRule, fileInfo); - } else { + return new (tree.Declaration)(name, value, important, merge, startOfRule, fileInfo); + } + else { parserInput.restore(); - if (value && !tryAnonymous) { - return this.rule(true); - } } } else { - parserInput.forget(); + parserInput.restore(); } }, anonymousValue: function () { - var match = parserInput.$re(/^([^@+\/'"*`(;{}-]*);/); + var index = parserInput.i; + var match = parserInput.$re(/^([^@\$+\/'"*`(;{}-]*);/); if (match) { - return new(tree.Anonymous)(match[1]); + return new(tree.Anonymous)(match[1], index); } }, // - // An @import directive + // An @import atrule // // @import "lib"; // @@ -4365,13 +4966,13 @@ var Parser = function Parser(context, imports, fileInfo) { var o, options = {}, optionName, value; // list of options, surrounded by parens - if (! parserInput.$char('(')) { return null; } + if (!parserInput.$char('(')) { return null; } do { o = this.importOption(); if (o) { optionName = o; value = true; - switch(optionName) { + switch (optionName) { case "css": optionName = "less"; value = false; @@ -4382,7 +4983,7 @@ var Parser = function Parser(context, imports, fileInfo) { break; } options[optionName] = value; - if (! parserInput.$char(',')) { break; } + if (!parserInput.$char(',')) { break; } } } while (o); expectChar(')'); @@ -4408,7 +5009,7 @@ var Parser = function Parser(context, imports, fileInfo) { e = this.value(); if (parserInput.$char(')')) { if (p && e) { - nodes.push(new(tree.Paren)(new(tree.Rule)(p, e, null, null, parserInput.i, fileInfo, true))); + nodes.push(new(tree.Paren)(new(tree.Declaration)(p, e, null, null, parserInput.i, fileInfo, true))); } else if (e) { nodes.push(new(tree.Paren)(e)); } else { @@ -4432,12 +5033,12 @@ var Parser = function Parser(context, imports, fileInfo) { e = this.mediaFeature(); if (e) { features.push(e); - if (! parserInput.$char(',')) { break; } + if (!parserInput.$char(',')) { break; } } else { e = entities.variable(); if (e) { features.push(e); - if (! parserInput.$char(',')) { break; } + if (!parserInput.$char(',')) { break; } } } } while (e); @@ -4477,45 +5078,68 @@ var Parser = function Parser(context, imports, fileInfo) { }, // - // A @plugin directive, used to import compiler extensions dynamically. - // - // @plugin "lib"; + + // A @plugin directive, used to import plugins dynamically. // - // Depending on our environment, importing is done differently: - // In the browser, it's an XHR request, in Node, it would be a - // file-system operation. The function used for importing is - // stored in `import`, which we pass to the Import constructor. + // @plugin (args) "lib"; // plugin: function () { - var path, + var path, args, options, index = parserInput.i, dir = parserInput.$re(/^@plugin?\s+/); if (dir) { - var options = { plugin : true }; + args = this.pluginArgs(); + + if (args) { + options = { + pluginArgs: args, + isPlugin: true + }; + } + else { + options = { isPlugin: true }; + } if ((path = this.entities.quoted() || this.entities.url())) { if (!parserInput.$char(';')) { parserInput.i = index; - error("missing semi-colon on plugin"); + error("missing semi-colon on @plugin"); } - return new(tree.Import)(path, null, options, index, fileInfo); } else { parserInput.i = index; - error("malformed plugin statement"); + error("malformed @plugin statement"); } } }, + pluginArgs: function() { + // list of options, surrounded by parens + parserInput.save(); + if (!parserInput.$char('(')) { + parserInput.restore(); + return null; + } + var args = parserInput.$re(/^\s*([^\);]+)\)\s*/); + if (args[1]) { + parserInput.forget(); + return args[1].trim(); + } + else { + parserInput.restore(); + return null; + } + }, + // - // A CSS Directive + // A CSS AtRule // // @charset "utf-8"; // - directive: function () { + atrule: function () { var index = parserInput.i, name, value, rules, nonVendorSpecificName, hasIdentifier, hasExpression, hasUnknown, hasBlock = true, isRooted = true; @@ -4537,7 +5161,7 @@ var Parser = function Parser(context, imports, fileInfo) { nonVendorSpecificName = "@" + name.slice(name.indexOf('-', 2) + 1); } - switch(nonVendorSpecificName) { + switch (nonVendorSpecificName) { case "@charset": hasIdentifier = true; hasBlock = false; @@ -4586,13 +5210,13 @@ var Parser = function Parser(context, imports, fileInfo) { if (rules || (!hasBlock && value && parserInput.$char(';'))) { parserInput.forget(); - return new (tree.Directive)(name, value, rules, index, fileInfo, + return new (tree.AtRule)(name, value, rules, index, fileInfo, context.dumpLineNumbers ? getDebugInfo(index) : null, isRooted ); } - parserInput.restore("directive options not recognised"); + parserInput.restore("at-rule options not recognised"); }, // @@ -4604,18 +5228,18 @@ var Parser = function Parser(context, imports, fileInfo) { // and before the `;`. // value: function () { - var e, expressions = []; + var e, expressions = [], index = parserInput.i; do { e = this.expression(); if (e) { expressions.push(e); - if (! parserInput.$char(',')) { break; } + if (!parserInput.$char(',')) { break; } } } while (e); if (expressions.length > 0) { - return new(tree.Value)(expressions); + return new(tree.Value)(expressions, index); } }, important: function () { @@ -4854,13 +5478,14 @@ var Parser = function Parser(context, imports, fileInfo) { operand: function () { var entities = this.entities, negate; - if (parserInput.peek(/^-[@\(]/)) { + if (parserInput.peek(/^-[@\$\(]/)) { negate = parserInput.$char('-'); } var o = this.sub() || entities.dimension() || entities.color() || entities.variable() || - entities.call() || entities.colorKeyword(); + entities.property() || entities.call() || + entities.colorKeyword(); if (negate) { o.parensInOp = true; @@ -4878,7 +5503,7 @@ var Parser = function Parser(context, imports, fileInfo) { // @var * 2 // expression: function () { - var entities = [], e, delim; + var entities = [], e, delim, index = parserInput.i; do { e = this.comment(); @@ -4893,7 +5518,7 @@ var Parser = function Parser(context, imports, fileInfo) { if (!parserInput.peek(/^\/[\/*]/)) { delim = parserInput.$char('/'); if (delim) { - entities.push(new(tree.Anonymous)(delim)); + entities.push(new(tree.Anonymous)(delim, index)); } } } @@ -4931,7 +5556,7 @@ var Parser = function Parser(context, imports, fileInfo) { match(/^(\*?)/); while (true) { - if (!match(/^((?:[\w-]+)|(?:@\{[\w-]+\}))/)) { + if (!match(/^((?:[\w-]+)|(?:[@\$]\{[\w-]+\}))/)) { break; } } @@ -4947,10 +5572,11 @@ var Parser = function Parser(context, imports, fileInfo) { } for (k = 0; k < name.length; k++) { s = name[k]; - name[k] = (s.charAt(0) !== '@') ? + name[k] = (s.charAt(0) !== '@' && s.charAt(0) !== '$') ? new(tree.Keyword)(s) : - new(tree.Variable)('@' + s.slice(2, -1), - index[k], fileInfo); + (s.charAt(0) === '@' ? + new(tree.Variable)('@' + s.slice(2, -1), index[k], fileInfo) : + new(tree.Property)('$' + s.slice(2, -1), index[k], fileInfo)); } return name; } @@ -4975,7 +5601,7 @@ Parser.serializeVars = function(vars) { module.exports = Parser; -},{"../less-error":32,"../tree":62,"../utils":83,"../visitors":87,"./parser-input":37}],39:[function(require,module,exports){ +},{"../functions/function-registry":26,"../less-error":36,"../tree":65,"../utils":86,"../visitors":90,"./parser-input":41}],43:[function(require,module,exports){ /** * Plugin Manager */ @@ -4986,7 +5612,18 @@ var PluginManager = function(less) { this.postProcessors = []; this.installedPlugins = []; this.fileManagers = []; + this.iterator = -1; + this.pluginCache = {}; + this.Loader = new less.PluginLoader(less); }; + +var pm, PluginManagerFactory = function(less, newFactory) { + if (newFactory || !pm) { + pm = new PluginManager(less); + } + return pm; + }; + /** * Adds all the plugins in the array * @param {Array} plugins @@ -5001,11 +5638,25 @@ PluginManager.prototype.addPlugins = function(plugins) { /** * * @param plugin + * @param {String} filename */ -PluginManager.prototype.addPlugin = function(plugin) { +PluginManager.prototype.addPlugin = function(plugin, filename, functionRegistry) { this.installedPlugins.push(plugin); - plugin.install(this.less, this); + if (filename) { + this.pluginCache[filename] = plugin; + } + if (plugin.install) { + plugin.install(this.less, this, functionRegistry || this.less.functions.functionRegistry); + } +}; +/** + * + * @param filename + */ +PluginManager.prototype.get = function(filename) { + return this.pluginCache[filename]; }; + /** * Adds a visitor. The visitor object has options on itself to determine * when it should run. @@ -5081,6 +5732,20 @@ PluginManager.prototype.getPostProcessors = function() { PluginManager.prototype.getVisitors = function() { return this.visitors; }; + +PluginManager.prototype.visitor = function() { + var self = this; + return { + first: function() { + self.iterator = -1; + return self.visitors[self.iterator]; + }, + get: function() { + self.iterator += 1; + return self.visitors[self.iterator]; + } + }; +}; /** * * @returns {Array} @@ -5089,53 +5754,22 @@ PluginManager.prototype.getVisitors = function() { PluginManager.prototype.getFileManagers = function() { return this.fileManagers; }; -module.exports = PluginManager; - -},{}],40:[function(require,module,exports){ -var LessError = require('../less-error'), - tree = require("../tree"); - -var FunctionImporter = module.exports = function FunctionImporter(context, fileInfo) { - this.fileInfo = fileInfo; -}; - -FunctionImporter.prototype.eval = function(contents, callback) { - var loaded = {}, - loader, - registry; - - registry = { - add: function(name, func) { - loaded[name] = func; - }, - addMultiple: function(functions) { - Object.keys(functions).forEach(function(name) { - loaded[name] = functions[name]; - }); - } - }; - try { - loader = new Function("functions", "tree", "fileInfo", contents); - loader(registry, tree, this.fileInfo); - } catch(e) { - callback(new LessError({ - message: "Plugin evaluation error: '" + e.name + ': ' + e.message.replace(/["]/g, "'") + "'" , - filename: this.fileInfo.filename - }), null ); - } - - callback(null, { functions: loaded }); -}; +// +module.exports = PluginManagerFactory; -},{"../less-error":32,"../tree":62}],41:[function(require,module,exports){ -var PromiseConstructor; +},{}],44:[function(require,module,exports){ +var PromiseConstructor, + utils = require('./utils'); module.exports = function(environment, ParseTree, ImportManager) { var render = function (input, options, callback) { if (typeof options === 'function') { callback = options; - options = {}; + options = utils.defaults(this.options, {}); + } + else { + options = utils.defaults(this.options, options || {}); } if (!callback) { @@ -5171,7 +5805,7 @@ module.exports = function(environment, ParseTree, ImportManager) { return render; }; -},{"promise":undefined}],42:[function(require,module,exports){ +},{"./utils":86,"promise":undefined}],45:[function(require,module,exports){ module.exports = function (SourceMapOutput, environment) { var SourceMapBuilder = function (options) { @@ -5200,6 +5834,9 @@ module.exports = function (SourceMapOutput, environment) { if (this.options.sourceMapInputFilename) { this.sourceMapInputFilename = sourceMapOutput.normalizeFilename(this.options.sourceMapInputFilename); } + if (this.options.sourceMapBasepath !== undefined && this.sourceMapURL !== undefined) { + this.sourceMapURL = sourceMapOutput.removeBasepath(this.sourceMapURL); + } return css + this.getCSSAppendage(); }; @@ -5242,7 +5879,7 @@ module.exports = function (SourceMapOutput, environment) { return SourceMapBuilder; }; -},{}],43:[function(require,module,exports){ +},{}],46:[function(require,module,exports){ module.exports = function (environment) { var SourceMapOutput = function (options) { @@ -5273,21 +5910,26 @@ module.exports = function (environment) { this._column = 0; }; - SourceMapOutput.prototype.normalizeFilename = function(filename) { - filename = filename.replace(/\\/g, '/'); - - if (this._sourceMapBasepath && filename.indexOf(this._sourceMapBasepath) === 0) { - filename = filename.substring(this._sourceMapBasepath.length); - if (filename.charAt(0) === '\\' || filename.charAt(0) === '/') { - filename = filename.substring(1); + SourceMapOutput.prototype.removeBasepath = function(path) { + if (this._sourceMapBasepath && path.indexOf(this._sourceMapBasepath) === 0) { + path = path.substring(this._sourceMapBasepath.length); + if (path.charAt(0) === '\\' || path.charAt(0) === '/') { + path = path.substring(1); } } + + return path; + }; + + SourceMapOutput.prototype.normalizeFilename = function(filename) { + filename = filename.replace(/\\/g, '/'); + filename = this.removeBasepath(filename); return (this._sourceMapRootpath || "") + filename; }; SourceMapOutput.prototype.add = function(chunk, fileInfo, index, mapLines) { - //ignore adding empty strings + // ignore adding empty strings if (!chunk) { return; } @@ -5382,7 +6024,7 @@ module.exports = function (environment) { return SourceMapOutput; }; -},{}],44:[function(require,module,exports){ +},{}],47:[function(require,module,exports){ var contexts = require("./contexts"), visitor = require("./visitors"), tree = require("./tree"); @@ -5398,7 +6040,7 @@ module.exports = function(root, options) { // // `{ color: new tree.Color('#f01') }` will become: // - // new tree.Rule('@color', + // new tree.Declaration('@color', // new tree.Value([ // new tree.Expression([ // new tree.Color('#f01') @@ -5410,92 +6052,61 @@ module.exports = function(root, options) { variables = Object.keys(variables).map(function (k) { var value = variables[k]; - if (! (value instanceof tree.Value)) { - if (! (value instanceof tree.Expression)) { + if (!(value instanceof tree.Value)) { + if (!(value instanceof tree.Expression)) { value = new tree.Expression([value]); } value = new tree.Value([value]); } - return new tree.Rule('@' + k, value, false, null, 0); + return new tree.Declaration('@' + k, value, false, null, 0); }); evalEnv.frames = [new tree.Ruleset(null, variables)]; } - var preEvalVisitors = [], - visitors = [ + var visitors = [ new visitor.JoinSelectorVisitor(), new visitor.MarkVisibleSelectorsVisitor(true), new visitor.ExtendVisitor(), new visitor.ToCSSVisitor({compress: Boolean(options.compress)}) - ], i; + ], v, visitorIterator; + // first() / get() allows visitors to be added while visiting if (options.pluginManager) { - var pluginVisitors = options.pluginManager.getVisitors(); - for (i = 0; i < pluginVisitors.length; i++) { - var pluginVisitor = pluginVisitors[i]; - if (pluginVisitor.isPreEvalVisitor) { - preEvalVisitors.push(pluginVisitor); - } else { - if (pluginVisitor.isPreVisitor) { - visitors.splice(0, 0, pluginVisitor); - } else { - visitors.push(pluginVisitor); - } + visitorIterator = options.pluginManager.visitor(); + visitorIterator.first(); + while ((v = visitorIterator.get())) { + if (v.isPreEvalVisitor) { + v.run(root); } } } - for (i = 0; i < preEvalVisitors.length; i++) { - preEvalVisitors[i].run(root); - } - evaldRoot = root.eval(evalEnv); - for (i = 0; i < visitors.length; i++) { + for (var i = 0; i < visitors.length; i++) { visitors[i].run(evaldRoot); } - return evaldRoot; -}; - -},{"./contexts":11,"./tree":62,"./visitors":87}],45:[function(require,module,exports){ -var Node = require("./node"); - -var Alpha = function (val) { - this.value = val; -}; -Alpha.prototype = new Node(); -Alpha.prototype.type = "Alpha"; - -Alpha.prototype.accept = function (visitor) { - this.value = visitor.visit(this.value); -}; -Alpha.prototype.eval = function (context) { - if (this.value.eval) { return new Alpha(this.value.eval(context)); } - return this; -}; -Alpha.prototype.genCSS = function (context, output) { - output.add("alpha(opacity="); - - if (this.value.genCSS) { - this.value.genCSS(context, output); - } else { - output.add(this.value); + if (options.pluginManager) { + visitorIterator.first(); + while ((v = visitorIterator.get())) { + if (!v.isPreEvalVisitor) { + v.run(evaldRoot); + } + } } - output.add(")"); + return evaldRoot; }; -module.exports = Alpha; - -},{"./node":70}],46:[function(require,module,exports){ +},{"./contexts":12,"./tree":65,"./visitors":90}],48:[function(require,module,exports){ var Node = require("./node"); var Anonymous = function (value, index, currentFileInfo, mapLines, rulesetLike, visibilityInfo) { this.value = value; - this.index = index; + this._index = index; + this._fileInfo = currentFileInfo; this.mapLines = mapLines; - this.currentFileInfo = currentFileInfo; this.rulesetLike = (typeof rulesetLike === 'undefined') ? false : rulesetLike; this.allowRoot = true; this.copyVisibilityInfo(visibilityInfo); @@ -5503,7 +6114,7 @@ var Anonymous = function (value, index, currentFileInfo, mapLines, rulesetLike, Anonymous.prototype = new Node(); Anonymous.prototype.type = "Anonymous"; Anonymous.prototype.eval = function () { - return new Anonymous(this.value, this.index, this.currentFileInfo, this.mapLines, this.rulesetLike, this.visibilityInfo()); + return new Anonymous(this.value, this._index, this._fileInfo, this.mapLines, this.rulesetLike, this.visibilityInfo()); }; Anonymous.prototype.compare = function (other) { return other.toCSS && this.toCSS() === other.toCSS() ? 0 : undefined; @@ -5512,11 +6123,14 @@ Anonymous.prototype.isRulesetLike = function() { return this.rulesetLike; }; Anonymous.prototype.genCSS = function (context, output) { - output.add(this.value, this.currentFileInfo, this.index, this.mapLines); + this.nodeVisible = Boolean(this.value); + if (this.nodeVisible) { + output.add(this.value, this._fileInfo, this._index, this.mapLines); + } }; module.exports = Anonymous; -},{"./node":70}],47:[function(require,module,exports){ +},{"./node":73}],49:[function(require,module,exports){ var Node = require("./node"); var Assignment = function (key, val) { @@ -5545,19 +6159,157 @@ Assignment.prototype.genCSS = function (context, output) { }; module.exports = Assignment; -},{"./node":70}],48:[function(require,module,exports){ -var Node = require("./node"); +},{"./node":73}],50:[function(require,module,exports){ +var Node = require("./node"), + Selector = require("./selector"), + Ruleset = require("./ruleset"), + Anonymous = require('./anonymous'); -var Attribute = function (key, op, value) { - this.key = key; - this.op = op; - this.value = value; -}; -Attribute.prototype = new Node(); -Attribute.prototype.type = "Attribute"; -Attribute.prototype.eval = function (context) { - return new Attribute(this.key.eval ? this.key.eval(context) : this.key, - this.op, (this.value && this.value.eval) ? this.value.eval(context) : this.value); +var AtRule = function (name, value, rules, index, currentFileInfo, debugInfo, isRooted, visibilityInfo) { + var i; + + this.name = name; + this.value = (value instanceof Node) ? value : (value ? new Anonymous(value) : value); + if (rules) { + if (Array.isArray(rules)) { + this.rules = rules; + } else { + this.rules = [rules]; + this.rules[0].selectors = (new Selector([], null, null, index, currentFileInfo)).createEmptySelectors(); + } + for (i = 0; i < this.rules.length; i++) { + this.rules[i].allowImports = true; + } + this.setParent(this.rules, this); + } + this._index = index; + this._fileInfo = currentFileInfo; + this.debugInfo = debugInfo; + this.isRooted = isRooted || false; + this.copyVisibilityInfo(visibilityInfo); + this.allowRoot = true; +}; + +AtRule.prototype = new Node(); +AtRule.prototype.type = "AtRule"; +AtRule.prototype.accept = function (visitor) { + var value = this.value, rules = this.rules; + if (rules) { + this.rules = visitor.visitArray(rules); + } + if (value) { + this.value = visitor.visit(value); + } +}; +AtRule.prototype.isRulesetLike = function() { + return this.rules || !this.isCharset(); +}; +AtRule.prototype.isCharset = function() { + return "@charset" === this.name; +}; +AtRule.prototype.genCSS = function (context, output) { + var value = this.value, rules = this.rules; + output.add(this.name, this.fileInfo(), this.getIndex()); + if (value) { + output.add(' '); + value.genCSS(context, output); + } + if (rules) { + this.outputRuleset(context, output, rules); + } else { + output.add(';'); + } +}; +AtRule.prototype.eval = function (context) { + var mediaPathBackup, mediaBlocksBackup, value = this.value, rules = this.rules; + + // media stored inside other atrule should not bubble over it + // backpup media bubbling information + mediaPathBackup = context.mediaPath; + mediaBlocksBackup = context.mediaBlocks; + // deleted media bubbling information + context.mediaPath = []; + context.mediaBlocks = []; + + if (value) { + value = value.eval(context); + } + if (rules) { + // assuming that there is only one rule at this point - that is how parser constructs the rule + rules = [rules[0].eval(context)]; + rules[0].root = true; + } + // restore media bubbling information + context.mediaPath = mediaPathBackup; + context.mediaBlocks = mediaBlocksBackup; + + return new AtRule(this.name, value, rules, + this.getIndex(), this.fileInfo(), this.debugInfo, this.isRooted, this.visibilityInfo()); +}; +AtRule.prototype.variable = function (name) { + if (this.rules) { + // assuming that there is only one rule at this point - that is how parser constructs the rule + return Ruleset.prototype.variable.call(this.rules[0], name); + } +}; +AtRule.prototype.find = function () { + if (this.rules) { + // assuming that there is only one rule at this point - that is how parser constructs the rule + return Ruleset.prototype.find.apply(this.rules[0], arguments); + } +}; +AtRule.prototype.rulesets = function () { + if (this.rules) { + // assuming that there is only one rule at this point - that is how parser constructs the rule + return Ruleset.prototype.rulesets.apply(this.rules[0]); + } +}; +AtRule.prototype.outputRuleset = function (context, output, rules) { + var ruleCnt = rules.length, i; + context.tabLevel = (context.tabLevel | 0) + 1; + + // Compressed + if (context.compress) { + output.add('{'); + for (i = 0; i < ruleCnt; i++) { + rules[i].genCSS(context, output); + } + output.add('}'); + context.tabLevel--; + return; + } + + // Non-compressed + var tabSetStr = '\n' + Array(context.tabLevel).join(" "), tabRuleStr = tabSetStr + " "; + if (!ruleCnt) { + output.add(" {" + tabSetStr + '}'); + } else { + output.add(" {" + tabRuleStr); + rules[0].genCSS(context, output); + for (i = 1; i < ruleCnt; i++) { + output.add(tabRuleStr); + rules[i].genCSS(context, output); + } + output.add(tabSetStr + '}'); + } + + context.tabLevel--; +}; +module.exports = AtRule; + +},{"./anonymous":48,"./node":73,"./ruleset":78,"./selector":79}],51:[function(require,module,exports){ +var Node = require("./node"); + +var Attribute = function (key, op, value) { + this.key = key; + this.op = op; + this.value = value; +}; +Attribute.prototype = new Node(); +Attribute.prototype.type = "Attribute"; +Attribute.prototype.eval = function (context) { + return new Attribute(this.key.eval ? this.key.eval(context) : this.key, + this.op, (this.value && this.value.eval) ? this.value.eval(context) : this.value); }; Attribute.prototype.genCSS = function (context, output) { output.add(this.toCSS(context)); @@ -5574,8 +6326,9 @@ Attribute.prototype.toCSS = function (context) { }; module.exports = Attribute; -},{"./node":70}],49:[function(require,module,exports){ +},{"./node":73}],52:[function(require,module,exports){ var Node = require("./node"), + Anonymous = require("./anonymous"), FunctionCaller = require("../functions/function-caller"); // // A function call node. @@ -5583,8 +6336,9 @@ var Node = require("./node"), var Call = function (name, args, index, currentFileInfo) { this.name = name; this.args = args; - this.index = index; - this.currentFileInfo = currentFileInfo; + this.mathOn = name === 'calc' ? false : true; + this._index = index; + this._fileInfo = currentFileInfo; }; Call.prototype = new Node(); Call.prototype.type = "Call"; @@ -5605,30 +6359,55 @@ Call.prototype.accept = function (visitor) { // The function should receive the value, not the variable. // Call.prototype.eval = function (context) { - var args = this.args.map(function (a) { return a.eval(context); }), - result, funcCaller = new FunctionCaller(this.name, context, this.index, this.currentFileInfo); + /** + * Turn off math for calc(), and switch back on for evaluating nested functions + */ + var currentMathContext = context.mathOn; + context.mathOn = this.mathOn; + var args = this.args.map(function (a) { return a.eval(context); }); + context.mathOn = currentMathContext; + + var result, funcCaller = new FunctionCaller(this.name, context, this.getIndex(), this.fileInfo()); + if (funcCaller.isValid()) { try { result = funcCaller.call(args); } catch (e) { - throw { type: e.type || "Runtime", - message: "error evaluating function `" + this.name + "`" + - (e.message ? ': ' + e.message : ''), - index: this.index, filename: this.currentFileInfo.filename }; + throw { + type: e.type || "Runtime", + message: "error evaluating function `" + this.name + "`" + + (e.message ? ': ' + e.message : ''), + index: this.getIndex(), + filename: this.fileInfo().filename, + line: e.lineNumber, + column: e.columnNumber + }; } - if (result != null) { - result.index = this.index; - result.currentFileInfo = this.currentFileInfo; + if (result !== null && result !== undefined) { + // Results that that are not nodes are cast as Anonymous nodes + // Falsy values or booleans are returned as empty nodes + if (!(result instanceof Node)) { + if (!result || result === true) { + result = new Anonymous(null); + } + else { + result = new Anonymous(result.toString()); + } + + } + result._index = this._index; + result._fileInfo = this._fileInfo; return result; } + } - return new Call(this.name, args, this.index, this.currentFileInfo); + return new Call(this.name, args, this.getIndex(), this.fileInfo()); }; Call.prototype.genCSS = function (context, output) { - output.add(this.name + "(", this.currentFileInfo, this.index); + output.add(this.name + "(", this.fileInfo(), this.getIndex()); for (var i = 0; i < this.args.length; i++) { this.args[i].genCSS(context, output); @@ -5641,7 +6420,7 @@ Call.prototype.genCSS = function (context, output) { }; module.exports = Call; -},{"../functions/function-caller":21,"./node":70}],50:[function(require,module,exports){ +},{"../functions/function-caller":25,"./anonymous":48,"./node":73}],53:[function(require,module,exports){ var Node = require("./node"), colors = require("../data/colors"); @@ -5743,7 +6522,7 @@ Color.prototype.toCSS = function (context, doNotCompress) { // we create a new Color node to hold the result. // Color.prototype.operate = function (context, op, other) { - var rgb = []; + var rgb = new Array(3); var alpha = this.alpha * (1 - other.alpha) + other.alpha; for (var c = 0; c < 3; c++) { rgb[c] = this._operate(context, op, this.rgb[c], other.rgb[c]); @@ -5776,7 +6555,7 @@ Color.prototype.toHSL = function () { } return { h: h * 360, s: s, l: l, a: a }; }; -//Adapted from http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript +// Adapted from http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript Color.prototype.toHSV = function () { var r = this.rgb[0] / 255, g = this.rgb[1] / 255, @@ -5796,7 +6575,7 @@ Color.prototype.toHSV = function () { if (max === min) { h = 0; } else { - switch(max) { + switch (max) { case r: h = (g - b) / d + (g < b ? 6 : 0); break; case g: h = (b - r) / d + 2; break; case b: h = (r - g) / d + 4; break; @@ -5832,7 +6611,7 @@ Color.fromKeyword = function(keyword) { }; module.exports = Color; -},{"../data/colors":12,"./node":70}],51:[function(require,module,exports){ +},{"../data/colors":13,"./node":73}],54:[function(require,module,exports){ var Node = require("./node"); var Combinator = function (value) { @@ -5857,22 +6636,22 @@ Combinator.prototype.genCSS = function (context, output) { }; module.exports = Combinator; -},{"./node":70}],52:[function(require,module,exports){ +},{"./node":73}],55:[function(require,module,exports){ var Node = require("./node"), getDebugInfo = require("./debug-info"); var Comment = function (value, isLineComment, index, currentFileInfo) { this.value = value; this.isLineComment = isLineComment; - this.index = index; - this.currentFileInfo = currentFileInfo; + this._index = index; + this._fileInfo = currentFileInfo; this.allowRoot = true; }; Comment.prototype = new Node(); Comment.prototype.type = "Comment"; Comment.prototype.genCSS = function (context, output) { if (this.debugInfo) { - output.add(getDebugInfo(context, this), this.currentFileInfo, this.index); + output.add(getDebugInfo(context, this), this.fileInfo(), this.getIndex()); } output.add(this.value); }; @@ -5882,14 +6661,14 @@ Comment.prototype.isSilent = function(context) { }; module.exports = Comment; -},{"./debug-info":54,"./node":70}],53:[function(require,module,exports){ +},{"./debug-info":57,"./node":73}],56:[function(require,module,exports){ var Node = require("./node"); var Condition = function (op, l, r, i, negate) { this.op = op.trim(); this.lvalue = l; this.rvalue = r; - this.index = i; + this._index = i; this.negate = negate; }; Condition.prototype = new Node(); @@ -5921,11 +6700,11 @@ Condition.prototype.eval = function (context) { }; module.exports = Condition; -},{"./node":70}],54:[function(require,module,exports){ +},{"./node":73}],57:[function(require,module,exports){ var debugInfo = function(context, ctx, lineSeparator) { var result = ""; if (context.dumpLineNumbers && !context.compress) { - switch(context.dumpLineNumbers) { + switch (context.dumpLineNumbers) { case 'comments': result = debugInfo.asComment(ctx); break; @@ -5961,13 +6740,114 @@ debugInfo.asMediaQuery = function(ctx) { module.exports = debugInfo; -},{}],55:[function(require,module,exports){ +},{}],58:[function(require,module,exports){ var Node = require("./node"), - contexts = require("../contexts"); + Value = require("./value"), + Keyword = require("./keyword"), + Anonymous = require("./anonymous"); + +var Declaration = function (name, value, important, merge, index, currentFileInfo, inline, variable) { + this.name = name; + this.value = (value instanceof Node) ? value : new Value([value ? new Anonymous(value) : null]); + this.important = important ? ' ' + important.trim() : ''; + this.merge = merge; + this._index = index; + this._fileInfo = currentFileInfo; + this.inline = inline || false; + this.variable = (variable !== undefined) ? variable + : (name.charAt && (name.charAt(0) === '@')); + this.allowRoot = true; + this.setParent(this.value, this); +}; + +function evalName(context, name) { + var value = "", i, n = name.length, + output = {add: function (s) {value += s;}}; + for (i = 0; i < n; i++) { + name[i].eval(context).genCSS(context, output); + } + return value; +} + +Declaration.prototype = new Node(); +Declaration.prototype.type = "Declaration"; +Declaration.prototype.genCSS = function (context, output) { + output.add(this.name + (context.compress ? ':' : ': '), this.fileInfo(), this.getIndex()); + try { + this.value.genCSS(context, output); + } + catch (e) { + e.index = this._index; + e.filename = this._fileInfo.filename; + throw e; + } + output.add(this.important + ((this.inline || (context.lastRule && context.compress)) ? "" : ";"), this._fileInfo, this._index); +}; +Declaration.prototype.eval = function (context) { + var strictMathBypass = false, name = this.name, evaldValue, variable = this.variable; + if (typeof name !== "string") { + // expand 'primitive' name directly to get + // things faster (~10% for benchmark.less): + name = (name.length === 1) && (name[0] instanceof Keyword) ? + name[0].value : evalName(context, name); + variable = false; // never treat expanded interpolation as new variable name + } + if (name === "font" && !context.strictMath) { + strictMathBypass = true; + context.strictMath = true; + } + try { + context.importantScope.push({}); + evaldValue = this.value.eval(context); + + if (!this.variable && evaldValue.type === "DetachedRuleset") { + throw { message: "Rulesets cannot be evaluated on a property.", + index: this.getIndex(), filename: this.fileInfo().filename }; + } + var important = this.important, + importantResult = context.importantScope.pop(); + if (!important && importantResult.important) { + important = importantResult.important; + } + + return new Declaration(name, + evaldValue, + important, + this.merge, + this.getIndex(), this.fileInfo(), this.inline, + variable); + } + catch (e) { + if (typeof e.index !== 'number') { + e.index = this.getIndex(); + e.filename = this.fileInfo().filename; + } + throw e; + } + finally { + if (strictMathBypass) { + context.strictMath = false; + } + } +}; +Declaration.prototype.makeImportant = function () { + return new Declaration(this.name, + this.value, + "!important", + this.merge, + this.getIndex(), this.fileInfo(), this.inline); +}; + +module.exports = Declaration; +},{"./anonymous":48,"./keyword":68,"./node":73,"./value":83}],59:[function(require,module,exports){ +var Node = require("./node"), + contexts = require("../contexts"), + utils = require("../utils"); var DetachedRuleset = function (ruleset, frames) { this.ruleset = ruleset; this.frames = frames; + this.setParent(this.ruleset, this); }; DetachedRuleset.prototype = new Node(); DetachedRuleset.prototype.type = "DetachedRuleset"; @@ -5976,7 +6856,7 @@ DetachedRuleset.prototype.accept = function (visitor) { this.ruleset = visitor.visit(this.ruleset); }; DetachedRuleset.prototype.eval = function (context) { - var frames = this.frames || context.frames.slice(0); + var frames = this.frames || utils.copyArray(context.frames); return new DetachedRuleset(this.ruleset, frames); }; DetachedRuleset.prototype.callEval = function (context) { @@ -5984,7 +6864,7 @@ DetachedRuleset.prototype.callEval = function (context) { }; module.exports = DetachedRuleset; -},{"../contexts":11,"./node":70}],56:[function(require,module,exports){ +},{"../contexts":12,"../utils":86,"./node":73}],60:[function(require,module,exports){ var Node = require("./node"), unitConversions = require("../data/unit-conversions"), Unit = require("./unit"), @@ -5995,8 +6875,12 @@ var Node = require("./node"), // var Dimension = function (value, unit) { this.value = parseFloat(value); + if (isNaN(this.value)) { + throw new Error("Dimension is not a number."); + } this.unit = (unit && unit instanceof Unit) ? unit : new Unit(unit ? [unit] : undefined); + this.setParent(this.unit, this); }; Dimension.prototype = new Node(); @@ -6044,7 +6928,7 @@ Dimension.prototype.genCSS = function (context, output) { // we default to the first Dimension's unit, // so `1px + 2` will yield `3px`. Dimension.prototype.operate = function (context, op, other) { - /*jshint noempty:false */ + /* jshint noempty:false */ var value = this._operate(context, op, this.value, other.value), unit = this.unit.clone(); @@ -6143,148 +7027,12 @@ Dimension.prototype.convertTo = function (conversions) { }; module.exports = Dimension; -},{"../data/unit-conversions":14,"./color":50,"./node":70,"./unit":79}],57:[function(require,module,exports){ -var Node = require("./node"), - Selector = require("./selector"), - Ruleset = require("./ruleset"); - -var Directive = function (name, value, rules, index, currentFileInfo, debugInfo, isRooted, visibilityInfo) { - var i; - - this.name = name; - this.value = value; - if (rules) { - if (Array.isArray(rules)) { - this.rules = rules; - } else { - this.rules = [rules]; - this.rules[0].selectors = (new Selector([], null, null, this.index, currentFileInfo)).createEmptySelectors(); - } - for (i = 0; i < this.rules.length; i++) { - this.rules[i].allowImports = true; - } - } - this.index = index; - this.currentFileInfo = currentFileInfo; - this.debugInfo = debugInfo; - this.isRooted = isRooted || false; - this.copyVisibilityInfo(visibilityInfo); - this.allowRoot = true; -}; - -Directive.prototype = new Node(); -Directive.prototype.type = "Directive"; -Directive.prototype.accept = function (visitor) { - var value = this.value, rules = this.rules; - if (rules) { - this.rules = visitor.visitArray(rules); - } - if (value) { - this.value = visitor.visit(value); - } -}; -Directive.prototype.isRulesetLike = function() { - return this.rules || !this.isCharset(); -}; -Directive.prototype.isCharset = function() { - return "@charset" === this.name; -}; -Directive.prototype.genCSS = function (context, output) { - var value = this.value, rules = this.rules; - output.add(this.name, this.currentFileInfo, this.index); - if (value) { - output.add(' '); - value.genCSS(context, output); - } - if (rules) { - this.outputRuleset(context, output, rules); - } else { - output.add(';'); - } -}; -Directive.prototype.eval = function (context) { - var mediaPathBackup, mediaBlocksBackup, value = this.value, rules = this.rules; - - //media stored inside other directive should not bubble over it - //backpup media bubbling information - mediaPathBackup = context.mediaPath; - mediaBlocksBackup = context.mediaBlocks; - //deleted media bubbling information - context.mediaPath = []; - context.mediaBlocks = []; - - if (value) { - value = value.eval(context); - } - if (rules) { - // assuming that there is only one rule at this point - that is how parser constructs the rule - rules = [rules[0].eval(context)]; - rules[0].root = true; - } - //restore media bubbling information - context.mediaPath = mediaPathBackup; - context.mediaBlocks = mediaBlocksBackup; - - return new Directive(this.name, value, rules, - this.index, this.currentFileInfo, this.debugInfo, this.isRooted, this.visibilityInfo()); -}; -Directive.prototype.variable = function (name) { - if (this.rules) { - // assuming that there is only one rule at this point - that is how parser constructs the rule - return Ruleset.prototype.variable.call(this.rules[0], name); - } -}; -Directive.prototype.find = function () { - if (this.rules) { - // assuming that there is only one rule at this point - that is how parser constructs the rule - return Ruleset.prototype.find.apply(this.rules[0], arguments); - } -}; -Directive.prototype.rulesets = function () { - if (this.rules) { - // assuming that there is only one rule at this point - that is how parser constructs the rule - return Ruleset.prototype.rulesets.apply(this.rules[0]); - } -}; -Directive.prototype.outputRuleset = function (context, output, rules) { - var ruleCnt = rules.length, i; - context.tabLevel = (context.tabLevel | 0) + 1; - - // Compressed - if (context.compress) { - output.add('{'); - for (i = 0; i < ruleCnt; i++) { - rules[i].genCSS(context, output); - } - output.add('}'); - context.tabLevel--; - return; - } - - // Non-compressed - var tabSetStr = '\n' + Array(context.tabLevel).join(" "), tabRuleStr = tabSetStr + " "; - if (!ruleCnt) { - output.add(" {" + tabSetStr + '}'); - } else { - output.add(" {" + tabRuleStr); - rules[0].genCSS(context, output); - for (i = 1; i < ruleCnt; i++) { - output.add(tabRuleStr); - rules[i].genCSS(context, output); - } - output.add(tabSetStr + '}'); - } - - context.tabLevel--; -}; -module.exports = Directive; - -},{"./node":70,"./ruleset":76,"./selector":77}],58:[function(require,module,exports){ +},{"../data/unit-conversions":15,"./color":53,"./node":73,"./unit":81}],61:[function(require,module,exports){ var Node = require("./node"), Paren = require("./paren"), Combinator = require("./combinator"); -var Element = function (combinator, value, index, currentFileInfo, info) { +var Element = function (combinator, value, index, currentFileInfo, visibilityInfo) { this.combinator = combinator instanceof Combinator ? combinator : new Combinator(combinator); @@ -6295,9 +7043,10 @@ var Element = function (combinator, value, index, currentFileInfo, info) { } else { this.value = ""; } - this.index = index; - this.currentFileInfo = currentFileInfo; - this.copyVisibilityInfo(info); + this._index = index; + this._fileInfo = currentFileInfo; + this.copyVisibilityInfo(visibilityInfo); + this.setParent(this.combinator, this); }; Element.prototype = new Node(); Element.prototype.type = "Element"; @@ -6311,17 +7060,17 @@ Element.prototype.accept = function (visitor) { Element.prototype.eval = function (context) { return new Element(this.combinator, this.value.eval ? this.value.eval(context) : this.value, - this.index, - this.currentFileInfo, this.visibilityInfo()); + this.getIndex(), + this.fileInfo(), this.visibilityInfo()); }; Element.prototype.clone = function () { return new Element(this.combinator, this.value, - this.index, - this.currentFileInfo, this.visibilityInfo()); + this.getIndex(), + this.fileInfo(), this.visibilityInfo()); }; Element.prototype.genCSS = function (context, output) { - output.add(this.toCSS(context), this.currentFileInfo, this.index); + output.add(this.toCSS(context), this.fileInfo(), this.getIndex()); }; Element.prototype.toCSS = function (context) { context = context || {}; @@ -6341,7 +7090,7 @@ Element.prototype.toCSS = function (context) { }; module.exports = Element; -},{"./combinator":51,"./node":70,"./paren":72}],59:[function(require,module,exports){ +},{"./combinator":54,"./node":73,"./paren":75}],62:[function(require,module,exports){ var Node = require("./node"), Paren = require("./paren"), Comment = require("./comment"); @@ -6399,21 +7148,21 @@ Expression.prototype.throwAwayComments = function () { }; module.exports = Expression; -},{"./comment":52,"./node":70,"./paren":72}],60:[function(require,module,exports){ +},{"./comment":55,"./node":73,"./paren":75}],63:[function(require,module,exports){ var Node = require("./node"), Selector = require("./selector"); var Extend = function Extend(selector, option, index, currentFileInfo, visibilityInfo) { this.selector = selector; this.option = option; - this.index = index; this.object_id = Extend.next_id++; this.parent_ids = [this.object_id]; - this.currentFileInfo = currentFileInfo || {}; + this._index = index; + this._fileInfo = currentFileInfo; this.copyVisibilityInfo(visibilityInfo); this.allowRoot = true; - switch(option) { + switch (option) { case "all": this.allowBefore = true; this.allowAfter = true; @@ -6423,6 +7172,7 @@ var Extend = function Extend(selector, option, index, currentFileInfo, visibilit this.allowAfter = false; break; } + this.setParent(this.selector, this); }; Extend.next_id = 0; @@ -6432,12 +7182,12 @@ Extend.prototype.accept = function (visitor) { this.selector = visitor.visit(this.selector); }; Extend.prototype.eval = function (context) { - return new Extend(this.selector.eval(context), this.option, this.index, this.currentFileInfo, this.visibilityInfo()); + return new Extend(this.selector.eval(context), this.option, this.getIndex(), this.fileInfo(), this.visibilityInfo()); }; Extend.prototype.clone = function (context) { - return new Extend(this.selector, this.option, this.index, this.currentFileInfo, this.visibilityInfo()); + return new Extend(this.selector, this.option, this.getIndex(), this.fileInfo(), this.visibilityInfo()); }; -//it concatenates (joins) all selectors in selector array +// it concatenates (joins) all selectors in selector array Extend.prototype.findSelfSelectors = function (selectors) { var selfElements = [], i, @@ -6458,13 +7208,15 @@ Extend.prototype.findSelfSelectors = function (selectors) { }; module.exports = Extend; -},{"./node":70,"./selector":77}],61:[function(require,module,exports){ +},{"./node":73,"./selector":79}],64:[function(require,module,exports){ var Node = require("./node"), Media = require("./media"), URL = require("./url"), Quoted = require("./quoted"), Ruleset = require("./ruleset"), - Anonymous = require("./anonymous"); + Anonymous = require("./anonymous"), + utils = require("../utils"), + LessError = require("../less-error"); // // CSS @import node @@ -6480,21 +7232,23 @@ var Node = require("./node"), // var Import = function (path, features, options, index, currentFileInfo, visibilityInfo) { this.options = options; - this.index = index; + this._index = index; + this._fileInfo = currentFileInfo; this.path = path; this.features = features; - this.currentFileInfo = currentFileInfo; this.allowRoot = true; if (this.options.less !== undefined || this.options.inline) { this.css = !this.options.less || this.options.inline; } else { var pathValue = this.getPath(); - if (pathValue && /[#\.\&\?\/]css([\?;].*)?$/.test(pathValue)) { + if (pathValue && /[#\.\&\?]css([\?;].*)?$/.test(pathValue)) { this.css = true; } } this.copyVisibilityInfo(visibilityInfo); + this.setParent(this.features, this); + this.setParent(this.path, this); }; // @@ -6513,13 +7267,13 @@ Import.prototype.accept = function (visitor) { this.features = visitor.visit(this.features); } this.path = visitor.visit(this.path); - if (!this.options.plugin && !this.options.inline && this.root) { + if (!this.options.isPlugin && !this.options.inline && this.root) { this.root = visitor.visit(this.root); } }; Import.prototype.genCSS = function (context, output) { - if (this.css && this.path.currentFileInfo.reference === undefined) { - output.add("@import ", this.currentFileInfo, this.index); + if (this.css && this.path._fileInfo.reference === undefined) { + output.add("@import ", this._fileInfo, this._index); this.path.genCSS(context, output); if (this.features) { output.add(" "); @@ -6550,11 +7304,11 @@ Import.prototype.evalForImport = function (context) { path = path.value; } - return new Import(path.eval(context), this.features, this.options, this.index, this.currentFileInfo, this.visibilityInfo()); + return new Import(path.eval(context), this.features, this.options, this._index, this._fileInfo, this.visibilityInfo()); }; Import.prototype.evalPath = function (context) { var path = this.path.eval(context); - var rootpath = this.currentFileInfo && this.currentFileInfo.rootpath; + var rootpath = this._fileInfo && this._fileInfo.rootpath; if (!(path instanceof URL)) { if (rootpath) { @@ -6574,8 +7328,8 @@ Import.prototype.eval = function (context) { if (this.options.reference || this.blocksVisibility()) { if (result.length || result.length === 0) { result.forEach(function (node) { - node.addVisibilityBlock(); - } + node.addVisibilityBlock(); + } ); } else { result.addVisibilityBlock(); @@ -6587,11 +7341,21 @@ Import.prototype.doEval = function (context) { var ruleset, registry, features = this.features && this.features.eval(context); - if (this.options.plugin) { + if (this.options.isPlugin) { + if (this.root && this.root.eval) { + try { + this.root.eval(context); + } + catch (e) { + e.message = "Plugin error during evaluation"; + throw new LessError(e, this.root.imports, this.root.filename); + } + } registry = context.frames[0] && context.frames[0].functionRegistry; if ( registry && this.root && this.root.functions ) { registry.addMultiple( this.root.functions ); } + return []; } @@ -6605,20 +7369,20 @@ Import.prototype.doEval = function (context) { } if (this.options.inline) { var contents = new Anonymous(this.root, 0, - { - filename: this.importedFilename, - reference: this.path.currentFileInfo && this.path.currentFileInfo.reference - }, true, true); + { + filename: this.importedFilename, + reference: this.path._fileInfo && this.path._fileInfo.reference + }, true, true); return this.features ? new Media([contents], this.features.value) : [contents]; } else if (this.css) { - var newImport = new Import(this.evalPath(context), features, this.options, this.index); + var newImport = new Import(this.evalPath(context), features, this.options, this._index); if (!newImport.css && this.error) { throw this.error; } return newImport; } else { - ruleset = new Ruleset(null, this.root.rules.slice(0)); + ruleset = new Ruleset(null, utils.copyArray(this.root.rules)); ruleset.evalImports(context); return this.features ? new Media(ruleset.rules, this.features.value) : ruleset.rules; @@ -6626,19 +7390,19 @@ Import.prototype.doEval = function (context) { }; module.exports = Import; -},{"./anonymous":46,"./media":66,"./node":70,"./quoted":73,"./ruleset":76,"./url":80}],62:[function(require,module,exports){ -var tree = {}; +},{"../less-error":36,"../utils":86,"./anonymous":48,"./media":69,"./node":73,"./quoted":77,"./ruleset":78,"./url":82}],65:[function(require,module,exports){ +var tree = Object.create(null); tree.Node = require('./node'); -tree.Alpha = require('./alpha'); tree.Color = require('./color'); -tree.Directive = require('./directive'); +tree.AtRule = require('./atrule'); tree.DetachedRuleset = require('./detached-ruleset'); tree.Operation = require('./operation'); tree.Dimension = require('./dimension'); tree.Unit = require('./unit'); tree.Keyword = require('./keyword'); tree.Variable = require('./variable'); +tree.Property = require('./property'); tree.Ruleset = require('./ruleset'); tree.Element = require('./element'); tree.Attribute = require('./attribute'); @@ -6646,7 +7410,7 @@ tree.Combinator = require('./combinator'); tree.Selector = require('./selector'); tree.Quoted = require('./quoted'); tree.Expression = require('./expression'); -tree.Rule = require('./rule'); +tree.Declaration = require('./declaration'); tree.Call = require('./call'); tree.URL = require('./url'); tree.Import = require('./import'); @@ -6665,11 +7429,11 @@ tree.Media = require('./media'); tree.UnicodeDescriptor = require('./unicode-descriptor'); tree.Negative = require('./negative'); tree.Extend = require('./extend'); -tree.RulesetCall = require('./ruleset-call'); +tree.VariableCall = require('./variable-call'); module.exports = tree; -},{"./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){ +},{"./anonymous":48,"./assignment":49,"./atrule":50,"./attribute":51,"./call":52,"./color":53,"./combinator":54,"./comment":55,"./condition":56,"./declaration":58,"./detached-ruleset":59,"./dimension":60,"./element":61,"./expression":62,"./extend":63,"./import":64,"./javascript":66,"./keyword":68,"./media":69,"./mixin-call":70,"./mixin-definition":71,"./negative":72,"./node":73,"./operation":74,"./paren":75,"./property":76,"./quoted":77,"./ruleset":78,"./selector":79,"./unicode-descriptor":80,"./unit":81,"./url":82,"./value":83,"./variable":85,"./variable-call":84}],66:[function(require,module,exports){ var JsEvalNode = require("./js-eval-node"), Dimension = require("./dimension"), Quoted = require("./quoted"), @@ -6678,8 +7442,8 @@ var JsEvalNode = require("./js-eval-node"), var JavaScript = function (string, escaped, index, currentFileInfo) { this.escaped = escaped; this.expression = string; - this.index = index; - this.currentFileInfo = currentFileInfo; + this._index = index; + this._fileInfo = currentFileInfo; }; JavaScript.prototype = new JsEvalNode(); JavaScript.prototype.type = "JavaScript"; @@ -6689,7 +7453,7 @@ JavaScript.prototype.eval = function(context) { if (typeof result === 'number') { return new Dimension(result); } else if (typeof result === 'string') { - return new Quoted('"' + result + '"', result, this.escaped, this.index); + return new Quoted('"' + result + '"', result, this.escaped, this._index); } else if (Array.isArray(result)) { return new Anonymous(result.join(', ')); } else { @@ -6699,7 +7463,7 @@ JavaScript.prototype.eval = function(context) { module.exports = JavaScript; -},{"./anonymous":46,"./dimension":56,"./js-eval-node":64,"./quoted":73}],64:[function(require,module,exports){ +},{"./anonymous":48,"./dimension":60,"./js-eval-node":67,"./quoted":77}],67:[function(require,module,exports){ var Node = require("./node"), Variable = require("./variable"); @@ -6712,28 +7476,28 @@ JsEvalNode.prototype.evaluateJavaScript = function (expression, context) { that = this, evalContext = {}; - if (context.javascriptEnabled !== undefined && !context.javascriptEnabled) { - throw { message: "You are using JavaScript, which has been disabled.", - filename: this.currentFileInfo.filename, - index: this.index }; + if (!context.javascriptEnabled) { + throw { message: "Inline JavaScript is not enabled. Is it set in your options?", + filename: this.fileInfo().filename, + index: this.getIndex() }; } expression = expression.replace(/@\{([\w-]+)\}/g, function (_, name) { - return that.jsify(new Variable('@' + name, that.index, that.currentFileInfo).eval(context)); + return that.jsify(new Variable('@' + name, that.getIndex(), that.fileInfo()).eval(context)); }); try { expression = new Function('return (' + expression + ')'); } catch (e) { throw { message: "JavaScript evaluation error: " + e.message + " from `" + expression + "`" , - filename: this.currentFileInfo.filename, - index: this.index }; + filename: this.fileInfo().filename, + index: this.getIndex() }; } var variables = context.frames[0].variables(); for (var k in variables) { if (variables.hasOwnProperty(k)) { - /*jshint loopfunc:true */ + /* jshint loopfunc:true */ evalContext[k.slice(1)] = { value: variables[k].value, toJS: function () { @@ -6747,8 +7511,8 @@ JsEvalNode.prototype.evaluateJavaScript = function (expression, context) { result = expression.call(evalContext); } catch (e) { throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message.replace(/["]/g, "'") + "'" , - filename: this.currentFileInfo.filename, - index: this.index }; + filename: this.fileInfo().filename, + index: this.getIndex() }; } return result; }; @@ -6762,7 +7526,7 @@ JsEvalNode.prototype.jsify = function (obj) { module.exports = JsEvalNode; -},{"./node":70,"./variable":82}],65:[function(require,module,exports){ +},{"./node":73,"./variable":85}],68:[function(require,module,exports){ var Node = require("./node"); var Keyword = function (value) { this.value = value; }; @@ -6778,29 +7542,33 @@ Keyword.False = new Keyword('false'); module.exports = Keyword; -},{"./node":70}],66:[function(require,module,exports){ +},{"./node":73}],69:[function(require,module,exports){ var Ruleset = require("./ruleset"), Value = require("./value"), Selector = require("./selector"), Anonymous = require("./anonymous"), Expression = require("./expression"), - Directive = require("./directive"); + AtRule = require("./atrule"), + utils = require("../utils"); var Media = function (value, features, index, currentFileInfo, visibilityInfo) { - this.index = index; - this.currentFileInfo = currentFileInfo; + this._index = index; + this._fileInfo = currentFileInfo; - var selectors = (new Selector([], null, null, this.index, this.currentFileInfo)).createEmptySelectors(); + var selectors = (new Selector([], null, null, this._index, this._fileInfo)).createEmptySelectors(); this.features = new Value(features); this.rules = [new Ruleset(selectors, value)]; this.rules[0].allowImports = true; this.copyVisibilityInfo(visibilityInfo); this.allowRoot = true; + this.setParent(selectors, this); + this.setParent(this.features, this); + this.setParent(this.rules, this); }; -Media.prototype = new Directive(); +Media.prototype = new AtRule(); Media.prototype.type = "Media"; -Media.prototype.isRulesetLike = true; +Media.prototype.isRulesetLike = function() { return true; }; Media.prototype.accept = function (visitor) { if (this.features) { this.features = visitor.visit(this.features); @@ -6810,7 +7578,7 @@ Media.prototype.accept = function (visitor) { } }; Media.prototype.genCSS = function (context, output) { - output.add('@media ', this.currentFileInfo, this.index); + output.add('@media ', this._fileInfo, this._index); this.features.genCSS(context, output); this.outputRuleset(context, output, this.rules); }; @@ -6820,24 +7588,13 @@ Media.prototype.eval = function (context) { context.mediaPath = []; } - var media = new Media(null, [], this.index, this.currentFileInfo, this.visibilityInfo()); + var media = new Media(null, [], this._index, this._fileInfo, this.visibilityInfo()); if (this.debugInfo) { this.rules[0].debugInfo = this.debugInfo; media.debugInfo = this.debugInfo; } - var strictMathBypass = false; - if (!context.strictMath) { - strictMathBypass = true; - context.strictMath = true; - } - try { - media.features = this.features.eval(context); - } - finally { - if (strictMathBypass) { - context.strictMath = false; - } - } + + media.features = this.features.eval(context); context.mediaPath.push(media); context.mediaBlocks.push(media); @@ -6857,10 +7614,11 @@ Media.prototype.evalTop = function (context) { // Render all dependent Media blocks. if (context.mediaBlocks.length > 1) { - var selectors = (new Selector([], null, null, this.index, this.currentFileInfo)).createEmptySelectors(); + var selectors = (new Selector([], null, null, this.getIndex(), this.fileInfo())).createEmptySelectors(); result = new Ruleset(selectors, context.mediaBlocks); result.multiMedia = true; result.copyVisibilityInfo(this.visibilityInfo()); + this.setParent(result, this); } delete context.mediaBlocks; @@ -6897,6 +7655,7 @@ Media.prototype.evalNested = function (context) { return new Expression(path); })); + this.setParent(this.features, this); // Fake a tree-node that doesn't output anything. return new Ruleset([], []); @@ -6921,11 +7680,12 @@ Media.prototype.bubbleSelectors = function (selectors) { if (!selectors) { return; } - this.rules = [new Ruleset(selectors.slice(0), [this.rules[0]])]; + this.rules = [new Ruleset(utils.copyArray(selectors), [this.rules[0]])]; + this.setParent(this.rules, this); }; module.exports = Media; -},{"./anonymous":46,"./directive":57,"./expression":59,"./ruleset":76,"./selector":77,"./value":81}],67:[function(require,module,exports){ +},{"../utils":86,"./anonymous":48,"./atrule":50,"./expression":62,"./ruleset":78,"./selector":79,"./value":83}],70:[function(require,module,exports){ var Node = require("./node"), Selector = require("./selector"), MixinDefinition = require("./mixin-definition"), @@ -6934,10 +7694,11 @@ var Node = require("./node"), var MixinCall = function (elements, args, index, currentFileInfo, important) { this.selector = new Selector(elements); this.arguments = args || []; - this.index = index; - this.currentFileInfo = currentFileInfo; + this._index = index; + this._fileInfo = currentFileInfo; this.important = important; this.allowRoot = true; + this.setParent(this.selector, this); }; MixinCall.prototype = new Node(); MixinCall.prototype.type = "MixinCall"; @@ -7045,7 +7806,7 @@ MixinCall.prototype.eval = function (context) { if ((count[defTrue] + count[defFalse]) > 1) { throw { type: 'Runtime', message: 'Ambiguous use of `default()` found when matching for `' + this.format(args) + '`', - index: this.index, filename: this.currentFileInfo.filename }; + index: this.getIndex(), filename: this.fileInfo().filename }; } } @@ -7063,7 +7824,7 @@ MixinCall.prototype.eval = function (context) { this._setVisibilityToReplacement(newRules); Array.prototype.push.apply(rules, newRules); } catch (e) { - throw { message: e.message, index: this.index, filename: this.currentFileInfo.filename, stack: e.stack }; + throw { message: e.message, index: this.getIndex(), filename: this.fileInfo().filename, stack: e.stack }; } } } @@ -7076,11 +7837,11 @@ MixinCall.prototype.eval = function (context) { if (isOneFound) { throw { type: 'Runtime', message: 'No matching definition was found for `' + this.format(args) + '`', - index: this.index, filename: this.currentFileInfo.filename }; + index: this.getIndex(), filename: this.fileInfo().filename }; } else { throw { type: 'Name', message: this.selector.toCSS().trim() + " is undefined", - index: this.index, filename: this.currentFileInfo.filename }; + index: this.getIndex(), filename: this.fileInfo().filename }; } }; @@ -7110,17 +7871,18 @@ MixinCall.prototype.format = function (args) { }; module.exports = MixinCall; -},{"../functions/default":20,"./mixin-definition":68,"./node":70,"./selector":77}],68:[function(require,module,exports){ +},{"../functions/default":24,"./mixin-definition":71,"./node":73,"./selector":79}],71:[function(require,module,exports){ var Selector = require("./selector"), Element = require("./element"), Ruleset = require("./ruleset"), - Rule = require("./rule"), + Declaration = require("./declaration"), Expression = require("./expression"), - contexts = require("../contexts"); + contexts = require("../contexts"), + utils = require("../utils"); var Definition = function (name, params, rules, condition, variadic, frames, visibilityInfo) { this.name = name; - this.selectors = [new Selector([new Element(null, name, this.index, this.currentFileInfo)])]; + this.selectors = [new Selector([new Element(null, name, this._index, this._fileInfo)])]; this.params = params; this.condition = condition; this.variadic = variadic; @@ -7155,10 +7917,10 @@ Definition.prototype.accept = function (visitor) { } }; Definition.prototype.evalParams = function (context, mixinEnv, args, evaldArguments) { - /*jshint boss:true */ + /* jshint boss:true */ var frame = new Ruleset(null, null), varargs, arg, - params = this.params.slice(0), + params = utils.copyArray(this.params), i, j, val, name, isNamedFound, argIndex, argsLength = 0; if (mixinEnv.frames && mixinEnv.frames[0] && mixinEnv.frames[0].functionRegistry) { @@ -7167,7 +7929,7 @@ Definition.prototype.evalParams = function (context, mixinEnv, args, evaldArgume mixinEnv = new contexts.Eval(mixinEnv, [frame].concat(mixinEnv.frames)); if (args) { - args = args.slice(0); + args = utils.copyArray(args); argsLength = args.length; for (i = 0; i < argsLength; i++) { @@ -7177,7 +7939,7 @@ Definition.prototype.evalParams = function (context, mixinEnv, args, evaldArgume for (j = 0; j < params.length; j++) { if (!evaldArguments[j] && name === params[j].name) { evaldArguments[j] = arg.value.eval(context); - frame.prependRule(new Rule(name, arg.value.eval(context))); + frame.prependRule(new Declaration(name, arg.value.eval(context))); isNamedFound = true; break; } @@ -7205,7 +7967,7 @@ Definition.prototype.evalParams = function (context, mixinEnv, args, evaldArgume for (j = argIndex; j < argsLength; j++) { varargs.push(args[j].value.eval(context)); } - frame.prependRule(new Rule(name, new Expression(varargs).eval(context))); + frame.prependRule(new Declaration(name, new Expression(varargs).eval(context))); } else { val = arg && arg.value; if (val) { @@ -7218,7 +7980,7 @@ Definition.prototype.evalParams = function (context, mixinEnv, args, evaldArgume ' (' + argsLength + ' for ' + this.arity + ')' }; } - frame.prependRule(new Rule(name, val)); + frame.prependRule(new Declaration(name, val)); evaldArguments[i] = val; } } @@ -7245,7 +8007,7 @@ Definition.prototype.makeImportant = function() { return result; }; Definition.prototype.eval = function (context) { - return new Definition(this.name, this.params, this.rules, this.condition, this.variadic, this.frames || context.frames.slice(0)); + return new Definition(this.name, this.params, this.rules, this.condition, this.variadic, this.frames || utils.copyArray(context.frames)); }; Definition.prototype.evalCall = function (context, args, important) { var _arguments = [], @@ -7253,9 +8015,9 @@ Definition.prototype.evalCall = function (context, args, important) { frame = this.evalParams(context, new contexts.Eval(context, mixinFrames), args, _arguments), rules, ruleset; - frame.prependRule(new Rule('@arguments', new Expression(_arguments).eval(context))); + frame.prependRule(new Declaration('@arguments', new Expression(_arguments).eval(context))); - rules = this.rules.slice(0); + rules = utils.copyArray(this.rules); ruleset = new Ruleset(null, rules); ruleset.originalRuleset = this; @@ -7268,7 +8030,7 @@ Definition.prototype.evalCall = function (context, args, important) { Definition.prototype.matchCondition = function (args, context) { if (this.condition && !this.condition.eval( new contexts.Eval(context, - [this.evalParams(context, /* the parameter variables*/ + [this.evalParams(context, /* the parameter variables */ new contexts.Eval(context, this.frames ? this.frames.concat(context.frames) : context.frames), args, [])] .concat(this.frames || []) // the parent namespace/mixin frames .concat(context.frames)))) { // the current environment frames @@ -7286,7 +8048,7 @@ Definition.prototype.matchArgs = function (args, context) { } }, 0); - if (! this.variadic) { + if (!this.variadic) { if (requiredArgsCnt < this.required) { return false; } @@ -7313,7 +8075,7 @@ Definition.prototype.matchArgs = function (args, context) { }; module.exports = Definition; -},{"../contexts":11,"./element":58,"./expression":59,"./rule":74,"./ruleset":76,"./selector":77}],69:[function(require,module,exports){ +},{"../contexts":12,"../utils":86,"./declaration":58,"./element":61,"./expression":62,"./ruleset":78,"./selector":79}],72:[function(require,module,exports){ var Node = require("./node"), Operation = require("./operation"), Dimension = require("./dimension"); @@ -7335,9 +8097,43 @@ Negative.prototype.eval = function (context) { }; module.exports = Negative; -},{"./dimension":56,"./node":70,"./operation":71}],70:[function(require,module,exports){ +},{"./dimension":60,"./node":73,"./operation":74}],73:[function(require,module,exports){ var Node = function() { + this.parent = null; + this.visibilityBlocks = undefined; + this.nodeVisible = undefined; + this.rootNode = null; + this.parsed = null; + + var self = this; + Object.defineProperty(this, "currentFileInfo", { + get: function() { return self.fileInfo(); } + }); + Object.defineProperty(this, "index", { + get: function() { return self.getIndex(); } + }); + +}; +Node.prototype.setParent = function(nodes, parent) { + function set(node) { + if (node && node instanceof Node) { + node.parent = parent; + } + } + if (Array.isArray(nodes)) { + nodes.forEach(set); + } + else { + set(nodes); + } +}; +Node.prototype.getIndex = function() { + return this._index || (this.parent && this.parent.getIndex()) || 0; }; +Node.prototype.fileInfo = function() { + return this._fileInfo || (this.parent && this.parent.fileInfo()) || {}; +}; +Node.prototype.isRulesetLike = function() { return false; }; Node.prototype.toCSS = function (context) { var strs = []; this.genCSS(context, { @@ -7367,8 +8163,8 @@ Node.prototype._operate = function (context, op, a, b) { }; Node.prototype.fround = function(context, value) { var precision = context && context.numPrecision; - //add "epsilon" to ensure numbers like 1.000000005 (represented as 1.000000004999....) are properly rounded... - return (precision == null) ? value : Number((value + 2e-16).toFixed(precision)); + // add "epsilon" to ensure numbers like 1.000000005 (represented as 1.000000004999...) are properly rounded: + return (precision) ? Number((value + 2e-16).toFixed(precision)) : value; }; Node.compare = function (a, b) { /* returns: @@ -7428,13 +8224,13 @@ Node.prototype.removeVisibilityBlock = function () { } this.visibilityBlocks = this.visibilityBlocks - 1; }; -//Turns on node visibility - if called node will be shown in output regardless -//of whether it comes from import by reference or not +// Turns on node visibility - if called node will be shown in output regardless +// of whether it comes from import by reference or not Node.prototype.ensureVisibility = function () { this.nodeVisible = true; }; -//Turns off node visibility - if called node will NOT be shown in output regardless -//of whether it comes from import by reference or not +// Turns off node visibility - if called node will NOT be shown in output regardless +// of whether it comes from import by reference or not Node.prototype.ensureInvisibility = function () { this.nodeVisible = false; }; @@ -7460,7 +8256,7 @@ Node.prototype.copyVisibilityInfo = function(info) { }; module.exports = Node; -},{}],71:[function(require,module,exports){ +},{}],74:[function(require,module,exports){ var Node = require("./node"), Color = require("./color"), Dimension = require("./dimension"); @@ -7488,7 +8284,7 @@ Operation.prototype.eval = function (context) { } if (!a.operate) { throw { type: "Operation", - message: "Operation on an invalid type" }; + message: "Operation on an invalid type" }; } return a.operate(context, this.op, b); @@ -7510,7 +8306,7 @@ Operation.prototype.genCSS = function (context, output) { module.exports = Operation; -},{"./color":50,"./dimension":56,"./node":70}],72:[function(require,module,exports){ +},{"./color":53,"./dimension":60,"./node":73}],75:[function(require,module,exports){ var Node = require("./node"); var Paren = function (node) { @@ -7523,28 +8319,100 @@ Paren.prototype.genCSS = function (context, output) { this.value.genCSS(context, output); output.add(')'); }; -Paren.prototype.eval = function (context) { - return new Paren(this.value.eval(context)); +Paren.prototype.eval = function (context) { + return new Paren(this.value.eval(context)); +}; +module.exports = Paren; + +},{"./node":73}],76:[function(require,module,exports){ +var Node = require("./node"), + Declaration = require("./declaration"); + +var Property = function (name, index, currentFileInfo) { + this.name = name; + this._index = index; + this._fileInfo = currentFileInfo; +}; +Property.prototype = new Node(); +Property.prototype.type = "Property"; +Property.prototype.eval = function (context) { + var property, name = this.name; + // TODO: shorten this reference + var mergeRules = context.pluginManager.less.visitors.ToCSSVisitor.prototype._mergeRules; + + if (this.evaluating) { + throw { type: 'Name', + message: "Recursive property reference for " + name, + filename: this.fileInfo().filename, + index: this.getIndex() }; + } + + this.evaluating = true; + + property = this.find(context.frames, function (frame) { + + var v, vArr = frame.property(name); + if (vArr) { + for (var i = 0; i < vArr.length; i++) { + v = vArr[i]; + + vArr[i] = new Declaration(v.name, + v.value, + v.important, + v.merge, + v.index, + v.currentFileInfo, + v.inline, + v.variable + ); + } + mergeRules(vArr); + + v = vArr[vArr.length - 1]; + if (v.important) { + var importantScope = context.importantScope[context.importantScope.length - 1]; + importantScope.important = v.important; + } + v = v.value.eval(context); + return v; + } + }); + if (property) { + this.evaluating = false; + return property; + } else { + throw { type: 'Name', + message: "Property '" + name + "' is undefined", + filename: this.currentFileInfo.filename, + index: this.index }; + } +}; +Property.prototype.find = function (obj, fun) { + for (var i = 0, r; i < obj.length; i++) { + r = fun.call(obj, obj[i]); + if (r) { return r; } + } + return null; }; -module.exports = Paren; +module.exports = Property; -},{"./node":70}],73:[function(require,module,exports){ +},{"./declaration":58,"./node":73}],77:[function(require,module,exports){ var Node = require("./node"), - JsEvalNode = require("./js-eval-node"), - Variable = require("./variable"); + Variable = require("./variable"), + Property = require("./property"); var Quoted = function (str, content, escaped, index, currentFileInfo) { this.escaped = (escaped == null) ? true : escaped; this.value = content || ''; this.quote = str.charAt(0); - this.index = index; - this.currentFileInfo = currentFileInfo; + this._index = index; + this._fileInfo = currentFileInfo; }; -Quoted.prototype = new JsEvalNode(); +Quoted.prototype = new Node(); Quoted.prototype.type = "Quoted"; Quoted.prototype.genCSS = function (context, output) { if (!this.escaped) { - output.add(this.quote, this.currentFileInfo, this.index); + output.add(this.quote, this.fileInfo(), this.getIndex()); } output.add(this.value); if (!this.escaped) { @@ -7552,15 +8420,16 @@ Quoted.prototype.genCSS = function (context, output) { } }; Quoted.prototype.containsVariables = function() { - return this.value.match(/(`([^`]+)`)|@\{([\w-]+)\}/); + return this.value.match(/@\{([\w-]+)\}/); }; Quoted.prototype.eval = function (context) { var that = this, value = this.value; - var javascriptReplacement = function (_, exp) { - return String(that.evaluateJavaScript(exp, context)); + var variableReplacement = function (_, name) { + var v = new Variable('@' + name, that.getIndex(), that.fileInfo()).eval(context, true); + return (v instanceof Quoted) ? v.value : v.toCSS(); }; - var interpolationReplacement = function (_, name) { - var v = new Variable('@' + name, that.index, that.currentFileInfo).eval(context, true); + var propertyReplacement = function (_, name) { + var v = new Property('$' + name, that.getIndex(), that.fileInfo()).eval(context, true); return (v instanceof Quoted) ? v.value : v.toCSS(); }; function iterativeReplace(value, regexp, replacementFnc) { @@ -7571,9 +8440,9 @@ Quoted.prototype.eval = function (context) { } while (value !== evaluatedValue); return evaluatedValue; } - value = iterativeReplace(value, /`([^`]+)`/g, javascriptReplacement); - value = iterativeReplace(value, /@\{([\w-]+)\}/g, interpolationReplacement); - return new Quoted(this.quote + value + this.quote, value, this.escaped, this.index, this.currentFileInfo); + value = iterativeReplace(value, /@\{([\w-]+)\}/g, variableReplacement); + value = iterativeReplace(value, /\$\{([\w-]+)\}/g, propertyReplacement); + return new Quoted(this.quote + value + this.quote, value, this.escaped, this.getIndex(), this.fileInfo()); }; Quoted.prototype.compare = function (other) { // when comparing quoted strings allow the quote to differ @@ -7585,142 +8454,39 @@ Quoted.prototype.compare = function (other) { }; module.exports = Quoted; -},{"./js-eval-node":64,"./node":70,"./variable":82}],74:[function(require,module,exports){ -var Node = require("./node"), - Value = require("./value"), - Keyword = require("./keyword"); - -var Rule = function (name, value, important, merge, index, currentFileInfo, inline, variable) { - this.name = name; - this.value = (value instanceof Node) ? value : new Value([value]); //value instanceof tree.Value || value instanceof tree.Ruleset ?? - this.important = important ? ' ' + important.trim() : ''; - this.merge = merge; - this.index = index; - this.currentFileInfo = currentFileInfo; - this.inline = inline || false; - this.variable = (variable !== undefined) ? variable - : (name.charAt && (name.charAt(0) === '@')); - this.allowRoot = true; -}; - -function evalName(context, name) { - var value = "", i, n = name.length, - output = {add: function (s) {value += s;}}; - for (i = 0; i < n; i++) { - name[i].eval(context).genCSS(context, output); - } - return value; -} - -Rule.prototype = new Node(); -Rule.prototype.type = "Rule"; -Rule.prototype.genCSS = function (context, output) { - output.add(this.name + (context.compress ? ':' : ': '), this.currentFileInfo, this.index); - try { - this.value.genCSS(context, output); - } - catch(e) { - e.index = this.index; - e.filename = this.currentFileInfo.filename; - throw e; - } - output.add(this.important + ((this.inline || (context.lastRule && context.compress)) ? "" : ";"), this.currentFileInfo, this.index); -}; -Rule.prototype.eval = function (context) { - var strictMathBypass = false, name = this.name, evaldValue, variable = this.variable; - if (typeof name !== "string") { - // expand 'primitive' name directly to get - // things faster (~10% for benchmark.less): - name = (name.length === 1) && (name[0] instanceof Keyword) ? - name[0].value : evalName(context, name); - variable = false; // never treat expanded interpolation as new variable name - } - if (name === "font" && !context.strictMath) { - strictMathBypass = true; - context.strictMath = true; - } - try { - context.importantScope.push({}); - evaldValue = this.value.eval(context); - - if (!this.variable && evaldValue.type === "DetachedRuleset") { - throw { message: "Rulesets cannot be evaluated on a property.", - index: this.index, filename: this.currentFileInfo.filename }; - } - var important = this.important, - importantResult = context.importantScope.pop(); - if (!important && importantResult.important) { - important = importantResult.important; - } - - return new Rule(name, - evaldValue, - important, - this.merge, - this.index, this.currentFileInfo, this.inline, - variable); - } - catch(e) { - if (typeof e.index !== 'number') { - e.index = this.index; - e.filename = this.currentFileInfo.filename; - } - throw e; - } - finally { - if (strictMathBypass) { - context.strictMath = false; - } - } -}; -Rule.prototype.makeImportant = function () { - return new Rule(this.name, - this.value, - "!important", - this.merge, - this.index, this.currentFileInfo, this.inline); -}; - -module.exports = Rule; -},{"./keyword":65,"./node":70,"./value":81}],75:[function(require,module,exports){ +},{"./node":73,"./property":76,"./variable":85}],78:[function(require,module,exports){ var Node = require("./node"), - Variable = require("./variable"); - -var RulesetCall = function (variable) { - this.variable = variable; - this.allowRoot = true; -}; -RulesetCall.prototype = new Node(); -RulesetCall.prototype.type = "RulesetCall"; -RulesetCall.prototype.eval = function (context) { - var detachedRuleset = new Variable(this.variable).eval(context); - return detachedRuleset.callEval(context); -}; -module.exports = RulesetCall; - -},{"./node":70,"./variable":82}],76:[function(require,module,exports){ -var Node = require("./node"), - Rule = require("./rule"), + Declaration = require("./declaration"), + Keyword = require("./keyword"), + Comment = require("./comment"), + Paren = require("./paren"), Selector = require("./selector"), Element = require("./element"), - Paren = require("./paren"), + Anonymous = require("./anonymous"), contexts = require("../contexts"), globalFunctionRegistry = require("../functions/function-registry"), defaultFunc = require("../functions/default"), - getDebugInfo = require("./debug-info"); + getDebugInfo = require("./debug-info"), + utils = require("../utils"); var Ruleset = function (selectors, rules, strictImports, visibilityInfo) { this.selectors = selectors; this.rules = rules; this._lookups = {}; + this._variables = null; + this._properties = null; this.strictImports = strictImports; this.copyVisibilityInfo(visibilityInfo); this.allowRoot = true; + + this.setParent(this.selectors, this); + this.setParent(this.rules, this); + }; Ruleset.prototype = new Node(); Ruleset.prototype.type = "Ruleset"; Ruleset.prototype.isRuleset = true; -Ruleset.prototype.isRulesetLike = true; +Ruleset.prototype.isRulesetLike = function() { return true; }; Ruleset.prototype.accept = function (visitor) { if (this.paths) { this.paths = visitor.visitArray(this.paths, true); @@ -7736,14 +8502,14 @@ Ruleset.prototype.eval = function (context) { selCnt, selector, i, hasOnePassingSelector = false; if (thisSelectors && (selCnt = thisSelectors.length)) { - selectors = []; + selectors = new Array(selCnt); defaultFunc.error({ type: "Syntax", message: "it is currently only allowed in parametric mixin guards," }); for (i = 0; i < selCnt; i++) { selector = thisSelectors[i].eval(context); - selectors.push(selector); + selectors[i] = selector; if (selector.evaldCondition) { hasOnePassingSelector = true; } @@ -7753,7 +8519,7 @@ Ruleset.prototype.eval = function (context) { hasOnePassingSelector = true; } - var rules = this.rules ? this.rules.slice(0) : null, + var rules = this.rules ? utils.copyArray(this.rules) : null, ruleset = new Ruleset(selectors, rules, this.strictImports, this.visibilityInfo()), rule, subRule; @@ -7801,21 +8567,21 @@ Ruleset.prototype.eval = function (context) { // Store the frames around mixin definitions, // so they can be evaluated like closures when the time comes. - var rsRules = ruleset.rules, rsRuleCnt = rsRules ? rsRules.length : 0; - for (i = 0; i < rsRuleCnt; i++) { - if (rsRules[i].evalFirst) { - rsRules[i] = rsRules[i].eval(context); + var rsRules = ruleset.rules; + for (i = 0; (rule = rsRules[i]); i++) { + if (rule.evalFirst) { + rsRules[i] = rule.eval(context); } } var mediaBlockCount = (context.mediaBlocks && context.mediaBlocks.length) || 0; // Evaluate mixin calls. - for (i = 0; i < rsRuleCnt; i++) { - if (rsRules[i].type === "MixinCall") { - /*jshint loopfunc:true */ - rules = rsRules[i].eval(context).filter(function(r) { - if ((r instanceof Rule) && r.variable) { + for (i = 0; (rule = rsRules[i]); i++) { + if (rule.type === "MixinCall") { + /* jshint loopfunc:true */ + rules = rule.eval(context).filter(function(r) { + if ((r instanceof Declaration) && r.variable) { // do not pollute the scope if the variable is // already there. consider returning false here // but we need a way to "return" variable from mixins @@ -7824,47 +8590,44 @@ Ruleset.prototype.eval = function (context) { return true; }); rsRules.splice.apply(rsRules, [i, 1].concat(rules)); - rsRuleCnt += rules.length - 1; i += rules.length - 1; ruleset.resetCache(); - } else if (rsRules[i].type === "RulesetCall") { - /*jshint loopfunc:true */ - rules = rsRules[i].eval(context).rules.filter(function(r) { - if ((r instanceof Rule) && r.variable) { + } else if (rule.type === "VariableCall") { + /* jshint loopfunc:true */ + rules = rule.eval(context).rules.filter(function(r) { + if ((r instanceof Declaration) && r.variable) { // do not pollute the scope at all return false; } return true; }); rsRules.splice.apply(rsRules, [i, 1].concat(rules)); - rsRuleCnt += rules.length - 1; i += rules.length - 1; ruleset.resetCache(); } } // Evaluate everything else - for (i = 0; i < rsRules.length; i++) { - rule = rsRules[i]; + for (i = 0; (rule = rsRules[i]); i++) { if (!rule.evalFirst) { rsRules[i] = rule = rule.eval ? rule.eval(context) : rule; } } // Evaluate everything else - for (i = 0; i < rsRules.length; i++) { - rule = rsRules[i]; + for (i = 0; (rule = rsRules[i]); i++) { // for rulesets, check if it is a css guard and can be removed if (rule instanceof Ruleset && rule.selectors && rule.selectors.length === 1) { // check if it can be folded in (e.g. & where) if (rule.selectors[0].isJustParentSelector()) { rsRules.splice(i--, 1); - for (var j = 0; j < rule.rules.length; j++) { - subRule = rule.rules[j]; - subRule.copyVisibilityInfo(rule.visibilityInfo()); - if (!(subRule instanceof Rule) || !subRule.variable) { - rsRules.splice(++i, 0, subRule); + for (var j = 0; (subRule = rule.rules[j]); j++) { + if (subRule instanceof Node) { + subRule.copyVisibilityInfo(rule.visibilityInfo()); + if (!(subRule instanceof Declaration) || !subRule.variable) { + rsRules.splice(++i, 0, subRule); + } } } } @@ -7892,7 +8655,7 @@ Ruleset.prototype.evalImports = function(context) { importRules = rules[i].eval(context); if (importRules && (importRules.length || importRules.length === 0)) { rules.splice.apply(rules, [i, 1].concat(importRules)); - i+= importRules.length - 1; + i += importRules.length - 1; } else { rules.splice(i, 1, importRules); } @@ -7931,12 +8694,13 @@ Ruleset.prototype.matchCondition = function (args, context) { Ruleset.prototype.resetCache = function () { this._rulesets = null; this._variables = null; + this._properties = null; this._lookups = {}; }; Ruleset.prototype.variables = function () { if (!this._variables) { this._variables = !this.rules ? {} : this.rules.reduce(function (hash, r) { - if (r instanceof Rule && r.variable === true) { + if (r instanceof Declaration && r.variable === true) { hash[r.name] = r; } // when evaluating variables in an import statement, imports have not been eval'd @@ -7955,17 +8719,81 @@ Ruleset.prototype.variables = function () { } return this._variables; }; +Ruleset.prototype.properties = function () { + if (!this._properties) { + this._properties = !this.rules ? {} : this.rules.reduce(function (hash, r) { + if (r instanceof Declaration && r.variable !== true) { + var name = (r.name.length === 1) && (r.name[0] instanceof Keyword) ? + r.name[0].value : r.name; + // Properties don't overwrite as they can merge + if (!hash['$' + name]) { + hash['$' + name] = [ r ]; + } + else { + hash['$' + name].push(r); + } + } + return hash; + }, {}); + } + return this._properties; +}; Ruleset.prototype.variable = function (name) { - return this.variables()[name]; + var decl = this.variables()[name]; + if (decl) { + return this.parseValue(decl); + } +}; +Ruleset.prototype.property = function (name) { + var decl = this.properties()[name]; + if (decl) { + return this.parseValue(decl); + } +}; +Ruleset.prototype.parseValue = function(toParse) { + var self = this; + function transformDeclaration(decl) { + if (decl.value instanceof Anonymous && !decl.parsed) { + this.parse.parseNode( + decl.value.value, + ["value", "important"], + decl.value.getIndex(), + decl.fileInfo(), + function(err, result) { + if (err) { + decl.parsed = true; + } + if (result) { + decl.value = result[0]; + decl.important = result[1] || ''; + decl.parsed = true; + } + }); + + return decl; + } + else { + return decl; + } + } + if (!Array.isArray(toParse)) { + return transformDeclaration.call(self, toParse); + } + else { + var nodes = []; + toParse.forEach(function(n) { + nodes.push(transformDeclaration.call(self, n)); + }); + return nodes; + } }; Ruleset.prototype.rulesets = function () { if (!this.rules) { return []; } - var filtRules = [], rules = this.rules, cnt = rules.length, + var filtRules = [], rules = this.rules, i, rule; - for (i = 0; i < cnt; i++) { - rule = rules[i]; + for (i = 0; (rule = rules[i]); i++) { if (rule.isRuleset) { filtRules.push(rule); } @@ -7980,6 +8808,7 @@ Ruleset.prototype.prependRule = function (rule) { } else { this.rules = [ rule ]; } + this.setParent(rule, this); }; Ruleset.prototype.find = function (selector, self, filter) { self = self || this; @@ -8030,25 +8859,10 @@ Ruleset.prototype.genCSS = function (context, output) { tabSetStr = context.compress ? '' : Array(context.tabLevel).join(" "), sep; - function isRulesetLikeNode(rule) { - // if it has nested rules, then it should be treated like a ruleset - // medias and comments do not have nested rules, but should be treated like rulesets anyway - // some directives and anonymous nodes are ruleset like, others are not - if (typeof rule.isRulesetLike === "boolean") { - return rule.isRulesetLike; - } else if (typeof rule.isRulesetLike === "function") { - return rule.isRulesetLike(); - } - - //anything else is assumed to be a rule - return false; - } - var charsetNodeIndex = 0; var importNodeIndex = 0; - for (i = 0; i < this.rules.length; i++) { - rule = this.rules[i]; - if (rule.type === "Comment") { + for (i = 0; (rule = this.rules[i]); i++) { + if (rule instanceof Comment) { if (importNodeIndex === i) { importNodeIndex++; } @@ -8099,15 +8913,14 @@ Ruleset.prototype.genCSS = function (context, output) { } // Compile rules and rulesets - for (i = 0; i < ruleNodes.length; i++) { - rule = ruleNodes[i]; + for (i = 0; (rule = ruleNodes[i]); i++) { if (i + 1 === ruleNodes.length) { context.lastRule = true; } var currentLastRule = context.lastRule; - if (isRulesetLikeNode(rule)) { + if (rule.isRulesetLike(rule)) { context.lastRule = false; } @@ -8119,7 +8932,7 @@ Ruleset.prototype.genCSS = function (context, output) { context.lastRule = currentLastRule; - if (!context.lastRule) { + if (!context.lastRule && rule.isVisible()) { output.add(context.compress ? '' : ('\n' + tabRuleStr)); } else { context.lastRule = false; @@ -8149,9 +8962,9 @@ Ruleset.prototype.joinSelector = function (paths, context, selector) { if (elementsToPak.length === 0) { replacementParen = new Paren(elementsToPak[0]); } else { - var insideParent = []; + var insideParent = new Array(elementsToPak.length); for (j = 0; j < elementsToPak.length; j++) { - insideParent.push(new Element(null, elementsToPak[j], originalElement.index, originalElement.currentFileInfo)); + insideParent[j] = new Element(null, elementsToPak[j], originalElement._index, originalElement._fileInfo); } replacementParen = new Paren(new Selector(insideParent)); } @@ -8160,7 +8973,7 @@ Ruleset.prototype.joinSelector = function (paths, context, selector) { function createSelector(containedElement, originalElement) { var element, selector; - element = new Element(null, containedElement, originalElement.index, originalElement.currentFileInfo); + element = new Element(null, containedElement, originalElement._index, originalElement._fileInfo); selector = new Selector([element]); return selector; } @@ -8173,12 +8986,12 @@ Ruleset.prototype.joinSelector = function (paths, context, selector) { // our new selector path newSelectorPath = []; - //construct the joined selector - if & is the first thing this will be empty, + // construct the joined selector - if & is the first thing this will be empty, // if not newJoinedSelector will be the last set of elements in the selector if (beginningPath.length > 0) { - newSelectorPath = beginningPath.slice(0); + newSelectorPath = utils.copyArray(beginningPath); lastSelector = newSelectorPath.pop(); - newJoinedSelector = originalSelector.createDerived(lastSelector.elements.slice(0)); + newJoinedSelector = originalSelector.createDerived(utils.copyArray(lastSelector.elements)); } else { newJoinedSelector = originalSelector.createDerived([]); @@ -8194,7 +9007,7 @@ Ruleset.prototype.joinSelector = function (paths, context, selector) { combinator = parentEl.combinator; } // join the elements so far with the first part of the parent - newJoinedSelector.elements.push(new Element(combinator, parentEl.value, replacedElement.index, replacedElement.currentFileInfo)); + newJoinedSelector.elements.push(new Element(combinator, parentEl.value, replacedElement._index, replacedElement._fileInfo)); newJoinedSelector.elements = newJoinedSelector.elements.concat(addPath[0].elements.slice(1)); } @@ -8203,7 +9016,7 @@ Ruleset.prototype.joinSelector = function (paths, context, selector) { newSelectorPath.push(newJoinedSelector); } - //put together the parent selectors after the join (e.g. the rest of the parent) + // put together the parent selectors after the join (e.g. the rest of the parent) if (addPath.length > 1) { var restOfPath = addPath.slice(1); restOfPath = restOfPath.map(function (selector) { @@ -8237,9 +9050,7 @@ Ruleset.prototype.joinSelector = function (paths, context, selector) { return; } - for (i = 0; i < selectors.length; i++) { - sel = selectors[i]; - + for (i = 0; (sel = selectors[i]); i++) { // if the previous thing in sel is a parent this needs to join on to it if (sel.length > 0) { sel[sel.length - 1] = sel[sel.length - 1].createDerived(sel[sel.length - 1].elements.concat(elements)); @@ -8267,12 +9078,12 @@ Ruleset.prototype.joinSelector = function (paths, context, selector) { var i, j, k, currentElements, newSelectors, selectorsMultiplied, sel, el, hadParentSelector = false, length, lastSelector; function findNestedSelector(element) { var maybeSelector; - if (element.value.type !== 'Paren') { + if (!(element.value instanceof Paren)) { return null; } maybeSelector = element.value.value; - if (maybeSelector.type !== 'Selector') { + if (!(maybeSelector instanceof Selector)) { return null; } @@ -8288,8 +9099,7 @@ Ruleset.prototype.joinSelector = function (paths, context, selector) { [] ]; - for (i = 0; i < inSelector.elements.length; i++) { - el = inSelector.elements[i]; + for (i = 0; (el = inSelector.elements[i]); i++) { // non parent reference elements just get added if (el.value !== "&") { var nestedSelector = findNestedSelector(el); @@ -8301,7 +9111,7 @@ Ruleset.prototype.joinSelector = function (paths, context, selector) { var nestedPaths = [], replaced, replacedNewSelectors = []; replaced = replaceParentSelector(nestedPaths, context, nestedSelector); hadParentSelector = hadParentSelector || replaced; - //the nestedPaths array should have only one member - replaceParentSelector does not multiply selectors + // the nestedPaths array should have only one member - replaceParentSelector does not multiply selectors for (k = 0; k < nestedPaths.length; k++) { var replacementSelector = createSelector(createParenthesis(nestedPaths[k], el), el); addAllReplacementsIntoPath(newSelectors, [replacementSelector], el, inSelector, replacedNewSelectors); @@ -8331,7 +9141,7 @@ Ruleset.prototype.joinSelector = function (paths, context, selector) { // the combinator used on el should now be applied to the next element instead so that // it is not lost if (sel.length > 0) { - sel[0].elements.push(new Element(el.combinator, '', el.index, el.currentFileInfo)); + sel[0].elements.push(new Element(el.combinator, '', el._index, el._fileInfo)); } selectorsMultiplied.push(sel); } @@ -8363,7 +9173,6 @@ Ruleset.prototype.joinSelector = function (paths, context, selector) { paths.push(newSelectors[i]); lastSelector = newSelectors[i][length - 1]; newSelectors[i][length - 1] = lastSelector.createDerived(lastSelector.elements, inSelector.extendList); - //newSelectors[i][length - 1].copyVisibilityInfo(inSelector.visibilityInfo()); } } @@ -8386,12 +9195,7 @@ Ruleset.prototype.joinSelector = function (paths, context, selector) { if (context.length > 0) { newPaths = []; for (i = 0; i < context.length; i++) { - //var concatenated = []; - //context[i].forEach(function(entry) { - // var newEntry = entry.createDerived(entry.elements, entry.extendList, entry.evaldCondition); - // newEntry.copyVisibilityInfo(selector.visibilityInfo()); - // concatenated.push(newEntry); - //}, this); + var concatenated = context[i].map(deriveSelector.bind(this, selector.visibilityInfo())); concatenated.push(selector); @@ -8410,19 +9214,21 @@ Ruleset.prototype.joinSelector = function (paths, context, selector) { }; module.exports = Ruleset; -},{"../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){ +},{"../contexts":12,"../functions/default":24,"../functions/function-registry":26,"../utils":86,"./anonymous":48,"./comment":55,"./debug-info":57,"./declaration":58,"./element":61,"./keyword":68,"./node":73,"./paren":75,"./selector":79}],79:[function(require,module,exports){ var Node = require("./node"), - Element = require("./element"); + Element = require("./element"), + LessError = require("../less-error"); var Selector = function (elements, extendList, condition, index, currentFileInfo, visibilityInfo) { - this.elements = elements; this.extendList = extendList; this.condition = condition; - this.currentFileInfo = currentFileInfo || {}; - if (!condition) { - this.evaldCondition = true; - } + this.evaldCondition = !condition; + this._index = index; + this._fileInfo = currentFileInfo; + this.elements = this.getElements(elements); + this.mixinElements_ = undefined; this.copyVisibilityInfo(visibilityInfo); + this.setParent(this.elements, this); }; Selector.prototype = new Node(); Selector.prototype.type = "Selector"; @@ -8438,16 +9244,35 @@ Selector.prototype.accept = function (visitor) { } }; Selector.prototype.createDerived = function(elements, extendList, evaldCondition) { - var info = this.visibilityInfo(); - evaldCondition = (evaldCondition != null) ? evaldCondition : this.evaldCondition; - var newSelector = new Selector(elements, extendList || this.extendList, null, this.index, this.currentFileInfo, info); - newSelector.evaldCondition = evaldCondition; + elements = this.getElements(elements); + var newSelector = new Selector(elements, extendList || this.extendList, + null, this.getIndex(), this.fileInfo(), this.visibilityInfo()); + newSelector.evaldCondition = (evaldCondition != null) ? evaldCondition : this.evaldCondition; newSelector.mediaEmpty = this.mediaEmpty; return newSelector; }; +Selector.prototype.getElements = function(els) { + if (typeof els === "string") { + this.parse.parseNode( + els, + ["selector"], + this._index, + this._fileInfo, + function(err, result) { + if (err) { + throw new LessError({ + index: err.index, + message: err.message + }, this.parse.imports, this._fileInfo.filename); + } + els = result[0].elements; + }); + } + return els; +}; Selector.prototype.createEmptySelectors = function() { - var el = new Element('', '&', this.index, this.currentFileInfo), - sels = [new Selector([el], null, null, this.index, this.currentFileInfo)]; + var el = new Element('', '&', this._index, this._fileInfo), + sels = [new Selector([el], null, null, this._index, this._fileInfo)]; sels[0].mediaEmpty = true; return sels; }; @@ -8456,14 +9281,13 @@ Selector.prototype.match = function (other) { len = elements.length, olen, i; - other.CacheElements(); - - olen = other._elements.length; + other = other.mixinElements(); + olen = other.length; if (olen === 0 || len < olen) { return 0; } else { for (i = 0; i < olen; i++) { - if (elements[i].value !== other._elements[i]) { + if (elements[i].value !== other[i]) { return 0; } } @@ -8471,9 +9295,9 @@ Selector.prototype.match = function (other) { return olen; // return number of matched elements }; -Selector.prototype.CacheElements = function() { - if (this._elements) { - return; +Selector.prototype.mixinElements = function() { + if (this.mixinElements_) { + return this.mixinElements_; } var elements = this.elements.map( function(v) { @@ -8488,7 +9312,7 @@ Selector.prototype.CacheElements = function() { elements = []; } - this._elements = elements; + return (this.mixinElements_ = elements); }; Selector.prototype.isJustParentSelector = function() { return !this.mediaEmpty && @@ -8508,14 +9332,11 @@ Selector.prototype.eval = function (context) { Selector.prototype.genCSS = function (context, output) { var i, element; if ((!context || !context.firstSelector) && this.elements[0].combinator.value === "") { - output.add(' ', this.currentFileInfo, this.index); + output.add(' ', this.fileInfo(), this.getIndex()); } - if (!this._css) { - //TODO caching? speed comparison? - for (i = 0; i < this.elements.length; i++) { - element = this.elements[i]; - element.genCSS(context, output); - } + for (i = 0; i < this.elements.length; i++) { + element = this.elements[i]; + element.genCSS(context, output); } }; Selector.prototype.getIsOutput = function() { @@ -8523,7 +9344,7 @@ Selector.prototype.getIsOutput = function() { }; module.exports = Selector; -},{"./element":58,"./node":70}],78:[function(require,module,exports){ +},{"../less-error":36,"./element":61,"./node":73}],80:[function(require,module,exports){ var Node = require("./node"); var UnicodeDescriptor = function (value) { @@ -8534,13 +9355,14 @@ UnicodeDescriptor.prototype.type = "UnicodeDescriptor"; module.exports = UnicodeDescriptor; -},{"./node":70}],79:[function(require,module,exports){ +},{"./node":73}],81:[function(require,module,exports){ var Node = require("./node"), - unitConversions = require("../data/unit-conversions"); + unitConversions = require("../data/unit-conversions"), + utils = require("../utils"); var Unit = function (numerator, denominator, backupUnit) { - this.numerator = numerator ? numerator.slice(0).sort() : []; - this.denominator = denominator ? denominator.slice(0).sort() : []; + this.numerator = numerator ? utils.copyArray(numerator).sort() : []; + this.denominator = denominator ? utils.copyArray(denominator).sort() : []; if (backupUnit) { this.backupUnit = backupUnit; } else if (numerator && numerator.length) { @@ -8551,7 +9373,7 @@ var Unit = function (numerator, denominator, backupUnit) { Unit.prototype = new Node(); Unit.prototype.type = "Unit"; Unit.prototype.clone = function () { - return new Unit(this.numerator.slice(0), this.denominator.slice(0), this.backupUnit); + return new Unit(utils.copyArray(this.numerator), utils.copyArray(this.denominator), this.backupUnit); }; Unit.prototype.genCSS = function (context, output) { // Dimension checks the unit is singular and throws an error if in strict math mode. @@ -8601,7 +9423,7 @@ Unit.prototype.usedUnits = function() { var group, result = {}, mapUnit, groupName; mapUnit = function (atomicUnit) { - /*jshint loopfunc:true */ + /* jshint loopfunc:true */ if (group.hasOwnProperty(atomicUnit) && !result[groupName]) { result[groupName] = atomicUnit; } @@ -8656,13 +9478,13 @@ Unit.prototype.cancel = function () { }; module.exports = Unit; -},{"../data/unit-conversions":14,"./node":70}],80:[function(require,module,exports){ +},{"../data/unit-conversions":15,"../utils":86,"./node":73}],82:[function(require,module,exports){ var Node = require("./node"); var URL = function (val, index, currentFileInfo, isEvald) { this.value = val; - this.currentFileInfo = currentFileInfo; - this.index = index; + this._index = index; + this._fileInfo = currentFileInfo; this.isEvald = isEvald; }; URL.prototype = new Node(); @@ -8681,7 +9503,7 @@ URL.prototype.eval = function (context) { if (!this.isEvald) { // Add the base path if the URL is relative - rootpath = this.currentFileInfo && this.currentFileInfo.rootpath; + rootpath = this.fileInfo() && this.fileInfo().rootpath; if (rootpath && typeof val.value === "string" && context.isPathRelative(val.value)) { @@ -8708,18 +9530,23 @@ URL.prototype.eval = function (context) { } } - return new URL(val, this.index, this.currentFileInfo, true); + return new URL(val, this.getIndex(), this.fileInfo(), true); }; module.exports = URL; -},{"./node":70}],81:[function(require,module,exports){ +},{"./node":73}],83:[function(require,module,exports){ var Node = require("./node"); var Value = function (value) { - this.value = value; if (!value) { throw new Error("Value requires an array argument"); } + if (!Array.isArray(value)) { + this.value = [ value ]; + } + else { + this.value = value; + } }; Value.prototype = new Node(); Value.prototype.type = "Value"; @@ -8748,13 +9575,29 @@ Value.prototype.genCSS = function (context, output) { }; module.exports = Value; -},{"./node":70}],82:[function(require,module,exports){ +},{"./node":73}],84:[function(require,module,exports){ +var Node = require("./node"), + Variable = require("./variable"); + +var VariableCall = function (variable) { + this.variable = variable; + this.allowRoot = true; +}; +VariableCall.prototype = new Node(); +VariableCall.prototype.type = "VariableCall"; +VariableCall.prototype.eval = function (context) { + var detachedRuleset = new Variable(this.variable).eval(context); + return detachedRuleset.callEval(context); +}; +module.exports = VariableCall; + +},{"./node":73,"./variable":85}],85:[function(require,module,exports){ var Node = require("./node"); var Variable = function (name, index, currentFileInfo) { this.name = name; - this.index = index; - this.currentFileInfo = currentFileInfo || {}; + this._index = index; + this._fileInfo = currentFileInfo; }; Variable.prototype = new Node(); Variable.prototype.type = "Variable"; @@ -8762,14 +9605,14 @@ Variable.prototype.eval = function (context) { var variable, name = this.name; if (name.indexOf('@@') === 0) { - name = '@' + new Variable(name.slice(1), this.index, this.currentFileInfo).eval(context).value; + name = '@' + new Variable(name.slice(1), this.getIndex(), this.fileInfo()).eval(context).value; } if (this.evaluating) { throw { type: 'Name', - message: "Recursive variable definition for " + name, - filename: this.currentFileInfo.filename, - index: this.index }; + message: "Recursive variable definition for " + name, + filename: this.fileInfo().filename, + index: this.getIndex() }; } this.evaluating = true; @@ -8789,9 +9632,9 @@ Variable.prototype.eval = function (context) { return variable; } else { throw { type: 'Name', - message: "variable " + name + " is undefined", - filename: this.currentFileInfo.filename, - index: this.index }; + message: "variable " + name + " is undefined", + filename: this.fileInfo().filename, + index: this.getIndex() }; } }; Variable.prototype.find = function (obj, fun) { @@ -8803,7 +9646,8 @@ Variable.prototype.find = function (obj, fun) { }; module.exports = Variable; -},{"./node":70}],83:[function(require,module,exports){ +},{"./node":73}],86:[function(require,module,exports){ +/* jshint proto: true */ module.exports = { getLocation: function(index, inputStream) { var n = index + 1, @@ -8822,15 +9666,64 @@ module.exports = { line: line, column: column }; + }, + copyArray: function(arr) { + var i, length = arr.length, + copy = new Array(length); + + for (i = 0; i < length; i++) { + copy[i] = arr[i]; + } + return copy; + }, + clone: function (obj) { + var cloned = {}; + for (var prop in obj) { + if (obj.hasOwnProperty(prop)) { + cloned[prop] = obj[prop]; + } + } + return cloned; + }, + defaults: function(obj1, obj2) { + if (!obj2._defaults || obj2._defaults !== obj1) { + for (var prop in obj1) { + if (obj1.hasOwnProperty(prop)) { + if (!obj2.hasOwnProperty(prop)) { + obj2[prop] = obj1[prop]; + } + else if (Array.isArray(obj1[prop]) + && Array.isArray(obj2[prop])) { + + obj1[prop].forEach(function(p) { + if (obj2[prop].indexOf(p) === -1) { + obj2[prop].push(p); + } + }); + } + } + } + } + obj2._defaults = obj1; + return obj2; + }, + merge: function(obj1, obj2) { + for (var prop in obj2) { + if (obj2.hasOwnProperty(prop)) { + obj1[prop] = obj2[prop]; + } + } + return obj1; } }; -},{}],84:[function(require,module,exports){ +},{}],87:[function(require,module,exports){ var tree = require("../tree"), Visitor = require("./visitor"), - logger = require("../logger"); + logger = require("../logger"), + utils = require("../utils"); -/*jshint loopfunc:true */ +/* jshint loopfunc:true */ var ExtendFinderVisitor = function() { this._visitor = new Visitor(this); @@ -8844,7 +9737,7 @@ ExtendFinderVisitor.prototype = { root.allExtends = this.allExtendsStack[0]; return root; }, - visitRule: function (ruleNode, visitArgs) { + visitDeclaration: function (declNode, visitArgs) { visitArgs.visitDeeper = false; }, visitMixinDefinition: function (mixinDefinitionNode, visitArgs) { @@ -8874,7 +9767,7 @@ ExtendFinderVisitor.prototype = { selector = selectorPath[selectorPath.length - 1], selExtendList = selector.extendList; - extendList = selExtendList ? selExtendList.slice(0).concat(allSelectorsExtendList) + extendList = selExtendList ? utils.copyArray(selExtendList).concat(allSelectorsExtendList) : allSelectorsExtendList; if (extendList) { @@ -8907,11 +9800,11 @@ ExtendFinderVisitor.prototype = { visitMediaOut: function (mediaNode) { this.allExtendsStack.length = this.allExtendsStack.length - 1; }, - visitDirective: function (directiveNode, visitArgs) { - directiveNode.allExtends = []; - this.allExtendsStack.push(directiveNode.allExtends); + visitAtRule: function (atRuleNode, visitArgs) { + atRuleNode.allExtends = []; + this.allExtendsStack.push(atRuleNode.allExtends); }, - visitDirectiveOut: function (directiveNode) { + visitAtRuleOut: function (atRuleNode) { this.allExtendsStack.length = this.allExtendsStack.length - 1; } }; @@ -8937,17 +9830,17 @@ ProcessExtendsVisitor.prototype = { extendList.filter(function(extend) { return !extend.hasFoundMatches && extend.parent_ids.length == 1; }).forEach(function(extend) { - var selector = "_unknown_"; - try { - selector = extend.selector.toCSS({}); - } - catch(_) {} + var selector = "_unknown_"; + try { + selector = extend.selector.toCSS({}); + } + catch (_) {} - if (!indices[extend.index + ' ' + selector]) { - indices[extend.index + ' ' + selector] = true; - logger.warn("extend '" + selector + "' has no matches"); - } - }); + if (!indices[extend.index + ' ' + selector]) { + indices[extend.index + ' ' + selector] = true; + logger.warn("extend '" + selector + "' has no matches"); + } + }); }, doExtendChaining: function (extendsList, extendsListTarget, iterationCount) { // @@ -8964,7 +9857,7 @@ ProcessExtendsVisitor.prototype = { iterationCount = iterationCount || 0; - //loop through comparing every extend with every target extend. + // loop through comparing every extend with every target extend. // a target extend is the one on the ruleset we are looking at copy/edit/pasting in place // e.g. .a:extend(.b) {} and .b:extend(.c) {} then the first extend extends the second one // and the second is the target. @@ -8994,7 +9887,7 @@ ProcessExtendsVisitor.prototype = { newSelector = extendVisitor.extendSelector(matches, selectorPath, selfSelector, extend.isVisible()); // but now we create a new extend from it - newExtend = new(tree.Extend)(targetExtend.selector, targetExtend.option, 0, targetExtend.currentFileInfo, info); + newExtend = new(tree.Extend)(targetExtend.selector, targetExtend.option, 0, targetExtend.fileInfo(), info); newExtend.selfSelectors = newSelector; // add the extend onto the list of extends for that selector @@ -9030,7 +9923,7 @@ ProcessExtendsVisitor.prototype = { selectorOne = extendsToAdd[0].selfSelectors[0].toCSS(); selectorTwo = extendsToAdd[0].selector.toCSS(); } - catch(e) {} + catch (e) {} throw { message: "extend circular reference detected. One of the circular extends is currently:" + selectorOne + ":extend(" + selectorTwo + ")"}; } @@ -9042,7 +9935,7 @@ ProcessExtendsVisitor.prototype = { return extendsToAdd; } }, - visitRule: function (ruleNode, visitArgs) { + visitDeclaration: function (ruleNode, visitArgs) { visitArgs.visitDeeper = false; }, visitMixinDefinition: function (mixinDefinitionNode, visitArgs) { @@ -9195,7 +10088,7 @@ ProcessExtendsVisitor.prototype = { }, extendSelector:function (matches, selectorPath, replacementSelector, isVisible) { - //for a set of matches, replace each match with the replacement selector + // for a set of matches, replace each match with the replacement selector var currentSelectorPathIndex = 0, currentSelectorPathElementIndex = 0, @@ -9212,8 +10105,8 @@ ProcessExtendsVisitor.prototype = { firstElement = new tree.Element( match.initialCombinator, replacementSelector.elements[0].value, - replacementSelector.elements[0].index, - replacementSelector.elements[0].currentFileInfo + replacementSelector.elements[0].getIndex(), + replacementSelector.elements[0].fileInfo() ); if (match.pathIndex > currentSelectorPathIndex && currentSelectorPathElementIndex > 0) { @@ -9274,12 +10167,12 @@ ProcessExtendsVisitor.prototype = { var lastIndex = this.allExtendsStack.length - 1; this.allExtendsStack.length = lastIndex; }, - visitDirective: function (directiveNode, visitArgs) { - var newAllExtends = directiveNode.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length - 1]); - newAllExtends = newAllExtends.concat(this.doExtendChaining(newAllExtends, directiveNode.allExtends)); + visitAtRule: function (atRuleNode, visitArgs) { + var newAllExtends = atRuleNode.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length - 1]); + newAllExtends = newAllExtends.concat(this.doExtendChaining(newAllExtends, atRuleNode.allExtends)); this.allExtendsStack.push(newAllExtends); }, - visitDirectiveOut: function (directiveNode) { + visitAtRuleOut: function (atRuleNode) { var lastIndex = this.allExtendsStack.length - 1; this.allExtendsStack.length = lastIndex; } @@ -9287,7 +10180,7 @@ ProcessExtendsVisitor.prototype = { module.exports = ProcessExtendsVisitor; -},{"../logger":33,"../tree":62,"./visitor":91}],85:[function(require,module,exports){ +},{"../logger":37,"../tree":65,"../utils":86,"./visitor":94}],88:[function(require,module,exports){ function ImportSequencer(onSequencerEmpty) { this.imports = []; this.variableImports = []; @@ -9343,10 +10236,11 @@ ImportSequencer.prototype.tryRun = function() { module.exports = ImportSequencer; -},{}],86:[function(require,module,exports){ +},{}],89:[function(require,module,exports){ var contexts = require("../contexts"), Visitor = require("./visitor"), - ImportSequencer = require("./import-sequencer"); + ImportSequencer = require("./import-sequencer"), + utils = require("../utils"); var ImportVisitor = function(importer, finish) { @@ -9367,7 +10261,7 @@ ImportVisitor.prototype = { // process the contents this._visitor.visit(root); } - catch(e) { + catch (e) { this.error = e; } @@ -9385,7 +10279,7 @@ ImportVisitor.prototype = { if (!importNode.css || inlineCSS) { - var context = new contexts.Eval(this.context, this.context.frames.slice(0)); + var context = new contexts.Eval(this.context, utils.copyArray(this.context.frames)); var importParent = context.frames[0]; this.importCount++; @@ -9403,8 +10297,8 @@ ImportVisitor.prototype = { try { evaldImportNode = importNode.evalForImport(context); - } catch(e) { - if (!e.filename) { e.index = importNode.index; e.filename = importNode.currentFileInfo.filename; } + } catch (e) { + if (!e.filename) { e.index = importNode.getIndex(); e.filename = importNode.fileInfo().filename; } // attempt to eval properly and treat as css importNode.css = true; // if that fails, this error will be thrown @@ -9430,7 +10324,7 @@ ImportVisitor.prototype = { var onImported = this.onImported.bind(this, evaldImportNode, context), sequencedOnImported = this._sequencer.addImport(onImported); - this._importer.push(evaldImportNode.getPath(), tryAppendLessExtension, evaldImportNode.currentFileInfo, + this._importer.push(evaldImportNode.getPath(), tryAppendLessExtension, evaldImportNode.fileInfo(), evaldImportNode.options, sequencedOnImported); } else { this.importCount--; @@ -9442,14 +10336,14 @@ ImportVisitor.prototype = { onImported: function (importNode, context, e, root, importedAtRoot, fullPath) { if (e) { if (!e.filename) { - e.index = importNode.index; e.filename = importNode.currentFileInfo.filename; + e.index = importNode.getIndex(); e.filename = importNode.fileInfo().filename; } this.error = e; } var importVisitor = this, inlineCSS = importNode.options.inline, - isPlugin = importNode.options.plugin, + isPlugin = importNode.options.isPlugin, isOptional = importNode.options.optional, duplicateImport = importedAtRoot || fullPath in importVisitor.recursionDetector; @@ -9495,22 +10389,22 @@ ImportVisitor.prototype = { importVisitor._sequencer.tryRun(); } }, - visitRule: function (ruleNode, visitArgs) { - if (ruleNode.value.type === "DetachedRuleset") { - this.context.frames.unshift(ruleNode); + visitDeclaration: function (declNode, visitArgs) { + if (declNode.value.type === "DetachedRuleset") { + this.context.frames.unshift(declNode); } else { visitArgs.visitDeeper = false; } }, - visitRuleOut : function(ruleNode) { - if (ruleNode.value.type === "DetachedRuleset") { + visitDeclarationOut: function(declNode) { + if (declNode.value.type === "DetachedRuleset") { this.context.frames.shift(); } }, - visitDirective: function (directiveNode, visitArgs) { - this.context.frames.unshift(directiveNode); + visitAtRule: function (atRuleNode, visitArgs) { + this.context.frames.unshift(atRuleNode); }, - visitDirectiveOut: function (directiveNode) { + visitAtRuleOut: function (atRuleNode) { this.context.frames.shift(); }, visitMixinDefinition: function (mixinDefinitionNode, visitArgs) { @@ -9534,7 +10428,7 @@ ImportVisitor.prototype = { }; module.exports = ImportVisitor; -},{"../contexts":11,"./import-sequencer":85,"./visitor":91}],87:[function(require,module,exports){ +},{"../contexts":12,"../utils":86,"./import-sequencer":88,"./visitor":94}],90:[function(require,module,exports){ var visitors = { Visitor: require("./visitor"), ImportVisitor: require('./import-visitor'), @@ -9546,7 +10440,7 @@ var visitors = { module.exports = visitors; -},{"./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){ +},{"./extend-visitor":87,"./import-visitor":89,"./join-selector-visitor":91,"./set-tree-visibility-visitor":92,"./to-css-visitor":93,"./visitor":94}],91:[function(require,module,exports){ var Visitor = require("./visitor"); var JoinSelectorVisitor = function() { @@ -9558,7 +10452,7 @@ JoinSelectorVisitor.prototype = { run: function (root) { return this._visitor.visit(root); }, - visitRule: function (ruleNode, visitArgs) { + visitDeclaration: function (declNode, visitArgs) { visitArgs.visitDeeper = false; }, visitMixinDefinition: function (mixinDefinitionNode, visitArgs) { @@ -9571,7 +10465,7 @@ JoinSelectorVisitor.prototype = { this.contexts.push(paths); - if (! rulesetNode.root) { + if (!rulesetNode.root) { selectors = rulesetNode.selectors; if (selectors) { selectors = selectors.filter(function(selector) { return selector.getIsOutput(); }); @@ -9589,17 +10483,17 @@ JoinSelectorVisitor.prototype = { var context = this.contexts[this.contexts.length - 1]; mediaNode.rules[0].root = (context.length === 0 || context[0].multiMedia); }, - visitDirective: function (directiveNode, visitArgs) { + visitAtRule: function (atRuleNode, visitArgs) { var context = this.contexts[this.contexts.length - 1]; - if (directiveNode.rules && directiveNode.rules.length) { - directiveNode.rules[0].root = (directiveNode.isRooted || context.length === 0 || null); + if (atRuleNode.rules && atRuleNode.rules.length) { + atRuleNode.rules[0].root = (atRuleNode.isRooted || context.length === 0 || null); } } }; module.exports = JoinSelectorVisitor; -},{"./visitor":91}],89:[function(require,module,exports){ +},{"./visitor":94}],92:[function(require,module,exports){ var SetTreeVisibilityVisitor = function(visible) { this.visible = visible; }; @@ -9638,7 +10532,7 @@ SetTreeVisibilityVisitor.prototype.visit = function(node) { return node; }; module.exports = SetTreeVisibilityVisitor; -},{}],90:[function(require,module,exports){ +},{}],93:[function(require,module,exports){ var tree = require("../tree"), Visitor = require("./visitor"); @@ -9650,14 +10544,14 @@ var CSSVisitorUtils = function(context) { CSSVisitorUtils.prototype = { containsSilentNonBlockedChild: function(bodyRules) { var rule; - if (bodyRules == null) { + if (!bodyRules) { return false; } for (var r = 0; r < bodyRules.length; r++) { rule = bodyRules[r]; if (rule.isSilent && rule.isSilent(this._context) && !rule.blocksVisibility()) { - //the directive contains something that was referenced (likely by extend) - //therefore it needs to be shown in output too + // the atrule contains something that was referenced (likely by extend) + // therefore it needs to be shown in output too return true; } } @@ -9665,28 +10559,21 @@ CSSVisitorUtils.prototype = { }, keepOnlyVisibleChilds: function(owner) { - if (owner == null || owner.rules == null) { - return ; - } - - owner.rules = owner.rules.filter(function(thing) { + if (owner && owner.rules) { + owner.rules = owner.rules.filter(function(thing) { return thing.isVisible(); - } - ); + }); + } }, isEmpty: function(owner) { - if (owner == null || owner.rules == null) { - return true; - } - return owner.rules.length === 0; + return (owner && owner.rules) + ? (owner.rules.length === 0) : true; }, hasVisibleSelector: function(rulesetNode) { - if (rulesetNode == null || rulesetNode.paths == null) { - return false; - } - return rulesetNode.paths.length > 0; + return (rulesetNode && rulesetNode.paths) + ? (rulesetNode.paths.length > 0) : false; }, resolveVisibility: function (node, originalRules) { @@ -9741,11 +10628,11 @@ ToCSSVisitor.prototype = { return this._visitor.visit(root); }, - visitRule: function (ruleNode, visitArgs) { - if (ruleNode.blocksVisibility() || ruleNode.variable) { + visitDeclaration: function (declNode, visitArgs) { + if (declNode.blocksVisibility() || declNode.variable) { return; } - return ruleNode; + return declNode; }, visitMixinDefinition: function (mixinNode, visitArgs) { @@ -9779,56 +10666,63 @@ ToCSSVisitor.prototype = { return importNode; }, - visitDirective: function(directiveNode, visitArgs) { - if (directiveNode.rules && directiveNode.rules.length) { - return this.visitDirectiveWithBody(directiveNode, visitArgs); + visitAtRule: function(atRuleNode, visitArgs) { + if (atRuleNode.rules && atRuleNode.rules.length) { + return this.visitAtRuleWithBody(atRuleNode, visitArgs); } else { - return this.visitDirectiveWithoutBody(directiveNode, visitArgs); + return this.visitAtRuleWithoutBody(atRuleNode, visitArgs); + } + }, + + visitAnonymous: function(anonymousNode, visitArgs) { + if (!anonymousNode.blocksVisibility()) { + anonymousNode.accept(this._visitor); + return anonymousNode; } }, - visitDirectiveWithBody: function(directiveNode, visitArgs) { - //if there is only one nested ruleset and that one has no path, then it is - //just fake ruleset - function hasFakeRuleset(directiveNode) { - var bodyRules = directiveNode.rules; + visitAtRuleWithBody: function(atRuleNode, visitArgs) { + // if there is only one nested ruleset and that one has no path, then it is + // just fake ruleset + function hasFakeRuleset(atRuleNode) { + var bodyRules = atRuleNode.rules; return bodyRules.length === 1 && (!bodyRules[0].paths || bodyRules[0].paths.length === 0); } - function getBodyRules(directiveNode) { - var nodeRules = directiveNode.rules; - if (hasFakeRuleset(directiveNode)) { + function getBodyRules(atRuleNode) { + var nodeRules = atRuleNode.rules; + if (hasFakeRuleset(atRuleNode)) { return nodeRules[0].rules; } return nodeRules; } - //it is still true that it is only one ruleset in array - //this is last such moment - //process childs - var originalRules = getBodyRules(directiveNode); - directiveNode.accept(this._visitor); + // it is still true that it is only one ruleset in array + // this is last such moment + // process childs + var originalRules = getBodyRules(atRuleNode); + atRuleNode.accept(this._visitor); visitArgs.visitDeeper = false; - if (!this.utils.isEmpty(directiveNode)) { - this._mergeRules(directiveNode.rules[0].rules); + if (!this.utils.isEmpty(atRuleNode)) { + this._mergeRules(atRuleNode.rules[0].rules); } - return this.utils.resolveVisibility(directiveNode, originalRules); + return this.utils.resolveVisibility(atRuleNode, originalRules); }, - visitDirectiveWithoutBody: function(directiveNode, visitArgs) { - if (directiveNode.blocksVisibility()) { + visitAtRuleWithoutBody: function(atRuleNode, visitArgs) { + if (atRuleNode.blocksVisibility()) { return; } - if (directiveNode.name === "@charset") { + if (atRuleNode.name === "@charset") { // Only output the debug info together with subsequent @charset definitions - // a comment (or @media statement) before the actual @charset directive would + // a comment (or @media statement) before the actual @charset atrule would // be considered illegal css as it has to be on the first line if (this.charset) { - if (directiveNode.debugInfo) { - var comment = new tree.Comment("/* " + directiveNode.toCSS(this._context).replace(/\n/g, "") + " */\n"); - comment.debugInfo = directiveNode.debugInfo; + if (atRuleNode.debugInfo) { + var comment = new tree.Comment("/* " + atRuleNode.toCSS(this._context).replace(/\n/g, "") + " */\n"); + comment.debugInfo = atRuleNode.debugInfo; return this._visitor.visit(comment); } return; @@ -9836,7 +10730,7 @@ ToCSSVisitor.prototype = { this.charset = true; } - return directiveNode; + return atRuleNode; }, checkValidNodes: function(rules, isRoot) { @@ -9846,29 +10740,29 @@ ToCSSVisitor.prototype = { for (var i = 0; i < rules.length; i++) { var ruleNode = rules[i]; - if (isRoot && ruleNode instanceof tree.Rule && !ruleNode.variable) { + if (isRoot && ruleNode instanceof tree.Declaration && !ruleNode.variable) { throw { message: "Properties must be inside selector blocks. They cannot be in the root", - index: ruleNode.index, filename: ruleNode.currentFileInfo && ruleNode.currentFileInfo.filename}; + index: ruleNode.getIndex(), filename: ruleNode.fileInfo() && ruleNode.fileInfo().filename}; } if (ruleNode instanceof tree.Call) { throw { message: "Function '" + ruleNode.name + "' is undefined", - index: ruleNode.index, filename: ruleNode.currentFileInfo && ruleNode.currentFileInfo.filename}; + index: ruleNode.getIndex(), filename: ruleNode.fileInfo() && ruleNode.fileInfo().filename}; } if (ruleNode.type && !ruleNode.allowRoot) { throw { message: ruleNode.type + " node returned by a function is not valid here", - index: ruleNode.index, filename: ruleNode.currentFileInfo && ruleNode.currentFileInfo.filename}; + index: ruleNode.getIndex(), filename: ruleNode.fileInfo() && ruleNode.fileInfo().filename}; } } }, visitRuleset: function (rulesetNode, visitArgs) { - //at this point rulesets are nested into each other + // at this point rulesets are nested into each other var rule, rulesets = []; this.checkValidNodes(rulesetNode.rules, rulesetNode.firstRoot); - if (! rulesetNode.root) { - //remove invisible paths + if (!rulesetNode.root) { + // remove invisible paths this._compileRulesetPaths(rulesetNode); // remove rulesets from this ruleset body and compile them separately @@ -9894,7 +10788,7 @@ ToCSSVisitor.prototype = { } visitArgs.visitDeeper = false; - } else { //if (! rulesetNode.root) { + } else { // if (! rulesetNode.root) { rulesetNode.accept(this._visitor); visitArgs.visitDeeper = false; } @@ -9904,7 +10798,7 @@ ToCSSVisitor.prototype = { this._removeDuplicateRules(rulesetNode.rules); } - //now decide whether we keep the ruleset + // now decide whether we keep the ruleset if (this.utils.isVisibleRuleset(rulesetNode)) { rulesetNode.ensureVisibility(); rulesets.splice(0, 0, rulesetNode); @@ -9943,12 +10837,12 @@ ToCSSVisitor.prototype = { for (i = rules.length - 1; i >= 0 ; i--) { rule = rules[i]; - if (rule instanceof tree.Rule) { + if (rule instanceof tree.Declaration) { if (!ruleCache[rule.name]) { ruleCache[rule.name] = rule; } else { ruleList = ruleCache[rule.name]; - if (ruleList instanceof tree.Rule) { + if (ruleList instanceof tree.Declaration) { ruleList = ruleCache[rule.name] = [ruleCache[rule.name].toCSS(this._context)]; } var ruleCSS = rule.toCSS(this._context); @@ -9962,78 +10856,45 @@ ToCSSVisitor.prototype = { } }, - _mergeRules: function (rules) { - if (!rules) { return; } - - var groups = {}, - parts, - rule, - key; + _mergeRules: function(rules) { + if (!rules) { + return; + } + var groups = {}, + groupsArr = []; + for (var i = 0; i < rules.length; i++) { - rule = rules[i]; - - if ((rule instanceof tree.Rule) && rule.merge) { - key = [rule.name, - rule.important ? "!" : ""].join(","); - - if (!groups[key]) { - groups[key] = []; - } else { - rules.splice(i--, 1); - } - + var rule = rules[i]; + if (rule.merge) { + var key = rule.name; + groups[key] ? rules.splice(i--, 1) : + groupsArr.push(groups[key] = []); groups[key].push(rule); } } - Object.keys(groups).map(function (k) { - - function toExpression(values) { - return new (tree.Expression)(values.map(function (p) { - return p.value; - })); - } - - function toValue(values) { - return new (tree.Value)(values.map(function (p) { - return p; - })); - } - - parts = groups[k]; - - if (parts.length > 1) { - rule = parts[0]; - var spacedGroups = []; - var lastSpacedGroup = []; - parts.map(function (p) { - if (p.merge === "+") { - if (lastSpacedGroup.length > 0) { - spacedGroups.push(toExpression(lastSpacedGroup)); - } - lastSpacedGroup = []; + groupsArr.forEach(function(group) { + if (group.length > 0) { + var result = group[0], + space = [], + comma = [new tree.Expression(space)]; + group.forEach(function(rule) { + if ((rule.merge === '+') && (space.length > 0)) { + comma.push(new tree.Expression(space = [])); } - lastSpacedGroup.push(p); + space.push(rule.value); + result.important = result.important || rule.important; }); - spacedGroups.push(toExpression(lastSpacedGroup)); - rule.value = toValue(spacedGroups); + result.value = new tree.Value(comma); } }); - }, - - visitAnonymous: function(anonymousNode, visitArgs) { - if (anonymousNode.blocksVisibility()) { - return ; - } - anonymousNode.accept(this._visitor); - return anonymousNode; } }; module.exports = ToCSSVisitor; -},{"../tree":62,"./visitor":91}],91:[function(require,module,exports){ +},{"../tree":65,"./visitor":94}],94:[function(require,module,exports){ var tree = require("../tree"); var _visitArgs = { visitDeeper: true }, @@ -10046,21 +10907,21 @@ function _noop(node) { function indexNodeTypes(parent, ticker) { // add .typeIndex to tree node types for lookup table var key, child; - for (key in parent) { - if (parent.hasOwnProperty(key)) { - child = parent[key]; - switch (typeof child) { - case "function": - // ignore bound functions directly on tree which do not have a prototype - // or aren't nodes - if (child.prototype && child.prototype.type) { - child.prototype.typeIndex = ticker++; - } - break; - case "object": - ticker = indexNodeTypes(child, ticker); - break; - } + for (key in parent) { + /* eslint guard-for-in: 0 */ + child = parent[key]; + switch (typeof child) { + case "function": + // ignore bound functions directly on tree which do not have a prototype + // or aren't nodes + if (child.prototype && child.prototype.type) { + child.prototype.typeIndex = ticker++; + } + break; + case "object": + ticker = indexNodeTypes(child, ticker); + break; + } } return ticker; @@ -10187,7 +11048,7 @@ Visitor.prototype = { }; module.exports = Visitor; -},{"../tree":62}],92:[function(require,module,exports){ +},{"../tree":65}],95:[function(require,module,exports){ "use strict"; // rawAsap provides everything we need except exception management. @@ -10255,7 +11116,7 @@ RawTask.prototype.call = function () { } }; -},{"./raw":93}],93:[function(require,module,exports){ +},{"./raw":96}],96:[function(require,module,exports){ (function (global){ "use strict"; @@ -10482,7 +11343,7 @@ rawAsap.makeRequestCallFromTimer = makeRequestCallFromTimer; // https://github.com/tildeio/rsvp.js/blob/cddf7232546a9cf858524b75cde6f9edf72620a7/lib/rsvp/asap.js }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],94:[function(require,module,exports){ +},{}],97:[function(require,module,exports){ 'use strict'; var asap = require('asap/raw'); @@ -10697,7 +11558,7 @@ function doResolve(fn, promise) { } } -},{"asap/raw":93}],95:[function(require,module,exports){ +},{"asap/raw":96}],98:[function(require,module,exports){ 'use strict'; //This file contains the ES6 extensions to the core Promises/A+ API @@ -10806,7 +11667,7 @@ Promise.prototype['catch'] = function (onRejected) { return this.then(null, onRejected); }; -},{"./core.js":94}],96:[function(require,module,exports){ +},{"./core.js":97}],99:[function(require,module,exports){ // should work in any browser without browserify if (typeof Promise.prototype.done !== 'function') { @@ -10819,7 +11680,7 @@ if (typeof Promise.prototype.done !== 'function') { }) } } -},{}],97:[function(require,module,exports){ +},{}],100:[function(require,module,exports){ // not "use strict" so we can declare global "Promise" var asap = require('asap'); @@ -10831,5 +11692,5 @@ if (typeof Promise === 'undefined') { require('./polyfill-done.js'); -},{"./lib/core.js":94,"./lib/es6-extensions.js":95,"./polyfill-done.js":96,"asap":92}]},{},[2])(2) +},{"./lib/core.js":97,"./lib/es6-extensions.js":98,"./polyfill-done.js":99,"asap":95}]},{},[2])(2) }); \ No newline at end of file diff --git a/dist/less.min.js b/dist/less.min.js index 0f9143ac8..90aa4b646 100644 --- a/dist/less.min.js +++ b/dist/less.min.js @@ -1,8 +1,8 @@ /*! - * Less - Leaner CSS v2.7.3 + * Less - Leaner CSS v3.0.0 * http://lesscss.org * - * Copyright (c) 2009-2017, Alexis Sellier + * Copyright (c) 2009-2018, Alexis Sellier * Licensed under the Apache-2.0 License. * */ @@ -10,8 +10,8 @@ /** * @license Apache-2.0 */ -!function(a){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=a();else if("function"==typeof define&&define.amd)define([],a);else{var b;b="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,b.less=a()}}(function(){return function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);var j=new Error("Cannot find module '"+g+"'");throw j.code="MODULE_NOT_FOUND",j}var k=c[g]={exports:{}};b[g][0].call(k.exports,function(a){var c=b[g][1][a];return e(c?c:a)},k,k.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g0||b.isFileProtocol?"development":"production");var c=/!dumpLineNumbers:(comments|mediaquery|all)/.exec(a.location.hash);c&&(b.dumpLineNumbers=c[1]),void 0===b.useFileCache&&(b.useFileCache=!0),void 0===b.onReady&&(b.onReady=!0)}},{"./browser":3,"./utils":10}],2:[function(a,b,c){function d(a){a.filename&&console.warn(a),e.async||h.removeChild(i)}a("promise/polyfill.js");var e=window.less||{};a("./add-default-options")(window,e);var f=b.exports=a("./index")(window,e);window.less=f;var g,h,i;e.onReady&&(/!watch/.test(window.location.hash)&&f.watch(),e.async||(g="body { display: none !important }",h=document.head||document.getElementsByTagName("head")[0],i=document.createElement("style"),i.type="text/css",i.styleSheet?i.styleSheet.cssText=g:i.appendChild(document.createTextNode(g)),h.appendChild(i)),f.registerStylesheetsImmediately(),f.pageLoadFinished=f.refresh("development"===f.env).then(d,d))},{"./add-default-options":1,"./index":8,"promise/polyfill.js":97}],3:[function(a,b,c){var d=a("./utils");b.exports={createCSS:function(a,b,c){var e=c.href||"",f="less:"+(c.title||d.extractId(e)),g=a.getElementById(f),h=!1,i=a.createElement("style");i.setAttribute("type","text/css"),c.media&&i.setAttribute("media",c.media),i.id=f,i.styleSheet||(i.appendChild(a.createTextNode(b)),h=null!==g&&g.childNodes.length>0&&i.childNodes.length>0&&g.firstChild.nodeValue===i.firstChild.nodeValue);var j=a.getElementsByTagName("head")[0];if(null===g||h===!1){var k=c&&c.nextSibling||null;k?k.parentNode.insertBefore(i,k):j.appendChild(i)}if(g&&h===!1&&g.parentNode.removeChild(g),i.styleSheet)try{i.styleSheet.cssText=b}catch(l){throw new Error("Couldn't reassign styleSheet.cssText.")}},currentScript:function(a){var b=a.document;return b.currentScript||function(){var a=b.getElementsByTagName("script");return a[a.length-1]}()}}},{"./utils":10}],4:[function(a,b,c){b.exports=function(a,b,c){var d=null;if("development"!==b.env)try{d="undefined"==typeof a.localStorage?null:a.localStorage}catch(e){}return{setCSS:function(a,b,e,f){if(d){c.info("saving "+a+" to cache.");try{d.setItem(a,f),d.setItem(a+":timestamp",b),e&&d.setItem(a+":vars",JSON.stringify(e))}catch(g){c.error('failed to save "'+a+'" to local storage for caching.')}}},getCSS:function(a,b,c){var e=d&&d.getItem(a),f=d&&d.getItem(a+":timestamp"),g=d&&d.getItem(a+":vars");if(c=c||{},f&&b.lastModified&&new Date(b.lastModified).valueOf()===new Date(f).valueOf()&&(!c&&!g||JSON.stringify(c)===g))return e}}}},{}],5:[function(a,b,c){var d=a("./utils"),e=a("./browser");b.exports=function(a,b,c){function f(b,f){var g,h,i="less-error-message:"+d.extractId(f||""),j='
  • {content}
  • ',k=a.document.createElement("div"),l=[],m=b.filename||f,n=m.match(/([^\/]+(\?.*)?)$/)[1];k.id=i,k.className="less-error-message",h="

    "+(b.type||"Syntax")+"Error: "+(b.message||"There is an error in your .less file")+'

    in '+n+" ";var o=function(a,b,c){void 0!==a.extract[b]&&l.push(j.replace(/\{line\}/,(parseInt(a.line,10)||0)+(b-1)).replace(/\{class\}/,c).replace(/\{content\}/,a.extract[b]))};b.extract&&(o(b,0,""),o(b,1,"line"),o(b,2,""),h+="on line "+b.line+", column "+(b.column+1)+":

      "+l.join("")+"
    "),b.stack&&(b.extract||c.logLevel>=4)&&(h+="
    Stack Trace
    "+b.stack.split("\n").slice(1).join("
    ")),k.innerHTML=h,e.createCSS(a.document,[".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #dd6666;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.line {","color: #ff0000;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),k.style.cssText=["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),"development"===c.env&&(g=setInterval(function(){var b=a.document,c=b.body;c&&(b.getElementById(i)?c.replaceChild(k,b.getElementById(i)):c.insertBefore(k,c.firstChild),clearInterval(g))},10))}function g(b){var c=a.document.getElementById("less-error-message:"+d.extractId(b));c&&c.parentNode.removeChild(c)}function h(a){}function i(a){c.errorReporting&&"html"!==c.errorReporting?"console"===c.errorReporting?h(a):"function"==typeof c.errorReporting&&c.errorReporting("remove",a):g(a)}function j(a,d){var e="{line} {content}",f=a.filename||d,g=[],h=(a.type||"Syntax")+"Error: "+(a.message||"There is an error in your .less file")+" in "+f+" ",i=function(a,b,c){void 0!==a.extract[b]&&g.push(e.replace(/\{line\}/,(parseInt(a.line,10)||0)+(b-1)).replace(/\{class\}/,c).replace(/\{content\}/,a.extract[b]))};a.extract&&(i(a,0,""),i(a,1,"line"),i(a,2,""),h+="on line "+a.line+", column "+(a.column+1)+":\n"+g.join("\n")),a.stack&&(a.extract||c.logLevel>=4)&&(h+="\nStack Trace\n"+a.stack),b.logger.error(h)}function k(a,b){c.errorReporting&&"html"!==c.errorReporting?"console"===c.errorReporting?j(a,b):"function"==typeof c.errorReporting&&c.errorReporting("add",a,b):f(a,b)}return{add:k,remove:i}}},{"./browser":3,"./utils":10}],6:[function(a,b,c){b.exports=function(b,c){function d(){if(window.XMLHttpRequest&&!("file:"===window.location.protocol&&"ActiveXObject"in window))return new XMLHttpRequest;try{return new ActiveXObject("Microsoft.XMLHTTP")}catch(a){return c.error("browser doesn't support AJAX."),null}}var e=a("../less/environment/abstract-file-manager.js"),f={},g=function(){};return g.prototype=new e,g.prototype.alwaysMakePathsAbsolute=function(){return!0},g.prototype.join=function(a,b){return a?this.extractUrlParts(b,a).path:b},g.prototype.doXHR=function(a,e,f,g){function h(b,c,d){b.status>=200&&b.status<300?c(b.responseText,b.getResponseHeader("Last-Modified")):"function"==typeof d&&d(b.status,a)}var i=d(),j=!b.isFileProtocol||b.fileAsync;"function"==typeof i.overrideMimeType&&i.overrideMimeType("text/css"),c.debug("XHR: Getting '"+a+"'"),i.open("GET",a,j),i.setRequestHeader("Accept",e||"text/x-less, text/css; q=0.9, */*; q=0.5"),i.send(null),b.isFileProtocol&&!b.fileAsync?0===i.status||i.status>=200&&i.status<300?f(i.responseText):g(i.status,a):j?i.onreadystatechange=function(){4==i.readyState&&h(i,f,g)}:h(i,f,g)},g.prototype.supports=function(a,b,c,d){return!0},g.prototype.clearFileCache=function(){f={}},g.prototype.loadFile=function(a,b,c,d,e){b&&!this.isPathAbsolute(a)&&(a=b+a),c=c||{};var g=this.extractUrlParts(a,window.location.href),h=g.url;if(c.useFileCache&&f[h])try{var i=f[h];e(null,{contents:i,filename:h,webInfo:{lastModified:new Date}})}catch(j){e({filename:h,message:"Error loading file "+h+" error was "+j.message})}else this.doXHR(h,c.mime,function(a,b){f[h]=a,e(null,{contents:a,filename:h,webInfo:{lastModified:b}})},function(a,b){e({type:"File",message:"'"+b+"' wasn't found ("+a+")",href:h})})},g}},{"../less/environment/abstract-file-manager.js":15}],7:[function(a,b,c){b.exports=function(){function b(){throw{type:"Runtime",message:"Image size functions are not supported in browser version of less"}}var c=a("./../less/functions/function-registry"),d={"image-size":function(a){return b(this,a),-1},"image-width":function(a){return b(this,a),-1},"image-height":function(a){return b(this,a),-1}};c.addMultiple(d)}},{"./../less/functions/function-registry":22}],8:[function(a,b,c){var d=a("./utils").addDataAttr,e=a("./browser");b.exports=function(b,c){function f(a){return c.postProcessor&&"function"==typeof c.postProcessor&&(a=c.postProcessor.call(a,a)||a),a}function g(a){var b={};for(var c in a)a.hasOwnProperty(c)&&(b[c]=a[c]);return b}function h(a,b){var c=Array.prototype.slice.call(arguments,2);return function(){var d=c.concat(Array.prototype.slice.call(arguments,0));return a.apply(b,d)}}function i(a){for(var b,d=m.getElementsByTagName("style"),e=0;e=c&&console.log(a)},info:function(a){b.logLevel>=d&&console.log(a)},warn:function(a){b.logLevel>=e&&console.warn(a)},error:function(a){b.logLevel>=f&&console.error(a)}}]);for(var g=0;g0&&(a=a.slice(0,b)),b=a.lastIndexOf("/"),b<0&&(b=a.lastIndexOf("\\")),b<0?"":a.slice(0,b+1)},d.prototype.tryAppendExtension=function(a,b){return/(\.[a-z]*$)|([\?;].*)$/.test(a)?a:a+b},d.prototype.tryAppendLessExtension=function(a){return this.tryAppendExtension(a,".less")},d.prototype.supportsSync=function(){return!1},d.prototype.alwaysMakePathsAbsolute=function(){return!1},d.prototype.isPathAbsolute=function(a){return/^(?:[a-z-]+:|\/|\\|#)/i.test(a)},d.prototype.join=function(a,b){return a?a+b:b},d.prototype.pathDiff=function(a,b){var c,d,e,f,g=this.extractUrlParts(a),h=this.extractUrlParts(b),i="";if(g.hostPart!==h.hostPart)return"";for(d=Math.max(h.directories.length,g.directories.length),c=0;c0&&(h.splice(c-1,2),c-=2)}return g.hostPart=f[1],g.directories=h,g.path=(f[1]||"")+h.join("/"),g.fileUrl=g.path+(f[4]||""),g.url=g.fileUrl+(f[5]||""),g},b.exports=d},{}],16:[function(a,b,c){var d=a("../logger"),e=function(a,b){this.fileManagers=b||[],a=a||{};for(var c=["encodeBase64","mimeLookup","charsetLookup","getSourceMapGenerator"],d=[],e=d.concat(c),f=0;f=0;h--){var i=g[h];if(i[f?"supportsSync":"supports"](a,b,c,e))return i}return null},e.prototype.addFileManager=function(a){this.fileManagers.push(a)},e.prototype.clearFileManagers=function(){this.fileManagers=[]},b.exports=e},{"../logger":33}],17:[function(a,b,c){function d(a,b,c){var d,f,g,h,i=b.alpha,j=c.alpha,k=[];g=j+i*(1-j);for(var l=0;l<3;l++)d=b.rgb[l]/255,f=c.rgb[l]/255,h=a(d,f),g&&(h=(j*f+i*(d-j*(d+f-h)))/g),k[l]=255*h;return new e(k,g)}var e=a("../tree/color"),f=a("./function-registry"),g={multiply:function(a,b){return a*b},screen:function(a,b){return a+b-a*b},overlay:function(a,b){return a*=2,a<=1?g.multiply(a,b):g.screen(a-1,b)},softlight:function(a,b){var c=1,d=a;return b>.5&&(d=1,c=a>.25?Math.sqrt(a):((16*a-12)*a+4)*a),a-(1-2*b)*d*(c-a)},hardlight:function(a,b){return g.overlay(b,a)},difference:function(a,b){return Math.abs(a-b)},exclusion:function(a,b){return a+b-2*a*b},average:function(a,b){return(a+b)/2},negation:function(a,b){return 1-Math.abs(a+b-1)}};for(var h in g)g.hasOwnProperty(h)&&(d[h]=d.bind(null,g[h]));f.addMultiple(d)},{"../tree/color":50,"./function-registry":22}],18:[function(a,b,c){function d(a){return Math.min(1,Math.max(0,a))}function e(a){return h.hsla(a.h,a.s,a.l,a.a)}function f(a){if(a instanceof i)return parseFloat(a.unit.is("%")?a.value/100:a.value);if("number"==typeof a)return a;throw{type:"Argument",message:"color functions take numbers as parameters"}}function g(a,b){return a instanceof i&&a.unit.is("%")?parseFloat(a.value*b/100):f(a)}var h,i=a("../tree/dimension"),j=a("../tree/color"),k=a("../tree/quoted"),l=a("../tree/anonymous"),m=a("./function-registry");h={rgb:function(a,b,c){return h.rgba(a,b,c,1)},rgba:function(a,b,c,d){var e=[a,b,c].map(function(a){return g(a,255)});return d=f(d),new j(e,d)},hsl:function(a,b,c){return h.hsla(a,b,c,1)},hsla:function(a,b,c,e){function g(a){return a=a<0?a+1:a>1?a-1:a,6*a<1?i+(j-i)*a*6:2*a<1?j:3*a<2?i+(j-i)*(2/3-a)*6:i}var i,j;return a=f(a)%360/360,b=d(f(b)),c=d(f(c)),e=d(f(e)),j=c<=.5?c*(b+1):c+b-c*b,i=2*c-j,h.rgba(255*g(a+1/3),255*g(a),255*g(a-1/3),e)},hsv:function(a,b,c){return h.hsva(a,b,c,1)},hsva:function(a,b,c,d){a=f(a)%360/360*360,b=f(b),c=f(c),d=f(d);var e,g;e=Math.floor(a/60%6),g=a/60-e;var i=[c,c*(1-b),c*(1-g*b),c*(1-(1-g)*b)],j=[[0,3,1],[2,0,1],[1,0,3],[1,2,0],[3,1,0],[0,1,2]];return h.rgba(255*i[j[e][0]],255*i[j[e][1]],255*i[j[e][2]],d)},hue:function(a){return new i(a.toHSL().h)},saturation:function(a){return new i(100*a.toHSL().s,"%")},lightness:function(a){return new i(100*a.toHSL().l,"%")},hsvhue:function(a){return new i(a.toHSV().h)},hsvsaturation:function(a){return new i(100*a.toHSV().s,"%")},hsvvalue:function(a){return new i(100*a.toHSV().v,"%")},red:function(a){return new i(a.rgb[0])},green:function(a){return new i(a.rgb[1])},blue:function(a){return new i(a.rgb[2])},alpha:function(a){return new i(a.toHSL().a)},luma:function(a){return new i(a.luma()*a.alpha*100,"%")},luminance:function(a){var b=.2126*a.rgb[0]/255+.7152*a.rgb[1]/255+.0722*a.rgb[2]/255;return new i(b*a.alpha*100,"%")},saturate:function(a,b,c){if(!a.rgb)return null;var f=a.toHSL();return f.s+="undefined"!=typeof c&&"relative"===c.value?f.s*b.value/100:b.value/100,f.s=d(f.s),e(f)},desaturate:function(a,b,c){var f=a.toHSL();return f.s-="undefined"!=typeof c&&"relative"===c.value?f.s*b.value/100:b.value/100,f.s=d(f.s),e(f)},lighten:function(a,b,c){var f=a.toHSL();return f.l+="undefined"!=typeof c&&"relative"===c.value?f.l*b.value/100:b.value/100,f.l=d(f.l),e(f)},darken:function(a,b,c){var f=a.toHSL();return f.l-="undefined"!=typeof c&&"relative"===c.value?f.l*b.value/100:b.value/100,f.l=d(f.l),e(f)},fadein:function(a,b,c){var f=a.toHSL();return f.a+="undefined"!=typeof c&&"relative"===c.value?f.a*b.value/100:b.value/100,f.a=d(f.a),e(f)},fadeout:function(a,b,c){var f=a.toHSL();return f.a-="undefined"!=typeof c&&"relative"===c.value?f.a*b.value/100:b.value/100,f.a=d(f.a),e(f)},fade:function(a,b){var c=a.toHSL();return c.a=b.value/100,c.a=d(c.a),e(c)},spin:function(a,b){var c=a.toHSL(),d=(c.h+b.value)%360;return c.h=d<0?360+d:d,e(c)},mix:function(a,b,c){a.toHSL&&b.toHSL||(console.log(b.type),console.dir(b)),c||(c=new i(50));var d=c.value/100,e=2*d-1,f=a.toHSL().a-b.toHSL().a,g=((e*f==-1?e:(e+f)/(1+e*f))+1)/2,h=1-g,k=[a.rgb[0]*g+b.rgb[0]*h,a.rgb[1]*g+b.rgb[1]*h,a.rgb[2]*g+b.rgb[2]*h],l=a.alpha*d+b.alpha*(1-d);return new j(k,l)},greyscale:function(a){return h.desaturate(a,new i(100))},contrast:function(a,b,c,d){if(!a.rgb)return null;if("undefined"==typeof c&&(c=h.rgba(255,255,255,1)),"undefined"==typeof b&&(b=h.rgba(0,0,0,1)),b.luma()>c.luma()){var e=c;c=b,b=e}return d="undefined"==typeof d?.43:f(d),a.luma()=t&&this.context.ieCompat!==!1?(g.warn("Skipped data-uri embedding of "+i+" because its size ("+s.length+" characters) exceeds IE8-safe "+t+" characters!"),f(this,e||a)):new d(new c('"'+s+'"',s,(!1),this.index,this.currentFileInfo),this.index,this.currentFileInfo)})}},{"../logger":33,"../tree/quoted":73,"../tree/url":80,"./function-registry":22}],20:[function(a,b,c){var d=a("../tree/keyword"),e=a("./function-registry"),f={eval:function(){var a=this.value_,b=this.error_;if(b)throw b;if(null!=a)return a?d.True:d.False},value:function(a){this.value_=a},error:function(a){this.error_=a},reset:function(){this.value_=this.error_=null}};e.add("default",f.eval.bind(f)),b.exports=f},{"../tree/keyword":65,"./function-registry":22}],21:[function(a,b,c){var d=a("../tree/expression"),e=function(a,b,c,d){this.name=a.toLowerCase(),this.index=c,this.context=b,this.currentFileInfo=d,this.func=b.frames[0].functionRegistry.get(this.name)};e.prototype.isValid=function(){return Boolean(this.func)},e.prototype.call=function(a){return Array.isArray(a)&&(a=a.filter(function(a){return"Comment"!==a.type}).map(function(a){if("Expression"===a.type){var b=a.value.filter(function(a){return"Comment"!==a.type});return 1===b.length?b[0]:new d(b)}return a})),this.func.apply(this,a)},b.exports=e},{"../tree/expression":59}],22:[function(a,b,c){function d(a){return{_data:{},add:function(a,b){a=a.toLowerCase(),this._data.hasOwnProperty(a),this._data[a]=b},addMultiple:function(a){Object.keys(a).forEach(function(b){this.add(b,a[b])}.bind(this))},get:function(b){return this._data[b]||a&&a.get(b)},inherit:function(){return d(this)}}}b.exports=d(null)},{}],23:[function(a,b,c){b.exports=function(b){var c={functionRegistry:a("./function-registry"),functionCaller:a("./function-caller")};return a("./default"),a("./color"),a("./color-blending"),a("./data-uri")(b),a("./math"),a("./number"),a("./string"),a("./svg")(b),a("./types"),c}},{"./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(a,b,c){var d=a("../tree/dimension"),e=function(){};e._math=function(a,b,c){if(!(c instanceof d))throw{type:"Argument",message:"argument must be a number"};return null==b?b=c.unit:c=c.unify(),new d(a(parseFloat(c.value)),b)},b.exports=e},{"../tree/dimension":56}],25:[function(a,b,c){var d=a("./function-registry"),e=a("./math-helper.js"),f={ceil:null,floor:null,sqrt:null,abs:null,tan:"",sin:"",cos:"",atan:"rad",asin:"rad",acos:"rad"};for(var g in f)f.hasOwnProperty(g)&&(f[g]=e._math.bind(null,Math[g],f[g]));f.round=function(a,b){var c="undefined"==typeof b?0:b.value;return e._math(function(a){return a.toFixed(c)},null,a)},d.addMultiple(f)},{"./function-registry":22,"./math-helper.js":24}],26:[function(a,b,c){var d=a("../tree/dimension"),e=a("../tree/anonymous"),f=a("./function-registry"),g=a("./math-helper.js"),h=function(a,b){switch(b=Array.prototype.slice.call(b),b.length){case 0:throw{type:"Argument",message:"one or more arguments required"}}var c,f,g,h,i,j,k,l,m=[],n={};for(c=0;ci.value)&&(m[f]=g);else{if(void 0!==k&&j!==k)throw{type:"Argument",message:"incompatible types"};n[j]=m.length,m.push(g)}else Array.isArray(b[c].value)&&Array.prototype.push.apply(b,Array.prototype.slice.call(b[c].value));return 1==m.length?m[0]:(b=m.map(function(a){return a.toCSS(this.context)}).join(this.context.compress?",":", "),new e((a?"min":"max")+"("+b+")"))};f.addMultiple({min:function(){return h(!0,arguments)},max:function(){return h(!1,arguments)},convert:function(a,b){return a.convertTo(b.value)},pi:function(){return new d(Math.PI)},mod:function(a,b){return new d(a.value%b.value,a.unit)},pow:function(a,b){if("number"==typeof a&&"number"==typeof b)a=new d(a),b=new d(b);else if(!(a instanceof d&&b instanceof d))throw{type:"Argument",message:"arguments must be numbers"};return new d(Math.pow(a.value,b.value),a.unit)},percentage:function(a){var b=g._math(function(a){return 100*a},"%",a);return b}})},{"../tree/anonymous":46,"../tree/dimension":56,"./function-registry":22,"./math-helper.js":24}],27:[function(a,b,c){var d=a("../tree/quoted"),e=a("../tree/anonymous"),f=a("../tree/javascript"),g=a("./function-registry");g.addMultiple({e:function(a){return new e(a instanceof f?a.evaluated:a.value)},escape:function(a){return new e(encodeURI(a.value).replace(/=/g,"%3D").replace(/:/g,"%3A").replace(/#/g,"%23").replace(/;/g,"%3B").replace(/\(/g,"%28").replace(/\)/g,"%29"))},replace:function(a,b,c,e){var f=a.value;return c="Quoted"===c.type?c.value:c.toCSS(),f=f.replace(new RegExp(b.value,e?e.value:""),c),new d(a.quote||"",f,a.escaped)},"%":function(a){for(var b=Array.prototype.slice.call(arguments,1),c=a.value,e=0;e",k=0;k";return j+="',j=encodeURIComponent(j),j="data:image/svg+xml,"+j,new g(new f("'"+j+"'",j,(!1),this.index,this.currentFileInfo),this.index,this.currentFileInfo)})}},{"../tree/color":50,"../tree/dimension":56,"../tree/expression":59,"../tree/quoted":73,"../tree/url":80,"./function-registry":22}],29:[function(a,b,c){var d=a("../tree/keyword"),e=a("../tree/detached-ruleset"),f=a("../tree/dimension"),g=a("../tree/color"),h=a("../tree/quoted"),i=a("../tree/anonymous"),j=a("../tree/url"),k=a("../tree/operation"),l=a("./function-registry"),m=function(a,b){return a instanceof b?d.True:d.False},n=function(a,b){if(void 0===b)throw{type:"Argument",message:"missing the required second argument to isunit."};if(b="string"==typeof b.value?b.value:b,"string"!=typeof b)throw{type:"Argument",message:"Second argument to isunit should be a unit or a string."};return a instanceof f&&a.unit.is(b)?d.True:d.False},o=function(a){var b=Array.isArray(a.value)?a.value:Array(a);return b};l.addMultiple({isruleset:function(a){return m(a,e)},iscolor:function(a){return m(a,g)},isnumber:function(a){return m(a,f)},isstring:function(a){return m(a,h)},iskeyword:function(a){return m(a,d)},isurl:function(a){return m(a,j)},ispixel:function(a){return n(a,"px")},ispercentage:function(a){return n(a,"%")},isem:function(a){return n(a,"em")},isunit:n,unit:function(a,b){if(!(a instanceof f))throw{type:"Argument",message:"the first argument to unit must be a number"+(a instanceof k?". Have you forgotten parenthesis?":"")};return b=b?b instanceof d?b.value:b.toCSS():"",new f(a.value,b)},"get-unit":function(a){return new i(a.unit)},extract:function(a,b){return b=b.value-1,o(a)[b]},length:function(a){return new f(o(a).length)}})},{"../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(a,b,c){var d=a("./contexts"),e=a("./parser/parser"),f=a("./plugins/function-importer");b.exports=function(a){var b=function(a,b){this.rootFilename=b.filename,this.paths=a.paths||[],this.contents={},this.contentsIgnoredChars={},this.mime=a.mime,this.error=null,this.context=a,this.queue=[],this.files={}};return b.prototype.push=function(b,c,g,h,i){var j=this;this.queue.push(b);var k=function(a,c,d){j.queue.splice(j.queue.indexOf(b),1);var e=d===j.rootFilename;h.optional&&a?i(null,{rules:[]},!1,null):(j.files[d]=c,a&&!j.error&&(j.error=a),i(a,c,e,d))},l={relativeUrls:this.context.relativeUrls,entryPath:g.entryPath,rootpath:g.rootpath,rootFilename:g.rootFilename},m=a.getFileManager(b,g.currentDirectory,this.context,a);if(!m)return void k({message:"Could not find a file-manager for "+b});c&&(b=m.tryAppendExtension(b,h.plugin?".js":".less"));var n=function(a){var b=a.filename,c=a.contents.replace(/^\uFEFF/,"");l.currentDirectory=m.getPath(b),l.relativeUrls&&(l.rootpath=m.join(j.context.rootpath||"",m.pathDiff(l.currentDirectory,l.entryPath)),!m.isPathAbsolute(l.rootpath)&&m.alwaysMakePathsAbsolute()&&(l.rootpath=m.join(l.entryPath,l.rootpath))),l.filename=b;var i=new d.Parse(j.context);i.processImports=!1,j.contents[b]=c,(g.reference||h.reference)&&(l.reference=!0),h.plugin?new f(i,l).eval(c,function(a,c){k(a,c,b)}):h.inline?k(null,c,b):new e(i,j,l).parse(c,function(a,c){k(a,c,b)})},o=m.loadFile(b,g.currentDirectory,this.context,a,function(a,b){a?k(a):n(b)});o&&o.then(n,k)},b}},{"./contexts":11,"./parser/parser":38,"./plugins/function-importer":40}],31:[function(a,b,c){b.exports=function(b,c){var d,e,f,g,h,i={version:[2,7,3],data:a("./data"),tree:a("./tree"),Environment:h=a("./environment/environment"),AbstractFileManager:a("./environment/abstract-file-manager"),environment:b=new h(b,c),visitors:a("./visitors"),Parser:a("./parser/parser"),functions:a("./functions")(b),contexts:a("./contexts"),SourceMapOutput:d=a("./source-map-output")(b),SourceMapBuilder:e=a("./source-map-builder")(d,b),ParseTree:f=a("./parse-tree")(e),ImportManager:g=a("./import-manager")(b),render:a("./render")(b,f,g),parse:a("./parse")(b,f,g),LessError:a("./less-error"),transformTree:a("./transform-tree"),utils:a("./utils"),PluginManager:a("./plugin-manager"),logger:a("./logger")};return i}},{"./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(a,b,c){var d=a("./utils"),e=b.exports=function(a,b,c){Error.call(this);var e=a.filename||c;if(b&&e){var f=b.contents[e],g=d.getLocation(a.index,f),h=g.line,i=g.column,j=a.call&&d.getLocation(a.call,f).line,k=f.split("\n");this.type=a.type||"Syntax",this.filename=e,this.index=a.index,this.line="number"==typeof h?h+1:null,this.callLine=j+1,this.callExtract=k[j],this.column=i,this.extract=[k[h-1],k[h],k[h+1]]}this.message=a.message,this.stack=a.stack};if("undefined"==typeof Object.create){var f=function(){};f.prototype=Error.prototype,e.prototype=new f}else e.prototype=Object.create(Error.prototype);e.prototype.constructor=e},{"./utils":83}],33:[function(a,b,c){b.exports={error:function(a){this._fireEvent("error",a)},warn:function(a){this._fireEvent("warn",a)},info:function(a){this._fireEvent("info",a)},debug:function(a){this._fireEvent("debug",a)},addListener:function(a){this._listeners.push(a)},removeListener:function(a){for(var b=0;b=97&&j<=122||j<34))switch(j){case 40:o++,e=h;continue;case 41:if(--o<0)return b("missing opening `(`",h);continue;case 59:o||c();continue;case 123:n++,d=h;continue;case 125:if(--n<0)return b("missing opening `{`",h);n||o||c();continue;case 92:if(h96)){if(k==j){l=1;break}if(92==k){if(h==m-1)return b("unescaped `\\`",h);h++}}if(l)continue;return b("unmatched `"+String.fromCharCode(j)+"`",i);case 47:if(o||h==m-1)continue;if(k=a.charCodeAt(h+1),47==k)for(h+=2;hd&&g>f?b("missing closing `}` or `*/`",d):b("missing closing `}`",d):0!==o?b("missing closing `)`",e):(c(!0),p)}},{}],37:[function(a,b,c){var d=a("./chunker");b.exports=function(){function a(d){for(var e,f,j,p=k.i,q=c,s=k.i-i,t=k.i+h.length-s,u=k.i+=d,v=b;k.i=0){j={index:k.i,text:v.substr(k.i,x+2-k.i),isLineComment:!1},k.i+=j.text.length-1,k.commentStore.push(j);continue}}break}if(e!==l&&e!==n&&e!==m&&e!==o)break}if(h=h.slice(d+k.i-u+s),i=k.i,!h.length){if(ce||k.i===e&&a&&!f)&&(e=k.i,f=a);var b=j.pop();h=b.current,i=k.i=b.i,c=b.j},k.forget=function(){j.pop()},k.isWhitespace=function(a){var c=k.i+(a||0),d=b.charCodeAt(c);return d===l||d===o||d===m||d===n},k.$re=function(b){k.i>i&&(h=h.slice(k.i-i),i=k.i);var c=b.exec(h);return c?(a(c[0].length),"string"==typeof c?c:1===c.length?c[0]:c):null},k.$char=function(c){return b.charAt(k.i)!==c?null:(a(1),c)},k.$str=function(c){for(var d=c.length,e=0;es||a=b.length;return k.i=b.length-1,furthestChar:b[k.i]}},k}},{"./chunker":36}],38:[function(a,b,c){var d=a("../less-error"),e=a("../tree"),f=a("../visitors"),g=a("./parser-input"),h=a("../utils"),i=function j(a,b,c){function i(a,e){throw new d({index:o.i,filename:c.filename,type:e||"Syntax",message:a},b)}function k(a,b,c){var d=a instanceof Function?a.call(n):o.$re(a);return d?d:void i(b||("string"==typeof a?"expected '"+a+"' got '"+o.currentChar()+"'":"unexpected token"))}function l(a,b){return o.$char(a)?a:void i(b||"expected '"+a+"' got '"+o.currentChar()+"'")}function m(a){var b=c.filename;return{lineNumber:h.getLocation(a,o.getInput()).line+1,fileName:b}}var n,o=g();return{parse:function(g,h,i){var k,l,m,n,p=null,q="";if(l=i&&i.globalVars?j.serializeVars(i.globalVars)+"\n":"",m=i&&i.modifyVars?"\n"+j.serializeVars(i.modifyVars):"",a.pluginManager)for(var r=a.pluginManager.getPreProcessors(),s=0;s1&&(b=new e.Value(g)),d.push(b),g=[])}return o.forget(),a?d:f},literal:function(){return this.dimension()||this.color()||this.quoted()||this.unicodeDescriptor()},assignment:function(){var a,b;return o.save(),(a=o.$re(/^\w+(?=\s?=)/i))&&o.$char("=")&&(b=n.entity())?(o.forget(),new e.Assignment(a,b)):void o.restore()},url:function(){var a,b=o.i;return o.autoCommentAbsorb=!1,o.$str("url(")?(a=this.quoted()||this.variable()||o.$re(/^(?:(?:\\[\(\)'"])|[^\(\)'"])+/)||"",o.autoCommentAbsorb=!0,l(")"),new e.URL(null!=a.value||a instanceof e.Variable?a:new e.Anonymous(a),b,c)):void(o.autoCommentAbsorb=!0)},variable:function(){var a,b=o.i;if("@"===o.currentChar()&&(a=o.$re(/^@@?[\w-]+/)))return new e.Variable(a,b,c)},variableCurly:function(){var a,b=o.i;if("@"===o.currentChar()&&(a=o.$re(/^@\{([\w-]+)\}/)))return new e.Variable("@"+a[1],b,c)},color:function(){var a;if("#"===o.currentChar()&&(a=o.$re(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/))){var b=a.input.match(/^#([\w]+).*/);return b=b[1],b.match(/^[A-Fa-f0-9]+$/)||i("Invalid HEX color code"),new e.Color(a[1],(void 0),"#"+b)}},colorKeyword:function(){o.save();var a=o.autoCommentAbsorb;o.autoCommentAbsorb=!1;var b=o.$re(/^[_A-Za-z-][_A-Za-z0-9-]+/);if(o.autoCommentAbsorb=a,!b)return void o.forget();o.restore();var c=e.Color.fromKeyword(b);return c?(o.$str(b),c):void 0},dimension:function(){if(!o.peekNotNumeric()){var a=o.$re(/^([+-]?\d*\.?\d+)(%|[a-z_]+)?/i);return a?new e.Dimension(a[1],a[2]):void 0}},unicodeDescriptor:function(){var a;if(a=o.$re(/^U\+[0-9a-fA-F?]+(\-[0-9a-fA-F?]+)?/))return new e.UnicodeDescriptor(a[0])},javascript:function(){var a,b=o.i;o.save();var d=o.$char("~"),f=o.$char("`");return f?(a=o.$re(/^[^`]*`/))?(o.forget(),new e.JavaScript(a.substr(0,a.length-1),Boolean(d),b,c)):void o.restore("invalid javascript definition"):void o.restore()}},variable:function(){var a;if("@"===o.currentChar()&&(a=o.$re(/^(@[\w-]+)\s*:/)))return a[1]},rulesetCall:function(){var a;if("@"===o.currentChar()&&(a=o.$re(/^(@[\w-]+)\(\s*\)\s*;/)))return new e.RulesetCall(a[1])},extend:function(a){var b,d,f,g,h,j=o.i;if(o.$str(a?"&:extend(":":extend(")){do{for(f=null,b=null;!(f=o.$re(/^(all)(?=\s*(\)|,))/))&&(d=this.element());)b?b.push(d):b=[d];f=f&&f[1],b||i("Missing target selector for :extend()."),h=new e.Extend(new e.Selector(b),f,j,c),g?g.push(h):g=[h]}while(o.$char(","));return k(/^\)/),a&&k(/^;/),g}},extendRule:function(){return this.extend(!0)},mixin:{call:function(){var a,b,d,f,g,h,i=o.currentChar(),j=!1,k=o.i;if("."===i||"#"===i){for(o.save();;){if(a=o.i,f=o.$re(/^[#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/),!f)break;d=new e.Element(g,f,a,c),b?b.push(d):b=[d],g=o.$char(">")}return b&&(o.$char("(")&&(h=this.args(!0).args,l(")")),n.important()&&(j=!0),n.end())?(o.forget(),new e.mixin.Call(b,h,k,c,j)):void o.restore()}},args:function(a){var b,c,d,f,g,h,j,k=n.entities,l={args:null,variadic:!1},m=[],p=[],q=[];for(o.save();;){if(a)h=n.detachedRuleset()||n.expression();else{if(o.commentStore.length=0,o.$str("...")){l.variadic=!0,o.$char(";")&&!b&&(b=!0),(b?p:q).push({variadic:!0});break}h=k.variable()||k.literal()||k.keyword()}if(!h)break;f=null,h.throwAwayComments&&h.throwAwayComments(),g=h;var r=null;if(a?h.value&&1==h.value.length&&(r=h.value[0]):r=h,r&&r instanceof e.Variable)if(o.$char(":")){if(m.length>0&&(b&&i("Cannot mix ; and , as delimiter types"),c=!0),g=n.detachedRuleset()||n.expression(),!g){if(!a)return o.restore(),l.args=[],l;i("could not understand value for named argument")}f=d=r.name}else if(o.$str("...")){if(!a){l.variadic=!0,o.$char(";")&&!b&&(b=!0),(b?p:q).push({name:h.name,variadic:!0});break}j=!0}else a||(d=f=r.name,g=null);g&&m.push(g),q.push({name:f,value:g,expand:j}),o.$char(",")||(o.$char(";")||b)&&(c&&i("Cannot mix ; and , as delimiter types"),b=!0,m.length>1&&(g=new e.Value(m)),p.push({name:d,value:g,expand:j}),d=null,m=[],c=!1)}return o.forget(),l.args=b?p:q,l},definition:function(){var a,b,c,d,f=[],g=!1;if(!("."!==o.currentChar()&&"#"!==o.currentChar()||o.peek(/^[^{]*\}/)))if(o.save(),b=o.$re(/^([#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+)\s*\(/)){a=b[1];var h=this.args(!1);if(f=h.args,g=h.variadic,!o.$char(")"))return void o.restore("Missing closing ')'");if(o.commentStore.length=0,o.$str("when")&&(d=k(n.conditions,"expected condition")),c=n.block())return o.forget(),new e.mixin.Definition(a,f,c,d,g);o.restore()}else o.forget()}},entity:function(){var a=this.entities;return this.comment()||a.literal()||a.variable()||a.url()||a.call()||a.keyword()||a.javascript()},end:function(){return o.$char(";")||o.peek("}")},alpha:function(){var a;if(o.$re(/^opacity=/i))return a=o.$re(/^\d+/),a||(a=k(this.entities.variable,"Could not parse alpha")),l(")"),new e.Alpha(a)},element:function(){var a,b,d,f=o.i;if(b=this.combinator(),a=o.$re(/^(?:\d+\.\d+|\d+)%/)||o.$re(/^(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/)||o.$char("*")||o.$char("&")||this.attribute()||o.$re(/^\([^&()@]+\)/)||o.$re(/^[\.#:](?=@)/)||this.entities.variableCurly(),a||(o.save(),o.$char("(")?(d=this.selector())&&o.$char(")")?(a=new e.Paren(d),o.forget()):o.restore("Missing closing ')'"):o.forget()),a)return new e.Element(b,a,f,c)},combinator:function(){var a=o.currentChar();if("/"===a){o.save();var b=o.$re(/^\/[a-z]+\//i);if(b)return o.forget(),new e.Combinator(b);o.restore()}if(">"===a||"+"===a||"~"===a||"|"===a||"^"===a){for(o.i++,"^"===a&&"^"===o.currentChar()&&(a="^^",o.i++);o.isWhitespace();)o.i++;return new e.Combinator(a)}return new e.Combinator(o.isWhitespace(-1)?" ":null)},lessSelector:function(){return this.selector(!0)},selector:function(a){for(var b,d,f,g,h,j,l,m=o.i;(a&&(d=this.extend())||a&&(j=o.$str("when"))||(g=this.element()))&&(j?l=k(this.conditions,"expected condition"):l?i("CSS guard can only be used at the end of selector"):d?h=h?h.concat(d):d:(h&&i("Extend can only be used at the end of selector"),f=o.currentChar(),b?b.push(g):b=[g],g=null),"{"!==f&&"}"!==f&&";"!==f&&","!==f&&")"!==f););return b?new e.Selector(b,h,l,m,c):void(h&&i("Extend must be used to extend a selector, it cannot be used on its own"))},attribute:function(){if(o.$char("[")){var a,b,c,d=this.entities;return(a=d.variableCurly())||(a=k(/^(?:[_A-Za-z0-9-\*]*\|)?(?:[_A-Za-z0-9-]|\\.)+/)),c=o.$re(/^[|~*$^]?=/),c&&(b=d.quoted()||o.$re(/^[0-9]+%/)||o.$re(/^[\w-]+/)||d.variableCurly()),l("]"),new e.Attribute(a,c,b)}},block:function(){var a;if(o.$char("{")&&(a=this.primary())&&o.$char("}"))return a},blockRuleset:function(){var a=this.block();return a&&(a=new e.Ruleset(null,a)),a},detachedRuleset:function(){var a=this.blockRuleset();if(a)return new e.DetachedRuleset(a)},ruleset:function(){var b,c,d,f;for(o.save(),a.dumpLineNumbers&&(f=m(o.i));;){if(c=this.lessSelector(),!c)break;if(b?b.push(c):b=[c],o.commentStore.length=0,c.condition&&b.length>1&&i("Guards are only currently allowed on a single selector."),!o.$char(","))break;c.condition&&i("Guards are only currently allowed on a single selector."),o.commentStore.length=0}if(b&&(d=this.block())){o.forget();var g=new e.Ruleset(b,d,a.strictImports);return a.dumpLineNumbers&&(g.debugInfo=f),g}o.restore()},rule:function(b){var d,f,g,h,i,j=o.i,k=o.currentChar();if("."!==k&&"#"!==k&&"&"!==k&&":"!==k)if(o.save(),d=this.variable()||this.ruleProperty()){if(i="string"==typeof d,i&&(f=this.detachedRuleset()),o.commentStore.length=0,!f){h=!i&&d.length>1&&d.pop().value;var l=!b&&(a.compress||i);if(l&&(f=this.value()),!f&&(f=this.anonymousValue()))return o.forget(),new e.Rule(d,f,(!1),h,j,c);l||f||(f=this.value()),g=this.important()}if(f&&this.end())return o.forget(),new e.Rule(d,f,g,h,j,c);if(o.restore(),f&&!b)return this.rule(!0)}else o.forget()},anonymousValue:function(){var a=o.$re(/^([^@+\/'"*`(;{}-]*);/);if(a)return new e.Anonymous(a[1])},"import":function(){var a,b,d=o.i,f=o.$re(/^@import?\s+/);if(f){var g=(f?this.importOptions():null)||{};if(a=this.entities.quoted()||this.entities.url())return b=this.mediaFeatures(),o.$char(";")||(o.i=d,i("missing semi-colon or unrecognised media features on import")),b=b&&new e.Value(b),new e.Import(a,b,g,d,c);o.i=d,i("malformed import statement")}},importOptions:function(){var a,b,c,d={};if(!o.$char("("))return null;do if(a=this.importOption()){switch(b=a,c=!0,b){case"css":b="less",c=!1;break;case"once":b="multiple",c=!1}if(d[b]=c,!o.$char(","))break}while(a);return l(")"),d},importOption:function(){var a=o.$re(/^(less|css|multiple|once|inline|reference|optional)/);if(a)return a[1]},mediaFeature:function(){var a,b,d=this.entities,f=[];o.save();do a=d.keyword()||d.variable(),a?f.push(a):o.$char("(")&&(b=this.property(),a=this.value(),o.$char(")")?b&&a?f.push(new e.Paren(new e.Rule(b,a,null,null,o.i,c,(!0)))):a?f.push(new e.Paren(a)):i("badly formed media feature definition"):i("Missing closing ')'","Parse"));while(a);if(o.forget(),f.length>0)return new e.Expression(f)},mediaFeatures:function(){var a,b=this.entities,c=[];do if(a=this.mediaFeature()){if(c.push(a),!o.$char(","))break}else if(a=b.variable(),a&&(c.push(a),!o.$char(",")))break;while(a);return c.length>0?c:null},media:function(){var b,d,f,g,h=o.i;return a.dumpLineNumbers&&(g=m(h)),o.save(),o.$str("@media")?(b=this.mediaFeatures(),d=this.block(),d||i("media definitions require block statements after any features"),o.forget(),f=new e.Media(d,b,h,c),a.dumpLineNumbers&&(f.debugInfo=g),f):void o.restore()},plugin:function(){var a,b=o.i,d=o.$re(/^@plugin?\s+/);if(d){var f={plugin:!0};if(a=this.entities.quoted()||this.entities.url())return o.$char(";")||(o.i=b,i("missing semi-colon on plugin")),new e.Import(a,null,f,b,c);o.i=b,i("malformed plugin statement")}},directive:function(){var b,d,f,g,h,j,k,l=o.i,n=!0,p=!0;if("@"===o.currentChar()){if(d=this["import"]()||this.plugin()||this.media())return d;if(o.save(),b=o.$re(/^@[a-z-]+/)){switch(g=b,"-"==b.charAt(1)&&b.indexOf("-",2)>0&&(g="@"+b.slice(b.indexOf("-",2)+1)),g){case"@charset":h=!0,n=!1;break;case"@namespace":j=!0,n=!1;break;case"@keyframes":case"@counter-style":h=!0;break;case"@document":case"@supports":k=!0,p=!1;break;default:k=!0}return o.commentStore.length=0,h?(d=this.entity(),d||i("expected "+b+" identifier")):j?(d=this.expression(),d||i("expected "+b+" expression")):k&&(d=(o.$re(/^[^{;]+/)||"").trim(),n="{"==o.currentChar(),d&&(d=new e.Anonymous(d))),n&&(f=this.blockRuleset()),f||!n&&d&&o.$char(";")?(o.forget(),new e.Directive(b,d,f,l,c,a.dumpLineNumbers?m(l):null,p)):void o.restore("directive options not recognised")}}},value:function(){var a,b=[];do if(a=this.expression(),a&&(b.push(a),!o.$char(",")))break;while(a);if(b.length>0)return new e.Value(b)},important:function(){if("!"===o.currentChar())return o.$re(/^! *important/)},sub:function(){var a,b;return o.save(),o.$char("(")?(a=this.addition(),a&&o.$char(")")?(o.forget(),b=new e.Expression([a]),b.parens=!0,b):void o.restore("Expected ')'")):void o.restore()},multiplication:function(){var a,b,c,d,f;if(a=this.operand()){for(f=o.isWhitespace(-1);;){if(o.peek(/^\/[*\/]/))break;if(o.save(),c=o.$char("/")||o.$char("*"),!c){o.forget();break}if(b=this.operand(),!b){o.restore();break}o.forget(),a.parensInOp=!0,b.parensInOp=!0,d=new e.Operation(c,[d||a,b],f),f=o.isWhitespace(-1)}return d||a}},addition:function(){var a,b,c,d,f;if(a=this.multiplication()){for(f=o.isWhitespace(-1);;){if(c=o.$re(/^[-+]\s+/)||!f&&(o.$char("+")||o.$char("-")),!c)break;if(b=this.multiplication(),!b)break;a.parensInOp=!0,b.parensInOp=!0,d=new e.Operation(c,[d||a,b],f),f=o.isWhitespace(-1)}return d||a}},conditions:function(){var a,b,c,d=o.i;if(a=this.condition()){for(;;){if(!o.peek(/^,\s*(not\s*)?\(/)||!o.$char(","))break;if(b=this.condition(),!b)break;c=new e.Condition("or",c||a,b,d)}return c||a}},condition:function(){function a(){return o.$str("or")}var b,c,d;if(b=this.conditionAnd(this)){if(c=a()){if(d=this.condition(),!d)return;b=new e.Condition(c,b,d)}return b}},conditionAnd:function(){function a(a){return a.negatedCondition()||a.parenthesisCondition()}function b(){return o.$str("and")}var c,d,f;if(c=a(this)){if(d=b()){if(f=this.conditionAnd(),!f)return;c=new e.Condition(d,c,f)}return c}},negatedCondition:function(){if(o.$str("not")){var a=this.parenthesisCondition();return a&&(a.negate=!a.negate),a}},parenthesisCondition:function(){function a(a){var b;return o.save(),(b=a.condition())&&o.$char(")")?(o.forget(),b):void o.restore()}var b;return o.save(),o.$str("(")?(b=a(this))?(o.forget(),b):(b=this.atomicCondition())?o.$char(")")?(o.forget(),b):void o.restore("expected ')' got '"+o.currentChar()+"'"):void o.restore():void o.restore()},atomicCondition:function(){var a,b,c,d,f=this.entities,g=o.i;if(a=this.addition()||f.keyword()||f.quoted())return o.$char(">")?d=o.$char("=")?">=":">":o.$char("<")?d=o.$char("=")?"<=":"<":o.$char("=")&&(d=o.$char(">")?"=>":o.$char("<")?"=<":"="),d?(b=this.addition()||f.keyword()||f.quoted(),b?c=new e.Condition(d,a,b,g,(!1)):i("expected expression")):c=new e.Condition("=",a,new e.Keyword("true"),g,(!1)),c},operand:function(){var a,b=this.entities;o.peek(/^-[@\(]/)&&(a=o.$char("-"));var c=this.sub()||b.dimension()||b.color()||b.variable()||b.call()||b.colorKeyword();return a&&(c.parensInOp=!0,c=new e.Negative(c)),c},expression:function(){var a,b,c=[];do a=this.comment(),a?c.push(a):(a=this.addition()||this.entity(),a&&(c.push(a),o.peek(/^\/[\/*]/)||(b=o.$char("/"),b&&c.push(new e.Anonymous(b)))));while(a);if(c.length>0)return new e.Expression(c)},property:function(){var a=o.$re(/^(\*?-?[_a-zA-Z0-9-]+)\s*:/);if(a)return a[1]},ruleProperty:function(){function a(a){var b=o.i,c=o.$re(a);if(c)return g.push(b),f.push(c[1])}var b,d,f=[],g=[];o.save();var h=o.$re(/^([_a-zA-Z0-9-]+)\s*:/);if(h)return f=[new e.Keyword(h[1])],o.forget(),f;for(a(/^(\*?)/);;)if(!a(/^((?:[\w-]+)|(?:@\{[\w-]+\}))/))break;if(f.length>1&&a(/^((?:\+_|\+)?)\s*:/)){for(o.forget(),""===f[0]&&(f.shift(),g.shift()),d=0;d=b);c++);this.preProcessors.splice(c,0,{preProcessor:a,priority:b})},d.prototype.addPostProcessor=function(a,b){var c;for(c=0;c=b);c++);this.postProcessors.splice(c,0,{postProcessor:a,priority:b})},d.prototype.addFileManager=function(a){this.fileManagers.push(a)},d.prototype.getPreProcessors=function(){for(var a=[],b=0;b0){var d,e=JSON.stringify(this._sourceMapGenerator.toJSON());this.sourceMapURL?d=this.sourceMapURL:this._sourceMapFilename&&(d=this._sourceMapFilename),this.sourceMapURL=d,this.sourceMap=e}return this._css.join("")},b}},{}],44:[function(a,b,c){var d=a("./contexts"),e=a("./visitors"),f=a("./tree");b.exports=function(a,b){b=b||{};var c,g=b.variables,h=new d.Eval(b);"object"!=typeof g||Array.isArray(g)||(g=Object.keys(g).map(function(a){var b=g[a];return b instanceof f.Value||(b instanceof f.Expression||(b=new f.Expression([b])),b=new f.Value([b])),new f.Rule("@"+a,b,(!1),null,0)}),h.frames=[new f.Ruleset(null,g)]);var i,j=[],k=[new e.JoinSelectorVisitor,new e.MarkVisibleSelectorsVisitor((!0)),new e.ExtendVisitor,new e.ToCSSVisitor({compress:Boolean(b.compress)})];if(b.pluginManager){var l=b.pluginManager.getVisitors();for(i=0;i.5?j/(2-g-h):j/(g+h),g){case c:a=(d-e)/j+(d="===a||"=<"===a||"<="===a;case 1:return">"===a||">="===a;default:return!1}}}(this.op,this.lvalue.eval(a),this.rvalue.eval(a));return this.negate?!b:b},b.exports=e},{"./node":70}],54:[function(a,b,c){var d=function(a,b,c){var e="";if(a.dumpLineNumbers&&!a.compress)switch(a.dumpLineNumbers){case"comments":e=d.asComment(b);break;case"mediaquery":e=d.asMediaQuery(b);break;case"all":e=d.asComment(b)+(c||"")+d.asMediaQuery(b)}return e};d.asComment=function(a){return"/* line "+a.debugInfo.lineNumber+", "+a.debugInfo.fileName+" */\n"},d.asMediaQuery=function(a){var b=a.debugInfo.fileName;return/^[a-z]+:\/\//i.test(b)||(b="file://"+b),"@media -sass-debug-info{filename{font-family:"+b.replace(/([.:\/\\])/g,function(a){return"\\"==a&&(a="/"),"\\"+a})+"}line{font-family:\\00003"+a.debugInfo.lineNumber+"}}\n"},b.exports=d},{}],55:[function(a,b,c){var d=a("./node"),e=a("../contexts"),f=function(a,b){this.ruleset=a,this.frames=b};f.prototype=new d,f.prototype.type="DetachedRuleset",f.prototype.evalFirst=!0,f.prototype.accept=function(a){this.ruleset=a.visit(this.ruleset)},f.prototype.eval=function(a){var b=this.frames||a.frames.slice(0);return new f(this.ruleset,b)},f.prototype.callEval=function(a){return this.ruleset.eval(this.frames?new e.Eval(a,this.frames.concat(a.frames)):a)},b.exports=f},{"../contexts":11,"./node":70}],56:[function(a,b,c){var d=a("./node"),e=a("../data/unit-conversions"),f=a("./unit"),g=a("./color"),h=function(a,b){this.value=parseFloat(a),this.unit=b&&b instanceof f?b:new f(b?[b]:void 0)};h.prototype=new d,h.prototype.type="Dimension",h.prototype.accept=function(a){this.unit=a.visit(this.unit)},h.prototype.eval=function(a){return this},h.prototype.toColor=function(){return new g([this.value,this.value,this.value])},h.prototype.genCSS=function(a,b){if(a&&a.strictUnits&&!this.unit.isSingular())throw new Error("Multiple units in dimension. Correct the units or use the unit function. Bad unit: "+this.unit.toString());var c=this.fround(a,this.value),d=String(c);if(0!==c&&c<1e-6&&c>-1e-6&&(d=c.toFixed(20).replace(/0+$/,"")),a&&a.compress){if(0===c&&this.unit.isLength())return void b.add(d);c>0&&c<1&&(d=d.substr(1))}b.add(d),this.unit.genCSS(a,b)},h.prototype.operate=function(a,b,c){var d=this._operate(a,b,this.value,c.value),e=this.unit.clone();if("+"===b||"-"===b)if(0===e.numerator.length&&0===e.denominator.length)e=c.unit.clone(),this.unit.backupUnit&&(e.backupUnit=this.unit.backupUnit);else if(0===c.unit.numerator.length&&0===e.denominator.length);else{if(c=c.convertTo(this.unit.usedUnits()),a.strictUnits&&c.unit.toString()!==e.toString())throw new Error("Incompatible units. Change the units or use the unit function. Bad units: '"+e.toString()+"' and '"+c.unit.toString()+"'.");d=this._operate(a,b,this.value,c.value)}else"*"===b?(e.numerator=e.numerator.concat(c.unit.numerator).sort(),e.denominator=e.denominator.concat(c.unit.denominator).sort(),e.cancel()):"/"===b&&(e.numerator=e.numerator.concat(c.unit.denominator).sort(),e.denominator=e.denominator.concat(c.unit.numerator).sort(),e.cancel());return new h(d,e)},h.prototype.compare=function(a){var b,c;if(a instanceof h){if(this.unit.isEmpty()||a.unit.isEmpty())b=this,c=a;else if(b=this.unify(),c=a.unify(),0!==b.unit.compare(c.unit))return;return d.numericCompare(b.value,c.value)}},h.prototype.unify=function(){return this.convertTo({length:"px",duration:"s",angle:"rad"})},h.prototype.convertTo=function(a){var b,c,d,f,g,i=this.value,j=this.unit.clone(),k={};if("string"==typeof a){for(b in e)e[b].hasOwnProperty(a)&&(k={},k[b]=a);a=k}g=function(a,b){return d.hasOwnProperty(a)?(b?i/=d[a]/d[f]:i*=d[a]/d[f],f):a};for(c in a)a.hasOwnProperty(c)&&(f=a[c],d=e[c],j.map(g));return j.cancel(),new h(i,j)},b.exports=h},{"../data/unit-conversions":14,"./color":50,"./node":70,"./unit":79}],57:[function(a,b,c){var d=a("./node"),e=a("./selector"),f=a("./ruleset"),g=function(a,b,c,d,f,g,h,i){var j;if(this.name=a,this.value=b,c)for(Array.isArray(c)?this.rules=c:(this.rules=[c],this.rules[0].selectors=new e([],null,null,this.index,f).createEmptySelectors()),j=0;j1?b=new g(this.value.map(function(b){return b.eval(a)})):1===this.value.length?(this.value[0].parens&&!this.value[0].parensInOp&&(d=!0),b=this.value[0].eval(a)):b=this,c&&a.outOfParenthesis(),this.parens&&this.parensInOp&&!a.isMathOn()&&!d&&(b=new e(b)),b},g.prototype.genCSS=function(a,b){for(var c=0;c0&&c.length&&""===c[0].combinator.value&&(c[0].combinator.value=" "),d=d.concat(a[b].elements);this.selfSelectors=[new e(d)],this.selfSelectors[0].copyVisibilityInfo(this.visibilityInfo())},b.exports=f},{"./node":70,"./selector":77}],61:[function(a,b,c){var d=a("./node"),e=a("./media"),f=a("./url"),g=a("./quoted"),h=a("./ruleset"),i=a("./anonymous"),j=function(a,b,c,d,e,f){if(this.options=c,this.index=d,this.path=a,this.features=b,this.currentFileInfo=e,this.allowRoot=!0,void 0!==this.options.less||this.options.inline)this.css=!this.options.less||this.options.inline;else{var g=this.getPath();g&&/[#\.\&\?\/]css([\?;].*)?$/.test(g)&&(this.css=!0)}this.copyVisibilityInfo(f)};j.prototype=new d,j.prototype.type="Import",j.prototype.accept=function(a){this.features&&(this.features=a.visit(this.features)),this.path=a.visit(this.path),this.options.plugin||this.options.inline||!this.root||(this.root=a.visit(this.root))},j.prototype.genCSS=function(a,b){this.css&&void 0===this.path.currentFileInfo.reference&&(b.add("@import ",this.currentFileInfo,this.index),this.path.genCSS(a,b),this.features&&(b.add(" "),this.features.genCSS(a,b)),b.add(";"))},j.prototype.getPath=function(){return this.path instanceof f?this.path.value.value:this.path.value},j.prototype.isVariableImport=function(){var a=this.path;return a instanceof f&&(a=a.value),!(a instanceof g)||a.containsVariables()},j.prototype.evalForImport=function(a){var b=this.path;return b instanceof f&&(b=b.value),new j(b.eval(a),this.features,this.options,this.index,this.currentFileInfo,this.visibilityInfo())},j.prototype.evalPath=function(a){var b=this.path.eval(a),c=this.currentFileInfo&&this.currentFileInfo.rootpath;if(!(b instanceof f)){if(c){var d=b.value;d&&a.isPathRelative(d)&&(b.value=c+d)}b.value=a.normalizePath(b.value)}return b},j.prototype.eval=function(a){var b=this.doEval(a);return(this.options.reference||this.blocksVisibility())&&(b.length||0===b.length?b.forEach(function(a){a.addVisibilityBlock()}):b.addVisibilityBlock()),b},j.prototype.doEval=function(a){var b,c,d=this.features&&this.features.eval(a);if(this.options.plugin)return c=a.frames[0]&&a.frames[0].functionRegistry,c&&this.root&&this.root.functions&&c.addMultiple(this.root.functions),[];if(this.skip&&("function"==typeof this.skip&&(this.skip=this.skip()),this.skip))return[];if(this.options.inline){var f=new i(this.root,0,{filename:this.importedFilename,reference:this.path.currentFileInfo&&this.path.currentFileInfo.reference},(!0),(!0));return this.features?new e([f],this.features.value):[f]}if(this.css){var g=new j(this.evalPath(a),d,this.options,this.index);if(!g.css&&this.error)throw this.error;return g}return b=new h(null,this.root.rules.slice(0)),b.evalImports(a),this.features?new e(b.rules,this.features.value):b.rules},b.exports=j},{"./anonymous":46,"./media":66,"./node":70,"./quoted":73,"./ruleset":76,"./url":80}],62:[function(a,b,c){var d={};d.Node=a("./node"),d.Alpha=a("./alpha"),d.Color=a("./color"),d.Directive=a("./directive"),d.DetachedRuleset=a("./detached-ruleset"),d.Operation=a("./operation"),d.Dimension=a("./dimension"),d.Unit=a("./unit"),d.Keyword=a("./keyword"),d.Variable=a("./variable"),d.Ruleset=a("./ruleset"),d.Element=a("./element"),d.Attribute=a("./attribute"),d.Combinator=a("./combinator"),d.Selector=a("./selector"),d.Quoted=a("./quoted"),d.Expression=a("./expression"),d.Rule=a("./rule"),d.Call=a("./call"),d.URL=a("./url"),d.Import=a("./import"),d.mixin={Call:a("./mixin-call"),Definition:a("./mixin-definition")},d.Comment=a("./comment"),d.Anonymous=a("./anonymous"),d.Value=a("./value"),d.JavaScript=a("./javascript"),d.Assignment=a("./assignment"),d.Condition=a("./condition"),d.Paren=a("./paren"),d.Media=a("./media"),d.UnicodeDescriptor=a("./unicode-descriptor"),d.Negative=a("./negative"),d.Extend=a("./extend"),d.RulesetCall=a("./ruleset-call"),b.exports=d},{"./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(a,b,c){var d=a("./js-eval-node"),e=a("./dimension"),f=a("./quoted"),g=a("./anonymous"),h=function(a,b,c,d){this.escaped=b,this.expression=a,this.index=c,this.currentFileInfo=d};h.prototype=new d,h.prototype.type="JavaScript",h.prototype.eval=function(a){var b=this.evaluateJavaScript(this.expression,a);return"number"==typeof b?new e(b):"string"==typeof b?new f('"'+b+'"',b,this.escaped,this.index):new g(Array.isArray(b)?b.join(", "):b)},b.exports=h},{"./anonymous":46,"./dimension":56,"./js-eval-node":64,"./quoted":73}],64:[function(a,b,c){var d=a("./node"),e=a("./variable"),f=function(){};f.prototype=new d,f.prototype.evaluateJavaScript=function(a,b){var c,d=this,f={};if(void 0!==b.javascriptEnabled&&!b.javascriptEnabled)throw{message:"You are using JavaScript, which has been disabled.",filename:this.currentFileInfo.filename,index:this.index};a=a.replace(/@\{([\w-]+)\}/g,function(a,c){return d.jsify(new e("@"+c,d.index,d.currentFileInfo).eval(b))});try{a=new Function("return ("+a+")")}catch(g){throw{message:"JavaScript evaluation error: "+g.message+" from `"+a+"`",filename:this.currentFileInfo.filename,index:this.index}}var h=b.frames[0].variables();for(var i in h)h.hasOwnProperty(i)&&(f[i.slice(1)]={value:h[i].value,toJS:function(){return this.value.eval(b).toCSS()}});try{c=a.call(f)}catch(g){throw{message:"JavaScript evaluation error: '"+g.name+": "+g.message.replace(/["]/g,"'")+"'",filename:this.currentFileInfo.filename,index:this.index}}return c},f.prototype.jsify=function(a){return Array.isArray(a.value)&&a.value.length>1?"["+a.value.map(function(a){return a.toCSS()}).join(", ")+"]":a.toCSS()},b.exports=f},{"./node":70,"./variable":82}],65:[function(a,b,c){var d=a("./node"),e=function(a){this.value=a};e.prototype=new d,e.prototype.type="Keyword",e.prototype.genCSS=function(a,b){if("%"===this.value)throw{type:"Syntax",message:"Invalid % without number"};b.add(this.value)},e.True=new e("true"),e.False=new e("false"),b.exports=e},{"./node":70}],66:[function(a,b,c){var d=a("./ruleset"),e=a("./value"),f=a("./selector"),g=a("./anonymous"),h=a("./expression"),i=a("./directive"),j=function(a,b,c,g,h){this.index=c,this.currentFileInfo=g;var i=new f([],null,null,this.index,this.currentFileInfo).createEmptySelectors();this.features=new e(b),this.rules=[new d(i,a)],this.rules[0].allowImports=!0,this.copyVisibilityInfo(h),this.allowRoot=!0};j.prototype=new i,j.prototype.type="Media",j.prototype.isRulesetLike=!0,j.prototype.accept=function(a){this.features&&(this.features=a.visit(this.features)),this.rules&&(this.rules=a.visitArray(this.rules))},j.prototype.genCSS=function(a,b){b.add("@media ",this.currentFileInfo,this.index),this.features.genCSS(a,b),this.outputRuleset(a,b,this.rules)},j.prototype.eval=function(a){a.mediaBlocks||(a.mediaBlocks=[],a.mediaPath=[]);var b=new j(null,[],this.index,this.currentFileInfo,this.visibilityInfo());this.debugInfo&&(this.rules[0].debugInfo=this.debugInfo,b.debugInfo=this.debugInfo);var c=!1;a.strictMath||(c=!0,a.strictMath=!0);try{b.features=this.features.eval(a)}finally{c&&(a.strictMath=!1)}return a.mediaPath.push(b),a.mediaBlocks.push(b),this.rules[0].functionRegistry=a.frames[0].functionRegistry.inherit(),a.frames.unshift(this.rules[0]),b.rules=[this.rules[0].eval(a)],a.frames.shift(),a.mediaPath.pop(),0===a.mediaPath.length?b.evalTop(a):b.evalNested(a)},j.prototype.evalTop=function(a){var b=this;if(a.mediaBlocks.length>1){var c=new f([],null,null,this.index,this.currentFileInfo).createEmptySelectors();b=new d(c,a.mediaBlocks),b.multiMedia=!0,b.copyVisibilityInfo(this.visibilityInfo())}return delete a.mediaBlocks,delete a.mediaPath,b},j.prototype.evalNested=function(a){var b,c,f=a.mediaPath.concat([this]);for(b=0;b0;b--)a.splice(b,0,new g("and"));return new h(a)})),new d([],[])},j.prototype.permute=function(a){if(0===a.length)return[];if(1===a.length)return a[0];for(var b=[],c=this.permute(a.slice(1)),d=0;d0){for(n=!0,k=0;k0)p=B;else if(p=A,q[A]+q[B]>1)throw{type:"Runtime",message:"Ambiguous use of `default()` found when matching for `"+this.format(t)+"`",index:this.index,filename:this.currentFileInfo.filename};for(k=0;kthis.params.length)return!1}c=Math.min(f,this.arity);for(var g=0;gb?1:void 0},d.prototype.blocksVisibility=function(){return null==this.visibilityBlocks&&(this.visibilityBlocks=0),0!==this.visibilityBlocks},d.prototype.addVisibilityBlock=function(){null==this.visibilityBlocks&&(this.visibilityBlocks=0),this.visibilityBlocks=this.visibilityBlocks+1},d.prototype.removeVisibilityBlock=function(){null==this.visibilityBlocks&&(this.visibilityBlocks=0),this.visibilityBlocks=this.visibilityBlocks-1},d.prototype.ensureVisibility=function(){this.nodeVisible=!0},d.prototype.ensureInvisibility=function(){this.nodeVisible=!1},d.prototype.isVisible=function(){return this.nodeVisible},d.prototype.visibilityInfo=function(){return{visibilityBlocks:this.visibilityBlocks,nodeVisible:this.nodeVisible}},d.prototype.copyVisibilityInfo=function(a){a&&(this.visibilityBlocks=a.visibilityBlocks,this.nodeVisible=a.nodeVisible)},b.exports=d},{}],71:[function(a,b,c){var d=a("./node"),e=a("./color"),f=a("./dimension"),g=function(a,b,c){this.op=a.trim(),this.operands=b,this.isSpaced=c};g.prototype=new d,g.prototype.type="Operation",g.prototype.accept=function(a){this.operands=a.visit(this.operands)},g.prototype.eval=function(a){var b=this.operands[0].eval(a),c=this.operands[1].eval(a);if(a.isMathOn()){if(b instanceof f&&c instanceof e&&(b=b.toColor()),c instanceof f&&b instanceof e&&(c=c.toColor()),!b.operate)throw{type:"Operation",message:"Operation on an invalid type"};return b.operate(a,this.op,c)}return new g(this.op,[b,c],this.isSpaced)},g.prototype.genCSS=function(a,b){this.operands[0].genCSS(a,b),this.isSpaced&&b.add(" "),b.add(this.op),this.isSpaced&&b.add(" "),this.operands[1].genCSS(a,b)},b.exports=g},{"./color":50,"./dimension":56,"./node":70}],72:[function(a,b,c){var d=a("./node"),e=function(a){this.value=a};e.prototype=new d,e.prototype.type="Paren",e.prototype.genCSS=function(a,b){b.add("("),this.value.genCSS(a,b),b.add(")")},e.prototype.eval=function(a){return new e(this.value.eval(a))},b.exports=e},{"./node":70}],73:[function(a,b,c){var d=a("./node"),e=a("./js-eval-node"),f=a("./variable"),g=function(a,b,c,d,e){this.escaped=null==c||c,this.value=b||"",this.quote=a.charAt(0),this.index=d,this.currentFileInfo=e};g.prototype=new e,g.prototype.type="Quoted",g.prototype.genCSS=function(a,b){this.escaped||b.add(this.quote,this.currentFileInfo,this.index),b.add(this.value),this.escaped||b.add(this.quote)},g.prototype.containsVariables=function(){return this.value.match(/(`([^`]+)`)|@\{([\w-]+)\}/)},g.prototype.eval=function(a){function b(a,b,c){var d=a;do a=d,d=a.replace(b,c);while(a!==d);return d}var c=this,d=this.value,e=function(b,d){return String(c.evaluateJavaScript(d,a))},h=function(b,d){var e=new f("@"+d,c.index,c.currentFileInfo).eval(a,!0);return e instanceof g?e.value:e.toCSS()};return d=b(d,/`([^`]+)`/g,e),d=b(d,/@\{([\w-]+)\}/g,h),new g(this.quote+d+this.quote,d,this.escaped,this.index,this.currentFileInfo)},g.prototype.compare=function(a){return"Quoted"!==a.type||this.escaped||a.escaped?a.toCSS&&this.toCSS()===a.toCSS()?0:void 0:d.numericCompare(this.value,a.value)},b.exports=g},{"./js-eval-node":64,"./node":70,"./variable":82}],74:[function(a,b,c){function d(a,b){var c,d="",e=b.length,f={add:function(a){d+=a}};for(c=0;cd){if(!c||c(h)){e=h.find(new f(a.elements.slice(d)),b,c);for(var j=0;j0&&b.add(k),a.firstSelector=!0,h[0].genCSS(a,b),a.firstSelector=!1,e=1;e0?(e=a.slice(0),f=e.pop(),h=d.createDerived(f.elements.slice(0))):h=d.createDerived([]),b.length>0){var i=c.combinator,j=b[0].elements[0];i.emptyOrWhitespace&&!j.combinator.emptyOrWhitespace&&(i=j.combinator),h.elements.push(new g(i,j.value,c.index,c.currentFileInfo)),h.elements=h.elements.concat(b[0].elements.slice(1))}if(0!==h.elements.length&&e.push(h),b.length>1){var k=b.slice(1);k=k.map(function(a){return a.createDerived(a.elements,[])}),e=e.concat(k)}return e}function j(a,b,c,d,e){var f;for(f=0;f0?d[d.length-1]=d[d.length-1].createDerived(d[d.length-1].elements.concat(a)):d.push(new f(a))}}function l(a,b,c){function f(a){var b;return"Paren"!==a.value.type?null:(b=a.value.value,"Selector"!==b.type?null:b)}var h,m,n,o,p,q,r,s,t,u,v=!1;for(o=[],p=[[]],h=0;h0&&r[0].elements.push(new g(s.combinator,"",s.index,s.currentFileInfo)),q.push(r);else for(n=0;n0&&(a.push(p[h]),u=p[h][t-1],p[h][t-1]=u.createDerived(u.elements,c.extendList));return v}function m(a,b){var c=b.createDerived(b.elements,b.extendList,b.evaldCondition);return c.copyVisibilityInfo(a),c}var n,o,p;if(o=[],p=l(o,b,c),!p)if(b.length>0)for(o=[],n=0;n0)for(b=0;b=0&&"\n"!==b.charAt(c);)e++;return"number"==typeof a&&(d=(b.slice(0,a).match(/\n/g)||"").length),{line:d,column:e}}}},{}],84:[function(a,b,c){var d=a("../tree"),e=a("./visitor"),f=a("../logger"),g=function(){this._visitor=new e(this),this.contexts=[],this.allExtendsStack=[[]]};g.prototype={run:function(a){return a=this._visitor.visit(a),a.allExtends=this.allExtendsStack[0],a},visitRule:function(a,b){b.visitDeeper=!1},visitMixinDefinition:function(a,b){b.visitDeeper=!1},visitRuleset:function(a,b){if(!a.root){var c,e,f,g,h=[],i=a.rules,j=i?i.length:0;for(c=0;c=0||(i=[k.selfSelectors[0]],g=n.findMatch(j,i),g.length&&(j.hasFoundMatches=!0,j.selfSelectors.forEach(function(a){var b=k.visibilityInfo();h=n.extendSelector(g,i,a,j.isVisible()),l=new d.Extend(k.selector,k.option,0,k.currentFileInfo,b),l.selfSelectors=h,h[h.length-1].extendList=[l],m.push(l),l.ruleset=k.ruleset,l.parent_ids=l.parent_ids.concat(k.parent_ids,j.parent_ids),k.firstExtendOnThisSelectorPath&&(l.firstExtendOnThisSelectorPath=!0,k.ruleset.paths.push(h))})));if(m.length){if(this.extendChainCount++,c>100){var o="{unable to calculate}",p="{unable to calculate}";try{o=m[0].selfSelectors[0].toCSS(),p=m[0].selector.toCSS()}catch(q){}throw{message:"extend circular reference detected. One of the circular extends is currently:"+o+":extend("+p+")"}}return m.concat(n.doExtendChaining(m,b,c+1))}return m},visitRule:function(a,b){b.visitDeeper=!1},visitMixinDefinition:function(a,b){b.visitDeeper=!1},visitSelector:function(a,b){b.visitDeeper=!1},visitRuleset:function(a,b){if(!a.root){var c,d,e,f,g=this.allExtendsStack[this.allExtendsStack.length-1],h=[],i=this;for(e=0;e0&&k[i.matched].combinator.value!==g?i=null:i.matched++,i&&(i.finished=i.matched===k.length,i.finished&&!a.allowAfter&&(e+1k&&l>0&&(m[m.length-1].elements=m[m.length-1].elements.concat(b[k].elements.slice(l)),l=0,k++),j=g.elements.slice(l,i.index).concat([h]).concat(c.elements.slice(1)),k===i.pathIndex&&f>0?m[m.length-1].elements=m[m.length-1].elements.concat(j):(m=m.concat(b.slice(k,i.pathIndex)),m.push(new d.Selector(j))),k=i.endPathIndex,l=i.endPathElementIndex,l>=b[k].elements.length&&(l=0,k++);return k0&&(m[m.length-1].elements=m[m.length-1].elements.concat(b[k].elements.slice(l)),k++),m=m.concat(b.slice(k,b.length)),m=m.map(function(a){var b=a.createDerived(a.elements);return e?b.ensureVisibility():b.ensureInvisibility(),b})},visitMedia:function(a,b){var c=a.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length-1]);c=c.concat(this.doExtendChaining(c,a.allExtends)),this.allExtendsStack.push(c)},visitMediaOut:function(a){var b=this.allExtendsStack.length-1;this.allExtendsStack.length=b},visitDirective:function(a,b){var c=a.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length-1]);c=c.concat(this.doExtendChaining(c,a.allExtends)),this.allExtendsStack.push(c)},visitDirectiveOut:function(a){var b=this.allExtendsStack.length-1;this.allExtendsStack.length=b}},b.exports=h},{"../logger":33,"../tree":62,"./visitor":91}],85:[function(a,b,c){function d(a){this.imports=[],this.variableImports=[],this._onSequencerEmpty=a,this._currentDepth=0}d.prototype.addImport=function(a){var b=this,c={callback:a,args:null,isReady:!1};return this.imports.push(c),function(){c.args=Array.prototype.slice.call(arguments,0),c.isReady=!0,b.tryRun()}},d.prototype.addVariableImport=function(a){this.variableImports.push(a)},d.prototype.tryRun=function(){this._currentDepth++;try{for(;;){for(;this.imports.length>0;){var a=this.imports[0];if(!a.isReady)return; -this.imports=this.imports.slice(1),a.callback.apply(null,a.args)}if(0===this.variableImports.length)break;var b=this.variableImports[0];this.variableImports=this.variableImports.slice(1),b()}}finally{this._currentDepth--}0===this._currentDepth&&this._onSequencerEmpty&&this._onSequencerEmpty()},b.exports=d},{}],86:[function(a,b,c){var d=a("../contexts"),e=a("./visitor"),f=a("./import-sequencer"),g=function(a,b){this._visitor=new e(this),this._importer=a,this._finish=b,this.context=new d.Eval,this.importCount=0,this.onceFileDetectionMap={},this.recursionDetector={},this._sequencer=new f(this._onSequencerEmpty.bind(this))};g.prototype={isReplacing:!1,run:function(a){try{this._visitor.visit(a)}catch(b){this.error=b}this.isFinished=!0,this._sequencer.tryRun()},_onSequencerEmpty:function(){this.isFinished&&this._finish(this.error)},visitImport:function(a,b){var c=a.options.inline;if(!a.css||c){var e=new d.Eval(this.context,this.context.frames.slice(0)),f=e.frames[0];this.importCount++,a.isVariableImport()?this._sequencer.addVariableImport(this.processImportNode.bind(this,a,e,f)):this.processImportNode(a,e,f)}b.visitDeeper=!1},processImportNode:function(a,b,c){var d,e=a.options.inline;try{d=a.evalForImport(b)}catch(f){f.filename||(f.index=a.index,f.filename=a.currentFileInfo.filename),a.css=!0,a.error=f}if(!d||d.css&&!e)this.importCount--,this.isFinished&&this._sequencer.tryRun();else{d.options.multiple&&(b.importMultiple=!0);for(var g=void 0===d.css,h=0;h0},resolveVisibility:function(a,b){if(!a.blocksVisibility()){if(this.isEmpty(a)&&!this.containsSilentNonBlockedChild(b))return;return a}var c=a.rules[0];if(this.keepOnlyVisibleChilds(c),!this.isEmpty(c))return a.ensureVisibility(),a.removeVisibilityBlock(),a},isVisibleRuleset:function(a){return!!a.firstRoot||!this.isEmpty(a)&&!(!a.root&&!this.hasVisibleSelector(a))}};var g=function(a){this._visitor=new e(this),this._context=a,this.utils=new f(a)};g.prototype={isReplacing:!0,run:function(a){return this._visitor.visit(a)},visitRule:function(a,b){if(!a.blocksVisibility()&&!a.variable)return a},visitMixinDefinition:function(a,b){a.frames=[]},visitExtend:function(a,b){},visitComment:function(a,b){if(!a.blocksVisibility()&&!a.isSilent(this._context))return a},visitMedia:function(a,b){var c=a.rules[0].rules;return a.accept(this._visitor),b.visitDeeper=!1,this.utils.resolveVisibility(a,c)},visitImport:function(a,b){if(!a.blocksVisibility())return a},visitDirective:function(a,b){return a.rules&&a.rules.length?this.visitDirectiveWithBody(a,b):this.visitDirectiveWithoutBody(a,b)},visitDirectiveWithBody:function(a,b){function c(a){var b=a.rules;return 1===b.length&&(!b[0].paths||0===b[0].paths.length)}function d(a){var b=a.rules;return c(a)?b[0].rules:b}var e=d(a);return a.accept(this._visitor),b.visitDeeper=!1,this.utils.isEmpty(a)||this._mergeRules(a.rules[0].rules),this.utils.resolveVisibility(a,e)},visitDirectiveWithoutBody:function(a,b){if(!a.blocksVisibility()){if("@charset"===a.name){if(this.charset){if(a.debugInfo){var c=new d.Comment("/* "+a.toCSS(this._context).replace(/\n/g,"")+" */\n");return c.debugInfo=a.debugInfo,this._visitor.visit(c)}return}this.charset=!0}return a}},checkValidNodes:function(a,b){if(a)for(var c=0;c0?a.accept(this._visitor):a.rules=null,b.visitDeeper=!1}return a.rules&&(this._mergeRules(a.rules),this._removeDuplicateRules(a.rules)),this.utils.isVisibleRuleset(a)&&(a.ensureVisibility(),d.splice(0,0,a)),1===d.length?d[0]:d},_compileRulesetPaths:function(a){a.paths&&(a.paths=a.paths.filter(function(a){var b;for(" "===a[0].elements[0].combinator.value&&(a[0].elements[0].combinator=new d.Combinator("")),b=0;b=0;e--)if(c=a[e],c instanceof d.Rule)if(f[c.name]){b=f[c.name],b instanceof d.Rule&&(b=f[c.name]=[f[c.name].toCSS(this._context)]);var g=c.toCSS(this._context);b.indexOf(g)!==-1?a.splice(e,1):b.push(g)}else f[c.name]=c}},_mergeRules:function(a){if(a){for(var b,c,e,f={},g=0;g1){c=b[0];var h=[],i=[];b.map(function(a){"+"===a.merge&&(i.length>0&&h.push(e(i)),i=[]),i.push(a)}),h.push(e(i)),c.value=g(h)}})}},visitAnonymous:function(a,b){if(!a.blocksVisibility())return a.accept(this._visitor),a}},b.exports=g},{"../tree":62,"./visitor":91}],91:[function(a,b,c){function d(a){return a}function e(a,b){var c,d;for(c in a)if(a.hasOwnProperty(c))switch(d=a[c],typeof d){case"function":d.prototype&&d.prototype.type&&(d.prototype.typeIndex=b++);break;case"object":b=e(d,b)}return b}var f=a("../tree"),g={visitDeeper:!0},h=!1,i=function(a){this._implementation=a,this._visitFnCache=[],h||(e(f,1),h=!0)};i.prototype={visit:function(a){if(!a)return a;var b=a.typeIndex;if(!b)return a;var c,e=this._visitFnCache,f=this._implementation,h=b<<1,i=1|h,j=e[h],k=e[i],l=g;if(l.visitDeeper=!0,j||(c="visit"+a.type,j=f[c]||d,k=f[c+"Out"]||d,e[h]=j,e[i]=k),j!==d){var m=j.call(f,a,l);f.isReplacing&&(a=m)}return l.visitDeeper&&a&&a.accept&&a.accept(this),k!=d&&k.call(f,a),a},visitArray:function(a,b){if(!a)return a;var c,d=a.length;if(b||!this._implementation.isReplacing){for(c=0;ck){for(var b=0,c=h.length-j;b0||b.isFileProtocol?"development":"production");var c=/!dumpLineNumbers:(comments|mediaquery|all)/.exec(a.location.hash);c&&(b.dumpLineNumbers=c[1]),void 0===b.useFileCache&&(b.useFileCache=!0),void 0===b.onReady&&(b.onReady=!0),b.javascriptEnabled=!(!b.javascriptEnabled&&!b.inlineJavaScript)}},{"./browser":3,"./utils":11}],2:[function(a,b,c){function d(a){a.filename&&console.warn(a),e.async||h.removeChild(i)}a("promise/polyfill");var e=a("../less/default-options")();if(window.less)for(key in window.less)window.less.hasOwnProperty(key)&&(e[key]=window.less[key]);a("./add-default-options")(window,e),e.plugins=e.plugins||[],window.LESS_PLUGINS&&(e.plugins=e.plugins.concat(window.LESS_PLUGINS));var f=b.exports=a("./index")(window,e);window.less=f;var g,h,i;e.onReady&&(/!watch/.test(window.location.hash)&&f.watch(),e.async||(g="body { display: none !important }",h=document.head||document.getElementsByTagName("head")[0],i=document.createElement("style"),i.type="text/css",i.styleSheet?i.styleSheet.cssText=g:i.appendChild(document.createTextNode(g)),h.appendChild(i)),f.registerStylesheetsImmediately(),f.pageLoadFinished=f.refresh("development"===f.env).then(d,d))},{"../less/default-options":16,"./add-default-options":1,"./index":8,"promise/polyfill":100}],3:[function(a,b,c){var d=a("./utils");b.exports={createCSS:function(a,b,c){var e=c.href||"",f="less:"+(c.title||d.extractId(e)),g=a.getElementById(f),h=!1,i=a.createElement("style");i.setAttribute("type","text/css"),c.media&&i.setAttribute("media",c.media),i.id=f,i.styleSheet||(i.appendChild(a.createTextNode(b)),h=null!==g&&g.childNodes.length>0&&i.childNodes.length>0&&g.firstChild.nodeValue===i.firstChild.nodeValue);var j=a.getElementsByTagName("head")[0];if(null===g||h===!1){var k=c&&c.nextSibling||null;k?k.parentNode.insertBefore(i,k):j.appendChild(i)}if(g&&h===!1&&g.parentNode.removeChild(g),i.styleSheet)try{i.styleSheet.cssText=b}catch(l){throw new Error("Couldn't reassign styleSheet.cssText.")}},currentScript:function(a){var b=a.document;return b.currentScript||function(){var a=b.getElementsByTagName("script");return a[a.length-1]}()}}},{"./utils":11}],4:[function(a,b,c){b.exports=function(a,b,c){var d=null;if("development"!==b.env)try{d="undefined"==typeof a.localStorage?null:a.localStorage}catch(e){}return{setCSS:function(a,b,e,f){if(d){c.info("saving "+a+" to cache.");try{d.setItem(a,f),d.setItem(a+":timestamp",b),e&&d.setItem(a+":vars",JSON.stringify(e))}catch(g){c.error('failed to save "'+a+'" to local storage for caching.')}}},getCSS:function(a,b,c){var e=d&&d.getItem(a),f=d&&d.getItem(a+":timestamp"),g=d&&d.getItem(a+":vars");if(c=c||{},f&&b.lastModified&&new Date(b.lastModified).valueOf()===new Date(f).valueOf()&&(!c&&!g||JSON.stringify(c)===g))return e}}}},{}],5:[function(a,b,c){var d=a("./utils"),e=a("./browser");b.exports=function(a,b,c){function f(b,f){var g,h,i="less-error-message:"+d.extractId(f||""),j='
  • {content}
  • ',k=a.document.createElement("div"),l=[],m=b.filename||f,n=m.match(/([^\/]+(\?.*)?)$/)[1];k.id=i,k.className="less-error-message",h="

    "+(b.type||"Syntax")+"Error: "+(b.message||"There is an error in your .less file")+'

    in '+n+" ";var o=function(a,b,c){void 0!==a.extract[b]&&l.push(j.replace(/\{line\}/,(parseInt(a.line,10)||0)+(b-1)).replace(/\{class\}/,c).replace(/\{content\}/,a.extract[b]))};b.line&&(o(b,0,""),o(b,1,"line"),o(b,2,""),h+="on line "+b.line+", column "+(b.column+1)+":

      "+l.join("")+"
    "),b.stack&&(b.extract||c.logLevel>=4)&&(h+="
    Stack Trace
    "+b.stack.split("\n").slice(1).join("
    ")),k.innerHTML=h,e.createCSS(a.document,[".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #dd6666;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.line {","color: #ff0000;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),k.style.cssText=["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),"development"===c.env&&(g=setInterval(function(){var b=a.document,c=b.body;c&&(b.getElementById(i)?c.replaceChild(k,b.getElementById(i)):c.insertBefore(k,c.firstChild),clearInterval(g))},10))}function g(b){var c=a.document.getElementById("less-error-message:"+d.extractId(b));c&&c.parentNode.removeChild(c)}function h(a){}function i(a){c.errorReporting&&"html"!==c.errorReporting?"console"===c.errorReporting?h(a):"function"==typeof c.errorReporting&&c.errorReporting("remove",a):g(a)}function j(a,d){var e="{line} {content}",f=a.filename||d,g=[],h=(a.type||"Syntax")+"Error: "+(a.message||"There is an error in your .less file")+" in "+f,i=function(a,b,c){void 0!==a.extract[b]&&g.push(e.replace(/\{line\}/,(parseInt(a.line,10)||0)+(b-1)).replace(/\{class\}/,c).replace(/\{content\}/,a.extract[b]))};a.line&&(i(a,0,""),i(a,1,"line"),i(a,2,""),h+=" on line "+a.line+", column "+(a.column+1)+":\n"+g.join("\n")),a.stack&&(a.extract||c.logLevel>=4)&&(h+="\nStack Trace\n"+a.stack),b.logger.error(h)}function k(a,b){c.errorReporting&&"html"!==c.errorReporting?"console"===c.errorReporting?j(a,b):"function"==typeof c.errorReporting&&c.errorReporting("add",a,b):f(a,b)}return{add:k,remove:i}}},{"./browser":3,"./utils":11}],6:[function(a,b,c){b.exports=function(b,c){var d=a("../less/environment/abstract-file-manager.js"),e={},f=function(){};return f.prototype=new d,f.prototype.alwaysMakePathsAbsolute=function(){return!0},f.prototype.join=function(a,b){return a?this.extractUrlParts(b,a).path:b},f.prototype.doXHR=function(a,d,e,f){function g(b,c,d){b.status>=200&&b.status<300?c(b.responseText,b.getResponseHeader("Last-Modified")):"function"==typeof d&&d(b.status,a)}var h=new XMLHttpRequest,i=!b.isFileProtocol||b.fileAsync;"function"==typeof h.overrideMimeType&&h.overrideMimeType("text/css"),c.debug("XHR: Getting '"+a+"'"),h.open("GET",a,i),h.setRequestHeader("Accept",d||"text/x-less, text/css; q=0.9, */*; q=0.5"),h.send(null),b.isFileProtocol&&!b.fileAsync?0===h.status||h.status>=200&&h.status<300?e(h.responseText):f(h.status,a):i?h.onreadystatechange=function(){4==h.readyState&&g(h,e,f)}:g(h,e,f)},f.prototype.supports=function(a,b,c,d){return!0},f.prototype.clearFileCache=function(){e={}},f.prototype.loadFile=function(a,b,c,d){b&&!this.isPathAbsolute(a)&&(a=b+a),a=c.ext?this.tryAppendExtension(a,c.ext):a,c=c||{};var f=this.extractUrlParts(a,window.location.href),g=f.url,h=this;return new Promise(function(a,b){if(c.useFileCache&&e[g])try{var d=e[g];return a({contents:d,filename:g,webInfo:{lastModified:new Date}})}catch(f){return b({filename:g,message:"Error loading file "+g+" error was "+f.message})}h.doXHR(g,c.mime,function(b,c){e[g]=b,a({contents:b,filename:g,webInfo:{lastModified:c}})},function(a,c){b({type:"File",message:"'"+c+"' wasn't found ("+a+")",href:g})})})},f}},{"../less/environment/abstract-file-manager.js":17}],7:[function(a,b,c){b.exports=function(){function b(){throw{type:"Runtime",message:"Image size functions are not supported in browser version of less"}}var c=a("./../less/functions/function-registry"),d={"image-size":function(a){return b(this,a),-1},"image-width":function(a){return b(this,a),-1},"image-height":function(a){return b(this,a),-1}};c.addMultiple(d)}},{"./../less/functions/function-registry":26}],8:[function(a,b,c){var d=a("./utils").addDataAttr,e=a("./browser");b.exports=function(b,c){function f(a){return JSON.parse(JSON.stringify(a||{}))}function g(a,b){var c=Array.prototype.slice.call(arguments,2);return function(){var d=c.concat(Array.prototype.slice.call(arguments,0));return a.apply(b,d)}}function h(a){for(var b,d=l.getElementsByTagName("style"),e=0;e=c&&console.log(a)},info:function(a){b.logLevel>=d&&console.log(a)},warn:function(a){b.logLevel>=e&&console.warn(a)},error:function(a){b.logLevel>=f&&console.error(a)}}]);for(var g=0;g0&&(a=a.slice(0,b)),b=a.lastIndexOf("/"),b<0&&(b=a.lastIndexOf("\\")),b<0?"":a.slice(0,b+1)},d.prototype.tryAppendExtension=function(a,b){return/(\.[a-z]*$)|([\?;].*)$/.test(a)?a:a+b},d.prototype.tryAppendLessExtension=function(a){return this.tryAppendExtension(a,".less")},d.prototype.supportsSync=function(){return!1},d.prototype.alwaysMakePathsAbsolute=function(){return!1},d.prototype.isPathAbsolute=function(a){return/^(?:[a-z-]+:|\/|\\|#)/i.test(a)},d.prototype.join=function(a,b){return a?a+b:b},d.prototype.pathDiff=function(a,b){var c,d,e,f,g=this.extractUrlParts(a),h=this.extractUrlParts(b),i="";if(g.hostPart!==h.hostPart)return"";for(d=Math.max(h.directories.length,g.directories.length),c=0;cparseInt(b[c])?-1:1;return 0},g.prototype.versionToString=function(a){for(var b="",c=0;c=0;h--){var i=g[h];if(i[f?"supportsSync":"supports"](a,b,c,e))return i}return null},e.prototype.addFileManager=function(a){this.fileManagers.push(a)},e.prototype.clearFileManagers=function(){this.fileManagers=[]},b.exports=e},{"../logger":37}],20:[function(a,b,c){var d=a("./function-registry"),e=a("../tree/anonymous"),f=a("../tree/keyword");d.addMultiple({"boolean":function(a){return a?f.True:f.False},"if":function(a,b,c){return a?b:c||new e}})},{"../tree/anonymous":48,"../tree/keyword":68,"./function-registry":26}],21:[function(a,b,c){function d(a,b,c){var d,f,g,h,i=b.alpha,j=c.alpha,k=[];g=j+i*(1-j);for(var l=0;l<3;l++)d=b.rgb[l]/255,f=c.rgb[l]/255,h=a(d,f),g&&(h=(j*f+i*(d-j*(d+f-h)))/g),k[l]=255*h;return new e(k,g)}var e=a("../tree/color"),f=a("./function-registry"),g={multiply:function(a,b){return a*b},screen:function(a,b){return a+b-a*b},overlay:function(a,b){return a*=2,a<=1?g.multiply(a,b):g.screen(a-1,b)},softlight:function(a,b){var c=1,d=a;return b>.5&&(d=1,c=a>.25?Math.sqrt(a):((16*a-12)*a+4)*a),a-(1-2*b)*d*(c-a)},hardlight:function(a,b){return g.overlay(b,a)},difference:function(a,b){return Math.abs(a-b)},exclusion:function(a,b){return a+b-2*a*b},average:function(a,b){return(a+b)/2},negation:function(a,b){return 1-Math.abs(a+b-1)}};for(var h in g)g.hasOwnProperty(h)&&(d[h]=d.bind(null,g[h]));f.addMultiple(d)},{"../tree/color":53,"./function-registry":26}],22:[function(a,b,c){function d(a){return Math.min(1,Math.max(0,a))}function e(a){return h.hsla(a.h,a.s,a.l,a.a)}function f(a){if(a instanceof i)return parseFloat(a.unit.is("%")?a.value/100:a.value);if("number"==typeof a)return a;throw{type:"Argument",message:"color functions take numbers as parameters"}}function g(a,b){return a instanceof i&&a.unit.is("%")?parseFloat(a.value*b/100):f(a)}var h,i=a("../tree/dimension"),j=a("../tree/color"),k=a("../tree/quoted"),l=a("../tree/anonymous"),m=a("./function-registry");h={rgb:function(a,b,c){return h.rgba(a,b,c,1)},rgba:function(a,b,c,d){var e=[a,b,c].map(function(a){return g(a,255)});return d=f(d),new j(e,d)},hsl:function(a,b,c){return h.hsla(a,b,c,1)},hsla:function(a,b,c,e){function g(a){return a=a<0?a+1:a>1?a-1:a,6*a<1?i+(j-i)*a*6:2*a<1?j:3*a<2?i+(j-i)*(2/3-a)*6:i}var i,j;return a=f(a)%360/360,b=d(f(b)),c=d(f(c)),e=d(f(e)),j=c<=.5?c*(b+1):c+b-c*b,i=2*c-j,h.rgba(255*g(a+1/3),255*g(a),255*g(a-1/3),e)},hsv:function(a,b,c){return h.hsva(a,b,c,1)},hsva:function(a,b,c,d){a=f(a)%360/360*360,b=f(b),c=f(c),d=f(d);var e,g;e=Math.floor(a/60%6),g=a/60-e;var i=[c,c*(1-b),c*(1-g*b),c*(1-(1-g)*b)],j=[[0,3,1],[2,0,1],[1,0,3],[1,2,0],[3,1,0],[0,1,2]];return h.rgba(255*i[j[e][0]],255*i[j[e][1]],255*i[j[e][2]],d)},hue:function(a){return new i(a.toHSL().h)},saturation:function(a){return new i(100*a.toHSL().s,"%")},lightness:function(a){return new i(100*a.toHSL().l,"%")},hsvhue:function(a){return new i(a.toHSV().h)},hsvsaturation:function(a){return new i(100*a.toHSV().s,"%")},hsvvalue:function(a){return new i(100*a.toHSV().v,"%")},red:function(a){return new i(a.rgb[0])},green:function(a){return new i(a.rgb[1])},blue:function(a){return new i(a.rgb[2])},alpha:function(a){return new i(a.toHSL().a)},luma:function(a){return new i(a.luma()*a.alpha*100,"%")},luminance:function(a){var b=.2126*a.rgb[0]/255+.7152*a.rgb[1]/255+.0722*a.rgb[2]/255;return new i(b*a.alpha*100,"%")},saturate:function(a,b,c){if(!a.rgb)return null;var f=a.toHSL();return f.s+="undefined"!=typeof c&&"relative"===c.value?f.s*b.value/100:b.value/100,f.s=d(f.s),e(f)},desaturate:function(a,b,c){var f=a.toHSL();return f.s-="undefined"!=typeof c&&"relative"===c.value?f.s*b.value/100:b.value/100,f.s=d(f.s),e(f)},lighten:function(a,b,c){var f=a.toHSL();return f.l+="undefined"!=typeof c&&"relative"===c.value?f.l*b.value/100:b.value/100,f.l=d(f.l),e(f)},darken:function(a,b,c){var f=a.toHSL();return f.l-="undefined"!=typeof c&&"relative"===c.value?f.l*b.value/100:b.value/100,f.l=d(f.l),e(f)},fadein:function(a,b,c){var f=a.toHSL();return f.a+="undefined"!=typeof c&&"relative"===c.value?f.a*b.value/100:b.value/100,f.a=d(f.a),e(f)},fadeout:function(a,b,c){var f=a.toHSL();return f.a-="undefined"!=typeof c&&"relative"===c.value?f.a*b.value/100:b.value/100,f.a=d(f.a),e(f)},fade:function(a,b){var c=a.toHSL();return c.a=b.value/100,c.a=d(c.a),e(c)},spin:function(a,b){var c=a.toHSL(),d=(c.h+b.value)%360;return c.h=d<0?360+d:d,e(c)},mix:function(a,b,c){a.toHSL&&b.toHSL||(console.log(b.type),console.dir(b)),c||(c=new i(50));var d=c.value/100,e=2*d-1,f=a.toHSL().a-b.toHSL().a,g=((e*f==-1?e:(e+f)/(1+e*f))+1)/2,h=1-g,k=[a.rgb[0]*g+b.rgb[0]*h,a.rgb[1]*g+b.rgb[1]*h,a.rgb[2]*g+b.rgb[2]*h],l=a.alpha*d+b.alpha*(1-d);return new j(k,l)},greyscale:function(a){return h.desaturate(a,new i(100))},contrast:function(a,b,c,d){if(!a.rgb)return null;if("undefined"==typeof c&&(c=h.rgba(255,255,255,1)),"undefined"==typeof b&&(b=h.rgba(0,0,0,1)),b.luma()>c.luma()){var e=c;c=b,b=e}return d="undefined"==typeof d?.43:f(d),a.luma()=v&&this.context.ieCompat!==!1?(h.warn("Skipped data-uri embedding of "+j+" because its size ("+u.length+" characters) exceeds IE8-safe "+v+" characters!"),g(this,f||a)):new d(new c('"'+u+'"',u,(!1),this.index,this.currentFileInfo),this.index,this.currentFileInfo)})}},{"../logger":37,"../tree/quoted":77,"../tree/url":82,"../utils":86,"./function-registry":26}],24:[function(a,b,c){var d=a("../tree/keyword"),e=a("./function-registry"),f={eval:function(){var a=this.value_,b=this.error_;if(b)throw b;if(null!=a)return a?d.True:d.False},value:function(a){this.value_=a},error:function(a){this.error_=a},reset:function(){this.value_=this.error_=null}};e.add("default",f.eval.bind(f)),b.exports=f},{"../tree/keyword":68,"./function-registry":26}],25:[function(a,b,c){var d=a("../tree/expression"),e=function(a,b,c,d){this.name=a.toLowerCase(),this.index=c,this.context=b,this.currentFileInfo=d,this.func=b.frames[0].functionRegistry.get(this.name)};e.prototype.isValid=function(){return Boolean(this.func)},e.prototype.call=function(a){return Array.isArray(a)&&(a=a.filter(function(a){return"Comment"!==a.type}).map(function(a){if("Expression"===a.type){var b=a.value.filter(function(a){return"Comment"!==a.type});return 1===b.length?b[0]:new d(b)}return a})),this.func.apply(this,a)},b.exports=e},{"../tree/expression":62}],26:[function(a,b,c){function d(a){return{_data:{},add:function(a,b){a=a.toLowerCase(),this._data.hasOwnProperty(a),this._data[a]=b},addMultiple:function(a){Object.keys(a).forEach(function(b){this.add(b,a[b])}.bind(this))},get:function(b){return this._data[b]||a&&a.get(b)},getLocalFunctions:function(){return this._data},inherit:function(){return d(this)},create:function(a){return d(a)}}}b.exports=d(null)},{}],27:[function(a,b,c){b.exports=function(b){var c={functionRegistry:a("./function-registry"),functionCaller:a("./function-caller")};return a("./boolean"),a("./default"),a("./color"),a("./color-blending"),a("./data-uri")(b),a("./math"),a("./number"),a("./string"),a("./svg")(b),a("./types"),c}},{"./boolean":20,"./color":22,"./color-blending":21,"./data-uri":23,"./default":24,"./function-caller":25,"./function-registry":26,"./math":29,"./number":30,"./string":31,"./svg":32,"./types":33}],28:[function(a,b,c){var d=a("../tree/dimension"),e=function(){};e._math=function(a,b,c){if(!(c instanceof d))throw{ +type:"Argument",message:"argument must be a number"};return null==b?b=c.unit:c=c.unify(),new d(a(parseFloat(c.value)),b)},b.exports=e},{"../tree/dimension":60}],29:[function(a,b,c){var d=a("./function-registry"),e=a("./math-helper.js"),f={ceil:null,floor:null,sqrt:null,abs:null,tan:"",sin:"",cos:"",atan:"rad",asin:"rad",acos:"rad"};for(var g in f)f.hasOwnProperty(g)&&(f[g]=e._math.bind(null,Math[g],f[g]));f.round=function(a,b){var c="undefined"==typeof b?0:b.value;return e._math(function(a){return a.toFixed(c)},null,a)},d.addMultiple(f)},{"./function-registry":26,"./math-helper.js":28}],30:[function(a,b,c){var d=a("../tree/dimension"),e=a("../tree/anonymous"),f=a("./function-registry"),g=a("./math-helper.js"),h=function(a,b){switch(b=Array.prototype.slice.call(b),b.length){case 0:throw{type:"Argument",message:"one or more arguments required"}}var c,f,g,h,i,j,k,l,m=[],n={};for(c=0;ci.value)&&(m[f]=g);else{if(void 0!==k&&j!==k)throw{type:"Argument",message:"incompatible types"};n[j]=m.length,m.push(g)}else Array.isArray(b[c].value)&&Array.prototype.push.apply(b,Array.prototype.slice.call(b[c].value));return 1==m.length?m[0]:(b=m.map(function(a){return a.toCSS(this.context)}).join(this.context.compress?",":", "),new e((a?"min":"max")+"("+b+")"))};f.addMultiple({min:function(){return h(!0,arguments)},max:function(){return h(!1,arguments)},convert:function(a,b){return a.convertTo(b.value)},pi:function(){return new d(Math.PI)},mod:function(a,b){return new d(a.value%b.value,a.unit)},pow:function(a,b){if("number"==typeof a&&"number"==typeof b)a=new d(a),b=new d(b);else if(!(a instanceof d&&b instanceof d))throw{type:"Argument",message:"arguments must be numbers"};return new d(Math.pow(a.value,b.value),a.unit)},percentage:function(a){var b=g._math(function(a){return 100*a},"%",a);return b}})},{"../tree/anonymous":48,"../tree/dimension":60,"./function-registry":26,"./math-helper.js":28}],31:[function(a,b,c){var d=a("../tree/quoted"),e=a("../tree/anonymous"),f=a("../tree/javascript"),g=a("./function-registry");g.addMultiple({e:function(a){return new e(a instanceof f?a.evaluated:a.value)},escape:function(a){return new e(encodeURI(a.value).replace(/=/g,"%3D").replace(/:/g,"%3A").replace(/#/g,"%23").replace(/;/g,"%3B").replace(/\(/g,"%28").replace(/\)/g,"%29"))},replace:function(a,b,c,e){var f=a.value;return c="Quoted"===c.type?c.value:c.toCSS(),f=f.replace(new RegExp(b.value,e?e.value:""),c),new d(a.quote||"",f,a.escaped)},"%":function(a){for(var b=Array.prototype.slice.call(arguments,1),c=a.value,e=0;e",k=0;k";return j+="',j=encodeURIComponent(j),j="data:image/svg+xml,"+j,new g(new f("'"+j+"'",j,(!1),this.index,this.currentFileInfo),this.index,this.currentFileInfo)})}},{"../tree/color":53,"../tree/dimension":60,"../tree/expression":62,"../tree/quoted":77,"../tree/url":82,"./function-registry":26}],33:[function(a,b,c){var d=a("../tree/keyword"),e=a("../tree/detached-ruleset"),f=a("../tree/dimension"),g=a("../tree/color"),h=a("../tree/quoted"),i=a("../tree/anonymous"),j=a("../tree/url"),k=a("../tree/operation"),l=a("./function-registry"),m=function(a,b){return a instanceof b?d.True:d.False},n=function(a,b){if(void 0===b)throw{type:"Argument",message:"missing the required second argument to isunit."};if(b="string"==typeof b.value?b.value:b,"string"!=typeof b)throw{type:"Argument",message:"Second argument to isunit should be a unit or a string."};return a instanceof f&&a.unit.is(b)?d.True:d.False},o=function(a){var b=Array.isArray(a.value)?a.value:Array(a);return b};l.addMultiple({isruleset:function(a){return m(a,e)},iscolor:function(a){return m(a,g)},isnumber:function(a){return m(a,f)},isstring:function(a){return m(a,h)},iskeyword:function(a){return m(a,d)},isurl:function(a){return m(a,j)},ispixel:function(a){return n(a,"px")},ispercentage:function(a){return n(a,"%")},isem:function(a){return n(a,"em")},isunit:n,unit:function(a,b){if(!(a instanceof f))throw{type:"Argument",message:"the first argument to unit must be a number"+(a instanceof k?". Have you forgotten parenthesis?":"")};return b=b?b instanceof d?b.value:b.toCSS():"",new f(a.value,b)},"get-unit":function(a){return new i(a.unit)},extract:function(a,b){return b=b.value-1,o(a)[b]},length:function(a){return new f(o(a).length)}})},{"../tree/anonymous":48,"../tree/color":53,"../tree/detached-ruleset":59,"../tree/dimension":60,"../tree/keyword":68,"../tree/operation":74,"../tree/quoted":77,"../tree/url":82,"./function-registry":26}],34:[function(a,b,c){var d=a("./contexts"),e=a("./parser/parser"),f=a("./less-error"),g=a("./utils");"undefined"==typeof Promise?a("promise"):Promise;b.exports=function(a){var b=function(a,b,c){this.less=a,this.rootFilename=c.filename,this.paths=b.paths||[],this.contents={},this.contentsIgnoredChars={},this.mime=b.mime,this.error=null,this.context=b,this.queue=[],this.files={}};return b.prototype.push=function(b,c,h,i,j){var k=this,l=this.context.pluginManager.Loader;this.queue.push(b);var m=function(a,c,d){k.queue.splice(k.queue.indexOf(b),1);var e=d===k.rootFilename;i.optional&&a?j(null,{rules:[]},!1,null):(k.files[d]||(k.files[d]={root:c,options:i}),a&&!k.error&&(k.error=a),j(a,c,e,d))},n={relativeUrls:this.context.relativeUrls,entryPath:h.entryPath,rootpath:h.rootpath,rootFilename:h.rootFilename},o=a.getFileManager(b,h.currentDirectory,this.context,a);if(!o)return void m({message:"Could not find a file-manager for "+b});var p,q=function(a){var b,c=a.filename,g=a.contents.replace(/^\uFEFF/,"");n.currentDirectory=o.getPath(c),n.relativeUrls&&(n.rootpath=o.join(k.context.rootpath||"",o.pathDiff(n.currentDirectory,n.entryPath)),!o.isPathAbsolute(n.rootpath)&&o.alwaysMakePathsAbsolute()&&(n.rootpath=o.join(n.entryPath,n.rootpath))),n.filename=c;var j=new d.Parse(k.context);j.processImports=!1,k.contents[c]=g,(h.reference||i.reference)&&(n.reference=!0),i.isPlugin?(b=l.evalPlugin(g,j,k,i.pluginArgs,n),b instanceof f?m(b,null,c):m(null,b,c)):i.inline?m(null,g,c):!k.files[c]||k.files[c].options.multiple||i.multiple?new e(j,k,n).parse(g,function(a,b){m(a,b,c)}):m(null,k.files[c].root,c)},r=g.clone(this.context);c&&(r.ext=i.isPlugin?".js":".less"),p=i.isPlugin?l.loadPlugin(b,h.currentDirectory,r,a,o):o.loadFile(b,h.currentDirectory,r,a,function(a,b){a?m(a):q(b)}),p&&p.then(q,m)},b}},{"./contexts":12,"./less-error":36,"./parser/parser":42,"./utils":86,promise:void 0}],35:[function(a,b,c){b.exports=function(b,c){var d,e,f,g,h,i,j={version:[3,0,0],data:a("./data"),tree:a("./tree"),Environment:h=a("./environment/environment"),AbstractFileManager:a("./environment/abstract-file-manager"),AbstractPluginLoader:a("./environment/abstract-plugin-loader"),environment:b=new h(b,c),visitors:a("./visitors"),Parser:a("./parser/parser"),functions:a("./functions")(b),contexts:a("./contexts"),SourceMapOutput:d=a("./source-map-output")(b),SourceMapBuilder:e=a("./source-map-builder")(d,b),ParseTree:f=a("./parse-tree")(e),ImportManager:g=a("./import-manager")(b),render:a("./render")(b,f,g),parse:a("./parse")(b,f,g),LessError:a("./less-error"),transformTree:a("./transform-tree"),utils:a("./utils"),PluginManager:a("./plugin-manager"),logger:a("./logger")},k=function(a){return function(){var b=Object.create(a.prototype);return a.apply(b,Array.prototype.slice.call(arguments,0)),b}},l=Object.create(j);for(var m in j.tree)if(i=j.tree[m],"function"==typeof i)l[m.toLowerCase()]=k(i);else{l[m]=Object.create(null);for(var n in i)l[m][n.toLowerCase()]=k(i[n])}return l}},{"./contexts":12,"./data":14,"./environment/abstract-file-manager":17,"./environment/abstract-plugin-loader":18,"./environment/environment":19,"./functions":27,"./import-manager":34,"./less-error":36,"./logger":37,"./parse":39,"./parse-tree":38,"./parser/parser":42,"./plugin-manager":43,"./render":44,"./source-map-builder":45,"./source-map-output":46,"./transform-tree":47,"./tree":65,"./utils":86,"./visitors":90}],36:[function(a,b,c){var d=a("./utils"),e=b.exports=function(a,b,c){Error.call(this);var e=a.filename||c;if(this.message=a.message,this.stack=a.stack,b&&e){var f=b.contents[e],g=d.getLocation(a.index,f),h=g.line,i=g.column,j=a.call&&d.getLocation(a.call,f).line,k=f.split("\n");if(this.type=a.type||"Syntax",this.filename=e,this.index=a.index,this.line="number"==typeof h?h+1:null,this.column=i,!this.line&&this.stack){var l=this.stack.match(/(|Function):(\d+):(\d+)/);l&&(l[2]&&(this.line=parseInt(l[2])-2),l[3]&&(this.column=parseInt(l[3])))}this.callLine=j+1,this.callExtract=k[j],this.extract=[k[this.line-2],k[this.line-1],k[this.line]]}};if("undefined"==typeof Object.create){var f=function(){};f.prototype=Error.prototype,e.prototype=new f}else e.prototype=Object.create(Error.prototype);e.prototype.constructor=e,e.prototype.toString=function(a){a=a||{};var b="",c=this.extract||[],d=[],e=function(a){return a};if(a.stylize){var f=typeof a.stylize;if("function"!==f)throw Error("options.stylize should be a function, got a "+f+"!");e=a.stylize}if(null!==this.line){if("string"==typeof c[0]&&d.push(e(this.line-1+" "+c[0],"grey")),"string"==typeof c[1]){var g=this.line+" ";c[1]&&(g+=c[1].slice(0,this.column)+e(e(e(c[1].substr(this.column,1),"bold")+c[1].slice(this.column+1),"red"),"inverse")),d.push(g)}"string"==typeof c[2]&&d.push(e(this.line+1+" "+c[2],"grey")),d=d.join("\n")+e("","reset")+"\n"}return b+=e(this.type+"Error: "+this.message,"red"),this.filename&&(b+=e(" in ","red")+this.filename),this.line&&(b+=e(" on line "+this.line+", column "+(this.column+1)+":","grey")),b+="\n"+d,this.callLine&&(b+=e("from ","red")+(this.filename||"")+"/n",b+=e(this.callLine,"grey")+" "+this.callExtract+"/n"),b}},{"./utils":86}],37:[function(a,b,c){b.exports={error:function(a){this._fireEvent("error",a)},warn:function(a){this._fireEvent("warn",a)},info:function(a){this._fireEvent("info",a)},debug:function(a){this._fireEvent("debug",a)},addListener:function(a){this._listeners.push(a)},removeListener:function(a){for(var b=0;b=97&&j<=122||j<34))switch(j){case 40:o++,e=h;continue;case 41:if(--o<0)return b("missing opening `(`",h);continue;case 59:o||c();continue;case 123:n++,d=h;continue;case 125:if(--n<0)return b("missing opening `{`",h);n||o||c();continue;case 92:if(h96)){if(k==j){l=1;break}if(92==k){if(h==m-1)return b("unescaped `\\`",h);h++}}if(l)continue;return b("unmatched `"+String.fromCharCode(j)+"`",i);case 47:if(o||h==m-1)continue;if(k=a.charCodeAt(h+1),47==k)for(h+=2;hd&&g>f?b("missing closing `}` or `*/`",d):b("missing closing `}`",d):0!==o?b("missing closing `)`",e):(c(!0),p)}},{}],41:[function(a,b,c){var d=a("./chunker");b.exports=function(){function a(d){for(var e,f,j,p=k.i,q=c,s=k.i-i,t=k.i+h.length-s,u=k.i+=d,v=b;k.i=0){j={index:k.i,text:v.substr(k.i,x+2-k.i),isLineComment:!1},k.i+=j.text.length-1,k.commentStore.push(j);continue}}break}if(e!==l&&e!==n&&e!==m&&e!==o)break}if(h=h.slice(d+k.i-u+s),i=k.i,!h.length){if(ce||k.i===e&&a&&!f)&&(e=k.i,f=a);var b=j.pop();h=b.current,i=k.i=b.i,c=b.j},k.forget=function(){j.pop()},k.isWhitespace=function(a){var c=k.i+(a||0),d=b.charCodeAt(c);return d===l||d===o||d===m||d===n},k.$re=function(b){k.i>i&&(h=h.slice(k.i-i),i=k.i);var c=b.exec(h);return c?(a(c[0].length),"string"==typeof c?c:1===c.length?c[0]:c):null},k.$char=function(c){return b.charAt(k.i)!==c?null:(a(1),c)},k.$str=function(c){for(var d=c.length,e=0;es||a=b.length;return k.i=b.length-1,furthestChar:b[k.i]}},k}},{"./chunker":40}],42:[function(a,b,c){var d=a("../less-error"),e=a("../tree"),f=a("../visitors"),g=a("./parser-input"),h=a("../utils"),i=a("../functions/function-registry"),j=function k(a,b,c){function j(a,e){throw new d({index:q.i,filename:c.filename,type:e||"Syntax",message:a},b)}function l(a,b,c){var d=a instanceof Function?a.call(p):q.$re(a);return d?d:void j(b||("string"==typeof a?"expected '"+a+"' got '"+q.currentChar()+"'":"unexpected token"))}function m(a,b){return q.$char(a)?a:void j(b||"expected '"+a+"' got '"+q.currentChar()+"'")}function n(a){var b=c.filename;return{lineNumber:h.getLocation(a,q.getInput()).line+1,fileName:b}}function o(a,c,e,f,g){var h,i=[],j=q;try{j.start(a,!1,function(a,b){g({message:a,index:b+e})});for(var k,l,m=0;k=c[m];m++)l=j.i,h=p[k](),h?(h._index=l+e,h._fileInfo=f,i.push(h)):i.push(null);var n=j.end();n.isFinished?g(null,i):g(!0,null)}catch(o){throw new d({index:o.index+e,message:o.message},b,f.filename)}}var p,q=g();return{parserInput:q,imports:b,fileInfo:c,parseNode:o,parse:function(g,h,j){var l,m,n,o,p=null,r="";if(m=j&&j.globalVars?k.serializeVars(j.globalVars)+"\n":"",n=j&&j.modifyVars?"\n"+k.serializeVars(j.modifyVars):"",a.pluginManager)for(var s=a.pluginManager.getPreProcessors(),t=0;t")}return b&&(q.$char("(")&&(h=this.args(!0).args,m(")")),p.important()&&(j=!0),p.end())?(q.forget(),new e.mixin.Call(b,h,k,c,j)):void q.restore()}},args:function(a){var b,c,d,f,g,h,i,k=p.entities,l={args:null,variadic:!1},m=[],n=[],o=[];for(q.save();;){if(a)h=p.detachedRuleset()||p.expression();else{if(q.commentStore.length=0,q.$str("...")){l.variadic=!0,q.$char(";")&&!b&&(b=!0),(b?n:o).push({variadic:!0});break}h=k.variable()||k.property()||k.literal()||k.keyword()}if(!h)break;f=null,h.throwAwayComments&&h.throwAwayComments(),g=h;var r=null;if(a?h.value&&1==h.value.length&&(r=h.value[0]):r=h,r&&(r instanceof e.Variable||r instanceof e.Property))if(q.$char(":")){if(m.length>0&&(b&&j("Cannot mix ; and , as delimiter types"),c=!0),g=p.detachedRuleset()||p.expression(),!g){if(!a)return q.restore(),l.args=[],l;j("could not understand value for named argument")}f=d=r.name}else if(q.$str("...")){if(!a){l.variadic=!0,q.$char(";")&&!b&&(b=!0),(b?n:o).push({name:h.name,variadic:!0});break}i=!0}else a||(d=f=r.name,g=null);g&&m.push(g),o.push({name:f,value:g,expand:i}),q.$char(",")||(q.$char(";")||b)&&(c&&j("Cannot mix ; and , as delimiter types"),b=!0,m.length>1&&(g=new e.Value(m)),n.push({name:d,value:g,expand:i}),d=null,m=[],c=!1)}return q.forget(),l.args=b?n:o,l},definition:function(){var a,b,c,d,f=[],g=!1;if(!("."!==q.currentChar()&&"#"!==q.currentChar()||q.peek(/^[^{]*\}/)))if(q.save(),b=q.$re(/^([#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+)\s*\(/)){a=b[1];var h=this.args(!1);if(f=h.args,g=h.variadic,!q.$char(")"))return void q.restore("Missing closing ')'");if(q.commentStore.length=0,q.$str("when")&&(d=l(p.conditions,"expected condition")),c=p.block())return q.forget(),new e.mixin.Definition(a,f,c,d,g);q.restore()}else q.forget()}},entity:function(){var a=this.entities;return this.comment()||a.literal()||a.variable()||a.url()||a.property()||a.call()||a.keyword()||a.javascript()},end:function(){return q.$char(";")||q.peek("}")},ieAlpha:function(){var a;if(q.$re(/^opacity=/i))return a=q.$re(/^\d+/),a||(a=l(p.entities.variable,"Could not parse alpha"),a="@{"+a.name.slice(1)+"}"),m(")"),new e.Quoted("","alpha(opacity="+a+")")},element:function(){var a,b,d,f=q.i;if(b=this.combinator(),a=q.$re(/^(?:\d+\.\d+|\d+)%/)||q.$re(/^(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/)||q.$char("*")||q.$char("&")||this.attribute()||q.$re(/^\([^&()@]+\)/)||q.$re(/^[\.#:](?=@)/)||this.entities.variableCurly(),a||(q.save(),q.$char("(")?(d=this.selector(!1))&&q.$char(")")?(a=new e.Paren(d),q.forget()):q.restore("Missing closing ')'"):q.forget()),a)return new e.Element(b,a,f,c)},combinator:function(){var a=q.currentChar();if("/"===a){q.save();var b=q.$re(/^\/[a-z]+\//i);if(b)return q.forget(),new e.Combinator(b);q.restore()}if(">"===a||"+"===a||"~"===a||"|"===a||"^"===a){for(q.i++,"^"===a&&"^"===q.currentChar()&&(a="^^",q.i++);q.isWhitespace();)q.i++;return new e.Combinator(a)}return new e.Combinator(q.isWhitespace(-1)?" ":null)},selector:function(a){var b,d,f,g,h,i,k,m=q.i;for(a=a!==!1;(a&&(d=this.extend())||a&&(i=q.$str("when"))||(g=this.element()))&&(i?k=l(this.conditions,"expected condition"):k?j("CSS guard can only be used at the end of selector"):d?h=h?h.concat(d):d:(h&&j("Extend can only be used at the end of selector"),f=q.currentChar(),b?b.push(g):b=[g],g=null),"{"!==f&&"}"!==f&&";"!==f&&","!==f&&")"!==f););return b?new e.Selector(b,h,k,m,c):void(h&&j("Extend must be used to extend a selector, it cannot be used on its own"))},attribute:function(){if(q.$char("[")){var a,b,c,d=this.entities;return(a=d.variableCurly())||(a=l(/^(?:[_A-Za-z0-9-\*]*\|)?(?:[_A-Za-z0-9-]|\\.)+/)),c=q.$re(/^[|~*$^]?=/),c&&(b=d.quoted()||q.$re(/^[0-9]+%/)||q.$re(/^[\w-]+/)||d.variableCurly()),m("]"),new e.Attribute(a,c,b)}},block:function(){var a;if(q.$char("{")&&(a=this.primary())&&q.$char("}"))return a},blockRuleset:function(){var a=this.block();return a&&(a=new e.Ruleset(null,a)),a},detachedRuleset:function(){var a=this.blockRuleset();if(a)return new e.DetachedRuleset(a)},ruleset:function(){var b,c,d,f;for(q.save(),a.dumpLineNumbers&&(f=n(q.i));;){if(c=this.selector(),!c)break;if(b?b.push(c):b=[c],q.commentStore.length=0,c.condition&&b.length>1&&j("Guards are only currently allowed on a single selector."),!q.$char(","))break;c.condition&&j("Guards are only currently allowed on a single selector."),q.commentStore.length=0}if(b&&(d=this.block())){q.forget();var g=new e.Ruleset(b,d,a.strictImports);return a.dumpLineNumbers&&(g.debugInfo=f),g}q.restore()},declaration:function(){var a,b,d,f,g,h=q.i,i=q.currentChar();if("."!==i&&"#"!==i&&"&"!==i&&":"!==i)if(q.save(),a=this.variable()||this.ruleProperty()){if(g="string"==typeof a,g&&(b=this.detachedRuleset()),q.commentStore.length=0,!b){if(f=!g&&a.length>1&&a.pop().value,b=this.anonymousValue())return q.forget(),new e.Declaration(a,b,(!1),f,h,c);b||(b=this.value()),d=this.important()}if(b&&this.end())return q.forget(),new e.Declaration(a,b,d,f,h,c);q.restore()}else q.restore()},anonymousValue:function(){var a=q.i,b=q.$re(/^([^@\$+\/'"*`(;{}-]*);/);if(b)return new e.Anonymous(b[1],a)},"import":function(){var a,b,d=q.i,f=q.$re(/^@import?\s+/);if(f){var g=(f?this.importOptions():null)||{};if(a=this.entities.quoted()||this.entities.url())return b=this.mediaFeatures(),q.$char(";")||(q.i=d,j("missing semi-colon or unrecognised media features on import")),b=b&&new e.Value(b),new e.Import(a,b,g,d,c);q.i=d,j("malformed import statement")}},importOptions:function(){var a,b,c,d={};if(!q.$char("("))return null;do if(a=this.importOption()){switch(b=a,c=!0,b){case"css":b="less",c=!1;break;case"once":b="multiple",c=!1}if(d[b]=c,!q.$char(","))break}while(a);return m(")"),d},importOption:function(){var a=q.$re(/^(less|css|multiple|once|inline|reference|optional)/);if(a)return a[1]},mediaFeature:function(){var a,b,d=this.entities,f=[];q.save();do a=d.keyword()||d.variable(),a?f.push(a):q.$char("(")&&(b=this.property(),a=this.value(),q.$char(")")?b&&a?f.push(new e.Paren(new e.Declaration(b,a,null,null,q.i,c,(!0)))):a?f.push(new e.Paren(a)):j("badly formed media feature definition"):j("Missing closing ')'","Parse"));while(a);if(q.forget(),f.length>0)return new e.Expression(f)},mediaFeatures:function(){var a,b=this.entities,c=[];do if(a=this.mediaFeature()){if(c.push(a),!q.$char(","))break}else if(a=b.variable(),a&&(c.push(a),!q.$char(",")))break;while(a);return c.length>0?c:null},media:function(){var b,d,f,g,h=q.i;return a.dumpLineNumbers&&(g=n(h)),q.save(),q.$str("@media")?(b=this.mediaFeatures(),d=this.block(),d||j("media definitions require block statements after any features"),q.forget(),f=new e.Media(d,b,h,c),a.dumpLineNumbers&&(f.debugInfo=g),f):void q.restore()},plugin:function(){ +var a,b,d,f=q.i,g=q.$re(/^@plugin?\s+/);if(g){if(b=this.pluginArgs(),d=b?{pluginArgs:b,isPlugin:!0}:{isPlugin:!0},a=this.entities.quoted()||this.entities.url())return q.$char(";")||(q.i=f,j("missing semi-colon on @plugin")),new e.Import(a,null,d,f,c);q.i=f,j("malformed @plugin statement")}},pluginArgs:function(){if(q.save(),!q.$char("("))return q.restore(),null;var a=q.$re(/^\s*([^\);]+)\)\s*/);return a[1]?(q.forget(),a[1].trim()):(q.restore(),null)},atrule:function(){var b,d,f,g,h,i,k,l=q.i,m=!0,o=!0;if("@"===q.currentChar()){if(d=this["import"]()||this.plugin()||this.media())return d;if(q.save(),b=q.$re(/^@[a-z-]+/)){switch(g=b,"-"==b.charAt(1)&&b.indexOf("-",2)>0&&(g="@"+b.slice(b.indexOf("-",2)+1)),g){case"@charset":h=!0,m=!1;break;case"@namespace":i=!0,m=!1;break;case"@keyframes":case"@counter-style":h=!0;break;case"@document":case"@supports":k=!0,o=!1;break;default:k=!0}return q.commentStore.length=0,h?(d=this.entity(),d||j("expected "+b+" identifier")):i?(d=this.expression(),d||j("expected "+b+" expression")):k&&(d=(q.$re(/^[^{;]+/)||"").trim(),m="{"==q.currentChar(),d&&(d=new e.Anonymous(d))),m&&(f=this.blockRuleset()),f||!m&&d&&q.$char(";")?(q.forget(),new e.AtRule(b,d,f,l,c,a.dumpLineNumbers?n(l):null,o)):void q.restore("at-rule options not recognised")}}},value:function(){var a,b=[],c=q.i;do if(a=this.expression(),a&&(b.push(a),!q.$char(",")))break;while(a);if(b.length>0)return new e.Value(b,c)},important:function(){if("!"===q.currentChar())return q.$re(/^! *important/)},sub:function(){var a,b;return q.save(),q.$char("(")?(a=this.addition(),a&&q.$char(")")?(q.forget(),b=new e.Expression([a]),b.parens=!0,b):void q.restore("Expected ')'")):void q.restore()},multiplication:function(){var a,b,c,d,f;if(a=this.operand()){for(f=q.isWhitespace(-1);;){if(q.peek(/^\/[*\/]/))break;if(q.save(),c=q.$char("/")||q.$char("*"),!c){q.forget();break}if(b=this.operand(),!b){q.restore();break}q.forget(),a.parensInOp=!0,b.parensInOp=!0,d=new e.Operation(c,[d||a,b],f),f=q.isWhitespace(-1)}return d||a}},addition:function(){var a,b,c,d,f;if(a=this.multiplication()){for(f=q.isWhitespace(-1);;){if(c=q.$re(/^[-+]\s+/)||!f&&(q.$char("+")||q.$char("-")),!c)break;if(b=this.multiplication(),!b)break;a.parensInOp=!0,b.parensInOp=!0,d=new e.Operation(c,[d||a,b],f),f=q.isWhitespace(-1)}return d||a}},conditions:function(){var a,b,c,d=q.i;if(a=this.condition()){for(;;){if(!q.peek(/^,\s*(not\s*)?\(/)||!q.$char(","))break;if(b=this.condition(),!b)break;c=new e.Condition("or",c||a,b,d)}return c||a}},condition:function(){function a(){return q.$str("or")}var b,c,d;if(b=this.conditionAnd(this)){if(c=a()){if(d=this.condition(),!d)return;b=new e.Condition(c,b,d)}return b}},conditionAnd:function(){function a(a){return a.negatedCondition()||a.parenthesisCondition()}function b(){return q.$str("and")}var c,d,f;if(c=a(this)){if(d=b()){if(f=this.conditionAnd(),!f)return;c=new e.Condition(d,c,f)}return c}},negatedCondition:function(){if(q.$str("not")){var a=this.parenthesisCondition();return a&&(a.negate=!a.negate),a}},parenthesisCondition:function(){function a(a){var b;return q.save(),(b=a.condition())&&q.$char(")")?(q.forget(),b):void q.restore()}var b;return q.save(),q.$str("(")?(b=a(this))?(q.forget(),b):(b=this.atomicCondition())?q.$char(")")?(q.forget(),b):void q.restore("expected ')' got '"+q.currentChar()+"'"):void q.restore():void q.restore()},atomicCondition:function(){var a,b,c,d,f=this.entities,g=q.i;if(a=this.addition()||f.keyword()||f.quoted())return q.$char(">")?d=q.$char("=")?">=":">":q.$char("<")?d=q.$char("=")?"<=":"<":q.$char("=")&&(d=q.$char(">")?"=>":q.$char("<")?"=<":"="),d?(b=this.addition()||f.keyword()||f.quoted(),b?c=new e.Condition(d,a,b,g,(!1)):j("expected expression")):c=new e.Condition("=",a,new e.Keyword("true"),g,(!1)),c},operand:function(){var a,b=this.entities;q.peek(/^-[@\$\(]/)&&(a=q.$char("-"));var c=this.sub()||b.dimension()||b.color()||b.variable()||b.property()||b.call()||b.colorKeyword();return a&&(c.parensInOp=!0,c=new e.Negative(c)),c},expression:function(){var a,b,c=[],d=q.i;do a=this.comment(),a?c.push(a):(a=this.addition()||this.entity(),a&&(c.push(a),q.peek(/^\/[\/*]/)||(b=q.$char("/"),b&&c.push(new e.Anonymous(b,d)))));while(a);if(c.length>0)return new e.Expression(c)},property:function(){var a=q.$re(/^(\*?-?[_a-zA-Z0-9-]+)\s*:/);if(a)return a[1]},ruleProperty:function(){function a(a){var b=q.i,c=q.$re(a);if(c)return g.push(b),f.push(c[1])}var b,d,f=[],g=[];q.save();var h=q.$re(/^([_a-zA-Z0-9-]+)\s*:/);if(h)return f=[new e.Keyword(h[1])],q.forget(),f;for(a(/^(\*?)/);;)if(!a(/^((?:[\w-]+)|(?:[@\$]\{[\w-]+\}))/))break;if(f.length>1&&a(/^((?:\+_|\+)?)\s*:/)){for(q.forget(),""===f[0]&&(f.shift(),g.shift()),d=0;d=b);c++);this.preProcessors.splice(c,0,{preProcessor:a,priority:b})},e.prototype.addPostProcessor=function(a,b){var c;for(c=0;c=b);c++);this.postProcessors.splice(c,0,{postProcessor:a,priority:b})},e.prototype.addFileManager=function(a){this.fileManagers.push(a)},e.prototype.getPreProcessors=function(){for(var a=[],b=0;b0){var d,e=JSON.stringify(this._sourceMapGenerator.toJSON());this.sourceMapURL?d=this.sourceMapURL:this._sourceMapFilename&&(d=this._sourceMapFilename),this.sourceMapURL=d,this.sourceMap=e}return this._css.join("")},b}},{}],47:[function(a,b,c){var d=a("./contexts"),e=a("./visitors"),f=a("./tree");b.exports=function(a,b){b=b||{};var c,g=b.variables,h=new d.Eval(b);"object"!=typeof g||Array.isArray(g)||(g=Object.keys(g).map(function(a){var b=g[a];return b instanceof f.Value||(b instanceof f.Expression||(b=new f.Expression([b])),b=new f.Value([b])),new f.Declaration("@"+a,b,(!1),null,0)}),h.frames=[new f.Ruleset(null,g)]);var i,j,k=[new e.JoinSelectorVisitor,new e.MarkVisibleSelectorsVisitor((!0)),new e.ExtendVisitor,new e.ToCSSVisitor({compress:Boolean(b.compress)})];if(b.pluginManager)for(j=b.pluginManager.visitor(),j.first();i=j.get();)i.isPreEvalVisitor&&i.run(a);c=a.eval(h);for(var l=0;l.5?j/(2-g-h):j/(g+h),g){case c:a=(d-e)/j+(d="===a||"=<"===a||"<="===a;case 1:return">"===a||">="===a;default:return!1}}}(this.op,this.lvalue.eval(a),this.rvalue.eval(a));return this.negate?!b:b},b.exports=e},{"./node":73}],57:[function(a,b,c){var d=function(a,b,c){var e="";if(a.dumpLineNumbers&&!a.compress)switch(a.dumpLineNumbers){case"comments":e=d.asComment(b);break;case"mediaquery":e=d.asMediaQuery(b);break;case"all":e=d.asComment(b)+(c||"")+d.asMediaQuery(b)}return e};d.asComment=function(a){return"/* line "+a.debugInfo.lineNumber+", "+a.debugInfo.fileName+" */\n"},d.asMediaQuery=function(a){var b=a.debugInfo.fileName;return/^[a-z]+:\/\//i.test(b)||(b="file://"+b),"@media -sass-debug-info{filename{font-family:"+b.replace(/([.:\/\\])/g,function(a){return"\\"==a&&(a="/"),"\\"+a})+"}line{font-family:\\00003"+a.debugInfo.lineNumber+"}}\n"},b.exports=d},{}],58:[function(a,b,c){function d(a,b){var c,d="",e=b.length,f={add:function(a){d+=a}};for(c=0;c-1e-6&&(d=c.toFixed(20).replace(/0+$/,"")),a&&a.compress){if(0===c&&this.unit.isLength())return void b.add(d);c>0&&c<1&&(d=d.substr(1))}b.add(d),this.unit.genCSS(a,b)},h.prototype.operate=function(a,b,c){var d=this._operate(a,b,this.value,c.value),e=this.unit.clone();if("+"===b||"-"===b)if(0===e.numerator.length&&0===e.denominator.length)e=c.unit.clone(),this.unit.backupUnit&&(e.backupUnit=this.unit.backupUnit);else if(0===c.unit.numerator.length&&0===e.denominator.length);else{if(c=c.convertTo(this.unit.usedUnits()),a.strictUnits&&c.unit.toString()!==e.toString())throw new Error("Incompatible units. Change the units or use the unit function. Bad units: '"+e.toString()+"' and '"+c.unit.toString()+"'.");d=this._operate(a,b,this.value,c.value)}else"*"===b?(e.numerator=e.numerator.concat(c.unit.numerator).sort(),e.denominator=e.denominator.concat(c.unit.denominator).sort(),e.cancel()):"/"===b&&(e.numerator=e.numerator.concat(c.unit.denominator).sort(),e.denominator=e.denominator.concat(c.unit.numerator).sort(),e.cancel());return new h(d,e)},h.prototype.compare=function(a){var b,c;if(a instanceof h){if(this.unit.isEmpty()||a.unit.isEmpty())b=this,c=a;else if(b=this.unify(),c=a.unify(),0!==b.unit.compare(c.unit))return;return d.numericCompare(b.value,c.value)}},h.prototype.unify=function(){return this.convertTo({length:"px",duration:"s",angle:"rad"})},h.prototype.convertTo=function(a){var b,c,d,f,g,i=this.value,j=this.unit.clone(),k={};if("string"==typeof a){for(b in e)e[b].hasOwnProperty(a)&&(k={},k[b]=a);a=k}g=function(a,b){return d.hasOwnProperty(a)?(b?i/=d[a]/d[f]:i*=d[a]/d[f],f):a};for(c in a)a.hasOwnProperty(c)&&(f=a[c],d=e[c],j.map(g));return j.cancel(),new h(i,j)},b.exports=h},{"../data/unit-conversions":15,"./color":53,"./node":73,"./unit":81}],61:[function(a,b,c){var d=a("./node"),e=a("./paren"),f=a("./combinator"),g=function(a,b,c,d,e){this.combinator=a instanceof f?a:new f(a),this.value="string"==typeof b?b.trim():b?b:"",this._index=c,this._fileInfo=d,this.copyVisibilityInfo(e),this.setParent(this.combinator,this)};g.prototype=new d,g.prototype.type="Element",g.prototype.accept=function(a){var b=this.value;this.combinator=a.visit(this.combinator),"object"==typeof b&&(this.value=a.visit(b))},g.prototype.eval=function(a){return new g(this.combinator,this.value.eval?this.value.eval(a):this.value,this.getIndex(),this.fileInfo(),this.visibilityInfo())},g.prototype.clone=function(){return new g(this.combinator,this.value,this.getIndex(),this.fileInfo(),this.visibilityInfo())},g.prototype.genCSS=function(a,b){b.add(this.toCSS(a),this.fileInfo(),this.getIndex())},g.prototype.toCSS=function(a){a=a||{};var b=this.value,c=a.firstSelector;return b instanceof e&&(a.firstSelector=!0),b=b.toCSS?b.toCSS(a):b,a.firstSelector=c,""===b&&"&"===this.combinator.value.charAt(0)?"":this.combinator.toCSS(a)+b},b.exports=g},{"./combinator":54,"./node":73,"./paren":75}],62:[function(a,b,c){var d=a("./node"),e=a("./paren"),f=a("./comment"),g=function(a){if(this.value=a,!a)throw new Error("Expression requires an array parameter")};g.prototype=new d,g.prototype.type="Expression",g.prototype.accept=function(a){this.value=a.visitArray(this.value)},g.prototype.eval=function(a){var b,c=this.parens&&!this.parensInOp,d=!1;return c&&a.inParenthesis(),this.value.length>1?b=new g(this.value.map(function(b){return b.eval(a)})):1===this.value.length?(this.value[0].parens&&!this.value[0].parensInOp&&(d=!0),b=this.value[0].eval(a)):b=this,c&&a.outOfParenthesis(),this.parens&&this.parensInOp&&!a.isMathOn()&&!d&&(b=new e(b)),b},g.prototype.genCSS=function(a,b){for(var c=0;c0&&c.length&&""===c[0].combinator.value&&(c[0].combinator.value=" "),d=d.concat(a[b].elements);this.selfSelectors=[new e(d)],this.selfSelectors[0].copyVisibilityInfo(this.visibilityInfo())},b.exports=f},{"./node":73,"./selector":79}],64:[function(a,b,c){var d=a("./node"),e=a("./media"),f=a("./url"),g=a("./quoted"),h=a("./ruleset"),i=a("./anonymous"),j=a("../utils"),k=a("../less-error"),l=function(a,b,c,d,e,f){if(this.options=c,this._index=d,this._fileInfo=e,this.path=a,this.features=b,this.allowRoot=!0,void 0!==this.options.less||this.options.inline)this.css=!this.options.less||this.options.inline;else{var g=this.getPath();g&&/[#\.\&\?]css([\?;].*)?$/.test(g)&&(this.css=!0)}this.copyVisibilityInfo(f),this.setParent(this.features,this),this.setParent(this.path,this)};l.prototype=new d,l.prototype.type="Import",l.prototype.accept=function(a){this.features&&(this.features=a.visit(this.features)),this.path=a.visit(this.path),this.options.isPlugin||this.options.inline||!this.root||(this.root=a.visit(this.root))},l.prototype.genCSS=function(a,b){this.css&&void 0===this.path._fileInfo.reference&&(b.add("@import ",this._fileInfo,this._index),this.path.genCSS(a,b),this.features&&(b.add(" "),this.features.genCSS(a,b)),b.add(";"))},l.prototype.getPath=function(){return this.path instanceof f?this.path.value.value:this.path.value},l.prototype.isVariableImport=function(){var a=this.path;return a instanceof f&&(a=a.value),!(a instanceof g)||a.containsVariables()},l.prototype.evalForImport=function(a){var b=this.path;return b instanceof f&&(b=b.value),new l(b.eval(a),this.features,this.options,this._index,this._fileInfo,this.visibilityInfo())},l.prototype.evalPath=function(a){var b=this.path.eval(a),c=this._fileInfo&&this._fileInfo.rootpath;if(!(b instanceof f)){if(c){var d=b.value;d&&a.isPathRelative(d)&&(b.value=c+d)}b.value=a.normalizePath(b.value)}return b},l.prototype.eval=function(a){var b=this.doEval(a);return(this.options.reference||this.blocksVisibility())&&(b.length||0===b.length?b.forEach(function(a){ +a.addVisibilityBlock()}):b.addVisibilityBlock()),b},l.prototype.doEval=function(a){var b,c,d=this.features&&this.features.eval(a);if(this.options.isPlugin){if(this.root&&this.root.eval)try{this.root.eval(a)}catch(f){throw f.message="Plugin error during evaluation",new k(f,this.root.imports,this.root.filename)}return c=a.frames[0]&&a.frames[0].functionRegistry,c&&this.root&&this.root.functions&&c.addMultiple(this.root.functions),[]}if(this.skip&&("function"==typeof this.skip&&(this.skip=this.skip()),this.skip))return[];if(this.options.inline){var g=new i(this.root,0,{filename:this.importedFilename,reference:this.path._fileInfo&&this.path._fileInfo.reference},(!0),(!0));return this.features?new e([g],this.features.value):[g]}if(this.css){var m=new l(this.evalPath(a),d,this.options,this._index);if(!m.css&&this.error)throw this.error;return m}return b=new h(null,j.copyArray(this.root.rules)),b.evalImports(a),this.features?new e(b.rules,this.features.value):b.rules},b.exports=l},{"../less-error":36,"../utils":86,"./anonymous":48,"./media":69,"./node":73,"./quoted":77,"./ruleset":78,"./url":82}],65:[function(a,b,c){var d=Object.create(null);d.Node=a("./node"),d.Color=a("./color"),d.AtRule=a("./atrule"),d.DetachedRuleset=a("./detached-ruleset"),d.Operation=a("./operation"),d.Dimension=a("./dimension"),d.Unit=a("./unit"),d.Keyword=a("./keyword"),d.Variable=a("./variable"),d.Property=a("./property"),d.Ruleset=a("./ruleset"),d.Element=a("./element"),d.Attribute=a("./attribute"),d.Combinator=a("./combinator"),d.Selector=a("./selector"),d.Quoted=a("./quoted"),d.Expression=a("./expression"),d.Declaration=a("./declaration"),d.Call=a("./call"),d.URL=a("./url"),d.Import=a("./import"),d.mixin={Call:a("./mixin-call"),Definition:a("./mixin-definition")},d.Comment=a("./comment"),d.Anonymous=a("./anonymous"),d.Value=a("./value"),d.JavaScript=a("./javascript"),d.Assignment=a("./assignment"),d.Condition=a("./condition"),d.Paren=a("./paren"),d.Media=a("./media"),d.UnicodeDescriptor=a("./unicode-descriptor"),d.Negative=a("./negative"),d.Extend=a("./extend"),d.VariableCall=a("./variable-call"),b.exports=d},{"./anonymous":48,"./assignment":49,"./atrule":50,"./attribute":51,"./call":52,"./color":53,"./combinator":54,"./comment":55,"./condition":56,"./declaration":58,"./detached-ruleset":59,"./dimension":60,"./element":61,"./expression":62,"./extend":63,"./import":64,"./javascript":66,"./keyword":68,"./media":69,"./mixin-call":70,"./mixin-definition":71,"./negative":72,"./node":73,"./operation":74,"./paren":75,"./property":76,"./quoted":77,"./ruleset":78,"./selector":79,"./unicode-descriptor":80,"./unit":81,"./url":82,"./value":83,"./variable":85,"./variable-call":84}],66:[function(a,b,c){var d=a("./js-eval-node"),e=a("./dimension"),f=a("./quoted"),g=a("./anonymous"),h=function(a,b,c,d){this.escaped=b,this.expression=a,this._index=c,this._fileInfo=d};h.prototype=new d,h.prototype.type="JavaScript",h.prototype.eval=function(a){var b=this.evaluateJavaScript(this.expression,a);return"number"==typeof b?new e(b):"string"==typeof b?new f('"'+b+'"',b,this.escaped,this._index):new g(Array.isArray(b)?b.join(", "):b)},b.exports=h},{"./anonymous":48,"./dimension":60,"./js-eval-node":67,"./quoted":77}],67:[function(a,b,c){var d=a("./node"),e=a("./variable"),f=function(){};f.prototype=new d,f.prototype.evaluateJavaScript=function(a,b){var c,d=this,f={};if(!b.javascriptEnabled)throw{message:"Inline JavaScript is not enabled. Is it set in your options?",filename:this.fileInfo().filename,index:this.getIndex()};a=a.replace(/@\{([\w-]+)\}/g,function(a,c){return d.jsify(new e("@"+c,d.getIndex(),d.fileInfo()).eval(b))});try{a=new Function("return ("+a+")")}catch(g){throw{message:"JavaScript evaluation error: "+g.message+" from `"+a+"`",filename:this.fileInfo().filename,index:this.getIndex()}}var h=b.frames[0].variables();for(var i in h)h.hasOwnProperty(i)&&(f[i.slice(1)]={value:h[i].value,toJS:function(){return this.value.eval(b).toCSS()}});try{c=a.call(f)}catch(g){throw{message:"JavaScript evaluation error: '"+g.name+": "+g.message.replace(/["]/g,"'")+"'",filename:this.fileInfo().filename,index:this.getIndex()}}return c},f.prototype.jsify=function(a){return Array.isArray(a.value)&&a.value.length>1?"["+a.value.map(function(a){return a.toCSS()}).join(", ")+"]":a.toCSS()},b.exports=f},{"./node":73,"./variable":85}],68:[function(a,b,c){var d=a("./node"),e=function(a){this.value=a};e.prototype=new d,e.prototype.type="Keyword",e.prototype.genCSS=function(a,b){if("%"===this.value)throw{type:"Syntax",message:"Invalid % without number"};b.add(this.value)},e.True=new e("true"),e.False=new e("false"),b.exports=e},{"./node":73}],69:[function(a,b,c){var d=a("./ruleset"),e=a("./value"),f=a("./selector"),g=a("./anonymous"),h=a("./expression"),i=a("./atrule"),j=a("../utils"),k=function(a,b,c,g,h){this._index=c,this._fileInfo=g;var i=new f([],null,null,this._index,this._fileInfo).createEmptySelectors();this.features=new e(b),this.rules=[new d(i,a)],this.rules[0].allowImports=!0,this.copyVisibilityInfo(h),this.allowRoot=!0,this.setParent(i,this),this.setParent(this.features,this),this.setParent(this.rules,this)};k.prototype=new i,k.prototype.type="Media",k.prototype.isRulesetLike=function(){return!0},k.prototype.accept=function(a){this.features&&(this.features=a.visit(this.features)),this.rules&&(this.rules=a.visitArray(this.rules))},k.prototype.genCSS=function(a,b){b.add("@media ",this._fileInfo,this._index),this.features.genCSS(a,b),this.outputRuleset(a,b,this.rules)},k.prototype.eval=function(a){a.mediaBlocks||(a.mediaBlocks=[],a.mediaPath=[]);var b=new k(null,[],this._index,this._fileInfo,this.visibilityInfo());return this.debugInfo&&(this.rules[0].debugInfo=this.debugInfo,b.debugInfo=this.debugInfo),b.features=this.features.eval(a),a.mediaPath.push(b),a.mediaBlocks.push(b),this.rules[0].functionRegistry=a.frames[0].functionRegistry.inherit(),a.frames.unshift(this.rules[0]),b.rules=[this.rules[0].eval(a)],a.frames.shift(),a.mediaPath.pop(),0===a.mediaPath.length?b.evalTop(a):b.evalNested(a)},k.prototype.evalTop=function(a){var b=this;if(a.mediaBlocks.length>1){var c=new f([],null,null,this.getIndex(),this.fileInfo()).createEmptySelectors();b=new d(c,a.mediaBlocks),b.multiMedia=!0,b.copyVisibilityInfo(this.visibilityInfo()),this.setParent(b,this)}return delete a.mediaBlocks,delete a.mediaPath,b},k.prototype.evalNested=function(a){var b,c,f=a.mediaPath.concat([this]);for(b=0;b0;b--)a.splice(b,0,new g("and"));return new h(a)})),this.setParent(this.features,this),new d([],[])},k.prototype.permute=function(a){if(0===a.length)return[];if(1===a.length)return a[0];for(var b=[],c=this.permute(a.slice(1)),d=0;d0){for(n=!0,k=0;k0)p=B;else if(p=A,q[A]+q[B]>1)throw{type:"Runtime",message:"Ambiguous use of `default()` found when matching for `"+this.format(t)+"`",index:this.getIndex(),filename:this.fileInfo().filename};for(k=0;kthis.params.length)return!1}c=Math.min(f,this.arity);for(var g=0;gb?1:void 0},d.prototype.blocksVisibility=function(){return null==this.visibilityBlocks&&(this.visibilityBlocks=0),0!==this.visibilityBlocks},d.prototype.addVisibilityBlock=function(){null==this.visibilityBlocks&&(this.visibilityBlocks=0),this.visibilityBlocks=this.visibilityBlocks+1},d.prototype.removeVisibilityBlock=function(){null==this.visibilityBlocks&&(this.visibilityBlocks=0),this.visibilityBlocks=this.visibilityBlocks-1},d.prototype.ensureVisibility=function(){this.nodeVisible=!0},d.prototype.ensureInvisibility=function(){this.nodeVisible=!1},d.prototype.isVisible=function(){return this.nodeVisible},d.prototype.visibilityInfo=function(){return{visibilityBlocks:this.visibilityBlocks,nodeVisible:this.nodeVisible}},d.prototype.copyVisibilityInfo=function(a){a&&(this.visibilityBlocks=a.visibilityBlocks,this.nodeVisible=a.nodeVisible)},b.exports=d},{}],74:[function(a,b,c){var d=a("./node"),e=a("./color"),f=a("./dimension"),g=function(a,b,c){this.op=a.trim(),this.operands=b,this.isSpaced=c};g.prototype=new d,g.prototype.type="Operation",g.prototype.accept=function(a){this.operands=a.visit(this.operands)},g.prototype.eval=function(a){var b=this.operands[0].eval(a),c=this.operands[1].eval(a);if(a.isMathOn()){if(b instanceof f&&c instanceof e&&(b=b.toColor()),c instanceof f&&b instanceof e&&(c=c.toColor()),!b.operate)throw{type:"Operation",message:"Operation on an invalid type"};return b.operate(a,this.op,c)}return new g(this.op,[b,c],this.isSpaced)},g.prototype.genCSS=function(a,b){this.operands[0].genCSS(a,b),this.isSpaced&&b.add(" "),b.add(this.op),this.isSpaced&&b.add(" "),this.operands[1].genCSS(a,b)},b.exports=g},{"./color":53,"./dimension":60,"./node":73}],75:[function(a,b,c){var d=a("./node"),e=function(a){this.value=a};e.prototype=new d,e.prototype.type="Paren",e.prototype.genCSS=function(a,b){b.add("("),this.value.genCSS(a,b),b.add(")")},e.prototype.eval=function(a){return new e(this.value.eval(a))},b.exports=e},{"./node":73}],76:[function(a,b,c){var d=a("./node"),e=a("./declaration"),f=function(a,b,c){this.name=a,this._index=b,this._fileInfo=c};f.prototype=new d,f.prototype.type="Property",f.prototype.eval=function(a){var b,c=this.name,d=a.pluginManager.less.visitors.ToCSSVisitor.prototype._mergeRules;if(this.evaluating)throw{type:"Name",message:"Recursive property reference for "+c,filename:this.fileInfo().filename,index:this.getIndex()};if(this.evaluating=!0,b=this.find(a.frames,function(b){var f,g=b.property(c);if(g){for(var h=0;hd){if(!c||c(g)){e=g.find(new i(a.elements.slice(d)),b,c);for(var j=0;j0&&b.add(k),a.firstSelector=!0,h[0].genCSS(a,b),a.firstSelector=!1,d=1;d0?(e=p.copyArray(a),f=e.pop(),g=d.createDerived(p.copyArray(f.elements))):g=d.createDerived([]),b.length>0){var h=c.combinator,i=b[0].elements[0];h.emptyOrWhitespace&&!i.combinator.emptyOrWhitespace&&(h=i.combinator),g.elements.push(new j(h,i.value,c._index,c._fileInfo)),g.elements=g.elements.concat(b[0].elements.slice(1))}if(0!==g.elements.length&&e.push(g),b.length>1){var k=b.slice(1);k=k.map(function(a){return a.createDerived(a.elements,[])}),e=e.concat(k)}return e}function g(a,b,c,d,e){var g;for(g=0;g0?d[d.length-1]=d[d.length-1].createDerived(d[d.length-1].elements.concat(a)):d.push(new i(a))}}function l(a,b,c){function m(a){var b;return a.value instanceof h?(b=a.value.value,b instanceof i?b:null):null}var n,o,p,q,r,s,t,u,v,w,x=!1;for(q=[],r=[[]],n=0;u=c.elements[n];n++)if("&"!==u.value){var y=m(u);if(null!=y){k(q,r);var z,A=[],B=[];for(z=l(A,b,y),x=x||z,p=0;p0&&t[0].elements.push(new j(u.combinator,"",u._index,u._fileInfo)),s.push(t);else for(p=0;p0&&(a.push(r[n]),w=r[n][v-1],r[n][v-1]=w.createDerived(w.elements,c.extendList));return x}function m(a,b){var c=b.createDerived(b.elements,b.extendList,b.evaldCondition);return c.copyVisibilityInfo(a),c}var n,o,q;if(o=[],q=l(o,b,c),!q)if(b.length>0)for(o=[],n=0;n0)for(b=0;b=0&&"\n"!==b.charAt(c);)e++;return"number"==typeof a&&(d=(b.slice(0,a).match(/\n/g)||"").length),{line:d,column:e}},copyArray:function(a){var b,c=a.length,d=new Array(c);for(b=0;b=0||(i=[k.selfSelectors[0]],g=n.findMatch(j,i),g.length&&(j.hasFoundMatches=!0,j.selfSelectors.forEach(function(a){var b=k.visibilityInfo();h=n.extendSelector(g,i,a,j.isVisible()),l=new d.Extend(k.selector,k.option,0,k.fileInfo(),b),l.selfSelectors=h,h[h.length-1].extendList=[l],m.push(l),l.ruleset=k.ruleset,l.parent_ids=l.parent_ids.concat(k.parent_ids,j.parent_ids),k.firstExtendOnThisSelectorPath&&(l.firstExtendOnThisSelectorPath=!0,k.ruleset.paths.push(h))})));if(m.length){if(this.extendChainCount++,c>100){var o="{unable to calculate}",p="{unable to calculate}";try{o=m[0].selfSelectors[0].toCSS(),p=m[0].selector.toCSS()}catch(q){}throw{message:"extend circular reference detected. One of the circular extends is currently:"+o+":extend("+p+")"}}return m.concat(n.doExtendChaining(m,b,c+1))}return m},visitDeclaration:function(a,b){b.visitDeeper=!1},visitMixinDefinition:function(a,b){b.visitDeeper=!1},visitSelector:function(a,b){b.visitDeeper=!1},visitRuleset:function(a,b){if(!a.root){var c,d,e,f,g=this.allExtendsStack[this.allExtendsStack.length-1],h=[],i=this;for(e=0;e0&&k[i.matched].combinator.value!==g?i=null:i.matched++,i&&(i.finished=i.matched===k.length,i.finished&&!a.allowAfter&&(e+1k&&l>0&&(m[m.length-1].elements=m[m.length-1].elements.concat(b[k].elements.slice(l)),l=0,k++),j=g.elements.slice(l,i.index).concat([h]).concat(c.elements.slice(1)),k===i.pathIndex&&f>0?m[m.length-1].elements=m[m.length-1].elements.concat(j):(m=m.concat(b.slice(k,i.pathIndex)),m.push(new d.Selector(j))),k=i.endPathIndex,l=i.endPathElementIndex,l>=b[k].elements.length&&(l=0,k++);return k0&&(m[m.length-1].elements=m[m.length-1].elements.concat(b[k].elements.slice(l)),k++),m=m.concat(b.slice(k,b.length)),m=m.map(function(a){var b=a.createDerived(a.elements);return e?b.ensureVisibility():b.ensureInvisibility(),b})},visitMedia:function(a,b){var c=a.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length-1]);c=c.concat(this.doExtendChaining(c,a.allExtends)),this.allExtendsStack.push(c)},visitMediaOut:function(a){var b=this.allExtendsStack.length-1;this.allExtendsStack.length=b},visitAtRule:function(a,b){var c=a.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length-1]);c=c.concat(this.doExtendChaining(c,a.allExtends)),this.allExtendsStack.push(c)},visitAtRuleOut:function(a){var b=this.allExtendsStack.length-1;this.allExtendsStack.length=b}},b.exports=i},{"../logger":37,"../tree":65,"../utils":86,"./visitor":94}],88:[function(a,b,c){function d(a){this.imports=[],this.variableImports=[],this._onSequencerEmpty=a,this._currentDepth=0}d.prototype.addImport=function(a){var b=this,c={callback:a,args:null,isReady:!1};return this.imports.push(c),function(){c.args=Array.prototype.slice.call(arguments,0),c.isReady=!0,b.tryRun()}},d.prototype.addVariableImport=function(a){this.variableImports.push(a)},d.prototype.tryRun=function(){this._currentDepth++;try{for(;;){for(;this.imports.length>0;){var a=this.imports[0];if(!a.isReady)return;this.imports=this.imports.slice(1),a.callback.apply(null,a.args)}if(0===this.variableImports.length)break;var b=this.variableImports[0];this.variableImports=this.variableImports.slice(1),b()}}finally{this._currentDepth--}0===this._currentDepth&&this._onSequencerEmpty&&this._onSequencerEmpty()},b.exports=d},{}],89:[function(a,b,c){var d=a("../contexts"),e=a("./visitor"),f=a("./import-sequencer"),g=a("../utils"),h=function(a,b){this._visitor=new e(this),this._importer=a,this._finish=b,this.context=new d.Eval,this.importCount=0,this.onceFileDetectionMap={},this.recursionDetector={},this._sequencer=new f(this._onSequencerEmpty.bind(this))};h.prototype={isReplacing:!1,run:function(a){try{this._visitor.visit(a)}catch(b){this.error=b}this.isFinished=!0,this._sequencer.tryRun()},_onSequencerEmpty:function(){this.isFinished&&this._finish(this.error)},visitImport:function(a,b){var c=a.options.inline;if(!a.css||c){var e=new d.Eval(this.context,g.copyArray(this.context.frames)),f=e.frames[0];this.importCount++,a.isVariableImport()?this._sequencer.addVariableImport(this.processImportNode.bind(this,a,e,f)):this.processImportNode(a,e,f)}b.visitDeeper=!1},processImportNode:function(a,b,c){var d,e=a.options.inline;try{d=a.evalForImport(b)}catch(f){f.filename||(f.index=a.getIndex(),f.filename=a.fileInfo().filename),a.css=!0,a.error=f}if(!d||d.css&&!e)this.importCount--,this.isFinished&&this._sequencer.tryRun();else{d.options.multiple&&(b.importMultiple=!0);for(var g=void 0===d.css,h=0;h0},resolveVisibility:function(a,b){if(!a.blocksVisibility()){if(this.isEmpty(a)&&!this.containsSilentNonBlockedChild(b))return;return a}var c=a.rules[0];if(this.keepOnlyVisibleChilds(c),!this.isEmpty(c))return a.ensureVisibility(),a.removeVisibilityBlock(),a},isVisibleRuleset:function(a){return!!a.firstRoot||!this.isEmpty(a)&&!(!a.root&&!this.hasVisibleSelector(a))}};var g=function(a){this._visitor=new e(this),this._context=a,this.utils=new f(a)};g.prototype={isReplacing:!0,run:function(a){return this._visitor.visit(a)},visitDeclaration:function(a,b){if(!a.blocksVisibility()&&!a.variable)return a},visitMixinDefinition:function(a,b){a.frames=[]},visitExtend:function(a,b){},visitComment:function(a,b){if(!a.blocksVisibility()&&!a.isSilent(this._context))return a},visitMedia:function(a,b){var c=a.rules[0].rules;return a.accept(this._visitor),b.visitDeeper=!1,this.utils.resolveVisibility(a,c)},visitImport:function(a,b){if(!a.blocksVisibility())return a},visitAtRule:function(a,b){return a.rules&&a.rules.length?this.visitAtRuleWithBody(a,b):this.visitAtRuleWithoutBody(a,b)},visitAnonymous:function(a,b){if(!a.blocksVisibility())return a.accept(this._visitor),a},visitAtRuleWithBody:function(a,b){function c(a){var b=a.rules;return 1===b.length&&(!b[0].paths||0===b[0].paths.length)}function d(a){var b=a.rules;return c(a)?b[0].rules:b}var e=d(a);return a.accept(this._visitor),b.visitDeeper=!1,this.utils.isEmpty(a)||this._mergeRules(a.rules[0].rules),this.utils.resolveVisibility(a,e)},visitAtRuleWithoutBody:function(a,b){if(!a.blocksVisibility()){if("@charset"===a.name){if(this.charset){if(a.debugInfo){var c=new d.Comment("/* "+a.toCSS(this._context).replace(/\n/g,"")+" */\n");return c.debugInfo=a.debugInfo,this._visitor.visit(c)}return}this.charset=!0}return a}},checkValidNodes:function(a,b){if(a)for(var c=0;c0?a.accept(this._visitor):a.rules=null,b.visitDeeper=!1}return a.rules&&(this._mergeRules(a.rules),this._removeDuplicateRules(a.rules)),this.utils.isVisibleRuleset(a)&&(a.ensureVisibility(),d.splice(0,0,a)),1===d.length?d[0]:d},_compileRulesetPaths:function(a){a.paths&&(a.paths=a.paths.filter(function(a){var b;for(" "===a[0].elements[0].combinator.value&&(a[0].elements[0].combinator=new d.Combinator("")),b=0;b=0;e--)if(c=a[e],c instanceof d.Declaration)if(f[c.name]){b=f[c.name],b instanceof d.Declaration&&(b=f[c.name]=[f[c.name].toCSS(this._context)]);var g=c.toCSS(this._context);b.indexOf(g)!==-1?a.splice(e,1):b.push(g)}else f[c.name]=c}},_mergeRules:function(a){if(a){for(var b={},c=[],e=0;e0){var b=a[0],c=[],e=[new d.Expression(c)];a.forEach(function(a){"+"===a.merge&&c.length>0&&e.push(new d.Expression(c=[])),c.push(a.value),b.important=b.important||a.important}),b.value=new d.Value(e)}})}}},b.exports=g},{"../tree":65,"./visitor":94}],94:[function(a,b,c){function d(a){return a}function e(a,b){var c,d;for(c in a)switch(d=a[c],typeof d){case"function":d.prototype&&d.prototype.type&&(d.prototype.typeIndex=b++);break;case"object":b=e(d,b)}return b}var f=a("../tree"),g={visitDeeper:!0},h=!1,i=function(a){this._implementation=a,this._visitFnCache=[],h||(e(f,1),h=!0)};i.prototype={visit:function(a){if(!a)return a;var b=a.typeIndex;if(!b)return a;var c,e=this._visitFnCache,f=this._implementation,h=b<<1,i=1|h,j=e[h],k=e[i],l=g;if(l.visitDeeper=!0,j||(c="visit"+a.type,j=f[c]||d,k=f[c+"Out"]||d,e[h]=j,e[i]=k),j!==d){var m=j.call(f,a,l);f.isReplacing&&(a=m)}return l.visitDeeper&&a&&a.accept&&a.accept(this),k!=d&&k.call(f,a),a},visitArray:function(a,b){if(!a)return a;var c,d=a.length;if(b||!this._implementation.isReplacing){for(c=0;ck){for(var b=0,c=h.length-j;b +// Browsers have good Promise support +require("promise/polyfill"); -var options = window.less || {}; +var options = require('../less/default-options')(); + +if (window.less) { + for (key in window.less) { + if (window.less.hasOwnProperty(key)) { + options[key] = window.less[key]; + } + } +} require("./add-default-options")(window, options); +options.plugins = options.plugins || []; + +if (window.LESS_PLUGINS) { + options.plugins = options.plugins.concat(window.LESS_PLUGINS); +} + var less = module.exports = require("./index")(window, options); window.less = less; @@ -31,7 +47,7 @@ if (options.onReady) { if (/!watch/.test(window.location.hash)) { less.watch(); } - // Simulate synchronous stylesheet loading by blocking page rendering + // Simulate synchronous stylesheet loading by hiding page rendering if (!options.async) { css = 'body { display: none !important }'; head = document.head || document.getElementsByTagName('head')[0]; diff --git a/lib/less-browser/cache.js b/lib/less-browser/cache.js index f3cf2b72d..2c8d6af34 100644 --- a/lib/less-browser/cache.js +++ b/lib/less-browser/cache.js @@ -17,8 +17,8 @@ module.exports = function(window, options, logger) { if (modifyVars) { cache.setItem(path + ':vars', JSON.stringify(modifyVars)); } - } catch(e) { - //TODO - could do with adding more robust error handling + } catch (e) { + // TODO - could do with adding more robust error handling logger.error('failed to save "' + path + '" to local storage for caching.'); } } diff --git a/lib/less-browser/error-reporting.js b/lib/less-browser/error-reporting.js index 264bf2a93..abf8e567a 100644 --- a/lib/less-browser/error-reporting.js +++ b/lib/less-browser/error-reporting.js @@ -24,7 +24,7 @@ module.exports = function(window, less, options) { } }; - if (e.extract) { + if (e.line) { errorline(e, 0, ''); errorline(e, 1, 'line'); errorline(e, 2, ''); @@ -112,7 +112,7 @@ module.exports = function(window, less, options) { } function removeErrorConsole(path) { - //no action + // no action } function removeError(path) { @@ -130,7 +130,7 @@ module.exports = function(window, less, options) { var filename = e.filename || rootHref; var errors = []; var content = (e.type || "Syntax") + "Error: " + (e.message || 'There is an error in your .less file') + - " in " + filename + " "; + " in " + filename; var errorline = function (e, i, classname) { if (e.extract[i] !== undefined) { @@ -140,11 +140,11 @@ module.exports = function(window, less, options) { } }; - if (e.extract) { + if (e.line) { errorline(e, 0, ''); errorline(e, 1, 'line'); errorline(e, 2, ''); - content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':\n' + + content += ' on line ' + e.line + ', column ' + (e.column + 1) + ':\n' + errors.join('\n'); } if (e.stack && (e.extract || options.logLevel >= 4)) { diff --git a/lib/less-browser/file-manager.js b/lib/less-browser/file-manager.js index d9727a1f8..5946afa43 100644 --- a/lib/less-browser/file-manager.js +++ b/lib/less-browser/file-manager.js @@ -1,4 +1,4 @@ -/*global window, XMLHttpRequest */ +/* global window, XMLHttpRequest */ module.exports = function(options, logger) { @@ -6,22 +6,7 @@ module.exports = function(options, logger) { var fileCache = {}; - //TODOS - move log somewhere. pathDiff and doing something similar in node. use pathDiff in the other browser file for the initial load - - function getXMLHttpRequest() { - if (window.XMLHttpRequest && (window.location.protocol !== "file:" || !("ActiveXObject" in window))) { - return new XMLHttpRequest(); - } else { - try { - /*global ActiveXObject */ - return new ActiveXObject("Microsoft.XMLHTTP"); - } catch (e) { - logger.error("browser doesn't support AJAX."); - return null; - } - } - } - + // TODOS - move log somewhere. pathDiff and doing something similar in node. use pathDiff in the other browser file for the initial load var FileManager = function() { }; @@ -38,7 +23,7 @@ module.exports = function(options, logger) { }; FileManager.prototype.doXHR = function doXHR(url, type, callback, errback) { - var xhr = getXMLHttpRequest(); + var xhr = new XMLHttpRequest(); var async = options.isFileProtocol ? options.fileAsync : true; if (typeof xhr.overrideMimeType === 'function') { @@ -82,36 +67,43 @@ module.exports = function(options, logger) { fileCache = {}; }; - FileManager.prototype.loadFile = function loadFile(filename, currentDirectory, options, environment, callback) { + FileManager.prototype.loadFile = function loadFile(filename, currentDirectory, options, environment) { + // TODO: Add prefix support like less-node? + // What about multiple paths? + if (currentDirectory && !this.isPathAbsolute(filename)) { filename = currentDirectory + filename; } + filename = options.ext ? this.tryAppendExtension(filename, options.ext) : filename; + options = options || {}; // sheet may be set to the stylesheet for the initial load or a collection of properties including // some context variables for imports var hrefParts = this.extractUrlParts(filename, window.location.href); var href = hrefParts.url; - - if (options.useFileCache && fileCache[href]) { - try { - var lessText = fileCache[href]; - callback(null, { contents: lessText, filename: href, webInfo: { lastModified: new Date() }}); - } catch (e) { - callback({filename: href, message: "Error loading file " + href + " error was " + e.message}); + var self = this; + + return new Promise(function(resolve, reject) { + if (options.useFileCache && fileCache[href]) { + try { + var lessText = fileCache[href]; + return resolve({ contents: lessText, filename: href, webInfo: { lastModified: new Date() }}); + } catch (e) { + return reject({ filename: href, message: "Error loading file " + href + " error was " + e.message }); + } } - return; - } - this.doXHR(href, options.mime, function doXHRCallback(data, lastModified) { - // per file cache - fileCache[href] = data; + self.doXHR(href, options.mime, function doXHRCallback(data, lastModified) { + // per file cache + fileCache[href] = data; - // Use remote copy (re-parse) - callback(null, { contents: data, filename: href, webInfo: { lastModified: lastModified }}); - }, function doXHRError(status, url) { - callback({ type: 'File', message: "'" + url + "' wasn't found (" + status + ")", href: href }); + // Use remote copy (re-parse) + resolve({ contents: data, filename: href, webInfo: { lastModified: lastModified }}); + }, function doXHRError(status, url) { + reject({ type: 'File', message: "'" + url + "' wasn't found (" + status + ")", href: href }); + }); }); }; diff --git a/lib/less-browser/index.js b/lib/less-browser/index.js index 8bb411d23..425d02050 100644 --- a/lib/less-browser/index.js +++ b/lib/less-browser/index.js @@ -8,42 +8,29 @@ var addDataAttr = require("./utils").addDataAttr, module.exports = function(window, options) { var document = window.document; var less = require('../less')(); - - //module.exports = less; + less.options = options; var environment = less.environment, FileManager = require("./file-manager")(options, less.logger), fileManager = new FileManager(); environment.addFileManager(fileManager); less.FileManager = FileManager; + less.PluginLoader = require("./plugin-loader"); require("./log-listener")(less, options); var errors = require("./error-reporting")(window, less, options); var cache = less.cache = options.cache || require("./cache")(window, options, less.logger); require('./image-size')(less.environment); - //Setup user functions + // Setup user functions - Deprecate? if (options.functions) { less.functions.functionRegistry.addMultiple(options.functions); } var typePattern = /^text\/(x-)?less$/; - function postProcessCSS(styles) { // deprecated, use a plugin for postprocesstasks - if (options.postProcessor && typeof options.postProcessor === 'function') { - styles = options.postProcessor.call(styles, styles) || styles; - } - return styles; - } - function clone(obj) { - var cloned = {}; - for (var prop in obj) { - if (obj.hasOwnProperty(prop)) { - cloned[prop] = obj[prop]; - } - } - return cloned; + return JSON.parse(JSON.stringify(obj || {})); } // only really needed for phantom @@ -67,7 +54,7 @@ module.exports = function(window, options) { var lessText = style.innerHTML || ''; instanceOptions.filename = document.location.href.replace(/#.*$/, ''); - /*jshint loopfunc:true */ + /* jshint loopfunc:true */ // use closure to store current style less.render(lessText, instanceOptions, bind(function(style, e, result) { @@ -123,7 +110,7 @@ module.exports = function(window, options) { } - //TODO add tests around how this behaves when reloading + // TODO add tests around how this behaves when reloading errors.remove(path); instanceOptions.rootFileInfo = newFileInfo; @@ -132,20 +119,20 @@ module.exports = function(window, options) { e.href = path; callback(e); } else { - result.css = postProcessCSS(result.css); cache.setCSS(sheet.href, webInfo.lastModified, instanceOptions.modifyVars, result.css); callback(null, result.css, data, sheet, webInfo, path); } }); } - fileManager.loadFile(sheet.href, null, instanceOptions, environment, function(e, loadedFile) { - if (e) { - callback(e); - return; - } - loadInitialFileCallback(loadedFile); - }); + fileManager.loadFile(sheet.href, null, instanceOptions, environment) + .then(function(loadedFile) { + loadInitialFileCallback(loadedFile); + }).catch(function(err) { + console.log(err); + callback(err); + }); + } function loadStyleSheets(callback, reload, modifyVars) { diff --git a/lib/less-browser/plugin-loader.js b/lib/less-browser/plugin-loader.js new file mode 100644 index 000000000..40ba6ebda --- /dev/null +++ b/lib/less-browser/plugin-loader.js @@ -0,0 +1,25 @@ +// TODO: Add tests for browser @plugin +/*global window */ + +var AbstractPluginLoader = require("../less/environment/abstract-plugin-loader.js"); + +/** + * Browser Plugin Loader + */ +var PluginLoader = function(less) { + this.less = less; + // shim for browser require? + this.require = require; +}; + +PluginLoader.prototype = new AbstractPluginLoader(); + +PluginLoader.prototype.loadPlugin = function(filename, basePath, context, environment, fileManager) { + return new Promise(function(fulfill, reject) { + fileManager.loadFile(filename, basePath, context, environment) + .then(fulfill).catch(reject); + }); +}; + +module.exports = PluginLoader; + diff --git a/lib/less-browser/utils.js b/lib/less-browser/utils.js index 6276e1eba..4ee140585 100644 --- a/lib/less-browser/utils.js +++ b/lib/less-browser/utils.js @@ -16,7 +16,7 @@ module.exports = { try { options[opt] = JSON.parse(tag.dataset[opt]); } - catch(_) {} + catch (_) {} } } } diff --git a/lib/less-node/file-manager.js b/lib/less-node/file-manager.js index d924e228e..542347c98 100644 --- a/lib/less-node/file-manager.js +++ b/lib/less-node/file-manager.js @@ -1,14 +1,10 @@ var path = require('path'), fs = require('./fs'), - PromiseConstructor, + PromiseConstructor = typeof Promise === 'undefined' ? require('promise') : Promise, AbstractFileManager = require("../less/environment/abstract-file-manager.js"); -try { - PromiseConstructor = typeof Promise === 'undefined' ? require('promise') : Promise; -} catch(e) { -} - var FileManager = function() { + this.files = {}; }; FileManager.prototype = new AbstractFileManager(); @@ -21,88 +17,122 @@ FileManager.prototype.supportsSync = function(filename, currentDirectory, option }; FileManager.prototype.loadFile = function(filename, currentDirectory, options, environment, callback) { + var fullFilename, - data, isAbsoluteFilename = this.isPathAbsolute(filename), - filenamesTried = []; + filenamesTried = [], + self = this, + prefix = filename.slice(0, 1), + explicit = prefix === "." || prefix === "/", + result = null; options = options || {}; - if (options.syncImport || !PromiseConstructor) { - data = this.loadFileSync(filename, currentDirectory, options, environment, 'utf-8'); - callback(data.error, data); - return; - } + var paths = isAbsoluteFilename ? [''] : [currentDirectory]; - var paths = isAbsoluteFilename ? [""] : [currentDirectory]; if (options.paths) { paths.push.apply(paths, options.paths); } + + // Search node_modules + if (!explicit) { paths.push.apply(paths, this.modulePaths); } + if (!isAbsoluteFilename && paths.indexOf('.') === -1) { paths.push('.'); } - // promise is guaranteed to be asyncronous - // which helps as it allows the file handle - // to be closed before it continues with the next file - return new PromiseConstructor(function(fulfill, reject) { + var prefixes = options.prefixes || ['']; + var fileParts = this.extractUrlParts(filename); + + if (options.syncImport) { + getFileData(returnData, returnData); + if (callback) { + callback(result.error, result); + } + else { + return result; + } + } + else { + // promise is guaranteed to be asyncronous + // which helps as it allows the file handle + // to be closed before it continues with the next file + return new PromiseConstructor(getFileData); + } + + function returnData(data) { + if (!data.filename) { + result = { error: data }; + } + else { + result = data; + } + } + + function getFileData(fulfill, reject) { (function tryPathIndex(i) { if (i < paths.length) { - fullFilename = filename; - if (paths[i]) { - fullFilename = path.join(paths[i], fullFilename); - } - fs.stat(fullFilename, function (err) { - if (err) { - filenamesTried.push(fullFilename); - tryPathIndex(i + 1); - } else { - fs.readFile(fullFilename, 'utf-8', function(e, data) { - if (e) { reject(e); return; } + (function tryPrefix(j) { + if (j < prefixes.length) { + fullFilename = fileParts.rawPath + prefixes[j] + fileParts.filename; + + if (paths[i]) { + fullFilename = path.join(paths[i], fullFilename); + } + + if (paths[i].indexOf('node_modules') > -1) { + try { + fullFilename = require.resolve(fullFilename); + } + catch (e) {} + } + + fullFilename = options.ext ? self.tryAppendExtension(fullFilename, options.ext) : fullFilename; + + if (self.files[fullFilename]) { + fulfill({ contents: self.files[fullFilename], filename: fullFilename}); + } + else { + var readFileArgs = [fullFilename]; + if (!options.rawBuffer) { + readFileArgs.push('utf-8'); + } + if (options.syncImport) { + try { + var data = fs.readFileSync.apply(this, readFileArgs); + self.files[fullFilename] = data; + fulfill({ contents: data, filename: fullFilename}); + } + catch (e) { + filenamesTried.push(fullFilename); + return tryPrefix(j + 1); + } + } + else { + readFileArgs.push(function(e, data) { + if (e) { + filenamesTried.push(fullFilename); + return tryPrefix(j + 1); + } + self.files[fullFilename] = data; + fulfill({ contents: data, filename: fullFilename}); + }); + fs.readFile.apply(this, readFileArgs); + } + + } - fulfill({ contents: data, filename: fullFilename}); - }); } - }); + else { + tryPathIndex(i + 1); + } + })(0); } else { reject({ type: 'File', message: "'" + filename + "' wasn't found. Tried - " + filenamesTried.join(",") }); } }(0)); - }); -}; - -FileManager.prototype.loadFileSync = function(filename, currentDirectory, options, environment, encoding) { - var fullFilename, paths, filenamesTried = [], isAbsoluteFilename = this.isPathAbsolute(filename) , data; - options = options || {}; - - paths = isAbsoluteFilename ? [""] : [currentDirectory]; - if (options.paths) { - paths.push.apply(paths, options.paths); - } - if (!isAbsoluteFilename && paths.indexOf('.') === -1) { - paths.push('.'); - } - - var err, result; - for (var i = 0; i < paths.length; i++) { - try { - fullFilename = filename; - if (paths[i]) { - fullFilename = path.join(paths[i], fullFilename); - } - filenamesTried.push(fullFilename); - fs.statSync(fullFilename); - break; - } catch (e) { - fullFilename = null; - } - } - - if (!fullFilename) { - err = { type: 'File', message: "'" + filename + "' wasn't found. Tried - " + filenamesTried.join(",") }; - result = { error: err }; - } else { - data = fs.readFileSync(fullFilename, encoding); - result = { contents: data, filename: fullFilename}; } +}; - return result; +FileManager.prototype.loadFileSync = function(filename, currentDirectory, options, environment) { + options.syncImport = true; + return this.loadFile(filename, currentDirectory, options, environment); }; module.exports = FileManager; diff --git a/lib/less-node/fs.js b/lib/less-node/fs.js index d124f8475..2a41c41aa 100644 --- a/lib/less-node/fs.js +++ b/lib/less-node/fs.js @@ -3,7 +3,7 @@ try { fs = require("graceful-fs"); } -catch(e) +catch (e) { fs = require("fs"); } diff --git a/lib/less-node/image-size.js b/lib/less-node/image-size.js index 660c4db34..01b963902 100644 --- a/lib/less-node/image-size.js +++ b/lib/less-node/image-size.js @@ -1,7 +1,7 @@ module.exports = function(environment) { var Dimension = require("../less/tree/dimension"), - Expression = require("../less/tree/expression"), - functionRegistry = require("./../less/functions/function-registry"); + Expression = require("../less/tree/expression"), + functionRegistry = require("./../less/functions/function-registry"); function imageSize(functionContext, filePathNode) { var filePath = filePathNode.value; diff --git a/lib/less-node/index.js b/lib/less-node/index.js index 9baaf8246..7b6fe7e74 100644 --- a/lib/less-node/index.js +++ b/lib/less-node/index.js @@ -3,7 +3,8 @@ var environment = require("./environment"), UrlFileManager = require("./url-file-manager"), createFromEnvironment = require("../less"), less = createFromEnvironment(environment, [new FileManager(), new UrlFileManager()]), - lesscHelper = require('./lessc-helper'); + lesscHelper = require('./lessc-helper'), + path = require('path'); // allow people to create less with their own environment less.createFromEnvironment = createFromEnvironment; @@ -12,61 +13,12 @@ less.PluginLoader = require("./plugin-loader"); less.fs = require("./fs"); less.FileManager = FileManager; less.UrlFileManager = UrlFileManager; -less.formatError = function(ctx, options) { - options = options || {}; - var message = ""; - var extract = ctx.extract; - var error = []; - var stylize = options.color ? lesscHelper.stylize : function (str) { return str; }; - - // only output a stack if it isn't a less error - if (ctx.stack && !ctx.type) { return stylize(ctx.stack, 'red'); } - - if (!ctx.hasOwnProperty('index') || !extract) { - return ctx.stack || ctx.message; - } - - if (typeof extract[0] === 'string') { - error.push(stylize((ctx.line - 1) + ' ' + extract[0], 'grey')); - } - - if (typeof extract[1] === 'string') { - var errorTxt = ctx.line + ' '; - if (extract[1]) { - errorTxt += extract[1].slice(0, ctx.column) + - stylize(stylize(stylize(extract[1].substr(ctx.column, 1), 'bold') + - extract[1].slice(ctx.column + 1), 'red'), 'inverse'); - } - error.push(errorTxt); - } - - if (typeof extract[2] === 'string') { - error.push(stylize((ctx.line + 1) + ' ' + extract[2], 'grey')); - } - error = error.join('\n') + stylize('', 'reset') + '\n'; - - message += stylize(ctx.type + 'Error: ' + ctx.message, 'red'); - if (ctx.filename) { - message += stylize(' in ', 'red') + ctx.filename + - stylize(' on line ' + ctx.line + ', column ' + (ctx.column + 1) + ':', 'grey'); - } - - message += '\n' + error; - - if (ctx.callLine) { - message += stylize('from ', 'red') + (ctx.filename || '') + '/n'; - message += stylize(ctx.callLine, 'grey') + ' ' + ctx.callExtract + '/n'; - } - - return message; -}; - -less.writeError = function (ctx, options) { - options = options || {}; - if (options.silent) { return; } - console.error(less.formatError(ctx, options)); -}; +// Set up options +less.options = require('../less/default-options')(); +less.options.paths = [ + path.join(process.cwd(), "node_modules") +]; // provide image-size functionality require('./image-size')(less.environment); diff --git a/lib/less-node/lessc-helper.js b/lib/less-node/lessc-helper.js index 7b57ce290..6dedbe3ca 100644 --- a/lib/less-node/lessc-helper.js +++ b/lib/less-node/lessc-helper.js @@ -3,7 +3,7 @@ // helper functions for lessc var lessc_helper = { - //Stylize a string + // Stylize a string stylize : function(str, style) { var styles = { 'reset' : [0, 0], @@ -19,49 +19,49 @@ var lessc_helper = { '\x1b[' + styles[style][1] + 'm'; }, - //Print command line options + // Print command line options printUsage: function() { console.log("usage: lessc [option option=parameter ...] [destination]"); console.log(""); console.log("If source is set to `-' (dash or hyphen-minus), input is read from stdin."); console.log(""); console.log("options:"); - console.log(" -h, --help Prints help (this message) and exit."); - console.log(" --include-path=PATHS Sets include paths. Separated by `:'. `;' also supported on windows."); - console.log(" -M, --depends Outputs a makefile import dependency list to stdout."); - console.log(" --no-color Disables colorized output."); - console.log(" --no-ie-compat Disables IE compatibility checks."); - console.log(" --no-js Disables JavaScript in less files"); - console.log(" -l, --lint Syntax check only (lint)."); - console.log(" -s, --silent Suppresses output of error messages."); - console.log(" --strict-imports Forces evaluation of imports."); - console.log(" --insecure Allows imports from insecure https hosts."); - console.log(" -v, --version Prints version number and exit."); - console.log(" --verbose Be verbose."); - console.log(" --source-map[=FILENAME] Outputs a v3 sourcemap to the filename (or output filename.map)."); - console.log(" --source-map-rootpath=X Adds this path onto the sourcemap filename and less file paths."); - console.log(" --source-map-basepath=X Sets sourcemap base path, defaults to current working directory."); - console.log(" --source-map-less-inline Puts the less files into the map instead of referencing them."); - console.log(" --source-map-map-inline Puts the map (and any less files) as a base64 data uri into the output css file."); - console.log(" --source-map-url=URL Sets a custom URL to map file, for sourceMappingURL comment"); - console.log(" in generated CSS file."); - console.log(" -rp, --rootpath=URL Sets rootpath for url rewriting in relative imports and urls"); - console.log(" Works with or without the relative-urls option."); - console.log(" -ru, --relative-urls Re-writes relative urls to the base less file."); - console.log(" -sm=on|off Turns on or off strict math, where in strict mode, math."); - console.log(" --strict-math=on|off Requires brackets. This option may default to on and then"); - console.log(" be removed in the future."); - console.log(" -su=on|off Allows mixed units, e.g. 1px+1em or 1px*1px which have units"); - console.log(" --strict-units=on|off that cannot be represented."); - console.log(" --global-var='VAR=VALUE' Defines a variable that can be referenced by the file."); - console.log(" --modify-var='VAR=VALUE' Modifies a variable already declared in the file."); - console.log(" --url-args='QUERYSTRING' Adds params into url tokens (e.g. 42, cb=42 or 'a=1&b=2')"); - console.log(" --plugin=PLUGIN=OPTIONS Loads a plugin. You can also omit the --plugin= if the plugin begins"); - console.log(" less-plugin. E.g. the clean css plugin is called less-plugin-clean-css"); - console.log(" once installed (npm install less-plugin-clean-css), use either with"); - console.log(" --plugin=less-plugin-clean-css or just --clean-css"); - console.log(" specify options afterwards e.g. --plugin=less-plugin-clean-css=\"advanced\""); - console.log(" or --clean-css=\"advanced\""); + console.log(" -h, --help Prints help (this message) and exit."); + console.log(" --include-path=PATHS Sets include paths. Separated by `:'. `;' also supported on windows."); + console.log(" -M, --depends Outputs a makefile import dependency list to stdout."); + console.log(" --no-color Disables colorized output."); + console.log(" --ie-compat Enables IE8 compatibility checks."); + console.log(" --js Enables inline JavaScript in less files"); + console.log(" -l, --lint Syntax check only (lint)."); + console.log(" -s, --silent Suppresses output of error messages."); + console.log(" --strict-imports Forces evaluation of imports."); + console.log(" --insecure Allows imports from insecure https hosts."); + console.log(" -v, --version Prints version number and exit."); + console.log(" --verbose Be verbose."); + console.log(" --source-map[=FILENAME] Outputs a v3 sourcemap to the filename (or output filename.map)."); + console.log(" --source-map-rootpath=X Adds this path onto the sourcemap filename and less file paths."); + console.log(" --source-map-basepath=X Sets sourcemap base path, defaults to current working directory."); + console.log(" --source-map-include-source Puts the less files into the map instead of referencing them."); + console.log(" --source-map-inline Puts the map (and any less files) as a base64 data uri into the output css file."); + console.log(" --source-map-url=URL Sets a custom URL to map file, for sourceMappingURL comment"); + console.log(" in generated CSS file."); + console.log(" -rp, --rootpath=URL Sets rootpath for url rewriting in relative imports and urls"); + console.log(" Works with or without the relative-urls option."); + console.log(" -ru, --relative-urls Re-writes relative urls to the base less file."); + console.log(" -sm=on|off Turns on or off strict math, where in strict mode, math."); + console.log(" --strict-math=on|off Requires brackets. This option may default to on and then"); + console.log(" be removed in the future."); + console.log(" -su=on|off Allows mixed units, e.g. 1px+1em or 1px*1px which have units"); + console.log(" --strict-units=on|off that cannot be represented."); + console.log(" --global-var='VAR=VALUE' Defines a variable that can be referenced by the file."); + console.log(" --modify-var='VAR=VALUE' Modifies a variable already declared in the file."); + console.log(" --url-args='QUERYSTRING' Adds params into url tokens (e.g. 42, cb=42 or 'a=1&b=2')"); + console.log(" --plugin=PLUGIN=OPTIONS Loads a plugin. You can also omit the --plugin= if the plugin begins"); + console.log(" less-plugin. E.g. the clean css plugin is called less-plugin-clean-css"); + console.log(" once installed (npm install less-plugin-clean-css), use either with"); + console.log(" --plugin=less-plugin-clean-css or just --clean-css"); + console.log(" specify options afterwards e.g. --plugin=less-plugin-clean-css=\"advanced\""); + console.log(" or --clean-css=\"advanced\""); console.log(""); console.log("-------------------------- Deprecated ----------------"); console.log(" --line-numbers=TYPE Outputs filename and line numbers."); diff --git a/lib/less-node/plugin-loader.js b/lib/less-node/plugin-loader.js index 29b28376d..6bbc62d1d 100644 --- a/lib/less-node/plugin-loader.js +++ b/lib/less-node/plugin-loader.js @@ -1,91 +1,54 @@ -var path = require("path"); +var path = require("path"), + PromiseConstructor = typeof Promise === 'undefined' ? require('promise') : Promise, + AbstractPluginLoader = require("../less/environment/abstract-plugin-loader.js"); + /** * Node Plugin Loader */ var PluginLoader = function(less) { this.less = less; -}; -PluginLoader.prototype.tryLoadPlugin = function(name, argument) { - var plugin = this.tryRequirePlugin(name); - if (plugin) { - // support plugins being a function - // so that the plugin can be more usable programmatically - if (typeof plugin === "function") { - plugin = new plugin(); - } - if (plugin.minVersion) { - if (this.compareVersion(plugin.minVersion, this.less.version) < 0) { - console.log("plugin " + name + " requires version " + this.versionToString(plugin.minVersion)); - return null; - } - } - if (argument) { - if (!plugin.setOptions) { - console.log("options have been provided but the plugin " + name + "does not support any options"); - return null; - } - try { - plugin.setOptions(argument); + this.require = require; + this.requireRelative = function(prefix) { + prefix = path.dirname(prefix); + return function(id) { + var str = id.substr(0, 2); + if (str === '..' || str === './') { + return require(path.join(prefix, id)); } - catch(e) { - console.log("Error setting options on plugin " + name); - console.log(e.message); - return null; + else { + return require(id); } - } - return plugin; - } - return null; -}; -PluginLoader.prototype.compareVersion = function(aVersion, bVersion) { - for (var i = 0; i < aVersion.length; i++) { - if (aVersion[i] !== bVersion[i]) { - return parseInt(aVersion[i]) > parseInt(bVersion[i]) ? -1 : 1; - } - } - return 0; -}; -PluginLoader.prototype.versionToString = function(version) { - var versionString = ""; - for (var i = 0; i < version.length; i++) { - versionString += (versionString ? "." : "") + version[i]; - } - return versionString; -}; -PluginLoader.prototype.tryRequirePlugin = function(name) { - // is at the same level as the less.js module - try { - return require("../../../" + name); - } - catch(e) { - } - // is installed as a sub dependency of the current folder - try { - return require(path.join(process.cwd(), "node_modules", name)); - } - catch(e) { - } - // is referenced relative to the current directory - try { - return require(path.join(process.cwd(), name)); - } - catch(e) { - } - // unlikely - would have to be a dependency of where this code was running (less.js)... - if (name[0] !== '.') { - try { - return require(name); - } - catch(e) { - } - } + }; + }; }; -PluginLoader.prototype.printUsage = function(plugins) { - for (var i = 0; i < plugins.length; i++) { - var plugin = plugins[i]; - if (plugin.printUsage) { - plugin.printUsage(); - } - } + +PluginLoader.prototype = new AbstractPluginLoader(); + +PluginLoader.prototype.loadPlugin = function(filename, basePath, context, environment, fileManager) { + var self = this; + var prefix = filename.slice(0, 1); + var explicit = prefix === "." || prefix === "/" || filename.slice(-3).toLowerCase() === ".js"; + if (!explicit) { + context.prefixes = ['less-plugin-', '']; + } + + return new PromiseConstructor(function(fulfill, reject) { + fileManager.loadFile(filename, basePath, context, environment).then( + function(data) { + try { + self.require = self.requireRelative(data.filename); + fulfill(data); + } + catch (e) { + reject(e); + } + } + ).catch(function(err) { + reject(err); + }); + }); + }; + module.exports = PluginLoader; + diff --git a/lib/less-node/url-file-manager.js b/lib/less-node/url-file-manager.js index 83a5653b2..d3884b4e2 100644 --- a/lib/less-node/url-file-manager.js +++ b/lib/less-node/url-file-manager.js @@ -21,7 +21,7 @@ UrlFileManager.prototype.loadFile = function(filename, currentDirectory, options return new PromiseConstructor(function(fulfill, reject) { if (request === undefined) { try { request = require('request'); } - catch(e) { request = null; } + catch (e) { request = null; } } if (!request) { reject({ type: 'File', message: "optional dependency 'request' required to import over http(s)\n" }); diff --git a/lib/less-rhino/index.js b/lib/less-rhino/index.js index 9d0f2313b..e82132c8d 100644 --- a/lib/less-rhino/index.js +++ b/lib/less-rhino/index.js @@ -1,6 +1,5 @@ /* jshint rhino:true, unused: false */ -/* jscs:disable validateIndentation */ -/*global name:true, less, loadStyleSheet, os */ +/* global name:true, less, loadStyleSheet, os */ function formatError(ctx, options) { options = options || {}; @@ -9,7 +8,7 @@ function formatError(ctx, options) { var extract = ctx.extract; var error = []; -// var stylize = options.color ? require('./lessc_helper').stylize : function (str) { return str; }; + // var stylize = options.color ? require('./lessc_helper').stylize : function (str) { return str; }; var stylize = function (str) { return str; }; // only output a stack if it isn't a less error @@ -81,7 +80,7 @@ function loadStyleSheet(sheet, callback, reload, remaining) { } try { callback(e, root, input, sheet, { local: false, lastModified: 0, remaining: remaining }, sheetName); - } catch(e) { + } catch (e) { writeError(e); } }); @@ -146,25 +145,10 @@ function writeFile(filename, content) { // Command line integration via Rhino (function (args) { - var options = { - depends: false, - compress: false, - cleancss: false, - max_line_len: -1, - silent: false, - verbose: false, - lint: false, - paths: [], - color: true, - strictImports: false, - rootpath: '', - relativeUrls: false, - ieCompat: true, - strictMath: false, - strictUnits: false - }; + var options = require('../default-options'); + var continueProcessing = true, - currentErrorcode; + currentErrorcode; var checkArgFunc = function(arg, option) { if (!option) { @@ -226,8 +210,8 @@ function writeFile(filename, content) { break; case 'h': case 'help': - //TODO -// require('../lib/less/lessc_helper').printUsage(); + // TODO + // require('../lib/less/lessc_helper').printUsage(); continueProcessing = false; break; case 'x': @@ -270,7 +254,7 @@ function writeFile(filename, content) { .split(os.type().match(/Windows/) ? /:(?!\\)|;/ : ':') .map(function(p) { if (p) { -// return path.resolve(process.cwd(), p); + // return path.resolve(process.cwd(), p); return p; } }); @@ -351,20 +335,20 @@ function writeFile(filename, content) { var name = args[0]; if (name && name != '-') { -// name = path.resolve(process.cwd(), name); + // name = path.resolve(process.cwd(), name); } var output = args[1]; var outputbase = args[1]; if (output) { options.sourceMapOutputFilename = output; -// output = path.resolve(process.cwd(), output); + // output = path.resolve(process.cwd(), output); if (warningMessages) { console.log(warningMessages); } } -// options.sourceMapBasepath = process.cwd(); -// options.sourceMapBasepath = ''; + // options.sourceMapBasepath = process.cwd(); + // options.sourceMapBasepath = ''; if (options.sourceMap === true) { console.log("output: " + output); @@ -382,24 +366,25 @@ function writeFile(filename, content) { console.log("lessc: no inout files"); console.log(""); // TODO -// require('../lib/less/lessc_helper').printUsage(); + // require('../lib/less/lessc_helper').printUsage(); currentErrorcode = 1; return; } -// var ensureDirectory = function (filepath) { -// var dir = path.dirname(filepath), -// cmd, -// existsSync = fs.existsSync || path.existsSync; -// if (!existsSync(dir)) { -// if (mkdirp === undefined) { -// try {mkdirp = require('mkdirp');} -// catch(e) { mkdirp = null; } -// } -// cmd = mkdirp && mkdirp.sync || fs.mkdirSync; -// cmd(dir); -// } -// }; + /* + var ensureDirectory = function (filepath) { + var dir = path.dirname(filepath), + cmd, + existsSync = fs.existsSync || path.existsSync; + if (!existsSync(dir)) { + if (mkdirp === undefined) { + try {mkdirp = require('mkdirp');} + catch(e) { mkdirp = null; } + } + cmd = mkdirp && mkdirp.sync || fs.mkdirSync; + cmd(dir); + } + }; */ if (options.depends) { if (!outputbase) { @@ -443,7 +428,7 @@ function writeFile(filename, content) { } }); } - catch(e) { + catch (e) { writeError(e, options); quit(1); } diff --git a/lib/less/contexts.js b/lib/less/contexts.js index 545280b34..4d21f7662 100644 --- a/lib/less/contexts.js +++ b/lib/less/contexts.js @@ -40,18 +40,18 @@ contexts.Parse = function(options) { }; var evalCopyProperties = [ - 'paths', // additional include paths - 'compress', // whether to compress - 'ieCompat', // whether to enforce IE compatibility (IE8 data-uri) - 'strictMath', // whether math has to be within parenthesis - 'strictUnits', // whether units need to evaluate correctly - 'sourceMap', // whether to output a source map - 'importMultiple', // whether we are currently importing multiple copies - 'urlArgs', // whether to add args into url tokens - 'javascriptEnabled',// option - whether JavaScript is enabled. if undefined, defaults to true - 'pluginManager', // Used as the plugin manager for the session - 'importantScope' // used to bubble up !important statements - ]; + 'paths', // additional include paths + 'compress', // whether to compress + 'ieCompat', // whether to enforce IE compatibility (IE8 data-uri) + 'strictMath', // whether math has to be within parenthesis + 'strictUnits', // whether units need to evaluate correctly + 'sourceMap', // whether to output a source map + 'importMultiple', // whether we are currently importing multiple copies + 'urlArgs', // whether to add args into url tokens + 'javascriptEnabled', // option - whether Inline JavaScript is enabled. if undefined, defaults to false + 'pluginManager', // Used as the plugin manager for the session + 'importantScope' // used to bubble up !important statements +]; contexts.Eval = function(options, frames) { copyFromOriginal(options, this, evalCopyProperties); @@ -73,7 +73,11 @@ contexts.Eval.prototype.outOfParenthesis = function () { this.parensStack.pop(); }; +contexts.Eval.prototype.mathOn = true; contexts.Eval.prototype.isMathOn = function () { + if (!this.mathOn) { + return false; + } return this.strictMath ? (this.parensStack && this.parensStack.length) : true; }; @@ -83,13 +87,13 @@ contexts.Eval.prototype.isPathRelative = function (path) { contexts.Eval.prototype.normalizePath = function( path ) { var - segments = path.split("/").reverse(), - segment; + segments = path.split("/").reverse(), + segment; path = []; while (segments.length !== 0 ) { segment = segments.pop(); - switch( segment ) { + switch ( segment ) { case ".": break; case "..": @@ -108,4 +112,4 @@ contexts.Eval.prototype.normalizePath = function( path ) { return path.join("/"); }; -//todo - do the same for the toCSS ? +// todo - do the same for the toCSS ? diff --git a/lib/less/default-options.js b/lib/less/default-options.js new file mode 100644 index 000000000..09c0b3cfe --- /dev/null +++ b/lib/less/default-options.js @@ -0,0 +1,65 @@ +// Export a new default each time +module.exports = function() { + return { + /* Outputs a makefile import dependency list to stdout. */ + depends: false, + + /* Compress using less built-in compression. + * This does an okay job but does not utilise all the tricks of + * dedicated css compression. */ + compress: false, + + /* Runs the less parser and just reports errors without any output. */ + lint: false, + + /* Sets available include paths. + * If the file in an @import rule does not exist at that exact location, + * less will look for it at the location(s) passed to this option. + * You might use this for instance to specify a path to a library which + * you want to be referenced simply and relatively in the less files. */ + paths: [], + + /* color output in the terminal */ + color: true, + + /* The strictImports controls whether the compiler will allow an @import inside of either + * @media blocks or (a later addition) other selector blocks. + * See: https://github.com/less/less.js/issues/656 */ + strictImports: false, + + /* Allow Imports from Insecure HTTPS Hosts */ + insecure: false, + + /* Allows you to add a path to every generated import and url in your css. + * This does not affect less import statements that are processed, just ones + * that are left in the output css. */ + rootpath: '', + + /* By default URLs are kept as-is, so if you import a file in a sub-directory + * that references an image, exactly the same URL will be output in the css. + * This option allows you to re-write URL's in imported files so that the + * URL is always relative to the base imported file */ + relativeUrls: false, + + /* Compatibility with IE8. Used for limiting data-uri length */ + ieCompat: false, // true until 3.0 + + /* Without this option on, Less will try and process all math in your css */ + strictMath: false, + + /* Without this option, less attempts to guess at the output unit when it does maths. */ + strictUnits: false, + + /* Effectively the declaration is put at the top of your base Less file, + * meaning it can be used but it also can be overridden if this variable + * is defined in the file. */ + globalVars: null, + + /* As opposed to the global variable option, this puts the declaration at the + * end of your base file, meaning it will override anything defined in your Less file. */ + modifyVars: null, + + /* This option allows you to specify a argument to go on to every URL. */ + urlArgs: '' + } +} \ No newline at end of file diff --git a/lib/less/environment/abstract-file-manager.js b/lib/less/environment/abstract-file-manager.js index d9a2f90b2..05911492c 100644 --- a/lib/less/environment/abstract-file-manager.js +++ b/lib/less/environment/abstract-file-manager.js @@ -35,13 +35,14 @@ abstractFileManager.prototype.alwaysMakePathsAbsolute = function() { abstractFileManager.prototype.isPathAbsolute = function(filename) { return (/^(?:[a-z-]+:|\/|\\|#)/i).test(filename); }; - +// TODO: pull out / replace? abstractFileManager.prototype.join = function(basePath, laterPath) { if (!basePath) { return laterPath; } return basePath + laterPath; }; + abstractFileManager.prototype.pathDiff = function pathDiff(url, baseUrl) { // diff between two paths to create a relative path @@ -75,7 +76,7 @@ abstractFileManager.prototype.extractUrlParts = function extractUrlParts(url, ba var urlPartsRegex = /^((?:[a-z-]+:)?\/{2}(?:[^\/\?#]*\/)|([\/\\]))?((?:[^\/\\\?#]*[\/\\])*)([^\/\\\?#]*)([#\?].*)?$/i, urlParts = url.match(urlPartsRegex), - returner = {}, directories = [], i, baseUrlParts; + returner = {}, rawDirectories = [], directories = [], i, baseUrlParts; if (!urlParts) { throw new Error("Could not parse sheet href - '" + url + "'"); @@ -94,27 +95,26 @@ abstractFileManager.prototype.extractUrlParts = function extractUrlParts(url, ba } if (urlParts[3]) { - directories = urlParts[3].replace(/\\/g, "/").split("/"); + rawDirectories = urlParts[3].replace(/\\/g, "/").split("/"); - // extract out . before .. so .. doesn't absorb a non-directory - for (i = 0; i < directories.length; i++) { - if (directories[i] === ".") { - directories.splice(i, 1); - i -= 1; - } - } + // collapse '..' and skip '.' + for (i = 0; i < rawDirectories.length; i++) { - for (i = 0; i < directories.length; i++) { - if (directories[i] === ".." && i > 0) { - directories.splice(i - 1, 2); - i -= 2; + if (rawDirectories[i] === "..") { + directories.pop(); + } + else if (rawDirectories[i] !== ".") { + directories.push(rawDirectories[i]); } + } } returner.hostPart = urlParts[1]; returner.directories = directories; + returner.rawPath = (urlParts[1] || "") + rawDirectories.join("/"); returner.path = (urlParts[1] || "") + directories.join("/"); + returner.filename = urlParts[4]; returner.fileUrl = returner.path + (urlParts[4] || ""); returner.url = returner.fileUrl + (urlParts[5] || ""); return returner; diff --git a/lib/less/environment/abstract-plugin-loader.js b/lib/less/environment/abstract-plugin-loader.js new file mode 100644 index 000000000..eba2413e0 --- /dev/null +++ b/lib/less/environment/abstract-plugin-loader.js @@ -0,0 +1,169 @@ +var functionRegistry = require("../functions/function-registry"), + LessError = require('../less-error'); + +var AbstractPluginLoader = function() { +}; + +function error(msg, type) { + throw new LessError( + { + type: type || 'Syntax', + message: msg + } + ); +} +AbstractPluginLoader.prototype.evalPlugin = function(contents, context, imports, pluginOptions, fileInfo) { + + var loader, + registry, + pluginObj, + localModule, + pluginManager, + filename; + + pluginManager = context.pluginManager; + + if (fileInfo) { + if (typeof fileInfo === "string") { + filename = fileInfo; + } + else { + filename = fileInfo.filename; + } + } + var shortname = (new this.less.FileManager()).extractUrlParts(filename).filename; + + if (filename) { + pluginObj = pluginManager.get(filename); + + if (pluginObj) { + this.trySetOptions(pluginObj, filename, shortname, pluginOptions); + try { + if (pluginObj.use) { + pluginObj.use.call(this.context, pluginObj); + } + } + catch (e) { + e.message = 'Error during @plugin call'; + return new this.less.LessError(e, imports, filename); + } + return pluginObj; + } + } + localModule = { + exports: {}, + pluginManager: pluginManager, + fileInfo: fileInfo + }; + registry = functionRegistry.create(); + + var registerPlugin = function(obj) { + pluginObj = obj; + }; + + try { + loader = new Function("module", "require", "registerPlugin", "functions", "tree", "less", "fileInfo", contents); + loader(localModule, this.require, registerPlugin, registry, this.less.tree, this.less, fileInfo); + } catch (e) { + return new this.less.LessError(e, imports, filename); + } + + if (!pluginObj) { + pluginObj = localModule.exports; + } + pluginObj = this.validatePlugin(pluginObj, filename, shortname); + + if (pluginObj) { + // Run on first load + pluginManager.addPlugin(pluginObj, fileInfo.filename, registry); + pluginObj.functions = registry.getLocalFunctions(); + pluginObj.imports = imports; + pluginObj.filename = filename; + + this.trySetOptions(pluginObj, filename, shortname, pluginOptions); + + // Run every @plugin call + try { + if (pluginObj.use) { + pluginObj.use.call(this.context, pluginObj); + } + } + catch (e) { + e.message = 'Error during @plugin call'; + return new this.less.LessError(e, imports, filename); + } + + } + else { + return new this.less.LessError({ message: "Not a valid plugin" }); + } + + return pluginObj; + +}; + +AbstractPluginLoader.prototype.trySetOptions = function(plugin, filename, name, options) { + if (options) { + if (!plugin.setOptions) { + error("Options have been provided but the plugin " + name + " does not support any options."); + return null; + } + try { + plugin.setOptions(options); + } + catch (e) { + error("Error setting options on plugin " + name + '\n' + e.message); + return null; + } + } +}; + +AbstractPluginLoader.prototype.validatePlugin = function(plugin, filename, name) { + if (plugin) { + // support plugins being a function + // so that the plugin can be more usable programmatically + if (typeof plugin === "function") { + plugin = new plugin(); + } + + if (plugin.minVersion) { + if (this.compareVersion(plugin.minVersion, this.less.version) < 0) { + error("Plugin " + name + " requires version " + this.versionToString(plugin.minVersion)); + return null; + } + } + return plugin; + } + return null; +}; + +AbstractPluginLoader.prototype.compareVersion = function(aVersion, bVersion) { + if (typeof aVersion === "string") { + aVersion = aVersion.match(/^(\d+)\.?(\d+)?\.?(\d+)?/); + aVersion.shift(); + } + for (var i = 0; i < aVersion.length; i++) { + if (aVersion[i] !== bVersion[i]) { + return parseInt(aVersion[i]) > parseInt(bVersion[i]) ? -1 : 1; + } + } + return 0; +}; +AbstractPluginLoader.prototype.versionToString = function(version) { + var versionString = ""; + for (var i = 0; i < version.length; i++) { + versionString += (versionString ? "." : "") + version[i]; + } + return versionString; +}; +AbstractPluginLoader.prototype.printUsage = function(plugins) { + for (var i = 0; i < plugins.length; i++) { + var plugin = plugins[i]; + if (plugin.printUsage) { + plugin.printUsage(); + } + } +}; + +module.exports = AbstractPluginLoader; + diff --git a/lib/less/functions/boolean.js b/lib/less/functions/boolean.js new file mode 100644 index 000000000..21254bc3d --- /dev/null +++ b/lib/less/functions/boolean.js @@ -0,0 +1,15 @@ + +var functionRegistry = require("./function-registry"), + Anonymous = require("../tree/anonymous"), + Keyword = require("../tree/keyword"); + +functionRegistry.addMultiple({ + boolean: function(condition) { + return condition ? Keyword.True : Keyword.False; + }, + + 'if': function(condition, trueValue, falseValue) { + return condition ? trueValue + : (falseValue || new Anonymous); + } +}); diff --git a/lib/less/functions/color.js b/lib/less/functions/color.js index a87250e02..864ee9374 100644 --- a/lib/less/functions/color.js +++ b/lib/less/functions/color.js @@ -278,7 +278,7 @@ colorFunctions = { if (typeof dark === 'undefined') { dark = colorFunctions.rgba(0, 0, 0, 1.0); } - //Figure out which is actually light and dark! + // Figure out which is actually light and dark: if (dark.luma() > light.luma()) { var t = light; light = dark; @@ -295,6 +295,44 @@ colorFunctions = { return dark; } }, + // Changes made in 2.7.0 - Reverted in 3.0.0 + // contrast: function (color, color1, color2, threshold) { + // // Return which of `color1` and `color2` has the greatest contrast with `color` + // // according to the standard WCAG contrast ratio calculation. + // // http://www.w3.org/TR/WCAG20/#contrast-ratiodef + // // The threshold param is no longer used, in line with SASS. + // // filter: contrast(3.2); + // // should be kept as is, so check for color + // if (!color.rgb) { + // return null; + // } + // if (typeof color1 === 'undefined') { + // color1 = colorFunctions.rgba(0, 0, 0, 1.0); + // } + // if (typeof color2 === 'undefined') { + // color2 = colorFunctions.rgba(255, 255, 255, 1.0); + // } + // var contrast1, contrast2; + // var luma = color.luma(); + // var luma1 = color1.luma(); + // var luma2 = color2.luma(); + // // Calculate contrast ratios for each color + // if (luma > luma1) { + // contrast1 = (luma + 0.05) / (luma1 + 0.05); + // } else { + // contrast1 = (luma1 + 0.05) / (luma + 0.05); + // } + // if (luma > luma2) { + // contrast2 = (luma + 0.05) / (luma2 + 0.05); + // } else { + // contrast2 = (luma2 + 0.05) / (luma + 0.05); + // } + // if (contrast1 > contrast2) { + // return color1; + // } else { + // return color2; + // } + // }, argb: function (color) { return new Anonymous(color.toARGB()); }, diff --git a/lib/less/functions/data-uri.js b/lib/less/functions/data-uri.js index 2bd373828..070db9a85 100644 --- a/lib/less/functions/data-uri.js +++ b/lib/less/functions/data-uri.js @@ -1,6 +1,7 @@ module.exports = function(environment) { var Quoted = require("../tree/quoted"), URL = require("../tree/url"), + utils = require('../utils'), functionRegistry = require("./function-registry"), fallback = function(functionThis, node) { return new URL(node, functionThis.index, functionThis.currentFileInfo).eval(functionThis.context); @@ -26,8 +27,10 @@ module.exports = function(environment) { fragment = filePath.slice(fragmentStart); filePath = filePath.slice(0, fragmentStart); } + var context = utils.clone(this.context); + context.rawBuffer = true; - var fileManager = environment.getFileManager(filePath, currentDirectory, this.context, environment, true); + var fileManager = environment.getFileManager(filePath, currentDirectory, context, environment, true); if (!fileManager) { return fallback(this, filePathNode); @@ -53,7 +56,7 @@ module.exports = function(environment) { useBase64 = /;base64$/.test(mimetype); } - var fileSync = fileManager.loadFileSync(filePath, currentDirectory, this.context, environment); + var fileSync = fileManager.loadFileSync(filePath, currentDirectory, context, environment); if (!fileSync.contents) { logger.warn("Skipped data-uri embedding of " + filePath + " because file not found"); return fallback(this, filePathNode || mimetypeNode); diff --git a/lib/less/functions/function-caller.js b/lib/less/functions/function-caller.js index d5358b3f5..ba8a9e987 100644 --- a/lib/less/functions/function-caller.js +++ b/lib/less/functions/function-caller.js @@ -11,8 +11,8 @@ var functionCaller = function(name, context, index, currentFileInfo) { functionCaller.prototype.isValid = function() { return Boolean(this.func); }; -functionCaller.prototype.call = function(args) { +functionCaller.prototype.call = function(args) { // This code is terrible and should be replaced as per this issue... // https://github.com/less/less.js/issues/2477 if (Array.isArray(args)) { diff --git a/lib/less/functions/function-registry.js b/lib/less/functions/function-registry.js index bc21bcc8e..d314355a4 100644 --- a/lib/less/functions/function-registry.js +++ b/lib/less/functions/function-registry.js @@ -7,7 +7,7 @@ function makeRegistry( base ) { name = name.toLowerCase(); if (this._data.hasOwnProperty(name)) { - //TODO warn + // TODO warn } this._data[name] = func; }, @@ -20,8 +20,14 @@ function makeRegistry( base ) { get: function(name) { return this._data[name] || ( base && base.get( name )); }, - inherit : function() { + getLocalFunctions: function() { + return this._data; + }, + inherit: function() { return makeRegistry( this ); + }, + create: function(base) { + return makeRegistry(base); } }; } diff --git a/lib/less/functions/index.js b/lib/less/functions/index.js index 90703c0ee..3b697d53b 100644 --- a/lib/less/functions/index.js +++ b/lib/less/functions/index.js @@ -4,7 +4,8 @@ module.exports = function(environment) { functionCaller: require("./function-caller") }; - //register functions + // register functions + require("./boolean"); require("./default"); require("./color"); require("./color-blending"); diff --git a/lib/less/functions/number.js b/lib/less/functions/number.js index 359d1725e..355f4314a 100644 --- a/lib/less/functions/number.js +++ b/lib/less/functions/number.js @@ -5,7 +5,7 @@ var Dimension = require("../tree/dimension"), var minMax = function (isMin, args) { args = Array.prototype.slice.call(args); - switch(args.length) { + switch (args.length) { case 0: throw { type: "Argument", message: "one or more arguments required" }; } var i, j, current, currentUnified, referenceUnified, unit, unitStatic, unitClone, @@ -27,7 +27,7 @@ var minMax = function (isMin, args) { j = values[""] !== undefined && unit !== "" && unit === unitStatic ? values[""] : values[unit]; if (j === undefined) { if (unitStatic !== undefined && unit !== unitStatic) { - throw{ type: "Argument", message: "incompatible types" }; + throw { type: "Argument", message: "incompatible types" }; } values[unit] = order.length; order.push(current); diff --git a/lib/less/functions/string.js b/lib/less/functions/string.js index 21150dc3f..5ae137596 100644 --- a/lib/less/functions/string.js +++ b/lib/less/functions/string.js @@ -19,12 +19,12 @@ functionRegistry.addMultiple({ result = result.replace(new RegExp(pattern.value, flags ? flags.value : ''), replacement); return new Quoted(string.quote || '', result, string.escaped); }, - '%': function (string /* arg, arg, ...*/) { + '%': function (string /* arg, arg, ... */) { var args = Array.prototype.slice.call(arguments, 1), result = string.value; for (var i = 0; i < args.length; i++) { - /*jshint loopfunc:true */ + /* jshint loopfunc:true */ result = result.replace(/%[sda]/i, function(token) { var value = ((args[i].type === "Quoted") && token.match(/s/i)) ? args[i].value : args[i].toCSS(); diff --git a/lib/less/functions/svg.js b/lib/less/functions/svg.js index ef5e84b96..e5f0e357a 100644 --- a/lib/less/functions/svg.js +++ b/lib/less/functions/svg.js @@ -15,12 +15,12 @@ module.exports = function(environment) { renderEnv = {compress: false}, returner, directionValue = direction.toCSS(renderEnv), - i, color, position, positionValue, alpha; + i, color, position, positionValue, alpha; function throwArgumentDescriptor() { throw { type: "Argument", - message: "svg-gradient expects direction, start_color [start_position], [color position,]...," + - " end_color [end_position] or direction, color list" }; + message: "svg-gradient expects direction, start_color [start_position], [color position,]...," + + " end_color [end_position] or direction, color list" }; } if (arguments.length == 2) { @@ -61,7 +61,7 @@ module.exports = function(environment) { '' + '<' + gradientType + 'Gradient id="gradient" gradientUnits="userSpaceOnUse" ' + gradientDirectionSvg + '>'; - for (i = 0; i < stops.length; i+= 1) { + for (i = 0; i < stops.length; i += 1) { if (stops[i] instanceof Expression) { color = stops[i].value[0]; position = stops[i].value[1]; diff --git a/lib/less/import-manager.js b/lib/less/import-manager.js index 79d2f3fec..2eb029013 100644 --- a/lib/less/import-manager.js +++ b/lib/less/import-manager.js @@ -1,6 +1,8 @@ var contexts = require("./contexts"), Parser = require('./parser/parser'), - FunctionImporter = require('./plugins/function-importer'); + LessError = require('./less-error'), + utils = require('./utils'), + PromiseConstructor = typeof Promise === 'undefined' ? require('promise') : Promise; module.exports = function(environment) { @@ -13,7 +15,8 @@ module.exports = function(environment) { // 'entryPath' - absolute path to the entry file // 'reference' - whether the file should not be output and only output parts that are referenced - var ImportManager = function(context, rootFileInfo) { + var ImportManager = function(less, context, rootFileInfo) { + this.less = less; this.rootFilename = rootFileInfo.filename; this.paths = context.paths || []; // Search paths, when importing this.contents = {}; // map - filename to contents of all the files @@ -25,16 +28,19 @@ module.exports = function(environment) { this.queue = []; // Files which haven't been imported yet this.files = {}; // Holds the imported parse trees. }; + /** * Add an import to be imported * @param path - the raw path - * @param tryAppendLessExtension - whether to try appending the less extension (if the path has no extension) + * @param tryAppendExtension - whether to try appending a file extension (.less or .js if the path has no extension) * @param currentFileInfo - the current file info (used for instance to work out relative paths) * @param importOptions - import options * @param callback - callback for when it is imported */ - ImportManager.prototype.push = function (path, tryAppendLessExtension, currentFileInfo, importOptions, callback) { - var importManager = this; + ImportManager.prototype.push = function (path, tryAppendExtension, currentFileInfo, importOptions, callback) { + var importManager = this, + pluginLoader = this.context.pluginManager.Loader; + this.queue.push(path); var fileParsedFunc = function (e, root, fullPath) { @@ -45,7 +51,9 @@ module.exports = function(environment) { callback(null, {rules:[]}, false, null); } else { - importManager.files[fullPath] = root; + if (!importManager.files[fullPath]) { + importManager.files[fullPath] = { root: root, options: importOptions }; + } if (e && !importManager.error) { importManager.error = e; } callback(e, root, importedEqualsRoot, fullPath); } @@ -65,12 +73,9 @@ module.exports = function(environment) { return; } - if (tryAppendLessExtension) { - path = fileManager.tryAppendExtension(path, importOptions.plugin ? ".js" : ".less"); - } - var loadFileCallback = function(loadedFile) { - var resolvedFilename = loadedFile.filename, + var plugin, + resolvedFilename = loadedFile.filename, contents = loadedFile.contents.replace(/^\uFEFF/, ''); // Pass on an updated rootpath if path of imported file is relative and file @@ -102,30 +107,56 @@ module.exports = function(environment) { newFileInfo.reference = true; } - if (importOptions.plugin) { - new FunctionImporter(newEnv, newFileInfo).eval(contents, function (e, root) { - fileParsedFunc(e, root, resolvedFilename); - }); + if (importOptions.isPlugin) { + plugin = pluginLoader.evalPlugin(contents, newEnv, importManager, importOptions.pluginArgs, newFileInfo); + if (plugin instanceof LessError) { + fileParsedFunc(plugin, null, resolvedFilename); + } + else { + fileParsedFunc(null, plugin, resolvedFilename); + } } else if (importOptions.inline) { fileParsedFunc(null, contents, resolvedFilename); } else { - new Parser(newEnv, importManager, newFileInfo).parse(contents, function (e, root) { - fileParsedFunc(e, root, resolvedFilename); - }); + + // import (multiple) parse trees apparently get altered and can't be cached. + // TODO: investigate why this is + if (importManager.files[resolvedFilename] + && !importManager.files[resolvedFilename].options.multiple + && !importOptions.multiple) { + + fileParsedFunc(null, importManager.files[resolvedFilename].root, resolvedFilename); + } + else { + new Parser(newEnv, importManager, newFileInfo).parse(contents, function (e, root) { + fileParsedFunc(e, root, resolvedFilename); + }); + } } }; + var promise, context = utils.clone(this.context); - var promise = fileManager.loadFile(path, currentFileInfo.currentDirectory, this.context, environment, - function(err, loadedFile) { - if (err) { - fileParsedFunc(err); - } else { - loadFileCallback(loadedFile); - } - }); + if (tryAppendExtension) { + context.ext = importOptions.isPlugin ? ".js" : ".less"; + } + + if (importOptions.isPlugin) { + promise = pluginLoader.loadPlugin(path, currentFileInfo.currentDirectory, context, environment, fileManager); + } + else { + promise = fileManager.loadFile(path, currentFileInfo.currentDirectory, context, environment, + function(err, loadedFile) { + if (err) { + fileParsedFunc(err); + } else { + loadFileCallback(loadedFile); + } + }); + } if (promise) { promise.then(loadFileCallback, fileParsedFunc); } + }; return ImportManager; }; diff --git a/lib/less/index.js b/lib/less/index.js index de3bb9431..bc3562ee5 100644 --- a/lib/less/index.js +++ b/lib/less/index.js @@ -1,12 +1,13 @@ module.exports = function(environment, fileManagers) { var SourceMapOutput, SourceMapBuilder, ParseTree, ImportManager, Environment; - var less = { - version: [2, 7, 3], + var initial = { + version: [3, 0, 0], data: require('./data'), tree: require('./tree'), Environment: (Environment = require("./environment/environment")), AbstractFileManager: require("./environment/abstract-file-manager"), + AbstractPluginLoader: require("./environment/abstract-plugin-loader"), environment: (environment = new Environment(environment, fileManagers)), visitors: require('./visitors'), Parser: require('./parser/parser'), @@ -25,5 +26,30 @@ module.exports = function(environment, fileManagers) { logger: require('./logger') }; - return less; + // Create a public API + + var ctor = function(t) { + return function() { + var obj = Object.create(t.prototype); + t.apply(obj, Array.prototype.slice.call(arguments, 0)); + return obj; + }; + }; + var t, api = Object.create(initial); + for (var n in initial.tree) { + /* eslint guard-for-in: 0 */ + t = initial.tree[n]; + if (typeof t === "function") { + api[n.toLowerCase()] = ctor(t); + } + else { + api[n] = Object.create(null); + for (var o in t) { + /* eslint guard-for-in: 0 */ + api[n][o.toLowerCase()] = ctor(t[o]); + } + } + } + + return api; }; diff --git a/lib/less/less-error.js b/lib/less/less-error.js index acaac22b1..67172a7af 100644 --- a/lib/less/less-error.js +++ b/lib/less/less-error.js @@ -1,11 +1,34 @@ -var utils = require("./utils"); - +var utils = require('./utils'); +/** + * This is a centralized class of any error that could be thrown internally (mostly by the parser). + * Besides standard .message it keeps some additional data like a path to the file where the error + * occurred along with line and column numbers. + * + * @class + * @extends Error + * @type {module.LessError} + * + * @prop {string} type + * @prop {string} filename + * @prop {number} index + * @prop {number} line + * @prop {number} column + * @prop {number} callLine + * @prop {number} callExtract + * @prop {string[]} extract + * + * @param {Object} e - An error object to wrap around or just a descriptive object + * @param {Object} importManager - An instance of ImportManager (see import-manager.js) + * @param {string} [currentFilename] + */ var LessError = module.exports = function LessError(e, importManager, currentFilename) { - Error.call(this); var filename = e.filename || currentFilename; + this.message = e.message; + this.stack = e.stack; + if (importManager && filename) { var input = importManager.contents[filename], loc = utils.getLocation(e.index, input), @@ -18,17 +41,32 @@ var LessError = module.exports = function LessError(e, importManager, currentFil this.filename = filename; this.index = e.index; this.line = typeof line === 'number' ? line + 1 : null; + this.column = col; + + if (!this.line && this.stack) { + var found = this.stack.match(/(|Function):(\d+):(\d+)/); + + if (found) { + if (found[2]) { + this.line = parseInt(found[2]) - 2; + } + if (found[3]) { + this.column = parseInt(found[3]); + } + } + } + this.callLine = callLine + 1; this.callExtract = lines[callLine]; - this.column = col; + this.extract = [ - lines[line - 1], - lines[line], - lines[line + 1] + lines[this.line - 2], + lines[this.line - 1], + lines[this.line] ]; + } - this.message = e.message; - this.stack = e.stack; + }; if (typeof Object.create === 'undefined') { @@ -40,3 +78,64 @@ if (typeof Object.create === 'undefined') { } LessError.prototype.constructor = LessError; + +/** + * An overridden version of the default Object.prototype.toString + * which uses additional information to create a helpful message. + * + * @param {Object} options + * @returns {string} + */ +LessError.prototype.toString = function(options) { + options = options || {}; + + var message = ''; + var extract = this.extract || []; + var error = []; + var stylize = function (str) { return str; }; + if (options.stylize) { + var type = typeof options.stylize; + if (type !== 'function') { + throw Error('options.stylize should be a function, got a ' + type + '!'); + } + stylize = options.stylize; + } + + if (this.line !== null) { + if (typeof extract[0] === 'string') { + error.push(stylize((this.line - 1) + ' ' + extract[0], 'grey')); + } + + if (typeof extract[1] === 'string') { + var errorTxt = this.line + ' '; + if (extract[1]) { + errorTxt += extract[1].slice(0, this.column) + + stylize(stylize(stylize(extract[1].substr(this.column, 1), 'bold') + + extract[1].slice(this.column + 1), 'red'), 'inverse'); + } + error.push(errorTxt); + } + + if (typeof extract[2] === 'string') { + error.push(stylize((this.line + 1) + ' ' + extract[2], 'grey')); + } + error = error.join('\n') + stylize('', 'reset') + '\n'; + } + + message += stylize(this.type + 'Error: ' + this.message, 'red'); + if (this.filename) { + message += stylize(' in ', 'red') + this.filename; + } + if (this.line) { + message += stylize(' on line ' + this.line + ', column ' + (this.column + 1) + ':', 'grey'); + } + + message += '\n' + error; + + if (this.callLine) { + message += stylize('from ', 'red') + (this.filename || '') + '/n'; + message += stylize(this.callLine, 'grey') + ' ' + this.callExtract + '/n'; + } + + return message; +}; diff --git a/lib/less/parse.js b/lib/less/parse.js index 6bc17f9ed..c2ff30d88 100644 --- a/lib/less/parse.js +++ b/lib/less/parse.js @@ -1,15 +1,19 @@ var PromiseConstructor, contexts = require("./contexts"), Parser = require('./parser/parser'), - PluginManager = require('./plugin-manager'); + PluginManager = require('./plugin-manager'), + LessError = require('./less-error'), + utils = require('./utils'); module.exports = function(environment, ParseTree, ImportManager) { var parse = function (input, options, callback) { - options = options || {}; if (typeof options === 'function') { callback = options; - options = {}; + options = utils.defaults(this.options, {}); + } + else { + options = utils.defaults(this.options, options || {}); } if (!callback) { @@ -29,9 +33,8 @@ module.exports = function(environment, ParseTree, ImportManager) { } else { var context, rootFileInfo, - pluginManager = new PluginManager(this); + pluginManager = new PluginManager(this, true); - pluginManager.addPlugins(options.plugins); options.pluginManager = pluginManager; context = new contexts.Parse(options); @@ -55,13 +58,33 @@ module.exports = function(environment, ParseTree, ImportManager) { } } - var imports = new ImportManager(context, rootFileInfo); + var imports = new ImportManager(this, context, rootFileInfo); + this.importManager = imports; + + // TODO: allow the plugins to be just a list of paths or names + // Do an async plugin queue like lessc + if (options.plugins) { + options.plugins.forEach(function(plugin) { + var evalResult, contents; + if (plugin.fileContent) { + contents = plugin.fileContent.replace(/^\uFEFF/, ''); + evalResult = pluginManager.Loader.evalPlugin(contents, context, imports, plugin.options, plugin.filename); + if (evalResult instanceof LessError) { + return callback(evalResult); + } + } + else { + pluginManager.addPlugin(plugin); + } + }); + } + new Parser(context, imports, rootFileInfo) .parse(input, function (e, root) { - if (e) { return callback(e); } - callback(null, root, imports, options); - }, options); + if (e) { return callback(e); } + callback(null, root, imports, options); + }, options); } }; return parse; diff --git a/lib/less/parser/parser-input.js b/lib/less/parser/parser-input.js index 4b27f325e..2394c9c3e 100644 --- a/lib/less/parser/parser-input.js +++ b/lib/less/parser/parser-input.js @@ -1,11 +1,11 @@ var chunker = require('./chunker'); module.exports = function() { - var input, // LeSS input string + var input, // Less input string j, // current chunk saveStack = [], // holds state for backtracking furthest, // furthest index the parser has gone to - furthestPossibleErrorMessage,// if this is furthest we got to, this is the probably cause + furthestPossibleErrorMessage, // if this is furthest we got to, this is the probably cause chunks, // chunkified input current, // current chunk currentPos, // index of current chunk, in `input` @@ -156,7 +156,7 @@ module.exports = function() { for (var i = 1; i + currentPosition < length; i++) { var nextChar = input.charAt(i + currentPosition); - switch(nextChar) { + switch (nextChar) { case "\\": i++; continue; @@ -209,7 +209,7 @@ module.exports = function() { parserInput.peekNotNumeric = function() { var c = input.charCodeAt(parserInput.i); - //Is the first char of the dimension 0-9, '.', '+' or '-' + // Is the first char of the dimension 0-9, '.', '+' or '-' return (c > CHARCODE_9 || c < CHARCODE_PLUS) || c === CHARCODE_FORWARD_SLASH || c === CHARCODE_COMMA; }; diff --git a/lib/less/parser/parser.js b/lib/less/parser/parser.js index 02618d36f..ef8357ce4 100644 --- a/lib/less/parser/parser.js +++ b/lib/less/parser/parser.js @@ -2,7 +2,8 @@ var LessError = require('../less-error'), tree = require("../tree"), visitors = require("../visitors"), getParserInput = require("./parser-input"), - utils = require("../utils"); + utils = require("../utils"), + functionRegistry = require('../functions/function-registry'); // // less.js - parser @@ -35,8 +36,8 @@ var LessError = require('../less-error'), // Token matching is done with the `$` function, which either takes // a terminal string or regexp, or a non-terminal function to call. // It also takes care of moving all the indices forwards. -//` // + var Parser = function Parser(context, imports, fileInfo) { var parsers, parserInput = getParserInput(); @@ -80,11 +81,61 @@ var Parser = function Parser(context, imports, fileInfo) { }; } + /** + * Used after initial parsing to create nodes on the fly + * + * @param {String} str - string to parse + * @param {Array} parseList - array of parsers to run input through e.g. ["value", "important"] + * @param {Number} currentIndex - start number to begin indexing + * @param {Object} fileInfo - fileInfo to attach to created nodes + */ + function parseNode(str, parseList, currentIndex, fileInfo, callback) { + var result, returnNodes = []; + var parser = parserInput; + + try { + parser.start(str, false, function fail(msg, index) { + callback({ + message: msg, + index: index + currentIndex + }); + }); + for (var x = 0, p, i; (p = parseList[x]); x++) { + i = parser.i; + result = parsers[p](); + if (result) { + result._index = i + currentIndex; + result._fileInfo = fileInfo; + returnNodes.push(result); + } + else { + returnNodes.push(null); + } + } + + var endInfo = parser.end(); + if (endInfo.isFinished) { + callback(null, returnNodes); + } + else { + callback(true, null); + } + } catch (e) { + throw new LessError({ + index: e.index + currentIndex, + message: e.message + }, imports, fileInfo.filename); + } + } + // // The Parser // return { - + parserInput: parserInput, + imports: imports, + fileInfo: fileInfo, + parseNode: parseNode, // // Parse an input string into an abstract syntax tree, // @param str A string containing 'less' markup @@ -130,9 +181,13 @@ var Parser = function Parser(context, imports, fileInfo) { }, imports); }); - root = new(tree.Ruleset)(null, this.parsers.primary()); + tree.Node.prototype.parse = this; + root = new tree.Ruleset(null, this.parsers.primary()); + tree.Node.prototype.rootNode = root; root.root = true; root.firstRoot = true; + root.functionRegistry = functionRegistry.inherit(); + } catch (e) { return callback(new LessError(e, imports, fileInfo.filename)); } @@ -197,7 +252,7 @@ var Parser = function Parser(context, imports, fileInfo) { // // The basic structure of the syntax tree generated is as follows: // - // Ruleset -> Rule -> Value -> Expression -> Entity + // Ruleset -> Declaration -> Value -> Expression -> Entity // // Here's some Less code: // @@ -211,9 +266,9 @@ var Parser = function Parser(context, imports, fileInfo) { // And here's what the parse tree might look like: // // Ruleset (Selector '.class', [ - // Rule ("color", Value ([Expression [Color #fff]])) - // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) - // Rule ("width", Value ([Expression [Operation " + " [Variable "@w"][Dimension 4px]]])) + // Declaration ("color", Value ([Expression [Color #fff]])) + // Declaration ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) + // Declaration ("width", Value ([Expression [Operation " + " [Variable "@w"][Dimension 4px]]])) // Ruleset (Selector [Element '>', '.child'], [...]) // ]) // @@ -230,7 +285,7 @@ var Parser = function Parser(context, imports, fileInfo) { // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, // as represented by this simplified grammar: // - // primary → (ruleset | rule)+ + // primary → (ruleset | declaration)+ // ruleset → selector+ block // block → '{' primary '}' // @@ -260,8 +315,8 @@ var Parser = function Parser(context, imports, fileInfo) { continue; } - node = mixin.definition() || this.rule() || this.ruleset() || - mixin.call() || this.rulesetCall() || this.entities.call() || this.directive(); + node = mixin.definition() || this.declaration() || this.ruleset() || + mixin.call() || this.variableCall() || this.entities.call() || this.atrule(); if (node) { root.push(node); } else { @@ -319,7 +374,7 @@ var Parser = function Parser(context, imports, fileInfo) { // black border-collapse // keyword: function () { - var k = parserInput.$char("%") || parserInput.$re(/^[_A-Za-z-][_A-Za-z0-9-]*/); + var k = parserInput.$char("%") || parserInput.$re(/^\[?[_A-Za-z-][_A-Za-z0-9-]*\]?/); if (k) { return tree.Color.fromKeyword(k) || new(tree.Keyword)(k); } @@ -330,13 +385,10 @@ var Parser = function Parser(context, imports, fileInfo) { // // rgb(255, 0, 255) // - // We also try to catch IE's `alpha()`, but let the `alpha` parser - // deal with the details. - // // The arguments are parsed with the `entities.arguments` parser. // call: function () { - var name, nameLC, args, alpha, index = parserInput.i; + var name, args, func, index = parserInput.i; // http://jsperf.com/case-insensitive-regex-vs-strtolower-then-regex/18 if (parserInput.peek(/^url\(/i)) { @@ -346,70 +398,98 @@ var Parser = function Parser(context, imports, fileInfo) { parserInput.save(); name = parserInput.$re(/^([\w-]+|%|progid:[\w\.]+)\(/); - if (!name) { parserInput.forget(); return; } + if (!name) { + parserInput.forget(); + return; + } name = name[1]; - nameLC = name.toLowerCase(); - - if (nameLC === 'alpha') { - alpha = parsers.alpha(); - if (alpha) { + func = this.customFuncCall(name); + if (func) { + args = func.parse(); + if (args && func.stop) { parserInput.forget(); - return alpha; + return args; } } - args = this.arguments(); + args = this.arguments(args); - if (! parserInput.$char(')')) { + if (!parserInput.$char(')')) { parserInput.restore("Could not parse call arguments or missing ')'"); return; } parserInput.forget(); + return new(tree.Call)(name, args, index, fileInfo); }, - arguments: function () { - var argsSemiColon = [], argsComma = [], - expressions = [], - isSemiColonSeparated, value, arg; - - parserInput.save(); + + // + // Parsing rules for functions with non-standard args, e.g.: + // + // boolean(not(2 > 1)) + // + // This is a quick prototype, to be modified/improved when + // more custom-parsed funcs come (e.g. `selector(...)`) + // - while (true) { + customFuncCall: function (name) { + /* Ideally the table is to be moved out of here for faster perf., + but it's quite tricky since it relies on all these `parsers` + and `expect` available only here */ + return { + alpha: f(parsers.ieAlpha, true), + boolean: f(condition), + 'if': f(condition) + }[name.toLowerCase()]; + + function f(parse, stop) { + return { + parse: parse, // parsing function + stop: stop // when true - stop after parse() and return its result, + // otherwise continue for plain args + }; + } + + function condition() { + return [expect(parsers.condition, 'expected condition')]; + } + }, - arg = parsers.detachedRuleset() || this.assignment() || parsers.expression(); + arguments: function (prevArgs) { + var argsComma = prevArgs || [], + argsSemiColon = [], + isSemiColonSeparated, value; - if (!arg) { - break; - } + parserInput.save(); - value = arg; + while (true) { + if (prevArgs) { + prevArgs = false; + } else { + value = parsers.detachedRuleset() || this.assignment() || parsers.expression(); + if (!value) { + break; + } - if (arg.value && arg.value.length == 1) { - value = arg.value[0]; - } + if (value.value && value.value.length == 1) { + value = value.value[0]; + } - if (value) { - expressions.push(value); + argsComma.push(value); } - argsComma.push(value); - if (parserInput.$char(',')) { continue; } if (parserInput.$char(';') || isSemiColonSeparated) { - isSemiColonSeparated = true; - - if (expressions.length > 1) { - value = new(tree.Value)(expressions); - } + value = (argsComma.length < 1) ? argsComma[0] + : new tree.Value(argsComma); argsSemiColon.push(value); - - expressions = []; + argsComma = []; } } @@ -467,15 +547,17 @@ var Parser = function Parser(context, imports, fileInfo) { return; } - value = this.quoted() || this.variable() || + value = this.quoted() || this.variable() || this.property() || parserInput.$re(/^(?:(?:\\[\(\)'"])|[^\(\)'"])+/) || ""; parserInput.autoCommentAbsorb = true; expectChar(')'); - return new(tree.URL)((value.value != null || value instanceof tree.Variable) ? - value : new(tree.Anonymous)(value), index, fileInfo); + return new(tree.URL)((value.value != null || + value instanceof tree.Variable || + value instanceof tree.Property) ? + value : new(tree.Anonymous)(value, index), index, fileInfo); }, // @@ -502,7 +584,27 @@ var Parser = function Parser(context, imports, fileInfo) { return new(tree.Variable)("@" + curly[1], index, fileInfo); } }, + // + // A Property accessor, such as `$color`, in + // + // background-color: $color + // + property: function () { + var name, index = parserInput.i; + + if (parserInput.currentChar() === '$' && (name = parserInput.$re(/^\$[\w-]+/))) { + return new(tree.Property)(name, index, fileInfo); + } + }, + // A property entity useing the protective {} e.g. ${prop} + propertyCurly: function () { + var curly, index = parserInput.i; + + if (parserInput.currentChar() === '$' && (curly = parserInput.$re(/^\$\{([\w-]+)\}/))) { + return new(tree.Property)("$" + curly[1], index, fileInfo); + } + }, // // A Hexadecimal color // @@ -612,15 +714,17 @@ var Parser = function Parser(context, imports, fileInfo) { }, // - // The variable part of a variable definition. Used in the `rule` parser + // Call a variable value // - // @fink(); + // @fink() // - rulesetCall: function () { + variableCall: function () { var name; - if (parserInput.currentChar() === '@' && (name = parserInput.$re(/^(@[\w-]+)\(\s*\)\s*;/))) { - return new tree.RulesetCall(name[1]); + if (parserInput.currentChar() === '@' + && (name = parserInput.$re(/^(@[\w-]+)\(\s*\)/)) + && parsers.end()) { + return new tree.VariableCall(name[1]); } }, @@ -637,7 +741,7 @@ var Parser = function Parser(context, imports, fileInfo) { do { option = null; elements = null; - while (! (option = parserInput.$re(/^(all)(?=\s*(\)|,))/))) { + while (!(option = parserInput.$re(/^(all)(?=\s*(\)|,))/))) { e = this.element(); if (!e) { break; @@ -756,7 +860,7 @@ var Parser = function Parser(context, imports, fileInfo) { .push({ variadic: true }); break; } - arg = entities.variable() || entities.literal() || entities.keyword(); + arg = entities.variable() || entities.property() || entities.literal() || entities.keyword(); } if (!arg) { @@ -779,7 +883,7 @@ var Parser = function Parser(context, imports, fileInfo) { val = arg; } - if (val && val instanceof tree.Variable) { + if (val && (val instanceof tree.Variable || val instanceof tree.Property)) { if (parserInput.$char(':')) { if (expressions.length > 0) { if (isSemiColonSeparated) { @@ -925,11 +1029,11 @@ var Parser = function Parser(context, imports, fileInfo) { var entities = this.entities; return this.comment() || entities.literal() || entities.variable() || entities.url() || - entities.call() || entities.keyword() || entities.javascript(); + entities.property() || entities.call() || entities.keyword() || entities.javascript(); }, // - // A Rule terminator. Note that we use `peek()` to check for '}', + // A Declaration terminator. Note that we use `peek()` to check for '}', // because the `block` rule will be expecting it, but we still need to make sure // it's there, if ';' was omitted. // @@ -942,17 +1046,18 @@ var Parser = function Parser(context, imports, fileInfo) { // // alpha(opacity=88) // - alpha: function () { + ieAlpha: function () { var value; // http://jsperf.com/case-insensitive-regex-vs-strtolower-then-regex/18 - if (! parserInput.$re(/^opacity=/i)) { return; } + if (!parserInput.$re(/^opacity=/i)) { return; } value = parserInput.$re(/^\d+/); if (!value) { - value = expect(this.entities.variable, "Could not parse alpha"); + value = expect(parsers.entities.variable, "Could not parse alpha"); + value = '@{' + value.name.slice(1) + '}'; } expectChar(')'); - return new(tree.Alpha)(value); + return new tree.Quoted('', 'alpha(opacity=' + value + ')'); }, // @@ -978,10 +1083,10 @@ var Parser = function Parser(context, imports, fileInfo) { parserInput.$re(/^\([^&()@]+\)/) || parserInput.$re(/^[\.#:](?=@)/) || this.entities.variableCurly(); - if (! e) { + if (!e) { parserInput.save(); if (parserInput.$char('(')) { - if ((v = this.selector()) && parserInput.$char(')')) { + if ((v = this.selector(false)) && parserInput.$char(')')) { e = new(tree.Paren)(v); parserInput.forget(); } else { @@ -1032,14 +1137,8 @@ var Parser = function Parser(context, imports, fileInfo) { } }, // - // A CSS selector (see selector below) - // with less extensions e.g. the ability to extend and guard - // - lessSelector: function () { - return this.selector(true); - }, - // // A CSS Selector + // with less extensions e.g. the ability to extend and guard // // .class > div + h1 // li a:hover @@ -1048,7 +1147,7 @@ var Parser = function Parser(context, imports, fileInfo) { // selector: function (isLess) { var index = parserInput.i, elements, extendList, c, e, allExtends, when, condition; - + isLess = isLess !== false; while ((isLess && (extendList = this.extend())) || (isLess && (when = parserInput.$str("when"))) || (e = this.element())) { if (when) { condition = expect(this.conditions, 'expected condition'); @@ -1079,7 +1178,7 @@ var Parser = function Parser(context, imports, fileInfo) { if (allExtends) { error("Extend must be used to extend a selector, it cannot be used on its own"); } }, attribute: function () { - if (! parserInput.$char('[')) { return; } + if (!parserInput.$char('[')) { return; } var entities = this.entities, key, val, op; @@ -1138,7 +1237,7 @@ var Parser = function Parser(context, imports, fileInfo) { } while (true) { - s = this.lessSelector(); + s = this.selector(); if (!s) { break; } @@ -1151,7 +1250,7 @@ var Parser = function Parser(context, imports, fileInfo) { if (s.condition && selectors.length > 1) { error("Guards are only currently allowed on a single selector."); } - if (! parserInput.$char(',')) { break; } + if (!parserInput.$char(',')) { break; } if (s.condition) { error("Guards are only currently allowed on a single selector."); } @@ -1169,7 +1268,7 @@ var Parser = function Parser(context, imports, fileInfo) { parserInput.restore(); } }, - rule: function (tryAnonymous) { + declaration: function () { var name, value, startOfRule = parserInput.i, c = parserInput.currentChar(), important, merge, isVariable; if (c === '.' || c === '#' || c === '&' || c === ':') { return; } @@ -1191,22 +1290,16 @@ var Parser = function Parser(context, imports, fileInfo) { // where each item is a tree.Keyword or tree.Variable merge = !isVariable && name.length > 1 && name.pop().value; - // prefer to try to parse first if its a variable or we are compressing - // but always fallback on the other one - var tryValueFirst = !tryAnonymous && (context.compress || isVariable); - - if (tryValueFirst) { - value = this.value(); + // Try to store values as anonymous + // If we need the value later we'll re-parse it in ruleset.parseValue + value = this.anonymousValue(); + if (value) { + parserInput.forget(); + // anonymous values absorb the end ';' which is required for them to work + return new (tree.Declaration)(name, value, false, merge, startOfRule, fileInfo); } + if (!value) { - value = this.anonymousValue(); - if (value) { - parserInput.forget(); - // anonymous values absorb the end ';' which is required for them to work - return new (tree.Rule)(name, value, false, merge, startOfRule, fileInfo); - } - } - if (!tryValueFirst && !value) { value = this.value(); } @@ -1215,26 +1308,25 @@ var Parser = function Parser(context, imports, fileInfo) { if (value && this.end()) { parserInput.forget(); - return new (tree.Rule)(name, value, important, merge, startOfRule, fileInfo); - } else { + return new (tree.Declaration)(name, value, important, merge, startOfRule, fileInfo); + } + else { parserInput.restore(); - if (value && !tryAnonymous) { - return this.rule(true); - } } } else { - parserInput.forget(); + parserInput.restore(); } }, anonymousValue: function () { - var match = parserInput.$re(/^([^@+\/'"*`(;{}-]*);/); + var index = parserInput.i; + var match = parserInput.$re(/^([^@\$+\/'"*`(;{}-]*);/); if (match) { - return new(tree.Anonymous)(match[1]); + return new(tree.Anonymous)(match[1], index); } }, // - // An @import directive + // An @import atrule // // @import "lib"; // @@ -1272,13 +1364,13 @@ var Parser = function Parser(context, imports, fileInfo) { var o, options = {}, optionName, value; // list of options, surrounded by parens - if (! parserInput.$char('(')) { return null; } + if (!parserInput.$char('(')) { return null; } do { o = this.importOption(); if (o) { optionName = o; value = true; - switch(optionName) { + switch (optionName) { case "css": optionName = "less"; value = false; @@ -1289,7 +1381,7 @@ var Parser = function Parser(context, imports, fileInfo) { break; } options[optionName] = value; - if (! parserInput.$char(',')) { break; } + if (!parserInput.$char(',')) { break; } } } while (o); expectChar(')'); @@ -1315,7 +1407,7 @@ var Parser = function Parser(context, imports, fileInfo) { e = this.value(); if (parserInput.$char(')')) { if (p && e) { - nodes.push(new(tree.Paren)(new(tree.Rule)(p, e, null, null, parserInput.i, fileInfo, true))); + nodes.push(new(tree.Paren)(new(tree.Declaration)(p, e, null, null, parserInput.i, fileInfo, true))); } else if (e) { nodes.push(new(tree.Paren)(e)); } else { @@ -1339,12 +1431,12 @@ var Parser = function Parser(context, imports, fileInfo) { e = this.mediaFeature(); if (e) { features.push(e); - if (! parserInput.$char(',')) { break; } + if (!parserInput.$char(',')) { break; } } else { e = entities.variable(); if (e) { features.push(e); - if (! parserInput.$char(',')) { break; } + if (!parserInput.$char(',')) { break; } } } } while (e); @@ -1384,45 +1476,68 @@ var Parser = function Parser(context, imports, fileInfo) { }, // - // A @plugin directive, used to import compiler extensions dynamically. - // - // @plugin "lib"; + + // A @plugin directive, used to import plugins dynamically. // - // Depending on our environment, importing is done differently: - // In the browser, it's an XHR request, in Node, it would be a - // file-system operation. The function used for importing is - // stored in `import`, which we pass to the Import constructor. + // @plugin (args) "lib"; // plugin: function () { - var path, + var path, args, options, index = parserInput.i, dir = parserInput.$re(/^@plugin?\s+/); if (dir) { - var options = { plugin : true }; + args = this.pluginArgs(); + + if (args) { + options = { + pluginArgs: args, + isPlugin: true + }; + } + else { + options = { isPlugin: true }; + } if ((path = this.entities.quoted() || this.entities.url())) { if (!parserInput.$char(';')) { parserInput.i = index; - error("missing semi-colon on plugin"); + error("missing semi-colon on @plugin"); } - return new(tree.Import)(path, null, options, index, fileInfo); } else { parserInput.i = index; - error("malformed plugin statement"); + error("malformed @plugin statement"); } } }, + pluginArgs: function() { + // list of options, surrounded by parens + parserInput.save(); + if (!parserInput.$char('(')) { + parserInput.restore(); + return null; + } + var args = parserInput.$re(/^\s*([^\);]+)\)\s*/); + if (args[1]) { + parserInput.forget(); + return args[1].trim(); + } + else { + parserInput.restore(); + return null; + } + }, + // - // A CSS Directive + // A CSS AtRule // // @charset "utf-8"; // - directive: function () { + atrule: function () { var index = parserInput.i, name, value, rules, nonVendorSpecificName, hasIdentifier, hasExpression, hasUnknown, hasBlock = true, isRooted = true; @@ -1444,7 +1559,7 @@ var Parser = function Parser(context, imports, fileInfo) { nonVendorSpecificName = "@" + name.slice(name.indexOf('-', 2) + 1); } - switch(nonVendorSpecificName) { + switch (nonVendorSpecificName) { case "@charset": hasIdentifier = true; hasBlock = false; @@ -1493,13 +1608,13 @@ var Parser = function Parser(context, imports, fileInfo) { if (rules || (!hasBlock && value && parserInput.$char(';'))) { parserInput.forget(); - return new (tree.Directive)(name, value, rules, index, fileInfo, + return new (tree.AtRule)(name, value, rules, index, fileInfo, context.dumpLineNumbers ? getDebugInfo(index) : null, isRooted ); } - parserInput.restore("directive options not recognised"); + parserInput.restore("at-rule options not recognised"); }, // @@ -1511,18 +1626,18 @@ var Parser = function Parser(context, imports, fileInfo) { // and before the `;`. // value: function () { - var e, expressions = []; + var e, expressions = [], index = parserInput.i; do { e = this.expression(); if (e) { expressions.push(e); - if (! parserInput.$char(',')) { break; } + if (!parserInput.$char(',')) { break; } } } while (e); if (expressions.length > 0) { - return new(tree.Value)(expressions); + return new(tree.Value)(expressions, index); } }, important: function () { @@ -1761,13 +1876,14 @@ var Parser = function Parser(context, imports, fileInfo) { operand: function () { var entities = this.entities, negate; - if (parserInput.peek(/^-[@\(]/)) { + if (parserInput.peek(/^-[@\$\(]/)) { negate = parserInput.$char('-'); } var o = this.sub() || entities.dimension() || entities.color() || entities.variable() || - entities.call() || entities.colorKeyword(); + entities.property() || entities.call() || + entities.colorKeyword(); if (negate) { o.parensInOp = true; @@ -1785,7 +1901,7 @@ var Parser = function Parser(context, imports, fileInfo) { // @var * 2 // expression: function () { - var entities = [], e, delim; + var entities = [], e, delim, index = parserInput.i; do { e = this.comment(); @@ -1800,7 +1916,7 @@ var Parser = function Parser(context, imports, fileInfo) { if (!parserInput.peek(/^\/[\/*]/)) { delim = parserInput.$char('/'); if (delim) { - entities.push(new(tree.Anonymous)(delim)); + entities.push(new(tree.Anonymous)(delim, index)); } } } @@ -1838,7 +1954,7 @@ var Parser = function Parser(context, imports, fileInfo) { match(/^(\*?)/); while (true) { - if (!match(/^((?:[\w-]+)|(?:@\{[\w-]+\}))/)) { + if (!match(/^((?:[\w-]+)|(?:[@\$]\{[\w-]+\}))/)) { break; } } @@ -1854,10 +1970,11 @@ var Parser = function Parser(context, imports, fileInfo) { } for (k = 0; k < name.length; k++) { s = name[k]; - name[k] = (s.charAt(0) !== '@') ? + name[k] = (s.charAt(0) !== '@' && s.charAt(0) !== '$') ? new(tree.Keyword)(s) : - new(tree.Variable)('@' + s.slice(2, -1), - index[k], fileInfo); + (s.charAt(0) === '@' ? + new(tree.Variable)('@' + s.slice(2, -1), index[k], fileInfo) : + new(tree.Property)('$' + s.slice(2, -1), index[k], fileInfo)); } return name; } diff --git a/lib/less/plugin-manager.js b/lib/less/plugin-manager.js index 8f6df7c79..3a9f75bb5 100644 --- a/lib/less/plugin-manager.js +++ b/lib/less/plugin-manager.js @@ -8,7 +8,18 @@ var PluginManager = function(less) { this.postProcessors = []; this.installedPlugins = []; this.fileManagers = []; + this.iterator = -1; + this.pluginCache = {}; + this.Loader = new less.PluginLoader(less); }; + +var pm, PluginManagerFactory = function(less, newFactory) { + if (newFactory || !pm) { + pm = new PluginManager(less); + } + return pm; + }; + /** * Adds all the plugins in the array * @param {Array} plugins @@ -23,11 +34,25 @@ PluginManager.prototype.addPlugins = function(plugins) { /** * * @param plugin + * @param {String} filename */ -PluginManager.prototype.addPlugin = function(plugin) { +PluginManager.prototype.addPlugin = function(plugin, filename, functionRegistry) { this.installedPlugins.push(plugin); - plugin.install(this.less, this); + if (filename) { + this.pluginCache[filename] = plugin; + } + if (plugin.install) { + plugin.install(this.less, this, functionRegistry || this.less.functions.functionRegistry); + } }; +/** + * + * @param filename + */ +PluginManager.prototype.get = function(filename) { + return this.pluginCache[filename]; +}; + /** * Adds a visitor. The visitor object has options on itself to determine * when it should run. @@ -103,6 +128,20 @@ PluginManager.prototype.getPostProcessors = function() { PluginManager.prototype.getVisitors = function() { return this.visitors; }; + +PluginManager.prototype.visitor = function() { + var self = this; + return { + first: function() { + self.iterator = -1; + return self.visitors[self.iterator]; + }, + get: function() { + self.iterator += 1; + return self.visitors[self.iterator]; + } + }; +}; /** * * @returns {Array} @@ -111,4 +150,6 @@ PluginManager.prototype.getVisitors = function() { PluginManager.prototype.getFileManagers = function() { return this.fileManagers; }; -module.exports = PluginManager; + +// +module.exports = PluginManagerFactory; diff --git a/lib/less/plugins/function-importer.js b/lib/less/plugins/function-importer.js deleted file mode 100644 index b863998b2..000000000 --- a/lib/less/plugins/function-importer.js +++ /dev/null @@ -1,35 +0,0 @@ -var LessError = require('../less-error'), - tree = require("../tree"); - -var FunctionImporter = module.exports = function FunctionImporter(context, fileInfo) { - this.fileInfo = fileInfo; -}; - -FunctionImporter.prototype.eval = function(contents, callback) { - var loaded = {}, - loader, - registry; - - registry = { - add: function(name, func) { - loaded[name] = func; - }, - addMultiple: function(functions) { - Object.keys(functions).forEach(function(name) { - loaded[name] = functions[name]; - }); - } - }; - - try { - loader = new Function("functions", "tree", "fileInfo", contents); - loader(registry, tree, this.fileInfo); - } catch(e) { - callback(new LessError({ - message: "Plugin evaluation error: '" + e.name + ': ' + e.message.replace(/["]/g, "'") + "'" , - filename: this.fileInfo.filename - }), null ); - } - - callback(null, { functions: loaded }); -}; diff --git a/lib/less/render.js b/lib/less/render.js index 95a191dd4..1743f352e 100644 --- a/lib/less/render.js +++ b/lib/less/render.js @@ -1,10 +1,14 @@ -var PromiseConstructor; +var PromiseConstructor, + utils = require('./utils'); module.exports = function(environment, ParseTree, ImportManager) { var render = function (input, options, callback) { if (typeof options === 'function') { callback = options; - options = {}; + options = utils.defaults(this.options, {}); + } + else { + options = utils.defaults(this.options, options || {}); } if (!callback) { diff --git a/lib/less/source-map-builder.js b/lib/less/source-map-builder.js index ee28041e8..62f7cf230 100644 --- a/lib/less/source-map-builder.js +++ b/lib/less/source-map-builder.js @@ -26,6 +26,9 @@ module.exports = function (SourceMapOutput, environment) { if (this.options.sourceMapInputFilename) { this.sourceMapInputFilename = sourceMapOutput.normalizeFilename(this.options.sourceMapInputFilename); } + if (this.options.sourceMapBasepath !== undefined && this.sourceMapURL !== undefined) { + this.sourceMapURL = sourceMapOutput.removeBasepath(this.sourceMapURL); + } return css + this.getCSSAppendage(); }; diff --git a/lib/less/source-map-output.js b/lib/less/source-map-output.js index 4e21e24cc..cf0b862ca 100644 --- a/lib/less/source-map-output.js +++ b/lib/less/source-map-output.js @@ -28,21 +28,26 @@ module.exports = function (environment) { this._column = 0; }; - SourceMapOutput.prototype.normalizeFilename = function(filename) { - filename = filename.replace(/\\/g, '/'); - - if (this._sourceMapBasepath && filename.indexOf(this._sourceMapBasepath) === 0) { - filename = filename.substring(this._sourceMapBasepath.length); - if (filename.charAt(0) === '\\' || filename.charAt(0) === '/') { - filename = filename.substring(1); + SourceMapOutput.prototype.removeBasepath = function(path) { + if (this._sourceMapBasepath && path.indexOf(this._sourceMapBasepath) === 0) { + path = path.substring(this._sourceMapBasepath.length); + if (path.charAt(0) === '\\' || path.charAt(0) === '/') { + path = path.substring(1); } } + + return path; + }; + + SourceMapOutput.prototype.normalizeFilename = function(filename) { + filename = filename.replace(/\\/g, '/'); + filename = this.removeBasepath(filename); return (this._sourceMapRootpath || "") + filename; }; SourceMapOutput.prototype.add = function(chunk, fileInfo, index, mapLines) { - //ignore adding empty strings + // ignore adding empty strings if (!chunk) { return; } diff --git a/lib/less/transform-tree.js b/lib/less/transform-tree.js index cac97dc62..d690d6930 100644 --- a/lib/less/transform-tree.js +++ b/lib/less/transform-tree.js @@ -13,7 +13,7 @@ module.exports = function(root, options) { // // `{ color: new tree.Color('#f01') }` will become: // - // new tree.Rule('@color', + // new tree.Declaration('@color', // new tree.Value([ // new tree.Expression([ // new tree.Color('#f01') @@ -25,50 +25,49 @@ module.exports = function(root, options) { variables = Object.keys(variables).map(function (k) { var value = variables[k]; - if (! (value instanceof tree.Value)) { - if (! (value instanceof tree.Expression)) { + if (!(value instanceof tree.Value)) { + if (!(value instanceof tree.Expression)) { value = new tree.Expression([value]); } value = new tree.Value([value]); } - return new tree.Rule('@' + k, value, false, null, 0); + return new tree.Declaration('@' + k, value, false, null, 0); }); evalEnv.frames = [new tree.Ruleset(null, variables)]; } - var preEvalVisitors = [], - visitors = [ + var visitors = [ new visitor.JoinSelectorVisitor(), new visitor.MarkVisibleSelectorsVisitor(true), new visitor.ExtendVisitor(), new visitor.ToCSSVisitor({compress: Boolean(options.compress)}) - ], i; + ], v, visitorIterator; + // first() / get() allows visitors to be added while visiting if (options.pluginManager) { - var pluginVisitors = options.pluginManager.getVisitors(); - for (i = 0; i < pluginVisitors.length; i++) { - var pluginVisitor = pluginVisitors[i]; - if (pluginVisitor.isPreEvalVisitor) { - preEvalVisitors.push(pluginVisitor); - } else { - if (pluginVisitor.isPreVisitor) { - visitors.splice(0, 0, pluginVisitor); - } else { - visitors.push(pluginVisitor); - } + visitorIterator = options.pluginManager.visitor(); + visitorIterator.first(); + while ((v = visitorIterator.get())) { + if (v.isPreEvalVisitor) { + v.run(root); } } } - for (i = 0; i < preEvalVisitors.length; i++) { - preEvalVisitors[i].run(root); - } - evaldRoot = root.eval(evalEnv); - for (i = 0; i < visitors.length; i++) { + for (var i = 0; i < visitors.length; i++) { visitors[i].run(evaldRoot); } + if (options.pluginManager) { + visitorIterator.first(); + while ((v = visitorIterator.get())) { + if (!v.isPreEvalVisitor) { + v.run(evaldRoot); + } + } + } + return evaldRoot; }; diff --git a/lib/less/tree/alpha.js b/lib/less/tree/alpha.js deleted file mode 100644 index 82a4ce5e8..000000000 --- a/lib/less/tree/alpha.js +++ /dev/null @@ -1,28 +0,0 @@ -var Node = require("./node"); - -var Alpha = function (val) { - this.value = val; -}; -Alpha.prototype = new Node(); -Alpha.prototype.type = "Alpha"; - -Alpha.prototype.accept = function (visitor) { - this.value = visitor.visit(this.value); -}; -Alpha.prototype.eval = function (context) { - if (this.value.eval) { return new Alpha(this.value.eval(context)); } - return this; -}; -Alpha.prototype.genCSS = function (context, output) { - output.add("alpha(opacity="); - - if (this.value.genCSS) { - this.value.genCSS(context, output); - } else { - output.add(this.value); - } - - output.add(")"); -}; - -module.exports = Alpha; diff --git a/lib/less/tree/anonymous.js b/lib/less/tree/anonymous.js index ec4f31304..5775b2eae 100644 --- a/lib/less/tree/anonymous.js +++ b/lib/less/tree/anonymous.js @@ -2,9 +2,9 @@ var Node = require("./node"); var Anonymous = function (value, index, currentFileInfo, mapLines, rulesetLike, visibilityInfo) { this.value = value; - this.index = index; + this._index = index; + this._fileInfo = currentFileInfo; this.mapLines = mapLines; - this.currentFileInfo = currentFileInfo; this.rulesetLike = (typeof rulesetLike === 'undefined') ? false : rulesetLike; this.allowRoot = true; this.copyVisibilityInfo(visibilityInfo); @@ -12,7 +12,7 @@ var Anonymous = function (value, index, currentFileInfo, mapLines, rulesetLike, Anonymous.prototype = new Node(); Anonymous.prototype.type = "Anonymous"; Anonymous.prototype.eval = function () { - return new Anonymous(this.value, this.index, this.currentFileInfo, this.mapLines, this.rulesetLike, this.visibilityInfo()); + return new Anonymous(this.value, this._index, this._fileInfo, this.mapLines, this.rulesetLike, this.visibilityInfo()); }; Anonymous.prototype.compare = function (other) { return other.toCSS && this.toCSS() === other.toCSS() ? 0 : undefined; @@ -21,6 +21,9 @@ Anonymous.prototype.isRulesetLike = function() { return this.rulesetLike; }; Anonymous.prototype.genCSS = function (context, output) { - output.add(this.value, this.currentFileInfo, this.index, this.mapLines); + this.nodeVisible = Boolean(this.value); + if (this.nodeVisible) { + output.add(this.value, this._fileInfo, this._index, this.mapLines); + } }; module.exports = Anonymous; diff --git a/lib/less/tree/directive.js b/lib/less/tree/atrule.js similarity index 70% rename from lib/less/tree/directive.js rename to lib/less/tree/atrule.js index 70be82c73..62386b818 100644 --- a/lib/less/tree/directive.js +++ b/lib/less/tree/atrule.js @@ -1,34 +1,36 @@ var Node = require("./node"), Selector = require("./selector"), - Ruleset = require("./ruleset"); + Ruleset = require("./ruleset"), + Anonymous = require('./anonymous'); -var Directive = function (name, value, rules, index, currentFileInfo, debugInfo, isRooted, visibilityInfo) { +var AtRule = function (name, value, rules, index, currentFileInfo, debugInfo, isRooted, visibilityInfo) { var i; this.name = name; - this.value = value; + this.value = (value instanceof Node) ? value : (value ? new Anonymous(value) : value); if (rules) { if (Array.isArray(rules)) { this.rules = rules; } else { this.rules = [rules]; - this.rules[0].selectors = (new Selector([], null, null, this.index, currentFileInfo)).createEmptySelectors(); + this.rules[0].selectors = (new Selector([], null, null, index, currentFileInfo)).createEmptySelectors(); } for (i = 0; i < this.rules.length; i++) { this.rules[i].allowImports = true; } + this.setParent(this.rules, this); } - this.index = index; - this.currentFileInfo = currentFileInfo; + this._index = index; + this._fileInfo = currentFileInfo; this.debugInfo = debugInfo; this.isRooted = isRooted || false; this.copyVisibilityInfo(visibilityInfo); this.allowRoot = true; }; -Directive.prototype = new Node(); -Directive.prototype.type = "Directive"; -Directive.prototype.accept = function (visitor) { +AtRule.prototype = new Node(); +AtRule.prototype.type = "AtRule"; +AtRule.prototype.accept = function (visitor) { var value = this.value, rules = this.rules; if (rules) { this.rules = visitor.visitArray(rules); @@ -37,15 +39,15 @@ Directive.prototype.accept = function (visitor) { this.value = visitor.visit(value); } }; -Directive.prototype.isRulesetLike = function() { +AtRule.prototype.isRulesetLike = function() { return this.rules || !this.isCharset(); }; -Directive.prototype.isCharset = function() { +AtRule.prototype.isCharset = function() { return "@charset" === this.name; }; -Directive.prototype.genCSS = function (context, output) { +AtRule.prototype.genCSS = function (context, output) { var value = this.value, rules = this.rules; - output.add(this.name, this.currentFileInfo, this.index); + output.add(this.name, this.fileInfo(), this.getIndex()); if (value) { output.add(' '); value.genCSS(context, output); @@ -56,14 +58,14 @@ Directive.prototype.genCSS = function (context, output) { output.add(';'); } }; -Directive.prototype.eval = function (context) { +AtRule.prototype.eval = function (context) { var mediaPathBackup, mediaBlocksBackup, value = this.value, rules = this.rules; - //media stored inside other directive should not bubble over it - //backpup media bubbling information + // media stored inside other atrule should not bubble over it + // backpup media bubbling information mediaPathBackup = context.mediaPath; mediaBlocksBackup = context.mediaBlocks; - //deleted media bubbling information + // deleted media bubbling information context.mediaPath = []; context.mediaBlocks = []; @@ -75,32 +77,32 @@ Directive.prototype.eval = function (context) { rules = [rules[0].eval(context)]; rules[0].root = true; } - //restore media bubbling information + // restore media bubbling information context.mediaPath = mediaPathBackup; context.mediaBlocks = mediaBlocksBackup; - return new Directive(this.name, value, rules, - this.index, this.currentFileInfo, this.debugInfo, this.isRooted, this.visibilityInfo()); + return new AtRule(this.name, value, rules, + this.getIndex(), this.fileInfo(), this.debugInfo, this.isRooted, this.visibilityInfo()); }; -Directive.prototype.variable = function (name) { +AtRule.prototype.variable = function (name) { if (this.rules) { // assuming that there is only one rule at this point - that is how parser constructs the rule return Ruleset.prototype.variable.call(this.rules[0], name); } }; -Directive.prototype.find = function () { +AtRule.prototype.find = function () { if (this.rules) { // assuming that there is only one rule at this point - that is how parser constructs the rule return Ruleset.prototype.find.apply(this.rules[0], arguments); } }; -Directive.prototype.rulesets = function () { +AtRule.prototype.rulesets = function () { if (this.rules) { // assuming that there is only one rule at this point - that is how parser constructs the rule return Ruleset.prototype.rulesets.apply(this.rules[0]); } }; -Directive.prototype.outputRuleset = function (context, output, rules) { +AtRule.prototype.outputRuleset = function (context, output, rules) { var ruleCnt = rules.length, i; context.tabLevel = (context.tabLevel | 0) + 1; @@ -131,4 +133,4 @@ Directive.prototype.outputRuleset = function (context, output, rules) { context.tabLevel--; }; -module.exports = Directive; +module.exports = AtRule; diff --git a/lib/less/tree/call.js b/lib/less/tree/call.js index 12e183747..00dc7b5df 100644 --- a/lib/less/tree/call.js +++ b/lib/less/tree/call.js @@ -1,4 +1,5 @@ var Node = require("./node"), + Anonymous = require("./anonymous"), FunctionCaller = require("../functions/function-caller"); // // A function call node. @@ -6,8 +7,9 @@ var Node = require("./node"), var Call = function (name, args, index, currentFileInfo) { this.name = name; this.args = args; - this.index = index; - this.currentFileInfo = currentFileInfo; + this.mathOn = name === 'calc' ? false : true; + this._index = index; + this._fileInfo = currentFileInfo; }; Call.prototype = new Node(); Call.prototype.type = "Call"; @@ -28,30 +30,55 @@ Call.prototype.accept = function (visitor) { // The function should receive the value, not the variable. // Call.prototype.eval = function (context) { - var args = this.args.map(function (a) { return a.eval(context); }), - result, funcCaller = new FunctionCaller(this.name, context, this.index, this.currentFileInfo); + /** + * Turn off math for calc(), and switch back on for evaluating nested functions + */ + var currentMathContext = context.mathOn; + context.mathOn = this.mathOn; + var args = this.args.map(function (a) { return a.eval(context); }); + context.mathOn = currentMathContext; + + var result, funcCaller = new FunctionCaller(this.name, context, this.getIndex(), this.fileInfo()); + if (funcCaller.isValid()) { try { result = funcCaller.call(args); } catch (e) { - throw { type: e.type || "Runtime", - message: "error evaluating function `" + this.name + "`" + - (e.message ? ': ' + e.message : ''), - index: this.index, filename: this.currentFileInfo.filename }; + throw { + type: e.type || "Runtime", + message: "error evaluating function `" + this.name + "`" + + (e.message ? ': ' + e.message : ''), + index: this.getIndex(), + filename: this.fileInfo().filename, + line: e.lineNumber, + column: e.columnNumber + }; } - if (result != null) { - result.index = this.index; - result.currentFileInfo = this.currentFileInfo; + if (result !== null && result !== undefined) { + // Results that that are not nodes are cast as Anonymous nodes + // Falsy values or booleans are returned as empty nodes + if (!(result instanceof Node)) { + if (!result || result === true) { + result = new Anonymous(null); + } + else { + result = new Anonymous(result.toString()); + } + + } + result._index = this._index; + result._fileInfo = this._fileInfo; return result; } + } - return new Call(this.name, args, this.index, this.currentFileInfo); + return new Call(this.name, args, this.getIndex(), this.fileInfo()); }; Call.prototype.genCSS = function (context, output) { - output.add(this.name + "(", this.currentFileInfo, this.index); + output.add(this.name + "(", this.fileInfo(), this.getIndex()); for (var i = 0; i < this.args.length; i++) { this.args[i].genCSS(context, output); diff --git a/lib/less/tree/color.js b/lib/less/tree/color.js index a694d5ff1..1910f4594 100644 --- a/lib/less/tree/color.js +++ b/lib/less/tree/color.js @@ -99,7 +99,7 @@ Color.prototype.toCSS = function (context, doNotCompress) { // we create a new Color node to hold the result. // Color.prototype.operate = function (context, op, other) { - var rgb = []; + var rgb = new Array(3); var alpha = this.alpha * (1 - other.alpha) + other.alpha; for (var c = 0; c < 3; c++) { rgb[c] = this._operate(context, op, this.rgb[c], other.rgb[c]); @@ -132,7 +132,7 @@ Color.prototype.toHSL = function () { } return { h: h * 360, s: s, l: l, a: a }; }; -//Adapted from http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript +// Adapted from http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript Color.prototype.toHSV = function () { var r = this.rgb[0] / 255, g = this.rgb[1] / 255, @@ -152,7 +152,7 @@ Color.prototype.toHSV = function () { if (max === min) { h = 0; } else { - switch(max) { + switch (max) { case r: h = (g - b) / d + (g < b ? 6 : 0); break; case g: h = (b - r) / d + 2; break; case b: h = (r - g) / d + 4; break; diff --git a/lib/less/tree/comment.js b/lib/less/tree/comment.js index b08c422af..a3cbfdcad 100644 --- a/lib/less/tree/comment.js +++ b/lib/less/tree/comment.js @@ -4,15 +4,15 @@ var Node = require("./node"), var Comment = function (value, isLineComment, index, currentFileInfo) { this.value = value; this.isLineComment = isLineComment; - this.index = index; - this.currentFileInfo = currentFileInfo; + this._index = index; + this._fileInfo = currentFileInfo; this.allowRoot = true; }; Comment.prototype = new Node(); Comment.prototype.type = "Comment"; Comment.prototype.genCSS = function (context, output) { if (this.debugInfo) { - output.add(getDebugInfo(context, this), this.currentFileInfo, this.index); + output.add(getDebugInfo(context, this), this.fileInfo(), this.getIndex()); } output.add(this.value); }; diff --git a/lib/less/tree/condition.js b/lib/less/tree/condition.js index 6b2b5365a..4c893089e 100644 --- a/lib/less/tree/condition.js +++ b/lib/less/tree/condition.js @@ -4,7 +4,7 @@ var Condition = function (op, l, r, i, negate) { this.op = op.trim(); this.lvalue = l; this.rvalue = r; - this.index = i; + this._index = i; this.negate = negate; }; Condition.prototype = new Node(); diff --git a/lib/less/tree/debug-info.js b/lib/less/tree/debug-info.js index f169c2244..5b1db51fa 100644 --- a/lib/less/tree/debug-info.js +++ b/lib/less/tree/debug-info.js @@ -1,7 +1,7 @@ var debugInfo = function(context, ctx, lineSeparator) { var result = ""; if (context.dumpLineNumbers && !context.compress) { - switch(context.dumpLineNumbers) { + switch (context.dumpLineNumbers) { case 'comments': result = debugInfo.asComment(ctx); break; diff --git a/lib/less/tree/rule.js b/lib/less/tree/declaration.js similarity index 67% rename from lib/less/tree/rule.js rename to lib/less/tree/declaration.js index 99d168cff..338a62124 100644 --- a/lib/less/tree/rule.js +++ b/lib/less/tree/declaration.js @@ -1,18 +1,20 @@ var Node = require("./node"), Value = require("./value"), - Keyword = require("./keyword"); + Keyword = require("./keyword"), + Anonymous = require("./anonymous"); -var Rule = function (name, value, important, merge, index, currentFileInfo, inline, variable) { +var Declaration = function (name, value, important, merge, index, currentFileInfo, inline, variable) { this.name = name; - this.value = (value instanceof Node) ? value : new Value([value]); //value instanceof tree.Value || value instanceof tree.Ruleset ?? + this.value = (value instanceof Node) ? value : new Value([value ? new Anonymous(value) : null]); this.important = important ? ' ' + important.trim() : ''; this.merge = merge; - this.index = index; - this.currentFileInfo = currentFileInfo; + this._index = index; + this._fileInfo = currentFileInfo; this.inline = inline || false; this.variable = (variable !== undefined) ? variable : (name.charAt && (name.charAt(0) === '@')); this.allowRoot = true; + this.setParent(this.value, this); }; function evalName(context, name) { @@ -24,21 +26,21 @@ function evalName(context, name) { return value; } -Rule.prototype = new Node(); -Rule.prototype.type = "Rule"; -Rule.prototype.genCSS = function (context, output) { - output.add(this.name + (context.compress ? ':' : ': '), this.currentFileInfo, this.index); +Declaration.prototype = new Node(); +Declaration.prototype.type = "Declaration"; +Declaration.prototype.genCSS = function (context, output) { + output.add(this.name + (context.compress ? ':' : ': '), this.fileInfo(), this.getIndex()); try { this.value.genCSS(context, output); } - catch(e) { - e.index = this.index; - e.filename = this.currentFileInfo.filename; + catch (e) { + e.index = this._index; + e.filename = this._fileInfo.filename; throw e; } - output.add(this.important + ((this.inline || (context.lastRule && context.compress)) ? "" : ";"), this.currentFileInfo, this.index); + output.add(this.important + ((this.inline || (context.lastRule && context.compress)) ? "" : ";"), this._fileInfo, this._index); }; -Rule.prototype.eval = function (context) { +Declaration.prototype.eval = function (context) { var strictMathBypass = false, name = this.name, evaldValue, variable = this.variable; if (typeof name !== "string") { // expand 'primitive' name directly to get @@ -57,7 +59,7 @@ Rule.prototype.eval = function (context) { if (!this.variable && evaldValue.type === "DetachedRuleset") { throw { message: "Rulesets cannot be evaluated on a property.", - index: this.index, filename: this.currentFileInfo.filename }; + index: this.getIndex(), filename: this.fileInfo().filename }; } var important = this.important, importantResult = context.importantScope.pop(); @@ -65,17 +67,17 @@ Rule.prototype.eval = function (context) { important = importantResult.important; } - return new Rule(name, + return new Declaration(name, evaldValue, important, this.merge, - this.index, this.currentFileInfo, this.inline, + this.getIndex(), this.fileInfo(), this.inline, variable); } - catch(e) { + catch (e) { if (typeof e.index !== 'number') { - e.index = this.index; - e.filename = this.currentFileInfo.filename; + e.index = this.getIndex(); + e.filename = this.fileInfo().filename; } throw e; } @@ -85,12 +87,12 @@ Rule.prototype.eval = function (context) { } } }; -Rule.prototype.makeImportant = function () { - return new Rule(this.name, +Declaration.prototype.makeImportant = function () { + return new Declaration(this.name, this.value, "!important", this.merge, - this.index, this.currentFileInfo, this.inline); + this.getIndex(), this.fileInfo(), this.inline); }; -module.exports = Rule; \ No newline at end of file +module.exports = Declaration; \ No newline at end of file diff --git a/lib/less/tree/detached-ruleset.js b/lib/less/tree/detached-ruleset.js index 01bbbc759..2805809fc 100644 --- a/lib/less/tree/detached-ruleset.js +++ b/lib/less/tree/detached-ruleset.js @@ -1,9 +1,11 @@ var Node = require("./node"), - contexts = require("../contexts"); + contexts = require("../contexts"), + utils = require("../utils"); var DetachedRuleset = function (ruleset, frames) { this.ruleset = ruleset; this.frames = frames; + this.setParent(this.ruleset, this); }; DetachedRuleset.prototype = new Node(); DetachedRuleset.prototype.type = "DetachedRuleset"; @@ -12,7 +14,7 @@ DetachedRuleset.prototype.accept = function (visitor) { this.ruleset = visitor.visit(this.ruleset); }; DetachedRuleset.prototype.eval = function (context) { - var frames = this.frames || context.frames.slice(0); + var frames = this.frames || utils.copyArray(context.frames); return new DetachedRuleset(this.ruleset, frames); }; DetachedRuleset.prototype.callEval = function (context) { diff --git a/lib/less/tree/dimension.js b/lib/less/tree/dimension.js index e3ce27ef1..aead4df16 100644 --- a/lib/less/tree/dimension.js +++ b/lib/less/tree/dimension.js @@ -8,8 +8,12 @@ var Node = require("./node"), // var Dimension = function (value, unit) { this.value = parseFloat(value); + if (isNaN(this.value)) { + throw new Error("Dimension is not a number."); + } this.unit = (unit && unit instanceof Unit) ? unit : new Unit(unit ? [unit] : undefined); + this.setParent(this.unit, this); }; Dimension.prototype = new Node(); @@ -57,7 +61,7 @@ Dimension.prototype.genCSS = function (context, output) { // we default to the first Dimension's unit, // so `1px + 2` will yield `3px`. Dimension.prototype.operate = function (context, op, other) { - /*jshint noempty:false */ + /* jshint noempty:false */ var value = this._operate(context, op, this.value, other.value), unit = this.unit.clone(); diff --git a/lib/less/tree/element.js b/lib/less/tree/element.js index 4daf52956..c759f97f0 100644 --- a/lib/less/tree/element.js +++ b/lib/less/tree/element.js @@ -2,7 +2,7 @@ var Node = require("./node"), Paren = require("./paren"), Combinator = require("./combinator"); -var Element = function (combinator, value, index, currentFileInfo, info) { +var Element = function (combinator, value, index, currentFileInfo, visibilityInfo) { this.combinator = combinator instanceof Combinator ? combinator : new Combinator(combinator); @@ -13,9 +13,10 @@ var Element = function (combinator, value, index, currentFileInfo, info) { } else { this.value = ""; } - this.index = index; - this.currentFileInfo = currentFileInfo; - this.copyVisibilityInfo(info); + this._index = index; + this._fileInfo = currentFileInfo; + this.copyVisibilityInfo(visibilityInfo); + this.setParent(this.combinator, this); }; Element.prototype = new Node(); Element.prototype.type = "Element"; @@ -29,17 +30,17 @@ Element.prototype.accept = function (visitor) { Element.prototype.eval = function (context) { return new Element(this.combinator, this.value.eval ? this.value.eval(context) : this.value, - this.index, - this.currentFileInfo, this.visibilityInfo()); + this.getIndex(), + this.fileInfo(), this.visibilityInfo()); }; Element.prototype.clone = function () { return new Element(this.combinator, this.value, - this.index, - this.currentFileInfo, this.visibilityInfo()); + this.getIndex(), + this.fileInfo(), this.visibilityInfo()); }; Element.prototype.genCSS = function (context, output) { - output.add(this.toCSS(context), this.currentFileInfo, this.index); + output.add(this.toCSS(context), this.fileInfo(), this.getIndex()); }; Element.prototype.toCSS = function (context) { context = context || {}; diff --git a/lib/less/tree/extend.js b/lib/less/tree/extend.js index e91fbf77d..8d2c37454 100644 --- a/lib/less/tree/extend.js +++ b/lib/less/tree/extend.js @@ -4,14 +4,14 @@ var Node = require("./node"), var Extend = function Extend(selector, option, index, currentFileInfo, visibilityInfo) { this.selector = selector; this.option = option; - this.index = index; this.object_id = Extend.next_id++; this.parent_ids = [this.object_id]; - this.currentFileInfo = currentFileInfo || {}; + this._index = index; + this._fileInfo = currentFileInfo; this.copyVisibilityInfo(visibilityInfo); this.allowRoot = true; - switch(option) { + switch (option) { case "all": this.allowBefore = true; this.allowAfter = true; @@ -21,6 +21,7 @@ var Extend = function Extend(selector, option, index, currentFileInfo, visibilit this.allowAfter = false; break; } + this.setParent(this.selector, this); }; Extend.next_id = 0; @@ -30,12 +31,12 @@ Extend.prototype.accept = function (visitor) { this.selector = visitor.visit(this.selector); }; Extend.prototype.eval = function (context) { - return new Extend(this.selector.eval(context), this.option, this.index, this.currentFileInfo, this.visibilityInfo()); + return new Extend(this.selector.eval(context), this.option, this.getIndex(), this.fileInfo(), this.visibilityInfo()); }; Extend.prototype.clone = function (context) { - return new Extend(this.selector, this.option, this.index, this.currentFileInfo, this.visibilityInfo()); + return new Extend(this.selector, this.option, this.getIndex(), this.fileInfo(), this.visibilityInfo()); }; -//it concatenates (joins) all selectors in selector array +// it concatenates (joins) all selectors in selector array Extend.prototype.findSelfSelectors = function (selectors) { var selfElements = [], i, diff --git a/lib/less/tree/import.js b/lib/less/tree/import.js index 3787b052b..b459bb392 100644 --- a/lib/less/tree/import.js +++ b/lib/less/tree/import.js @@ -3,7 +3,9 @@ var Node = require("./node"), URL = require("./url"), Quoted = require("./quoted"), Ruleset = require("./ruleset"), - Anonymous = require("./anonymous"); + Anonymous = require("./anonymous"), + utils = require("../utils"), + LessError = require("../less-error"); // // CSS @import node @@ -19,21 +21,23 @@ var Node = require("./node"), // var Import = function (path, features, options, index, currentFileInfo, visibilityInfo) { this.options = options; - this.index = index; + this._index = index; + this._fileInfo = currentFileInfo; this.path = path; this.features = features; - this.currentFileInfo = currentFileInfo; this.allowRoot = true; if (this.options.less !== undefined || this.options.inline) { this.css = !this.options.less || this.options.inline; } else { var pathValue = this.getPath(); - if (pathValue && /[#\.\&\?\/]css([\?;].*)?$/.test(pathValue)) { + if (pathValue && /[#\.\&\?]css([\?;].*)?$/.test(pathValue)) { this.css = true; } } this.copyVisibilityInfo(visibilityInfo); + this.setParent(this.features, this); + this.setParent(this.path, this); }; // @@ -52,13 +56,13 @@ Import.prototype.accept = function (visitor) { this.features = visitor.visit(this.features); } this.path = visitor.visit(this.path); - if (!this.options.plugin && !this.options.inline && this.root) { + if (!this.options.isPlugin && !this.options.inline && this.root) { this.root = visitor.visit(this.root); } }; Import.prototype.genCSS = function (context, output) { - if (this.css && this.path.currentFileInfo.reference === undefined) { - output.add("@import ", this.currentFileInfo, this.index); + if (this.css && this.path._fileInfo.reference === undefined) { + output.add("@import ", this._fileInfo, this._index); this.path.genCSS(context, output); if (this.features) { output.add(" "); @@ -89,11 +93,11 @@ Import.prototype.evalForImport = function (context) { path = path.value; } - return new Import(path.eval(context), this.features, this.options, this.index, this.currentFileInfo, this.visibilityInfo()); + return new Import(path.eval(context), this.features, this.options, this._index, this._fileInfo, this.visibilityInfo()); }; Import.prototype.evalPath = function (context) { var path = this.path.eval(context); - var rootpath = this.currentFileInfo && this.currentFileInfo.rootpath; + var rootpath = this._fileInfo && this._fileInfo.rootpath; if (!(path instanceof URL)) { if (rootpath) { @@ -113,8 +117,8 @@ Import.prototype.eval = function (context) { if (this.options.reference || this.blocksVisibility()) { if (result.length || result.length === 0) { result.forEach(function (node) { - node.addVisibilityBlock(); - } + node.addVisibilityBlock(); + } ); } else { result.addVisibilityBlock(); @@ -126,11 +130,21 @@ Import.prototype.doEval = function (context) { var ruleset, registry, features = this.features && this.features.eval(context); - if (this.options.plugin) { + if (this.options.isPlugin) { + if (this.root && this.root.eval) { + try { + this.root.eval(context); + } + catch (e) { + e.message = "Plugin error during evaluation"; + throw new LessError(e, this.root.imports, this.root.filename); + } + } registry = context.frames[0] && context.frames[0].functionRegistry; if ( registry && this.root && this.root.functions ) { registry.addMultiple( this.root.functions ); } + return []; } @@ -144,20 +158,20 @@ Import.prototype.doEval = function (context) { } if (this.options.inline) { var contents = new Anonymous(this.root, 0, - { - filename: this.importedFilename, - reference: this.path.currentFileInfo && this.path.currentFileInfo.reference - }, true, true); + { + filename: this.importedFilename, + reference: this.path._fileInfo && this.path._fileInfo.reference + }, true, true); return this.features ? new Media([contents], this.features.value) : [contents]; } else if (this.css) { - var newImport = new Import(this.evalPath(context), features, this.options, this.index); + var newImport = new Import(this.evalPath(context), features, this.options, this._index); if (!newImport.css && this.error) { throw this.error; } return newImport; } else { - ruleset = new Ruleset(null, this.root.rules.slice(0)); + ruleset = new Ruleset(null, utils.copyArray(this.root.rules)); ruleset.evalImports(context); return this.features ? new Media(ruleset.rules, this.features.value) : ruleset.rules; diff --git a/lib/less/tree/index.js b/lib/less/tree/index.js index c4624dd69..349cb3fb6 100644 --- a/lib/less/tree/index.js +++ b/lib/less/tree/index.js @@ -1,15 +1,15 @@ -var tree = {}; +var tree = Object.create(null); tree.Node = require('./node'); -tree.Alpha = require('./alpha'); tree.Color = require('./color'); -tree.Directive = require('./directive'); +tree.AtRule = require('./atrule'); tree.DetachedRuleset = require('./detached-ruleset'); tree.Operation = require('./operation'); tree.Dimension = require('./dimension'); tree.Unit = require('./unit'); tree.Keyword = require('./keyword'); tree.Variable = require('./variable'); +tree.Property = require('./property'); tree.Ruleset = require('./ruleset'); tree.Element = require('./element'); tree.Attribute = require('./attribute'); @@ -17,7 +17,7 @@ tree.Combinator = require('./combinator'); tree.Selector = require('./selector'); tree.Quoted = require('./quoted'); tree.Expression = require('./expression'); -tree.Rule = require('./rule'); +tree.Declaration = require('./declaration'); tree.Call = require('./call'); tree.URL = require('./url'); tree.Import = require('./import'); @@ -36,6 +36,6 @@ tree.Media = require('./media'); tree.UnicodeDescriptor = require('./unicode-descriptor'); tree.Negative = require('./negative'); tree.Extend = require('./extend'); -tree.RulesetCall = require('./ruleset-call'); +tree.VariableCall = require('./variable-call'); module.exports = tree; diff --git a/lib/less/tree/javascript.js b/lib/less/tree/javascript.js index 157738275..e2ee01371 100644 --- a/lib/less/tree/javascript.js +++ b/lib/less/tree/javascript.js @@ -6,8 +6,8 @@ var JsEvalNode = require("./js-eval-node"), var JavaScript = function (string, escaped, index, currentFileInfo) { this.escaped = escaped; this.expression = string; - this.index = index; - this.currentFileInfo = currentFileInfo; + this._index = index; + this._fileInfo = currentFileInfo; }; JavaScript.prototype = new JsEvalNode(); JavaScript.prototype.type = "JavaScript"; @@ -17,7 +17,7 @@ JavaScript.prototype.eval = function(context) { if (typeof result === 'number') { return new Dimension(result); } else if (typeof result === 'string') { - return new Quoted('"' + result + '"', result, this.escaped, this.index); + return new Quoted('"' + result + '"', result, this.escaped, this._index); } else if (Array.isArray(result)) { return new Anonymous(result.join(', ')); } else { diff --git a/lib/less/tree/js-eval-node.js b/lib/less/tree/js-eval-node.js index 30fbbfae1..24d6594de 100644 --- a/lib/less/tree/js-eval-node.js +++ b/lib/less/tree/js-eval-node.js @@ -10,28 +10,28 @@ JsEvalNode.prototype.evaluateJavaScript = function (expression, context) { that = this, evalContext = {}; - if (context.javascriptEnabled !== undefined && !context.javascriptEnabled) { - throw { message: "You are using JavaScript, which has been disabled.", - filename: this.currentFileInfo.filename, - index: this.index }; + if (!context.javascriptEnabled) { + throw { message: "Inline JavaScript is not enabled. Is it set in your options?", + filename: this.fileInfo().filename, + index: this.getIndex() }; } expression = expression.replace(/@\{([\w-]+)\}/g, function (_, name) { - return that.jsify(new Variable('@' + name, that.index, that.currentFileInfo).eval(context)); + return that.jsify(new Variable('@' + name, that.getIndex(), that.fileInfo()).eval(context)); }); try { expression = new Function('return (' + expression + ')'); } catch (e) { throw { message: "JavaScript evaluation error: " + e.message + " from `" + expression + "`" , - filename: this.currentFileInfo.filename, - index: this.index }; + filename: this.fileInfo().filename, + index: this.getIndex() }; } var variables = context.frames[0].variables(); for (var k in variables) { if (variables.hasOwnProperty(k)) { - /*jshint loopfunc:true */ + /* jshint loopfunc:true */ evalContext[k.slice(1)] = { value: variables[k].value, toJS: function () { @@ -45,8 +45,8 @@ JsEvalNode.prototype.evaluateJavaScript = function (expression, context) { result = expression.call(evalContext); } catch (e) { throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message.replace(/["]/g, "'") + "'" , - filename: this.currentFileInfo.filename, - index: this.index }; + filename: this.fileInfo().filename, + index: this.getIndex() }; } return result; }; diff --git a/lib/less/tree/media.js b/lib/less/tree/media.js index 0bbd23a65..6cd821436 100644 --- a/lib/less/tree/media.js +++ b/lib/less/tree/media.js @@ -3,23 +3,27 @@ var Ruleset = require("./ruleset"), Selector = require("./selector"), Anonymous = require("./anonymous"), Expression = require("./expression"), - Directive = require("./directive"); + AtRule = require("./atrule"), + utils = require("../utils"); var Media = function (value, features, index, currentFileInfo, visibilityInfo) { - this.index = index; - this.currentFileInfo = currentFileInfo; + this._index = index; + this._fileInfo = currentFileInfo; - var selectors = (new Selector([], null, null, this.index, this.currentFileInfo)).createEmptySelectors(); + var selectors = (new Selector([], null, null, this._index, this._fileInfo)).createEmptySelectors(); this.features = new Value(features); this.rules = [new Ruleset(selectors, value)]; this.rules[0].allowImports = true; this.copyVisibilityInfo(visibilityInfo); this.allowRoot = true; + this.setParent(selectors, this); + this.setParent(this.features, this); + this.setParent(this.rules, this); }; -Media.prototype = new Directive(); +Media.prototype = new AtRule(); Media.prototype.type = "Media"; -Media.prototype.isRulesetLike = true; +Media.prototype.isRulesetLike = function() { return true; }; Media.prototype.accept = function (visitor) { if (this.features) { this.features = visitor.visit(this.features); @@ -29,7 +33,7 @@ Media.prototype.accept = function (visitor) { } }; Media.prototype.genCSS = function (context, output) { - output.add('@media ', this.currentFileInfo, this.index); + output.add('@media ', this._fileInfo, this._index); this.features.genCSS(context, output); this.outputRuleset(context, output, this.rules); }; @@ -39,24 +43,13 @@ Media.prototype.eval = function (context) { context.mediaPath = []; } - var media = new Media(null, [], this.index, this.currentFileInfo, this.visibilityInfo()); + var media = new Media(null, [], this._index, this._fileInfo, this.visibilityInfo()); if (this.debugInfo) { this.rules[0].debugInfo = this.debugInfo; media.debugInfo = this.debugInfo; } - var strictMathBypass = false; - if (!context.strictMath) { - strictMathBypass = true; - context.strictMath = true; - } - try { - media.features = this.features.eval(context); - } - finally { - if (strictMathBypass) { - context.strictMath = false; - } - } + + media.features = this.features.eval(context); context.mediaPath.push(media); context.mediaBlocks.push(media); @@ -76,10 +69,11 @@ Media.prototype.evalTop = function (context) { // Render all dependent Media blocks. if (context.mediaBlocks.length > 1) { - var selectors = (new Selector([], null, null, this.index, this.currentFileInfo)).createEmptySelectors(); + var selectors = (new Selector([], null, null, this.getIndex(), this.fileInfo())).createEmptySelectors(); result = new Ruleset(selectors, context.mediaBlocks); result.multiMedia = true; result.copyVisibilityInfo(this.visibilityInfo()); + this.setParent(result, this); } delete context.mediaBlocks; @@ -116,6 +110,7 @@ Media.prototype.evalNested = function (context) { return new Expression(path); })); + this.setParent(this.features, this); // Fake a tree-node that doesn't output anything. return new Ruleset([], []); @@ -140,6 +135,7 @@ Media.prototype.bubbleSelectors = function (selectors) { if (!selectors) { return; } - this.rules = [new Ruleset(selectors.slice(0), [this.rules[0]])]; + this.rules = [new Ruleset(utils.copyArray(selectors), [this.rules[0]])]; + this.setParent(this.rules, this); }; module.exports = Media; diff --git a/lib/less/tree/mixin-call.js b/lib/less/tree/mixin-call.js index 5864a0c36..7b1d0c0bc 100644 --- a/lib/less/tree/mixin-call.js +++ b/lib/less/tree/mixin-call.js @@ -6,10 +6,11 @@ var Node = require("./node"), var MixinCall = function (elements, args, index, currentFileInfo, important) { this.selector = new Selector(elements); this.arguments = args || []; - this.index = index; - this.currentFileInfo = currentFileInfo; + this._index = index; + this._fileInfo = currentFileInfo; this.important = important; this.allowRoot = true; + this.setParent(this.selector, this); }; MixinCall.prototype = new Node(); MixinCall.prototype.type = "MixinCall"; @@ -117,7 +118,7 @@ MixinCall.prototype.eval = function (context) { if ((count[defTrue] + count[defFalse]) > 1) { throw { type: 'Runtime', message: 'Ambiguous use of `default()` found when matching for `' + this.format(args) + '`', - index: this.index, filename: this.currentFileInfo.filename }; + index: this.getIndex(), filename: this.fileInfo().filename }; } } @@ -135,7 +136,7 @@ MixinCall.prototype.eval = function (context) { this._setVisibilityToReplacement(newRules); Array.prototype.push.apply(rules, newRules); } catch (e) { - throw { message: e.message, index: this.index, filename: this.currentFileInfo.filename, stack: e.stack }; + throw { message: e.message, index: this.getIndex(), filename: this.fileInfo().filename, stack: e.stack }; } } } @@ -148,11 +149,11 @@ MixinCall.prototype.eval = function (context) { if (isOneFound) { throw { type: 'Runtime', message: 'No matching definition was found for `' + this.format(args) + '`', - index: this.index, filename: this.currentFileInfo.filename }; + index: this.getIndex(), filename: this.fileInfo().filename }; } else { throw { type: 'Name', message: this.selector.toCSS().trim() + " is undefined", - index: this.index, filename: this.currentFileInfo.filename }; + index: this.getIndex(), filename: this.fileInfo().filename }; } }; diff --git a/lib/less/tree/mixin-definition.js b/lib/less/tree/mixin-definition.js index b2e3413d0..31b3b39ad 100644 --- a/lib/less/tree/mixin-definition.js +++ b/lib/less/tree/mixin-definition.js @@ -1,13 +1,14 @@ var Selector = require("./selector"), Element = require("./element"), Ruleset = require("./ruleset"), - Rule = require("./rule"), + Declaration = require("./declaration"), Expression = require("./expression"), - contexts = require("../contexts"); + contexts = require("../contexts"), + utils = require("../utils"); var Definition = function (name, params, rules, condition, variadic, frames, visibilityInfo) { this.name = name; - this.selectors = [new Selector([new Element(null, name, this.index, this.currentFileInfo)])]; + this.selectors = [new Selector([new Element(null, name, this._index, this._fileInfo)])]; this.params = params; this.condition = condition; this.variadic = variadic; @@ -42,10 +43,10 @@ Definition.prototype.accept = function (visitor) { } }; Definition.prototype.evalParams = function (context, mixinEnv, args, evaldArguments) { - /*jshint boss:true */ + /* jshint boss:true */ var frame = new Ruleset(null, null), varargs, arg, - params = this.params.slice(0), + params = utils.copyArray(this.params), i, j, val, name, isNamedFound, argIndex, argsLength = 0; if (mixinEnv.frames && mixinEnv.frames[0] && mixinEnv.frames[0].functionRegistry) { @@ -54,7 +55,7 @@ Definition.prototype.evalParams = function (context, mixinEnv, args, evaldArgume mixinEnv = new contexts.Eval(mixinEnv, [frame].concat(mixinEnv.frames)); if (args) { - args = args.slice(0); + args = utils.copyArray(args); argsLength = args.length; for (i = 0; i < argsLength; i++) { @@ -64,7 +65,7 @@ Definition.prototype.evalParams = function (context, mixinEnv, args, evaldArgume for (j = 0; j < params.length; j++) { if (!evaldArguments[j] && name === params[j].name) { evaldArguments[j] = arg.value.eval(context); - frame.prependRule(new Rule(name, arg.value.eval(context))); + frame.prependRule(new Declaration(name, arg.value.eval(context))); isNamedFound = true; break; } @@ -92,7 +93,7 @@ Definition.prototype.evalParams = function (context, mixinEnv, args, evaldArgume for (j = argIndex; j < argsLength; j++) { varargs.push(args[j].value.eval(context)); } - frame.prependRule(new Rule(name, new Expression(varargs).eval(context))); + frame.prependRule(new Declaration(name, new Expression(varargs).eval(context))); } else { val = arg && arg.value; if (val) { @@ -105,7 +106,7 @@ Definition.prototype.evalParams = function (context, mixinEnv, args, evaldArgume ' (' + argsLength + ' for ' + this.arity + ')' }; } - frame.prependRule(new Rule(name, val)); + frame.prependRule(new Declaration(name, val)); evaldArguments[i] = val; } } @@ -132,7 +133,7 @@ Definition.prototype.makeImportant = function() { return result; }; Definition.prototype.eval = function (context) { - return new Definition(this.name, this.params, this.rules, this.condition, this.variadic, this.frames || context.frames.slice(0)); + return new Definition(this.name, this.params, this.rules, this.condition, this.variadic, this.frames || utils.copyArray(context.frames)); }; Definition.prototype.evalCall = function (context, args, important) { var _arguments = [], @@ -140,9 +141,9 @@ Definition.prototype.evalCall = function (context, args, important) { frame = this.evalParams(context, new contexts.Eval(context, mixinFrames), args, _arguments), rules, ruleset; - frame.prependRule(new Rule('@arguments', new Expression(_arguments).eval(context))); + frame.prependRule(new Declaration('@arguments', new Expression(_arguments).eval(context))); - rules = this.rules.slice(0); + rules = utils.copyArray(this.rules); ruleset = new Ruleset(null, rules); ruleset.originalRuleset = this; @@ -155,7 +156,7 @@ Definition.prototype.evalCall = function (context, args, important) { Definition.prototype.matchCondition = function (args, context) { if (this.condition && !this.condition.eval( new contexts.Eval(context, - [this.evalParams(context, /* the parameter variables*/ + [this.evalParams(context, /* the parameter variables */ new contexts.Eval(context, this.frames ? this.frames.concat(context.frames) : context.frames), args, [])] .concat(this.frames || []) // the parent namespace/mixin frames .concat(context.frames)))) { // the current environment frames @@ -173,7 +174,7 @@ Definition.prototype.matchArgs = function (args, context) { } }, 0); - if (! this.variadic) { + if (!this.variadic) { if (requiredArgsCnt < this.required) { return false; } diff --git a/lib/less/tree/node.js b/lib/less/tree/node.js index 50e122a25..2de98c6c0 100644 --- a/lib/less/tree/node.js +++ b/lib/less/tree/node.js @@ -1,5 +1,39 @@ var Node = function() { + this.parent = null; + this.visibilityBlocks = undefined; + this.nodeVisible = undefined; + this.rootNode = null; + this.parsed = null; + + var self = this; + Object.defineProperty(this, "currentFileInfo", { + get: function() { return self.fileInfo(); } + }); + Object.defineProperty(this, "index", { + get: function() { return self.getIndex(); } + }); + +}; +Node.prototype.setParent = function(nodes, parent) { + function set(node) { + if (node && node instanceof Node) { + node.parent = parent; + } + } + if (Array.isArray(nodes)) { + nodes.forEach(set); + } + else { + set(nodes); + } +}; +Node.prototype.getIndex = function() { + return this._index || (this.parent && this.parent.getIndex()) || 0; +}; +Node.prototype.fileInfo = function() { + return this._fileInfo || (this.parent && this.parent.fileInfo()) || {}; }; +Node.prototype.isRulesetLike = function() { return false; }; Node.prototype.toCSS = function (context) { var strs = []; this.genCSS(context, { @@ -29,8 +63,8 @@ Node.prototype._operate = function (context, op, a, b) { }; Node.prototype.fround = function(context, value) { var precision = context && context.numPrecision; - //add "epsilon" to ensure numbers like 1.000000005 (represented as 1.000000004999....) are properly rounded... - return (precision == null) ? value : Number((value + 2e-16).toFixed(precision)); + // add "epsilon" to ensure numbers like 1.000000005 (represented as 1.000000004999...) are properly rounded: + return (precision) ? Number((value + 2e-16).toFixed(precision)) : value; }; Node.compare = function (a, b) { /* returns: @@ -90,13 +124,13 @@ Node.prototype.removeVisibilityBlock = function () { } this.visibilityBlocks = this.visibilityBlocks - 1; }; -//Turns on node visibility - if called node will be shown in output regardless -//of whether it comes from import by reference or not +// Turns on node visibility - if called node will be shown in output regardless +// of whether it comes from import by reference or not Node.prototype.ensureVisibility = function () { this.nodeVisible = true; }; -//Turns off node visibility - if called node will NOT be shown in output regardless -//of whether it comes from import by reference or not +// Turns off node visibility - if called node will NOT be shown in output regardless +// of whether it comes from import by reference or not Node.prototype.ensureInvisibility = function () { this.nodeVisible = false; }; diff --git a/lib/less/tree/operation.js b/lib/less/tree/operation.js index ec40d3ce0..e3c225a9e 100644 --- a/lib/less/tree/operation.js +++ b/lib/less/tree/operation.js @@ -25,7 +25,7 @@ Operation.prototype.eval = function (context) { } if (!a.operate) { throw { type: "Operation", - message: "Operation on an invalid type" }; + message: "Operation on an invalid type" }; } return a.operate(context, this.op, b); diff --git a/lib/less/tree/property.js b/lib/less/tree/property.js new file mode 100644 index 000000000..86d5f4987 --- /dev/null +++ b/lib/less/tree/property.js @@ -0,0 +1,70 @@ +var Node = require("./node"), + Declaration = require("./declaration"); + +var Property = function (name, index, currentFileInfo) { + this.name = name; + this._index = index; + this._fileInfo = currentFileInfo; +}; +Property.prototype = new Node(); +Property.prototype.type = "Property"; +Property.prototype.eval = function (context) { + var property, name = this.name; + // TODO: shorten this reference + var mergeRules = context.pluginManager.less.visitors.ToCSSVisitor.prototype._mergeRules; + + if (this.evaluating) { + throw { type: 'Name', + message: "Recursive property reference for " + name, + filename: this.fileInfo().filename, + index: this.getIndex() }; + } + + this.evaluating = true; + + property = this.find(context.frames, function (frame) { + + var v, vArr = frame.property(name); + if (vArr) { + for (var i = 0; i < vArr.length; i++) { + v = vArr[i]; + + vArr[i] = new Declaration(v.name, + v.value, + v.important, + v.merge, + v.index, + v.currentFileInfo, + v.inline, + v.variable + ); + } + mergeRules(vArr); + + v = vArr[vArr.length - 1]; + if (v.important) { + var importantScope = context.importantScope[context.importantScope.length - 1]; + importantScope.important = v.important; + } + v = v.value.eval(context); + return v; + } + }); + if (property) { + this.evaluating = false; + return property; + } else { + throw { type: 'Name', + message: "Property '" + name + "' is undefined", + filename: this.currentFileInfo.filename, + index: this.index }; + } +}; +Property.prototype.find = function (obj, fun) { + for (var i = 0, r; i < obj.length; i++) { + r = fun.call(obj, obj[i]); + if (r) { return r; } + } + return null; +}; +module.exports = Property; diff --git a/lib/less/tree/quoted.js b/lib/less/tree/quoted.js index e1be87d10..dd41f8ce3 100644 --- a/lib/less/tree/quoted.js +++ b/lib/less/tree/quoted.js @@ -1,19 +1,19 @@ var Node = require("./node"), - JsEvalNode = require("./js-eval-node"), - Variable = require("./variable"); + Variable = require("./variable"), + Property = require("./property"); var Quoted = function (str, content, escaped, index, currentFileInfo) { this.escaped = (escaped == null) ? true : escaped; this.value = content || ''; this.quote = str.charAt(0); - this.index = index; - this.currentFileInfo = currentFileInfo; + this._index = index; + this._fileInfo = currentFileInfo; }; -Quoted.prototype = new JsEvalNode(); +Quoted.prototype = new Node(); Quoted.prototype.type = "Quoted"; Quoted.prototype.genCSS = function (context, output) { if (!this.escaped) { - output.add(this.quote, this.currentFileInfo, this.index); + output.add(this.quote, this.fileInfo(), this.getIndex()); } output.add(this.value); if (!this.escaped) { @@ -21,15 +21,16 @@ Quoted.prototype.genCSS = function (context, output) { } }; Quoted.prototype.containsVariables = function() { - return this.value.match(/(`([^`]+)`)|@\{([\w-]+)\}/); + return this.value.match(/@\{([\w-]+)\}/); }; Quoted.prototype.eval = function (context) { var that = this, value = this.value; - var javascriptReplacement = function (_, exp) { - return String(that.evaluateJavaScript(exp, context)); + var variableReplacement = function (_, name) { + var v = new Variable('@' + name, that.getIndex(), that.fileInfo()).eval(context, true); + return (v instanceof Quoted) ? v.value : v.toCSS(); }; - var interpolationReplacement = function (_, name) { - var v = new Variable('@' + name, that.index, that.currentFileInfo).eval(context, true); + var propertyReplacement = function (_, name) { + var v = new Property('$' + name, that.getIndex(), that.fileInfo()).eval(context, true); return (v instanceof Quoted) ? v.value : v.toCSS(); }; function iterativeReplace(value, regexp, replacementFnc) { @@ -40,9 +41,9 @@ Quoted.prototype.eval = function (context) { } while (value !== evaluatedValue); return evaluatedValue; } - value = iterativeReplace(value, /`([^`]+)`/g, javascriptReplacement); - value = iterativeReplace(value, /@\{([\w-]+)\}/g, interpolationReplacement); - return new Quoted(this.quote + value + this.quote, value, this.escaped, this.index, this.currentFileInfo); + value = iterativeReplace(value, /@\{([\w-]+)\}/g, variableReplacement); + value = iterativeReplace(value, /\$\{([\w-]+)\}/g, propertyReplacement); + return new Quoted(this.quote + value + this.quote, value, this.escaped, this.getIndex(), this.fileInfo()); }; Quoted.prototype.compare = function (other) { // when comparing quoted strings allow the quote to differ diff --git a/lib/less/tree/ruleset.js b/lib/less/tree/ruleset.js index dcf8ae843..8c2ff3956 100644 --- a/lib/less/tree/ruleset.js +++ b/lib/less/tree/ruleset.js @@ -1,25 +1,35 @@ var Node = require("./node"), - Rule = require("./rule"), + Declaration = require("./declaration"), + Keyword = require("./keyword"), + Comment = require("./comment"), + Paren = require("./paren"), Selector = require("./selector"), Element = require("./element"), - Paren = require("./paren"), + Anonymous = require("./anonymous"), contexts = require("../contexts"), globalFunctionRegistry = require("../functions/function-registry"), defaultFunc = require("../functions/default"), - getDebugInfo = require("./debug-info"); + getDebugInfo = require("./debug-info"), + utils = require("../utils"); var Ruleset = function (selectors, rules, strictImports, visibilityInfo) { this.selectors = selectors; this.rules = rules; this._lookups = {}; + this._variables = null; + this._properties = null; this.strictImports = strictImports; this.copyVisibilityInfo(visibilityInfo); this.allowRoot = true; + + this.setParent(this.selectors, this); + this.setParent(this.rules, this); + }; Ruleset.prototype = new Node(); Ruleset.prototype.type = "Ruleset"; Ruleset.prototype.isRuleset = true; -Ruleset.prototype.isRulesetLike = true; +Ruleset.prototype.isRulesetLike = function() { return true; }; Ruleset.prototype.accept = function (visitor) { if (this.paths) { this.paths = visitor.visitArray(this.paths, true); @@ -35,14 +45,14 @@ Ruleset.prototype.eval = function (context) { selCnt, selector, i, hasOnePassingSelector = false; if (thisSelectors && (selCnt = thisSelectors.length)) { - selectors = []; + selectors = new Array(selCnt); defaultFunc.error({ type: "Syntax", message: "it is currently only allowed in parametric mixin guards," }); for (i = 0; i < selCnt; i++) { selector = thisSelectors[i].eval(context); - selectors.push(selector); + selectors[i] = selector; if (selector.evaldCondition) { hasOnePassingSelector = true; } @@ -52,7 +62,7 @@ Ruleset.prototype.eval = function (context) { hasOnePassingSelector = true; } - var rules = this.rules ? this.rules.slice(0) : null, + var rules = this.rules ? utils.copyArray(this.rules) : null, ruleset = new Ruleset(selectors, rules, this.strictImports, this.visibilityInfo()), rule, subRule; @@ -100,21 +110,21 @@ Ruleset.prototype.eval = function (context) { // Store the frames around mixin definitions, // so they can be evaluated like closures when the time comes. - var rsRules = ruleset.rules, rsRuleCnt = rsRules ? rsRules.length : 0; - for (i = 0; i < rsRuleCnt; i++) { - if (rsRules[i].evalFirst) { - rsRules[i] = rsRules[i].eval(context); + var rsRules = ruleset.rules; + for (i = 0; (rule = rsRules[i]); i++) { + if (rule.evalFirst) { + rsRules[i] = rule.eval(context); } } var mediaBlockCount = (context.mediaBlocks && context.mediaBlocks.length) || 0; // Evaluate mixin calls. - for (i = 0; i < rsRuleCnt; i++) { - if (rsRules[i].type === "MixinCall") { - /*jshint loopfunc:true */ - rules = rsRules[i].eval(context).filter(function(r) { - if ((r instanceof Rule) && r.variable) { + for (i = 0; (rule = rsRules[i]); i++) { + if (rule.type === "MixinCall") { + /* jshint loopfunc:true */ + rules = rule.eval(context).filter(function(r) { + if ((r instanceof Declaration) && r.variable) { // do not pollute the scope if the variable is // already there. consider returning false here // but we need a way to "return" variable from mixins @@ -123,47 +133,44 @@ Ruleset.prototype.eval = function (context) { return true; }); rsRules.splice.apply(rsRules, [i, 1].concat(rules)); - rsRuleCnt += rules.length - 1; i += rules.length - 1; ruleset.resetCache(); - } else if (rsRules[i].type === "RulesetCall") { - /*jshint loopfunc:true */ - rules = rsRules[i].eval(context).rules.filter(function(r) { - if ((r instanceof Rule) && r.variable) { + } else if (rule.type === "VariableCall") { + /* jshint loopfunc:true */ + rules = rule.eval(context).rules.filter(function(r) { + if ((r instanceof Declaration) && r.variable) { // do not pollute the scope at all return false; } return true; }); rsRules.splice.apply(rsRules, [i, 1].concat(rules)); - rsRuleCnt += rules.length - 1; i += rules.length - 1; ruleset.resetCache(); } } // Evaluate everything else - for (i = 0; i < rsRules.length; i++) { - rule = rsRules[i]; + for (i = 0; (rule = rsRules[i]); i++) { if (!rule.evalFirst) { rsRules[i] = rule = rule.eval ? rule.eval(context) : rule; } } // Evaluate everything else - for (i = 0; i < rsRules.length; i++) { - rule = rsRules[i]; + for (i = 0; (rule = rsRules[i]); i++) { // for rulesets, check if it is a css guard and can be removed if (rule instanceof Ruleset && rule.selectors && rule.selectors.length === 1) { // check if it can be folded in (e.g. & where) if (rule.selectors[0].isJustParentSelector()) { rsRules.splice(i--, 1); - for (var j = 0; j < rule.rules.length; j++) { - subRule = rule.rules[j]; - subRule.copyVisibilityInfo(rule.visibilityInfo()); - if (!(subRule instanceof Rule) || !subRule.variable) { - rsRules.splice(++i, 0, subRule); + for (var j = 0; (subRule = rule.rules[j]); j++) { + if (subRule instanceof Node) { + subRule.copyVisibilityInfo(rule.visibilityInfo()); + if (!(subRule instanceof Declaration) || !subRule.variable) { + rsRules.splice(++i, 0, subRule); + } } } } @@ -191,7 +198,7 @@ Ruleset.prototype.evalImports = function(context) { importRules = rules[i].eval(context); if (importRules && (importRules.length || importRules.length === 0)) { rules.splice.apply(rules, [i, 1].concat(importRules)); - i+= importRules.length - 1; + i += importRules.length - 1; } else { rules.splice(i, 1, importRules); } @@ -230,12 +237,13 @@ Ruleset.prototype.matchCondition = function (args, context) { Ruleset.prototype.resetCache = function () { this._rulesets = null; this._variables = null; + this._properties = null; this._lookups = {}; }; Ruleset.prototype.variables = function () { if (!this._variables) { this._variables = !this.rules ? {} : this.rules.reduce(function (hash, r) { - if (r instanceof Rule && r.variable === true) { + if (r instanceof Declaration && r.variable === true) { hash[r.name] = r; } // when evaluating variables in an import statement, imports have not been eval'd @@ -254,17 +262,81 @@ Ruleset.prototype.variables = function () { } return this._variables; }; +Ruleset.prototype.properties = function () { + if (!this._properties) { + this._properties = !this.rules ? {} : this.rules.reduce(function (hash, r) { + if (r instanceof Declaration && r.variable !== true) { + var name = (r.name.length === 1) && (r.name[0] instanceof Keyword) ? + r.name[0].value : r.name; + // Properties don't overwrite as they can merge + if (!hash['$' + name]) { + hash['$' + name] = [ r ]; + } + else { + hash['$' + name].push(r); + } + } + return hash; + }, {}); + } + return this._properties; +}; Ruleset.prototype.variable = function (name) { - return this.variables()[name]; + var decl = this.variables()[name]; + if (decl) { + return this.parseValue(decl); + } +}; +Ruleset.prototype.property = function (name) { + var decl = this.properties()[name]; + if (decl) { + return this.parseValue(decl); + } +}; +Ruleset.prototype.parseValue = function(toParse) { + var self = this; + function transformDeclaration(decl) { + if (decl.value instanceof Anonymous && !decl.parsed) { + this.parse.parseNode( + decl.value.value, + ["value", "important"], + decl.value.getIndex(), + decl.fileInfo(), + function(err, result) { + if (err) { + decl.parsed = true; + } + if (result) { + decl.value = result[0]; + decl.important = result[1] || ''; + decl.parsed = true; + } + }); + + return decl; + } + else { + return decl; + } + } + if (!Array.isArray(toParse)) { + return transformDeclaration.call(self, toParse); + } + else { + var nodes = []; + toParse.forEach(function(n) { + nodes.push(transformDeclaration.call(self, n)); + }); + return nodes; + } }; Ruleset.prototype.rulesets = function () { if (!this.rules) { return []; } - var filtRules = [], rules = this.rules, cnt = rules.length, + var filtRules = [], rules = this.rules, i, rule; - for (i = 0; i < cnt; i++) { - rule = rules[i]; + for (i = 0; (rule = rules[i]); i++) { if (rule.isRuleset) { filtRules.push(rule); } @@ -279,6 +351,7 @@ Ruleset.prototype.prependRule = function (rule) { } else { this.rules = [ rule ]; } + this.setParent(rule, this); }; Ruleset.prototype.find = function (selector, self, filter) { self = self || this; @@ -329,25 +402,10 @@ Ruleset.prototype.genCSS = function (context, output) { tabSetStr = context.compress ? '' : Array(context.tabLevel).join(" "), sep; - function isRulesetLikeNode(rule) { - // if it has nested rules, then it should be treated like a ruleset - // medias and comments do not have nested rules, but should be treated like rulesets anyway - // some directives and anonymous nodes are ruleset like, others are not - if (typeof rule.isRulesetLike === "boolean") { - return rule.isRulesetLike; - } else if (typeof rule.isRulesetLike === "function") { - return rule.isRulesetLike(); - } - - //anything else is assumed to be a rule - return false; - } - var charsetNodeIndex = 0; var importNodeIndex = 0; - for (i = 0; i < this.rules.length; i++) { - rule = this.rules[i]; - if (rule.type === "Comment") { + for (i = 0; (rule = this.rules[i]); i++) { + if (rule instanceof Comment) { if (importNodeIndex === i) { importNodeIndex++; } @@ -398,15 +456,14 @@ Ruleset.prototype.genCSS = function (context, output) { } // Compile rules and rulesets - for (i = 0; i < ruleNodes.length; i++) { - rule = ruleNodes[i]; + for (i = 0; (rule = ruleNodes[i]); i++) { if (i + 1 === ruleNodes.length) { context.lastRule = true; } var currentLastRule = context.lastRule; - if (isRulesetLikeNode(rule)) { + if (rule.isRulesetLike(rule)) { context.lastRule = false; } @@ -418,7 +475,7 @@ Ruleset.prototype.genCSS = function (context, output) { context.lastRule = currentLastRule; - if (!context.lastRule) { + if (!context.lastRule && rule.isVisible()) { output.add(context.compress ? '' : ('\n' + tabRuleStr)); } else { context.lastRule = false; @@ -448,9 +505,9 @@ Ruleset.prototype.joinSelector = function (paths, context, selector) { if (elementsToPak.length === 0) { replacementParen = new Paren(elementsToPak[0]); } else { - var insideParent = []; + var insideParent = new Array(elementsToPak.length); for (j = 0; j < elementsToPak.length; j++) { - insideParent.push(new Element(null, elementsToPak[j], originalElement.index, originalElement.currentFileInfo)); + insideParent[j] = new Element(null, elementsToPak[j], originalElement._index, originalElement._fileInfo); } replacementParen = new Paren(new Selector(insideParent)); } @@ -459,7 +516,7 @@ Ruleset.prototype.joinSelector = function (paths, context, selector) { function createSelector(containedElement, originalElement) { var element, selector; - element = new Element(null, containedElement, originalElement.index, originalElement.currentFileInfo); + element = new Element(null, containedElement, originalElement._index, originalElement._fileInfo); selector = new Selector([element]); return selector; } @@ -472,12 +529,12 @@ Ruleset.prototype.joinSelector = function (paths, context, selector) { // our new selector path newSelectorPath = []; - //construct the joined selector - if & is the first thing this will be empty, + // construct the joined selector - if & is the first thing this will be empty, // if not newJoinedSelector will be the last set of elements in the selector if (beginningPath.length > 0) { - newSelectorPath = beginningPath.slice(0); + newSelectorPath = utils.copyArray(beginningPath); lastSelector = newSelectorPath.pop(); - newJoinedSelector = originalSelector.createDerived(lastSelector.elements.slice(0)); + newJoinedSelector = originalSelector.createDerived(utils.copyArray(lastSelector.elements)); } else { newJoinedSelector = originalSelector.createDerived([]); @@ -493,7 +550,7 @@ Ruleset.prototype.joinSelector = function (paths, context, selector) { combinator = parentEl.combinator; } // join the elements so far with the first part of the parent - newJoinedSelector.elements.push(new Element(combinator, parentEl.value, replacedElement.index, replacedElement.currentFileInfo)); + newJoinedSelector.elements.push(new Element(combinator, parentEl.value, replacedElement._index, replacedElement._fileInfo)); newJoinedSelector.elements = newJoinedSelector.elements.concat(addPath[0].elements.slice(1)); } @@ -502,7 +559,7 @@ Ruleset.prototype.joinSelector = function (paths, context, selector) { newSelectorPath.push(newJoinedSelector); } - //put together the parent selectors after the join (e.g. the rest of the parent) + // put together the parent selectors after the join (e.g. the rest of the parent) if (addPath.length > 1) { var restOfPath = addPath.slice(1); restOfPath = restOfPath.map(function (selector) { @@ -536,9 +593,7 @@ Ruleset.prototype.joinSelector = function (paths, context, selector) { return; } - for (i = 0; i < selectors.length; i++) { - sel = selectors[i]; - + for (i = 0; (sel = selectors[i]); i++) { // if the previous thing in sel is a parent this needs to join on to it if (sel.length > 0) { sel[sel.length - 1] = sel[sel.length - 1].createDerived(sel[sel.length - 1].elements.concat(elements)); @@ -566,12 +621,12 @@ Ruleset.prototype.joinSelector = function (paths, context, selector) { var i, j, k, currentElements, newSelectors, selectorsMultiplied, sel, el, hadParentSelector = false, length, lastSelector; function findNestedSelector(element) { var maybeSelector; - if (element.value.type !== 'Paren') { + if (!(element.value instanceof Paren)) { return null; } maybeSelector = element.value.value; - if (maybeSelector.type !== 'Selector') { + if (!(maybeSelector instanceof Selector)) { return null; } @@ -587,8 +642,7 @@ Ruleset.prototype.joinSelector = function (paths, context, selector) { [] ]; - for (i = 0; i < inSelector.elements.length; i++) { - el = inSelector.elements[i]; + for (i = 0; (el = inSelector.elements[i]); i++) { // non parent reference elements just get added if (el.value !== "&") { var nestedSelector = findNestedSelector(el); @@ -600,7 +654,7 @@ Ruleset.prototype.joinSelector = function (paths, context, selector) { var nestedPaths = [], replaced, replacedNewSelectors = []; replaced = replaceParentSelector(nestedPaths, context, nestedSelector); hadParentSelector = hadParentSelector || replaced; - //the nestedPaths array should have only one member - replaceParentSelector does not multiply selectors + // the nestedPaths array should have only one member - replaceParentSelector does not multiply selectors for (k = 0; k < nestedPaths.length; k++) { var replacementSelector = createSelector(createParenthesis(nestedPaths[k], el), el); addAllReplacementsIntoPath(newSelectors, [replacementSelector], el, inSelector, replacedNewSelectors); @@ -630,7 +684,7 @@ Ruleset.prototype.joinSelector = function (paths, context, selector) { // the combinator used on el should now be applied to the next element instead so that // it is not lost if (sel.length > 0) { - sel[0].elements.push(new Element(el.combinator, '', el.index, el.currentFileInfo)); + sel[0].elements.push(new Element(el.combinator, '', el._index, el._fileInfo)); } selectorsMultiplied.push(sel); } @@ -662,7 +716,6 @@ Ruleset.prototype.joinSelector = function (paths, context, selector) { paths.push(newSelectors[i]); lastSelector = newSelectors[i][length - 1]; newSelectors[i][length - 1] = lastSelector.createDerived(lastSelector.elements, inSelector.extendList); - //newSelectors[i][length - 1].copyVisibilityInfo(inSelector.visibilityInfo()); } } @@ -685,12 +738,7 @@ Ruleset.prototype.joinSelector = function (paths, context, selector) { if (context.length > 0) { newPaths = []; for (i = 0; i < context.length; i++) { - //var concatenated = []; - //context[i].forEach(function(entry) { - // var newEntry = entry.createDerived(entry.elements, entry.extendList, entry.evaldCondition); - // newEntry.copyVisibilityInfo(selector.visibilityInfo()); - // concatenated.push(newEntry); - //}, this); + var concatenated = context[i].map(deriveSelector.bind(this, selector.visibilityInfo())); concatenated.push(selector); diff --git a/lib/less/tree/selector.js b/lib/less/tree/selector.js index cb5beee10..fb866a9b3 100644 --- a/lib/less/tree/selector.js +++ b/lib/less/tree/selector.js @@ -1,15 +1,17 @@ var Node = require("./node"), - Element = require("./element"); + Element = require("./element"), + LessError = require("../less-error"); var Selector = function (elements, extendList, condition, index, currentFileInfo, visibilityInfo) { - this.elements = elements; this.extendList = extendList; this.condition = condition; - this.currentFileInfo = currentFileInfo || {}; - if (!condition) { - this.evaldCondition = true; - } + this.evaldCondition = !condition; + this._index = index; + this._fileInfo = currentFileInfo; + this.elements = this.getElements(elements); + this.mixinElements_ = undefined; this.copyVisibilityInfo(visibilityInfo); + this.setParent(this.elements, this); }; Selector.prototype = new Node(); Selector.prototype.type = "Selector"; @@ -25,16 +27,35 @@ Selector.prototype.accept = function (visitor) { } }; Selector.prototype.createDerived = function(elements, extendList, evaldCondition) { - var info = this.visibilityInfo(); - evaldCondition = (evaldCondition != null) ? evaldCondition : this.evaldCondition; - var newSelector = new Selector(elements, extendList || this.extendList, null, this.index, this.currentFileInfo, info); - newSelector.evaldCondition = evaldCondition; + elements = this.getElements(elements); + var newSelector = new Selector(elements, extendList || this.extendList, + null, this.getIndex(), this.fileInfo(), this.visibilityInfo()); + newSelector.evaldCondition = (evaldCondition != null) ? evaldCondition : this.evaldCondition; newSelector.mediaEmpty = this.mediaEmpty; return newSelector; }; +Selector.prototype.getElements = function(els) { + if (typeof els === "string") { + this.parse.parseNode( + els, + ["selector"], + this._index, + this._fileInfo, + function(err, result) { + if (err) { + throw new LessError({ + index: err.index, + message: err.message + }, this.parse.imports, this._fileInfo.filename); + } + els = result[0].elements; + }); + } + return els; +}; Selector.prototype.createEmptySelectors = function() { - var el = new Element('', '&', this.index, this.currentFileInfo), - sels = [new Selector([el], null, null, this.index, this.currentFileInfo)]; + var el = new Element('', '&', this._index, this._fileInfo), + sels = [new Selector([el], null, null, this._index, this._fileInfo)]; sels[0].mediaEmpty = true; return sels; }; @@ -43,14 +64,13 @@ Selector.prototype.match = function (other) { len = elements.length, olen, i; - other.CacheElements(); - - olen = other._elements.length; + other = other.mixinElements(); + olen = other.length; if (olen === 0 || len < olen) { return 0; } else { for (i = 0; i < olen; i++) { - if (elements[i].value !== other._elements[i]) { + if (elements[i].value !== other[i]) { return 0; } } @@ -58,9 +78,9 @@ Selector.prototype.match = function (other) { return olen; // return number of matched elements }; -Selector.prototype.CacheElements = function() { - if (this._elements) { - return; +Selector.prototype.mixinElements = function() { + if (this.mixinElements_) { + return this.mixinElements_; } var elements = this.elements.map( function(v) { @@ -75,7 +95,7 @@ Selector.prototype.CacheElements = function() { elements = []; } - this._elements = elements; + return (this.mixinElements_ = elements); }; Selector.prototype.isJustParentSelector = function() { return !this.mediaEmpty && @@ -95,14 +115,11 @@ Selector.prototype.eval = function (context) { Selector.prototype.genCSS = function (context, output) { var i, element; if ((!context || !context.firstSelector) && this.elements[0].combinator.value === "") { - output.add(' ', this.currentFileInfo, this.index); + output.add(' ', this.fileInfo(), this.getIndex()); } - if (!this._css) { - //TODO caching? speed comparison? - for (i = 0; i < this.elements.length; i++) { - element = this.elements[i]; - element.genCSS(context, output); - } + for (i = 0; i < this.elements.length; i++) { + element = this.elements[i]; + element.genCSS(context, output); } }; Selector.prototype.getIsOutput = function() { diff --git a/lib/less/tree/unit.js b/lib/less/tree/unit.js index aa53124d0..0e27daaad 100644 --- a/lib/less/tree/unit.js +++ b/lib/less/tree/unit.js @@ -1,9 +1,10 @@ var Node = require("./node"), - unitConversions = require("../data/unit-conversions"); + unitConversions = require("../data/unit-conversions"), + utils = require("../utils"); var Unit = function (numerator, denominator, backupUnit) { - this.numerator = numerator ? numerator.slice(0).sort() : []; - this.denominator = denominator ? denominator.slice(0).sort() : []; + this.numerator = numerator ? utils.copyArray(numerator).sort() : []; + this.denominator = denominator ? utils.copyArray(denominator).sort() : []; if (backupUnit) { this.backupUnit = backupUnit; } else if (numerator && numerator.length) { @@ -14,7 +15,7 @@ var Unit = function (numerator, denominator, backupUnit) { Unit.prototype = new Node(); Unit.prototype.type = "Unit"; Unit.prototype.clone = function () { - return new Unit(this.numerator.slice(0), this.denominator.slice(0), this.backupUnit); + return new Unit(utils.copyArray(this.numerator), utils.copyArray(this.denominator), this.backupUnit); }; Unit.prototype.genCSS = function (context, output) { // Dimension checks the unit is singular and throws an error if in strict math mode. @@ -64,7 +65,7 @@ Unit.prototype.usedUnits = function() { var group, result = {}, mapUnit, groupName; mapUnit = function (atomicUnit) { - /*jshint loopfunc:true */ + /* jshint loopfunc:true */ if (group.hasOwnProperty(atomicUnit) && !result[groupName]) { result[groupName] = atomicUnit; } diff --git a/lib/less/tree/url.js b/lib/less/tree/url.js index 65347af43..fa0d4c871 100644 --- a/lib/less/tree/url.js +++ b/lib/less/tree/url.js @@ -2,8 +2,8 @@ var Node = require("./node"); var URL = function (val, index, currentFileInfo, isEvald) { this.value = val; - this.currentFileInfo = currentFileInfo; - this.index = index; + this._index = index; + this._fileInfo = currentFileInfo; this.isEvald = isEvald; }; URL.prototype = new Node(); @@ -22,7 +22,7 @@ URL.prototype.eval = function (context) { if (!this.isEvald) { // Add the base path if the URL is relative - rootpath = this.currentFileInfo && this.currentFileInfo.rootpath; + rootpath = this.fileInfo() && this.fileInfo().rootpath; if (rootpath && typeof val.value === "string" && context.isPathRelative(val.value)) { @@ -49,6 +49,6 @@ URL.prototype.eval = function (context) { } } - return new URL(val, this.index, this.currentFileInfo, true); + return new URL(val, this.getIndex(), this.fileInfo(), true); }; module.exports = URL; diff --git a/lib/less/tree/value.js b/lib/less/tree/value.js index 1a03886c3..1e2d9b0ba 100644 --- a/lib/less/tree/value.js +++ b/lib/less/tree/value.js @@ -1,10 +1,15 @@ var Node = require("./node"); var Value = function (value) { - this.value = value; if (!value) { throw new Error("Value requires an array argument"); } + if (!Array.isArray(value)) { + this.value = [ value ]; + } + else { + this.value = value; + } }; Value.prototype = new Node(); Value.prototype.type = "Value"; diff --git a/lib/less/tree/ruleset-call.js b/lib/less/tree/variable-call.js similarity index 54% rename from lib/less/tree/ruleset-call.js rename to lib/less/tree/variable-call.js index d271c8ddd..b24fd7d53 100644 --- a/lib/less/tree/ruleset-call.js +++ b/lib/less/tree/variable-call.js @@ -1,14 +1,14 @@ var Node = require("./node"), Variable = require("./variable"); -var RulesetCall = function (variable) { +var VariableCall = function (variable) { this.variable = variable; this.allowRoot = true; }; -RulesetCall.prototype = new Node(); -RulesetCall.prototype.type = "RulesetCall"; -RulesetCall.prototype.eval = function (context) { +VariableCall.prototype = new Node(); +VariableCall.prototype.type = "VariableCall"; +VariableCall.prototype.eval = function (context) { var detachedRuleset = new Variable(this.variable).eval(context); return detachedRuleset.callEval(context); }; -module.exports = RulesetCall; +module.exports = VariableCall; diff --git a/lib/less/tree/variable.js b/lib/less/tree/variable.js index 9d1091920..f590711f2 100644 --- a/lib/less/tree/variable.js +++ b/lib/less/tree/variable.js @@ -2,8 +2,8 @@ var Node = require("./node"); var Variable = function (name, index, currentFileInfo) { this.name = name; - this.index = index; - this.currentFileInfo = currentFileInfo || {}; + this._index = index; + this._fileInfo = currentFileInfo; }; Variable.prototype = new Node(); Variable.prototype.type = "Variable"; @@ -11,14 +11,14 @@ Variable.prototype.eval = function (context) { var variable, name = this.name; if (name.indexOf('@@') === 0) { - name = '@' + new Variable(name.slice(1), this.index, this.currentFileInfo).eval(context).value; + name = '@' + new Variable(name.slice(1), this.getIndex(), this.fileInfo()).eval(context).value; } if (this.evaluating) { throw { type: 'Name', - message: "Recursive variable definition for " + name, - filename: this.currentFileInfo.filename, - index: this.index }; + message: "Recursive variable definition for " + name, + filename: this.fileInfo().filename, + index: this.getIndex() }; } this.evaluating = true; @@ -38,9 +38,9 @@ Variable.prototype.eval = function (context) { return variable; } else { throw { type: 'Name', - message: "variable " + name + " is undefined", - filename: this.currentFileInfo.filename, - index: this.index }; + message: "variable " + name + " is undefined", + filename: this.fileInfo().filename, + index: this.getIndex() }; } }; Variable.prototype.find = function (obj, fun) { diff --git a/lib/less/utils.js b/lib/less/utils.js index 6efdb21bb..c90d6e69f 100644 --- a/lib/less/utils.js +++ b/lib/less/utils.js @@ -1,3 +1,4 @@ +/* jshint proto: true */ module.exports = { getLocation: function(index, inputStream) { var n = index + 1, @@ -16,5 +17,53 @@ module.exports = { line: line, column: column }; + }, + copyArray: function(arr) { + var i, length = arr.length, + copy = new Array(length); + + for (i = 0; i < length; i++) { + copy[i] = arr[i]; + } + return copy; + }, + clone: function (obj) { + var cloned = {}; + for (var prop in obj) { + if (obj.hasOwnProperty(prop)) { + cloned[prop] = obj[prop]; + } + } + return cloned; + }, + defaults: function(obj1, obj2) { + if (!obj2._defaults || obj2._defaults !== obj1) { + for (var prop in obj1) { + if (obj1.hasOwnProperty(prop)) { + if (!obj2.hasOwnProperty(prop)) { + obj2[prop] = obj1[prop]; + } + else if (Array.isArray(obj1[prop]) + && Array.isArray(obj2[prop])) { + + obj1[prop].forEach(function(p) { + if (obj2[prop].indexOf(p) === -1) { + obj2[prop].push(p); + } + }); + } + } + } + } + obj2._defaults = obj1; + return obj2; + }, + merge: function(obj1, obj2) { + for (var prop in obj2) { + if (obj2.hasOwnProperty(prop)) { + obj1[prop] = obj2[prop]; + } + } + return obj1; } }; diff --git a/lib/less/visitors/extend-visitor.js b/lib/less/visitors/extend-visitor.js index ff2b3c86e..5c4128823 100644 --- a/lib/less/visitors/extend-visitor.js +++ b/lib/less/visitors/extend-visitor.js @@ -1,8 +1,9 @@ var tree = require("../tree"), Visitor = require("./visitor"), - logger = require("../logger"); + logger = require("../logger"), + utils = require("../utils"); -/*jshint loopfunc:true */ +/* jshint loopfunc:true */ var ExtendFinderVisitor = function() { this._visitor = new Visitor(this); @@ -16,7 +17,7 @@ ExtendFinderVisitor.prototype = { root.allExtends = this.allExtendsStack[0]; return root; }, - visitRule: function (ruleNode, visitArgs) { + visitDeclaration: function (declNode, visitArgs) { visitArgs.visitDeeper = false; }, visitMixinDefinition: function (mixinDefinitionNode, visitArgs) { @@ -46,7 +47,7 @@ ExtendFinderVisitor.prototype = { selector = selectorPath[selectorPath.length - 1], selExtendList = selector.extendList; - extendList = selExtendList ? selExtendList.slice(0).concat(allSelectorsExtendList) + extendList = selExtendList ? utils.copyArray(selExtendList).concat(allSelectorsExtendList) : allSelectorsExtendList; if (extendList) { @@ -79,11 +80,11 @@ ExtendFinderVisitor.prototype = { visitMediaOut: function (mediaNode) { this.allExtendsStack.length = this.allExtendsStack.length - 1; }, - visitDirective: function (directiveNode, visitArgs) { - directiveNode.allExtends = []; - this.allExtendsStack.push(directiveNode.allExtends); + visitAtRule: function (atRuleNode, visitArgs) { + atRuleNode.allExtends = []; + this.allExtendsStack.push(atRuleNode.allExtends); }, - visitDirectiveOut: function (directiveNode) { + visitAtRuleOut: function (atRuleNode) { this.allExtendsStack.length = this.allExtendsStack.length - 1; } }; @@ -109,17 +110,17 @@ ProcessExtendsVisitor.prototype = { extendList.filter(function(extend) { return !extend.hasFoundMatches && extend.parent_ids.length == 1; }).forEach(function(extend) { - var selector = "_unknown_"; - try { - selector = extend.selector.toCSS({}); - } - catch(_) {} + var selector = "_unknown_"; + try { + selector = extend.selector.toCSS({}); + } + catch (_) {} - if (!indices[extend.index + ' ' + selector]) { - indices[extend.index + ' ' + selector] = true; - logger.warn("extend '" + selector + "' has no matches"); - } - }); + if (!indices[extend.index + ' ' + selector]) { + indices[extend.index + ' ' + selector] = true; + logger.warn("extend '" + selector + "' has no matches"); + } + }); }, doExtendChaining: function (extendsList, extendsListTarget, iterationCount) { // @@ -136,7 +137,7 @@ ProcessExtendsVisitor.prototype = { iterationCount = iterationCount || 0; - //loop through comparing every extend with every target extend. + // loop through comparing every extend with every target extend. // a target extend is the one on the ruleset we are looking at copy/edit/pasting in place // e.g. .a:extend(.b) {} and .b:extend(.c) {} then the first extend extends the second one // and the second is the target. @@ -166,7 +167,7 @@ ProcessExtendsVisitor.prototype = { newSelector = extendVisitor.extendSelector(matches, selectorPath, selfSelector, extend.isVisible()); // but now we create a new extend from it - newExtend = new(tree.Extend)(targetExtend.selector, targetExtend.option, 0, targetExtend.currentFileInfo, info); + newExtend = new(tree.Extend)(targetExtend.selector, targetExtend.option, 0, targetExtend.fileInfo(), info); newExtend.selfSelectors = newSelector; // add the extend onto the list of extends for that selector @@ -202,7 +203,7 @@ ProcessExtendsVisitor.prototype = { selectorOne = extendsToAdd[0].selfSelectors[0].toCSS(); selectorTwo = extendsToAdd[0].selector.toCSS(); } - catch(e) {} + catch (e) {} throw { message: "extend circular reference detected. One of the circular extends is currently:" + selectorOne + ":extend(" + selectorTwo + ")"}; } @@ -214,7 +215,7 @@ ProcessExtendsVisitor.prototype = { return extendsToAdd; } }, - visitRule: function (ruleNode, visitArgs) { + visitDeclaration: function (ruleNode, visitArgs) { visitArgs.visitDeeper = false; }, visitMixinDefinition: function (mixinDefinitionNode, visitArgs) { @@ -367,7 +368,7 @@ ProcessExtendsVisitor.prototype = { }, extendSelector:function (matches, selectorPath, replacementSelector, isVisible) { - //for a set of matches, replace each match with the replacement selector + // for a set of matches, replace each match with the replacement selector var currentSelectorPathIndex = 0, currentSelectorPathElementIndex = 0, @@ -384,8 +385,8 @@ ProcessExtendsVisitor.prototype = { firstElement = new tree.Element( match.initialCombinator, replacementSelector.elements[0].value, - replacementSelector.elements[0].index, - replacementSelector.elements[0].currentFileInfo + replacementSelector.elements[0].getIndex(), + replacementSelector.elements[0].fileInfo() ); if (match.pathIndex > currentSelectorPathIndex && currentSelectorPathElementIndex > 0) { @@ -446,12 +447,12 @@ ProcessExtendsVisitor.prototype = { var lastIndex = this.allExtendsStack.length - 1; this.allExtendsStack.length = lastIndex; }, - visitDirective: function (directiveNode, visitArgs) { - var newAllExtends = directiveNode.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length - 1]); - newAllExtends = newAllExtends.concat(this.doExtendChaining(newAllExtends, directiveNode.allExtends)); + visitAtRule: function (atRuleNode, visitArgs) { + var newAllExtends = atRuleNode.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length - 1]); + newAllExtends = newAllExtends.concat(this.doExtendChaining(newAllExtends, atRuleNode.allExtends)); this.allExtendsStack.push(newAllExtends); }, - visitDirectiveOut: function (directiveNode) { + visitAtRuleOut: function (atRuleNode) { var lastIndex = this.allExtendsStack.length - 1; this.allExtendsStack.length = lastIndex; } diff --git a/lib/less/visitors/import-visitor.js b/lib/less/visitors/import-visitor.js index 8af0b8928..9fe266b03 100644 --- a/lib/less/visitors/import-visitor.js +++ b/lib/less/visitors/import-visitor.js @@ -1,6 +1,7 @@ var contexts = require("../contexts"), Visitor = require("./visitor"), - ImportSequencer = require("./import-sequencer"); + ImportSequencer = require("./import-sequencer"), + utils = require("../utils"); var ImportVisitor = function(importer, finish) { @@ -21,7 +22,7 @@ ImportVisitor.prototype = { // process the contents this._visitor.visit(root); } - catch(e) { + catch (e) { this.error = e; } @@ -39,7 +40,7 @@ ImportVisitor.prototype = { if (!importNode.css || inlineCSS) { - var context = new contexts.Eval(this.context, this.context.frames.slice(0)); + var context = new contexts.Eval(this.context, utils.copyArray(this.context.frames)); var importParent = context.frames[0]; this.importCount++; @@ -57,8 +58,8 @@ ImportVisitor.prototype = { try { evaldImportNode = importNode.evalForImport(context); - } catch(e) { - if (!e.filename) { e.index = importNode.index; e.filename = importNode.currentFileInfo.filename; } + } catch (e) { + if (!e.filename) { e.index = importNode.getIndex(); e.filename = importNode.fileInfo().filename; } // attempt to eval properly and treat as css importNode.css = true; // if that fails, this error will be thrown @@ -84,7 +85,7 @@ ImportVisitor.prototype = { var onImported = this.onImported.bind(this, evaldImportNode, context), sequencedOnImported = this._sequencer.addImport(onImported); - this._importer.push(evaldImportNode.getPath(), tryAppendLessExtension, evaldImportNode.currentFileInfo, + this._importer.push(evaldImportNode.getPath(), tryAppendLessExtension, evaldImportNode.fileInfo(), evaldImportNode.options, sequencedOnImported); } else { this.importCount--; @@ -96,14 +97,14 @@ ImportVisitor.prototype = { onImported: function (importNode, context, e, root, importedAtRoot, fullPath) { if (e) { if (!e.filename) { - e.index = importNode.index; e.filename = importNode.currentFileInfo.filename; + e.index = importNode.getIndex(); e.filename = importNode.fileInfo().filename; } this.error = e; } var importVisitor = this, inlineCSS = importNode.options.inline, - isPlugin = importNode.options.plugin, + isPlugin = importNode.options.isPlugin, isOptional = importNode.options.optional, duplicateImport = importedAtRoot || fullPath in importVisitor.recursionDetector; @@ -149,22 +150,22 @@ ImportVisitor.prototype = { importVisitor._sequencer.tryRun(); } }, - visitRule: function (ruleNode, visitArgs) { - if (ruleNode.value.type === "DetachedRuleset") { - this.context.frames.unshift(ruleNode); + visitDeclaration: function (declNode, visitArgs) { + if (declNode.value.type === "DetachedRuleset") { + this.context.frames.unshift(declNode); } else { visitArgs.visitDeeper = false; } }, - visitRuleOut : function(ruleNode) { - if (ruleNode.value.type === "DetachedRuleset") { + visitDeclarationOut: function(declNode) { + if (declNode.value.type === "DetachedRuleset") { this.context.frames.shift(); } }, - visitDirective: function (directiveNode, visitArgs) { - this.context.frames.unshift(directiveNode); + visitAtRule: function (atRuleNode, visitArgs) { + this.context.frames.unshift(atRuleNode); }, - visitDirectiveOut: function (directiveNode) { + visitAtRuleOut: function (atRuleNode) { this.context.frames.shift(); }, visitMixinDefinition: function (mixinDefinitionNode, visitArgs) { diff --git a/lib/less/visitors/join-selector-visitor.js b/lib/less/visitors/join-selector-visitor.js index c75973c44..c1fcd0cfa 100644 --- a/lib/less/visitors/join-selector-visitor.js +++ b/lib/less/visitors/join-selector-visitor.js @@ -9,7 +9,7 @@ JoinSelectorVisitor.prototype = { run: function (root) { return this._visitor.visit(root); }, - visitRule: function (ruleNode, visitArgs) { + visitDeclaration: function (declNode, visitArgs) { visitArgs.visitDeeper = false; }, visitMixinDefinition: function (mixinDefinitionNode, visitArgs) { @@ -22,7 +22,7 @@ JoinSelectorVisitor.prototype = { this.contexts.push(paths); - if (! rulesetNode.root) { + if (!rulesetNode.root) { selectors = rulesetNode.selectors; if (selectors) { selectors = selectors.filter(function(selector) { return selector.getIsOutput(); }); @@ -40,10 +40,10 @@ JoinSelectorVisitor.prototype = { var context = this.contexts[this.contexts.length - 1]; mediaNode.rules[0].root = (context.length === 0 || context[0].multiMedia); }, - visitDirective: function (directiveNode, visitArgs) { + visitAtRule: function (atRuleNode, visitArgs) { var context = this.contexts[this.contexts.length - 1]; - if (directiveNode.rules && directiveNode.rules.length) { - directiveNode.rules[0].root = (directiveNode.isRooted || context.length === 0 || null); + if (atRuleNode.rules && atRuleNode.rules.length) { + atRuleNode.rules[0].root = (atRuleNode.isRooted || context.length === 0 || null); } } }; diff --git a/lib/less/visitors/to-css-visitor.js b/lib/less/visitors/to-css-visitor.js index ed6ed44d9..861242b1a 100644 --- a/lib/less/visitors/to-css-visitor.js +++ b/lib/less/visitors/to-css-visitor.js @@ -9,14 +9,14 @@ var CSSVisitorUtils = function(context) { CSSVisitorUtils.prototype = { containsSilentNonBlockedChild: function(bodyRules) { var rule; - if (bodyRules == null) { + if (!bodyRules) { return false; } for (var r = 0; r < bodyRules.length; r++) { rule = bodyRules[r]; if (rule.isSilent && rule.isSilent(this._context) && !rule.blocksVisibility()) { - //the directive contains something that was referenced (likely by extend) - //therefore it needs to be shown in output too + // the atrule contains something that was referenced (likely by extend) + // therefore it needs to be shown in output too return true; } } @@ -24,28 +24,21 @@ CSSVisitorUtils.prototype = { }, keepOnlyVisibleChilds: function(owner) { - if (owner == null || owner.rules == null) { - return ; - } - - owner.rules = owner.rules.filter(function(thing) { + if (owner && owner.rules) { + owner.rules = owner.rules.filter(function(thing) { return thing.isVisible(); - } - ); + }); + } }, isEmpty: function(owner) { - if (owner == null || owner.rules == null) { - return true; - } - return owner.rules.length === 0; + return (owner && owner.rules) + ? (owner.rules.length === 0) : true; }, hasVisibleSelector: function(rulesetNode) { - if (rulesetNode == null || rulesetNode.paths == null) { - return false; - } - return rulesetNode.paths.length > 0; + return (rulesetNode && rulesetNode.paths) + ? (rulesetNode.paths.length > 0) : false; }, resolveVisibility: function (node, originalRules) { @@ -100,11 +93,11 @@ ToCSSVisitor.prototype = { return this._visitor.visit(root); }, - visitRule: function (ruleNode, visitArgs) { - if (ruleNode.blocksVisibility() || ruleNode.variable) { + visitDeclaration: function (declNode, visitArgs) { + if (declNode.blocksVisibility() || declNode.variable) { return; } - return ruleNode; + return declNode; }, visitMixinDefinition: function (mixinNode, visitArgs) { @@ -138,56 +131,63 @@ ToCSSVisitor.prototype = { return importNode; }, - visitDirective: function(directiveNode, visitArgs) { - if (directiveNode.rules && directiveNode.rules.length) { - return this.visitDirectiveWithBody(directiveNode, visitArgs); + visitAtRule: function(atRuleNode, visitArgs) { + if (atRuleNode.rules && atRuleNode.rules.length) { + return this.visitAtRuleWithBody(atRuleNode, visitArgs); } else { - return this.visitDirectiveWithoutBody(directiveNode, visitArgs); + return this.visitAtRuleWithoutBody(atRuleNode, visitArgs); } }, - visitDirectiveWithBody: function(directiveNode, visitArgs) { - //if there is only one nested ruleset and that one has no path, then it is - //just fake ruleset - function hasFakeRuleset(directiveNode) { - var bodyRules = directiveNode.rules; + visitAnonymous: function(anonymousNode, visitArgs) { + if (!anonymousNode.blocksVisibility()) { + anonymousNode.accept(this._visitor); + return anonymousNode; + } + }, + + visitAtRuleWithBody: function(atRuleNode, visitArgs) { + // if there is only one nested ruleset and that one has no path, then it is + // just fake ruleset + function hasFakeRuleset(atRuleNode) { + var bodyRules = atRuleNode.rules; return bodyRules.length === 1 && (!bodyRules[0].paths || bodyRules[0].paths.length === 0); } - function getBodyRules(directiveNode) { - var nodeRules = directiveNode.rules; - if (hasFakeRuleset(directiveNode)) { + function getBodyRules(atRuleNode) { + var nodeRules = atRuleNode.rules; + if (hasFakeRuleset(atRuleNode)) { return nodeRules[0].rules; } return nodeRules; } - //it is still true that it is only one ruleset in array - //this is last such moment - //process childs - var originalRules = getBodyRules(directiveNode); - directiveNode.accept(this._visitor); + // it is still true that it is only one ruleset in array + // this is last such moment + // process childs + var originalRules = getBodyRules(atRuleNode); + atRuleNode.accept(this._visitor); visitArgs.visitDeeper = false; - if (!this.utils.isEmpty(directiveNode)) { - this._mergeRules(directiveNode.rules[0].rules); + if (!this.utils.isEmpty(atRuleNode)) { + this._mergeRules(atRuleNode.rules[0].rules); } - return this.utils.resolveVisibility(directiveNode, originalRules); + return this.utils.resolveVisibility(atRuleNode, originalRules); }, - visitDirectiveWithoutBody: function(directiveNode, visitArgs) { - if (directiveNode.blocksVisibility()) { + visitAtRuleWithoutBody: function(atRuleNode, visitArgs) { + if (atRuleNode.blocksVisibility()) { return; } - if (directiveNode.name === "@charset") { + if (atRuleNode.name === "@charset") { // Only output the debug info together with subsequent @charset definitions - // a comment (or @media statement) before the actual @charset directive would + // a comment (or @media statement) before the actual @charset atrule would // be considered illegal css as it has to be on the first line if (this.charset) { - if (directiveNode.debugInfo) { - var comment = new tree.Comment("/* " + directiveNode.toCSS(this._context).replace(/\n/g, "") + " */\n"); - comment.debugInfo = directiveNode.debugInfo; + if (atRuleNode.debugInfo) { + var comment = new tree.Comment("/* " + atRuleNode.toCSS(this._context).replace(/\n/g, "") + " */\n"); + comment.debugInfo = atRuleNode.debugInfo; return this._visitor.visit(comment); } return; @@ -195,7 +195,7 @@ ToCSSVisitor.prototype = { this.charset = true; } - return directiveNode; + return atRuleNode; }, checkValidNodes: function(rules, isRoot) { @@ -205,29 +205,29 @@ ToCSSVisitor.prototype = { for (var i = 0; i < rules.length; i++) { var ruleNode = rules[i]; - if (isRoot && ruleNode instanceof tree.Rule && !ruleNode.variable) { + if (isRoot && ruleNode instanceof tree.Declaration && !ruleNode.variable) { throw { message: "Properties must be inside selector blocks. They cannot be in the root", - index: ruleNode.index, filename: ruleNode.currentFileInfo && ruleNode.currentFileInfo.filename}; + index: ruleNode.getIndex(), filename: ruleNode.fileInfo() && ruleNode.fileInfo().filename}; } if (ruleNode instanceof tree.Call) { throw { message: "Function '" + ruleNode.name + "' is undefined", - index: ruleNode.index, filename: ruleNode.currentFileInfo && ruleNode.currentFileInfo.filename}; + index: ruleNode.getIndex(), filename: ruleNode.fileInfo() && ruleNode.fileInfo().filename}; } if (ruleNode.type && !ruleNode.allowRoot) { throw { message: ruleNode.type + " node returned by a function is not valid here", - index: ruleNode.index, filename: ruleNode.currentFileInfo && ruleNode.currentFileInfo.filename}; + index: ruleNode.getIndex(), filename: ruleNode.fileInfo() && ruleNode.fileInfo().filename}; } } }, visitRuleset: function (rulesetNode, visitArgs) { - //at this point rulesets are nested into each other + // at this point rulesets are nested into each other var rule, rulesets = []; this.checkValidNodes(rulesetNode.rules, rulesetNode.firstRoot); - if (! rulesetNode.root) { - //remove invisible paths + if (!rulesetNode.root) { + // remove invisible paths this._compileRulesetPaths(rulesetNode); // remove rulesets from this ruleset body and compile them separately @@ -253,7 +253,7 @@ ToCSSVisitor.prototype = { } visitArgs.visitDeeper = false; - } else { //if (! rulesetNode.root) { + } else { // if (! rulesetNode.root) { rulesetNode.accept(this._visitor); visitArgs.visitDeeper = false; } @@ -263,7 +263,7 @@ ToCSSVisitor.prototype = { this._removeDuplicateRules(rulesetNode.rules); } - //now decide whether we keep the ruleset + // now decide whether we keep the ruleset if (this.utils.isVisibleRuleset(rulesetNode)) { rulesetNode.ensureVisibility(); rulesets.splice(0, 0, rulesetNode); @@ -302,12 +302,12 @@ ToCSSVisitor.prototype = { for (i = rules.length - 1; i >= 0 ; i--) { rule = rules[i]; - if (rule instanceof tree.Rule) { + if (rule instanceof tree.Declaration) { if (!ruleCache[rule.name]) { ruleCache[rule.name] = rule; } else { ruleList = ruleCache[rule.name]; - if (ruleList instanceof tree.Rule) { + if (ruleList instanceof tree.Declaration) { ruleList = ruleCache[rule.name] = [ruleCache[rule.name].toCSS(this._context)]; } var ruleCSS = rule.toCSS(this._context); @@ -321,72 +321,39 @@ ToCSSVisitor.prototype = { } }, - _mergeRules: function (rules) { - if (!rules) { return; } - - var groups = {}, - parts, - rule, - key; + _mergeRules: function(rules) { + if (!rules) { + return; + } + var groups = {}, + groupsArr = []; + for (var i = 0; i < rules.length; i++) { - rule = rules[i]; - - if ((rule instanceof tree.Rule) && rule.merge) { - key = [rule.name, - rule.important ? "!" : ""].join(","); - - if (!groups[key]) { - groups[key] = []; - } else { - rules.splice(i--, 1); - } - + var rule = rules[i]; + if (rule.merge) { + var key = rule.name; + groups[key] ? rules.splice(i--, 1) : + groupsArr.push(groups[key] = []); groups[key].push(rule); } } - Object.keys(groups).map(function (k) { - - function toExpression(values) { - return new (tree.Expression)(values.map(function (p) { - return p.value; - })); - } - - function toValue(values) { - return new (tree.Value)(values.map(function (p) { - return p; - })); - } - - parts = groups[k]; - - if (parts.length > 1) { - rule = parts[0]; - var spacedGroups = []; - var lastSpacedGroup = []; - parts.map(function (p) { - if (p.merge === "+") { - if (lastSpacedGroup.length > 0) { - spacedGroups.push(toExpression(lastSpacedGroup)); - } - lastSpacedGroup = []; + groupsArr.forEach(function(group) { + if (group.length > 0) { + var result = group[0], + space = [], + comma = [new tree.Expression(space)]; + group.forEach(function(rule) { + if ((rule.merge === '+') && (space.length > 0)) { + comma.push(new tree.Expression(space = [])); } - lastSpacedGroup.push(p); + space.push(rule.value); + result.important = result.important || rule.important; }); - spacedGroups.push(toExpression(lastSpacedGroup)); - rule.value = toValue(spacedGroups); + result.value = new tree.Value(comma); } }); - }, - - visitAnonymous: function(anonymousNode, visitArgs) { - if (anonymousNode.blocksVisibility()) { - return ; - } - anonymousNode.accept(this._visitor); - return anonymousNode; } }; diff --git a/lib/less/visitors/visitor.js b/lib/less/visitors/visitor.js index afa05d704..cf67040c0 100644 --- a/lib/less/visitors/visitor.js +++ b/lib/less/visitors/visitor.js @@ -10,21 +10,21 @@ function _noop(node) { function indexNodeTypes(parent, ticker) { // add .typeIndex to tree node types for lookup table var key, child; - for (key in parent) { - if (parent.hasOwnProperty(key)) { - child = parent[key]; - switch (typeof child) { - case "function": - // ignore bound functions directly on tree which do not have a prototype - // or aren't nodes - if (child.prototype && child.prototype.type) { - child.prototype.typeIndex = ticker++; - } - break; - case "object": - ticker = indexNodeTypes(child, ticker); - break; - } + for (key in parent) { + /* eslint guard-for-in: 0 */ + child = parent[key]; + switch (typeof child) { + case "function": + // ignore bound functions directly on tree which do not have a prototype + // or aren't nodes + if (child.prototype && child.prototype.type) { + child.prototype.typeIndex = ticker++; + } + break; + case "object": + ticker = indexNodeTypes(child, ticker); + break; + } } return ticker; diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 000000000..e521eccbe --- /dev/null +++ b/package-lock.json @@ -0,0 +1,5865 @@ +{ + "name": "less", + "version": "3.0.0-alpha.3", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "accepts": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.4.tgz", + "integrity": "sha1-hiRnWMfdbSGmR0/whKR0DsBesh8=", + "dev": true, + "requires": { + "mime-types": "2.1.17", + "negotiator": "0.6.1" + } + }, + "acorn": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", + "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=", + "dev": true + }, + "acorn-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", + "dev": true, + "requires": { + "acorn": "3.3.0" + }, + "dependencies": { + "acorn": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", + "dev": true + } + } + }, + "agent-base": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-2.1.1.tgz", + "integrity": "sha1-1t4Q1a9hMtW9aSQn1G/FOFOQlMc=", + "dev": true, + "requires": { + "extend": "3.0.1", + "semver": "5.0.3" + }, + "dependencies": { + "semver": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.0.3.tgz", + "integrity": "sha1-d0Zt5YnNXTyV8TiqeLxWmjy10no=", + "dev": true + } + } + }, + "ajv": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "dev": true, + "requires": { + "co": "4.6.0", + "json-stable-stringify": "1.0.1" + }, + "dependencies": { + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "dev": true, + "requires": { + "jsonify": "0.0.0" + } + } + } + }, + "ajv-keywords": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz", + "integrity": "sha1-MU3QpLM2j609/NxU7eYXG4htrzw=", + "dev": true + }, + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "dev": true, + "requires": { + "kind-of": "3.2.2", + "longest": "1.0.1", + "repeat-string": "1.6.1" + } + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "dev": true + }, + "ansi-escapes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", + "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "anymatch": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", + "dev": true, + "requires": { + "micromatch": "2.3.11", + "normalize-path": "2.1.1" + } + }, + "argparse": { + "version": "0.1.16", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-0.1.16.tgz", + "integrity": "sha1-z9AeD7uj1srtBJ+9dY1A9lGW9Xw=", + "dev": true, + "requires": { + "underscore": "1.7.0", + "underscore.string": "2.4.0" + }, + "dependencies": { + "underscore.string": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.4.0.tgz", + "integrity": "sha1-jN2PusTi0uoefi6Al8QvRCKA+Fs=", + "dev": true + } + } + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "requires": { + "arr-flatten": "1.1.0" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "array-filter": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-0.0.1.tgz", + "integrity": "sha1-fajPLiZijtcygDWB/SH2fKzS7uw=", + "dev": true + }, + "array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", + "dev": true + }, + "array-map": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/array-map/-/array-map-0.0.0.tgz", + "integrity": "sha1-iKK6tz0c97zVwbEYoAP2b2ZfpmI=", + "dev": true + }, + "array-reduce": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/array-reduce/-/array-reduce-0.0.0.tgz", + "integrity": "sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys=", + "dev": true + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "1.0.3" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=", + "dev": true, + "optional": true + }, + "asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", + "dev": true + }, + "asn1.js": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.9.1.tgz", + "integrity": "sha1-SLokC0WpKA6UdImQull9IWYX/UA=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0" + } + }, + "assert": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", + "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", + "dev": true, + "requires": { + "util": "0.10.3" + } + }, + "assert-plus": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", + "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", + "dev": true + }, + "astw": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/astw/-/astw-2.2.0.tgz", + "integrity": "sha1-e9QXhNMkk5h66yOba04cV6hzuRc=", + "dev": true, + "requires": { + "acorn": "4.0.13" + } + }, + "async": { + "version": "0.1.22", + "resolved": "https://registry.npmjs.org/async/-/async-0.1.22.tgz", + "integrity": "sha1-D8GqoIig4+8Ovi2IMbqw3PiEUGE=", + "dev": true + }, + "async-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", + "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "aws-sign2": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", + "dev": true + }, + "aws4": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", + "dev": true + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "esutils": "2.0.2", + "js-tokens": "3.0.2" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base64-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.1.tgz", + "integrity": "sha512-dwVUVIXsBZXwTuwnXI9RK8sBmgq09NDHzyR9SAph9eqk76gKK2JSQmZARC2zRC81JC2QTtxD0ARU5qTS25gIGw==", + "dev": true + }, + "basic-auth": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.0.tgz", + "integrity": "sha1-AV2z81PgLlY3d1X5YnQuiYHnu7o=", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=", + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "dev": true, + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "binary-extensions": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.10.0.tgz", + "integrity": "sha1-muuabF6IY4qtFx4Wf1kAq+JINdA=", + "dev": true + }, + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, + "boom": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "brace-expansion": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, + "requires": { + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.2" + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "dev": true + }, + "browser-pack": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/browser-pack/-/browser-pack-6.0.2.tgz", + "integrity": "sha1-+GzWzvT1MAyOY+B6TVEvZfv/RTE=", + "dev": true, + "requires": { + "combine-source-map": "0.7.2", + "defined": "1.0.0", + "JSONStream": "1.3.1", + "through2": "2.0.3", + "umd": "3.0.1" + } + }, + "browser-resolve": { + "version": "1.11.2", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.2.tgz", + "integrity": "sha1-j/CbCixCFxihBRwmCzLkj0QpOM4=", + "dev": true, + "requires": { + "resolve": "1.1.7" + }, + "dependencies": { + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + } + } + }, + "browserify": { + "version": "14.4.0", + "resolved": "https://registry.npmjs.org/browserify/-/browserify-14.4.0.tgz", + "integrity": "sha1-CJo0Y69Y0OSNjNQHCz90ZU1avKk=", + "dev": true, + "requires": { + "assert": "1.4.1", + "browser-pack": "6.0.2", + "browser-resolve": "1.11.2", + "browserify-zlib": "0.1.4", + "buffer": "5.0.8", + "cached-path-relative": "1.0.1", + "concat-stream": "1.5.2", + "console-browserify": "1.1.0", + "constants-browserify": "1.0.0", + "crypto-browserify": "3.11.1", + "defined": "1.0.0", + "deps-sort": "2.0.0", + "domain-browser": "1.1.7", + "duplexer2": "0.1.4", + "events": "1.1.1", + "glob": "7.1.2", + "has": "1.0.1", + "htmlescape": "1.1.1", + "https-browserify": "1.0.0", + "inherits": "2.0.3", + "insert-module-globals": "7.0.1", + "JSONStream": "1.3.1", + "labeled-stream-splicer": "2.0.0", + "module-deps": "4.1.1", + "os-browserify": "0.1.2", + "parents": "1.0.1", + "path-browserify": "0.0.0", + "process": "0.11.10", + "punycode": "1.4.1", + "querystring-es3": "0.2.1", + "read-only-stream": "2.0.0", + "readable-stream": "2.3.3", + "resolve": "1.4.0", + "shasum": "1.0.2", + "shell-quote": "1.6.1", + "stream-browserify": "2.0.1", + "stream-http": "2.7.2", + "string_decoder": "1.0.3", + "subarg": "1.0.0", + "syntax-error": "1.3.0", + "through2": "2.0.3", + "timers-browserify": "1.4.2", + "tty-browserify": "0.0.0", + "url": "0.11.0", + "util": "0.10.3", + "vm-browserify": "0.0.4", + "xtend": "4.0.1" + }, + "dependencies": { + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } + } + } + }, + "browserify-aes": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.0.8.tgz", + "integrity": "sha512-WYCMOT/PtGTlpOKFht0YJFYcPy6pLCR98CtWfzK13zoynLlBMvAdEMSRGmgnJCw2M2j/5qxBkinZQFobieM8dQ==", + "dev": true, + "requires": { + "buffer-xor": "1.0.3", + "cipher-base": "1.0.4", + "create-hash": "1.1.3", + "evp_bytestokey": "1.0.3", + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + }, + "browserify-cache-api": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/browserify-cache-api/-/browserify-cache-api-3.0.1.tgz", + "integrity": "sha1-liR+hT8Gj9bg1FzHPwuyzZd47wI=", + "dev": true, + "requires": { + "async": "1.5.2", + "through2": "2.0.3", + "xtend": "4.0.1" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + } + } + }, + "browserify-cipher": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.0.tgz", + "integrity": "sha1-mYgkSHS/XtTijalWZtzWasj8Njo=", + "dev": true, + "requires": { + "browserify-aes": "1.0.8", + "browserify-des": "1.0.0", + "evp_bytestokey": "1.0.3" + } + }, + "browserify-des": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.0.tgz", + "integrity": "sha1-2qJ3cXRwki7S/hhZQRihdUOXId0=", + "dev": true, + "requires": { + "cipher-base": "1.0.4", + "des.js": "1.0.0", + "inherits": "2.0.3" + } + }, + "browserify-incremental": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/browserify-incremental/-/browserify-incremental-3.1.1.tgz", + "integrity": "sha1-BxPLdYckemMqnwjPG9FpuHi2Koo=", + "dev": true, + "requires": { + "browserify-cache-api": "3.0.1", + "JSONStream": "0.10.0", + "through2": "2.0.3", + "xtend": "4.0.1" + }, + "dependencies": { + "jsonparse": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-0.0.5.tgz", + "integrity": "sha1-MwVCrT8KZUZlt3jz6y2an6UHrGQ=", + "dev": true + }, + "JSONStream": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-0.10.0.tgz", + "integrity": "sha1-dDSdDYlSK3HzDwoD/5vSDKbxKsA=", + "dev": true, + "requires": { + "jsonparse": "0.0.5", + "through": "2.3.8" + } + } + } + }, + "browserify-rsa": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "randombytes": "2.0.5" + } + }, + "browserify-sign": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", + "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "browserify-rsa": "4.0.1", + "create-hash": "1.1.3", + "create-hmac": "1.1.6", + "elliptic": "6.4.0", + "inherits": "2.0.3", + "parse-asn1": "5.1.0" + } + }, + "browserify-zlib": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", + "integrity": "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=", + "dev": true, + "requires": { + "pako": "0.2.9" + } + }, + "buffer": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.0.8.tgz", + "integrity": "sha512-xXvjQhVNz50v2nPeoOsNqWCLGfiv4ji/gXZM28jnVwdLJxH4mFyqgqCKfaK9zf1KUbG6zTkjLOy7ou+jSMarGA==", + "dev": true, + "requires": { + "base64-js": "1.2.1", + "ieee754": "1.1.8" + } + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", + "dev": true + }, + "cached-path-relative": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.0.1.tgz", + "integrity": "sha1-0JxLUoAKpMB44t2BqGmqyQ0uVOc=", + "dev": true + }, + "caller-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", + "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", + "dev": true, + "requires": { + "callsites": "0.2.0" + } + }, + "callsites": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", + "dev": true + }, + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", + "dev": true + }, + "camelcase-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", + "dev": true, + "requires": { + "camelcase": "2.1.1", + "map-obj": "1.0.1" + } + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, + "center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "dev": true, + "requires": { + "align-text": "0.1.4", + "lazy-cache": "1.0.4" + } + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "chokidar": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", + "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", + "dev": true, + "requires": { + "anymatch": "1.3.2", + "async-each": "1.0.1", + "fsevents": "1.1.2", + "glob-parent": "2.0.0", + "inherits": "2.0.3", + "is-binary-path": "1.0.1", + "is-glob": "2.0.1", + "path-is-absolute": "1.0.1", + "readdirp": "2.1.0" + } + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + }, + "circular-json": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", + "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", + "dev": true + }, + "clean-css": { + "version": "3.4.28", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-3.4.28.tgz", + "integrity": "sha1-vxlF6C/ICPVWlebd6uwBQA79A/8=", + "dev": true, + "requires": { + "commander": "2.8.1", + "source-map": "0.4.4" + }, + "dependencies": { + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "dev": true, + "requires": { + "amdefine": "1.0.1" + } + } + } + }, + "cli-cursor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", + "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", + "dev": true, + "requires": { + "restore-cursor": "1.0.1" + } + }, + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", + "dev": true + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "dev": true, + "requires": { + "center-align": "0.1.3", + "right-align": "0.1.3", + "wordwrap": "0.0.2" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "coffee-script": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.3.3.tgz", + "integrity": "sha1-FQ1rTLUiiUNp7+1qIQHCC8f0pPQ=", + "dev": true + }, + "colors": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz", + "integrity": "sha1-JCP+ZnisDF2uiFLl0OW+CMmXq8w=", + "dev": true + }, + "combine-source-map": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.7.2.tgz", + "integrity": "sha1-CHAxKFazB6h8xKxIbzqaYq7MwJ4=", + "dev": true, + "requires": { + "convert-source-map": "1.1.3", + "inline-source-map": "0.6.2", + "lodash.memoize": "3.0.4", + "source-map": "0.5.7" + } + }, + "combined-stream": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", + "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", + "dev": true, + "requires": { + "delayed-stream": "1.0.0" + } + }, + "commander": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz", + "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", + "dev": true, + "requires": { + "graceful-readlink": "1.0.1" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.2.tgz", + "integrity": "sha1-cIl4Yk2FavQaWnQd790mHadSwmY=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.0.6", + "typedarray": "0.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "0.10.31", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "connect": { + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.6.5.tgz", + "integrity": "sha1-+43ee6B2OHfQ7J352sC0tA5yx9o=", + "dev": true, + "requires": { + "debug": "2.6.9", + "finalhandler": "1.0.6", + "parseurl": "1.3.2", + "utils-merge": "1.0.1" + } + }, + "connect-livereload": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/connect-livereload/-/connect-livereload-0.5.4.tgz", + "integrity": "sha1-gBV9E3HJ83zBQDmrGJWXDRGdw7w=", + "dev": true + }, + "console-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", + "dev": true, + "requires": { + "date-now": "0.1.4" + } + }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", + "dev": true + }, + "convert-source-map": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz", + "integrity": "sha1-SCnId+n+SbMWHzvzZziI4gRpmGA=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "create-ecdh": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.0.tgz", + "integrity": "sha1-iIxyNZbN92EvZJgjPuvXo1MBc30=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "elliptic": "6.4.0" + } + }, + "create-hash": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", + "integrity": "sha1-YGBCrIuSYnUPSDyt2rD1gZFy2P0=", + "dev": true, + "requires": { + "cipher-base": "1.0.4", + "inherits": "2.0.3", + "ripemd160": "2.0.1", + "sha.js": "2.4.9" + } + }, + "create-hmac": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.6.tgz", + "integrity": "sha1-rLniIaThe9sHbpBlfEK5PjcmzwY=", + "dev": true, + "requires": { + "cipher-base": "1.0.4", + "create-hash": "1.1.3", + "inherits": "2.0.3", + "ripemd160": "2.0.1", + "safe-buffer": "5.1.1", + "sha.js": "2.4.9" + } + }, + "cryptiles": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", + "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", + "dev": true, + "requires": { + "boom": "2.10.1" + } + }, + "crypto-browserify": { + "version": "3.11.1", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.11.1.tgz", + "integrity": "sha512-Na7ZlwCOqoaW5RwUK1WpXws2kv8mNhWdTlzob0UXulk6G9BDbyiJaGTYBIX61Ozn9l1EPPJpICZb4DaOpT9NlQ==", + "dev": true, + "requires": { + "browserify-cipher": "1.0.0", + "browserify-sign": "4.0.4", + "create-ecdh": "4.0.0", + "create-hash": "1.1.3", + "create-hmac": "1.1.6", + "diffie-hellman": "5.0.2", + "inherits": "2.0.3", + "pbkdf2": "3.0.14", + "public-encrypt": "4.0.0", + "randombytes": "2.0.5" + } + }, + "currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", + "dev": true, + "requires": { + "array-find-index": "1.0.2" + } + }, + "d": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", + "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", + "dev": true, + "requires": { + "es5-ext": "0.10.30" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "date-now": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", + "dev": true + }, + "date-time": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/date-time/-/date-time-1.1.0.tgz", + "integrity": "sha1-GIdtC9pMGf5w3Tv0sDTygbEqQLY=", + "dev": true, + "requires": { + "time-zone": "0.1.0" + } + }, + "dateformat": { + "version": "1.0.2-1.2.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.2-1.2.3.tgz", + "integrity": "sha1-sCIMAt6YYXQztyhRz0fePfLNvuk=", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", + "dev": true + }, + "del": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "dev": true, + "requires": { + "globby": "5.0.0", + "is-path-cwd": "1.0.0", + "is-path-in-cwd": "1.0.0", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "rimraf": "2.2.8" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "depd": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", + "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=", + "dev": true + }, + "deps-sort": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/deps-sort/-/deps-sort-2.0.0.tgz", + "integrity": "sha1-CRckkC6EZYJg65EHSMzNGvbiH7U=", + "dev": true, + "requires": { + "JSONStream": "1.3.1", + "shasum": "1.0.2", + "subarg": "1.0.0", + "through2": "2.0.3" + } + }, + "des.js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", + "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0" + } + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", + "dev": true + }, + "detective": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/detective/-/detective-4.5.0.tgz", + "integrity": "sha1-blqMaybmx6JUsca210kNmOyR7dE=", + "dev": true, + "requires": { + "acorn": "4.0.13", + "defined": "1.0.0" + } + }, + "diff": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.4.0.tgz", + "integrity": "sha512-QpVuMTEoJMF7cKzi6bvWhRulU1fZqZnvyVQgNhPaxxuTYwyjn/j1v9falseQ/uXWwPnO56RBfwtg4h/EQXmucA==", + "dev": true + }, + "diffie-hellman": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.2.tgz", + "integrity": "sha1-tYNXOScM/ias9jIJn97SoH8gnl4=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "miller-rabin": "4.0.1", + "randombytes": "2.0.5" + } + }, + "doctrine": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.0.0.tgz", + "integrity": "sha1-xz2NKQnSIpHhoAejlYBNqLZl/mM=", + "dev": true, + "requires": { + "esutils": "2.0.2", + "isarray": "1.0.0" + } + }, + "domain-browser": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.1.7.tgz", + "integrity": "sha1-hnqksJP6oF8d4IwG9NeyH9+GmLw=", + "dev": true + }, + "duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", + "dev": true, + "requires": { + "readable-stream": "2.3.3" + } + }, + "ecc-jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true + }, + "elliptic": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz", + "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "brorand": "1.1.0", + "hash.js": "1.1.3", + "hmac-drbg": "1.0.1", + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0", + "minimalistic-crypto-utils": "1.0.1" + } + }, + "encodeurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz", + "integrity": "sha1-eePVhlU0aQn+bw9Fpd5oEDspTSA=", + "dev": true + }, + "errno": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.4.tgz", + "integrity": "sha1-uJbiOp5ei6M4cfyZar02NfyaHH0=", + "optional": true, + "requires": { + "prr": "0.0.0" + } + }, + "error-ex": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", + "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", + "dev": true, + "requires": { + "is-arrayish": "0.2.1" + } + }, + "es5-ext": { + "version": "0.10.30", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.30.tgz", + "integrity": "sha1-cUGhaDZpfbq/qq7uQUlc4p9SyTk=", + "dev": true, + "requires": { + "es6-iterator": "2.0.1", + "es6-symbol": "3.1.1" + } + }, + "es6-iterator": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.1.tgz", + "integrity": "sha1-jjGcnwRTv1ddN0lAplWSDlnKVRI=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.30", + "es6-symbol": "3.1.1" + } + }, + "es6-map": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", + "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.30", + "es6-iterator": "2.0.1", + "es6-set": "0.1.5", + "es6-symbol": "3.1.1", + "event-emitter": "0.3.5" + } + }, + "es6-promise": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.0.5.tgz", + "integrity": "sha1-eILzCt3lskDM+n99eMVIMwlRrkI=", + "dev": true + }, + "es6-set": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", + "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.30", + "es6-iterator": "2.0.1", + "es6-symbol": "3.1.1", + "event-emitter": "0.3.5" + } + }, + "es6-symbol": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", + "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.30" + } + }, + "es6-weak-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", + "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.30", + "es6-iterator": "2.0.1", + "es6-symbol": "3.1.1" + } + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "escope": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", + "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", + "dev": true, + "requires": { + "es6-map": "0.1.5", + "es6-weak-map": "2.0.2", + "esrecurse": "4.2.0", + "estraverse": "4.2.0" + } + }, + "eslint": { + "version": "3.19.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-3.19.0.tgz", + "integrity": "sha1-yPxiAcf0DdCJQbh8CFdnOGpnmsw=", + "dev": true, + "requires": { + "babel-code-frame": "6.26.0", + "chalk": "1.1.3", + "concat-stream": "1.5.2", + "debug": "2.6.9", + "doctrine": "2.0.0", + "escope": "3.6.0", + "espree": "3.5.1", + "esquery": "1.0.0", + "estraverse": "4.2.0", + "esutils": "2.0.2", + "file-entry-cache": "2.0.0", + "glob": "7.1.2", + "globals": "9.18.0", + "ignore": "3.3.6", + "imurmurhash": "0.1.4", + "inquirer": "0.12.0", + "is-my-json-valid": "2.16.1", + "is-resolvable": "1.0.0", + "js-yaml": "3.10.0", + "json-stable-stringify": "1.0.1", + "levn": "0.3.0", + "lodash": "4.17.4", + "mkdirp": "0.5.1", + "natural-compare": "1.4.0", + "optionator": "0.8.2", + "path-is-inside": "1.0.2", + "pluralize": "1.2.1", + "progress": "1.1.8", + "require-uncached": "1.0.3", + "shelljs": "0.7.8", + "strip-bom": "3.0.0", + "strip-json-comments": "2.0.1", + "table": "3.8.3", + "text-table": "0.2.0", + "user-home": "2.0.0" + }, + "dependencies": { + "argparse": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", + "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", + "dev": true, + "requires": { + "sprintf-js": "1.0.3" + } + }, + "esprima": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", + "dev": true + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "js-yaml": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", + "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==", + "dev": true, + "requires": { + "argparse": "1.0.9", + "esprima": "4.0.0" + } + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "dev": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "lodash": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + } + } + }, + "espree": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.1.tgz", + "integrity": "sha1-DJiLirRttTEAoZVK5LqZXd0n2H4=", + "dev": true, + "requires": { + "acorn": "5.1.2", + "acorn-jsx": "3.0.1" + }, + "dependencies": { + "acorn": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.1.2.tgz", + "integrity": "sha512-o96FZLJBPY1lvTuJylGA9Bk3t/GKPPJG8H0ydQQl01crzwJgspa4AEIq/pVTXigmK0PHVQhiAtn8WMBLL9D2WA==", + "dev": true + } + } + }, + "esprima": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz", + "integrity": "sha1-n1V+CPw7TSbs6d00+Pv0drYlha0=", + "dev": true + }, + "esquery": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.0.tgz", + "integrity": "sha1-z7qLV9f7qT8XKYqKAGoEzaE9gPo=", + "dev": true, + "requires": { + "estraverse": "4.2.0" + } + }, + "esrecurse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz", + "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=", + "dev": true, + "requires": { + "estraverse": "4.2.0", + "object-assign": "4.1.1" + } + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "dev": true + }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.30" + } + }, + "eventemitter2": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", + "integrity": "sha1-j2G3XN4BKy6esoTUVFWDtWQ7Yas=", + "dev": true + }, + "events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", + "dev": true + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "requires": { + "md5.js": "1.3.4", + "safe-buffer": "5.1.1" + } + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "dev": true + }, + "exit-hook": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", + "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=", + "dev": true + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, + "requires": { + "is-posix-bracket": "0.1.1" + } + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "dev": true, + "requires": { + "fill-range": "2.2.3" + } + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", + "dev": true + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "extract-zip": { + "version": "1.6.5", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.6.5.tgz", + "integrity": "sha1-maBnNbbqIOqbcF13ms/8yHz/BEA=", + "dev": true, + "requires": { + "concat-stream": "1.6.0", + "debug": "2.2.0", + "mkdirp": "0.5.0", + "yauzl": "2.4.1" + }, + "dependencies": { + "concat-stream": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", + "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.3", + "typedarray": "0.0.6" + } + }, + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true, + "requires": { + "ms": "0.7.1" + } + }, + "mkdirp": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", + "integrity": "sha1-HXMHam35hs2TROFecfzAWkyavxI=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + } + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "fd-slicer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", + "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", + "dev": true, + "requires": { + "pend": "1.2.0" + } + }, + "fg-lodash": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/fg-lodash/-/fg-lodash-0.0.2.tgz", + "integrity": "sha1-mINSU39CfaavIiEpu2OsyknmL6M=", + "dev": true, + "requires": { + "lodash": "2.4.2", + "underscore.string": "2.3.3" + }, + "dependencies": { + "lodash": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=", + "dev": true + }, + "underscore.string": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.3.3.tgz", + "integrity": "sha1-ccCL9rQosRM/N+ePo6Icgvcymw0=", + "dev": true + } + } + }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true, + "requires": { + "escape-string-regexp": "1.0.5", + "object-assign": "4.1.1" + } + }, + "file-entry-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", + "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", + "dev": true, + "requires": { + "flat-cache": "1.3.0", + "object-assign": "4.1.1" + } + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", + "dev": true + }, + "fill-range": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", + "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", + "dev": true, + "requires": { + "is-number": "2.1.0", + "isobject": "2.1.0", + "randomatic": "1.1.7", + "repeat-element": "1.1.2", + "repeat-string": "1.6.1" + } + }, + "finalhandler": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.0.6.tgz", + "integrity": "sha1-AHrqM9Gk0+QgF/YkhIrVjSEvgU8=", + "dev": true, + "requires": { + "debug": "2.6.9", + "encodeurl": "1.0.1", + "escape-html": "1.0.3", + "on-finished": "2.3.0", + "parseurl": "1.3.2", + "statuses": "1.3.1", + "unpipe": "1.0.0" + } + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "2.1.0", + "pinkie-promise": "2.0.1" + } + }, + "findup-sync": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.1.3.tgz", + "integrity": "sha1-fz56l7gjksZTvwZYm9hRkOk8NoM=", + "dev": true, + "requires": { + "glob": "3.2.11", + "lodash": "2.4.2" + }, + "dependencies": { + "glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", + "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "minimatch": "0.3.0" + } + }, + "lodash": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=", + "dev": true + }, + "minimatch": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", + "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=", + "dev": true, + "requires": { + "lru-cache": "2.7.3", + "sigmund": "1.0.1" + } + } + } + }, + "flat-cache": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", + "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", + "dev": true, + "requires": { + "circular-json": "0.3.3", + "del": "2.2.2", + "graceful-fs": "4.1.11", + "write": "0.2.1" + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, + "requires": { + "for-in": "1.0.2" + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "form-data": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", + "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", + "dev": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.17" + } + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "dev": true + }, + "fs-extra": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-1.0.0.tgz", + "integrity": "sha1-zTzl9+fLYUWIP8rjGR6Yd/hYeVA=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "jsonfile": "2.4.0", + "klaw": "1.3.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.2.tgz", + "integrity": "sha512-Sn44E5wQW4bTHXvQmvSHwqbuiXtduD6Rrjm2ZtUEGbyrig+nUH3t/QD4M4/ZXViY556TBpRgZkHLDx3JxPwxiw==", + "dev": true, + "optional": true, + "requires": { + "nan": "2.7.0", + "node-pre-gyp": "0.6.36" + }, + "dependencies": { + "abbrev": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "ajv": { + "version": "4.11.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "co": "4.6.0", + "json-stable-stringify": "1.0.1" + } + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "aproba": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.2.9" + } + }, + "asn1": { + "version": "0.2.3", + "bundled": true, + "dev": true, + "optional": true + }, + "assert-plus": { + "version": "0.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "asynckit": { + "version": "0.4.0", + "bundled": true, + "dev": true, + "optional": true + }, + "aws-sign2": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "aws4": { + "version": "1.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "balanced-match": { + "version": "0.4.2", + "bundled": true, + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "block-stream": { + "version": "0.0.9", + "bundled": true, + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, + "boom": { + "version": "2.10.1", + "bundled": true, + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "brace-expansion": { + "version": "1.1.7", + "bundled": true, + "dev": true, + "requires": { + "balanced-match": "0.4.2", + "concat-map": "0.0.1" + } + }, + "buffer-shims": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "caseless": { + "version": "0.12.0", + "bundled": true, + "dev": true, + "optional": true + }, + "co": { + "version": "4.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "combined-stream": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "requires": { + "delayed-stream": "1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "cryptiles": { + "version": "2.0.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "boom": "2.10.1" + } + }, + "dashdash": { + "version": "1.14.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "debug": { + "version": "2.6.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.4.2", + "bundled": true, + "dev": true, + "optional": true + }, + "delayed-stream": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "ecc-jsbn": { + "version": "0.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "extend": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "extsprintf": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "forever-agent": { + "version": "0.6.1", + "bundled": true, + "dev": true, + "optional": true + }, + "form-data": { + "version": "2.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.15" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "fstream": { + "version": "1.0.11", + "bundled": true, + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.6.1" + } + }, + "fstream-ignore": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fstream": "1.0.11", + "inherits": "2.0.3", + "minimatch": "3.0.4" + } + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "1.1.1", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + } + }, + "getpass": { + "version": "0.1.7", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "graceful-fs": { + "version": "4.1.11", + "bundled": true, + "dev": true + }, + "har-schema": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "optional": true + }, + "har-validator": { + "version": "4.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ajv": "4.11.8", + "har-schema": "1.0.5" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "hawk": { + "version": "3.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" + } + }, + "hoek": { + "version": "2.16.3", + "bundled": true, + "dev": true + }, + "http-signature": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "0.2.0", + "jsprim": "1.4.0", + "sshpk": "1.13.0" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true + }, + "ini": { + "version": "1.3.4", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-typedarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "isstream": { + "version": "0.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "jodid25519": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "jsbn": { + "version": "0.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "bundled": true, + "dev": true, + "optional": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "jsonify": { + "version": "0.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "jsprim": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.0.2", + "json-schema": "0.2.3", + "verror": "1.3.6" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "mime-db": { + "version": "1.27.0", + "bundled": true, + "dev": true + }, + "mime-types": { + "version": "2.1.15", + "bundled": true, + "dev": true, + "requires": { + "mime-db": "1.27.0" + } + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "brace-expansion": "1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "node-pre-gyp": { + "version": "0.6.36", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "mkdirp": "0.5.1", + "nopt": "4.0.1", + "npmlog": "4.1.0", + "rc": "1.2.1", + "request": "2.81.0", + "rimraf": "2.6.1", + "semver": "5.3.0", + "tar": "2.2.1", + "tar-pack": "3.4.0" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1.1.0", + "osenv": "0.1.4" + } + }, + "npmlog": { + "version": "4.1.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "oauth-sign": { + "version": "0.8.2", + "bundled": true, + "dev": true, + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "performance-now": { + "version": "0.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "1.0.7", + "bundled": true, + "dev": true + }, + "punycode": { + "version": "1.4.1", + "bundled": true, + "dev": true, + "optional": true + }, + "qs": { + "version": "6.4.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "0.4.2", + "ini": "1.3.4", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.2.9", + "bundled": true, + "dev": true, + "requires": { + "buffer-shims": "1.0.0", + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "1.0.1", + "util-deprecate": "1.0.2" + } + }, + "request": { + "version": "2.81.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aws-sign2": "0.6.0", + "aws4": "1.6.0", + "caseless": "0.12.0", + "combined-stream": "1.0.5", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.1.4", + "har-validator": "4.2.1", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.15", + "oauth-sign": "0.8.2", + "performance-now": "0.2.0", + "qs": "6.4.0", + "safe-buffer": "5.0.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.2", + "tunnel-agent": "0.6.0", + "uuid": "3.0.1" + } + }, + "rimraf": { + "version": "2.6.1", + "bundled": true, + "dev": true, + "requires": { + "glob": "7.1.2" + } + }, + "safe-buffer": { + "version": "5.0.1", + "bundled": true, + "dev": true + }, + "semver": { + "version": "5.3.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sntp": { + "version": "1.0.9", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "hoek": "2.16.3" + } + }, + "sshpk": { + "version": "1.13.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jodid25519": "1.0.2", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "string_decoder": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "5.0.1" + } + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "stringstream": { + "version": "0.0.5", + "bundled": true, + "dev": true, + "optional": true + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "2.2.1", + "bundled": true, + "dev": true, + "requires": { + "block-stream": "0.0.9", + "fstream": "1.0.11", + "inherits": "2.0.3" + } + }, + "tar-pack": { + "version": "3.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "2.6.8", + "fstream": "1.0.11", + "fstream-ignore": "1.0.5", + "once": "1.4.0", + "readable-stream": "2.2.9", + "rimraf": "2.6.1", + "tar": "2.2.1", + "uid-number": "0.0.6" + } + }, + "tough-cookie": { + "version": "2.3.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "punycode": "1.4.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "bundled": true, + "dev": true, + "optional": true + }, + "uid-number": { + "version": "0.0.6", + "bundled": true, + "dev": true, + "optional": true + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "uuid": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "verror": { + "version": "1.3.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "extsprintf": "1.0.2" + } + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true + } + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "generate-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", + "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", + "dev": true + }, + "generate-object-property": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", + "dev": true, + "requires": { + "is-property": "1.0.2" + } + }, + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "dev": true + }, + "getobject": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/getobject/-/getobject-0.1.0.tgz", + "integrity": "sha1-BHpEl4n6Fg0Bj1SG7ZEyC27HiFw=", + "dev": true + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "git-rev": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/git-rev/-/git-rev-0.2.1.tgz", + "integrity": "sha1-jMvSCSs0W8LJFJVIOW31SWRspj8=", + "dev": true + }, + "glob": { + "version": "3.1.21", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", + "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", + "dev": true, + "requires": { + "graceful-fs": "1.2.3", + "inherits": "1.0.2", + "minimatch": "0.2.14" + }, + "dependencies": { + "graceful-fs": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", + "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=", + "dev": true + }, + "inherits": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", + "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=", + "dev": true + } + } + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "dev": true, + "requires": { + "glob-parent": "2.0.0", + "is-glob": "2.0.1" + } + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "requires": { + "is-glob": "2.0.1" + } + }, + "globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "dev": true + }, + "globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "dev": true, + "requires": { + "array-union": "1.0.2", + "arrify": "1.0.1", + "glob": "7.1.2", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + }, + "dependencies": { + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } + } + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + }, + "graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", + "dev": true + }, + "grunt": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/grunt/-/grunt-0.4.5.tgz", + "integrity": "sha1-VpN81RlDJK3/bSB2MYMqnWuk5/A=", + "dev": true, + "requires": { + "async": "0.1.22", + "coffee-script": "1.3.3", + "colors": "0.6.2", + "dateformat": "1.0.2-1.2.3", + "eventemitter2": "0.4.14", + "exit": "0.1.2", + "findup-sync": "0.1.3", + "getobject": "0.1.0", + "glob": "3.1.21", + "grunt-legacy-log": "0.1.3", + "grunt-legacy-util": "0.2.0", + "hooker": "0.2.3", + "iconv-lite": "0.2.11", + "js-yaml": "2.0.5", + "lodash": "0.9.2", + "minimatch": "0.2.14", + "nopt": "1.0.10", + "rimraf": "2.2.8", + "underscore.string": "2.2.1", + "which": "1.0.9" + } + }, + "grunt-browserify": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/grunt-browserify/-/grunt-browserify-5.2.0.tgz", + "integrity": "sha512-q2KKJiXiwgew6+iR3GN44Pbee7jpCxdDnIDnkShQw7fCHWEoSWHnOc4jm4lgoCaHFjVXK3O1di3WHsMF3W6BGw==", + "dev": true, + "requires": { + "async": "2.5.0", + "browserify": "14.4.0", + "browserify-incremental": "3.1.1", + "glob": "7.1.2", + "lodash": "4.17.4", + "resolve": "1.4.0", + "watchify": "3.9.0" + }, + "dependencies": { + "async": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/async/-/async-2.5.0.tgz", + "integrity": "sha512-e+lJAJeNWuPCNyxZKOBdaJGyLGHugXVQtrAwtuAe2vhxTYxFTKE73p8JuTmdH0qdQZtDvI4dhJwjZc5zsfIsYw==", + "dev": true, + "requires": { + "lodash": "4.17.4" + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "lodash": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } + } + } + }, + "grunt-contrib-clean": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/grunt-contrib-clean/-/grunt-contrib-clean-1.1.0.tgz", + "integrity": "sha1-Vkq/LQN4qYOhW54/MO51tzjEBjg=", + "dev": true, + "requires": { + "async": "1.5.2", + "rimraf": "2.6.2" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "dev": true, + "requires": { + "glob": "7.1.2" + } + } + } + }, + "grunt-contrib-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/grunt-contrib-concat/-/grunt-contrib-concat-1.0.1.tgz", + "integrity": "sha1-YVCYYwhOhx1+ht5IwBUlntl3Rb0=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "source-map": "0.5.7" + } + }, + "grunt-contrib-connect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/grunt-contrib-connect/-/grunt-contrib-connect-1.0.2.tgz", + "integrity": "sha1-XPkzuRpnOGBEJzwLJERgPNmIebo=", + "dev": true, + "requires": { + "async": "1.5.2", + "connect": "3.6.5", + "connect-livereload": "0.5.4", + "http2": "3.3.7", + "morgan": "1.9.0", + "opn": "4.0.2", + "portscanner": "1.2.0", + "serve-index": "1.9.1", + "serve-static": "1.13.1" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + } + } + }, + "grunt-contrib-jasmine": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/grunt-contrib-jasmine/-/grunt-contrib-jasmine-1.1.0.tgz", + "integrity": "sha1-9oL3dX2il3Wf4+G0xl1GcMw66kk=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "grunt-lib-phantomjs": "1.1.0", + "jasmine-core": "2.4.1", + "lodash": "2.4.2", + "rimraf": "2.2.8", + "sprintf-js": "1.0.3" + }, + "dependencies": { + "lodash": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=", + "dev": true + } + } + }, + "grunt-contrib-uglify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/grunt-contrib-uglify/-/grunt-contrib-uglify-1.0.2.tgz", + "integrity": "sha1-rmekb5FT7dTLEYE6Vetpxw19svs=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "lodash": "4.17.4", + "maxmin": "1.1.0", + "uglify-js": "2.6.4", + "uri-path": "1.0.0" + }, + "dependencies": { + "lodash": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", + "dev": true + } + } + }, + "grunt-eslint": { + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/grunt-eslint/-/grunt-eslint-19.0.0.tgz", + "integrity": "sha1-u3TDeQYVmc7B9mFp3vKonYYthhs=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "eslint": "3.19.0" + } + }, + "grunt-legacy-log": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/grunt-legacy-log/-/grunt-legacy-log-0.1.3.tgz", + "integrity": "sha1-7ClCboAwIa9ZAp+H0vnNczWgVTE=", + "dev": true, + "requires": { + "colors": "0.6.2", + "grunt-legacy-log-utils": "0.1.1", + "hooker": "0.2.3", + "lodash": "2.4.2", + "underscore.string": "2.3.3" + }, + "dependencies": { + "lodash": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=", + "dev": true + }, + "underscore.string": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.3.3.tgz", + "integrity": "sha1-ccCL9rQosRM/N+ePo6Icgvcymw0=", + "dev": true + } + } + }, + "grunt-legacy-log-utils": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/grunt-legacy-log-utils/-/grunt-legacy-log-utils-0.1.1.tgz", + "integrity": "sha1-wHBrndkGThFvNvI/5OawSGcsD34=", + "dev": true, + "requires": { + "colors": "0.6.2", + "lodash": "2.4.2", + "underscore.string": "2.3.3" + }, + "dependencies": { + "lodash": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=", + "dev": true + }, + "underscore.string": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.3.3.tgz", + "integrity": "sha1-ccCL9rQosRM/N+ePo6Icgvcymw0=", + "dev": true + } + } + }, + "grunt-legacy-util": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/grunt-legacy-util/-/grunt-legacy-util-0.2.0.tgz", + "integrity": "sha1-kzJIhNv343qf98Am3/RR2UqeVUs=", + "dev": true, + "requires": { + "async": "0.1.22", + "exit": "0.1.2", + "getobject": "0.1.0", + "hooker": "0.2.3", + "lodash": "0.9.2", + "underscore.string": "2.2.1", + "which": "1.0.9" + } + }, + "grunt-lib-phantomjs": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/grunt-lib-phantomjs/-/grunt-lib-phantomjs-1.1.0.tgz", + "integrity": "sha1-np7c3Z/S3UDgwYHJQ3HVcqpe6tI=", + "dev": true, + "requires": { + "eventemitter2": "0.4.14", + "phantomjs-prebuilt": "2.1.15", + "rimraf": "2.6.2", + "semver": "5.4.1", + "temporary": "0.0.8" + }, + "dependencies": { + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "dev": true, + "requires": { + "glob": "7.1.2" + } + } + } + }, + "grunt-saucelabs": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/grunt-saucelabs/-/grunt-saucelabs-9.0.0.tgz", + "integrity": "sha1-1ogCWgVQHeysCp4SndTk9QpCAUo=", + "dev": true, + "requires": { + "colors": "1.1.2", + "lodash": "4.13.1", + "q": "1.4.1", + "requestretry": "1.9.1", + "sauce-tunnel": "2.5.0", + "saucelabs": "1.2.0" + }, + "dependencies": { + "colors": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", + "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", + "dev": true + }, + "lodash": { + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.13.1.tgz", + "integrity": "sha1-g+SxCRP0hJbU0W/sSlYK8u50S2g=", + "dev": true + } + } + }, + "grunt-shell": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/grunt-shell/-/grunt-shell-1.3.1.tgz", + "integrity": "sha1-XivuzQXV03h/pAECjVcz1dQ7m9E=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "npm-run-path": "1.0.0", + "object-assign": "4.1.1" + } + }, + "gzip-size": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-1.0.0.tgz", + "integrity": "sha1-Zs+LEBBHInuVus5uodoMF37Vwi8=", + "dev": true, + "requires": { + "browserify-zlib": "0.1.4", + "concat-stream": "1.5.2" + } + }, + "har-schema": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", + "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=", + "dev": true + }, + "har-validator": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", + "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", + "dev": true, + "requires": { + "ajv": "4.11.8", + "har-schema": "1.0.5" + } + }, + "has": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", + "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", + "dev": true, + "requires": { + "function-bind": "1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "hash-base": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz", + "integrity": "sha1-ZuodhW206KVHDK32/OI65SRO8uE=", + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, + "hash.js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", + "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0" + } + }, + "hasha": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/hasha/-/hasha-2.2.0.tgz", + "integrity": "sha1-eNfL/B5tZjA/55g3NlmEUXsvbuE=", + "dev": true, + "requires": { + "is-stream": "1.1.0", + "pinkie-promise": "2.0.1" + } + }, + "hawk": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", + "dev": true, + "requires": { + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" + } + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dev": true, + "requires": { + "hash.js": "1.1.3", + "minimalistic-assert": "1.0.0", + "minimalistic-crypto-utils": "1.0.1" + } + }, + "hoek": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", + "dev": true + }, + "hooker": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz", + "integrity": "sha1-uDT3I8xKJCqmWWNFnfbZhMXT2Vk=", + "dev": true + }, + "hosted-git-info": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", + "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==", + "dev": true + }, + "htmlescape": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/htmlescape/-/htmlescape-1.1.1.tgz", + "integrity": "sha1-OgPtwiFLyjtmQko+eVk0lQnLA1E=", + "dev": true + }, + "http-errors": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", + "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", + "dev": true, + "requires": { + "depd": "1.1.1", + "inherits": "2.0.3", + "setprototypeof": "1.0.3", + "statuses": "1.3.1" + } + }, + "http-signature": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", + "dev": true, + "requires": { + "assert-plus": "0.2.0", + "jsprim": "1.4.1", + "sshpk": "1.13.1" + } + }, + "http2": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/http2/-/http2-3.3.7.tgz", + "integrity": "sha512-puSi8M8WNlFJm9Pk4c/Mbz9Gwparuj3gO9/RRO5zv6piQ0FY+9Qywp0PdWshYgsMJSalixFY7eC6oPu0zRxLAQ==", + "dev": true + }, + "https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", + "dev": true + }, + "https-proxy-agent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz", + "integrity": "sha1-NffabEjOTdv6JkiRrFk+5f+GceY=", + "dev": true, + "requires": { + "agent-base": "2.1.1", + "debug": "2.6.9", + "extend": "3.0.1" + } + }, + "iconv-lite": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.2.11.tgz", + "integrity": "sha1-HOYKOleGSiktEyH/RgnKS7llrcg=", + "dev": true + }, + "ieee754": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz", + "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=", + "dev": true + }, + "ignore": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.6.tgz", + "integrity": "sha512-HrxmNxKTGZ9a3uAl/FNG66Sdt0G9L4TtMbbUQjP1WhGmSj0FOyHvSgx7623aGJvXfPOur8MwmarlHT+37jmzlw==", + "dev": true + }, + "image-size": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", + "integrity": "sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w=", + "optional": true + }, + "import-module": { + "version": "file:test/import-module", + "dev": true + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "dev": true, + "requires": { + "repeating": "2.0.1" + } + }, + "indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "inline-source-map": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.6.2.tgz", + "integrity": "sha1-+Tk0ccGKedFyT4Y/o4tYY3Ct4qU=", + "dev": true, + "requires": { + "source-map": "0.5.7" + } + }, + "inquirer": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz", + "integrity": "sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=", + "dev": true, + "requires": { + "ansi-escapes": "1.4.0", + "ansi-regex": "2.1.1", + "chalk": "1.1.3", + "cli-cursor": "1.0.2", + "cli-width": "2.2.0", + "figures": "1.7.0", + "lodash": "4.17.4", + "readline2": "1.0.1", + "run-async": "0.1.0", + "rx-lite": "3.1.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "through": "2.3.8" + }, + "dependencies": { + "lodash": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", + "dev": true + } + } + }, + "insert-module-globals": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-7.0.1.tgz", + "integrity": "sha1-wDv04BywhtW15azorQr+eInWOMM=", + "dev": true, + "requires": { + "combine-source-map": "0.7.2", + "concat-stream": "1.5.2", + "is-buffer": "1.1.5", + "JSONStream": "1.3.1", + "lexical-scope": "1.2.0", + "process": "0.11.10", + "through2": "2.0.3", + "xtend": "4.0.1" + } + }, + "interpret": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.0.4.tgz", + "integrity": "sha1-ggzdWIuGj/sZGoCVBtbJyPISsbA=", + "dev": true + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "requires": { + "binary-extensions": "1.10.0" + } + }, + "is-buffer": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz", + "integrity": "sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw=", + "dev": true + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "dev": true, + "requires": { + "builtin-modules": "1.1.1" + } + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", + "dev": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "dev": true, + "requires": { + "is-primitive": "2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-finite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "is-my-json-valid": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.16.1.tgz", + "integrity": "sha512-ochPsqWS1WXj8ZnMIV0vnNXooaMhp7cyL4FMSIPKTtnV0Ha/T19G2b9kkhcNsabV9bxYkze7/aLZJb/bYuFduQ==", + "dev": true, + "requires": { + "generate-function": "2.0.0", + "generate-object-property": "1.2.0", + "jsonpointer": "4.0.1", + "xtend": "4.0.1" + } + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "dev": true + }, + "is-path-in-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", + "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", + "dev": true, + "requires": { + "is-path-inside": "1.0.0" + } + }, + "is-path-inside": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz", + "integrity": "sha1-/AbloWg/vaE95mev9xe7wQpI838=", + "dev": true, + "requires": { + "path-is-inside": "1.0.2" + } + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "dev": true + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "dev": true + }, + "is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", + "dev": true + }, + "is-resolvable": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.0.0.tgz", + "integrity": "sha1-jfV8YeouPFAUCNEA+wE8+NbgzGI=", + "dev": true, + "requires": { + "tryit": "1.0.3" + } + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "jasmine-core": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.4.1.tgz", + "integrity": "sha1-b4OrOg8WlRcizgfSBsdz1XzIOL4=", + "dev": true + }, + "jit-grunt": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/jit-grunt/-/jit-grunt-0.10.0.tgz", + "integrity": "sha1-AIw6f+Hpa9DYTiYOofoXg0V/ecI=", + "dev": true + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + }, + "js-yaml": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-2.0.5.tgz", + "integrity": "sha1-olrmUJmZ6X3yeMZxnaEb0Gh3Q6g=", + "dev": true, + "requires": { + "argparse": "0.1.16", + "esprima": "1.0.4" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true, + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, + "json-stable-stringify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz", + "integrity": "sha1-YRwj6BTbN1Un34URk9tZ3Sryf0U=", + "dev": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "jsonfile": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11" + } + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true + }, + "jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "dev": true + }, + "jsonpointer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", + "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", + "dev": true + }, + "JSONStream": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.1.tgz", + "integrity": "sha1-cH92HgHa6eFvG8+TcDt4xwlmV5o=", + "dev": true, + "requires": { + "jsonparse": "1.3.1", + "through": "2.3.8" + } + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "kew": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/kew/-/kew-0.7.0.tgz", + "integrity": "sha1-edk9LTM2PW/dKXCzNdkUGtWR15s=", + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.5" + } + }, + "klaw": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", + "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11" + } + }, + "labeled-stream-splicer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.0.tgz", + "integrity": "sha1-pS4dE4AkwAuGscDJH2d5GLiuClk=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "isarray": "0.0.1", + "stream-splicer": "2.0.0" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + } + } + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", + "dev": true + }, + "less-plugin-clean-css": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/less-plugin-clean-css/-/less-plugin-clean-css-1.5.1.tgz", + "integrity": "sha1-zFeveqM5iVflbezr5jy2DCNClwM=", + "dev": true, + "requires": { + "clean-css": "3.4.28" + } + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "1.1.2", + "type-check": "0.3.2" + } + }, + "lexical-scope": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/lexical-scope/-/lexical-scope-1.2.0.tgz", + "integrity": "sha1-/Ope3HBKSzqHls3KQZw6CvryLfQ=", + "dev": true, + "requires": { + "astw": "2.2.0" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0" + } + }, + "lodash": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-0.9.2.tgz", + "integrity": "sha1-jzSZxSRdNG1oLlsNO0B2fgnxqSw=", + "dev": true + }, + "lodash.memoize": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz", + "integrity": "sha1-LcvSwofLwKVcxCMovQxzYVDVPj8=", + "dev": true + }, + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", + "dev": true + }, + "loud-rejection": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "dev": true, + "requires": { + "currently-unhandled": "0.4.1", + "signal-exit": "3.0.2" + } + }, + "lru-cache": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", + "dev": true + }, + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true + }, + "maxmin": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/maxmin/-/maxmin-1.1.0.tgz", + "integrity": "sha1-cTZehKmd2Piz99X94vANHn9zvmE=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "figures": "1.7.0", + "gzip-size": "1.0.0", + "pretty-bytes": "1.0.4" + } + }, + "md5.js": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", + "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", + "dev": true, + "requires": { + "hash-base": "3.0.4", + "inherits": "2.0.3" + }, + "dependencies": { + "hash-base": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + } + } + }, + "meow": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", + "dev": true, + "requires": { + "camelcase-keys": "2.1.0", + "decamelize": "1.2.0", + "loud-rejection": "1.6.0", + "map-obj": "1.0.1", + "minimist": "1.2.0", + "normalize-package-data": "2.4.0", + "object-assign": "4.1.1", + "read-pkg-up": "1.0.1", + "redent": "1.0.0", + "trim-newlines": "1.0.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "requires": { + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.4" + } + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "brorand": "1.1.0" + } + }, + "mime": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" + }, + "mime-db": { + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", + "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=", + "dev": true + }, + "mime-types": { + "version": "2.1.17", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", + "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", + "dev": true, + "requires": { + "mime-db": "1.30.0" + } + }, + "minimalistic-assert": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz", + "integrity": "sha1-cCvi3aazf0g2vLP121ZkG2Sh09M=", + "dev": true + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "dev": true + }, + "minimatch": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", + "dev": true, + "requires": { + "lru-cache": "2.7.3", + "sigmund": "1.0.1" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + } + }, + "module-deps": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-4.1.1.tgz", + "integrity": "sha1-IyFYM/HaE/1gbMuAh7RIUty4If0=", + "dev": true, + "requires": { + "browser-resolve": "1.11.2", + "cached-path-relative": "1.0.1", + "concat-stream": "1.5.2", + "defined": "1.0.0", + "detective": "4.5.0", + "duplexer2": "0.1.4", + "inherits": "2.0.3", + "JSONStream": "1.3.1", + "parents": "1.0.1", + "readable-stream": "2.3.3", + "resolve": "1.4.0", + "stream-combiner2": "1.1.1", + "subarg": "1.0.0", + "through2": "2.0.3", + "xtend": "4.0.1" + } + }, + "morgan": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.9.0.tgz", + "integrity": "sha1-0B+mxlhZt2/PMbPLU6OCGjEdgFE=", + "dev": true, + "requires": { + "basic-auth": "2.0.0", + "debug": "2.6.9", + "depd": "1.1.1", + "on-finished": "2.3.0", + "on-headers": "1.0.1" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "mute-stream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz", + "integrity": "sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=", + "dev": true + }, + "nan": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.7.0.tgz", + "integrity": "sha1-2Vv3IeyHfgjbJ27T/G63j5CDrUY=", + "dev": true, + "optional": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "negotiator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", + "dev": true + }, + "nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", + "dev": true, + "requires": { + "abbrev": "1.1.1" + } + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "dev": true, + "requires": { + "hosted-git-info": "2.5.0", + "is-builtin-module": "1.0.0", + "semver": "5.4.1", + "validate-npm-package-license": "3.0.1" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "1.1.0" + } + }, + "npm-run-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-1.0.0.tgz", + "integrity": "sha1-9cMr9ZX+ga6Sfa7FLoL4sACsPI8=", + "dev": true, + "requires": { + "path-key": "1.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "dev": true, + "requires": { + "for-own": "0.1.5", + "is-extendable": "0.1.1" + } + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true, + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", + "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "onetime": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", + "dev": true + }, + "opn": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/opn/-/opn-4.0.2.tgz", + "integrity": "sha1-erwi5kTf9jsKltWrfyeQwPAavJU=", + "dev": true, + "requires": { + "object-assign": "4.1.1", + "pinkie-promise": "2.0.1" + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true, + "requires": { + "deep-is": "0.1.3", + "fast-levenshtein": "2.0.6", + "levn": "0.3.0", + "prelude-ls": "1.1.2", + "type-check": "0.3.2", + "wordwrap": "1.0.0" + }, + "dependencies": { + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + } + } + }, + "os-browserify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.1.2.tgz", + "integrity": "sha1-ScoCk+CxlZCl9d4Qx/JlphfY/lQ=", + "dev": true + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "outpipe": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/outpipe/-/outpipe-1.1.1.tgz", + "integrity": "sha1-UM+GFjZeh+Ax4ppeyTOaPaRyX6I=", + "dev": true, + "requires": { + "shell-quote": "1.6.1" + } + }, + "package": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package/-/package-1.0.1.tgz", + "integrity": "sha1-0lofmeJQbcsn1nBLg9yooxLk7cw=", + "dev": true + }, + "pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=", + "dev": true + }, + "parents": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", + "integrity": "sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E=", + "dev": true, + "requires": { + "path-platform": "0.11.15" + } + }, + "parse-asn1": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.0.tgz", + "integrity": "sha1-N8T5t+06tlx0gXtfJICTf7+XxxI=", + "dev": true, + "requires": { + "asn1.js": "4.9.1", + "browserify-aes": "1.0.8", + "create-hash": "1.1.3", + "evp_bytestokey": "1.0.3", + "pbkdf2": "3.0.14" + } + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "dev": true, + "requires": { + "glob-base": "0.3.0", + "is-dotfile": "1.0.3", + "is-extglob": "1.0.0", + "is-glob": "2.0.1" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "1.3.1" + } + }, + "parse-ms": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-1.0.1.tgz", + "integrity": "sha1-VjRtR0nXjyNDDKDHE4UK75GqNh0=", + "dev": true + }, + "parseurl": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=", + "dev": true + }, + "path-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", + "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", + "dev": true + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "2.0.1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-key": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-1.0.0.tgz", + "integrity": "sha1-XVPVeAGWRsDWiADbThRua9wqx68=", + "dev": true + }, + "path-parse": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", + "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", + "dev": true + }, + "path-platform": { + "version": "0.11.15", + "resolved": "https://registry.npmjs.org/path-platform/-/path-platform-0.11.15.tgz", + "integrity": "sha1-6GQhf3TDaFDwhSt43Hv31KVyG/I=", + "dev": true + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "pbkdf2": { + "version": "3.0.14", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.14.tgz", + "integrity": "sha512-gjsZW9O34fm0R7PaLHRJmLLVfSoesxztjPjE9o6R+qtVJij90ltg1joIovN9GKrRW3t1PzhDDG3UMEMFfZ+1wA==", + "dev": true, + "requires": { + "create-hash": "1.1.3", + "create-hmac": "1.1.6", + "ripemd160": "2.0.1", + "safe-buffer": "5.1.1", + "sha.js": "2.4.9" + } + }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", + "dev": true + }, + "performance-now": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", + "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=", + "dev": true + }, + "phantomjs-prebuilt": { + "version": "2.1.15", + "resolved": "https://registry.npmjs.org/phantomjs-prebuilt/-/phantomjs-prebuilt-2.1.15.tgz", + "integrity": "sha1-IPhugtM0nFBZF1J3RbekEeCLOQM=", + "dev": true, + "requires": { + "es6-promise": "4.0.5", + "extract-zip": "1.6.5", + "fs-extra": "1.0.0", + "hasha": "2.2.0", + "kew": "0.7.0", + "progress": "1.1.8", + "request": "2.81.0", + "request-progress": "2.0.1", + "which": "1.2.14" + }, + "dependencies": { + "which": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/which/-/which-1.2.14.tgz", + "integrity": "sha1-mofEN48D6CfOyvGs31bHNsAcFOU=", + "dev": true, + "requires": { + "isexe": "2.0.0" + } + } + } + }, + "phin": { + "version": "2.4.18", + "resolved": "https://registry.npmjs.org/phin/-/phin-2.4.18.tgz", + "integrity": "sha512-2/18cxAwR+Tj6aXPppGF/PQjrEO+v+paSNkL5B3FD8IWRluqfxnuE7gdMmOMuU7LzJuS/1BsB0A8SDc8tmapnA==", + "dev": true + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "2.0.4" + } + }, + "plur": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/plur/-/plur-1.0.0.tgz", + "integrity": "sha1-24XGgU9eXlo7Se/CjWBP7GKXUVY=", + "dev": true + }, + "pluralize": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-1.2.1.tgz", + "integrity": "sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU=", + "dev": true + }, + "portscanner": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/portscanner/-/portscanner-1.2.0.tgz", + "integrity": "sha1-sUu9olfRTDEPqcwJaCrwLUCWGAI=", + "dev": true, + "requires": { + "async": "1.5.2" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + } + } + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true + }, + "pretty-bytes": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-1.0.4.tgz", + "integrity": "sha1-CiLoIQYJrTVUL4yNXSFZr/B1HIQ=", + "dev": true, + "requires": { + "get-stdin": "4.0.1", + "meow": "3.7.0" + } + }, + "pretty-ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-2.1.0.tgz", + "integrity": "sha1-QlfCVt8/sLRR1q/6qwIYhBJpgdw=", + "dev": true, + "requires": { + "is-finite": "1.0.2", + "parse-ms": "1.0.1", + "plur": "1.0.0" + } + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "progress": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", + "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", + "dev": true + }, + "promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "dev": true, + "optional": true, + "requires": { + "asap": "2.0.6" + } + }, + "prr": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/prr/-/prr-0.0.0.tgz", + "integrity": "sha1-GoS4WQgyVQFBGFPQCB7j+obikmo=", + "optional": true + }, + "public-encrypt": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.0.tgz", + "integrity": "sha1-OfaZ86RlYN1eusvKaTyvfGXBjMY=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "browserify-rsa": "4.0.1", + "create-hash": "1.1.3", + "parse-asn1": "5.1.0", + "randombytes": "2.0.5" + } + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "q": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz", + "integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=", + "dev": true + }, + "qs": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", + "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=", + "dev": true + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "dev": true + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "dev": true + }, + "randomatic": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", + "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", + "dev": true, + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.5" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "1.1.5" + } + } + } + }, + "randombytes": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.5.tgz", + "integrity": "sha512-8T7Zn1AhMsQ/HI1SjcCfT/t4ii3eAqco3yOcSzS4mozsOz69lHLsoMXmF9nZgnFanYscnSlUSgs8uZyKzpE6kg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", + "dev": true + }, + "read-only-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-only-stream/-/read-only-stream-2.0.0.tgz", + "integrity": "sha1-JyT9aoET1zdkrCiNQ4YnDB2/F/A=", + "dev": true, + "requires": { + "readable-stream": "2.3.3" + } + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "1.1.0", + "normalize-package-data": "2.4.0", + "path-type": "1.1.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "requires": { + "find-up": "1.1.2", + "read-pkg": "1.1.0" + } + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "readdirp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", + "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "minimatch": "3.0.4", + "readable-stream": "2.3.3", + "set-immediate-shim": "1.0.1" + }, + "dependencies": { + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } + } + } + }, + "readline2": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/readline2/-/readline2-1.0.1.tgz", + "integrity": "sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "mute-stream": "0.0.5" + } + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, + "requires": { + "resolve": "1.4.0" + } + }, + "redent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", + "dev": true, + "requires": { + "indent-string": "2.1.0", + "strip-indent": "1.0.1" + } + }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "dev": true, + "requires": { + "is-equal-shallow": "0.1.3" + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "repeat-element": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true, + "requires": { + "is-finite": "1.0.2" + } + }, + "request": { + "version": "2.81.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", + "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", + "dev": true, + "requires": { + "aws-sign2": "0.6.0", + "aws4": "1.6.0", + "caseless": "0.12.0", + "combined-stream": "1.0.5", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.1.4", + "har-validator": "4.2.1", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.17", + "oauth-sign": "0.8.2", + "performance-now": "0.2.0", + "qs": "6.4.0", + "safe-buffer": "5.1.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.3", + "tunnel-agent": "0.6.0", + "uuid": "3.1.0" + } + }, + "request-progress": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-2.0.1.tgz", + "integrity": "sha1-XTa7V5YcZzqlt4jbyBQf3yO0Tgg=", + "dev": true, + "requires": { + "throttleit": "1.0.0" + } + }, + "requestretry": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/requestretry/-/requestretry-1.9.1.tgz", + "integrity": "sha1-CioATq8hGWnEzCz+vz/p5XuSx04=", + "dev": true, + "requires": { + "extend": "3.0.1", + "fg-lodash": "0.0.2", + "request": "2.81.0", + "when": "3.7.8" + } + }, + "require-uncached": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", + "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", + "dev": true, + "requires": { + "caller-path": "0.1.0", + "resolve-from": "1.0.1" + } + }, + "resolve": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.4.0.tgz", + "integrity": "sha512-aW7sVKPufyHqOmyyLzg/J+8606v5nevBgaliIlV7nUpVMsDnoBGV/cbSLNjZAg9q0Cfd/+easKVKQ8vOu8fn1Q==", + "dev": true, + "requires": { + "path-parse": "1.0.5" + } + }, + "resolve-from": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", + "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", + "dev": true + }, + "restore-cursor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", + "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", + "dev": true, + "requires": { + "exit-hook": "1.1.1", + "onetime": "1.1.0" + } + }, + "right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "dev": true, + "requires": { + "align-text": "0.1.4" + } + }, + "rimraf": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", + "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=", + "dev": true + }, + "ripemd160": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz", + "integrity": "sha1-D0WEKVxTo2KK9+bXmsohzlfRxuc=", + "dev": true, + "requires": { + "hash-base": "2.0.2", + "inherits": "2.0.3" + } + }, + "run-async": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz", + "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=", + "dev": true, + "requires": { + "once": "1.4.0" + } + }, + "rx-lite": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz", + "integrity": "sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=", + "dev": true + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", + "dev": true + }, + "sauce-tunnel": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/sauce-tunnel/-/sauce-tunnel-2.5.0.tgz", + "integrity": "sha1-DuTE/5tH4BPosHLL+sSVt/7Y6Os=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "request": "2.81.0", + "split": "1.0.1" + } + }, + "saucelabs": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/saucelabs/-/saucelabs-1.2.0.tgz", + "integrity": "sha1-XoBHazbaG0LRDzlwfprypTsD2Io=", + "dev": true, + "requires": { + "https-proxy-agent": "1.0.0" + } + }, + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", + "dev": true + }, + "send": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.16.1.tgz", + "integrity": "sha512-ElCLJdJIKPk6ux/Hocwhk7NFHpI3pVm/IZOYWqUmoxcgeyM+MpxHHKhb8QmlJDX1pU6WrgaHBkVNm73Sv7uc2A==", + "dev": true, + "requires": { + "debug": "2.6.9", + "depd": "1.1.1", + "destroy": "1.0.4", + "encodeurl": "1.0.1", + "escape-html": "1.0.3", + "etag": "1.8.1", + "fresh": "0.5.2", + "http-errors": "1.6.2", + "mime": "1.4.1", + "ms": "2.0.0", + "on-finished": "2.3.0", + "range-parser": "1.2.0", + "statuses": "1.3.1" + } + }, + "serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", + "dev": true, + "requires": { + "accepts": "1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "1.0.3", + "http-errors": "1.6.2", + "mime-types": "2.1.17", + "parseurl": "1.3.2" + } + }, + "serve-static": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.1.tgz", + "integrity": "sha512-hSMUZrsPa/I09VYFJwa627JJkNs0NrfL1Uzuup+GqHfToR2KcsXFymXSV90hoyw3M+msjFuQly+YzIH/q0MGlQ==", + "dev": true, + "requires": { + "encodeurl": "1.0.1", + "escape-html": "1.0.3", + "parseurl": "1.3.2", + "send": "0.16.1" + } + }, + "set-immediate-shim": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", + "dev": true + }, + "setprototypeof": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", + "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=", + "dev": true + }, + "sha.js": { + "version": "2.4.9", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.9.tgz", + "integrity": "sha512-G8zektVqbiPHrylgew9Zg1VRB1L/DtXNUVAM6q4QLy8NE3qtHlFXTf8VLL4k1Yl6c7NMjtZUTdXV+X44nFaT6A==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + }, + "shasum": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/shasum/-/shasum-1.0.2.tgz", + "integrity": "sha1-5wEjENj0F/TetXEhUOVni4euVl8=", + "dev": true, + "requires": { + "json-stable-stringify": "0.0.1", + "sha.js": "2.4.9" + } + }, + "shell-quote": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.6.1.tgz", + "integrity": "sha1-9HgZSczkAmlxJ0MOo7PFR29IF2c=", + "dev": true, + "requires": { + "array-filter": "0.0.1", + "array-map": "0.0.0", + "array-reduce": "0.0.0", + "jsonify": "0.0.0" + } + }, + "shelljs": { + "version": "0.7.8", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.8.tgz", + "integrity": "sha1-3svPh0sNHl+3LhSxZKloMEjprLM=", + "dev": true, + "requires": { + "glob": "7.1.2", + "interpret": "1.0.4", + "rechoir": "0.6.2" + }, + "dependencies": { + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } + } + } + }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "slice-ansi": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", + "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", + "dev": true + }, + "sntp": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", + "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + }, + "spdx-correct": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", + "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", + "dev": true, + "requires": { + "spdx-license-ids": "1.2.2" + } + }, + "spdx-expression-parse": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", + "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=", + "dev": true + }, + "spdx-license-ids": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", + "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=", + "dev": true + }, + "split": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", + "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", + "dev": true, + "requires": { + "through": "2.3.8" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "sshpk": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", + "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", + "dev": true, + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "statuses": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", + "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=", + "dev": true + }, + "stream-browserify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", + "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.3" + } + }, + "stream-combiner2": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", + "integrity": "sha1-+02KFCDqNidk4hrUeAOXvry0HL4=", + "dev": true, + "requires": { + "duplexer2": "0.1.4", + "readable-stream": "2.3.3" + } + }, + "stream-http": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.7.2.tgz", + "integrity": "sha512-c0yTD2rbQzXtSsFSVhtpvY/vS6u066PcXOX9kBB3mSO76RiUQzL340uJkGBWnlBg4/HZzqiUXtaVA7wcRcJgEw==", + "dev": true, + "requires": { + "builtin-status-codes": "3.0.0", + "inherits": "2.0.3", + "readable-stream": "2.3.3", + "to-arraybuffer": "1.0.1", + "xtend": "4.0.1" + } + }, + "stream-splicer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/stream-splicer/-/stream-splicer-2.0.0.tgz", + "integrity": "sha1-G2O+Q4oTPktnHMGTUZdgAXWRDYM=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.3" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "stringstream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "0.2.1" + } + }, + "strip-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "dev": true, + "requires": { + "get-stdin": "4.0.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "subarg": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", + "integrity": "sha1-9izxdYHplrSPyWVpn1TAauJouNI=", + "dev": true, + "requires": { + "minimist": "1.2.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "syntax-error": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.3.0.tgz", + "integrity": "sha1-HtkmbE1AvnXcVb+bsct3Biu5bKE=", + "dev": true, + "requires": { + "acorn": "4.0.13" + } + }, + "table": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/table/-/table-3.8.3.tgz", + "integrity": "sha1-K7xULw/amGGnVdOUf+/Ys/UThV8=", + "dev": true, + "requires": { + "ajv": "4.11.8", + "ajv-keywords": "1.5.1", + "chalk": "1.1.3", + "lodash": "4.17.4", + "slice-ansi": "0.0.4", + "string-width": "2.1.1" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "lodash": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + } + } + }, + "temporary": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/temporary/-/temporary-0.0.8.tgz", + "integrity": "sha1-oYqYHSi6jKNgJ/s8MFOMPst0CsA=", + "dev": true, + "requires": { + "package": "1.0.1" + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "throttleit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz", + "integrity": "sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw=", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dev": true, + "requires": { + "readable-stream": "2.3.3", + "xtend": "4.0.1" + } + }, + "time-grunt": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/time-grunt/-/time-grunt-1.4.0.tgz", + "integrity": "sha1-BiIT5mDJB+hvRAVWwB6mWXtxJCA=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "date-time": "1.1.0", + "figures": "1.7.0", + "hooker": "0.2.3", + "number-is-nan": "1.0.1", + "pretty-ms": "2.1.0", + "text-table": "0.2.0" + } + }, + "time-zone": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/time-zone/-/time-zone-0.1.0.tgz", + "integrity": "sha1-Sncotqwo2w4Aj1FAQ/1VW9VXO0Y=", + "dev": true + }, + "timers-browserify": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz", + "integrity": "sha1-ycWLV1voQHN1y14kYtrO50NZ9B0=", + "dev": true, + "requires": { + "process": "0.11.10" + } + }, + "to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", + "dev": true + }, + "tough-cookie": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", + "integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=", + "dev": true, + "requires": { + "punycode": "1.4.1" + } + }, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "dev": true + }, + "tryit": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tryit/-/tryit-1.0.3.tgz", + "integrity": "sha1-OTvnMKlEb9Hq1tpZoBQwjzbCics=", + "dev": true + }, + "tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", + "dev": true + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true, + "optional": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "1.1.2" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "uglify-js": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.6.4.tgz", + "integrity": "sha1-ZeovswWck5RpLxX+2HwrNsFrmt8=", + "dev": true, + "requires": { + "async": "0.2.10", + "source-map": "0.5.7", + "uglify-to-browserify": "1.0.2", + "yargs": "3.10.0" + }, + "dependencies": { + "async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", + "dev": true + } + } + }, + "uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "dev": true + }, + "umd": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/umd/-/umd-3.0.1.tgz", + "integrity": "sha1-iuVW4RAR9jwllnCKiDclnwGz1g4=", + "dev": true + }, + "underscore": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz", + "integrity": "sha1-a7rwh3UA02vjTsqlhODbn+8DUgk=", + "dev": true + }, + "underscore.string": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.2.1.tgz", + "integrity": "sha1-18D6KvXVoaZ/QlPa7pgTLnM/Dxk=", + "dev": true + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true + }, + "uri-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/uri-path/-/uri-path-1.0.0.tgz", + "integrity": "sha1-l0fwGDWJM8Md4PzP2C0TjmcmLjI=", + "dev": true + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + } + } + }, + "user-home": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz", + "integrity": "sha1-nHC/2Babwdy/SGBODwS4tJzenp8=", + "dev": true, + "requires": { + "os-homedir": "1.0.2" + } + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "requires": { + "inherits": "2.0.1" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + } + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "dev": true + }, + "uuid": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", + "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", + "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", + "dev": true, + "requires": { + "spdx-correct": "1.0.2", + "spdx-expression-parse": "1.0.4" + } + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "1.3.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "vm-browserify": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", + "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", + "dev": true, + "requires": { + "indexof": "0.0.1" + } + }, + "watchify": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/watchify/-/watchify-3.9.0.tgz", + "integrity": "sha1-8HX9LoqGrN6Eztum5cKgvt1SPZ4=", + "dev": true, + "requires": { + "anymatch": "1.3.2", + "browserify": "14.4.0", + "chokidar": "1.7.0", + "defined": "1.0.0", + "outpipe": "1.1.1", + "through2": "2.0.3", + "xtend": "4.0.1" + } + }, + "when": { + "version": "3.7.8", + "resolved": "https://registry.npmjs.org/when/-/when-3.7.8.tgz", + "integrity": "sha1-xxMLan6gRpPoQs3J56Hyqjmjn4I=", + "dev": true + }, + "which": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/which/-/which-1.0.9.tgz", + "integrity": "sha1-RgwdoPgQED0DIam2M6+eV15kSG8=", + "dev": true + }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", + "dev": true + }, + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "write": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", + "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "dev": true, + "requires": { + "mkdirp": "0.5.1" + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "dev": true, + "requires": { + "camelcase": "1.2.1", + "cliui": "2.1.0", + "decamelize": "1.2.0", + "window-size": "0.1.0" + }, + "dependencies": { + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "dev": true + } + } + }, + "yauzl": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz", + "integrity": "sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU=", + "dev": true, + "requires": { + "fd-slicer": "1.0.1" + } + } + } +} diff --git a/package.json b/package.json index d506ad655..497c10fb5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "less", - "version": "2.7.3", + "version": "3.0.0", "description": "Leaner CSS", "homepage": "http://lesscss.org", "author": { @@ -34,7 +34,7 @@ }, "browser": "./dist/less.js", "engines": { - "node": ">=0.12" + "node": ">=4" }, "scripts": { "test": "grunt test" @@ -43,27 +43,32 @@ "errno": "^0.1.1", "graceful-fs": "^4.1.2", "image-size": "~0.5.0", - "mime": "^1.2.11", + "mime": "^1.4.1", "mkdirp": "^0.5.0", "promise": "^7.1.1", "source-map": "^0.5.3", "request": "2.81.0" }, "devDependencies": { - "diff": "^2.2.2", + "diff": "^3.2.0", + "git-rev": "^0.2.1", "grunt": "~0.4.5", "grunt-browserify": "^5.0.0", "grunt-contrib-clean": "^1.0.0", "grunt-contrib-concat": "^1.0.1", "grunt-contrib-connect": "^1.0.2", "grunt-contrib-jasmine": "^1.0.3", - "grunt-contrib-jshint": "^1.0.0", "grunt-contrib-uglify": "^1.0.1", - "grunt-jscs": "^2.8.0", - "grunt-saucelabs": "^8.6.2", + "grunt-eslint": "^19.0.0", + "grunt-saucelabs": "^9.0.0", "grunt-shell": "^1.3.0", + "import-module": "file:test/import-module", "jit-grunt": "^0.10.0", + "less-plugin-clean-css": "^1.5.1", + "performance-now": "^0.2.0", "phantomjs-prebuilt": "^2.1.7", + "phin": "^2.2.3", + "promise": "^7.1.1", "time-grunt": "^1.3.0" }, "keywords": [ @@ -92,5 +97,6 @@ "css less" ], "rawcurrent": "https://raw.github.com/less/less.js/v", - "sourcearchive": "https://github.com/less/less.js/archive/v" + "sourcearchive": "https://github.com/less/less.js/archive/v", + "dependencies": {} } diff --git a/test/browser/common.js b/test/browser/common.js index 887e9cc64..9fd69fffb 100644 --- a/test/browser/common.js +++ b/test/browser/common.js @@ -1,7 +1,42 @@ /* Add js reporter for sauce */ - jasmine.getEnv().addReporter(new jasmine.JSReporter2()); +jasmine.getEnv().defaultTimeoutInterval = 3000; + +// From https://github.com/axemclion/grunt-saucelabs/issues/109#issuecomment-166767282 +// (function () { +// var oldJSReport = window.jasmine.getJSReport; +// window.jasmine.getJSReport = function () { +// var results = oldJSReport(); +// if (results) { +// return { +// durationSec: results.durationSec, +// suites: removePassingTests(results.suites), +// passed: results.passed +// }; +// } else { +// return null; +// } +// }; + +// function removePassingTests (suites) { +// return suites.filter(specFailed) +// .map(mapSuite); +// } + +// function mapSuite (suite) { +// var result = {}; +// for (var s in suite) { +// result[s] = suite[s]; +// } +// result.specs = suite.specs.filter(specFailed); +// result.suites = removePassingTests(suite.suites); +// return result; +// } +// function specFailed (item) { +// return !item.passed; +// } +// })(); /* record log messages for testing */ var logMessages = []; @@ -44,15 +79,15 @@ less.loggers = [ } ]; -var testLessEqualsInDocument = function () { +testLessEqualsInDocument = function () { testLessInDocument(testSheet); }; -var testLessErrorsInDocument = function (isConsole) { +testLessErrorsInDocument = function (isConsole) { testLessInDocument(isConsole ? testErrorSheetConsole : testErrorSheet); }; -var testLessInDocument = function (testFunc) { +testLessInDocument = function (testFunc) { var links = document.getElementsByTagName('link'), typePattern = /^text\/(x-)?less$/; @@ -64,7 +99,7 @@ var testLessInDocument = function (testFunc) { } }; -var ieFormat = function(text) { +ieFormat = function(text) { var styleNode = document.createElement('style'); styleNode.setAttribute('type', 'text/css'); var headNode = document.getElementsByTagName('head')[0]; @@ -83,7 +118,7 @@ var ieFormat = function(text) { return transformedText; }; -var testSheet = function (sheet) { +testSheet = function (sheet) { it(sheet.id + " should match the expected output", function (done) { var lessOutputId = sheet.id.replace("original-", ""), expectedOutputId = "expected-" + lessOutputId, @@ -112,7 +147,7 @@ var testSheet = function (sheet) { }); }; -//TODO: do it cleaner - the same way as in css +// TODO: do it cleaner - the same way as in css function extractId(href) { return href.replace(/^[a-z-]+:\/+?[^\/]+/i, '') // Remove protocol & domain @@ -122,7 +157,7 @@ function extractId(href) { .replace(/\./g, ':'); // Replace dots with colons(for valid id) } -var waitFor = function (waitFunc) { +waitFor = function (waitFunc) { return new Promise(function (resolve) { var timeoutId = setInterval(function () { if (waitFunc()) { @@ -133,7 +168,7 @@ var waitFor = function (waitFunc) { }); }; -var testErrorSheet = function (sheet) { +testErrorSheet = function (sheet) { it(sheet.id + " should match an error", function (done) { var lessHref = sheet.href, id = "less-error-message:" + extractId(lessHref), @@ -147,7 +182,7 @@ var testErrorSheet = function (sheet) { actualErrorElement = document.getElementById(id); return actualErrorElement !== null; }).then(function () { - var innerText = (actualErrorElement.innerHTML + var innerText = (actualErrorElement.innerHTML .replace(/

    |<\/?p>||<\/a>|
      |<\/?pre( class="?[^">]*"?)?>|<\/li>|<\/?label>/ig, "") .replace(/<\/h3>/ig, " ") .replace(/
    • |<\/ul>|
      /ig, "\n")) @@ -155,34 +190,36 @@ var testErrorSheet = function (sheet) { // for IE8 .replace(/\r\n/g, "\n") .replace(/\. \nin/, ". in"); - actualErrorMsg = innerText + actualErrorMsg = innerText .replace(/\n\d+/g, function (lineNo) { return lineNo + " "; }) .replace(/\n\s*in /g, " in ") .replace(/\n{2,}/g, "\n") .replace(/\nStack Trace\n[\s\S]*/i, "") - .replace(/\n$/, ""); - errorFile + .replace(/\n$/, "") + .trim(); + errorFile .then(function (errorTxt) { errorTxt = errorTxt .replace(/\{path\}/g, "") .replace(/\{pathrel\}/g, "") .replace(/\{pathhref\}/g, "http://localhost:8081/test/less/errors/") .replace(/\{404status\}/g, " (404)") - .replace(/\{node\}.*\{\/node\}/g, "") - .replace(/\n$/, ""); + .replace(/\{node\}[\s\S]*\{\/node\}/g, "") + .replace(/\n$/, "") + .trim(); expect(actualErrorMsg).toEqual(errorTxt); if (errorTxt == actualErrorMsg) { actualErrorElement.style.display = "none"; } done(); }); - }); + }); }); }; -var testErrorSheetConsole = function (sheet) { +testErrorSheetConsole = function (sheet) { it(sheet.id + " should match an error", function (done) { var lessHref = sheet.href, id = sheet.id.replace(/^original-less:/, "less-error-message:"), @@ -211,7 +248,7 @@ var testErrorSheetConsole = function (sheet) { }); }; -var loadFile = function (href) { +loadFile = function (href) { return new Promise(function (resolve, reject) { var request = new XMLHttpRequest(); request.open('GET', href, true); diff --git a/test/browser/css/plugin/plugin.css b/test/browser/css/plugin/plugin.css new file mode 100644 index 000000000..270b73aba --- /dev/null +++ b/test/browser/css/plugin/plugin.css @@ -0,0 +1,3 @@ +.test { + val: http://localhost:8081/tmp/browser/test-runner-browser.html; +} diff --git a/test/browser/jasmine-jsreporter.js b/test/browser/jasmine-jsreporter.js index 0d5562999..9a14e32c7 100644 --- a/test/browser/jasmine-jsreporter.js +++ b/test/browser/jasmine-jsreporter.js @@ -42,7 +42,7 @@ * @param startMs Start time in Milliseconds * @param finishMs Finish time in Milliseconds * @return Elapsed time in Seconds */ - function elapsedSec (startMs, finishMs) { + function elapsedSec(startMs, finishMs) { return (finishMs - startMs) / 1000; } @@ -52,7 +52,7 @@ * @param amount Amount to round * @param numOfDecDigits Number of Digits to round to. Default value is '2'. * @return Rounded amount */ - function round (amount, numOfDecDigits) { + function round(amount, numOfDecDigits) { numOfDecDigits = numOfDecDigits || 2; return Math.round(amount * Math.pow(10, numOfDecDigits)) / Math.pow(10, numOfDecDigits); } @@ -61,7 +61,7 @@ * Create a new array which contains only the failed items. * @param items Items which will be filtered * @returns {Array} of failed items */ - function failures (items) { + function failures(items) { var fs = [], i, v; for (i = 0; i < items.length; i += 1) { v = items[i]; @@ -76,7 +76,7 @@ * Collect information about a Suite, recursively, and return a JSON result. * @param suite The Jasmine Suite to get data from */ - function getSuiteData (suite) { + function getSuiteData(suite) { var suiteData = { description : suite.description, durationSec : 0, diff --git a/test/browser/less/plugin/plugin.js b/test/browser/less/plugin/plugin.js new file mode 100644 index 000000000..8065d815c --- /dev/null +++ b/test/browser/less/plugin/plugin.js @@ -0,0 +1,7 @@ +registerPlugin({ + install: function(less, pluginManager, functions) { + functions.add('func', function() { + return less.anonymous(location.href); + }); + } +}); \ No newline at end of file diff --git a/test/browser/less/plugin/plugin.less b/test/browser/less/plugin/plugin.less new file mode 100644 index 000000000..159a5a899 --- /dev/null +++ b/test/browser/less/plugin/plugin.less @@ -0,0 +1,4 @@ +@plugin "plugin"; +.test { + val: func(); +} diff --git a/test/browser/runner-browser-options.js b/test/browser/runner-browser-options.js index 64037bbb0..8eb2f1e7d 100644 --- a/test/browser/runner-browser-options.js +++ b/test/browser/runner-browser-options.js @@ -1,4 +1,9 @@ -var less = {logLevel: 4, errorReporting: "console"}; +var less = { + logLevel: 4, + errorReporting: "console", + javascriptEnabled: true, + strictMath: false +}; // There originally run inside describe method. However, since they have not // been inside it, they run at jasmine compile time (not runtime). It all diff --git a/test/browser/runner-errors-options.js b/test/browser/runner-errors-options.js index 8ba00e27d..97b211d93 100644 --- a/test/browser/runner-errors-options.js +++ b/test/browser/runner-errors-options.js @@ -1,4 +1,6 @@ var less = { strictUnits: true, strictMath: true, - logLevel: 4 }; + logLevel: 4, + javascriptEnabled: true +}; diff --git a/test/browser/runner-filemanagerPlugin-options.js b/test/browser/runner-filemanagerPlugin-options.js index 588fbb046..ecf54da68 100644 --- a/test/browser/runner-filemanagerPlugin-options.js +++ b/test/browser/runner-filemanagerPlugin-options.js @@ -1,4 +1,5 @@ -var less = {logLevel: 4, +var less = { + logLevel: 4, errorReporting: "console", plugins: [AddFilePlugin] - }; +}; diff --git a/test/browser/runner-legacy-options.js b/test/browser/runner-legacy-options.js index ed93fbd4c..4f8528d67 100644 --- a/test/browser/runner-legacy-options.js +++ b/test/browser/runner-legacy-options.js @@ -2,4 +2,5 @@ var less = { logLevel: 4, errorReporting: "console", strictMath: false, - strictUnits: false }; + strictUnits: false +}; diff --git a/test/browser/runner-main-options.js b/test/browser/runner-main-options.js index c0008334a..5c2287567 100644 --- a/test/browser/runner-main-options.js +++ b/test/browser/runner-main-options.js @@ -2,7 +2,6 @@ var less = { logLevel: 4, errorReporting: "console" }; -less.strictMath = true; less.functions = { add: function(a, b) { return new(less.tree.Dimension)(a.value + b.value); diff --git a/test/browser/runner-modify-vars-spec.js b/test/browser/runner-modify-vars-spec.js index 09cfe7a2e..c7ed80bd8 100644 --- a/test/browser/runner-modify-vars-spec.js +++ b/test/browser/runner-modify-vars-spec.js @@ -17,8 +17,8 @@ describe("less.js modify vars", function () { var2: "purple", scale: 20 }).then(function () { - done(); - }); + done(); + }); }); }); diff --git a/test/browser/runner-postProcessor-options.js b/test/browser/runner-postProcessor-options.js deleted file mode 100644 index fe7111b69..000000000 --- a/test/browser/runner-postProcessor-options.js +++ /dev/null @@ -1,5 +0,0 @@ -var less = {logLevel: 4, - errorReporting: "console"}; -less.postProcessor = function(styles) { - return 'hr {height:50px;}\n' + styles; -}; diff --git a/test/browser/runner-postProcessor.js b/test/browser/runner-postProcessor.js deleted file mode 100644 index 64937669f..000000000 --- a/test/browser/runner-postProcessor.js +++ /dev/null @@ -1,3 +0,0 @@ -describe("less.js postProcessor (deprecated)", function() { - testLessEqualsInDocument(); -}); diff --git a/test/browser/test-runner-template.tmpl b/test/browser/test-runner-template.tmpl index c02c38f30..ffaf05d9a 100644 --- a/test/browser/test-runner-template.tmpl +++ b/test/browser/test-runner-template.tmpl @@ -2,6 +2,27 @@ + + Jasmine Spec Runner @@ -57,27 +78,29 @@ document.body.appendChild(script); }; - - // allow sauce to query for the jasmine report - // because we have to load the page before starting the test, so the thing - // sauce queries for might not be setup yet - window.jasmine = { getJSReport: function() { } }; - setTimeout(function() { - var jasmine = <% toArray([].concat(scripts.polyfills, scripts.jasmine, scripts.boot)) %>, + var jasmine = <% toArray([].concat(scripts.polyfills, scripts.jasmine, scripts.boot)) %>, helpers = <% toArray(scripts.helpers) %>, vendor = <% toArray(scripts.vendor) %>, specs = <% toArray(scripts.specs) %>, reporters = <% toArray([].concat(scripts.reporters)) %>, - allScripts = jasmine.concat(helpers).concat(vendor).concat(specs).concat(reporters); + setupScripts = jasmine.concat(helpers).concat(vendor), + runScripts = specs.concat(reporters); + + + <% generateScriptTags(scripts.polyfills); %> + <% generateScriptTags(scripts.jasmine); %> + <% generateScriptTags(scripts.boot); %> + <% generateScriptTags(scripts.helpers); %> + <% generateScriptTags(scripts.vendor); %> + +