diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..aa5855a8 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,13 @@ +# @see http://editorconfig.org/ + +# the buck stops here +root = true + +# all files +[*] +end_of_line = LF +indent_style = space +indent_size = 4 +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 00000000..ba399023 --- /dev/null +++ b/.eslintignore @@ -0,0 +1 @@ +Gruntfile.js \ No newline at end of file diff --git a/.eslintrc.json b/.eslintrc.json index 754c3845..6a9e809e 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -3,11 +3,8 @@ "node": true }, "globals": {}, + "rules": { - "quotes": [ - 1, - "single" - ], "no-eval": 2, "no-use-before-define": [ 2, diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 00000000..9f53f9f4 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,16 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "launch", + "name": "Less test", + "program": "${workspaceFolder}/test/index.js", + "cwd": "${workspaceFolder}", + "console": "integratedTerminal" + } + ] +} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index a84aa210..035445aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,50 @@ +## 3.5.3 + +2018-07-06 + - Reverts @media eval change + - Other bug fixes + +## 3.5.0 + +2018-07-05 + - Feature: Namespaced Values / Maps e.g. `color: @color[primary]` + - Fixes to calc() + - Permissive parsing of custom properties and variables + - Inline expressions now not evaluated in at-rules `@media (min-width: @var) {}` works, `@media (min-width: @var + 1) {}` will not + - Allows unnamed lookups i.e. "functions" e.g. `.mixin(@a, @b)[]` + - Lots of bug fixes + +## 3.5.0-beta.4 + +2018-06-30 + - Fixes #3235, #3187 + - Feature: Namespaced Values e.g. `color: #color[primary]` + +## 3.5.0-beta.3 + +2018-06-29 + - Fix: browser cache is always considered stale if .modifyVars wasn't + +## 3.5.0-beta.2 + +2018-06-27 + - Re-parses selectors after variables in selectors are evaluated - Fixes #1421 + - Fixes #3191 + +## 3.5.0-beta + +2018-06-24 + - Adds permissive parsing for at-rules and custom properties - fixes #3147 #2715 + - Updates dependencies + - Fixes file caching issue (not reloading modified files in "watched" environments) + ## 3.0.4 + 2018-05-06 - Update source-map to 0.6.x (#3180). Enforces node 6+ though. -# 3.0.0 +## 3.0.0 + 2018-02-10 - Fix `calc()` function to not do math operations on compile - Rename Directive -> AtRule & Rule -> Declaration @@ -17,25 +59,27 @@ - Bug fixes - Removal of unnecessary nodes from API (like IE's `alpha()`) -# 2.7.3 +## 2.7.3 + 2017-10-23 - Bump `request` dependency -# 2.7.2 +## 2.7.2 + 2017-01-04 - Revert breaking changes to contrast() function - Fix error reporting of lessc executable - Changed octals to hex for ES6 strict mode -# 2.7.1 HOTFIX +## 2.7.1 HOTFIX 2016-05-09 - Revert commit 470af20 (source map performance) which broke source maps -# 2.7.0 +## 2.7.0 2016-05-07 @@ -48,7 +92,7 @@ - Fix AST to include single-line comments - Fix reversion for "color-like" words (outputting color values) -# 2.6.1 +## 2.6.1 2016-03-04 @@ -57,7 +101,7 @@ - use instanceof operator instead of class comparison optimization - disallow whitespace in variable calls -# 2.6.0 +## 2.6.0 2016-01-29 @@ -72,13 +116,13 @@ - Logical operator ```and``` now has higher precedence than logical operator ```or```. - Allow unknown at-rules w/o {} block -# 2.5.3 +## 2.5.3 2015-09-25 - Fix import inline a URL -# 2.5.2 +## 2.5.2 2015-09-24 @@ -89,7 +133,7 @@ - Fixed mixin definition matching problem when mixin definition contains parameters with default values - Observe reference for imported comments -# 2.5.1 +## 2.5.1 2015-05-21 @@ -97,7 +141,7 @@ - Minor fix only likely to affect programmatic usage of ruleset find - Fix error when a namespaced mixin is invoked in global scope -# 2.5.0 +## 2.5.0 2015-04-03 @@ -118,7 +162,7 @@ - consistently keep units if strict units is off - Better support for comments in function all arguments -# 2.4.0 +## 2.4.0 2015-02-07 @@ -132,14 +176,14 @@ - Files with just `\r` newlines now process ok (regression in 2.0.0) - When strict units is off and the unit is 1/x, (e.g. 1 / 12px) the unit output is x, previously nothing (regression in 2.0.0) -# 2.3.1 +## 2.3.1 2015-01-28 - Fix depends option (regression in 2.3.0) - Support parent selector (`&`) used in sub element expression (e.g. `:not(.c_&)`) -# 2.3.0 +## 2.3.0 2015-01-27 @@ -157,7 +201,7 @@ - Unicode BOM removed again - Misc. bug fixes -# 2.2.0 +## 2.2.0 2015-01-04 @@ -177,14 +221,14 @@ - support safari extension - less.parse now exposes a way to get the AST. We do not recommend you use this unless you need to. -# 2.1.2 +## 2.1.2 2014-12-20 - Fix for use with requirejs - Fixes for data-uri function -# 2.1.1 +## 2.1.1 2014-11-27 @@ -193,7 +237,7 @@ - Fix problem with plugins when used with the promises version of render - If the render callback throws an exception it now propagates instead of calling the callback again with an error -# 2.1.0 +## 2.1.0 2014-11-23 @@ -208,7 +252,7 @@ - livereload cache buster is now treated specially - upgrade dependencies -# 2.0.0 +## 2.0.0 2014-11-09 @@ -219,7 +263,7 @@ - fixed some local variable spellings - support for `@counter-style` directive -# 2.0.0-b3 +## 2.0.0-b3 2014-11-01 @@ -228,7 +272,7 @@ - browser can now be scoped with just window - browser `useFileCache` defaults to `true`, but file cache is now cleared when refreshing or in watch mode -# 2.0.0-b2 +## 2.0.0-b2 2014-10-26 @@ -240,7 +284,7 @@ - Fixed a bug where unquoted urls beginning `//` e.g. `url(//file/file.less)` would be incorrectly interpreted (bug introduced in b-1) - lessc plugins can be a function, used as a constructor as well as an object - this to allow the plugin more flexibility to be used programattically -# 2.0.0-b1 +## 2.0.0-b1 2014-10-19 @@ -261,7 +305,7 @@ - default values for the sourcemap options have been re-done and improved to hopefully mean creating sourcemaps is easier - Many smaller bugfixes and API changes. Please let us know if something you relied on has disappeared or an area should be better documented. -# 1.7.5 +## 1.7.5 2014-09-03 @@ -274,7 +318,7 @@ - Fix interpolated import in media query - A few other various small corrections -# 1.7.4 +## 1.7.4 2014-07-27 @@ -286,7 +330,7 @@ - Better error message for imports missing semi-colons or malformed - Do not use util.print to avoid deprecate warnings in node 0.11 -# 1.7.3 +## 1.7.3 2014-06-22 @@ -294,14 +338,14 @@ - Do not round the results of color functions, like lightness, hue, luma etc. - Support cover and contain keywords in background definitions - # 1.7.2 + ## 1.7.2 2014-06-19 - Allow paths option to be a string (in 1.7.1 less started throwing an exception instead of incorrectly processing the string as an array of chars) - Do not round numbers when used with javascript (introduced 1.7.0) -# 1.7.1 +## 1.7.1 2014-06-08 @@ -319,7 +363,7 @@ - Fix the e() function when passed empty string - Several minor bug fixes -# 1.7.0 +## 1.7.0 2014-02-27 @@ -341,13 +385,13 @@ - Browser - added postProcessor option, a function called to post-process the css before adding to the page - Browser - use the right request for file access in IE -# 1.6.3 +## 1.6.3 2014-02-08 - Fix issue with calling toCSS twice not working in some situations (like with bootstrap 2) -# 1.6.2 +## 1.6.2 2014-02-02 @@ -362,7 +406,7 @@ - some improvements to the default() function in more complex scenarios - improved missing '{' and '(' detection -# 1.6.1 +## 1.6.1 2014-01-12 @@ -375,7 +419,7 @@ - use innerHTML in tests, not innerText - protect for-in in case Array and Object prototypes have custom fields -# 1.6.0 +## 1.6.0 2014-01-01 @@ -394,7 +438,7 @@ - Fixed error messages for undefined variables in javascript evaluation - Fixed line/column numbers from math errors -# 1.5.1 +## 1.5.1 2013-11-17 @@ -406,7 +450,7 @@ - correct a bug meaning imports weren't synchronous (syncImport option available for full synchronous behaviour) - better mixin matching behaviour with calling multiple classes e.g. .a.b.c; -# 1.5.0 +## 1.5.0 2013-10-21 @@ -432,7 +476,7 @@ - Now uses grunt for building and testing - A few bug fixes for media queries, extends, scoping, compression and import once. -# 1.4.2 +## 1.4.2 2013-07-20 @@ -441,7 +485,7 @@ - property names may include capital letters - various windows path fixes (capital letters, multiple // in a path) -# 1.4.1 +## 1.4.1 2013-07-05 @@ -449,20 +493,20 @@ - fixed several global variable leaks - handle getting null or undefined passed as the options object -# 1.4.0 +## 1.4.0 2013-06-05 - fix passing of strict maths option -# 1.4.0 Beta 4 +## 1.4.0 Beta 4 2013-05-04 - change strictMaths to strictMath. Enable this with --strict-math=on in lessc and strictMath:true in JavaScript. - change lessc option for strict units to --strict-units=off -# 1.4.0 Beta 3 +## 1.4.0 Beta 3 2013-04-30 @@ -474,7 +518,7 @@ - remove es-5-shim as standard from the browser - Fix path issues with windows/linux local paths -# 1.4.0 Beta 1 & 2 +## 1.4.0 Beta 1 & 2 2013-03-07 @@ -500,14 +544,14 @@ - support for namespaces in attributes and selector interpolation in attributes - other bug fixes -# 1.3.3 +## 1.3.3 2012-12-30 - Fix critical bug with mixin call if using multiple brackets - when using the filter contrast function, the function is passed through if the first argument is not a color -# 1.3.2 +## 1.3.2 2012-12-28 @@ -544,7 +588,7 @@ - sass debug statements are now chrome compatible - modifyVars function added to re-render with different root variables -# 1.3.1 +## 1.3.1 2012-10-18 @@ -569,7 +613,7 @@ - implement named parameters when calling mixins - many numerous bug fixes -# 1.3.0 +## 1.3.0 2012-03-10 @@ -587,7 +631,7 @@ - Fix a bug when using @media with mixins -# 1.2.1 +## 1.2.1 2012-01-15 @@ -597,7 +641,7 @@ - Fix `File not found` import error reporting -# 1.2.0 +## 1.2.0 2012-01-07 diff --git a/Gruntfile.js b/Gruntfile.js index c8bbde7a..22f8e25b 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -15,12 +15,12 @@ module.exports = function (grunt) { var browsers = [ // Desktop browsers { - browserName: "chrome", + browserName: 'chrome', version: 'latest', platform: 'Windows 7' }, { - browserName: "firefox", + browserName: 'firefox', version: 'latest', platform: 'Linux' }, @@ -30,17 +30,17 @@ module.exports = function (grunt) { platform: 'OS X 10.11' }, { - browserName: "internet explorer", + browserName: 'internet explorer', version: '8', platform: 'Windows XP' }, { - browserName: "internet explorer", + browserName: 'internet explorer', version: '11', platform: 'Windows 8.1' }, { - browserName: "edge", + browserName: 'edge', version: '13', platform: 'Windows 10' }, @@ -70,17 +70,17 @@ module.exports = function (grunt) { var sauceJobs = {}; - var browserTests = [ "filemanager-plugin", - "visitor-plugin", - "global-vars", - "modify-vars", - "production", - "rootpath-relative", - "rootpath", - "relative-urls", - "browser", - "no-js-errors", - "legacy" + var browserTests = [ 'filemanager-plugin', + 'visitor-plugin', + 'global-vars', + 'modify-vars', + 'production', + 'rootpath-relative', + 'rootpath', + 'relative-urls', + 'browser', + 'no-js-errors', + 'legacy' ]; function makeJob(testName) { @@ -88,16 +88,16 @@ module.exports = function (grunt) { options: { urls: testName === 'all' ? browserTests.map(function(name) { - return "http://localhost:8081/tmp/browser/test-runner-" + name + ".html"; + return 'http://localhost:8081/tmp/browser/test-runner-' + name + '.html'; }) : - ["http://localhost:8081/tmp/browser/test-runner-" + testName + ".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, + 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: { @@ -190,10 +190,13 @@ module.exports = function (grunt) { command: [ 'node bin/lessc --clean-css="--s1 --advanced" test/less/lazy-eval.less tmp/lazy-eval.css', 'cd lib', - 'node ../bin/lessc --clean-css="--s1 --advanced" ../test/less/lazy-eval.less ../tmp/lazy-eval.css' + 'node ../bin/lessc --clean-css="--s1 --advanced" ../test/less/lazy-eval.less ../tmp/lazy-eval.css', + 'cd ..', + // Test multiple plugins + 'node bin/lessc --plugin=clean-css="--s1 --advanced" --plugin=autoprefix="ie 11,Edge >= 13,Chrome >= 47,Firefox >= 45,iOS >= 9.2,Safari >= 9" test/less/lazy-eval.less tmp/lazy-eval.css' ].join(' && ') }, - "sourcemap-test": { + 'sourcemap-test': { command: [ 'node bin/lessc --source-map=test/sourcemaps/maps/import-map.map test/less/import.less test/sourcemaps/import.css', 'node bin/lessc --source-map test/less/sourcemaps/basic.less test/sourcemaps/basic.css' @@ -205,7 +208,7 @@ module.exports = function (grunt) { browser: { src: ['./lib/less-browser/bootstrap.js'], options: { - exclude: ["promise"], + exclude: ['promise'], browserifyOptions: { standalone: 'less' } @@ -265,15 +268,15 @@ module.exports = function (grunt) { }, eslint: { - target: ["Gruntfile.js", - "test/**/*.js", - "lib/less*/**/*.js", - "bin/lessc", - "!test/browser/jasmine-jsreporter.js", - "!test/less/errors/plugin/plugin-error.js" + target: ['Gruntfile.js', + 'test/**/*.js', + 'lib/less*/**/*.js', + 'bin/lessc', + '!test/browser/jasmine-jsreporter.js', + '!test/less/errors/plugin/plugin-error.js' ], options: { - configFile: ".eslintrc.json" + configFile: '.eslintrc.json' } }, @@ -295,7 +298,7 @@ module.exports = function (grunt) { main: { // src is used to build list of less files to compile src: [ - 'test/less/*.less', + 'test/less/plugin.less', // Don't test NPM import, obviously '!test/less/plugin-module.less', '!test/less/import-module.less', @@ -438,8 +441,8 @@ module.exports = function (grunt) { // Clean the version of less built for the tests clean: { test: ['test/browser/less.js', 'tmp', 'test/less-bom'], - "sourcemap-test": ['test/sourcemaps/*.css', 'test/sourcemaps/*.map'], - sauce_log: ["sc_*.log"] + 'sourcemap-test': ['test/sourcemaps/*.css', 'test/sourcemaps/*.map'], + sauce_log: ['sc_*.log'] } }); @@ -491,17 +494,17 @@ module.exports = function (grunt) { 'connect::keepalive' ]); - var previous_force_state = grunt.option("force"); + var previous_force_state = grunt.option('force'); - grunt.registerTask("force",function(set) { - if (set === "on") { - grunt.option("force",true); + grunt.registerTask('force',function(set) { + if (set === 'on') { + grunt.option('force',true); } - else if (set === "off") { - grunt.option("force",false); + else if (set === 'off') { + grunt.option('force',false); } - else if (set === "restore") { - grunt.option("force",previous_force_state); + else if (set === 'restore') { + grunt.option('force',previous_force_state); } }); @@ -527,10 +530,10 @@ module.exports = function (grunt) { if (isNaN(Number(process.env.TRAVIS_PULL_REQUEST, 10)) && 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"); + (process.env.TRAVIS_BRANCH === 'master' || process.env.TRAVIS_BRANCH === '3.x')) { + testTasks.push('force:on'); + testTasks.push('sauce-after-setup'); + testTasks.push('force:off'); } // Run all tests diff --git a/README.md b/README.md index 6cf60e6e..41a58540 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,10 @@ -[![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/master?svg=true)](https://ci.appveyor.com/project/lukeapage/less-js/branch/master) [![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) +

optionalDependency Status Twitter Follow

+ +


Chat with Less.js users and contributors

+ +

Sauce Test Status

# [Less.js](http://lesscss.org) diff --git a/bin/lessc b/bin/lessc index e19ad239..7360ff07 100755 --- a/bin/lessc +++ b/bin/lessc @@ -2,7 +2,7 @@ var path = require('path'), fs = require('../lib/less-node/fs'), - os = require("os"), + os = require('os'), utils = require('../lib/less/utils'), errno, mkdirp; @@ -37,20 +37,20 @@ var continueProcessing = true; // Additionally we also need to make sure that uncaughtExceptions are never swallowed. // @see https://github.com/less/less.js/issues/2881 // This code can safely be removed if node 0.10.x is not supported anymore. -process.on("exit", function() { process.reallyExit(process.exitCode); }); -process.on("uncaughtException", function(err) { +process.on('exit', function() { process.reallyExit(process.exitCode); }); +process.on('uncaughtException', function(err) { console.error(err); process.exitCode = 1; }); // This code will still be required because otherwise rejected promises would not be reported to the user -process.on("unhandledRejection", function(err) { +process.on('unhandledRejection', function(err) { console.error(err); process.exitCode = 1; }); var checkArgFunc = function(arg, option) { if (!option) { - console.error(arg + " option requires a parameter"); + console.error(arg + ' option requires a parameter'); continueProcessing = false; process.exitCode = 1; return false; @@ -61,7 +61,7 @@ var checkArgFunc = function(arg, option) { var checkBooleanArg = function(arg) { var onOff = /^((on|t|true|y|yes)|(off|f|false|n|no))$/i.exec(arg); if (!onOff) { - console.error(" unable to parse " + arg + " as a boolean. use one of on/t/true/y/yes/off/f/false/n/no"); + console.error(' unable to parse ' + arg + ' as a boolean. use one of on/t/true/y/yes/off/f/false/n/no'); continueProcessing = false; process.exitCode = 1; return false; @@ -102,15 +102,15 @@ function render() { sourceMapOptions.sourceMapInputFilename = input; if (!sourceMapOptions.sourceMapFullFilename) { if (!output && !sourceMapFileInline) { - console.error("the sourcemap option only has an optional filename if the css filename is given"); - console.error("consider adding --source-map-map-inline which embeds the sourcemap into the css"); + console.error('the sourcemap option only has an optional filename if the css filename is given'); + console.error('consider adding --source-map-map-inline which embeds the sourcemap into the css'); process.exitCode = 1; return; } // its in the same directory, so always just the basename if (output) { sourceMapOptions.sourceMapOutputFilename = path.basename(output); - sourceMapOptions.sourceMapFullFilename = output + ".map"; + sourceMapOptions.sourceMapFullFilename = output + '.map'; } // its in the same directory, so always just the basename if ('sourceMapFullFilename' in sourceMapOptions) { @@ -142,8 +142,8 @@ function render() { if (!input) { - console.error("lessc: no input files"); - console.error(""); + console.error('lessc: no input files'); + console.error(''); printUsage(); process.exitCode = 1; return; @@ -165,25 +165,25 @@ function render() { if (options.depends) { if (!outputbase) { - console.error("option --depends requires an output path to be specified"); + console.error('option --depends requires an output path to be specified'); process.exitCode = 1; return; } - process.stdout.write(outputbase + ": "); + process.stdout.write(outputbase + ': '); } if (!sourceMapFileInline) { var writeSourceMap = function(output, onDone) { - output = output || ""; + output = output || ''; var filename = sourceMapOptions.sourceMapFullFilename; ensureDirectory(filename); fs.writeFile(filename, output, 'utf8', function (err) { if (err) { - var description = "Error: "; + var description = 'Error: '; if (errno && errno.errno[err.errno]) { description += errno.errno[err.errno].description; } else { - description += err.code + " " + err.message; + description += err.code + ' ' + err.message; } console.error('lessc: failed to create file ' + filename); console.error(description); @@ -211,11 +211,11 @@ function render() { ensureDirectory(output); fs.writeFile(output, result.css, {encoding: 'utf8'}, function (err) { if (err) { - var description = "Error: "; + var description = 'Error: '; if (errno && errno.errno[err.errno]) { description += errno.errno[err.errno].description; } else { - description += err.code + " " + err.message; + description += err.code + ' ' + err.message; } console.error('lessc: failed to create file ' + output); console.error(description); @@ -233,9 +233,9 @@ function render() { var logDependencies = function(options, result) { if (options.depends) { - var depends = ""; + var depends = ''; for (var i = 0; i < result.imports.length; i++) { - depends += result.imports[i] + " "; + depends += result.imports[i] + ' '; } console.log(depends); } @@ -243,7 +243,7 @@ function render() { var parseLessFile = function (e, data) { if (e) { - console.error("lessc: " + e.message); + console.error('lessc: ' + e.message); process.exitCode = 1; return; } @@ -320,8 +320,8 @@ 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"); + 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) { @@ -368,7 +368,7 @@ function processPluginQueue() { switch (arg) { case 'v': case 'version': - console.log("lessc " + less.version.join('.') + " (Less Compiler) [JavaScript]"); + console.log('lessc ' + less.version.join('.') + ' (Less Compiler) [JavaScript]'); continueProcessing = false; break; case 'verbose': @@ -475,23 +475,23 @@ function processPluginQueue() { options.rootpath = match[2].replace(/\\/g, '/'); } break; - case "ru": - case "relative-urls": + case 'ru': + case 'relative-urls': options.relativeUrls = true; break; - case "sm": - case "strict-math": + case 'sm': + case 'strict-math': if (checkArgFunc(arg, match[2])) { options.strictMath = checkBooleanArg(match[2]); } break; - case "su": - case "strict-units": + case 'su': + case 'strict-units': if (checkArgFunc(arg, match[2])) { options.strictUnits = checkBooleanArg(match[2]); } break; - case "global-var": + case 'global-var': if (checkArgFunc(arg, match[2])) { if (!options.globalVars) { options.globalVars = {}; @@ -499,7 +499,7 @@ function processPluginQueue() { parseVariableOption(match[2], options.globalVars); } break; - case "modify-var": + case 'modify-var': if (checkArgFunc(arg, match[2])) { if (!options.modifyVars) { options.modifyVars = {}; diff --git a/dist/less.js b/dist/less.js index 3a957942..6f9c3d6f 100644 --- a/dist/less.js +++ b/dist/less.js @@ -1,5 +1,5 @@ /*! - * Less - Leaner CSS v3.0.4 + * Less - Leaner CSS v3.5.3 * http://lesscss.org * * Copyright (c) 2009-2018, Alexis Sellier @@ -10,9 +10,9 @@ /** * @license Apache-2.0 */ -(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.less = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i // Browsers have good Promise support -require("promise/polyfill"); +require('promise/polyfill'); var options = require('../less/default-options')(); @@ -82,7 +83,7 @@ if (window.less) { } } } -require("./add-default-options")(window, options); +require('./add-default-options')(window, options); options.plugins = options.plugins || []; @@ -90,7 +91,7 @@ if (window.LESS_PLUGINS) { options.plugins = options.plugins.concat(window.LESS_PLUGINS); } -var less = module.exports = require("./index")(window, options); +var less = module.exports = require('./index')(window, options); window.less = less; @@ -129,8 +130,8 @@ if (options.onReady) { less.pageLoadFinished = less.refresh(less.env === 'development').then(resolveOrReject, resolveOrReject); } -},{"../less/default-options":16,"./add-default-options":1,"./index":8,"promise/polyfill":100}],3:[function(require,module,exports){ -var utils = require("./utils"); +},{"../less/default-options":16,"./add-default-options":1,"./index":8,"promise/polyfill":101}],3:[function(require,module,exports){ +var utils = require('./utils'); module.exports = { createCSS: function (document, styles, sheet) { // Strip the query-string @@ -182,14 +183,14 @@ module.exports = { try { styleNode.styleSheet.cssText = styles; } catch (e) { - throw new Error("Couldn't reassign styleSheet.cssText."); + throw new Error('Couldn\'t reassign styleSheet.cssText.'); } } }, currentScript: function(window) { var document = window.document; return document.currentScript || (function() { - var scripts = document.getElementsByTagName("script"); + var scripts = document.getElementsByTagName('script'); return scripts[scripts.length - 1]; })(); } @@ -227,11 +228,12 @@ module.exports = function(window, options, logger) { vars = cache && cache.getItem(path + ':vars'); modifyVars = modifyVars || {}; + vars = vars || "{}"; // if not set, treat as the JSON representation of an empty object if (timestamp && webInfo.lastModified && (new Date(webInfo.lastModified).valueOf() === new Date(timestamp).valueOf()) && - (!modifyVars && !vars || JSON.stringify(modifyVars) === vars)) { + JSON.stringify(modifyVars) === vars) { // Use local copy return css; } @@ -240,23 +242,23 @@ module.exports = function(window, options, logger) { }; },{}],5:[function(require,module,exports){ -var utils = require("./utils"), - browser = require("./browser"); +var utils = require('./utils'), + browser = require('./browser'); module.exports = function(window, less, options) { function errorHTML(e, rootHref) { - var id = 'less-error-message:' + utils.extractId(rootHref || ""); + var id = 'less-error-message:' + utils.extractId(rootHref || ''); var template = '
  • {content}
  • '; var elem = window.document.createElement('div'), timer, content, errors = []; var filename = e.filename || rootHref; var filenameNoPath = filename.match(/([^\/]+(\?.*)?)$/)[1]; elem.id = id; - elem.className = "less-error-message"; + elem.className = 'less-error-message'; - content = '

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

    ' + '

    in ' + filenameNoPath + " "; + content = '

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

    ' + '

    in ' + filenameNoPath + ' '; var errorline = function (e, i, classname) { if (e.extract[i] !== undefined) { @@ -319,15 +321,15 @@ module.exports = function(window, less, options) { ].join('\n'), { title: 'error-message' }); elem.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" + '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(';'); if (options.env === 'development') { @@ -358,12 +360,12 @@ module.exports = function(window, less, options) { } function removeError(path) { - if (!options.errorReporting || options.errorReporting === "html") { + if (!options.errorReporting || options.errorReporting === 'html') { removeErrorHTML(path); - } else if (options.errorReporting === "console") { + } else if (options.errorReporting === 'console') { removeErrorConsole(path); } else if (typeof options.errorReporting === 'function') { - options.errorReporting("remove", path); + options.errorReporting('remove', path); } } @@ -371,8 +373,8 @@ module.exports = function(window, less, options) { var template = '{line} {content}'; 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; + var content = (e.type || 'Syntax') + 'Error: ' + (e.message || 'There is an error in your .less file') + + ' in ' + filename; var errorline = function (e, i, classname) { if (e.extract[i] !== undefined) { @@ -396,12 +398,12 @@ module.exports = function(window, less, options) { } function error(e, rootHref) { - if (!options.errorReporting || options.errorReporting === "html") { + if (!options.errorReporting || options.errorReporting === 'html') { errorHTML(e, rootHref); - } else if (options.errorReporting === "console") { + } else if (options.errorReporting === 'console') { errorConsole(e, rootHref); } else if (typeof options.errorReporting === 'function') { - options.errorReporting("add", e, rootHref); + options.errorReporting('add', e, rootHref); } } @@ -416,7 +418,7 @@ module.exports = function(window, less, options) { module.exports = function(options, logger) { - var AbstractFileManager = require("../less/environment/abstract-file-manager.js"); + var AbstractFileManager = require('../less/environment/abstract-file-manager.js'); var fileCache = {}; @@ -443,7 +445,7 @@ module.exports = function(options, logger) { if (typeof xhr.overrideMimeType === 'function') { xhr.overrideMimeType('text/css'); } - logger.debug("XHR: Getting '" + url + "'"); + logger.debug('XHR: Getting \'' + url + '\''); xhr.open('GET', url, async); xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5'); xhr.send(null); @@ -451,7 +453,7 @@ module.exports = function(options, logger) { function handleResponse(xhr, callback, errback) { if (xhr.status >= 200 && xhr.status < 300) { callback(xhr.responseText, - xhr.getResponseHeader("Last-Modified")); + xhr.getResponseHeader('Last-Modified')); } else if (typeof errback === 'function') { errback(xhr.status, url); } @@ -505,7 +507,7 @@ module.exports = function(options, logger) { 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 reject({ filename: href, message: 'Error loading file ' + href + ' error was ' + e.message }); } } @@ -516,7 +518,7 @@ module.exports = function(options, logger) { // 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 }); + reject({ type: 'File', message: '\'' + url + '\' wasn\'t found (' + status + ')', href: href }); }); }); }; @@ -527,25 +529,25 @@ module.exports = function(options, logger) { },{"../less/environment/abstract-file-manager.js":17}],7:[function(require,module,exports){ module.exports = function() { - var functionRegistry = require("./../less/functions/function-registry"); + var functionRegistry = require('./../less/functions/function-registry'); function imageSize() { throw { - type: "Runtime", - message: "Image size functions are not supported in browser version of less" + type: 'Runtime', + message: 'Image size functions are not supported in browser version of less' }; } var imageFunctions = { - "image-size": function(filePathNode) { + 'image-size': function(filePathNode) { imageSize(this, filePathNode); return -1; }, - "image-width": function(filePathNode) { + 'image-width': function(filePathNode) { imageSize(this, filePathNode); return -1; }, - "image-height": function(filePathNode) { + 'image-height': function(filePathNode) { imageSize(this, filePathNode); return -1; } @@ -559,8 +561,8 @@ module.exports = function() { // index.js // Should expose the additional browser functions on to the less object // -var addDataAttr = require("./utils").addDataAttr, - browser = require("./browser"); +var addDataAttr = require('./utils').addDataAttr, + browser = require('./browser'); module.exports = function(window, options) { var document = window.document; @@ -568,15 +570,15 @@ module.exports = function(window, options) { less.options = options; var environment = less.environment, - FileManager = require("./file-manager")(options, less.logger), + FileManager = require('./file-manager')(options, less.logger), fileManager = new FileManager(); environment.addFileManager(fileManager); less.FileManager = FileManager; - less.PluginLoader = require("./plugin-loader"); + 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('./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 - Deprecate? @@ -616,7 +618,7 @@ module.exports = function(window, options) { less.render(lessText, instanceOptions, bind(function(style, e, result) { if (e) { - errors.add(e, "inline"); + errors.add(e, 'inline'); } else { style.type = 'text/css'; if (style.styleSheet) { @@ -779,7 +781,7 @@ module.exports = function(window, options) { endTime = new Date(); totalMilliseconds = endTime - startTime; - less.logger.info("Less has finished and no sheets were loaded."); + less.logger.info('Less has finished and no sheets were loaded.'); resolve({ startTime: startTime, endTime: endTime, @@ -796,12 +798,12 @@ module.exports = function(window, options) { return; } if (webInfo.local) { - less.logger.info("Loading " + sheet.href + " from cache."); + less.logger.info('Loading ' + sheet.href + ' from cache.'); } else { - less.logger.info("Rendered " + sheet.href + " successfully."); + less.logger.info('Rendered ' + sheet.href + ' successfully.'); } browser.createCSS(window.document, css, sheet); - less.logger.info("CSS for " + sheet.href + " generated in " + (new Date() - endTime) + 'ms'); + less.logger.info('CSS for ' + sheet.href + ' generated in ' + (new Date() - endTime) + 'ms'); // Count completed sheet remainingSheets--; @@ -809,7 +811,7 @@ module.exports = function(window, options) { // Check if the last remaining sheet was processed and then call the promise if (remainingSheets === 0) { totalMilliseconds = new Date() - startTime; - less.logger.info("Less has finished. CSS generated in " + totalMilliseconds + 'ms'); + less.logger.info('Less has finished. CSS generated in ' + totalMilliseconds + 'ms'); resolve({ startTime: startTime, endTime: endTime, @@ -876,17 +878,16 @@ module.exports = function(less, options) { },{}],10:[function(require,module,exports){ // TODO: Add tests for browser @plugin -/*global window */ +/* global window */ -var AbstractPluginLoader = require("../less/environment/abstract-plugin-loader.js"); +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; + // Should we shim this.require for browser? Probably not? }; PluginLoader.prototype = new AbstractPluginLoader(); @@ -914,7 +915,7 @@ module.exports = { addDataAttr: function(options, tag) { for (var opt in tag.dataset) { if (tag.dataset.hasOwnProperty(opt)) { - if (opt === "env" || opt === "dumpLineNumbers" || opt === "rootpath" || opt === "errorReporting") { + if (opt === 'env' || opt === 'dumpLineNumbers' || opt === 'rootpath' || opt === 'errorReporting') { options[opt] = tag.dataset[opt]; } else { try { @@ -966,7 +967,7 @@ var parseCopyProperties = [ contexts.Parse = function(options) { copyFromOriginal(options, this, parseCopyProperties); - if (typeof this.paths === "string") { this.paths = [this.paths]; } + if (typeof this.paths === 'string') { this.paths = [this.paths]; } }; var evalCopyProperties = [ @@ -986,12 +987,27 @@ var evalCopyProperties = [ contexts.Eval = function(options, frames) { copyFromOriginal(options, this, evalCopyProperties); - if (typeof this.paths === "string") { this.paths = [this.paths]; } + if (typeof this.paths === 'string') { this.paths = [this.paths]; } this.frames = frames || []; this.importantScope = this.importantScope || []; }; +contexts.Eval.prototype.enterCalc = function () { + if (!this.calcStack) { + this.calcStack = []; + } + this.calcStack.push(true); + this.inCalc = true; +}; + +contexts.Eval.prototype.exitCalc = function () { + this.calcStack.pop(); + if (!this.calcStack) { + this.inCalc = false; + } +}; + contexts.Eval.prototype.inParenthesis = function () { if (!this.parensStack) { this.parensStack = []; @@ -1003,6 +1019,7 @@ contexts.Eval.prototype.outOfParenthesis = function () { this.parensStack.pop(); }; +contexts.Eval.prototype.inCalc = false; contexts.Eval.prototype.mathOn = true; contexts.Eval.prototype.isMathOn = function () { if (!this.mathOn) { @@ -1017,17 +1034,17 @@ contexts.Eval.prototype.isPathRelative = function (path) { contexts.Eval.prototype.normalizePath = function( path ) { var - segments = path.split("/").reverse(), + segments = path.split('/').reverse(), segment; path = []; while (segments.length !== 0 ) { segment = segments.pop(); switch ( segment ) { - case ".": + case '.': break; - case "..": - if ((path.length === 0) || (path[path.length - 1] === "..")) { + case '..': + if ((path.length === 0) || (path[path.length - 1] === '..')) { path.push( segment ); } else { path.pop(); @@ -1039,7 +1056,7 @@ contexts.Eval.prototype.normalizePath = function( path ) { } } - return path.join("/"); + return path.join('/'); }; // todo - do the same for the toCSS ? @@ -1197,8 +1214,8 @@ module.exports = { }; },{}],14:[function(require,module,exports){ module.exports = { - colors: require("./colors"), - unitConversions: require("./unit-conversions") + colors: require('./colors'), + unitConversions: require('./unit-conversions') }; },{"./colors":13,"./unit-conversions":15}],15:[function(require,module,exports){ @@ -1303,7 +1320,7 @@ abstractFileManager.prototype.getPath = function (filename) { j = filename.lastIndexOf('\\'); } if (j < 0) { - return ""; + return ''; } return filename.slice(0, j + 1); }; @@ -1340,9 +1357,9 @@ abstractFileManager.prototype.pathDiff = function pathDiff(url, baseUrl) { var urlParts = this.extractUrlParts(url), baseUrlParts = this.extractUrlParts(baseUrl), - i, max, urlDirectories, baseUrlDirectories, diff = ""; + i, max, urlDirectories, baseUrlDirectories, diff = ''; if (urlParts.hostPart !== baseUrlParts.hostPart) { - return ""; + return ''; } max = Math.max(baseUrlParts.directories.length, urlParts.directories.length); for (i = 0; i < max; i++) { @@ -1351,10 +1368,10 @@ abstractFileManager.prototype.pathDiff = function pathDiff(url, baseUrl) { baseUrlDirectories = baseUrlParts.directories.slice(i); urlDirectories = urlParts.directories.slice(i); for (i = 0; i < baseUrlDirectories.length - 1; i++) { - diff += "../"; + diff += '../'; } for (i = 0; i < urlDirectories.length - 1; i++) { - diff += urlDirectories[i] + "/"; + diff += urlDirectories[i] + '/'; } return diff; }; @@ -1371,31 +1388,31 @@ abstractFileManager.prototype.extractUrlParts = function extractUrlParts(url, ba returner = {}, rawDirectories = [], directories = [], i, baseUrlParts; if (!urlParts) { - throw new Error("Could not parse sheet href - '" + url + "'"); + throw new Error('Could not parse sheet href - \'' + url + '\''); } // Stylesheets in IE don't always return the full path if (baseUrl && (!urlParts[1] || urlParts[2])) { baseUrlParts = baseUrl.match(urlPartsRegex); if (!baseUrlParts) { - throw new Error("Could not parse page url - '" + baseUrl + "'"); + throw new Error('Could not parse page url - \'' + baseUrl + '\''); } - urlParts[1] = urlParts[1] || baseUrlParts[1] || ""; + urlParts[1] = urlParts[1] || baseUrlParts[1] || ''; if (!urlParts[2]) { urlParts[3] = baseUrlParts[3] + urlParts[3]; } } if (urlParts[3]) { - rawDirectories = urlParts[3].replace(/\\/g, "/").split("/"); + rawDirectories = urlParts[3].replace(/\\/g, '/').split('/'); // collapse '..' and skip '.' for (i = 0; i < rawDirectories.length; i++) { - if (rawDirectories[i] === "..") { + if (rawDirectories[i] === '..') { directories.pop(); } - else if (rawDirectories[i] !== ".") { + else if (rawDirectories[i] !== '.') { directories.push(rawDirectories[i]); } @@ -1404,31 +1421,27 @@ abstractFileManager.prototype.extractUrlParts = function extractUrlParts(url, ba returner.hostPart = urlParts[1]; returner.directories = directories; - returner.rawPath = (urlParts[1] || "") + rawDirectories.join("/"); - returner.path = (urlParts[1] || "") + directories.join("/"); + 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] || ""); + returner.fileUrl = returner.path + (urlParts[4] || ''); + returner.url = returner.fileUrl + (urlParts[5] || ''); return returner; }; module.exports = abstractFileManager; },{}],18:[function(require,module,exports){ -var functionRegistry = require("../functions/function-registry"), +var functionRegistry = require('../functions/function-registry'), LessError = require('../less-error'); var AbstractPluginLoader = function() { + // Implemented by Node.js plugin loader + this.require = function() { + return null; + } }; -function error(msg, type) { - throw new LessError( - { - type: type || 'Syntax', - message: msg - } - ); -} AbstractPluginLoader.prototype.evalPlugin = function(contents, context, imports, pluginOptions, fileInfo) { var loader, @@ -1436,12 +1449,13 @@ AbstractPluginLoader.prototype.evalPlugin = function(contents, context, imports, pluginObj, localModule, pluginManager, - filename; + filename, + result; pluginManager = context.pluginManager; if (fileInfo) { - if (typeof fileInfo === "string") { + if (typeof fileInfo === 'string') { filename = fileInfo; } else { @@ -1454,15 +1468,18 @@ AbstractPluginLoader.prototype.evalPlugin = function(contents, context, imports, pluginObj = pluginManager.get(filename); if (pluginObj) { - this.trySetOptions(pluginObj, filename, shortname, pluginOptions); + result = this.trySetOptions(pluginObj, filename, shortname, pluginOptions); + if (result) { + return result; + } 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); + e.message = e.message || 'Error during @plugin call'; + return new LessError(e, imports, filename); } return pluginObj; } @@ -1479,10 +1496,11 @@ AbstractPluginLoader.prototype.evalPlugin = function(contents, context, imports, }; 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); + loader = new Function('module', 'require', 'registerPlugin', 'functions', 'tree', 'less', 'fileInfo', contents); + loader(localModule, this.require(filename), registerPlugin, registry, this.less.tree, this.less, fileInfo); + } + catch (e) { + return new LessError(e, imports, filename); } if (!pluginObj) { @@ -1490,14 +1508,32 @@ AbstractPluginLoader.prototype.evalPlugin = function(contents, context, imports, } pluginObj = this.validatePlugin(pluginObj, filename, shortname); + if (pluginObj instanceof LessError) { + return pluginObj; + } + 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); + // For < 3.x (or unspecified minVersion) - setOptions() before install() + if (!pluginObj.minVersion || this.compareVersion('3.0.0', pluginObj.minVersion) < 0) { + result = this.trySetOptions(pluginObj, filename, shortname, pluginOptions); + + if (result) { + return result; + } + } + + // Run on first load + pluginManager.addPlugin(pluginObj, fileInfo.filename, registry); + pluginObj.functions = registry.getLocalFunctions(); + + // Need to call setOptions again because the pluginObj might have functions + result = this.trySetOptions(pluginObj, filename, shortname, pluginOptions); + if (result) { + return result; + } // Run every @plugin call try { @@ -1506,13 +1542,13 @@ AbstractPluginLoader.prototype.evalPlugin = function(contents, context, imports, } } catch (e) { - e.message = 'Error during @plugin call'; - return new this.less.LessError(e, imports, filename); + e.message = e.message || 'Error during @plugin call'; + return new LessError(e, imports, filename); } } else { - return new this.less.LessError({ message: "Not a valid plugin" }); + return new LessError({ message: 'Not a valid plugin' }, imports, filename); } return pluginObj; @@ -1520,18 +1556,17 @@ AbstractPluginLoader.prototype.evalPlugin = function(contents, context, imports, }; 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; - } + if (options && !plugin.setOptions) { + return new LessError({ + message: 'Options have been provided but the plugin ' + + name + ' does not support any options.' + }); + } + try { + plugin.setOptions && plugin.setOptions(options); + } + catch (e) { + return new LessError(e); } }; @@ -1539,14 +1574,16 @@ 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") { + 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 new LessError({ + message: 'Plugin ' + name + ' requires version ' + + this.versionToString(plugin.minVersion) + }); } } return plugin; @@ -1555,7 +1592,7 @@ AbstractPluginLoader.prototype.validatePlugin = function(plugin, filename, name) }; AbstractPluginLoader.prototype.compareVersion = function(aVersion, bVersion) { - if (typeof aVersion === "string") { + if (typeof aVersion === 'string') { aVersion = aVersion.match(/^(\d+)\.?(\d+)?\.?(\d+)?/); aVersion.shift(); } @@ -1567,9 +1604,9 @@ AbstractPluginLoader.prototype.compareVersion = function(aVersion, bVersion) { return 0; }; AbstractPluginLoader.prototype.versionToString = function(version) { - var versionString = ""; + var versionString = ''; for (var i = 0; i < version.length; i++) { - versionString += (versionString ? "." : "") + version[i]; + versionString += (versionString ? '.' : '') + version[i]; } return versionString; }; @@ -1591,12 +1628,12 @@ module.exports = AbstractPluginLoader; * environment, file managers, and plugin manager */ -var logger = require("../logger"); +var logger = require('../logger'); var environment = function(externalEnvironment, fileManagers) { this.fileManagers = fileManagers || []; externalEnvironment = externalEnvironment || {}; - var optionalFunctions = ["encodeBase64", "mimeLookup", "charsetLookup", "getSourceMapGenerator"], + var optionalFunctions = ['encodeBase64', 'mimeLookup', 'charsetLookup', 'getSourceMapGenerator'], requiredFunctions = [], functions = requiredFunctions.concat(optionalFunctions); @@ -1606,7 +1643,7 @@ var environment = function(externalEnvironment, fileManagers) { if (environmentFunc) { this[propName] = environmentFunc.bind(externalEnvironment); } else if (i < requiredFunctions.length) { - this.warn("missing required function in environment - " + propName); + this.warn('missing required function in environment - ' + propName); } } }; @@ -1614,10 +1651,10 @@ var environment = function(externalEnvironment, fileManagers) { environment.prototype.getFileManager = function (filename, currentDirectory, options, environment, isSync) { if (!filename) { - logger.warn("getFileManager called with no filename.. Please report this issue. continuing."); + logger.warn('getFileManager called with no filename.. Please report this issue. continuing.'); } if (currentDirectory == null) { - logger.warn("getFileManager called with null directory.. Please report this issue. continuing."); + logger.warn('getFileManager called with null directory.. Please report this issue. continuing.'); } var fileManagers = this.fileManagers; @@ -1626,7 +1663,7 @@ environment.prototype.getFileManager = function (filename, currentDirectory, opt } for (var i = fileManagers.length - 1; i >= 0 ; i--) { var fileManager = fileManagers[i]; - if (fileManager[isSync ? "supportsSync" : "supports"](filename, currentDirectory, options, environment)) { + if (fileManager[isSync ? 'supportsSync' : 'supports'](filename, currentDirectory, options, environment)) { return fileManager; } } @@ -1645,9 +1682,9 @@ module.exports = environment; },{"../logger":37}],20:[function(require,module,exports){ -var functionRegistry = require("./function-registry"), - Anonymous = require("../tree/anonymous"), - Keyword = require("../tree/keyword"); +var functionRegistry = require('./function-registry'), + Anonymous = require('../tree/anonymous'), + Keyword = require('../tree/keyword'); functionRegistry.addMultiple({ boolean: function(condition) { @@ -1661,8 +1698,8 @@ functionRegistry.addMultiple({ }); },{"../tree/anonymous":48,"../tree/keyword":68,"./function-registry":26}],21:[function(require,module,exports){ -var Color = require("../tree/color"), - functionRegistry = require("./function-registry"); +var Color = require('../tree/color'), + functionRegistry = require('./function-registry'); // Color Blending // ref: http://www.w3.org/TR/compositing-1 @@ -1737,11 +1774,11 @@ for (var f in colorBlendModeFunctions) { functionRegistry.addMultiple(colorBlend); },{"../tree/color":53,"./function-registry":26}],22:[function(require,module,exports){ -var Dimension = require("../tree/dimension"), - Color = require("../tree/color"), - Quoted = require("../tree/quoted"), - Anonymous = require("../tree/anonymous"), - functionRegistry = require("./function-registry"), +var Dimension = require('../tree/dimension'), + Color = require('../tree/color'), + Quoted = require('../tree/quoted'), + Anonymous = require('../tree/anonymous'), + functionRegistry = require('./function-registry'), colorFunctions; function clamp(val) { @@ -1757,8 +1794,8 @@ function number(n) { return n; } else { throw { - type: "Argument", - message: "color functions take numbers as parameters" + type: 'Argument', + message: 'color functions take numbers as parameters' }; } } @@ -1891,7 +1928,7 @@ colorFunctions = { } var hsl = color.toHSL(); - if (typeof method !== "undefined" && method.value === "relative") { + if (typeof method !== 'undefined' && method.value === 'relative') { hsl.s += hsl.s * amount.value / 100; } else { @@ -1903,7 +1940,7 @@ colorFunctions = { desaturate: function (color, amount, method) { var hsl = color.toHSL(); - if (typeof method !== "undefined" && method.value === "relative") { + if (typeof method !== 'undefined' && method.value === 'relative') { hsl.s -= hsl.s * amount.value / 100; } else { @@ -1915,7 +1952,7 @@ colorFunctions = { lighten: function (color, amount, method) { var hsl = color.toHSL(); - if (typeof method !== "undefined" && method.value === "relative") { + if (typeof method !== 'undefined' && method.value === 'relative') { hsl.l += hsl.l * amount.value / 100; } else { @@ -1927,7 +1964,7 @@ colorFunctions = { darken: function (color, amount, method) { var hsl = color.toHSL(); - if (typeof method !== "undefined" && method.value === "relative") { + if (typeof method !== 'undefined' && method.value === 'relative') { hsl.l -= hsl.l * amount.value / 100; } else { @@ -1939,7 +1976,7 @@ colorFunctions = { fadein: function (color, amount, method) { var hsl = color.toHSL(); - if (typeof method !== "undefined" && method.value === "relative") { + if (typeof method !== 'undefined' && method.value === 'relative') { hsl.a += hsl.a * amount.value / 100; } else { @@ -1951,7 +1988,7 @@ colorFunctions = { fadeout: function (color, amount, method) { var hsl = color.toHSL(); - if (typeof method !== "undefined" && method.value === "relative") { + if (typeof method !== 'undefined' && method.value === 'relative') { hsl.a -= hsl.a * amount.value / 100; } else { @@ -2085,8 +2122,8 @@ colorFunctions = { return c; } throw { - type: "Argument", - message: "argument must be a color keyword or 3/6 digit hex e.g. #FFF" + type: 'Argument', + message: 'argument must be a color keyword or 3/6 digit hex e.g. #FFF' }; }, tint: function(color, amount) { @@ -2098,18 +2135,18 @@ colorFunctions = { }; functionRegistry.addMultiple(colorFunctions); -},{"../tree/anonymous":48,"../tree/color":53,"../tree/dimension":60,"../tree/quoted":77,"./function-registry":26}],23:[function(require,module,exports){ +},{"../tree/anonymous":48,"../tree/color":53,"../tree/dimension":60,"../tree/quoted":78,"./function-registry":26}],23:[function(require,module,exports){ module.exports = function(environment) { - var Quoted = require("../tree/quoted"), - URL = require("../tree/url"), + var Quoted = require('../tree/quoted'), + URL = require('../tree/url'), utils = require('../utils'), - functionRegistry = require("./function-registry"), + functionRegistry = require('./function-registry'), fallback = function(functionThis, node) { return new URL(node, functionThis.index, functionThis.currentFileInfo).eval(functionThis.context); }, logger = require('../logger'); - functionRegistry.add("data-uri", function(mimetypeNode, filePathNode) { + functionRegistry.add('data-uri', function(mimetypeNode, filePathNode) { if (!filePathNode) { filePathNode = mimetypeNode; @@ -2144,7 +2181,7 @@ module.exports = function(environment) { mimetype = environment.mimeLookup(filePath); - if (mimetype === "image/svg+xml") { + if (mimetype === 'image/svg+xml') { useBase64 = false; } else { // use base 64 unless it's an ASCII or UTF-8 format @@ -2159,7 +2196,7 @@ module.exports = function(environment) { var fileSync = fileManager.loadFileSync(filePath, currentDirectory, context, environment); if (!fileSync.contents) { - logger.warn("Skipped data-uri embedding of " + filePath + " because file not found"); + logger.warn('Skipped data-uri embedding of ' + filePath + ' because file not found'); return fallback(this, filePathNode || mimetypeNode); } var buf = fileSync.contents; @@ -2169,7 +2206,7 @@ module.exports = function(environment) { buf = useBase64 ? environment.encodeBase64(buf) : encodeURIComponent(buf); - var uri = "data:" + mimetype + ',' + buf + fragment; + var uri = 'data:' + mimetype + ',' + buf + fragment; // IE8 cannot handle a data-uri larger than 32,768 characters. If this is exceeded // and the --ieCompat flag is enabled, return a normal url() instead. @@ -2177,8 +2214,8 @@ module.exports = function(environment) { if (uri.length >= DATA_URI_MAX) { if (this.context.ieCompat !== false) { - logger.warn("Skipped data-uri embedding of " + filePath + " because its size (" + uri.length + - " characters) exceeds IE8-safe " + DATA_URI_MAX + " characters!"); + logger.warn('Skipped data-uri embedding of ' + filePath + ' because its size (' + uri.length + + ' characters) exceeds IE8-safe ' + DATA_URI_MAX + ' characters!'); return fallback(this, filePathNode || mimetypeNode); } @@ -2188,9 +2225,9 @@ module.exports = function(environment) { }); }; -},{"../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"); +},{"../logger":37,"../tree/quoted":78,"../tree/url":83,"../utils":87,"./function-registry":26}],24:[function(require,module,exports){ +var Keyword = require('../tree/keyword'), + functionRegistry = require('./function-registry'); var defaultFunc = { eval: function () { @@ -2213,12 +2250,12 @@ var defaultFunc = { } }; -functionRegistry.add("default", defaultFunc.eval.bind(defaultFunc)); +functionRegistry.add('default', defaultFunc.eval.bind(defaultFunc)); module.exports = defaultFunc; },{"../tree/keyword":68,"./function-registry":26}],25:[function(require,module,exports){ -var Expression = require("../tree/expression"); +var Expression = require('../tree/expression'); var functionCaller = function(name, context, index, currentFileInfo) { this.name = name.toLowerCase(); @@ -2237,15 +2274,15 @@ functionCaller.prototype.call = function(args) { // https://github.com/less/less.js/issues/2477 if (Array.isArray(args)) { args = args.filter(function (item) { - if (item.type === "Comment") { + if (item.type === 'Comment') { return false; } return true; }) .map(function(item) { - if (item.type === "Expression") { + if (item.type === 'Expression') { var subNodes = item.value.filter(function (item) { - if (item.type === "Comment") { + if (item.type === 'Comment') { return false; } return true; @@ -2304,33 +2341,33 @@ module.exports = makeRegistry( null ); },{}],27:[function(require,module,exports){ module.exports = function(environment) { var functions = { - functionRegistry: require("./function-registry"), - functionCaller: require("./function-caller") + functionRegistry: require('./function-registry'), + functionCaller: require('./function-caller') }; // register functions - require("./boolean"); - require("./default"); - require("./color"); - require("./color-blending"); - require("./data-uri")(environment); - require("./math"); - require("./number"); - require("./string"); - require("./svg")(environment); - require("./types"); + require('./boolean'); + require('./default'); + require('./color'); + require('./color-blending'); + require('./data-uri')(environment); + require('./math'); + require('./number'); + require('./string'); + require('./svg')(environment); + require('./types'); return functions; }; },{"./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 Dimension = require('../tree/dimension'); var MathHelper = function() { }; MathHelper._math = function (fn, unit, n) { if (!(n instanceof Dimension)) { - throw { type: "Argument", message: "argument must be a number" }; + throw { type: 'Argument', message: 'argument must be a number' }; } if (unit == null) { unit = n.unit; @@ -2341,8 +2378,8 @@ MathHelper._math = function (fn, unit, n) { }; module.exports = MathHelper; },{"../tree/dimension":60}],29:[function(require,module,exports){ -var functionRegistry = require("./function-registry"), - mathHelper = require("./math-helper.js"); +var functionRegistry = require('./function-registry'), + mathHelper = require('./math-helper.js'); var mathFunctions = { // name, unit @@ -2350,12 +2387,12 @@ var mathFunctions = { floor: null, sqrt: null, abs: null, - tan: "", - sin: "", - cos: "", - atan: "rad", - asin: "rad", - acos: "rad" + tan: '', + sin: '', + cos: '', + atan: 'rad', + asin: 'rad', + acos: 'rad' }; for (var f in mathFunctions) { @@ -2365,22 +2402,22 @@ for (var f in mathFunctions) { } mathFunctions.round = function (n, f) { - var fraction = typeof f === "undefined" ? 0 : f.value; + var fraction = typeof f === 'undefined' ? 0 : f.value; return mathHelper._math(function(num) { return num.toFixed(fraction); }, null, n); }; functionRegistry.addMultiple(mathFunctions); },{"./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"), - mathHelper = require("./math-helper.js"); +var Dimension = require('../tree/dimension'), + Anonymous = require('../tree/anonymous'), + functionRegistry = require('./function-registry'), + mathHelper = require('./math-helper.js'); var minMax = function (isMin, args) { args = Array.prototype.slice.call(args); switch (args.length) { - case 0: throw { type: "Argument", message: "one or more arguments required" }; + case 0: throw { type: 'Argument', message: 'one or more arguments required' }; } var i, j, current, currentUnified, referenceUnified, unit, unitStatic, unitClone, order = [], // elems only contains original argument values. @@ -2394,20 +2431,20 @@ var minMax = function (isMin, args) { } continue; } - currentUnified = current.unit.toString() === "" && unitClone !== undefined ? new Dimension(current.value, unitClone).unify() : current.unify(); - unit = currentUnified.unit.toString() === "" && unitStatic !== undefined ? unitStatic : currentUnified.unit.toString(); - unitStatic = unit !== "" && unitStatic === undefined || unit !== "" && order[0].unify().unit.toString() === "" ? unit : unitStatic; - unitClone = unit !== "" && unitClone === undefined ? current.unit.toString() : unitClone; - j = values[""] !== undefined && unit !== "" && unit === unitStatic ? values[""] : values[unit]; + currentUnified = current.unit.toString() === '' && unitClone !== undefined ? new Dimension(current.value, unitClone).unify() : current.unify(); + unit = currentUnified.unit.toString() === '' && unitStatic !== undefined ? unitStatic : currentUnified.unit.toString(); + unitStatic = unit !== '' && unitStatic === undefined || unit !== '' && order[0].unify().unit.toString() === '' ? unit : unitStatic; + unitClone = unit !== '' && unitClone === undefined ? current.unit.toString() : unitClone; + 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); continue; } - referenceUnified = order[j].unit.toString() === "" && unitClone !== undefined ? new Dimension(order[j].value, unitClone).unify() : order[j].unify(); + referenceUnified = order[j].unit.toString() === '' && unitClone !== undefined ? new Dimension(order[j].value, unitClone).unify() : order[j].unify(); if ( isMin && currentUnified.value < referenceUnified.value || !isMin && currentUnified.value > referenceUnified.value) { order[j] = current; @@ -2416,8 +2453,8 @@ var minMax = function (isMin, args) { if (order.length == 1) { return order[0]; } - args = order.map(function (a) { return a.toCSS(this.context); }).join(this.context.compress ? "," : ", "); - return new Anonymous((isMin ? "min" : "max") + "(" + args + ")"); + args = order.map(function (a) { return a.toCSS(this.context); }).join(this.context.compress ? ',' : ', '); + return new Anonymous((isMin ? 'min' : 'max') + '(' + args + ')'); }; functionRegistry.addMultiple({ min: function () { @@ -2436,11 +2473,11 @@ functionRegistry.addMultiple({ return new Dimension(a.value % b.value, a.unit); }, pow: function(x, y) { - if (typeof x === "number" && typeof y === "number") { + if (typeof x === 'number' && typeof y === 'number') { x = new Dimension(x); y = new Dimension(y); } else if (!(x instanceof Dimension) || !(y instanceof Dimension)) { - throw { type: "Argument", message: "arguments must be numbers" }; + throw { type: 'Argument', message: 'arguments must be numbers' }; } return new Dimension(Math.pow(x.value, y.value), x.unit); @@ -2455,10 +2492,10 @@ functionRegistry.addMultiple({ }); },{"../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"), - functionRegistry = require("./function-registry"); +var Quoted = require('../tree/quoted'), + Anonymous = require('../tree/anonymous'), + JavaScript = require('../tree/javascript'), + functionRegistry = require('./function-registry'); functionRegistry.addMultiple({ e: function (str) { @@ -2466,12 +2503,12 @@ functionRegistry.addMultiple({ }, escape: function (str) { return new Anonymous( - encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B") - .replace(/\(/g, "%28").replace(/\)/g, "%29")); + encodeURI(str.value).replace(/=/g, '%3D').replace(/:/g, '%3A').replace(/#/g, '%23').replace(/;/g, '%3B') + .replace(/\(/g, '%28').replace(/\)/g, '%29')); }, replace: function (string, pattern, replacement, flags) { var result = string.value; - replacement = (replacement.type === "Quoted") ? + replacement = (replacement.type === 'Quoted') ? replacement.value : replacement.toCSS(); result = result.replace(new RegExp(pattern.value, flags ? flags.value : ''), replacement); return new Quoted(string.quote || '', result, string.escaped); @@ -2483,7 +2520,7 @@ functionRegistry.addMultiple({ for (var i = 0; i < args.length; i++) { /* jshint loopfunc:true */ result = result.replace(/%[sda]/i, function(token) { - var value = ((args[i].type === "Quoted") && + var value = ((args[i].type === 'Quoted') && token.match(/s/i)) ? args[i].value : args[i].toCSS(); return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; }); @@ -2493,20 +2530,20 @@ functionRegistry.addMultiple({ } }); -},{"../tree/anonymous":48,"../tree/javascript":66,"../tree/quoted":77,"./function-registry":26}],32:[function(require,module,exports){ +},{"../tree/anonymous":48,"../tree/javascript":66,"../tree/quoted":78,"./function-registry":26}],32:[function(require,module,exports){ module.exports = function(environment) { - var Dimension = require("../tree/dimension"), - Color = require("../tree/color"), - Expression = require("../tree/expression"), - Quoted = require("../tree/quoted"), - URL = require("../tree/url"), - functionRegistry = require("./function-registry"); + var Dimension = require('../tree/dimension'), + Color = require('../tree/color'), + Expression = require('../tree/expression'), + Quoted = require('../tree/quoted'), + URL = require('../tree/url'), + functionRegistry = require('./function-registry'); - functionRegistry.add("svg-gradient", function(direction) { + functionRegistry.add('svg-gradient', function(direction) { var stops, gradientDirectionSvg, - gradientType = "linear", + gradientType = 'linear', rectangleDimension = 'x="0" y="0" width="1" height="1"', renderEnv = {compress: false}, returner, @@ -2514,9 +2551,9 @@ module.exports = function(environment) { 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" }; + throw { type: 'Argument', + message: 'svg-gradient expects direction, start_color [start_position], [color position,]...,' + + ' end_color [end_position] or direction, color list' }; } if (arguments.length == 2) { @@ -2531,27 +2568,27 @@ module.exports = function(environment) { } switch (directionValue) { - case "to bottom": + case 'to bottom': gradientDirectionSvg = 'x1="0%" y1="0%" x2="0%" y2="100%"'; break; - case "to right": + case 'to right': gradientDirectionSvg = 'x1="0%" y1="0%" x2="100%" y2="0%"'; break; - case "to bottom right": + case 'to bottom right': gradientDirectionSvg = 'x1="0%" y1="0%" x2="100%" y2="100%"'; break; - case "to top right": + case 'to top right': gradientDirectionSvg = 'x1="0%" y1="100%" x2="100%" y2="0%"'; break; - case "ellipse": - case "ellipse at center": - gradientType = "radial"; + case 'ellipse': + case 'ellipse at center': + gradientType = 'radial'; gradientDirectionSvg = 'cx="50%" cy="50%" r="75%"'; rectangleDimension = 'x="-50" y="-50" width="101" height="101"'; break; default: - throw { type: "Argument", message: "svg-gradient direction must be 'to bottom', 'to right'," + - " 'to bottom right', 'to top right' or 'ellipse at center'" }; + throw { type: 'Argument', message: 'svg-gradient direction must be \'to bottom\', \'to right\',' + + ' \'to bottom right\', \'to top right\' or \'ellipse at center\'' }; } returner = '' + '' + @@ -2569,7 +2606,7 @@ module.exports = function(environment) { if (!(color instanceof Color) || (!((i === 0 || i + 1 === stops.length) && position === undefined) && !(position instanceof Dimension))) { throwArgumentDescriptor(); } - positionValue = position ? position.toCSS(renderEnv) : i === 0 ? "0%" : "100%"; + positionValue = position ? position.toCSS(renderEnv) : i === 0 ? '0%' : '100%'; alpha = color.alpha; returner += ''; } @@ -2578,32 +2615,32 @@ module.exports = function(environment) { returner = encodeURIComponent(returner); - returner = "data:image/svg+xml," + returner; - return new URL(new Quoted("'" + returner + "'", returner, false, this.index, this.currentFileInfo), this.index, this.currentFileInfo); + returner = 'data:image/svg+xml,' + returner; + return new URL(new Quoted('\'' + returner + '\'', returner, false, 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(require,module,exports){ -var Keyword = require("../tree/keyword"), - DetachedRuleset = require("../tree/detached-ruleset"), - Dimension = require("../tree/dimension"), - Color = require("../tree/color"), - Quoted = require("../tree/quoted"), - Anonymous = require("../tree/anonymous"), - URL = require("../tree/url"), - Operation = require("../tree/operation"), - functionRegistry = require("./function-registry"); +},{"../tree/color":53,"../tree/dimension":60,"../tree/expression":62,"../tree/quoted":78,"../tree/url":83,"./function-registry":26}],33:[function(require,module,exports){ +var Keyword = require('../tree/keyword'), + DetachedRuleset = require('../tree/detached-ruleset'), + Dimension = require('../tree/dimension'), + Color = require('../tree/color'), + Quoted = require('../tree/quoted'), + Anonymous = require('../tree/anonymous'), + URL = require('../tree/url'), + Operation = require('../tree/operation'), + functionRegistry = require('./function-registry'); var isa = function (n, Type) { return (n instanceof Type) ? Keyword.True : Keyword.False; }, isunit = function (n, unit) { if (unit === undefined) { - throw { type: "Argument", message: "missing the required second argument to isunit." }; + throw { type: 'Argument', message: 'missing the required second argument to isunit.' }; } - unit = typeof unit.value === "string" ? unit.value : unit; - if (typeof unit !== "string") { - throw { type: "Argument", message: "Second argument to isunit should be a unit or a string." }; + unit = typeof unit.value === 'string' ? unit.value : unit; + if (typeof unit !== 'string') { + throw { type: 'Argument', message: 'Second argument to isunit should be a unit or a string.' }; } return (n instanceof Dimension) && n.unit.is(unit) ? Keyword.True : Keyword.False; }, @@ -2646,9 +2683,9 @@ functionRegistry.addMultiple({ isunit: isunit, unit: function (val, unit) { if (!(val instanceof Dimension)) { - throw { type: "Argument", - message: "the first argument to unit must be a number" + - (val instanceof Operation ? ". Have you forgotten parenthesis?" : "") }; + throw { type: 'Argument', + message: 'the first argument to unit must be a number' + + (val instanceof Operation ? '. Have you forgotten parenthesis?' : '') }; } if (unit) { if (unit instanceof Keyword) { @@ -2657,11 +2694,11 @@ functionRegistry.addMultiple({ unit = unit.toCSS(); } } else { - unit = ""; + unit = ''; } return new Dimension(val.value, unit); }, - "get-unit": function (n) { + 'get-unit': function (n) { return new Anonymous(n.unit); }, extract: function(values, index) { @@ -2671,15 +2708,19 @@ functionRegistry.addMultiple({ }, length: function(values) { return new Dimension(getItemsFromNode(values).length); + }, + _SELF: function(n) { + return n; } }); -},{"../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"), +},{"../tree/anonymous":48,"../tree/color":53,"../tree/detached-ruleset":59,"../tree/dimension":60,"../tree/keyword":68,"../tree/operation":75,"../tree/quoted":78,"../tree/url":83,"./function-registry":26}],34:[function(require,module,exports){ +var contexts = require('./contexts'), Parser = require('./parser/parser'), LessError = require('./less-error'), utils = require('./utils'), - PromiseConstructor = typeof Promise === 'undefined' ? require('promise') : Promise; + PromiseConstructor = typeof Promise === 'undefined' ? require('promise') : Promise, + logger = require('./logger'); module.exports = function(environment) { @@ -2705,7 +2746,7 @@ 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 @@ -2726,6 +2767,7 @@ module.exports = function(environment) { var importedEqualsRoot = fullPath === importManager.rootFilename; if (importOptions.optional && e) { callback(null, {rules:[]}, false, null); + logger.info('The file ' + fullPath + ' was skipped because it was not found and the import was marked optional.'); } else { // Inline imports aren't cached here. @@ -2733,7 +2775,7 @@ module.exports = function(environment) { // same name as they used to do before this comment and the condition below have been added. if (!importManager.files[fullPath] && !importOptions.inline) { importManager.files[fullPath] = { root: root, options: importOptions }; - } + } if (e && !importManager.error) { importManager.error = e; } callback(e, root, importedEqualsRoot, fullPath); } @@ -2749,7 +2791,7 @@ module.exports = function(environment) { var fileManager = environment.getFileManager(path, currentFileInfo.currentDirectory, this.context, environment); if (!fileManager) { - fileParsedFunc({ message: "Could not find a file-manager for " + path }); + fileParsedFunc({ message: 'Could not find a file-manager for ' + path }); return; } @@ -2769,7 +2811,7 @@ module.exports = function(environment) { newFileInfo.currentDirectory = fileManager.getPath(resolvedFilename); if (newFileInfo.relativeUrls) { newFileInfo.rootpath = fileManager.join( - (importManager.context.rootpath || ""), + (importManager.context.rootpath || ''), fileManager.pathDiff(newFileInfo.currentDirectory, newFileInfo.entryPath)); if (!fileManager.isPathAbsolute(newFileInfo.rootpath) && fileManager.alwaysMakePathsAbsolute()) { @@ -2798,10 +2840,10 @@ module.exports = function(environment) { } else if (importOptions.inline) { fileParsedFunc(null, contents, resolvedFilename); } else { - + // import (multiple) parse trees apparently get altered and can't be cached. // TODO: investigate why this is - if (importManager.files[resolvedFilename] + if (importManager.files[resolvedFilename] && !importManager.files[resolvedFilename].options.multiple && !importOptions.multiple) { @@ -2817,14 +2859,14 @@ module.exports = function(environment) { var promise, context = utils.clone(this.context); if (tryAppendExtension) { - context.ext = importOptions.isPlugin ? ".js" : ".less"; + 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, + promise = fileManager.loadFile(path, currentFileInfo.currentDirectory, context, environment, function(err, loadedFile) { if (err) { fileParsedFunc(err); @@ -2841,28 +2883,28 @@ module.exports = function(environment) { return ImportManager; }; -},{"./contexts":12,"./less-error":36,"./parser/parser":42,"./utils":86,"promise":undefined}],35:[function(require,module,exports){ +},{"./contexts":12,"./less-error":36,"./logger":37,"./parser/parser":42,"./utils":87,"promise":undefined}],35:[function(require,module,exports){ module.exports = function(environment, fileManagers) { var SourceMapOutput, SourceMapBuilder, ParseTree, ImportManager, Environment; var initial = { - version: [3, 0, 4], + version: [3, 5, 3], 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 = 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'), functions: require('./functions')(environment), - contexts: require("./contexts"), + contexts: require('./contexts'), SourceMapOutput: (SourceMapOutput = require('./source-map-output')(environment)), SourceMapBuilder: (SourceMapBuilder = require('./source-map-builder')(SourceMapOutput, environment)), ParseTree: (ParseTree = require('./parse-tree')(SourceMapBuilder)), ImportManager: (ImportManager = require('./import-manager')(environment)), - render: require("./render")(environment, ParseTree, ImportManager), - parse: require("./parse")(environment, ParseTree, ImportManager), + render: require('./render')(environment, ParseTree, ImportManager), + parse: require('./parse')(environment, ParseTree, ImportManager), LessError: require('./less-error'), transformTree: require('./transform-tree'), utils: require('./utils'), @@ -2883,7 +2925,7 @@ module.exports = function(environment, fileManagers) { for (var n in initial.tree) { /* eslint guard-for-in: 0 */ t = initial.tree[n]; - if (typeof t === "function") { + if (typeof t === 'function') { api[n.toLowerCase()] = ctor(t); } else { @@ -2898,7 +2940,7 @@ module.exports = function(environment, fileManagers) { 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){ +},{"./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":87,"./visitors":91}],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). @@ -3041,19 +3083,19 @@ LessError.prototype.toString = function(options) { return message; }; -},{"./utils":86}],37:[function(require,module,exports){ +},{"./utils":87}],37:[function(require,module,exports){ module.exports = { error: function(msg) { - this._fireEvent("error", msg); + this._fireEvent('error', msg); }, warn: function(msg) { - this._fireEvent("warn", msg); + this._fireEvent('warn', msg); }, info: function(msg) { - this._fireEvent("info", msg); + this._fireEvent('info', msg); }, debug: function(msg) { - this._fireEvent("debug", msg); + this._fireEvent('debug', msg); }, addListener: function(listener) { this._listeners.push(listener); @@ -3079,8 +3121,8 @@ module.exports = { },{}],38:[function(require,module,exports){ var LessError = require('./less-error'), - transformTree = require("./transform-tree"), - logger = require("./logger"); + transformTree = require('./transform-tree'), + logger = require('./logger'); module.exports = function(SourceMapBuilder) { var ParseTree = function(root, imports) { @@ -3099,7 +3141,7 @@ module.exports = function(SourceMapBuilder) { try { var compress = Boolean(options.compress); if (compress) { - logger.warn("The compress option has been deprecated. We recommend you use a dedicated css minifier, for instance see less-plugin-clean-css."); + logger.warn('The compress option has been deprecated. We recommend you use a dedicated css minifier, for instance see less-plugin-clean-css.'); } var toCSSOptions = { @@ -3141,7 +3183,7 @@ module.exports = function(SourceMapBuilder) { },{"./less-error":36,"./logger":37,"./transform-tree":47}],39:[function(require,module,exports){ var PromiseConstructor, - contexts = require("./contexts"), + contexts = require('./contexts'), Parser = require('./parser/parser'), PluginManager = require('./plugin-manager'), LessError = require('./less-error'), @@ -3184,19 +3226,19 @@ module.exports = function(environment, ParseTree, ImportManager) { if (options.rootFileInfo) { rootFileInfo = options.rootFileInfo; } else { - var filename = options.filename || "input"; - var entryPath = filename.replace(/[^\/\\]*$/, ""); + var filename = options.filename || 'input'; + var entryPath = filename.replace(/[^\/\\]*$/, ''); rootFileInfo = { filename: filename, relativeUrls: context.relativeUrls, - rootpath: context.rootpath || "", + rootpath: context.rootpath || '', currentDirectory: entryPath, entryPath: entryPath, rootFilename: filename }; // add in a missing trailing slash - if (rootFileInfo.rootpath && rootFileInfo.rootpath.slice(-1) !== "/") { - rootFileInfo.rootpath += "/"; + if (rootFileInfo.rootpath && rootFileInfo.rootpath.slice(-1) !== '/') { + rootFileInfo.rootpath += '/'; } } @@ -3232,7 +3274,7 @@ module.exports = function(environment, ParseTree, ImportManager) { return parse; }; -},{"./contexts":12,"./less-error":36,"./parser/parser":42,"./plugin-manager":43,"./utils":86,"promise":undefined}],40:[function(require,module,exports){ +},{"./contexts":12,"./less-error":36,"./parser/parser":42,"./plugin-manager":43,"./utils":87,"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, @@ -3263,7 +3305,7 @@ module.exports = function (input, fail) { continue; case 41: // ) if (--parenLevel < 0) { - return fail("missing opening `(`", chunkerCurrentIndex); + return fail('missing opening `(`', chunkerCurrentIndex); } continue; case 59: // ; @@ -3275,13 +3317,13 @@ module.exports = function (input, fail) { continue; case 125: // } if (--level < 0) { - return fail("missing opening `{`", chunkerCurrentIndex); + return fail('missing opening `{`', chunkerCurrentIndex); } if (!level && !parenLevel) { emitChunk(); } continue; case 92: // \ if (chunkerCurrentIndex < len - 1) { chunkerCurrentIndex++; continue; } - return fail("unescaped `\\`", chunkerCurrentIndex); + return fail('unescaped `\\`', chunkerCurrentIndex); case 34: case 39: case 96: // ", ' and ` @@ -3293,13 +3335,13 @@ module.exports = function (input, fail) { if (cc2 == cc) { matched = 1; break; } if (cc2 == 92) { // \ if (chunkerCurrentIndex == len - 1) { - return fail("unescaped `\\`", chunkerCurrentIndex); + return fail('unescaped `\\`', chunkerCurrentIndex); } chunkerCurrentIndex++; } } if (matched) { continue; } - return fail("unmatched `" + String.fromCharCode(cc) + "`", currentChunkStartIndex); + return fail('unmatched `' + String.fromCharCode(cc) + '`', currentChunkStartIndex); case 47: // /, check for comment if (parenLevel || (chunkerCurrentIndex == len - 1)) { continue; } cc2 = input.charCodeAt(chunkerCurrentIndex + 1); @@ -3319,14 +3361,14 @@ module.exports = function (input, fail) { if (input.charCodeAt(chunkerCurrentIndex + 1) == 47) { break; } } if (chunkerCurrentIndex == len - 1) { - return fail("missing closing `*/`", currentChunkStartIndex); + return fail('missing closing `*/`', currentChunkStartIndex); } chunkerCurrentIndex++; } continue; case 42: // *, check for unmatched */ if ((chunkerCurrentIndex < len - 1) && (input.charCodeAt(chunkerCurrentIndex + 1) == 47)) { - return fail("unmatched `/*`", chunkerCurrentIndex); + return fail('unmatched `/*`', chunkerCurrentIndex); } continue; } @@ -3334,12 +3376,12 @@ module.exports = function (input, fail) { if (level !== 0) { if ((lastMultiComment > lastOpening) && (lastMultiCommentEndBrace > lastMultiComment)) { - return fail("missing closing `}` or `*/`", lastOpening); + return fail('missing closing `}` or `*/`', lastOpening); } else { - return fail("missing closing `}`", lastOpening); + return fail('missing closing `}`', lastOpening); } } else if (parenLevel !== 0) { - return fail("missing closing `)`", lastOpeningParen); + return fail('missing closing `)`', lastOpeningParen); } emitChunk(true); @@ -3384,7 +3426,7 @@ module.exports = function() { nextChar = inp.charAt(parserInput.i + 1); if (nextChar === '/') { comment = {index: parserInput.i, isLineComment: true}; - var nextNewLine = inp.indexOf("\n", parserInput.i + 2); + var nextNewLine = inp.indexOf('\n', parserInput.i + 2); if (nextNewLine < 0) { nextNewLine = endIndex; } @@ -3393,7 +3435,7 @@ module.exports = function() { parserInput.commentStore.push(comment); continue; } else if (nextChar === '*') { - var nextStarSlash = inp.indexOf("*/", parserInput.i + 2); + var nextStarSlash = inp.indexOf('*/', parserInput.i + 2); if (nextStarSlash >= 0) { comment = { index: parserInput.i, @@ -3465,7 +3507,7 @@ module.exports = function() { } skipWhitespace(m[0].length); - if (typeof m === "string") { + if (typeof m === 'string') { return m; } @@ -3494,34 +3536,154 @@ module.exports = function() { return tok; }; - parserInput.$quoted = function() { + parserInput.$quoted = function(loc) { + var pos = loc || parserInput.i, + startChar = input.charAt(pos); - var startChar = input.charAt(parserInput.i); - if (startChar !== "'" && startChar !== '"') { + if (startChar !== '\'' && startChar !== '"') { return; } var length = input.length, - currentPosition = parserInput.i; + currentPosition = pos; for (var i = 1; i + currentPosition < length; i++) { var nextChar = input.charAt(i + currentPosition); switch (nextChar) { - case "\\": + case '\\': i++; continue; - case "\r": - case "\n": + case '\r': + case '\n': break; case startChar: var str = input.substr(currentPosition, i + 1); - skipWhitespace(i + 1); - return str; + if (!loc && loc !== 0) { + skipWhitespace(i + 1); + return str + } + return [startChar, str]; default: } } return null; }; + /** + * Permissive parsing. Ignores everything except matching {} [] () and quotes + * until matching token (outside of blocks) + */ + parserInput.$parseUntil = function(tok) { + var quote = '', + returnVal = null, + inComment = false, + blockDepth = 0, + blockStack = [], + parseGroups = [], + length = input.length, + startPos = parserInput.i, + lastPos = parserInput.i, + i = parserInput.i, + loop = true, + testChar; + + if (typeof tok === 'string') { + testChar = function(char) { + return char === tok; + } + } else { + testChar = function(char) { + return tok.test(char); + } + } + + do { + var prevChar, nextChar = input.charAt(i); + if (blockDepth === 0 && testChar(nextChar)) { + returnVal = input.substr(lastPos, i - lastPos); + if (returnVal) { + parseGroups.push(returnVal); + } + else { + parseGroups.push(' '); + } + returnVal = parseGroups; + skipWhitespace(i - startPos); + loop = false + } else { + if (inComment) { + if (nextChar === '*' && + input.charAt(i + 1) === '/') { + i++; + blockDepth--; + inComment = false; + } + i++; + continue; + } + switch (nextChar) { + case '\\': + i++; + nextChar = input.charAt(i); + parseGroups.push(input.substr(lastPos, i - lastPos + 1)); + lastPos = i + 1; + break; + case '/': + if (input.charAt(i + 1) === '*') { + i++; + inComment = true; + blockDepth++; + } + break; + case '\'': + case '"': + quote = parserInput.$quoted(i); + if (quote) { + parseGroups.push(input.substr(lastPos, i - lastPos), quote); + i += quote[1].length - 1; + lastPos = i + 1; + } + else { + skipWhitespace(i - startPos); + returnVal = nextChar; + loop = false; + } + break; + case '{': + blockStack.push('}'); + blockDepth++; + break; + case '(': + blockStack.push(')'); + blockDepth++; + break; + case '[': + blockStack.push(']'); + blockDepth++; + break; + case '}': + case ')': + case ']': + var expected = blockStack.pop(); + if (nextChar === expected) { + blockDepth--; + } else { + // move the parser to the error and return expected + skipWhitespace(i - startPos); + returnVal = expected; + loop = false; + } + } + i++; + if (i > length) { + loop = false; + } + } + prevChar = nextChar; + } while (loop); + + return returnVal ? returnVal : null; + } + parserInput.autoCommentAbsorb = true; parserInput.commentStore = []; parserInput.finished = false; @@ -3552,6 +3714,10 @@ module.exports = function() { return input.charAt(parserInput.i); }; + parserInput.prevChar = function() { + return input.charAt(parserInput.i - 1); + }; + parserInput.getInput = function() { return input; }; @@ -3609,10 +3775,10 @@ module.exports = function() { },{"./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"), + tree = require('../tree'), + visitors = require('../visitors'), + getParserInput = require('./parser-input'), + utils = require('../utils'), functionRegistry = require('../functions/function-registry'); // @@ -3670,8 +3836,8 @@ var Parser = function Parser(context, imports, fileInfo) { if (result) { return result; } - error(msg || (typeof arg === 'string' ? "expected '" + arg + "' got '" + parserInput.currentChar() + "'" - : "unexpected token")); + error(msg || (typeof arg === 'string' ? 'expected \'' + arg + '\' got \'' + parserInput.currentChar() + '\'' + : 'unexpected token')); } // Specialization of expect() @@ -3679,7 +3845,7 @@ var Parser = function Parser(context, imports, fileInfo) { if (parserInput.$char(arg)) { return arg; } - error(msg || "expected '" + arg + "' got '" + parserInput.currentChar() + "'"); + error(msg || 'expected \'' + arg + '\' got \'' + parserInput.currentChar() + '\''); } function getDebugInfo(index) { @@ -3753,7 +3919,7 @@ var Parser = function Parser(context, imports, fileInfo) { // @param [additionalData] An optional map which can contains vars - a map (key, value) of variables to apply // parse: function (str, callback, additionalData) { - var root, error = null, globalVars, modifyVars, ignored, preText = ""; + var root, error = null, globalVars, modifyVars, ignored, preText = ''; globalVars = (additionalData && additionalData.globalVars) ? Parser.serializeVars(additionalData.globalVars) + '\n' : ''; modifyVars = (additionalData && additionalData.modifyVars) ? '\n' + Parser.serializeVars(additionalData.modifyVars) : ''; @@ -3766,7 +3932,7 @@ var Parser = function Parser(context, imports, fileInfo) { } if (globalVars || (additionalData && additionalData.banner)) { - preText = ((additionalData && additionalData.banner) ? additionalData.banner : "") + globalVars; + preText = ((additionalData && additionalData.banner) ? additionalData.banner : '') + globalVars; ignored = imports.contentsIgnoredChars; ignored[fileInfo.filename] = ignored[fileInfo.filename] || 0; ignored[fileInfo.filename] += preText.length; @@ -3816,18 +3982,18 @@ var Parser = function Parser(context, imports, fileInfo) { var message = endInfo.furthestPossibleErrorMessage; if (!message) { - message = "Unrecognised input"; + message = 'Unrecognised input'; if (endInfo.furthestChar === '}') { - message += ". Possibly missing opening '{'"; + message += '. Possibly missing opening \'{\''; } else if (endInfo.furthestChar === ')') { - message += ". Possibly missing opening '('"; + message += '. Possibly missing opening \'(\''; } else if (endInfo.furthestReachedEnd) { - message += ". Possibly missing something"; + message += '. Possibly missing something'; } } error = new LessError({ - type: "Parse", + type: 'Parse', message: message, index: endInfo.furthest, filename: fileInfo.filename @@ -3926,12 +4092,12 @@ var Parser = function Parser(context, imports, fileInfo) { } node = mixin.definition() || this.declaration() || this.ruleset() || - mixin.call() || this.variableCall() || this.entities.call() || this.atrule(); + mixin.call(false, false) || this.variableCall() || this.entities.call() || this.atrule(); if (node) { root.push(node); } else { var foundSemiColon = false; - while (parserInput.$char(";")) { + while (parserInput.$char(';')) { foundSemiColon = true; } if (!foundSemiColon) { @@ -3956,18 +4122,25 @@ var Parser = function Parser(context, imports, fileInfo) { // Entities are tokens which can be found inside an Expression // entities: { + mixinLookup: function() { + return parsers.mixin.call(true, true); + }, // // A string, which supports escaping " and ' // // "milky way" 'he\'s the one!' // - quoted: function () { + quoted: function (forceEscaped) { var str, index = parserInput.i, isEscaped = false; parserInput.save(); - if (parserInput.$char("~")) { + if (parserInput.$char('~')) { isEscaped = true; + } else if (forceEscaped) { + parserInput.restore(); + return; } + str = parserInput.$quoted(); if (!str) { parserInput.restore(); @@ -3984,7 +4157,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(/^\[?(?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+\]?/); if (k) { return tree.Color.fromKeyword(k) || new(tree.Keyword)(k); } @@ -4026,7 +4199,7 @@ var Parser = function Parser(context, imports, fileInfo) { args = this.arguments(args); if (!parserInput.$char(')')) { - parserInput.restore("Could not parse call arguments or missing ')'"); + parserInput.restore('Could not parse call arguments or missing \')\''); return; } @@ -4152,13 +4325,13 @@ var Parser = function Parser(context, imports, fileInfo) { parserInput.autoCommentAbsorb = false; - if (!parserInput.$str("url(")) { + if (!parserInput.$str('url(')) { parserInput.autoCommentAbsorb = true; return; } value = this.quoted() || this.variable() || this.property() || - parserInput.$re(/^(?:(?:\\[\(\)'"])|[^\(\)'"])+/) || ""; + parserInput.$re(/^(?:(?:\\[\(\)'"])|[^\(\)'"])+/) || ''; parserInput.autoCommentAbsorb = true; @@ -4179,11 +4352,23 @@ var Parser = function Parser(context, imports, fileInfo) { // see `parsers.variable`. // variable: function () { - var name, index = parserInput.i; + var ch, name, index = parserInput.i; + parserInput.save(); if (parserInput.currentChar() === '@' && (name = parserInput.$re(/^@@?[\w-]+/))) { + ch = parserInput.currentChar(); + if (ch === '(' || ch === '[' && !parserInput.prevChar().match(/^\s/)) { + // this may be a VariableCall lookup + var result = parsers.variableCall(name); + if (result) { + parserInput.forget(); + return result; + } + } + parserInput.forget(); return new(tree.Variable)(name, index, fileInfo); } + parserInput.restore(); }, // A variable entity using the protective {} e.g. @{var} @@ -4191,7 +4376,7 @@ var Parser = function Parser(context, imports, fileInfo) { var curly, index = parserInput.i; if (parserInput.currentChar() === '@' && (curly = parserInput.$re(/^@\{([\w-]+)\}/))) { - return new(tree.Variable)("@" + curly[1], index, fileInfo); + return new(tree.Variable)('@' + curly[1], index, fileInfo); } }, // @@ -4212,7 +4397,7 @@ var Parser = function Parser(context, imports, fileInfo) { var curly, index = parserInput.i; if (parserInput.currentChar() === '$' && (curly = parserInput.$re(/^\$\{([\w-]+)\}/))) { - return new(tree.Property)("$" + curly[1], index, fileInfo); + return new(tree.Property)('$' + curly[1], index, fileInfo); } }, // @@ -4231,7 +4416,7 @@ var Parser = function Parser(context, imports, fileInfo) { var colorCandidateString = rgb.input.match(/^#([\w]+).*/); colorCandidateString = colorCandidateString[1]; if (!colorCandidateString.match(/^[A-Fa-f0-9]+$/)) { // verify if candidate consists only of allowed HEX characters - error("Invalid HEX color code"); + error('Invalid HEX color code'); } return new(tree.Color)(rgb[1], undefined, '#' + colorCandidateString); } @@ -4295,8 +4480,8 @@ var Parser = function Parser(context, imports, fileInfo) { parserInput.save(); - var escape = parserInput.$char("~"); - var jsQuote = parserInput.$char("`"); + var escape = parserInput.$char('~'); + var jsQuote = parserInput.$char('`'); if (!jsQuote) { parserInput.restore(); @@ -4308,7 +4493,7 @@ var Parser = function Parser(context, imports, fileInfo) { parserInput.forget(); return new(tree.JavaScript)(js.substr(0, js.length - 1), Boolean(escape), index, fileInfo); } - parserInput.restore("invalid javascript definition"); + parserInput.restore('invalid javascript definition'); } }, @@ -4324,18 +4509,49 @@ var Parser = function Parser(context, imports, fileInfo) { }, // - // Call a variable value + // Call a variable value to retrieve a detached ruleset + // or a value from a detached ruleset's rules. // - // @fink() + // @fink(); + // @fink; + // color: @fink[@color]; // - variableCall: function () { - var name; + variableCall: function (parsedName) { + var lookups, important, i = parserInput.i, + inValue = !!parsedName, name = parsedName; - if (parserInput.currentChar() === '@' - && (name = parserInput.$re(/^(@[\w-]+)\(\s*\)/)) - && parsers.end()) { - return new tree.VariableCall(name[1]); + parserInput.save(); + + if (name || (parserInput.currentChar() === '@' + && (name = parserInput.$re(/^(@[\w-]+)(\(\s*\))?/)))) { + + lookups = this.mixin.ruleLookups(); + + if (!lookups && ((inValue && parserInput.$str('()') !== '()') || (name[2] !== '()'))) { + parserInput.restore('Missing \'[...]\' lookup in variable call'); + return; + } + + if (!inValue) { + name = name[1]; + } + + if (lookups && parsers.important()) { + important = true; + } + + var call = new tree.VariableCall(name, i, fileInfo); + if (!inValue && parsers.end()) { + parserInput.forget(); + return call; + } + else { + parserInput.forget(); + return new tree.NamespaceValue(call, lookups, important, i, fileInfo); + } } + + parserInput.restore(); }, // @@ -4344,7 +4560,7 @@ var Parser = function Parser(context, imports, fileInfo) { extend: function(isRule) { var elements, e, index = parserInput.i, option, extendList, extend; - if (!parserInput.$str(isRule ? "&:extend(" : ":extend(")) { + if (!parserInput.$str(isRule ? '&:extend(' : ':extend(')) { return; } @@ -4365,7 +4581,7 @@ var Parser = function Parser(context, imports, fileInfo) { option = option && option[1]; if (!elements) { - error("Missing target selector for :extend()."); + error('Missing target selector for :extend().'); } extend = new(tree.Extend)(new(tree.Selector)(elements), option, index, fileInfo); if (extendList) { @@ -4373,7 +4589,7 @@ var Parser = function Parser(context, imports, fileInfo) { } else { extendList = [ extend ]; } - } while (parserInput.$char(",")); + } while (parserInput.$char(',')); expect(/^\)/); @@ -4399,28 +4615,82 @@ var Parser = function Parser(context, imports, fileInfo) { // A Mixin call, with an optional argument list // // #mixins > .square(#fff); + // #mixins.square(#fff); // .rounded(4px, black); // .button; // + // We can lookup / return a value using the lookup syntax: + // + // color: #mixin.square(#fff)[@color]; + // // The `while` loop is there because mixins can be // namespaced, but we only support the child and descendant // selector for now. // - call: function () { - var s = parserInput.currentChar(), important = false, index = parserInput.i, elemIndex, - elements, elem, e, c, args; + call: function (inValue, getLookup) { + var s = parserInput.currentChar(), important = false, lookups, + index = parserInput.i, elements, args, hasParens; if (s !== '.' && s !== '#') { return; } parserInput.save(); // stop us absorbing part of an invalid selector + elements = this.elements(); + + if (elements) { + if (parserInput.$char('(')) { + args = this.args(true).args; + expectChar(')'); + hasParens = true; + } + + if (getLookup !== false) { + lookups = this.ruleLookups(); + } + if (getLookup === true && !lookups) { + parserInput.restore(); + return; + } + + if (inValue && !lookups && !hasParens) { + // This isn't a valid in-value mixin call + parserInput.restore(); + return; + } + + if (!inValue && parsers.important()) { + important = true; + } + + if (inValue || parsers.end()) { + parserInput.forget(); + var mixin = new(tree.mixin.Call)(elements, args, index, fileInfo, !lookups && important); + if (lookups) { + return new tree.NamespaceValue(mixin, lookups, important); + } + else { + return mixin; + } + } + } + + parserInput.restore(); + }, + /** + * Matching elements for mixins + * (Start with . or # and can have > ) + */ + elements: function() { + var elements, e, c, elem, elemIndex, + re = /^[#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/; while (true) { elemIndex = parserInput.i; - e = parserInput.$re(/^[#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/); + e = parserInput.$re(re); + if (!e) { break; } - elem = new(tree.Element)(c, e, elemIndex, fileInfo); + elem = new(tree.Element)(c, e, false, elemIndex, fileInfo); if (elements) { elements.push(elem); } else { @@ -4428,24 +4698,7 @@ var Parser = function Parser(context, imports, fileInfo) { } c = parserInput.$char('>'); } - - if (elements) { - if (parserInput.$char('(')) { - args = this.args(true).args; - expectChar(')'); - } - - if (parsers.important()) { - important = true; - } - - if (parsers.end()) { - parserInput.forget(); - return new(tree.mixin.Call)(elements, args, index, fileInfo, important); - } - } - - parserInput.restore(); + return elements; }, args: function (isCall) { var entities = parsers.entities, @@ -4461,16 +4714,16 @@ var Parser = function Parser(context, imports, fileInfo) { arg = parsers.detachedRuleset() || parsers.expression(); } else { parserInput.commentStore.length = 0; - if (parserInput.$str("...")) { + if (parserInput.$str('...')) { returner.variadic = true; - if (parserInput.$char(";") && !isSemiColonSeparated) { + if (parserInput.$char(';') && !isSemiColonSeparated) { isSemiColonSeparated = true; } (isSemiColonSeparated ? argsSemiColon : argsComma) .push({ variadic: true }); break; } - arg = entities.variable() || entities.property() || entities.literal() || entities.keyword(); + arg = entities.variable() || entities.property() || entities.literal() || entities.keyword() || this.call(true); } if (!arg) { @@ -4497,7 +4750,7 @@ var Parser = function Parser(context, imports, fileInfo) { if (parserInput.$char(':')) { if (expressions.length > 0) { if (isSemiColonSeparated) { - error("Cannot mix ; and , as delimiter types"); + error('Cannot mix ; and , as delimiter types'); } expressionContainsNamed = true; } @@ -4506,7 +4759,7 @@ var Parser = function Parser(context, imports, fileInfo) { if (!value) { if (isCall) { - error("could not understand value for named argument"); + error('could not understand value for named argument'); } else { parserInput.restore(); returner.args = []; @@ -4514,10 +4767,10 @@ var Parser = function Parser(context, imports, fileInfo) { } } nameLoop = (name = val.name); - } else if (parserInput.$str("...")) { + } else if (parserInput.$str('...')) { if (!isCall) { returner.variadic = true; - if (parserInput.$char(";") && !isSemiColonSeparated) { + if (parserInput.$char(';') && !isSemiColonSeparated) { isSemiColonSeparated = true; } (isSemiColonSeparated ? argsSemiColon : argsComma) @@ -4545,7 +4798,7 @@ var Parser = function Parser(context, imports, fileInfo) { if (parserInput.$char(';') || isSemiColonSeparated) { if (expressionContainsNamed) { - error("Cannot mix ; and , as delimiter types"); + error('Cannot mix ; and , as delimiter types'); } isSemiColonSeparated = true; @@ -4607,13 +4860,13 @@ var Parser = function Parser(context, imports, fileInfo) { // .mixincall(@a: {rule: set;}); // so we have to be nice and restore if (!parserInput.$char(')')) { - parserInput.restore("Missing closing ')'"); + parserInput.restore('Missing closing \')\''); return; } parserInput.commentStore.length = 0; - if (parserInput.$str("when")) { // Guard + if (parserInput.$str('when')) { // Guard cond = expect(parsers.conditions, 'expected condition'); } @@ -4628,9 +4881,54 @@ var Parser = function Parser(context, imports, fileInfo) { } else { parserInput.forget(); } + }, + + ruleLookups: function() { + var rule, args, lookups = []; + + if (parserInput.currentChar() !== '[') { + return; + } + + while (true) { + parserInput.save(); + args = null; + rule = this.lookupValue(); + if (!rule && rule !== '') { + parserInput.restore(); + break; + } + lookups.push(rule); + parserInput.forget(); + } + if (lookups.length > 0) { + return lookups; + } + }, + + lookupValue: function() { + parserInput.save(); + + if (!parserInput.$char('[')) { + parserInput.restore(); + return; + } + + var name = parserInput.$re(/^(?:[@$]{0,2})[_a-zA-Z0-9-]*/); + + if (!parserInput.$char(']')) { + parserInput.restore(); + return; + } + + if (name || name === '') { + parserInput.forget(); + return name; + } + + parserInput.restore(); } }, - // // Entities are the smallest recognized token, // and can be found inside a rule's value. @@ -4639,7 +4937,8 @@ var Parser = function Parser(context, imports, fileInfo) { var entities = this.entities; return this.comment() || entities.literal() || entities.variable() || entities.url() || - entities.property() || entities.call() || entities.keyword() || entities.javascript(); + entities.property() || entities.call() || entities.keyword() || this.mixin.call(true) || + entities.javascript(); }, // @@ -4663,7 +4962,7 @@ var Parser = function Parser(context, imports, fileInfo) { if (!parserInput.$re(/^opacity=/i)) { return; } value = parserInput.$re(/^\d+/); if (!value) { - value = expect(parsers.entities.variable, "Could not parse alpha"); + value = expect(parsers.entities.variable, 'Could not parse alpha'); value = '@{' + value.name.slice(1) + '}'; } expectChar(')'); @@ -4700,14 +4999,14 @@ var Parser = function Parser(context, imports, fileInfo) { e = new(tree.Paren)(v); parserInput.forget(); } else { - parserInput.restore("Missing closing ')'"); + parserInput.restore('Missing closing \')\''); } } else { parserInput.forget(); } } - if (e) { return new(tree.Element)(c, e, index, fileInfo); } + if (e) { return new(tree.Element)(c, e, e instanceof tree.Variable, index, fileInfo); } }, // @@ -4741,7 +5040,7 @@ var Parser = function Parser(context, imports, fileInfo) { while (parserInput.isWhitespace()) { parserInput.i++; } return new(tree.Combinator)(c); } else if (parserInput.isWhitespace(-1)) { - return new(tree.Combinator)(" "); + return new(tree.Combinator)(' '); } else { return new(tree.Combinator)(null); } @@ -4758,11 +5057,11 @@ 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())) { + while ((isLess && (extendList = this.extend())) || (isLess && (when = parserInput.$str('when'))) || (e = this.element())) { if (when) { condition = expect(this.conditions, 'expected condition'); } else if (condition) { - error("CSS guard can only be used at the end of selector"); + error('CSS guard can only be used at the end of selector'); } else if (extendList) { if (allExtends) { allExtends = allExtends.concat(extendList); @@ -4770,7 +5069,7 @@ var Parser = function Parser(context, imports, fileInfo) { allExtends = extendList; } } else { - if (allExtends) { error("Extend can only be used at the end of selector"); } + if (allExtends) { error('Extend can only be used at the end of selector'); } c = parserInput.currentChar(); if (elements) { elements.push(e); @@ -4785,7 +5084,31 @@ var Parser = function Parser(context, imports, fileInfo) { } if (elements) { return new(tree.Selector)(elements, allExtends, condition, index, fileInfo); } - if (allExtends) { error("Extend must be used to extend a selector, it cannot be used on its own"); } + if (allExtends) { error('Extend must be used to extend a selector, it cannot be used on its own'); } + }, + selectors: function () { + var s, selectors; + while (true) { + s = this.selector(); + if (!s) { + break; + } + if (selectors) { + selectors.push(s); + } else { + selectors = [ s ]; + } + parserInput.commentStore.length = 0; + if (s.condition && selectors.length > 1) { + error("Guards are only currently allowed on a single selector."); + } + if (!parserInput.$char(',')) { break; } + if (s.condition) { + error("Guards are only currently allowed on a single selector."); + } + parserInput.commentStore.length = 0; + } + return selectors; }, attribute: function () { if (!parserInput.$char('[')) { return; } @@ -4838,7 +5161,7 @@ var Parser = function Parser(context, imports, fileInfo) { // div, .class, body > p {...} // ruleset: function () { - var selectors, s, rules, debugInfo; + var selectors, rules, debugInfo; parserInput.save(); @@ -4846,26 +5169,7 @@ var Parser = function Parser(context, imports, fileInfo) { debugInfo = getDebugInfo(parserInput.i); } - while (true) { - s = this.selector(); - if (!s) { - break; - } - if (selectors) { - selectors.push(s); - } else { - selectors = [ s ]; - } - parserInput.commentStore.length = 0; - if (s.condition && selectors.length > 1) { - error("Guards are only currently allowed on a single selector."); - } - if (!parserInput.$char(',')) { break; } - if (s.condition) { - error("Guards are only currently allowed on a single selector."); - } - parserInput.commentStore.length = 0; - } + selectors = this.selectors(); if (selectors && (rules = this.block())) { parserInput.forget(); @@ -4879,7 +5183,8 @@ var Parser = function Parser(context, imports, fileInfo) { } }, declaration: function () { - var name, value, startOfRule = parserInput.i, c = parserInput.currentChar(), important, merge, isVariable; + var name, value, index = parserInput.i, hasDR, + c = parserInput.currentChar(), important, merge, isVariable; if (c === '.' || c === '#' || c === '&' || c === ':') { return; } @@ -4887,10 +5192,13 @@ var Parser = function Parser(context, imports, fileInfo) { name = this.variable() || this.ruleProperty(); if (name) { - isVariable = typeof name === "string"; + isVariable = typeof name === 'string'; if (isVariable) { value = this.detachedRuleset(); + if (value) { + hasDR = true; + } } parserInput.commentStore.length = 0; @@ -4900,25 +5208,36 @@ 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; + // Custom property values get permissive parsing + if (name[0].value && name[0].value.slice(0, 2) === '--') { + value = this.permissiveValue(); + } // Try to store values as anonymous // If we need the value later we'll re-parse it in ruleset.parseValue - value = this.anonymousValue(); + else { + 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); + return new (tree.Declaration)(name, value, false, merge, index, fileInfo); } if (!value) { value = this.value(); } - important = this.important(); + if (value) { + important = this.important(); + } else if (isVariable) { + // As a last resort, try permissiveValue + value = this.permissiveValue(); + } } - if (value && this.end()) { + if (value && (this.end() || hasDR)) { parserInput.forget(); - return new (tree.Declaration)(name, value, important, merge, startOfRule, fileInfo); + return new (tree.Declaration)(name, value, important, merge, index, fileInfo); } else { parserInput.restore(); @@ -4929,11 +5248,99 @@ var Parser = function Parser(context, imports, fileInfo) { }, anonymousValue: function () { var index = parserInput.i; - var match = parserInput.$re(/^([^@\$+\/'"*`(;{}-]*);/); + var match = parserInput.$re(/^([^.#@\$+\/'"*`(;{}-]*);/); if (match) { return new(tree.Anonymous)(match[1], index); } }, + /** + * Used for custom properties, at-rules, and variables (as fallback) + * Parses almost anything inside of {} [] () "" blocks + * until it reaches outer-most tokens. + * + * First, it will try to parse comments and entities to reach + * the end. This is mostly like the Expression parser except no + * math is allowed. + */ + permissiveValue: function (untilTokens) { + var i, e, done, value, + tok = untilTokens || ';', + index = parserInput.i, result = []; + + function testCurrentChar() { + var char = parserInput.currentChar(); + if (typeof tok === 'string') { + return char === tok; + } else { + return tok.test(char); + } + } + if (testCurrentChar()) { + return; + } + value = []; + do { + e = this.comment(); + if (e) { + value.push(e); + continue; + } + e = this.entity(); + if (e) { + value.push(e); + } + } while (e); + + done = testCurrentChar(); + + if (value.length > 0) { + value = new(tree.Expression)(value); + if (done) { + return value; + } + else { + result.push(value); + } + // Preserve space before $parseUntil as it will not + if (parserInput.prevChar() === ' ') { + result.push(new tree.Anonymous(' ', index)); + } + } + parserInput.save(); + + value = parserInput.$parseUntil(tok); + + if (value) { + if (typeof value === 'string') { + error('Expected \'' + value + '\'', 'Parse'); + } + if (value.length === 1 && value[0] === ' ') { + parserInput.forget(); + return new tree.Anonymous('', index); + } + var item; + for (i = 0; i < value.length; i++) { + item = value[i]; + if (Array.isArray(item)) { + // Treat actual quotes as normal quoted values + result.push(new tree.Quoted(item[0], item[1], true, index, fileInfo)); + } + else { + if (i === value.length - 1) { + item = item.trim(); + } + // Treat like quoted values, but replace vars like unquoted expressions + var quote = new tree.Quoted('\'', item, true, index, fileInfo); + quote.variableRegex = /@([\w-]+)/g; + quote.propRegex = /\$([\w-]+)/g; + result.push(quote); + } + } + parserInput.forget(); + return new tree.Expression(result, true); + } + parserInput.restore(); + }, // // An @import atrule @@ -4945,7 +5352,7 @@ var Parser = function Parser(context, imports, fileInfo) { // file-system operation. The function used for importing is // stored in `import`, which we pass to the Import constructor. // - "import": function () { + 'import': function () { var path, features, index = parserInput.i; var dir = parserInput.$re(/^@import?\s+/); @@ -4958,14 +5365,14 @@ var Parser = function Parser(context, imports, fileInfo) { if (!parserInput.$char(';')) { parserInput.i = index; - error("missing semi-colon or unrecognised media features on import"); + error('missing semi-colon or unrecognised media features on import'); } features = features && new(tree.Value)(features); return new(tree.Import)(path, features, options, index, fileInfo); } else { parserInput.i = index; - error("malformed import statement"); + error('malformed import statement'); } } }, @@ -4981,12 +5388,12 @@ var Parser = function Parser(context, imports, fileInfo) { optionName = o; value = true; switch (optionName) { - case "css": - optionName = "less"; + case 'css': + optionName = 'less'; value = false; break; - case "once": - optionName = "multiple"; + case 'once': + optionName = 'multiple'; value = false; break; } @@ -5009,7 +5416,7 @@ var Parser = function Parser(context, imports, fileInfo) { var entities = this.entities, nodes = [], e, p; parserInput.save(); do { - e = entities.keyword() || entities.variable(); + e = entities.keyword() || entities.variable() || entities.mixinLookup(); if (e) { nodes.push(e); } else if (parserInput.$char('(')) { @@ -5021,10 +5428,10 @@ var Parser = function Parser(context, imports, fileInfo) { } else if (e) { nodes.push(new(tree.Paren)(e)); } else { - error("badly formed media feature definition"); + error('badly formed media feature definition'); } } else { - error("Missing closing ')'", "Parse"); + error('Missing closing \')\'', 'Parse'); } } } while (e); @@ -5043,7 +5450,7 @@ var Parser = function Parser(context, imports, fileInfo) { features.push(e); if (!parserInput.$char(',')) { break; } } else { - e = entities.variable(); + e = entities.variable() || entities.mixinLookup(); if (e) { features.push(e); if (!parserInput.$char(',')) { break; } @@ -5063,13 +5470,13 @@ var Parser = function Parser(context, imports, fileInfo) { parserInput.save(); - if (parserInput.$str("@media")) { + if (parserInput.$str('@media')) { features = this.mediaFeatures(); rules = this.block(); if (!rules) { - error("media definitions require block statements after any features"); + error('media definitions require block statements after any features'); } parserInput.forget(); @@ -5113,13 +5520,13 @@ var Parser = function Parser(context, imports, fileInfo) { 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'); } } }, @@ -5166,24 +5573,24 @@ var Parser = function Parser(context, imports, fileInfo) { nonVendorSpecificName = name; if (name.charAt(1) == '-' && name.indexOf('-', 2) > 0) { - nonVendorSpecificName = "@" + name.slice(name.indexOf('-', 2) + 1); + nonVendorSpecificName = '@' + name.slice(name.indexOf('-', 2) + 1); } switch (nonVendorSpecificName) { - case "@charset": + case '@charset': hasIdentifier = true; hasBlock = false; break; - case "@namespace": + case '@namespace': hasExpression = true; hasBlock = false; break; - case "@keyframes": - case "@counter-style": + case '@keyframes': + case '@counter-style': hasIdentifier = true; break; - case "@document": - case "@supports": + case '@document': + case '@supports': hasUnknown = true; isRooted = false; break; @@ -5197,18 +5604,23 @@ var Parser = function Parser(context, imports, fileInfo) { if (hasIdentifier) { value = this.entity(); if (!value) { - error("expected " + name + " identifier"); + error('expected ' + name + ' identifier'); } } else if (hasExpression) { value = this.expression(); if (!value) { - error("expected " + name + " expression"); + error('expected ' + name + ' expression'); } } else if (hasUnknown) { - value = (parserInput.$re(/^[^{;]+/) || '').trim(); - hasBlock = (parserInput.currentChar() == '{'); - if (value) { - value = new(tree.Anonymous)(value); + value = this.permissiveValue(/^[{;]/); + hasBlock = (parserInput.currentChar() === '{'); + if (!value) { + if (!hasBlock && parserInput.currentChar() !== ';') { + error(name + ' rule is missing block or ending semi-colon'); + } + } + else if (!value.value) { + value = null; } } @@ -5224,7 +5636,7 @@ var Parser = function Parser(context, imports, fileInfo) { ); } - parserInput.restore("at-rule options not recognised"); + parserInput.restore('at-rule options not recognised'); }, // @@ -5267,7 +5679,7 @@ var Parser = function Parser(context, imports, fileInfo) { e.parens = true; return e; } - parserInput.restore("Expected ')'"); + parserInput.restore('Expected \')\''); return; } parserInput.restore(); @@ -5345,7 +5757,7 @@ var Parser = function Parser(context, imports, fileInfo) { condition: function () { var result, logical, next; function or() { - return parserInput.$str("or"); + return parserInput.$str('or'); } result = this.conditionAnd(this); @@ -5369,7 +5781,7 @@ var Parser = function Parser(context, imports, fileInfo) { return me.negatedCondition() || me.parenthesisCondition(); } function and() { - return parserInput.$str("and"); + return parserInput.$str('and'); } result = insideCondition(this); @@ -5388,7 +5800,7 @@ var Parser = function Parser(context, imports, fileInfo) { return result; }, negatedCondition: function () { - if (parserInput.$str("not")) { + if (parserInput.$str('not')) { var result = this.parenthesisCondition(); if (result) { result.negate = !result.negate; @@ -5415,7 +5827,7 @@ var Parser = function Parser(context, imports, fileInfo) { var body; parserInput.save(); - if (!parserInput.$str("(")) { + if (!parserInput.$str('(')) { parserInput.restore(); return ; } @@ -5431,7 +5843,7 @@ var Parser = function Parser(context, imports, fileInfo) { return ; } if (!parserInput.$char(')')) { - parserInput.restore("expected ')' got '" + parserInput.currentChar() + "'"); + parserInput.restore('expected \')\' got \'' + parserInput.currentChar() + '\''); return ; } parserInput.forget(); @@ -5440,25 +5852,30 @@ var Parser = function Parser(context, imports, fileInfo) { atomicCondition: function () { var entities = this.entities, index = parserInput.i, a, b, c, op; - a = this.addition() || entities.keyword() || entities.quoted(); + function cond() { + return this.addition() || entities.keyword() || entities.quoted() || entities.mixinLookup(); + } + cond = cond.bind(this); + + a = cond(); if (a) { if (parserInput.$char('>')) { if (parserInput.$char('=')) { - op = ">="; + op = '>='; } else { op = '>'; } } else if (parserInput.$char('<')) { if (parserInput.$char('=')) { - op = "<="; + op = '<='; } else { op = '<'; } } else if (parserInput.$char('=')) { if (parserInput.$char('>')) { - op = "=>"; + op = '=>'; } else if (parserInput.$char('<')) { op = '=<'; } else { @@ -5466,7 +5883,7 @@ var Parser = function Parser(context, imports, fileInfo) { } } if (op) { - b = this.addition() || entities.keyword() || entities.quoted(); + b = cond(); if (b) { c = new(tree.Condition)(op, a, b, index, false); } else { @@ -5493,7 +5910,8 @@ var Parser = function Parser(context, imports, fileInfo) { var o = this.sub() || entities.dimension() || entities.color() || entities.variable() || entities.property() || entities.call() || - entities.colorKeyword(); + entities.quoted(true) || entities.colorKeyword() || + entities.mixinLookup(); if (negate) { o.parensInOp = true; @@ -5609,7 +6027,7 @@ Parser.serializeVars = function(vars) { module.exports = Parser; -},{"../functions/function-registry":26,"../less-error":36,"../tree":65,"../utils":86,"../visitors":90,"./parser-input":41}],43:[function(require,module,exports){ +},{"../functions/function-registry":26,"../less-error":36,"../tree":65,"../utils":87,"../visitors":91,"./parser-input":41}],43:[function(require,module,exports){ /** * Plugin Manager */ @@ -5813,7 +6231,7 @@ module.exports = function(environment, ParseTree, ImportManager) { return render; }; -},{"./utils":86,"promise":undefined}],45:[function(require,module,exports){ +},{"./utils":87,"promise":undefined}],45:[function(require,module,exports){ module.exports = function (SourceMapOutput, environment) { var SourceMapBuilder = function (options) { @@ -5853,15 +6271,15 @@ module.exports = function (SourceMapOutput, environment) { var sourceMapURL = this.sourceMapURL; if (this.options.sourceMapFileInline) { if (this.sourceMap === undefined) { - return ""; + return ''; } - sourceMapURL = "data:application/json;base64," + environment.encodeBase64(this.sourceMap); + sourceMapURL = 'data:application/json;base64,' + environment.encodeBase64(this.sourceMap); } if (sourceMapURL) { - return "/*# sourceMappingURL=" + sourceMapURL + " */"; + return '/*# sourceMappingURL=' + sourceMapURL + ' */'; } - return ""; + return ''; }; SourceMapBuilder.prototype.getExternalSourceMap = function() { @@ -5909,7 +6327,7 @@ module.exports = function (environment) { this._sourceMapRootpath += '/'; } } else { - this._sourceMapRootpath = ""; + this._sourceMapRootpath = ''; } this._outputSourceFiles = options.outputSourceFiles; this._sourceMapGeneratorConstructor = environment.getSourceMapGenerator(); @@ -5932,7 +6350,7 @@ module.exports = function (environment) { SourceMapOutput.prototype.normalizeFilename = function(filename) { filename = filename.replace(/\\/g, '/'); filename = this.removeBasepath(filename); - return (this._sourceMapRootpath || "") + filename; + return (this._sourceMapRootpath || '') + filename; }; SourceMapOutput.prototype.add = function(chunk, fileInfo, index, mapLines) { @@ -5960,11 +6378,11 @@ module.exports = function (environment) { inputSource = inputSource.slice(this._contentsIgnoredCharsMap[fileInfo.filename]); } inputSource = inputSource.substring(0, index); - sourceLines = inputSource.split("\n"); + sourceLines = inputSource.split('\n'); sourceColumns = sourceLines[sourceLines.length - 1]; } - lines = chunk.split("\n"); + lines = chunk.split('\n'); columns = lines[lines.length - 1]; if (fileInfo) { @@ -6033,9 +6451,9 @@ module.exports = function (environment) { }; },{}],47:[function(require,module,exports){ -var contexts = require("./contexts"), - visitor = require("./visitors"), - tree = require("./tree"); +var contexts = require('./contexts'), + visitor = require('./visitors'), + tree = require('./tree'); module.exports = function(root, options) { options = options || {}; @@ -6076,29 +6494,49 @@ module.exports = function(root, options) { new visitor.MarkVisibleSelectorsVisitor(true), new visitor.ExtendVisitor(), new visitor.ToCSSVisitor({compress: Boolean(options.compress)}) - ], v, visitorIterator; + ], preEvalVisitors = [], v, visitorIterator; - // first() / get() allows visitors to be added while visiting + /** + * first() / get() allows visitors to be added while visiting + * + * @todo Add scoping for visitors just like functions for @plugin; right now they're global + */ if (options.pluginManager) { visitorIterator = options.pluginManager.visitor(); - visitorIterator.first(); - while ((v = visitorIterator.get())) { - if (v.isPreEvalVisitor) { - v.run(root); + for (var i = 0; i < 2; i++) { + visitorIterator.first(); + while ((v = visitorIterator.get())) { + if (v.isPreEvalVisitor) { + if (i === 0 || preEvalVisitors.indexOf(v) === -1) { + preEvalVisitors.push(v); + v.run(root); + } + } + else { + if (i === 0 || visitors.indexOf(v) === -1) { + if (v.isPreVisitor) { + visitors.unshift(v); + } + else { + visitors.push(v); + } + } + } } } } - + evaldRoot = root.eval(evalEnv); for (var i = 0; i < visitors.length; i++) { visitors[i].run(evaldRoot); } + // Run any remaining visitors added after eval pass if (options.pluginManager) { visitorIterator.first(); while ((v = visitorIterator.get())) { - if (!v.isPreEvalVisitor) { + if (visitors.indexOf(v) === -1 && preEvalVisitors.indexOf(v) === -1) { v.run(evaldRoot); } } @@ -6107,8 +6545,8 @@ module.exports = function(root, options) { return evaldRoot; }; -},{"./contexts":12,"./tree":65,"./visitors":90}],48:[function(require,module,exports){ -var Node = require("./node"); +},{"./contexts":12,"./tree":65,"./visitors":91}],48:[function(require,module,exports){ +var Node = require('./node'); var Anonymous = function (value, index, currentFileInfo, mapLines, rulesetLike, visibilityInfo) { this.value = value; @@ -6120,7 +6558,7 @@ var Anonymous = function (value, index, currentFileInfo, mapLines, rulesetLike, this.copyVisibilityInfo(visibilityInfo); }; Anonymous.prototype = new Node(); -Anonymous.prototype.type = "Anonymous"; +Anonymous.prototype.type = 'Anonymous'; Anonymous.prototype.eval = function () { return new Anonymous(this.value, this._index, this._fileInfo, this.mapLines, this.rulesetLike, this.visibilityInfo()); }; @@ -6138,8 +6576,8 @@ Anonymous.prototype.genCSS = function (context, output) { }; module.exports = Anonymous; -},{"./node":73}],49:[function(require,module,exports){ -var Node = require("./node"); +},{"./node":74}],49:[function(require,module,exports){ +var Node = require('./node'); var Assignment = function (key, val) { this.key = key; @@ -6147,7 +6585,7 @@ var Assignment = function (key, val) { }; Assignment.prototype = new Node(); -Assignment.prototype.type = "Assignment"; +Assignment.prototype.type = 'Assignment'; Assignment.prototype.accept = function (visitor) { this.value = visitor.visit(this.value); }; @@ -6167,10 +6605,10 @@ Assignment.prototype.genCSS = function (context, output) { }; module.exports = Assignment; -},{"./node":73}],50:[function(require,module,exports){ -var Node = require("./node"), - Selector = require("./selector"), - Ruleset = require("./ruleset"), +},{"./node":74}],50:[function(require,module,exports){ +var Node = require('./node'), + Selector = require('./selector'), + Ruleset = require('./ruleset'), Anonymous = require('./anonymous'); var AtRule = function (name, value, rules, index, currentFileInfo, debugInfo, isRooted, visibilityInfo) { @@ -6199,7 +6637,7 @@ var AtRule = function (name, value, rules, index, currentFileInfo, debugInfo, is }; AtRule.prototype = new Node(); -AtRule.prototype.type = "AtRule"; +AtRule.prototype.type = 'AtRule'; AtRule.prototype.accept = function (visitor) { var value = this.value, rules = this.rules; if (rules) { @@ -6213,7 +6651,7 @@ AtRule.prototype.isRulesetLike = function() { return this.rules || !this.isCharset(); }; AtRule.prototype.isCharset = function() { - return "@charset" === this.name; + return '@charset' === this.name; }; AtRule.prototype.genCSS = function (context, output) { var value = this.value, rules = this.rules; @@ -6288,11 +6726,11 @@ AtRule.prototype.outputRuleset = function (context, output, rules) { } // Non-compressed - var tabSetStr = '\n' + Array(context.tabLevel).join(" "), tabRuleStr = tabSetStr + " "; + var tabSetStr = '\n' + Array(context.tabLevel).join(' '), tabRuleStr = tabSetStr + ' '; if (!ruleCnt) { - output.add(" {" + tabSetStr + '}'); + output.add(' {' + tabSetStr + '}'); } else { - output.add(" {" + tabRuleStr); + output.add(' {' + tabRuleStr); rules[0].genCSS(context, output); for (i = 1; i < ruleCnt; i++) { output.add(tabRuleStr); @@ -6305,8 +6743,8 @@ AtRule.prototype.outputRuleset = function (context, output, rules) { }; module.exports = AtRule; -},{"./anonymous":48,"./node":73,"./ruleset":78,"./selector":79}],51:[function(require,module,exports){ -var Node = require("./node"); +},{"./anonymous":48,"./node":74,"./ruleset":79,"./selector":80}],51:[function(require,module,exports){ +var Node = require('./node'); var Attribute = function (key, op, value) { this.key = key; @@ -6314,7 +6752,7 @@ var Attribute = function (key, op, value) { this.value = value; }; Attribute.prototype = new Node(); -Attribute.prototype.type = "Attribute"; +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); @@ -6334,22 +6772,22 @@ Attribute.prototype.toCSS = function (context) { }; module.exports = Attribute; -},{"./node":73}],52:[function(require,module,exports){ -var Node = require("./node"), - Anonymous = require("./anonymous"), - FunctionCaller = require("../functions/function-caller"); +},{"./node":74}],52:[function(require,module,exports){ +var Node = require('./node'), + Anonymous = require('./anonymous'), + FunctionCaller = require('../functions/function-caller'); // // A function call node. // var Call = function (name, args, index, currentFileInfo) { this.name = name; this.args = args; - this.mathOn = name === 'calc' ? false : true; + this.calc = name === 'calc'; this._index = index; this._fileInfo = currentFileInfo; }; Call.prototype = new Node(); -Call.prototype.type = "Call"; +Call.prototype.type = 'Call'; Call.prototype.accept = function (visitor) { if (this.args) { this.args = visitor.visitArray(this.args); @@ -6367,13 +6805,18 @@ Call.prototype.accept = function (visitor) { // The function should receive the value, not the variable. // Call.prototype.eval = function (context) { - /** * Turn off math for calc(), and switch back on for evaluating nested functions */ var currentMathContext = context.mathOn; - context.mathOn = this.mathOn; + context.mathOn = !this.calc; + if (this.calc || context.inCalc) { + context.enterCalc(); + } var args = this.args.map(function (a) { return a.eval(context); }); + if (this.calc || context.inCalc) { + context.exitCalc(); + } context.mathOn = currentMathContext; var result, funcCaller = new FunctionCaller(this.name, context, this.getIndex(), this.fileInfo()); @@ -6383,8 +6826,8 @@ Call.prototype.eval = function (context) { result = funcCaller.call(args); } catch (e) { throw { - type: e.type || "Runtime", - message: "error evaluating function `" + this.name + "`" + + type: e.type || 'Runtime', + message: 'error evaluating function `' + this.name + '`' + (e.message ? ': ' + e.message : ''), index: this.getIndex(), filename: this.fileInfo().filename, @@ -6415,22 +6858,22 @@ Call.prototype.eval = function (context) { return new Call(this.name, args, this.getIndex(), this.fileInfo()); }; Call.prototype.genCSS = function (context, output) { - output.add(this.name + "(", this.fileInfo(), this.getIndex()); + output.add(this.name + '(', this.fileInfo(), this.getIndex()); for (var i = 0; i < this.args.length; i++) { this.args[i].genCSS(context, output); if (i + 1 < this.args.length) { - output.add(", "); + output.add(', '); } } - output.add(")"); + output.add(')'); }; module.exports = Call; -},{"../functions/function-caller":25,"./anonymous":48,"./node":73}],53:[function(require,module,exports){ -var Node = require("./node"), - colors = require("../data/colors"); +},{"../functions/function-caller":25,"./anonymous":48,"./node":74}],53:[function(require,module,exports){ +var Node = require('./node'), + colors = require('../data/colors'); // // RGB Colors - #ff0014, #eee @@ -6460,7 +6903,7 @@ var Color = function (rgb, a, originalForm) { }; Color.prototype = new Node(); -Color.prototype.type = "Color"; +Color.prototype.type = 'Color'; function clamp(v, max) { return Math.min(Math.max(v, 0), max); @@ -6503,10 +6946,10 @@ Color.prototype.toCSS = function (context, doNotCompress) { // Values are capped between `0` and `255`, rounded and zero-padded. alpha = this.fround(context, this.alpha); if (alpha < 1) { - return "rgba(" + this.rgb.map(function (c) { + return 'rgba(' + this.rgb.map(function (c) { return clamp(Math.round(c), 255); }).concat(clamp(alpha, 1)) - .join(',' + (compress ? '' : ' ')) + ")"; + .join(',' + (compress ? '' : ' ')) + ')'; } color = this.toRGB(); @@ -6608,7 +7051,7 @@ Color.fromKeyword = function(keyword) { if (colors.hasOwnProperty(key)) { c = new Color(colors[key].slice(1)); } - else if (key === "transparent") { + else if (key === 'transparent') { c = new Color([0, 0, 0], 0); } @@ -6619,20 +7062,20 @@ Color.fromKeyword = function(keyword) { }; module.exports = Color; -},{"../data/colors":13,"./node":73}],54:[function(require,module,exports){ -var Node = require("./node"); +},{"../data/colors":13,"./node":74}],54:[function(require,module,exports){ +var Node = require('./node'); var Combinator = function (value) { if (value === ' ') { this.value = ' '; this.emptyOrWhitespace = true; } else { - this.value = value ? value.trim() : ""; - this.emptyOrWhitespace = this.value === ""; + this.value = value ? value.trim() : ''; + this.emptyOrWhitespace = this.value === ''; } }; Combinator.prototype = new Node(); -Combinator.prototype.type = "Combinator"; +Combinator.prototype.type = 'Combinator'; var _noSpaceCombinators = { '': true, ' ': true, @@ -6644,9 +7087,9 @@ Combinator.prototype.genCSS = function (context, output) { }; module.exports = Combinator; -},{"./node":73}],55:[function(require,module,exports){ -var Node = require("./node"), - getDebugInfo = require("./debug-info"); +},{"./node":74}],55:[function(require,module,exports){ +var Node = require('./node'), + getDebugInfo = require('./debug-info'); var Comment = function (value, isLineComment, index, currentFileInfo) { this.value = value; @@ -6656,7 +7099,7 @@ var Comment = function (value, isLineComment, index, currentFileInfo) { this.allowRoot = true; }; Comment.prototype = new Node(); -Comment.prototype.type = "Comment"; +Comment.prototype.type = 'Comment'; Comment.prototype.genCSS = function (context, output) { if (this.debugInfo) { output.add(getDebugInfo(context, this), this.fileInfo(), this.getIndex()); @@ -6664,13 +7107,13 @@ Comment.prototype.genCSS = function (context, output) { output.add(this.value); }; Comment.prototype.isSilent = function(context) { - var isCompressed = context.compress && this.value[2] !== "!"; + var isCompressed = context.compress && this.value[2] !== '!'; return this.isLineComment || isCompressed; }; module.exports = Comment; -},{"./debug-info":57,"./node":73}],56:[function(require,module,exports){ -var Node = require("./node"); +},{"./debug-info":57,"./node":74}],56:[function(require,module,exports){ +var Node = require('./node'); var Condition = function (op, l, r, i, negate) { this.op = op.trim(); @@ -6680,7 +7123,7 @@ var Condition = function (op, l, r, i, negate) { this.negate = negate; }; Condition.prototype = new Node(); -Condition.prototype.type = "Condition"; +Condition.prototype.type = 'Condition'; Condition.prototype.accept = function (visitor) { this.lvalue = visitor.visit(this.lvalue); this.rvalue = visitor.visit(this.rvalue); @@ -6708,9 +7151,9 @@ Condition.prototype.eval = function (context) { }; module.exports = Condition; -},{"./node":73}],57:[function(require,module,exports){ +},{"./node":74}],57:[function(require,module,exports){ var debugInfo = function(context, ctx, lineSeparator) { - var result = ""; + var result = ''; if (context.dumpLineNumbers && !context.compress) { switch (context.dumpLineNumbers) { case 'comments': @@ -6720,7 +7163,7 @@ var debugInfo = function(context, ctx, lineSeparator) { result = debugInfo.asMediaQuery(ctx); break; case 'all': - result = debugInfo.asComment(ctx) + (lineSeparator || "") + debugInfo.asMediaQuery(ctx); + result = debugInfo.asComment(ctx) + (lineSeparator || '') + debugInfo.asMediaQuery(ctx); break; } } @@ -6749,10 +7192,10 @@ debugInfo.asMediaQuery = function(ctx) { module.exports = debugInfo; },{}],58:[function(require,module,exports){ -var Node = require("./node"), - Value = require("./value"), - Keyword = require("./keyword"), - Anonymous = require("./anonymous"); +var Node = require('./node'), + Value = require('./value'), + Keyword = require('./keyword'), + Anonymous = require('./anonymous'); var Declaration = function (name, value, important, merge, index, currentFileInfo, inline, variable) { this.name = name; @@ -6769,7 +7212,7 @@ var Declaration = function (name, value, important, merge, index, currentFileInf }; function evalName(context, name) { - var value = "", i, n = name.length, + 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); @@ -6778,7 +7221,7 @@ function evalName(context, name) { } Declaration.prototype = new Node(); -Declaration.prototype.type = "Declaration"; +Declaration.prototype.type = 'Declaration'; Declaration.prototype.genCSS = function (context, output) { output.add(this.name + (context.compress ? ':' : ': '), this.fileInfo(), this.getIndex()); try { @@ -6789,18 +7232,18 @@ Declaration.prototype.genCSS = function (context, output) { e.filename = this._fileInfo.filename; throw e; } - output.add(this.important + ((this.inline || (context.lastRule && context.compress)) ? "" : ";"), this._fileInfo, this._index); + 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") { + 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) { + if (name === 'font' && !context.strictMath) { strictMathBypass = true; context.strictMath = true; } @@ -6808,8 +7251,8 @@ Declaration.prototype.eval = function (context) { context.importantScope.push({}); evaldValue = this.value.eval(context); - if (!this.variable && evaldValue.type === "DetachedRuleset") { - throw { message: "Rulesets cannot be evaluated on a property.", + 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, @@ -6841,16 +7284,16 @@ Declaration.prototype.eval = function (context) { Declaration.prototype.makeImportant = function () { return new Declaration(this.name, this.value, - "!important", + '!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"); +},{"./anonymous":48,"./keyword":68,"./node":74,"./value":84}],59:[function(require,module,exports){ +var Node = require('./node'), + contexts = require('../contexts'), + utils = require('../utils'); var DetachedRuleset = function (ruleset, frames) { this.ruleset = ruleset; @@ -6858,7 +7301,7 @@ var DetachedRuleset = function (ruleset, frames) { this.setParent(this.ruleset, this); }; DetachedRuleset.prototype = new Node(); -DetachedRuleset.prototype.type = "DetachedRuleset"; +DetachedRuleset.prototype.type = 'DetachedRuleset'; DetachedRuleset.prototype.evalFirst = true; DetachedRuleset.prototype.accept = function (visitor) { this.ruleset = visitor.visit(this.ruleset); @@ -6872,11 +7315,11 @@ DetachedRuleset.prototype.callEval = function (context) { }; module.exports = DetachedRuleset; -},{"../contexts":12,"../utils":86,"./node":73}],60:[function(require,module,exports){ -var Node = require("./node"), - unitConversions = require("../data/unit-conversions"), - Unit = require("./unit"), - Color = require("./color"); +},{"../contexts":12,"../utils":87,"./node":74}],60:[function(require,module,exports){ +var Node = require('./node'), + unitConversions = require('../data/unit-conversions'), + Unit = require('./unit'), + Color = require('./color'); // // A number with a unit @@ -6884,7 +7327,7 @@ 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."); + throw new Error('Dimension is not a number.'); } this.unit = (unit && unit instanceof Unit) ? unit : new Unit(unit ? [unit] : undefined); @@ -6892,7 +7335,7 @@ var Dimension = function (value, unit) { }; Dimension.prototype = new Node(); -Dimension.prototype.type = "Dimension"; +Dimension.prototype.type = 'Dimension'; Dimension.prototype.accept = function (visitor) { this.unit = visitor.visit(this.unit); }; @@ -6904,7 +7347,7 @@ Dimension.prototype.toColor = function () { }; Dimension.prototype.genCSS = function (context, output) { if ((context && context.strictUnits) && !this.unit.isSingular()) { - throw new Error("Multiple units in dimension. Correct the units or use the unit function. Bad unit: " + this.unit.toString()); + throw new Error('Multiple units in dimension. Correct the units or use the unit function. Bad unit: ' + this.unit.toString()); } var value = this.fround(context, this.value), @@ -6912,7 +7355,7 @@ Dimension.prototype.genCSS = function (context, output) { if (value !== 0 && value < 0.000001 && value > -0.000001) { // would be output 1e-6 etc. - strValue = value.toFixed(20).replace(/0+$/, ""); + strValue = value.toFixed(20).replace(/0+$/, ''); } if (context && context.compress) { @@ -6952,8 +7395,8 @@ Dimension.prototype.operate = function (context, op, other) { other = other.convertTo(this.unit.usedUnits()); if (context.strictUnits && other.unit.toString() !== unit.toString()) { - throw new Error("Incompatible units. Change the units or use the unit function. Bad units: '" + unit.toString() + - "' and '" + other.unit.toString() + "'."); + throw new Error('Incompatible units. Change the units or use the unit function. Bad units: \'' + unit.toString() + + '\' and \'' + other.unit.toString() + '\'.'); } value = this._operate(context, op, this.value, other.value); @@ -7035,12 +7478,12 @@ Dimension.prototype.convertTo = function (conversions) { }; module.exports = Dimension; -},{"../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"); +},{"../data/unit-conversions":15,"./color":53,"./node":74,"./unit":82}],61:[function(require,module,exports){ +var Node = require('./node'), + Paren = require('./paren'), + Combinator = require('./combinator'); -var Element = function (combinator, value, index, currentFileInfo, visibilityInfo) { +var Element = function (combinator, value, isVariable, index, currentFileInfo, visibilityInfo) { this.combinator = combinator instanceof Combinator ? combinator : new Combinator(combinator); @@ -7049,31 +7492,34 @@ var Element = function (combinator, value, index, currentFileInfo, visibilityInf } else if (value) { this.value = value; } else { - this.value = ""; + this.value = ''; } + this.isVariable = isVariable; this._index = index; this._fileInfo = currentFileInfo; this.copyVisibilityInfo(visibilityInfo); this.setParent(this.combinator, this); }; Element.prototype = new Node(); -Element.prototype.type = "Element"; +Element.prototype.type = 'Element'; Element.prototype.accept = function (visitor) { var value = this.value; this.combinator = visitor.visit(this.combinator); - if (typeof value === "object") { + if (typeof value === 'object') { this.value = visitor.visit(value); } }; Element.prototype.eval = function (context) { return new Element(this.combinator, this.value.eval ? this.value.eval(context) : this.value, + this.isVariable, this.getIndex(), this.fileInfo(), this.visibilityInfo()); }; Element.prototype.clone = function () { return new Element(this.combinator, this.value, + this.isVariable, this.getIndex(), this.fileInfo(), this.visibilityInfo()); }; @@ -7098,24 +7544,26 @@ Element.prototype.toCSS = function (context) { }; module.exports = Element; -},{"./combinator":54,"./node":73,"./paren":75}],62:[function(require,module,exports){ -var Node = require("./node"), - Paren = require("./paren"), - Comment = require("./comment"); +},{"./combinator":54,"./node":74,"./paren":76}],62:[function(require,module,exports){ +var Node = require('./node'), + Paren = require('./paren'), + Comment = require('./comment'); -var Expression = function (value) { +var Expression = function (value, noSpacing) { this.value = value; + this.noSpacing = noSpacing; if (!value) { - throw new Error("Expression requires an array parameter"); + throw new Error('Expression requires an array parameter'); } }; Expression.prototype = new Node(); -Expression.prototype.type = "Expression"; +Expression.prototype.type = 'Expression'; Expression.prototype.accept = function (visitor) { this.value = visitor.visitArray(this.value); }; Expression.prototype.eval = function (context) { var returnValue, + mathOn = context.isMathOn(), inParenthesis = this.parens && !this.parensInOp, doubleParen = false; if (inParenthesis) { @@ -7123,10 +7571,13 @@ Expression.prototype.eval = function (context) { } if (this.value.length > 1) { returnValue = new Expression(this.value.map(function (e) { + if (!e.eval) { + return e; + } return e.eval(context); - })); + }), this.noSpacing); } else if (this.value.length === 1) { - if (this.value[0].parens && !this.value[0].parensInOp) { + if (this.value[0].parens && !this.value[0].parensInOp && !context.inCalc) { doubleParen = true; } returnValue = this.value[0].eval(context); @@ -7136,7 +7587,7 @@ Expression.prototype.eval = function (context) { if (inParenthesis) { context.outOfParenthesis(); } - if (this.parens && this.parensInOp && !(context.isMathOn()) && !doubleParen) { + if (this.parens && this.parensInOp && !mathOn && !doubleParen) { returnValue = new Paren(returnValue); } return returnValue; @@ -7144,8 +7595,8 @@ Expression.prototype.eval = function (context) { Expression.prototype.genCSS = function (context, output) { for (var i = 0; i < this.value.length; i++) { this.value[i].genCSS(context, output); - if (i + 1 < this.value.length) { - output.add(" "); + if (!this.noSpacing && i + 1 < this.value.length) { + output.add(' '); } } }; @@ -7156,9 +7607,9 @@ Expression.prototype.throwAwayComments = function () { }; module.exports = Expression; -},{"./comment":55,"./node":73,"./paren":75}],63:[function(require,module,exports){ -var Node = require("./node"), - Selector = require("./selector"); +},{"./comment":55,"./node":74,"./paren":76}],63:[function(require,module,exports){ +var Node = require('./node'), + Selector = require('./selector'); var Extend = function Extend(selector, option, index, currentFileInfo, visibilityInfo) { this.selector = selector; @@ -7171,7 +7622,7 @@ var Extend = function Extend(selector, option, index, currentFileInfo, visibilit this.allowRoot = true; switch (option) { - case "all": + case 'all': this.allowBefore = true; this.allowAfter = true; break; @@ -7185,7 +7636,7 @@ var Extend = function Extend(selector, option, index, currentFileInfo, visibilit Extend.next_id = 0; Extend.prototype = new Node(); -Extend.prototype.type = "Extend"; +Extend.prototype.type = 'Extend'; Extend.prototype.accept = function (visitor) { this.selector = visitor.visit(this.selector); }; @@ -7205,7 +7656,7 @@ Extend.prototype.findSelfSelectors = function (selectors) { selectorElements = selectors[i].elements; // duplicate the logic in genCSS function inside the selector node. // future TODO - move both logics into the selector joiner visitor - if (i > 0 && selectorElements.length && selectorElements[0].combinator.value === "") { + if (i > 0 && selectorElements.length && selectorElements[0].combinator.value === '') { selectorElements[0].combinator.value = ' '; } selfElements = selfElements.concat(selectors[i].elements); @@ -7216,15 +7667,15 @@ Extend.prototype.findSelfSelectors = function (selectors) { }; module.exports = Extend; -},{"./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"), - utils = require("../utils"), - LessError = require("../less-error"); +},{"./node":74,"./selector":80}],64:[function(require,module,exports){ +var Node = require('./node'), + Media = require('./media'), + URL = require('./url'), + Quoted = require('./quoted'), + Ruleset = require('./ruleset'), + Anonymous = require('./anonymous'), + utils = require('../utils'), + LessError = require('../less-error'); // // CSS @import node @@ -7269,7 +7720,7 @@ var Import = function (path, features, options, index, currentFileInfo, visibili // ruleset. // Import.prototype = new Node(); -Import.prototype.type = "Import"; +Import.prototype.type = 'Import'; Import.prototype.accept = function (visitor) { if (this.features) { this.features = visitor.visit(this.features); @@ -7281,10 +7732,10 @@ Import.prototype.accept = function (visitor) { }; Import.prototype.genCSS = function (context, output) { if (this.css && this.path._fileInfo.reference === undefined) { - output.add("@import ", this._fileInfo, this._index); + output.add('@import ', this._fileInfo, this._index); this.path.genCSS(context, output); if (this.features) { - output.add(" "); + output.add(' '); this.features.genCSS(context, output); } output.add(';'); @@ -7355,7 +7806,7 @@ Import.prototype.doEval = function (context) { this.root.eval(context); } catch (e) { - e.message = "Plugin error during evaluation"; + e.message = 'Plugin error during evaluation'; throw new LessError(e, this.root.imports, this.root.filename); } } @@ -7368,7 +7819,7 @@ Import.prototype.doEval = function (context) { } if (this.skip) { - if (typeof this.skip === "function") { + if (typeof this.skip === 'function') { this.skip = this.skip(); } if (this.skip) { @@ -7398,7 +7849,7 @@ Import.prototype.doEval = function (context) { }; module.exports = Import; -},{"../less-error":36,"../utils":86,"./anonymous":48,"./media":69,"./node":73,"./quoted":77,"./ruleset":78,"./url":82}],65:[function(require,module,exports){ +},{"../less-error":36,"../utils":87,"./anonymous":48,"./media":69,"./node":74,"./quoted":78,"./ruleset":79,"./url":83}],65:[function(require,module,exports){ var tree = Object.create(null); tree.Node = require('./node'); @@ -7438,14 +7889,15 @@ tree.UnicodeDescriptor = require('./unicode-descriptor'); tree.Negative = require('./negative'); tree.Extend = require('./extend'); tree.VariableCall = require('./variable-call'); +tree.NamespaceValue = require('./namespace-value'); module.exports = tree; -},{"./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"), - Anonymous = require("./anonymous"); +},{"./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,"./namespace-value":72,"./negative":73,"./node":74,"./operation":75,"./paren":76,"./property":77,"./quoted":78,"./ruleset":79,"./selector":80,"./unicode-descriptor":81,"./unit":82,"./url":83,"./value":84,"./variable":86,"./variable-call":85}],66:[function(require,module,exports){ +var JsEvalNode = require('./js-eval-node'), + Dimension = require('./dimension'), + Quoted = require('./quoted'), + Anonymous = require('./anonymous'); var JavaScript = function (string, escaped, index, currentFileInfo) { this.escaped = escaped; @@ -7454,13 +7906,14 @@ var JavaScript = function (string, escaped, index, currentFileInfo) { this._fileInfo = currentFileInfo; }; JavaScript.prototype = new JsEvalNode(); -JavaScript.prototype.type = "JavaScript"; +JavaScript.prototype.type = 'JavaScript'; JavaScript.prototype.eval = function(context) { var result = this.evaluateJavaScript(this.expression, context); + var type = typeof result; - if (typeof result === 'number') { + if (type === 'number' && !isNaN(result)) { return new Dimension(result); - } else if (typeof result === 'string') { + } else if (type === 'string') { return new Quoted('"' + result + '"', result, this.escaped, this._index); } else if (Array.isArray(result)) { return new Anonymous(result.join(', ')); @@ -7471,9 +7924,9 @@ JavaScript.prototype.eval = function(context) { module.exports = JavaScript; -},{"./anonymous":48,"./dimension":60,"./js-eval-node":67,"./quoted":77}],67:[function(require,module,exports){ -var Node = require("./node"), - Variable = require("./variable"); +},{"./anonymous":48,"./dimension":60,"./js-eval-node":67,"./quoted":78}],67:[function(require,module,exports){ +var Node = require('./node'), + Variable = require('./variable'); var JsEvalNode = function() { }; @@ -7485,7 +7938,7 @@ JsEvalNode.prototype.evaluateJavaScript = function (expression, context) { evalContext = {}; if (!context.javascriptEnabled) { - throw { message: "Inline JavaScript is not enabled. Is it set in your options?", + throw { message: 'Inline JavaScript is not enabled. Is it set in your options?', filename: this.fileInfo().filename, index: this.getIndex() }; } @@ -7497,7 +7950,7 @@ JsEvalNode.prototype.evaluateJavaScript = function (expression, context) { try { expression = new Function('return (' + expression + ')'); } catch (e) { - throw { message: "JavaScript evaluation error: " + e.message + " from `" + expression + "`" , + throw { message: 'JavaScript evaluation error: ' + e.message + ' from `' + expression + '`' , filename: this.fileInfo().filename, index: this.getIndex() }; } @@ -7518,7 +7971,7 @@ JsEvalNode.prototype.evaluateJavaScript = function (expression, context) { try { result = expression.call(evalContext); } catch (e) { - throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message.replace(/["]/g, "'") + "'" , + throw { message: 'JavaScript evaluation error: \'' + e.name + ': ' + e.message.replace(/["]/g, '\'') + '\'' , filename: this.fileInfo().filename, index: this.getIndex() }; } @@ -7534,14 +7987,14 @@ JsEvalNode.prototype.jsify = function (obj) { module.exports = JsEvalNode; -},{"./node":73,"./variable":85}],68:[function(require,module,exports){ -var Node = require("./node"); +},{"./node":74,"./variable":86}],68:[function(require,module,exports){ +var Node = require('./node'); var Keyword = function (value) { this.value = value; }; Keyword.prototype = new Node(); -Keyword.prototype.type = "Keyword"; +Keyword.prototype.type = 'Keyword'; Keyword.prototype.genCSS = function (context, output) { - if (this.value === '%') { throw { type: "Syntax", message: "Invalid % without number" }; } + if (this.value === '%') { throw { type: 'Syntax', message: 'Invalid % without number' }; } output.add(this.value); }; @@ -7550,14 +8003,14 @@ Keyword.False = new Keyword('false'); module.exports = Keyword; -},{"./node":73}],69:[function(require,module,exports){ -var Ruleset = require("./ruleset"), - Value = require("./value"), - Selector = require("./selector"), - Anonymous = require("./anonymous"), - Expression = require("./expression"), - AtRule = require("./atrule"), - utils = require("../utils"); +},{"./node":74}],69:[function(require,module,exports){ +var Ruleset = require('./ruleset'), + Value = require('./value'), + Selector = require('./selector'), + Anonymous = require('./anonymous'), + Expression = require('./expression'), + AtRule = require('./atrule'), + utils = require('../utils'); var Media = function (value, features, index, currentFileInfo, visibilityInfo) { this._index = index; @@ -7575,7 +8028,7 @@ var Media = function (value, features, index, currentFileInfo, visibilityInfo) { this.setParent(this.rules, this); }; Media.prototype = new AtRule(); -Media.prototype.type = "Media"; +Media.prototype.type = 'Media'; Media.prototype.isRulesetLike = function() { return true; }; Media.prototype.accept = function (visitor) { if (this.features) { @@ -7658,7 +8111,7 @@ Media.prototype.evalNested = function (context) { }); for (i = path.length - 1; i > 0; i--) { - path.splice(i, 0, new Anonymous("and")); + path.splice(i, 0, new Anonymous('and')); } return new Expression(path); @@ -7693,11 +8146,11 @@ Media.prototype.bubbleSelectors = function (selectors) { }; module.exports = Media; -},{"../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"), - defaultFunc = require("../functions/default"); +},{"../utils":87,"./anonymous":48,"./atrule":50,"./expression":62,"./ruleset":79,"./selector":80,"./value":84}],70:[function(require,module,exports){ +var Node = require('./node'), + Selector = require('./selector'), + MixinDefinition = require('./mixin-definition'), + defaultFunc = require('../functions/default'); var MixinCall = function (elements, args, index, currentFileInfo, important) { this.selector = new Selector(elements); @@ -7709,7 +8162,7 @@ var MixinCall = function (elements, args, index, currentFileInfo, important) { this.setParent(this.selector, this); }; MixinCall.prototype = new Node(); -MixinCall.prototype.type = "MixinCall"; +MixinCall.prototype.type = 'MixinCall'; MixinCall.prototype.accept = function (visitor) { if (this.selector) { this.selector = visitor.visit(this.selector); @@ -7724,6 +8177,8 @@ MixinCall.prototype.eval = function (context) { candidates = [], candidate, conditionResult = [], defaultResult, defFalseEitherCase = -1, defNone = 0, defTrue = 1, defFalse = 2, count, originalRuleset, noArgumentsFilter; + this.selector = this.selector.eval(context); + function calcDefGroup(mixin, mixinPath) { var f, p, namespace; @@ -7825,7 +8280,7 @@ MixinCall.prototype.eval = function (context) { mixin = candidates[m].mixin; if (!(mixin instanceof MixinDefinition)) { originalRuleset = mixin.originalRuleset || mixin; - mixin = new MixinDefinition("", [], mixin.rules, null, false, null, originalRuleset.visibilityInfo()); + mixin = new MixinDefinition('', [], mixin.rules, null, false, null, originalRuleset.visibilityInfo()); mixin.originalRuleset = originalRuleset; } var newRules = mixin.evalCall(context, args, this.important).rules; @@ -7848,7 +8303,7 @@ MixinCall.prototype.eval = function (context) { index: this.getIndex(), filename: this.fileInfo().filename }; } else { throw { type: 'Name', - message: this.selector.toCSS().trim() + " is undefined", + message: this.selector.toCSS().trim() + ' is undefined', index: this.getIndex(), filename: this.fileInfo().filename }; } }; @@ -7865,32 +8320,33 @@ MixinCall.prototype._setVisibilityToReplacement = function (replacement) { MixinCall.prototype.format = function (args) { return this.selector.toCSS().trim() + '(' + (args ? args.map(function (a) { - var argValue = ""; + var argValue = ''; if (a.name) { - argValue += a.name + ":"; + argValue += a.name + ':'; } if (a.value.toCSS) { argValue += a.value.toCSS(); } else { - argValue += "???"; + argValue += '???'; } return argValue; - }).join(', ') : "") + ")"; + }).join(', ') : '') + ')'; }; module.exports = MixinCall; -},{"../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"), - Declaration = require("./declaration"), - Expression = require("./expression"), - contexts = require("../contexts"), - utils = require("../utils"); +},{"../functions/default":24,"./mixin-definition":71,"./node":74,"./selector":80}],71:[function(require,module,exports){ +var Selector = require('./selector'), + Element = require('./element'), + Ruleset = require('./ruleset'), + Declaration = require('./declaration'), + DetachedRuleset = require('./detached-ruleset'), + Expression = require('./expression'), + 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._fileInfo)])]; + this.selectors = [new Selector([new Element(null, name, false, this._index, this._fileInfo)])]; this.params = params; this.condition = condition; this.variadic = variadic; @@ -7913,7 +8369,7 @@ var Definition = function (name, params, rules, condition, variadic, frames, vis this.allowRoot = true; }; Definition.prototype = new Ruleset(); -Definition.prototype.type = "MixinDefinition"; +Definition.prototype.type = 'MixinDefinition'; Definition.prototype.evalFirst = true; Definition.prototype.accept = function (visitor) { if (this.params && this.params.length) { @@ -7957,7 +8413,7 @@ Definition.prototype.evalParams = function (context, mixinEnv, args, evaldArgume i--; continue; } else { - throw { type: 'Runtime', message: "Named argument for " + this.name + + throw { type: 'Runtime', message: 'Named argument for ' + this.name + ' ' + args[i].name + ' not found' }; } } @@ -7979,12 +8435,18 @@ Definition.prototype.evalParams = function (context, mixinEnv, args, evaldArgume } else { val = arg && arg.value; if (val) { - val = val.eval(context); + // This was a mixin call, pass in a detached ruleset of it's eval'd rules + if (Array.isArray(val)) { + val = new DetachedRuleset(new Ruleset('', val)); + } + else { + val = val.eval(context); + } } else if (params[i].value) { val = params[i].value.eval(mixinEnv); frame.resetCache(); } else { - throw { type: 'Runtime', message: "wrong number of arguments for " + this.name + + throw { type: 'Runtime', message: 'wrong number of arguments for ' + this.name + ' (' + argsLength + ' for ' + this.arity + ')' }; } @@ -8083,16 +8545,97 @@ Definition.prototype.matchArgs = function (args, context) { }; module.exports = Definition; -},{"../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"); +},{"../contexts":12,"../utils":87,"./declaration":58,"./detached-ruleset":59,"./element":61,"./expression":62,"./ruleset":79,"./selector":80}],72:[function(require,module,exports){ +var Node = require('./node'), + Variable = require('./variable'), + Ruleset = require('./ruleset'), + Selector = require('./selector'); + +var NamespaceValue = function (ruleCall, lookups, important, index, fileInfo) { + this.value = ruleCall; + this.lookups = lookups; + this.important = important; + this._index = index; + this._fileInfo = fileInfo; +}; +NamespaceValue.prototype = new Node(); +NamespaceValue.prototype.type = 'NamespaceValue'; +NamespaceValue.prototype.eval = function (context) { + var i, j, name, rules = this.value.eval(context); + + for (i = 0; i < this.lookups.length; i++) { + name = this.lookups[i]; + + /** + * Eval'd DRs return rulesets. + * Eval'd mixins return rules, so let's make a ruleset if we need it. + * We need to do this because of late parsing of values + */ + if (Array.isArray(rules)) { + rules = new Ruleset([new Selector()], rules); + } + + if (name === '') { + rules = rules.lastDeclaration(); + } + else if (name.charAt(0) === '@') { + if (name.charAt(1) === '@') { + name = '@' + new Variable(name.substr(1)).eval(context).value; + } + if (rules.variables) { + rules = rules.variable(name); + } + + if (!rules) { + throw { type: 'Name', + message: 'variable ' + name + ' not found', + filename: this.fileInfo().filename, + index: this.getIndex() }; + } + } + else { + if (name.substring(0, 2) === '$@') { + name = '$' + new Variable(name.substr(1)).eval(context).value; + } + else { + name = name.charAt(0) === '$' ? name : '$' + name; + } + if (rules.properties) { + rules = rules.property(name); + } + + if (!rules) { + throw { type: 'Name', + message: 'property "' + name.substr(1) + '" not found', + filename: this.fileInfo().filename, + index: this.getIndex() }; + } + // Properties are an array of values, since a ruleset can have multiple props. + // We pick the last one (the "cascaded" value) + rules = rules[rules.length - 1]; + } + + if (rules.value) { + rules = rules.eval(context).value; + } + if (rules.ruleset) { + rules = rules.ruleset.eval(context); + } + } + return rules; +}; +module.exports = NamespaceValue; + +},{"./node":74,"./ruleset":79,"./selector":80,"./variable":86}],73:[function(require,module,exports){ +var Node = require('./node'), + Operation = require('./operation'), + Dimension = require('./dimension'); var Negative = function (node) { this.value = node; }; Negative.prototype = new Node(); -Negative.prototype.type = "Negative"; +Negative.prototype.type = 'Negative'; Negative.prototype.genCSS = function (context, output) { output.add('-'); this.value.genCSS(context, output); @@ -8105,7 +8648,7 @@ Negative.prototype.eval = function (context) { }; module.exports = Negative; -},{"./dimension":60,"./node":73,"./operation":74}],73:[function(require,module,exports){ +},{"./dimension":60,"./node":74,"./operation":75}],74:[function(require,module,exports){ var Node = function() { this.parent = null; this.visibilityBlocks = undefined; @@ -8114,10 +8657,10 @@ var Node = function() { this.parsed = null; var self = this; - Object.defineProperty(this, "currentFileInfo", { + Object.defineProperty(this, 'currentFileInfo', { get: function() { return self.fileInfo(); } }); - Object.defineProperty(this, "index", { + Object.defineProperty(this, 'index', { get: function() { return self.getIndex(); } }); @@ -8184,7 +8727,7 @@ Node.compare = function (a, b) { if ((a.compare) && // for "symmetric results" force toCSS-based comparison // of Quoted or Anonymous if either value is one of those - !(b.type === "Quoted" || b.type === "Anonymous")) { + !(b.type === 'Quoted' || b.type === 'Anonymous')) { return a.compare(b); } else if (b.compare) { return -b.compare(a); @@ -8264,10 +8807,10 @@ Node.prototype.copyVisibilityInfo = function(info) { }; module.exports = Node; -},{}],74:[function(require,module,exports){ -var Node = require("./node"), - Color = require("./color"), - Dimension = require("./dimension"); +},{}],75:[function(require,module,exports){ +var Node = require('./node'), + Color = require('./color'), + Dimension = require('./dimension'); var Operation = function (op, operands, isSpaced) { this.op = op.trim(); @@ -8275,7 +8818,7 @@ var Operation = function (op, operands, isSpaced) { this.isSpaced = isSpaced; }; Operation.prototype = new Node(); -Operation.prototype.type = "Operation"; +Operation.prototype.type = 'Operation'; Operation.prototype.accept = function (visitor) { this.operands = visitor.visit(this.operands); }; @@ -8291,8 +8834,8 @@ Operation.prototype.eval = function (context) { b = b.toColor(); } if (!a.operate) { - throw { type: "Operation", - message: "Operation on an invalid type" }; + throw { type: 'Operation', + message: 'Operation on an invalid type' }; } return a.operate(context, this.op, b); @@ -8303,25 +8846,25 @@ Operation.prototype.eval = function (context) { Operation.prototype.genCSS = function (context, output) { this.operands[0].genCSS(context, output); if (this.isSpaced) { - output.add(" "); + output.add(' '); } output.add(this.op); if (this.isSpaced) { - output.add(" "); + output.add(' '); } this.operands[1].genCSS(context, output); }; module.exports = Operation; -},{"./color":53,"./dimension":60,"./node":73}],75:[function(require,module,exports){ -var Node = require("./node"); +},{"./color":53,"./dimension":60,"./node":74}],76:[function(require,module,exports){ +var Node = require('./node'); var Paren = function (node) { this.value = node; }; Paren.prototype = new Node(); -Paren.prototype.type = "Paren"; +Paren.prototype.type = 'Paren'; Paren.prototype.genCSS = function (context, output) { output.add('('); this.value.genCSS(context, output); @@ -8332,9 +8875,9 @@ Paren.prototype.eval = function (context) { }; module.exports = Paren; -},{"./node":73}],76:[function(require,module,exports){ -var Node = require("./node"), - Declaration = require("./declaration"); +},{"./node":74}],77:[function(require,module,exports){ +var Node = require('./node'), + Declaration = require('./declaration'); var Property = function (name, index, currentFileInfo) { this.name = name; @@ -8342,7 +8885,7 @@ var Property = function (name, index, currentFileInfo) { this._fileInfo = currentFileInfo; }; Property.prototype = new Node(); -Property.prototype.type = "Property"; +Property.prototype.type = 'Property'; Property.prototype.eval = function (context) { var property, name = this.name; // TODO: shorten this reference @@ -8350,7 +8893,7 @@ Property.prototype.eval = function (context) { if (this.evaluating) { throw { type: 'Name', - message: "Recursive property reference for " + name, + message: 'Recursive property reference for ' + name, filename: this.fileInfo().filename, index: this.getIndex() }; } @@ -8390,7 +8933,7 @@ Property.prototype.eval = function (context) { return property; } else { throw { type: 'Name', - message: "Property '" + name + "' is undefined", + message: 'Property \'' + name + '\' is undefined', filename: this.currentFileInfo.filename, index: this.index }; } @@ -8404,10 +8947,10 @@ Property.prototype.find = function (obj, fun) { }; module.exports = Property; -},{"./declaration":58,"./node":73}],77:[function(require,module,exports){ -var Node = require("./node"), - Variable = require("./variable"), - Property = require("./property"); +},{"./declaration":58,"./node":74}],78:[function(require,module,exports){ +var Node = require('./node'), + Variable = require('./variable'), + Property = require('./property'); var Quoted = function (str, content, escaped, index, currentFileInfo) { this.escaped = (escaped == null) ? true : escaped; @@ -8415,9 +8958,11 @@ var Quoted = function (str, content, escaped, index, currentFileInfo) { this.quote = str.charAt(0); this._index = index; this._fileInfo = currentFileInfo; + this.variableRegex = /@\{([\w-]+)\}/g; + this.propRegex = /\$\{([\w-]+)\}/g; }; Quoted.prototype = new Node(); -Quoted.prototype.type = "Quoted"; +Quoted.prototype.type = 'Quoted'; Quoted.prototype.genCSS = function (context, output) { if (!this.escaped) { output.add(this.quote, this.fileInfo(), this.getIndex()); @@ -8428,7 +8973,7 @@ Quoted.prototype.genCSS = function (context, output) { } }; Quoted.prototype.containsVariables = function() { - return this.value.match(/@\{([\w-]+)\}/); + return this.value.match(this.variableRegex); }; Quoted.prototype.eval = function (context) { var that = this, value = this.value; @@ -8448,13 +8993,13 @@ Quoted.prototype.eval = function (context) { } while (value !== evaluatedValue); return evaluatedValue; } - value = iterativeReplace(value, /@\{([\w-]+)\}/g, variableReplacement); - value = iterativeReplace(value, /\$\{([\w-]+)\}/g, propertyReplacement); + value = iterativeReplace(value, this.variableRegex, variableReplacement); + value = iterativeReplace(value, this.propRegex, 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 - if (other.type === "Quoted" && !this.escaped && !other.escaped) { + if (other.type === 'Quoted' && !this.escaped && !other.escaped) { return Node.numericCompare(this.value, other.value); } else { return other.toCSS && this.toCSS() === other.toCSS() ? 0 : undefined; @@ -8462,20 +9007,20 @@ Quoted.prototype.compare = function (other) { }; module.exports = Quoted; -},{"./node":73,"./property":76,"./variable":85}],78:[function(require,module,exports){ -var Node = require("./node"), - Declaration = require("./declaration"), - Keyword = require("./keyword"), - Comment = require("./comment"), - Paren = require("./paren"), - Selector = require("./selector"), - Element = require("./element"), - Anonymous = require("./anonymous"), - contexts = require("../contexts"), - globalFunctionRegistry = require("../functions/function-registry"), - defaultFunc = require("../functions/default"), - getDebugInfo = require("./debug-info"), - utils = require("../utils"); +},{"./node":74,"./property":77,"./variable":86}],79:[function(require,module,exports){ +var Node = require('./node'), + Declaration = require('./declaration'), + Keyword = require('./keyword'), + Comment = require('./comment'), + Paren = require('./paren'), + Selector = require('./selector'), + Element = require('./element'), + Anonymous = require('./anonymous'), + contexts = require('../contexts'), + globalFunctionRegistry = require('../functions/function-registry'), + defaultFunc = require('../functions/default'), + getDebugInfo = require('./debug-info'), + utils = require('../utils'); var Ruleset = function (selectors, rules, strictImports, visibilityInfo) { this.selectors = selectors; @@ -8492,7 +9037,7 @@ var Ruleset = function (selectors, rules, strictImports, visibilityInfo) { }; Ruleset.prototype = new Node(); -Ruleset.prototype.type = "Ruleset"; +Ruleset.prototype.type = 'Ruleset'; Ruleset.prototype.isRuleset = true; Ruleset.prototype.isRulesetLike = function() { return true; }; Ruleset.prototype.accept = function (visitor) { @@ -8506,22 +9051,47 @@ Ruleset.prototype.accept = function (visitor) { } }; Ruleset.prototype.eval = function (context) { - var thisSelectors = this.selectors, selectors, - selCnt, selector, i, hasOnePassingSelector = false; + var that = this, selectors, selCnt, selector, i, hasVariable, hasOnePassingSelector = false; - if (thisSelectors && (selCnt = thisSelectors.length)) { + if (this.selectors && (selCnt = this.selectors.length)) { selectors = new Array(selCnt); defaultFunc.error({ - type: "Syntax", - message: "it is currently only allowed in parametric mixin guards," + type: 'Syntax', + message: 'it is currently only allowed in parametric mixin guards,' }); + for (i = 0; i < selCnt; i++) { - selector = thisSelectors[i].eval(context); + selector = this.selectors[i].eval(context); + for (var j = 0; j < selector.elements.length; j++) { + if (selector.elements[j].isVariable) { + hasVariable = true; + break; + } + } selectors[i] = selector; if (selector.evaldCondition) { hasOnePassingSelector = true; } } + + if (hasVariable) { + var toParseSelectors = new Array(selCnt); + for (i = 0; i < selCnt; i++) { + selector = selectors[i]; + toParseSelectors[i] = selector.toCSS(context); + } + this.parse.parseNode( + toParseSelectors.join(','), + ["selectors"], + selectors[0].getIndex(), + selectors[0].fileInfo(), + function(err, result) { + if (result) { + selectors = utils.flattenArray(result); + } + }); + } + defaultFunc.reset(); } else { hasOnePassingSelector = true; @@ -8586,7 +9156,7 @@ Ruleset.prototype.eval = function (context) { // Evaluate mixin calls. for (i = 0; (rule = rsRules[i]); i++) { - if (rule.type === "MixinCall") { + if (rule.type === 'MixinCall') { /* jshint loopfunc:true */ rules = rule.eval(context).filter(function(r) { if ((r instanceof Declaration) && r.variable) { @@ -8600,7 +9170,7 @@ Ruleset.prototype.eval = function (context) { rsRules.splice.apply(rsRules, [i, 1].concat(rules)); i += rules.length - 1; ruleset.resetCache(); - } else if (rule.type === "VariableCall") { + } else if (rule.type === 'VariableCall') { /* jshint loopfunc:true */ rules = rule.eval(context).rules.filter(function(r) { if ((r instanceof Declaration) && r.variable) { @@ -8627,7 +9197,7 @@ Ruleset.prototype.eval = function (context) { // 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()) { + if (rule.selectors[0] && rule.selectors[0].isJustParentSelector()) { rsRules.splice(i--, 1); for (var j = 0; (subRule = rule.rules[j]); j++) { @@ -8659,7 +9229,7 @@ Ruleset.prototype.evalImports = function(context) { if (!rules) { return; } for (i = 0; i < rules.length; i++) { - if (rules[i].type === "Import") { + if (rules[i].type === 'Import') { importRules = rules[i].eval(context); if (importRules && (importRules.length || importRules.length === 0)) { rules.splice.apply(rules, [i, 1].concat(importRules)); @@ -8714,11 +9284,11 @@ Ruleset.prototype.variables = function () { // when evaluating variables in an import statement, imports have not been eval'd // so we need to go inside import statements. // guard against root being a string (in the case of inlined less) - if (r.type === "Import" && r.root && r.root.variables) { + if (r.type === 'Import' && r.root && r.root.variables) { var vars = r.root.variables(); for (var name in vars) { if (vars.hasOwnProperty(name)) { - hash[name] = vars[name]; + hash[name] = r.root.variable(name); } } } @@ -8758,25 +9328,37 @@ Ruleset.prototype.property = function (name) { return this.parseValue(decl); } }; +Ruleset.prototype.lastDeclaration = function () { + for (var i = this.rules.length; i > 0; i--) { + var decl = this.rules[i - 1]; + if (decl instanceof Declaration) { + 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; - } - }); + if (typeof decl.value.value === 'string') { + 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; + } + }); + } else { + decl.parsed = true; + } return decl; } @@ -8863,8 +9445,8 @@ Ruleset.prototype.genCSS = function (context, output) { context.tabLevel++; } - var tabRuleStr = context.compress ? '' : Array(context.tabLevel + 1).join(" "), - tabSetStr = context.compress ? '' : Array(context.tabLevel).join(" "), + var tabRuleStr = context.compress ? '' : Array(context.tabLevel + 1).join(' '), + tabSetStr = context.compress ? '' : Array(context.tabLevel).join(' '), sep; var charsetNodeIndex = 0; @@ -8879,7 +9461,7 @@ Ruleset.prototype.genCSS = function (context, output) { ruleNodes.splice(charsetNodeIndex, 0, rule); charsetNodeIndex++; importNodeIndex++; - } else if (rule.type === "Import") { + } else if (rule.type === 'Import') { ruleNodes.splice(importNodeIndex, 0, rule); importNodeIndex++; } else { @@ -8972,7 +9554,13 @@ Ruleset.prototype.joinSelector = function (paths, context, selector) { } else { var insideParent = new Array(elementsToPak.length); for (j = 0; j < elementsToPak.length; j++) { - insideParent[j] = new Element(null, elementsToPak[j], originalElement._index, originalElement._fileInfo); + insideParent[j] = new Element( + null, + elementsToPak[j], + originalElement.isVariable, + originalElement._index, + originalElement._fileInfo + ); } replacementParen = new Paren(new Selector(insideParent)); } @@ -8981,7 +9569,7 @@ Ruleset.prototype.joinSelector = function (paths, context, selector) { function createSelector(containedElement, originalElement) { var element, selector; - element = new Element(null, containedElement, originalElement._index, originalElement._fileInfo); + element = new Element(null, containedElement, originalElement.isVariable, originalElement._index, originalElement._fileInfo); selector = new Selector([element]); return selector; } @@ -9006,7 +9594,8 @@ Ruleset.prototype.joinSelector = function (paths, context, selector) { } if (addPath.length > 0) { - // /deep/ is a combinator that is valid without anything in front of it + // /deep/ is a CSS4 selector - (removed, so should deprecate) + // that is valid without anything in front of it // so if the & does not have a combinator that is "" or " " then // and there is a combinator on the parent, then grab that. // this also allows + a { & .b { .a & { ... though not sure why you would want to do that @@ -9015,7 +9604,13 @@ 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._fileInfo)); + newJoinedSelector.elements.push(new Element( + combinator, + parentEl.value, + replacedElement.isVariable, + replacedElement._index, + replacedElement._fileInfo + )); newJoinedSelector.elements = newJoinedSelector.elements.concat(addPath[0].elements.slice(1)); } @@ -9109,7 +9704,7 @@ Ruleset.prototype.joinSelector = function (paths, context, selector) { for (i = 0; (el = inSelector.elements[i]); i++) { // non parent reference elements just get added - if (el.value !== "&") { + if (el.value !== '&') { var nestedSelector = findNestedSelector(el); if (nestedSelector != null) { // merge the current list of non parent selector elements @@ -9149,7 +9744,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._fileInfo)); + sel[0].elements.push(new Element(el.combinator, '', el.isVariable, el._index, el._fileInfo)); } selectorsMultiplied.push(sel); } @@ -9222,10 +9817,10 @@ Ruleset.prototype.joinSelector = function (paths, context, selector) { }; module.exports = Ruleset; -},{"../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"), - LessError = require("../less-error"); +},{"../contexts":12,"../functions/default":24,"../functions/function-registry":26,"../utils":87,"./anonymous":48,"./comment":55,"./debug-info":57,"./declaration":58,"./element":61,"./keyword":68,"./node":74,"./paren":76,"./selector":80}],80:[function(require,module,exports){ +var Node = require('./node'), + Element = require('./element'), + LessError = require('../less-error'); var Selector = function (elements, extendList, condition, index, currentFileInfo, visibilityInfo) { this.extendList = extendList; @@ -9239,7 +9834,7 @@ var Selector = function (elements, extendList, condition, index, currentFileInfo this.setParent(this.elements, this); }; Selector.prototype = new Node(); -Selector.prototype.type = "Selector"; +Selector.prototype.type = 'Selector'; Selector.prototype.accept = function (visitor) { if (this.elements) { this.elements = visitor.visitArray(this.elements); @@ -9260,10 +9855,13 @@ Selector.prototype.createDerived = function(elements, extendList, evaldCondition return newSelector; }; Selector.prototype.getElements = function(els) { - if (typeof els === "string") { + if (!els) { + return [new Element('', '&', false, this._index, this._fileInfo)]; + } + if (typeof els === 'string') { this.parse.parseNode( els, - ["selector"], + ['selector'], this._index, this._fileInfo, function(err, result) { @@ -9279,7 +9877,7 @@ Selector.prototype.getElements = function(els) { return els; }; Selector.prototype.createEmptySelectors = function() { - var el = new Element('', '&', this._index, this._fileInfo), + var el = new Element('', '&', false, this._index, this._fileInfo), sels = [new Selector([el], null, null, this._index, this._fileInfo)]; sels[0].mediaEmpty = true; return sels; @@ -9310,10 +9908,10 @@ Selector.prototype.mixinElements = function() { var elements = this.elements.map( function(v) { return v.combinator.value + (v.value.value || v.value); - }).join("").match(/[,&#\*\.\w-]([\w-]|(\\.))*/g); + }).join('').match(/[,&#\*\.\w-]([\w-]|(\\.))*/g); if (elements) { - if (elements[0] === "&") { + if (elements[0] === '&') { elements.shift(); } } else { @@ -9339,7 +9937,7 @@ Selector.prototype.eval = function (context) { }; Selector.prototype.genCSS = function (context, output) { var i, element; - if ((!context || !context.firstSelector) && this.elements[0].combinator.value === "") { + if ((!context || !context.firstSelector) && this.elements[0].combinator.value === '') { output.add(' ', this.fileInfo(), this.getIndex()); } for (i = 0; i < this.elements.length; i++) { @@ -9352,21 +9950,21 @@ Selector.prototype.getIsOutput = function() { }; module.exports = Selector; -},{"../less-error":36,"./element":61,"./node":73}],80:[function(require,module,exports){ -var Node = require("./node"); +},{"../less-error":36,"./element":61,"./node":74}],81:[function(require,module,exports){ +var Node = require('./node'); var UnicodeDescriptor = function (value) { this.value = value; }; UnicodeDescriptor.prototype = new Node(); -UnicodeDescriptor.prototype.type = "UnicodeDescriptor"; +UnicodeDescriptor.prototype.type = 'UnicodeDescriptor'; module.exports = UnicodeDescriptor; -},{"./node":73}],81:[function(require,module,exports){ -var Node = require("./node"), - unitConversions = require("../data/unit-conversions"), - utils = require("../utils"); +},{"./node":74}],82:[function(require,module,exports){ +var Node = require('./node'), + unitConversions = require('../data/unit-conversions'), + utils = require('../utils'); var Unit = function (numerator, denominator, backupUnit) { this.numerator = numerator ? utils.copyArray(numerator).sort() : []; @@ -9379,7 +9977,7 @@ var Unit = function (numerator, denominator, backupUnit) { }; Unit.prototype = new Node(); -Unit.prototype.type = "Unit"; +Unit.prototype.type = 'Unit'; Unit.prototype.clone = function () { return new Unit(utils.copyArray(this.numerator), utils.copyArray(this.denominator), this.backupUnit); }; @@ -9395,9 +9993,9 @@ Unit.prototype.genCSS = function (context, output) { } }; Unit.prototype.toString = function () { - var i, returnStr = this.numerator.join("*"); + var i, returnStr = this.numerator.join('*'); for (i = 0; i < this.denominator.length; i++) { - returnStr += "/" + this.denominator[i]; + returnStr += '/' + this.denominator[i]; } return returnStr; }; @@ -9486,8 +10084,8 @@ Unit.prototype.cancel = function () { }; module.exports = Unit; -},{"../data/unit-conversions":15,"../utils":86,"./node":73}],82:[function(require,module,exports){ -var Node = require("./node"); +},{"../data/unit-conversions":15,"../utils":87,"./node":74}],83:[function(require,module,exports){ +var Node = require('./node'); var URL = function (val, index, currentFileInfo, isEvald) { this.value = val; @@ -9496,14 +10094,14 @@ var URL = function (val, index, currentFileInfo, isEvald) { this.isEvald = isEvald; }; URL.prototype = new Node(); -URL.prototype.type = "Url"; +URL.prototype.type = 'Url'; URL.prototype.accept = function (visitor) { this.value = visitor.visit(this.value); }; URL.prototype.genCSS = function (context, output) { - output.add("url("); + output.add('url('); this.value.genCSS(context, output); - output.add(")"); + output.add(')'); }; URL.prototype.eval = function (context) { var val = this.value.eval(context), @@ -9513,11 +10111,11 @@ URL.prototype.eval = function (context) { // Add the base path if the URL is relative rootpath = this.fileInfo() && this.fileInfo().rootpath; if (rootpath && - typeof val.value === "string" && + typeof val.value === 'string' && context.isPathRelative(val.value)) { if (!val.quote) { - rootpath = rootpath.replace(/[\(\)'"\s]/g, function(match) { return "\\" + match; }); + rootpath = rootpath.replace(/[\(\)'"\s]/g, function(match) { return '\\' + match; }); } val.value = rootpath + val.value; } @@ -9542,12 +10140,12 @@ URL.prototype.eval = function (context) { }; module.exports = URL; -},{"./node":73}],83:[function(require,module,exports){ -var Node = require("./node"); +},{"./node":74}],84:[function(require,module,exports){ +var Node = require('./node'); var Value = function (value) { if (!value) { - throw new Error("Value requires an array argument"); + throw new Error('Value requires an array argument'); } if (!Array.isArray(value)) { this.value = [ value ]; @@ -9557,7 +10155,7 @@ var Value = function (value) { } }; Value.prototype = new Node(); -Value.prototype.type = "Value"; +Value.prototype.type = 'Value'; Value.prototype.accept = function (visitor) { if (this.value) { this.value = visitor.visitArray(this.value); @@ -9583,24 +10181,47 @@ Value.prototype.genCSS = function (context, output) { }; module.exports = Value; -},{"./node":73}],84:[function(require,module,exports){ -var Node = require("./node"), - Variable = require("./variable"); +},{"./node":74}],85:[function(require,module,exports){ +var Node = require('./node'), + Variable = require('./variable'), + Ruleset = require('./ruleset'), + DetachedRuleset = require('./detached-ruleset'), + LessError = require('../less-error'); -var VariableCall = function (variable) { +var VariableCall = function (variable, index, currentFileInfo) { this.variable = variable; + this._index = index; + this._fileInfo = currentFileInfo; this.allowRoot = true; }; VariableCall.prototype = new Node(); -VariableCall.prototype.type = "VariableCall"; +VariableCall.prototype.type = 'VariableCall'; VariableCall.prototype.eval = function (context) { - var detachedRuleset = new Variable(this.variable).eval(context); - return detachedRuleset.callEval(context); + var rules, detachedRuleset = new Variable(this.variable, this.getIndex(), this.fileInfo()).eval(context), + error = new LessError({message: 'Could not evaluate variable call ' + this.variable}); + + if (!detachedRuleset.ruleset) { + if (Array.isArray(detachedRuleset)) { + rules = detachedRuleset; + } + else if (Array.isArray(detachedRuleset.value)) { + rules = detachedRuleset.value; + } + else { + throw error; + } + detachedRuleset = new DetachedRuleset(new Ruleset('', rules)); + } + if (detachedRuleset.ruleset) { + return detachedRuleset.callEval(context); + } + throw error; }; module.exports = VariableCall; -},{"./node":73,"./variable":85}],85:[function(require,module,exports){ -var Node = require("./node"); +},{"../less-error":36,"./detached-ruleset":59,"./node":74,"./ruleset":79,"./variable":86}],86:[function(require,module,exports){ +var Node = require('./node'), + Call = require('./call'); var Variable = function (name, index, currentFileInfo) { this.name = name; @@ -9608,7 +10229,7 @@ var Variable = function (name, index, currentFileInfo) { this._fileInfo = currentFileInfo; }; Variable.prototype = new Node(); -Variable.prototype.type = "Variable"; +Variable.prototype.type = 'Variable'; Variable.prototype.eval = function (context) { var variable, name = this.name; @@ -9618,7 +10239,7 @@ Variable.prototype.eval = function (context) { if (this.evaluating) { throw { type: 'Name', - message: "Recursive variable definition for " + name, + message: 'Recursive variable definition for ' + name, filename: this.fileInfo().filename, index: this.getIndex() }; } @@ -9632,7 +10253,13 @@ Variable.prototype.eval = function (context) { var importantScope = context.importantScope[context.importantScope.length - 1]; importantScope.important = v.important; } - return v.value.eval(context); + // If in calc, wrap vars in a function call to cascade evaluate args first + if (context.inCalc) { + return (new Call('_SELF', [v.value])).eval(context); + } + else { + return v.value.eval(context); + } } }); if (variable) { @@ -9640,7 +10267,7 @@ Variable.prototype.eval = function (context) { return variable; } else { throw { type: 'Name', - message: "variable " + name + " is undefined", + message: 'variable ' + name + ' is undefined', filename: this.fileInfo().filename, index: this.getIndex() }; } @@ -9654,9 +10281,9 @@ Variable.prototype.find = function (obj, fun) { }; module.exports = Variable; -},{"./node":73}],86:[function(require,module,exports){ +},{"./call":52,"./node":74}],87:[function(require,module,exports){ /* jshint proto: true */ -module.exports = { +var utils = { getLocation: function(index, inputStream) { var n = index + 1, line = null, @@ -9667,7 +10294,7 @@ module.exports = { } if (typeof index === 'number') { - line = (inputStream.slice(0, index).match(/\n/g) || "").length; + line = (inputStream.slice(0, index).match(/\n/g) || '').length; } return { @@ -9722,14 +10349,29 @@ module.exports = { } } return obj1; + }, + flattenArray: function(arr, result) { + result = result || []; + for (var i = 0, length = arr.length; i < length; i++) { + var value = arr[i]; + if (Array.isArray(value)) { + utils.flattenArray(value, result); + } else { + if (value !== undefined) { + result.push(value); + } + } + } + return result; } }; -},{}],87:[function(require,module,exports){ -var tree = require("../tree"), - Visitor = require("./visitor"), - logger = require("../logger"), - utils = require("../utils"); +module.exports = utils; +},{}],88:[function(require,module,exports){ +var tree = require('../tree'), + Visitor = require('./visitor'), + logger = require('../logger'), + utils = require('../utils'); /* jshint loopfunc:true */ @@ -9838,7 +10480,7 @@ ProcessExtendsVisitor.prototype = { extendList.filter(function(extend) { return !extend.hasFoundMatches && extend.parent_ids.length == 1; }).forEach(function(extend) { - var selector = "_unknown_"; + var selector = '_unknown_'; try { selector = extend.selector.toCSS({}); } @@ -9846,7 +10488,7 @@ ProcessExtendsVisitor.prototype = { if (!indices[extend.index + ' ' + selector]) { indices[extend.index + ' ' + selector] = true; - logger.warn("extend '" + selector + "' has no matches"); + logger.warn('extend \'' + selector + '\' has no matches'); } }); }, @@ -9905,7 +10547,7 @@ ProcessExtendsVisitor.prototype = { extendsToAdd.push(newExtend); newExtend.ruleset = targetExtend.ruleset; - //remember its parents for circular references + // remember its parents for circular references newExtend.parent_ids = newExtend.parent_ids.concat(targetExtend.parent_ids, extend.parent_ids); // only process the selector once.. if we have :extend(.a,.b) then multiple @@ -9925,15 +10567,15 @@ ProcessExtendsVisitor.prototype = { // may no longer be needed. this.extendChainCount++; if (iterationCount > 100) { - var selectorOne = "{unable to calculate}"; - var selectorTwo = "{unable to calculate}"; + var selectorOne = '{unable to calculate}'; + var selectorTwo = '{unable to calculate}'; try { selectorOne = extendsToAdd[0].selfSelectors[0].toCSS(); selectorTwo = extendsToAdd[0].selector.toCSS(); } catch (e) {} - throw { message: "extend circular reference detected. One of the circular extends is currently:" + - selectorOne + ":extend(" + selectorTwo + ")"}; + throw { message: 'extend circular reference detected. One of the circular extends is currently:' + + selectorOne + ':extend(' + selectorTwo + ')'}; } // now process the new extends on the existing rules so that we can handle a extending b extending c extending @@ -10057,7 +10699,7 @@ ProcessExtendsVisitor.prototype = { return matches; }, isElementValuesEqual: function(elementValue1, elementValue2) { - if (typeof elementValue1 === "string" || typeof elementValue2 === "string") { + if (typeof elementValue1 === 'string' || typeof elementValue2 === 'string') { return elementValue1 === elementValue2; } if (elementValue1 instanceof tree.Attribute) { @@ -10113,6 +10755,7 @@ ProcessExtendsVisitor.prototype = { firstElement = new tree.Element( match.initialCombinator, replacementSelector.elements[0].value, + replacementSelector.elements[0].isVariable, replacementSelector.elements[0].getIndex(), replacementSelector.elements[0].fileInfo() ); @@ -10188,7 +10831,7 @@ ProcessExtendsVisitor.prototype = { module.exports = ProcessExtendsVisitor; -},{"../logger":37,"../tree":65,"../utils":86,"./visitor":94}],88:[function(require,module,exports){ +},{"../logger":37,"../tree":65,"../utils":87,"./visitor":95}],89:[function(require,module,exports){ function ImportSequencer(onSequencerEmpty) { this.imports = []; this.variableImports = []; @@ -10244,11 +10887,11 @@ ImportSequencer.prototype.tryRun = function() { module.exports = ImportSequencer; -},{}],89:[function(require,module,exports){ -var contexts = require("../contexts"), - Visitor = require("./visitor"), - ImportSequencer = require("./import-sequencer"), - utils = require("../utils"); +},{}],90:[function(require,module,exports){ +var contexts = require('../contexts'), + Visitor = require('./visitor'), + ImportSequencer = require('./import-sequencer'), + utils = require('../utils'); var ImportVisitor = function(importer, finish) { @@ -10398,14 +11041,14 @@ ImportVisitor.prototype = { } }, visitDeclaration: function (declNode, visitArgs) { - if (declNode.value.type === "DetachedRuleset") { + if (declNode.value.type === 'DetachedRuleset') { this.context.frames.unshift(declNode); } else { visitArgs.visitDeeper = false; } }, visitDeclarationOut: function(declNode) { - if (declNode.value.type === "DetachedRuleset") { + if (declNode.value.type === 'DetachedRuleset') { this.context.frames.shift(); } }, @@ -10436,11 +11079,11 @@ ImportVisitor.prototype = { }; module.exports = ImportVisitor; -},{"../contexts":12,"../utils":86,"./import-sequencer":88,"./visitor":94}],90:[function(require,module,exports){ +},{"../contexts":12,"../utils":87,"./import-sequencer":89,"./visitor":95}],91:[function(require,module,exports){ var visitors = { - Visitor: require("./visitor"), + Visitor: require('./visitor'), ImportVisitor: require('./import-visitor'), - MarkVisibleSelectorsVisitor: require("./set-tree-visibility-visitor"), + MarkVisibleSelectorsVisitor: require('./set-tree-visibility-visitor'), ExtendVisitor: require('./extend-visitor'), JoinSelectorVisitor: require('./join-selector-visitor'), ToCSSVisitor: require('./to-css-visitor') @@ -10448,8 +11091,8 @@ var visitors = { module.exports = visitors; -},{"./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"); +},{"./extend-visitor":88,"./import-visitor":90,"./join-selector-visitor":92,"./set-tree-visibility-visitor":93,"./to-css-visitor":94,"./visitor":95}],92:[function(require,module,exports){ +var Visitor = require('./visitor'); var JoinSelectorVisitor = function() { this.contexts = [[]]; @@ -10501,7 +11144,7 @@ JoinSelectorVisitor.prototype = { module.exports = JoinSelectorVisitor; -},{"./visitor":94}],92:[function(require,module,exports){ +},{"./visitor":95}],93:[function(require,module,exports){ var SetTreeVisibilityVisitor = function(visible) { this.visible = visible; }; @@ -10540,9 +11183,9 @@ SetTreeVisibilityVisitor.prototype.visit = function(node) { return node; }; module.exports = SetTreeVisibilityVisitor; -},{}],93:[function(require,module,exports){ -var tree = require("../tree"), - Visitor = require("./visitor"); +},{}],94:[function(require,module,exports){ +var tree = require('../tree'), + Visitor = require('./visitor'); var CSSVisitorUtils = function(context) { this._visitor = new Visitor(this); @@ -10723,13 +11366,13 @@ ToCSSVisitor.prototype = { return; } - if (atRuleNode.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 atrule would // be considered illegal css as it has to be on the first line if (this.charset) { if (atRuleNode.debugInfo) { - var comment = new tree.Comment("/* " + atRuleNode.toCSS(this._context).replace(/\n/g, "") + " */\n"); + var comment = new tree.Comment('/* ' + atRuleNode.toCSS(this._context).replace(/\n/g, '') + ' */\n'); comment.debugInfo = atRuleNode.debugInfo; return this._visitor.visit(comment); } @@ -10749,15 +11392,15 @@ ToCSSVisitor.prototype = { for (var i = 0; i < rules.length; i++) { var ruleNode = rules[i]; if (isRoot && ruleNode instanceof tree.Declaration && !ruleNode.variable) { - throw { message: "Properties must be inside selector blocks. They cannot be in the root", + throw { message: 'Properties must be inside selector blocks. They cannot be in the root', index: ruleNode.getIndex(), filename: ruleNode.fileInfo() && ruleNode.fileInfo().filename}; } if (ruleNode instanceof tree.Call) { - throw { message: "Function '" + ruleNode.name + "' is undefined", + throw { message: 'Function \'' + ruleNode.name + '\' is undefined', 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", + throw { message: ruleNode.type + ' node returned by a function is not valid here', index: ruleNode.getIndex(), filename: ruleNode.fileInfo() && ruleNode.fileInfo().filename}; } } @@ -10902,8 +11545,8 @@ ToCSSVisitor.prototype = { module.exports = ToCSSVisitor; -},{"../tree":65,"./visitor":94}],94:[function(require,module,exports){ -var tree = require("../tree"); +},{"../tree":65,"./visitor":95}],95:[function(require,module,exports){ +var tree = require('../tree'); var _visitArgs = { visitDeeper: true }, _hasIndexed = false; @@ -10919,14 +11562,14 @@ function indexNodeTypes(parent, ticker) { /* eslint guard-for-in: 0 */ child = parent[key]; switch (typeof child) { - case "function": + 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": + case 'object': ticker = indexNodeTypes(child, ticker); break; @@ -10937,7 +11580,8 @@ function indexNodeTypes(parent, ticker) { var Visitor = function(implementation) { this._implementation = implementation; - this._visitFnCache = []; + this._visitInCache = {}; + this._visitOutCache = {}; if (!_hasIndexed) { indexNodeTypes(tree, 1); @@ -10953,31 +11597,32 @@ Visitor.prototype = { var nodeTypeIndex = node.typeIndex; if (!nodeTypeIndex) { + // MixinCall args aren't a node type? + if (node.value && node.value.typeIndex) { + this.visit(node.value); + } return node; } - var visitFnCache = this._visitFnCache, - impl = this._implementation, - aryIndx = nodeTypeIndex << 1, - outAryIndex = aryIndx | 1, - func = visitFnCache[aryIndx], - funcOut = visitFnCache[outAryIndex], + var impl = this._implementation, + func = this._visitInCache[nodeTypeIndex], + funcOut = this._visitOutCache[nodeTypeIndex], visitArgs = _visitArgs, fnName; visitArgs.visitDeeper = true; if (!func) { - fnName = "visit" + node.type; + fnName = 'visit' + node.type; func = impl[fnName] || _noop; - funcOut = impl[fnName + "Out"] || _noop; - visitFnCache[aryIndx] = func; - visitFnCache[outAryIndex] = funcOut; + funcOut = impl[fnName + 'Out'] || _noop; + this._visitInCache[nodeTypeIndex] = func; + this._visitOutCache[nodeTypeIndex] = funcOut; } if (func !== _noop) { var newNode = func.call(impl, node, visitArgs); - if (impl.isReplacing) { + if (node && impl.isReplacing) { node = newNode; } } @@ -11056,7 +11701,7 @@ Visitor.prototype = { }; module.exports = Visitor; -},{"../tree":65}],95:[function(require,module,exports){ +},{"../tree":65}],96:[function(require,module,exports){ "use strict"; // rawAsap provides everything we need except exception management. @@ -11124,7 +11769,7 @@ RawTask.prototype.call = function () { } }; -},{"./raw":96}],96:[function(require,module,exports){ +},{"./raw":97}],97:[function(require,module,exports){ (function (global){ "use strict"; @@ -11351,7 +11996,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 : {}) -},{}],97:[function(require,module,exports){ +},{}],98:[function(require,module,exports){ 'use strict'; var asap = require('asap/raw'); @@ -11566,7 +12211,7 @@ function doResolve(fn, promise) { } } -},{"asap/raw":96}],98:[function(require,module,exports){ +},{"asap/raw":97}],99:[function(require,module,exports){ 'use strict'; //This file contains the ES6 extensions to the core Promises/A+ API @@ -11675,7 +12320,7 @@ Promise.prototype['catch'] = function (onRejected) { return this.then(null, onRejected); }; -},{"./core.js":97}],99:[function(require,module,exports){ +},{"./core.js":98}],100:[function(require,module,exports){ // should work in any browser without browserify if (typeof Promise.prototype.done !== 'function') { @@ -11688,7 +12333,7 @@ if (typeof Promise.prototype.done !== 'function') { }) } } -},{}],100:[function(require,module,exports){ +},{}],101:[function(require,module,exports){ // not "use strict" so we can declare global "Promise" var asap = require('asap'); @@ -11700,5 +12345,5 @@ if (typeof Promise === 'undefined') { require('./polyfill-done.js'); -},{"./lib/core.js":97,"./lib/es6-extensions.js":98,"./polyfill-done.js":99,"asap":95}]},{},[2])(2) -}); +},{"./lib/core.js":98,"./lib/es6-extensions.js":99,"./polyfill-done.js":100,"asap":96}]},{},[2])(2) +}); \ No newline at end of file diff --git a/dist/less.min.js b/dist/less.min.js index 12bd6a1f..9abc15e2 100644 --- a/dist/less.min.js +++ b/dist/less.min.js @@ -1,5 +1,5 @@ /*! - * Less - Leaner CSS v3.0.4 + * Less - Leaner CSS v3.5.3 * http://lesscss.org * * Copyright (c) 2009-2018, Alexis Sellier @@ -10,8 +10,9 @@ /** * @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(){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||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),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)+":

    "),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]||i.inline||(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,4],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?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;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":101}],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||{},g=g||"{}",f&&b.lastModified&&new Date(b.lastModified).valueOf()===new Date(f).valueOf()&&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},f.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":78,"../tree/url":83,"../utils":87,"./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":78,"../tree/url":83,"./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)},_SELF:function(a){return a}})},{"../tree/anonymous":48,"../tree/color":53,"../tree/detached-ruleset":59,"../tree/dimension":60,"../tree/keyword":68,"../tree/operation":75,"../tree/quoted":78,"../tree/url":83,"./function-registry":26}],34:[function(a,b,c){var d=a("./contexts"),e=a("./parser/parser"),f=a("./less-error"),g=a("./utils"),h=("undefined"==typeof Promise?a("promise"):Promise,a("./logger"));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,i,j,k){var l=this,m=this.context.pluginManager.Loader;this.queue.push(b);var n=function(a,c,d){l.queue.splice(l.queue.indexOf(b),1);var e=d===l.rootFilename;j.optional&&a?(k(null,{rules:[]},!1,null),h.info("The file "+d+" was skipped because it was not found and the import was marked optional.")):(l.files[d]||j.inline||(l.files[d]={root:c,options:j}),a&&!l.error&&(l.error=a),k(a,c,e,d))},o={relativeUrls:this.context.relativeUrls,entryPath:i.entryPath,rootpath:i.rootpath,rootFilename:i.rootFilename},p=a.getFileManager(b,i.currentDirectory,this.context,a);if(!p)return void n({message:"Could not find a file-manager for "+b});var q,r=function(a){var b,c=a.filename,g=a.contents.replace(/^\uFEFF/,"");o.currentDirectory=p.getPath(c),o.relativeUrls&&(o.rootpath=p.join(l.context.rootpath||"",p.pathDiff(o.currentDirectory,o.entryPath)),!p.isPathAbsolute(o.rootpath)&&p.alwaysMakePathsAbsolute()&&(o.rootpath=p.join(o.entryPath,o.rootpath))),o.filename=c;var h=new d.Parse(l.context);h.processImports=!1,l.contents[c]=g,(i.reference||j.reference)&&(o.reference=!0),j.isPlugin?(b=m.evalPlugin(g,h,l,j.pluginArgs,o),b instanceof f?n(b,null,c):n(null,b,c)):j.inline?n(null,g,c):!l.files[c]||l.files[c].options.multiple||j.multiple?new e(h,l,o).parse(g,function(a,b){n(a,b,c)}):n(null,l.files[c].root,c)},s=g.clone(this.context);c&&(s.ext=j.isPlugin?".js":".less"),q=j.isPlugin?m.loadPlugin(b,i.currentDirectory,s,a,p):p.loadFile(b,i.currentDirectory,s,a,function(a,b){a?n(a):r(b)}),q&&q.then(r,n)},b}},{"./contexts":12,"./less-error":36,"./logger":37,"./parser/parser":42,"./utils":87,promise:void 0}],35:[function(a,b,c){b.exports=function(b,c){var d,e,f,g,h,i,j={version:[3,5,3],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":87,"./visitors":91}],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?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":87}],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;el&&(p=!1)}q=r}while(p);return f?f:null},k.autoCommentAbsorb=!0,k.commentStore=[],k.finished=!1,k.peek=function(a){if("string"==typeof a){for(var c=0;cs||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 a},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()||this.call(!0)}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()},ruleLookups:function(){var a,b,c=[];if("["===q.currentChar()){for(;;){if(q.save(),b=null,a=this.lookupValue(),!a&&""!==a){q.restore();break}c.push(a),q.forget()}return c.length>0?c:void 0}},lookupValue:function(){if(q.save(),!q.$char("["))return void q.restore();var a=q.$re(/^(?:[@$]{0,2})[_a-zA-Z0-9-]*/);return q.$char("]")&&(a||""===a)?(q.forget(),a):void q.restore()}},entity:function(){var a=this.entities;return this.comment()||a.literal()||a.variable()||a.url()||a.property()||a.call()||a.keyword()||this.mixin.call(!0)||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,a instanceof e.Variable,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"))},selectors:function(){for(var a,b;;){if(a=this.selector(),!a)break;if(b?b.push(a):b=[a],q.commentStore.length=0,a.condition&&b.length>1&&j("Guards are only currently allowed on a single selector."),!q.$char(","))break;a.condition&&j("Guards are only currently allowed on a single selector."),q.commentStore.length=0}return b},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;if(q.save(),a.dumpLineNumbers&&(d=n(q.i)),b=this.selectors(),b&&(c=this.block())){q.forget();var f=new e.Ruleset(b,c,a.strictImports);return a.dumpLineNumbers&&(f.debugInfo=d),f}q.restore()},declaration:function(){var a,b,d,f,g,h,i=q.i,j=q.currentChar();if("."!==j&&"#"!==j&&"&"!==j&&":"!==j)if(q.save(),a=this.variable()||this.ruleProperty()){if(h="string"==typeof a,h&&(b=this.detachedRuleset(),b&&(d=!0)),q.commentStore.length=0,!b){if(g=!h&&a.length>1&&a.pop().value,b=a[0].value&&"--"===a[0].value.slice(0,2)?this.permissiveValue():this.anonymousValue())return q.forget(),new e.Declaration(a,b,(!1),g,i,c);b||(b=this.value()),b?f=this.important():h&&(b=this.permissiveValue())}if(b&&(this.end()||d))return q.forget(),new e.Declaration(a,b,f,g,i,c);q.restore()}else q.restore()},anonymousValue:function(){var a=q.i,b=q.$re(/^([^.#@\$+\/'"*`(;{}-]*);/);if(b)return new e.Anonymous(b[1],a)},permissiveValue:function(a){function b(){var a=q.currentChar();return"string"==typeof i?a===i:i.test(a)}var d,f,g,h,i=a||";",k=q.i,l=[];if(!b()){h=[];do f=this.comment(),f?h.push(f):(f=this.entity(),f&&h.push(f));while(f);if(g=b(),h.length>0){if(h=new e.Expression(h),g)return h;l.push(h)," "===q.prevChar()&&l.push(new e.Anonymous(" ",k))}if(q.save(),h=q.$parseUntil(i)){if("string"==typeof h&&j("Expected '"+h+"'","Parse"),1===h.length&&" "===h[0])return q.forget(),new e.Anonymous("",k);var m;for(d=0;d0)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()||b.mixinLookup(),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=this.permissiveValue(/^[{;]/),m="{"===q.currentChar(),d?d.value||(d=null):m||";"===q.currentChar()||j(b+" rule is missing block or ending semi-colon")),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(){function a(){return this.addition()||g.keyword()||g.quoted()||g.mixinLookup()}var b,c,d,f,g=this.entities,h=q.i;if(a=a.bind(this),b=a())return q.$char(">")?f=q.$char("=")?">=":">":q.$char("<")?f=q.$char("=")?"<=":"<":q.$char("=")&&(f=q.$char(">")?"=>":q.$char("<")?"=<":"="),f?(c=a(),c?d=new e.Condition(f,b,c,h,(!1)):j("expected expression")):d=new e.Condition("=",b,new e.Keyword("true"),h,(!1)),d},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.quoted(!0)||b.colorKeyword()||b.mixinLookup();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)})],l=[];if(b.pluginManager){j=b.pluginManager.visitor();for(var m=0;m<2;m++)for(j.first();i=j.get();)i.isPreEvalVisitor?0!==m&&l.indexOf(i)!==-1||(l.push(i),i.run(a)):0!==m&&k.indexOf(i)!==-1||(i.isPreVisitor?k.unshift(i):k.push(i))}c=a.eval(h);for(var m=0;m.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":74}],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":74,"./unit":82}],61:[function(a,b,c){var d=a("./node"),e=a("./paren"),f=a("./combinator"),g=function(a,b,c,d,e,g){this.combinator=a instanceof f?a:new f(a),this.value="string"==typeof b?b.trim():b?b:"",this.isVariable=c,this._index=d,this._fileInfo=e,this.copyVisibilityInfo(g),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.isVariable,this.getIndex(),this.fileInfo(),this.visibilityInfo())},g.prototype.clone=function(){return new g(this.combinator,this.value,this.isVariable,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":74,"./paren":76}],62:[function(a,b,c){var d=a("./node"),e=a("./paren"),f=a("./comment"),g=function(a,b){if(this.value=a,this.noSpacing=b,!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=a.isMathOn(),d=this.parens&&!this.parensInOp,f=!1;return d&&a.inParenthesis(),this.value.length>1?b=new g(this.value.map(function(b){return b.eval?b.eval(a):b}),this.noSpacing):1===this.value.length?(!this.value[0].parens||this.value[0].parensInOp||a.inCalc||(f=!0),b=this.value[0].eval(a)):b=this,d&&a.outOfParenthesis(),this.parens&&this.parensInOp&&!c&&!f&&(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":74,"./selector":80}],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":87,"./anonymous":48,"./media":69,"./node":74,"./quoted":78,"./ruleset":79,"./url":83}],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"),d.NamespaceValue=a("./namespace-value"),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,"./namespace-value":72,"./negative":73,"./node":74,"./operation":75,"./paren":76,"./property":77,"./quoted":78,"./ruleset":79,"./selector":80,"./unicode-descriptor":81,"./unit":82,"./url":83,"./value":84,"./variable":86,"./variable-call":85}],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),c=typeof b;return"number"!==c||isNaN(b)?"string"===c?new f('"'+b+'"',b,this.escaped,this._index):new g(Array.isArray(b)?b.join(", "):b):new e(b)},b.exports=h},{"./anonymous":48,"./dimension":60,"./js-eval-node":67,"./quoted":78}],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":74,"./variable":86}],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":74}],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},{}],75:[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":74}],76:[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":74}],77:[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;h0;a--){var b=this.rules[a-1];if(b instanceof e)return this.parseValue(b)}},q.prototype.parseValue=function(a){function b(a){return a.value instanceof k&&!a.parsed?("string"==typeof a.value.value?this.parse.parseNode(a.value.value,["value","important"],a.value.getIndex(),a.fileInfo(),function(b,c){b&&(a.parsed=!0),c&&(a.value=c[0],a.important=c[1]||"",a.parsed=!0)}):a.parsed=!0,a):a}var c=this;if(Array.isArray(a)){var d=[];return a.forEach(function(a){d.push(b.call(c,a))}),d}return b.call(c,a)},q.prototype.rulesets=function(){if(!this.rules)return[];var a,b,c=[],d=this.rules;for(a=0;b=d[a];a++)b.isRuleset&&c.push(b);return c},q.prototype.prependRule=function(a){var b=this.rules;b?b.unshift(a):this.rules=[a],this.setParent(a,this)},q.prototype.find=function(a,b,c){b=b||this;var d,e,f=[],g=a.toCSS();return g in this._lookups?this._lookups[g]:(this.rulesets().forEach(function(g){if(g!==b)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.isVariable,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.isVariable,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":87,"./visitor":95}],89:[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},{}],90:[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":95}],95:[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._visitInCache={},this._visitOutCache={},h||(e(f,1),h=!0)};i.prototype={visit:function(a){if(!a)return a;var b=a.typeIndex;if(!b)return a.value&&a.value.typeIndex&&this.visit(a.value),a;var c,e=this._implementation,f=this._visitInCache[b],h=this._visitOutCache[b],i=g;if(i.visitDeeper=!0,f||(c="visit"+a.type,f=e[c]||d,h=e[c+"Out"]||d,this._visitInCache[b]=f,this._visitOutCache[b]=h),f!==d){var j=f.call(e,a,i);a&&e.isReplacing&&(a=j)}return i.visitDeeper&&a&&a.accept&&a.accept(this),h!=d&&h.call(e,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"); +require('promise/polyfill'); var options = require('../less/default-options')(); @@ -19,7 +19,7 @@ if (window.less) { } } } -require("./add-default-options")(window, options); +require('./add-default-options')(window, options); options.plugins = options.plugins || []; @@ -27,7 +27,7 @@ if (window.LESS_PLUGINS) { options.plugins = options.plugins.concat(window.LESS_PLUGINS); } -var less = module.exports = require("./index")(window, options); +var less = module.exports = require('./index')(window, options); window.less = less; diff --git a/lib/less-browser/browser.js b/lib/less-browser/browser.js index 1fe6f8c2..defc9772 100644 --- a/lib/less-browser/browser.js +++ b/lib/less-browser/browser.js @@ -1,4 +1,4 @@ -var utils = require("./utils"); +var utils = require('./utils'); module.exports = { createCSS: function (document, styles, sheet) { // Strip the query-string @@ -50,14 +50,14 @@ module.exports = { try { styleNode.styleSheet.cssText = styles; } catch (e) { - throw new Error("Couldn't reassign styleSheet.cssText."); + throw new Error('Couldn\'t reassign styleSheet.cssText.'); } } }, currentScript: function(window) { var document = window.document; return document.currentScript || (function() { - var scripts = document.getElementsByTagName("script"); + var scripts = document.getElementsByTagName('script'); return scripts[scripts.length - 1]; })(); } diff --git a/lib/less-browser/cache.js b/lib/less-browser/cache.js index 2c8d6af3..827bc251 100644 --- a/lib/less-browser/cache.js +++ b/lib/less-browser/cache.js @@ -29,11 +29,12 @@ module.exports = function(window, options, logger) { vars = cache && cache.getItem(path + ':vars'); modifyVars = modifyVars || {}; + vars = vars || "{}"; // if not set, treat as the JSON representation of an empty object if (timestamp && webInfo.lastModified && (new Date(webInfo.lastModified).valueOf() === new Date(timestamp).valueOf()) && - (!modifyVars && !vars || JSON.stringify(modifyVars) === vars)) { + JSON.stringify(modifyVars) === vars) { // Use local copy return css; } diff --git a/lib/less-browser/error-reporting.js b/lib/less-browser/error-reporting.js index abf8e567..65df6ec1 100644 --- a/lib/less-browser/error-reporting.js +++ b/lib/less-browser/error-reporting.js @@ -1,20 +1,20 @@ -var utils = require("./utils"), - browser = require("./browser"); +var utils = require('./utils'), + browser = require('./browser'); module.exports = function(window, less, options) { function errorHTML(e, rootHref) { - var id = 'less-error-message:' + utils.extractId(rootHref || ""); + var id = 'less-error-message:' + utils.extractId(rootHref || ''); var template = '
  • {content}
  • '; var elem = window.document.createElement('div'), timer, content, errors = []; var filename = e.filename || rootHref; var filenameNoPath = filename.match(/([^\/]+(\?.*)?)$/)[1]; elem.id = id; - elem.className = "less-error-message"; + elem.className = 'less-error-message'; - content = '

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

    ' + '

    in ' + filenameNoPath + " "; + content = '

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

    ' + '

    in ' + filenameNoPath + ' '; var errorline = function (e, i, classname) { if (e.extract[i] !== undefined) { @@ -77,15 +77,15 @@ module.exports = function(window, less, options) { ].join('\n'), { title: 'error-message' }); elem.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" + '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(';'); if (options.env === 'development') { @@ -116,12 +116,12 @@ module.exports = function(window, less, options) { } function removeError(path) { - if (!options.errorReporting || options.errorReporting === "html") { + if (!options.errorReporting || options.errorReporting === 'html') { removeErrorHTML(path); - } else if (options.errorReporting === "console") { + } else if (options.errorReporting === 'console') { removeErrorConsole(path); } else if (typeof options.errorReporting === 'function') { - options.errorReporting("remove", path); + options.errorReporting('remove', path); } } @@ -129,8 +129,8 @@ module.exports = function(window, less, options) { var template = '{line} {content}'; 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; + var content = (e.type || 'Syntax') + 'Error: ' + (e.message || 'There is an error in your .less file') + + ' in ' + filename; var errorline = function (e, i, classname) { if (e.extract[i] !== undefined) { @@ -154,12 +154,12 @@ module.exports = function(window, less, options) { } function error(e, rootHref) { - if (!options.errorReporting || options.errorReporting === "html") { + if (!options.errorReporting || options.errorReporting === 'html') { errorHTML(e, rootHref); - } else if (options.errorReporting === "console") { + } else if (options.errorReporting === 'console') { errorConsole(e, rootHref); } else if (typeof options.errorReporting === 'function') { - options.errorReporting("add", e, rootHref); + options.errorReporting('add', e, rootHref); } } diff --git a/lib/less-browser/file-manager.js b/lib/less-browser/file-manager.js index 5946afa4..b59e0a40 100644 --- a/lib/less-browser/file-manager.js +++ b/lib/less-browser/file-manager.js @@ -2,7 +2,7 @@ module.exports = function(options, logger) { - var AbstractFileManager = require("../less/environment/abstract-file-manager.js"); + var AbstractFileManager = require('../less/environment/abstract-file-manager.js'); var fileCache = {}; @@ -29,7 +29,7 @@ module.exports = function(options, logger) { if (typeof xhr.overrideMimeType === 'function') { xhr.overrideMimeType('text/css'); } - logger.debug("XHR: Getting '" + url + "'"); + logger.debug('XHR: Getting \'' + url + '\''); xhr.open('GET', url, async); xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5'); xhr.send(null); @@ -37,7 +37,7 @@ module.exports = function(options, logger) { function handleResponse(xhr, callback, errback) { if (xhr.status >= 200 && xhr.status < 300) { callback(xhr.responseText, - xhr.getResponseHeader("Last-Modified")); + xhr.getResponseHeader('Last-Modified')); } else if (typeof errback === 'function') { errback(xhr.status, url); } @@ -91,7 +91,7 @@ module.exports = function(options, logger) { 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 reject({ filename: href, message: 'Error loading file ' + href + ' error was ' + e.message }); } } @@ -102,7 +102,7 @@ module.exports = function(options, logger) { // 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 }); + reject({ type: 'File', message: '\'' + url + '\' wasn\'t found (' + status + ')', href: href }); }); }); }; diff --git a/lib/less-browser/image-size.js b/lib/less-browser/image-size.js index 31460fdb..439336c1 100644 --- a/lib/less-browser/image-size.js +++ b/lib/less-browser/image-size.js @@ -1,24 +1,24 @@ module.exports = function() { - var functionRegistry = require("./../less/functions/function-registry"); + var functionRegistry = require('./../less/functions/function-registry'); function imageSize() { throw { - type: "Runtime", - message: "Image size functions are not supported in browser version of less" + type: 'Runtime', + message: 'Image size functions are not supported in browser version of less' }; } var imageFunctions = { - "image-size": function(filePathNode) { + 'image-size': function(filePathNode) { imageSize(this, filePathNode); return -1; }, - "image-width": function(filePathNode) { + 'image-width': function(filePathNode) { imageSize(this, filePathNode); return -1; }, - "image-height": function(filePathNode) { + 'image-height': function(filePathNode) { imageSize(this, filePathNode); return -1; } diff --git a/lib/less-browser/index.js b/lib/less-browser/index.js index 425d0205..dd0bc361 100644 --- a/lib/less-browser/index.js +++ b/lib/less-browser/index.js @@ -2,8 +2,8 @@ // index.js // Should expose the additional browser functions on to the less object // -var addDataAttr = require("./utils").addDataAttr, - browser = require("./browser"); +var addDataAttr = require('./utils').addDataAttr, + browser = require('./browser'); module.exports = function(window, options) { var document = window.document; @@ -11,15 +11,15 @@ module.exports = function(window, options) { less.options = options; var environment = less.environment, - FileManager = require("./file-manager")(options, less.logger), + FileManager = require('./file-manager')(options, less.logger), fileManager = new FileManager(); environment.addFileManager(fileManager); less.FileManager = FileManager; - less.PluginLoader = require("./plugin-loader"); + 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('./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 - Deprecate? @@ -59,7 +59,7 @@ module.exports = function(window, options) { less.render(lessText, instanceOptions, bind(function(style, e, result) { if (e) { - errors.add(e, "inline"); + errors.add(e, 'inline'); } else { style.type = 'text/css'; if (style.styleSheet) { @@ -222,7 +222,7 @@ module.exports = function(window, options) { endTime = new Date(); totalMilliseconds = endTime - startTime; - less.logger.info("Less has finished and no sheets were loaded."); + less.logger.info('Less has finished and no sheets were loaded.'); resolve({ startTime: startTime, endTime: endTime, @@ -239,12 +239,12 @@ module.exports = function(window, options) { return; } if (webInfo.local) { - less.logger.info("Loading " + sheet.href + " from cache."); + less.logger.info('Loading ' + sheet.href + ' from cache.'); } else { - less.logger.info("Rendered " + sheet.href + " successfully."); + less.logger.info('Rendered ' + sheet.href + ' successfully.'); } browser.createCSS(window.document, css, sheet); - less.logger.info("CSS for " + sheet.href + " generated in " + (new Date() - endTime) + 'ms'); + less.logger.info('CSS for ' + sheet.href + ' generated in ' + (new Date() - endTime) + 'ms'); // Count completed sheet remainingSheets--; @@ -252,7 +252,7 @@ module.exports = function(window, options) { // Check if the last remaining sheet was processed and then call the promise if (remainingSheets === 0) { totalMilliseconds = new Date() - startTime; - less.logger.info("Less has finished. CSS generated in " + totalMilliseconds + 'ms'); + less.logger.info('Less has finished. CSS generated in ' + totalMilliseconds + 'ms'); resolve({ startTime: startTime, endTime: endTime, diff --git a/lib/less-browser/plugin-loader.js b/lib/less-browser/plugin-loader.js index bd160f2f..3fabd5a0 100644 --- a/lib/less-browser/plugin-loader.js +++ b/lib/less-browser/plugin-loader.js @@ -1,15 +1,14 @@ // TODO: Add tests for browser @plugin -/*global window */ +/* global window */ -var AbstractPluginLoader = require("../less/environment/abstract-plugin-loader.js"); +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; + // Should we shim this.require for browser? Probably not? }; PluginLoader.prototype = new AbstractPluginLoader(); diff --git a/lib/less-browser/utils.js b/lib/less-browser/utils.js index 4ee14058..80e73233 100644 --- a/lib/less-browser/utils.js +++ b/lib/less-browser/utils.js @@ -10,7 +10,7 @@ module.exports = { addDataAttr: function(options, tag) { for (var opt in tag.dataset) { if (tag.dataset.hasOwnProperty(opt)) { - if (opt === "env" || opt === "dumpLineNumbers" || opt === "rootpath" || opt === "errorReporting") { + if (opt === 'env' || opt === 'dumpLineNumbers' || opt === 'rootpath' || opt === 'errorReporting') { options[opt] = tag.dataset[opt]; } else { try { diff --git a/lib/less-node/environment.js b/lib/less-node/environment.js index 4df4e185..104222af 100644 --- a/lib/less-node/environment.js +++ b/lib/less-node/environment.js @@ -9,6 +9,6 @@ module.exports = { return require('mime').charsets.lookup(mime); }, getSourceMapGenerator: function getSourceMapGenerator() { - return require("source-map").SourceMapGenerator; + return require('source-map').SourceMapGenerator; } }; diff --git a/lib/less-node/file-manager.js b/lib/less-node/file-manager.js index 435dbfb4..7bec25d0 100644 --- a/lib/less-node/file-manager.js +++ b/lib/less-node/file-manager.js @@ -1,7 +1,7 @@ var path = require('path'), fs = require('./fs'), PromiseConstructor = typeof Promise === 'undefined' ? require('promise') : Promise, - AbstractFileManager = require("../less/environment/abstract-file-manager.js"); + AbstractFileManager = require('../less/environment/abstract-file-manager.js'); var FileManager = function() { this.contents = {}; @@ -23,7 +23,7 @@ FileManager.prototype.loadFile = function(filename, currentDirectory, options, e filenamesTried = [], self = this, prefix = filename.slice(0, 1), - explicit = prefix === "." || prefix === "/", + explicit = prefix === '.' || prefix === '/', result = null, isNodeModule = false, npmPrefix = 'npm://'; @@ -162,7 +162,7 @@ FileManager.prototype.loadFile = function(filename, currentDirectory, options, e } })(0); } else { - reject({ type: 'File', message: "'" + filename + "' wasn't found. Tried - " + filenamesTried.join(",") }); + reject({ type: 'File', message: '\'' + filename + '\' wasn\'t found. Tried - ' + filenamesTried.join(',') }); } }(0)); } diff --git a/lib/less-node/fs.js b/lib/less-node/fs.js index 2a41c41a..89986b62 100644 --- a/lib/less-node/fs.js +++ b/lib/less-node/fs.js @@ -1,10 +1,10 @@ var fs; try { - fs = require("graceful-fs"); + fs = require('graceful-fs'); } catch (e) { - fs = require("fs"); + fs = require('fs'); } module.exports = fs; diff --git a/lib/less-node/image-size.js b/lib/less-node/image-size.js index 01b96390..ef8c8487 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"); + var Dimension = require('../less/tree/dimension'), + Expression = require('../less/tree/expression'), + functionRegistry = require('./../less/functions/function-registry'); function imageSize(functionContext, filePathNode) { var filePath = filePathNode.value; @@ -20,8 +20,8 @@ module.exports = function(environment) { if (!fileManager) { throw { - type: "File", - message: "Can not set up FileManager for " + filePathNode + type: 'File', + message: 'Can not set up FileManager for ' + filePathNode }; } @@ -36,20 +36,20 @@ module.exports = function(environment) { } var imageFunctions = { - "image-size": function(filePathNode) { + 'image-size': function(filePathNode) { var size = imageSize(this, filePathNode); return new Expression([ - new Dimension(size.width, "px"), - new Dimension(size.height, "px") + new Dimension(size.width, 'px'), + new Dimension(size.height, 'px') ]); }, - "image-width": function(filePathNode) { + 'image-width': function(filePathNode) { var size = imageSize(this, filePathNode); - return new Dimension(size.width, "px"); + return new Dimension(size.width, 'px'); }, - "image-height": function(filePathNode) { + 'image-height': function(filePathNode) { var size = imageSize(this, filePathNode); - return new Dimension(size.height, "px"); + return new Dimension(size.height, 'px'); } }; diff --git a/lib/less-node/index.js b/lib/less-node/index.js index 2273a347..d485aa9c 100644 --- a/lib/less-node/index.js +++ b/lib/less-node/index.js @@ -1,7 +1,7 @@ -var environment = require("./environment"), - FileManager = require("./file-manager"), - UrlFileManager = require("./url-file-manager"), - createFromEnvironment = require("../less"), +var environment = require('./environment'), + FileManager = require('./file-manager'), + UrlFileManager = require('./url-file-manager'), + createFromEnvironment = require('../less'), less = createFromEnvironment(environment, [new FileManager(), new UrlFileManager()]), lesscHelper = require('./lessc-helper'), path = require('path'); @@ -9,8 +9,8 @@ var environment = require("./environment"), // allow people to create less with their own environment less.createFromEnvironment = createFromEnvironment; less.lesscHelper = lesscHelper; -less.PluginLoader = require("./plugin-loader"); -less.fs = require("./fs"); +less.PluginLoader = require('./plugin-loader'); +less.fs = require('./fs'); less.FileManager = FileManager; less.UrlFileManager = UrlFileManager; diff --git a/lib/less-node/lessc-helper.js b/lib/less-node/lessc-helper.js index 6dedbe3c..8b40f4fd 100644 --- a/lib/less-node/lessc-helper.js +++ b/lib/less-node/lessc-helper.js @@ -21,60 +21,60 @@ var lessc_helper = { // 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(" --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."); - console.log(" TYPE can be either 'comments', which will output"); - console.log(" the debug info within comments, 'mediaquery'"); - console.log(" that will output the information within a fake"); - console.log(" media query which is compatible with the SASS"); - console.log(" format, and 'all' which will do both."); - console.log(" -x, --compress Compresses output by removing some whitespaces."); - console.log(" We recommend you use a dedicated minifer like less-plugin-clean-css"); - console.log(""); - console.log("Report bugs to: http://github.com/less/less.js/issues"); - console.log("Home page: "); + 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(' --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.'); + console.log(' TYPE can be either \'comments\', which will output'); + console.log(' the debug info within comments, \'mediaquery\''); + console.log(' that will output the information within a fake'); + console.log(' media query which is compatible with the SASS'); + console.log(' format, and \'all\' which will do both.'); + console.log(' -x, --compress Compresses output by removing some whitespaces.'); + console.log(' We recommend you use a dedicated minifer like less-plugin-clean-css'); + console.log(''); + console.log('Report bugs to: http://github.com/less/less.js/issues'); + console.log('Home page: '); } }; diff --git a/lib/less-node/plugin-loader.js b/lib/less-node/plugin-loader.js index fa45b9f4..8e6f4fbf 100644 --- a/lib/less-node/plugin-loader.js +++ b/lib/less-node/plugin-loader.js @@ -1,14 +1,13 @@ -var path = require("path"), +var path = require('path'), PromiseConstructor = typeof Promise === 'undefined' ? require('promise') : Promise, - AbstractPluginLoader = require("../less/environment/abstract-plugin-loader.js"); + AbstractPluginLoader = require('../less/environment/abstract-plugin-loader.js'); /** * Node Plugin Loader */ var PluginLoader = function(less) { this.less = less; - this.require = require; - this.requireRelative = function(prefix) { + this.require = function(prefix) { prefix = path.dirname(prefix); return function(id) { var str = id.substr(0, 2); @@ -25,9 +24,8 @@ var PluginLoader = function(less) { 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"; + var explicit = prefix === '.' || prefix === '/' || filename.slice(-3).toLowerCase() === '.js'; if (!explicit) { context.prefixes = ['less-plugin-', '']; } @@ -36,7 +34,6 @@ PluginLoader.prototype.loadPlugin = function(filename, basePath, context, enviro fileManager.loadFile(filename, basePath, context, environment).then( function(data) { try { - self.require = self.requireRelative(data.filename); fulfill(data); } catch (e) { diff --git a/lib/less-node/url-file-manager.js b/lib/less-node/url-file-manager.js index d3884b4e..a9dbb1c4 100644 --- a/lib/less-node/url-file-manager.js +++ b/lib/less-node/url-file-manager.js @@ -2,8 +2,8 @@ var isUrlRe = /^(?:https?:)?\/\//i, url = require('url'), request, PromiseConstructor, - AbstractFileManager = require("../less/environment/abstract-file-manager.js"), - logger = require("../less/logger"); + AbstractFileManager = require('../less/environment/abstract-file-manager.js'), + logger = require('../less/logger'); var UrlFileManager = function() { }; @@ -24,7 +24,7 @@ UrlFileManager.prototype.loadFile = function(filename, currentDirectory, options catch (e) { request = null; } } if (!request) { - reject({ type: 'File', message: "optional dependency 'request' required to import over http(s)\n" }); + reject({ type: 'File', message: 'optional dependency \'request\' required to import over http(s)\n' }); return; } @@ -32,17 +32,17 @@ UrlFileManager.prototype.loadFile = function(filename, currentDirectory, options urlObj = url.parse(urlStr); if (!urlObj.protocol) { - urlObj.protocol = "http"; + urlObj.protocol = 'http'; urlStr = urlObj.format(); } request.get({uri: urlStr, strictSSL: !options.insecure }, function (error, res, body) { if (error) { - reject({ type: 'File', message: "resource '" + urlStr + "' gave this Error:\n " + error + "\n" }); + reject({ type: 'File', message: 'resource \'' + urlStr + '\' gave this Error:\n ' + error + '\n' }); return; } if (res && res.statusCode === 404) { - reject({ type: 'File', message: "resource '" + urlStr + "' was not found\n" }); + reject({ type: 'File', message: 'resource \'' + urlStr + '\' was not found\n' }); return; } if (!body) { diff --git a/lib/less-rhino/index.js b/lib/less-rhino/index.js index e82132c8..79015eb9 100644 --- a/lib/less-rhino/index.js +++ b/lib/less-rhino/index.js @@ -4,7 +4,7 @@ function formatError(ctx, options) { options = options || {}; - var message = ""; + var message = ''; var extract = ctx.extract; var error = []; @@ -124,7 +124,7 @@ less.Parser.fileLoader = function (file, currentFileInfo, callback, env) { try { data = readFile(href); } catch (e) { - callback({ type: 'File', message: "'" + less.modules.path.basename(href) + "' wasn't found" }); + callback({ type: 'File', message: '\'' + less.modules.path.basename(href) + '\' wasn\'t found' }); return; } @@ -152,7 +152,7 @@ function writeFile(filename, content) { var checkArgFunc = function(arg, option) { if (!option) { - print(arg + " option requires a parameter"); + print(arg + ' option requires a parameter'); continueProcessing = false; return false; } @@ -162,14 +162,14 @@ function writeFile(filename, content) { var checkBooleanArg = function(arg) { var onOff = /^((on|t|true|y|yes)|(off|f|false|n|no))$/i.exec(arg); if (!onOff) { - print(" unable to parse " + arg + " as a boolean. use one of on/t/true/y/yes/off/f/false/n/no"); + print(' unable to parse ' + arg + ' as a boolean. use one of on/t/true/y/yes/off/f/false/n/no'); continueProcessing = false; return false; } return Boolean(onOff[2]); }; - var warningMessages = ""; + var warningMessages = ''; var sourceMapFileInline = false; args = args.filter(function (arg) { @@ -191,7 +191,7 @@ function writeFile(filename, content) { switch (arg) { case 'v': case 'version': - console.log("lessc " + less.version.join('.') + " (Less Compiler) [JavaScript]"); + console.log('lessc ' + less.version.join('.') + ' (Less Compiler) [JavaScript]'); continueProcessing = false; break; case 'verbose': @@ -223,7 +223,7 @@ function writeFile(filename, content) { options.depends = true; break; case 'yui-compress': - warningMessages += "yui-compress option has been removed. assuming clean-css."; + warningMessages += 'yui-compress option has been removed. assuming clean-css.'; options.cleancss = true; break; case 'clean-css': @@ -307,18 +307,18 @@ function writeFile(filename, content) { options.rootpath = match[2].replace(/\\/g, '/'); } break; - case "ru": - case "relative-urls": + case 'ru': + case 'relative-urls': options.relativeUrls = true; break; - case "sm": - case "strict-math": + case 'sm': + case 'strict-math': if (checkArgFunc(arg, match[2])) { options.strictMath = checkBooleanArg(match[2]); } break; - case "su": - case "strict-units": + case 'su': + case 'strict-units': if (checkArgFunc(arg, match[2])) { options.strictUnits = checkBooleanArg(match[2]); } @@ -351,20 +351,20 @@ function writeFile(filename, content) { // options.sourceMapBasepath = ''; if (options.sourceMap === true) { - console.log("output: " + output); + console.log('output: ' + output); if (!output && !sourceMapFileInline) { - console.log("the sourcemap option only has an optional filename if the css filename is given"); + console.log('the sourcemap option only has an optional filename if the css filename is given'); return; } - options.sourceMapFullFilename = options.sourceMapOutputFilename + ".map"; + options.sourceMapFullFilename = options.sourceMapOutputFilename + '.map'; options.sourceMap = less.modules.path.basename(options.sourceMapFullFilename); } else if (options.sourceMap) { options.sourceMapOutputFilename = options.sourceMap; } if (!name) { - console.log("lessc: no inout files"); - console.log(""); + console.log('lessc: no inout files'); + console.log(''); // TODO // require('../lib/less/lessc_helper').printUsage(); currentErrorcode = 1; @@ -388,10 +388,10 @@ function writeFile(filename, content) { if (options.depends) { if (!outputbase) { - console.log("option --depends requires an output path to be specified"); + console.log('option --depends requires an output path to be specified'); return; } - console.log(outputbase + ": "); + console.log(outputbase + ': '); } if (!name) { @@ -420,7 +420,7 @@ function writeFile(filename, content) { result = root.toCSS(options); if (output) { writeFile(output, result); - console.log("Written to " + output); + console.log('Written to ' + output); } else { print(result); } diff --git a/lib/less/contexts.js b/lib/less/contexts.js index e4d5342e..17067ec5 100644 --- a/lib/less/contexts.js +++ b/lib/less/contexts.js @@ -36,7 +36,7 @@ var parseCopyProperties = [ contexts.Parse = function(options) { copyFromOriginal(options, this, parseCopyProperties); - if (typeof this.paths === "string") { this.paths = [this.paths]; } + if (typeof this.paths === 'string') { this.paths = [this.paths]; } }; var evalCopyProperties = [ @@ -56,12 +56,27 @@ var evalCopyProperties = [ contexts.Eval = function(options, frames) { copyFromOriginal(options, this, evalCopyProperties); - if (typeof this.paths === "string") { this.paths = [this.paths]; } + if (typeof this.paths === 'string') { this.paths = [this.paths]; } this.frames = frames || []; this.importantScope = this.importantScope || []; }; +contexts.Eval.prototype.enterCalc = function () { + if (!this.calcStack) { + this.calcStack = []; + } + this.calcStack.push(true); + this.inCalc = true; +}; + +contexts.Eval.prototype.exitCalc = function () { + this.calcStack.pop(); + if (!this.calcStack) { + this.inCalc = false; + } +}; + contexts.Eval.prototype.inParenthesis = function () { if (!this.parensStack) { this.parensStack = []; @@ -73,6 +88,7 @@ contexts.Eval.prototype.outOfParenthesis = function () { this.parensStack.pop(); }; +contexts.Eval.prototype.inCalc = false; contexts.Eval.prototype.mathOn = true; contexts.Eval.prototype.isMathOn = function (op) { if (!this.mathOn) { @@ -93,17 +109,17 @@ contexts.Eval.prototype.isPathRelative = function (path) { contexts.Eval.prototype.normalizePath = function( path ) { var - segments = path.split("/").reverse(), + segments = path.split('/').reverse(), segment; path = []; while (segments.length !== 0 ) { segment = segments.pop(); switch ( segment ) { - case ".": + case '.': break; - case "..": - if ((path.length === 0) || (path[path.length - 1] === "..")) { + case '..': + if ((path.length === 0) || (path[path.length - 1] === '..')) { path.push( segment ); } else { path.pop(); @@ -115,7 +131,7 @@ contexts.Eval.prototype.normalizePath = function( path ) { } } - return path.join("/"); + return path.join('/'); }; // todo - do the same for the toCSS ? diff --git a/lib/less/data/index.js b/lib/less/data/index.js index a5f41e2e..ced7f71e 100644 --- a/lib/less/data/index.js +++ b/lib/less/data/index.js @@ -1,4 +1,4 @@ module.exports = { - colors: require("./colors"), - unitConversions: require("./unit-conversions") + colors: require('./colors'), + unitConversions: require('./unit-conversions') }; diff --git a/lib/less/environment/abstract-file-manager.js b/lib/less/environment/abstract-file-manager.js index 05911492..36428f06 100644 --- a/lib/less/environment/abstract-file-manager.js +++ b/lib/less/environment/abstract-file-manager.js @@ -11,7 +11,7 @@ abstractFileManager.prototype.getPath = function (filename) { j = filename.lastIndexOf('\\'); } if (j < 0) { - return ""; + return ''; } return filename.slice(0, j + 1); }; @@ -48,9 +48,9 @@ abstractFileManager.prototype.pathDiff = function pathDiff(url, baseUrl) { var urlParts = this.extractUrlParts(url), baseUrlParts = this.extractUrlParts(baseUrl), - i, max, urlDirectories, baseUrlDirectories, diff = ""; + i, max, urlDirectories, baseUrlDirectories, diff = ''; if (urlParts.hostPart !== baseUrlParts.hostPart) { - return ""; + return ''; } max = Math.max(baseUrlParts.directories.length, urlParts.directories.length); for (i = 0; i < max; i++) { @@ -59,10 +59,10 @@ abstractFileManager.prototype.pathDiff = function pathDiff(url, baseUrl) { baseUrlDirectories = baseUrlParts.directories.slice(i); urlDirectories = urlParts.directories.slice(i); for (i = 0; i < baseUrlDirectories.length - 1; i++) { - diff += "../"; + diff += '../'; } for (i = 0; i < urlDirectories.length - 1; i++) { - diff += urlDirectories[i] + "/"; + diff += urlDirectories[i] + '/'; } return diff; }; @@ -79,31 +79,31 @@ abstractFileManager.prototype.extractUrlParts = function extractUrlParts(url, ba returner = {}, rawDirectories = [], directories = [], i, baseUrlParts; if (!urlParts) { - throw new Error("Could not parse sheet href - '" + url + "'"); + throw new Error('Could not parse sheet href - \'' + url + '\''); } // Stylesheets in IE don't always return the full path if (baseUrl && (!urlParts[1] || urlParts[2])) { baseUrlParts = baseUrl.match(urlPartsRegex); if (!baseUrlParts) { - throw new Error("Could not parse page url - '" + baseUrl + "'"); + throw new Error('Could not parse page url - \'' + baseUrl + '\''); } - urlParts[1] = urlParts[1] || baseUrlParts[1] || ""; + urlParts[1] = urlParts[1] || baseUrlParts[1] || ''; if (!urlParts[2]) { urlParts[3] = baseUrlParts[3] + urlParts[3]; } } if (urlParts[3]) { - rawDirectories = urlParts[3].replace(/\\/g, "/").split("/"); + rawDirectories = urlParts[3].replace(/\\/g, '/').split('/'); // collapse '..' and skip '.' for (i = 0; i < rawDirectories.length; i++) { - if (rawDirectories[i] === "..") { + if (rawDirectories[i] === '..') { directories.pop(); } - else if (rawDirectories[i] !== ".") { + else if (rawDirectories[i] !== '.') { directories.push(rawDirectories[i]); } @@ -112,11 +112,11 @@ abstractFileManager.prototype.extractUrlParts = function extractUrlParts(url, ba returner.hostPart = urlParts[1]; returner.directories = directories; - returner.rawPath = (urlParts[1] || "") + rawDirectories.join("/"); - returner.path = (urlParts[1] || "") + directories.join("/"); + 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] || ""); + 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 index 0a4ad918..ba3b6771 100644 --- a/lib/less/environment/abstract-plugin-loader.js +++ b/lib/less/environment/abstract-plugin-loader.js @@ -1,17 +1,13 @@ -var functionRegistry = require("../functions/function-registry"), +var functionRegistry = require('../functions/function-registry'), LessError = require('../less-error'); var AbstractPluginLoader = function() { + // Implemented by Node.js plugin loader + this.require = function() { + return null; + } }; -function error(msg, type) { - throw new LessError( - { - type: type || 'Syntax', - message: msg - } - ); -} AbstractPluginLoader.prototype.evalPlugin = function(contents, context, imports, pluginOptions, fileInfo) { var loader, @@ -19,12 +15,13 @@ AbstractPluginLoader.prototype.evalPlugin = function(contents, context, imports, pluginObj, localModule, pluginManager, - filename; + filename, + result; pluginManager = context.pluginManager; if (fileInfo) { - if (typeof fileInfo === "string") { + if (typeof fileInfo === 'string') { filename = fileInfo; } else { @@ -37,15 +34,18 @@ AbstractPluginLoader.prototype.evalPlugin = function(contents, context, imports, pluginObj = pluginManager.get(filename); if (pluginObj) { - this.trySetOptions(pluginObj, filename, shortname, pluginOptions); + result = this.trySetOptions(pluginObj, filename, shortname, pluginOptions); + if (result) { + return result; + } 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); + e.message = e.message || 'Error during @plugin call'; + return new LessError(e, imports, filename); } return pluginObj; } @@ -62,10 +62,11 @@ AbstractPluginLoader.prototype.evalPlugin = function(contents, context, imports, }; 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); + loader = new Function('module', 'require', 'registerPlugin', 'functions', 'tree', 'less', 'fileInfo', contents); + loader(localModule, this.require(filename), registerPlugin, registry, this.less.tree, this.less, fileInfo); + } + catch (e) { + return new LessError(e, imports, filename); } if (!pluginObj) { @@ -73,14 +74,32 @@ AbstractPluginLoader.prototype.evalPlugin = function(contents, context, imports, } pluginObj = this.validatePlugin(pluginObj, filename, shortname); + if (pluginObj instanceof LessError) { + return pluginObj; + } + 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); + // For < 3.x (or unspecified minVersion) - setOptions() before install() + if (!pluginObj.minVersion || this.compareVersion('3.0.0', pluginObj.minVersion) < 0) { + result = this.trySetOptions(pluginObj, filename, shortname, pluginOptions); + + if (result) { + return result; + } + } + + // Run on first load + pluginManager.addPlugin(pluginObj, fileInfo.filename, registry); + pluginObj.functions = registry.getLocalFunctions(); + + // Need to call setOptions again because the pluginObj might have functions + result = this.trySetOptions(pluginObj, filename, shortname, pluginOptions); + if (result) { + return result; + } // Run every @plugin call try { @@ -89,13 +108,13 @@ AbstractPluginLoader.prototype.evalPlugin = function(contents, context, imports, } } catch (e) { - e.message = 'Error during @plugin call'; - return new this.less.LessError(e, imports, filename); + e.message = e.message || 'Error during @plugin call'; + return new LessError(e, imports, filename); } } else { - return new this.less.LessError({ message: "Not a valid plugin" }); + return new LessError({ message: 'Not a valid plugin' }, imports, filename); } return pluginObj; @@ -103,18 +122,17 @@ AbstractPluginLoader.prototype.evalPlugin = function(contents, context, imports, }; 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; - } + if (options && !plugin.setOptions) { + return new LessError({ + message: 'Options have been provided but the plugin ' + + name + ' does not support any options.' + }); + } + try { + plugin.setOptions && plugin.setOptions(options); + } + catch (e) { + return new LessError(e); } }; @@ -122,14 +140,16 @@ 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") { + 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 new LessError({ + message: 'Plugin ' + name + ' requires version ' + + this.versionToString(plugin.minVersion) + }); } } return plugin; @@ -138,7 +158,7 @@ AbstractPluginLoader.prototype.validatePlugin = function(plugin, filename, name) }; AbstractPluginLoader.prototype.compareVersion = function(aVersion, bVersion) { - if (typeof aVersion === "string") { + if (typeof aVersion === 'string') { aVersion = aVersion.match(/^(\d+)\.?(\d+)?\.?(\d+)?/); aVersion.shift(); } @@ -150,9 +170,9 @@ AbstractPluginLoader.prototype.compareVersion = function(aVersion, bVersion) { return 0; }; AbstractPluginLoader.prototype.versionToString = function(version) { - var versionString = ""; + var versionString = ''; for (var i = 0; i < version.length; i++) { - versionString += (versionString ? "." : "") + version[i]; + versionString += (versionString ? '.' : '') + version[i]; } return versionString; }; diff --git a/lib/less/environment/environment.js b/lib/less/environment/environment.js index 1f9f762b..926d48f3 100644 --- a/lib/less/environment/environment.js +++ b/lib/less/environment/environment.js @@ -3,12 +3,12 @@ * environment, file managers, and plugin manager */ -var logger = require("../logger"); +var logger = require('../logger'); var environment = function(externalEnvironment, fileManagers) { this.fileManagers = fileManagers || []; externalEnvironment = externalEnvironment || {}; - var optionalFunctions = ["encodeBase64", "mimeLookup", "charsetLookup", "getSourceMapGenerator"], + var optionalFunctions = ['encodeBase64', 'mimeLookup', 'charsetLookup', 'getSourceMapGenerator'], requiredFunctions = [], functions = requiredFunctions.concat(optionalFunctions); @@ -18,7 +18,7 @@ var environment = function(externalEnvironment, fileManagers) { if (environmentFunc) { this[propName] = environmentFunc.bind(externalEnvironment); } else if (i < requiredFunctions.length) { - this.warn("missing required function in environment - " + propName); + this.warn('missing required function in environment - ' + propName); } } }; @@ -26,10 +26,10 @@ var environment = function(externalEnvironment, fileManagers) { environment.prototype.getFileManager = function (filename, currentDirectory, options, environment, isSync) { if (!filename) { - logger.warn("getFileManager called with no filename.. Please report this issue. continuing."); + logger.warn('getFileManager called with no filename.. Please report this issue. continuing.'); } if (currentDirectory == null) { - logger.warn("getFileManager called with null directory.. Please report this issue. continuing."); + logger.warn('getFileManager called with null directory.. Please report this issue. continuing.'); } var fileManagers = this.fileManagers; @@ -38,7 +38,7 @@ environment.prototype.getFileManager = function (filename, currentDirectory, opt } for (var i = fileManagers.length - 1; i >= 0 ; i--) { var fileManager = fileManagers[i]; - if (fileManager[isSync ? "supportsSync" : "supports"](filename, currentDirectory, options, environment)) { + if (fileManager[isSync ? 'supportsSync' : 'supports'](filename, currentDirectory, options, environment)) { return fileManager; } } diff --git a/lib/less/functions/boolean.js b/lib/less/functions/boolean.js index 21254bc3..829ee207 100644 --- a/lib/less/functions/boolean.js +++ b/lib/less/functions/boolean.js @@ -1,7 +1,7 @@ -var functionRegistry = require("./function-registry"), - Anonymous = require("../tree/anonymous"), - Keyword = require("../tree/keyword"); +var functionRegistry = require('./function-registry'), + Anonymous = require('../tree/anonymous'), + Keyword = require('../tree/keyword'); functionRegistry.addMultiple({ boolean: function(condition) { diff --git a/lib/less/functions/color-blending.js b/lib/less/functions/color-blending.js index cc192b63..e34979e3 100644 --- a/lib/less/functions/color-blending.js +++ b/lib/less/functions/color-blending.js @@ -1,5 +1,5 @@ -var Color = require("../tree/color"), - functionRegistry = require("./function-registry"); +var Color = require('../tree/color'), + functionRegistry = require('./function-registry'); // Color Blending // ref: http://www.w3.org/TR/compositing-1 diff --git a/lib/less/functions/color.js b/lib/less/functions/color.js index 864ee937..3669dbbf 100644 --- a/lib/less/functions/color.js +++ b/lib/less/functions/color.js @@ -1,8 +1,8 @@ -var Dimension = require("../tree/dimension"), - Color = require("../tree/color"), - Quoted = require("../tree/quoted"), - Anonymous = require("../tree/anonymous"), - functionRegistry = require("./function-registry"), +var Dimension = require('../tree/dimension'), + Color = require('../tree/color'), + Quoted = require('../tree/quoted'), + Anonymous = require('../tree/anonymous'), + functionRegistry = require('./function-registry'), colorFunctions; function clamp(val) { @@ -18,8 +18,8 @@ function number(n) { return n; } else { throw { - type: "Argument", - message: "color functions take numbers as parameters" + type: 'Argument', + message: 'color functions take numbers as parameters' }; } } @@ -152,7 +152,7 @@ colorFunctions = { } var hsl = color.toHSL(); - if (typeof method !== "undefined" && method.value === "relative") { + if (typeof method !== 'undefined' && method.value === 'relative') { hsl.s += hsl.s * amount.value / 100; } else { @@ -164,7 +164,7 @@ colorFunctions = { desaturate: function (color, amount, method) { var hsl = color.toHSL(); - if (typeof method !== "undefined" && method.value === "relative") { + if (typeof method !== 'undefined' && method.value === 'relative') { hsl.s -= hsl.s * amount.value / 100; } else { @@ -176,7 +176,7 @@ colorFunctions = { lighten: function (color, amount, method) { var hsl = color.toHSL(); - if (typeof method !== "undefined" && method.value === "relative") { + if (typeof method !== 'undefined' && method.value === 'relative') { hsl.l += hsl.l * amount.value / 100; } else { @@ -188,7 +188,7 @@ colorFunctions = { darken: function (color, amount, method) { var hsl = color.toHSL(); - if (typeof method !== "undefined" && method.value === "relative") { + if (typeof method !== 'undefined' && method.value === 'relative') { hsl.l -= hsl.l * amount.value / 100; } else { @@ -200,7 +200,7 @@ colorFunctions = { fadein: function (color, amount, method) { var hsl = color.toHSL(); - if (typeof method !== "undefined" && method.value === "relative") { + if (typeof method !== 'undefined' && method.value === 'relative') { hsl.a += hsl.a * amount.value / 100; } else { @@ -212,7 +212,7 @@ colorFunctions = { fadeout: function (color, amount, method) { var hsl = color.toHSL(); - if (typeof method !== "undefined" && method.value === "relative") { + if (typeof method !== 'undefined' && method.value === 'relative') { hsl.a -= hsl.a * amount.value / 100; } else { @@ -346,8 +346,8 @@ colorFunctions = { return c; } throw { - type: "Argument", - message: "argument must be a color keyword or 3/6 digit hex e.g. #FFF" + type: 'Argument', + message: 'argument must be a color keyword or 3/6 digit hex e.g. #FFF' }; }, tint: function(color, amount) { diff --git a/lib/less/functions/data-uri.js b/lib/less/functions/data-uri.js index 070db9a8..a210589a 100644 --- a/lib/less/functions/data-uri.js +++ b/lib/less/functions/data-uri.js @@ -1,14 +1,14 @@ module.exports = function(environment) { - var Quoted = require("../tree/quoted"), - URL = require("../tree/url"), + var Quoted = require('../tree/quoted'), + URL = require('../tree/url'), utils = require('../utils'), - functionRegistry = require("./function-registry"), + functionRegistry = require('./function-registry'), fallback = function(functionThis, node) { return new URL(node, functionThis.index, functionThis.currentFileInfo).eval(functionThis.context); }, logger = require('../logger'); - functionRegistry.add("data-uri", function(mimetypeNode, filePathNode) { + functionRegistry.add('data-uri', function(mimetypeNode, filePathNode) { if (!filePathNode) { filePathNode = mimetypeNode; @@ -43,7 +43,7 @@ module.exports = function(environment) { mimetype = environment.mimeLookup(filePath); - if (mimetype === "image/svg+xml") { + if (mimetype === 'image/svg+xml') { useBase64 = false; } else { // use base 64 unless it's an ASCII or UTF-8 format @@ -58,7 +58,7 @@ module.exports = function(environment) { var fileSync = fileManager.loadFileSync(filePath, currentDirectory, context, environment); if (!fileSync.contents) { - logger.warn("Skipped data-uri embedding of " + filePath + " because file not found"); + logger.warn('Skipped data-uri embedding of ' + filePath + ' because file not found'); return fallback(this, filePathNode || mimetypeNode); } var buf = fileSync.contents; @@ -68,7 +68,7 @@ module.exports = function(environment) { buf = useBase64 ? environment.encodeBase64(buf) : encodeURIComponent(buf); - var uri = "data:" + mimetype + ',' + buf + fragment; + var uri = 'data:' + mimetype + ',' + buf + fragment; // IE8 cannot handle a data-uri larger than 32,768 characters. If this is exceeded // and the --ieCompat flag is enabled, return a normal url() instead. @@ -76,8 +76,8 @@ module.exports = function(environment) { if (uri.length >= DATA_URI_MAX) { if (this.context.ieCompat !== false) { - logger.warn("Skipped data-uri embedding of " + filePath + " because its size (" + uri.length + - " characters) exceeds IE8-safe " + DATA_URI_MAX + " characters!"); + logger.warn('Skipped data-uri embedding of ' + filePath + ' because its size (' + uri.length + + ' characters) exceeds IE8-safe ' + DATA_URI_MAX + ' characters!'); return fallback(this, filePathNode || mimetypeNode); } diff --git a/lib/less/functions/default.js b/lib/less/functions/default.js index 7e11bee8..194dd398 100644 --- a/lib/less/functions/default.js +++ b/lib/less/functions/default.js @@ -1,5 +1,5 @@ -var Keyword = require("../tree/keyword"), - functionRegistry = require("./function-registry"); +var Keyword = require('../tree/keyword'), + functionRegistry = require('./function-registry'); var defaultFunc = { eval: function () { @@ -22,6 +22,6 @@ var defaultFunc = { } }; -functionRegistry.add("default", defaultFunc.eval.bind(defaultFunc)); +functionRegistry.add('default', defaultFunc.eval.bind(defaultFunc)); module.exports = defaultFunc; diff --git a/lib/less/functions/function-caller.js b/lib/less/functions/function-caller.js index ba8a9e98..1062e7f5 100644 --- a/lib/less/functions/function-caller.js +++ b/lib/less/functions/function-caller.js @@ -1,4 +1,4 @@ -var Expression = require("../tree/expression"); +var Expression = require('../tree/expression'); var functionCaller = function(name, context, index, currentFileInfo) { this.name = name.toLowerCase(); @@ -17,15 +17,15 @@ functionCaller.prototype.call = function(args) { // https://github.com/less/less.js/issues/2477 if (Array.isArray(args)) { args = args.filter(function (item) { - if (item.type === "Comment") { + if (item.type === 'Comment') { return false; } return true; }) .map(function(item) { - if (item.type === "Expression") { + if (item.type === 'Expression') { var subNodes = item.value.filter(function (item) { - if (item.type === "Comment") { + if (item.type === 'Comment') { return false; } return true; diff --git a/lib/less/functions/index.js b/lib/less/functions/index.js index 3b697d53..1b778319 100644 --- a/lib/less/functions/index.js +++ b/lib/less/functions/index.js @@ -1,20 +1,20 @@ module.exports = function(environment) { var functions = { - functionRegistry: require("./function-registry"), - functionCaller: require("./function-caller") + functionRegistry: require('./function-registry'), + functionCaller: require('./function-caller') }; // register functions - require("./boolean"); - require("./default"); - require("./color"); - require("./color-blending"); - require("./data-uri")(environment); - require("./math"); - require("./number"); - require("./string"); - require("./svg")(environment); - require("./types"); + require('./boolean'); + require('./default'); + require('./color'); + require('./color-blending'); + require('./data-uri')(environment); + require('./math'); + require('./number'); + require('./string'); + require('./svg')(environment); + require('./types'); return functions; }; diff --git a/lib/less/functions/math-helper.js b/lib/less/functions/math-helper.js index 440017c6..41b51295 100644 --- a/lib/less/functions/math-helper.js +++ b/lib/less/functions/math-helper.js @@ -1,10 +1,10 @@ -var Dimension = require("../tree/dimension"); +var Dimension = require('../tree/dimension'); var MathHelper = function() { }; MathHelper._math = function (fn, unit, n) { if (!(n instanceof Dimension)) { - throw { type: "Argument", message: "argument must be a number" }; + throw { type: 'Argument', message: 'argument must be a number' }; } if (unit == null) { unit = n.unit; diff --git a/lib/less/functions/math.js b/lib/less/functions/math.js index fc50423a..31fc30ab 100644 --- a/lib/less/functions/math.js +++ b/lib/less/functions/math.js @@ -1,5 +1,5 @@ -var functionRegistry = require("./function-registry"), - mathHelper = require("./math-helper.js"); +var functionRegistry = require('./function-registry'), + mathHelper = require('./math-helper.js'); var mathFunctions = { // name, unit @@ -7,12 +7,12 @@ var mathFunctions = { floor: null, sqrt: null, abs: null, - tan: "", - sin: "", - cos: "", - atan: "rad", - asin: "rad", - acos: "rad" + tan: '', + sin: '', + cos: '', + atan: 'rad', + asin: 'rad', + acos: 'rad' }; for (var f in mathFunctions) { @@ -22,7 +22,7 @@ for (var f in mathFunctions) { } mathFunctions.round = function (n, f) { - var fraction = typeof f === "undefined" ? 0 : f.value; + var fraction = typeof f === 'undefined' ? 0 : f.value; return mathHelper._math(function(num) { return num.toFixed(fraction); }, null, n); }; diff --git a/lib/less/functions/number.js b/lib/less/functions/number.js index 355f4314..fc085a91 100644 --- a/lib/less/functions/number.js +++ b/lib/less/functions/number.js @@ -1,12 +1,12 @@ -var Dimension = require("../tree/dimension"), - Anonymous = require("../tree/anonymous"), - functionRegistry = require("./function-registry"), - mathHelper = require("./math-helper.js"); +var Dimension = require('../tree/dimension'), + Anonymous = require('../tree/anonymous'), + functionRegistry = require('./function-registry'), + mathHelper = require('./math-helper.js'); var minMax = function (isMin, args) { args = Array.prototype.slice.call(args); switch (args.length) { - case 0: throw { type: "Argument", message: "one or more arguments required" }; + case 0: throw { type: 'Argument', message: 'one or more arguments required' }; } var i, j, current, currentUnified, referenceUnified, unit, unitStatic, unitClone, order = [], // elems only contains original argument values. @@ -20,20 +20,20 @@ var minMax = function (isMin, args) { } continue; } - currentUnified = current.unit.toString() === "" && unitClone !== undefined ? new Dimension(current.value, unitClone).unify() : current.unify(); - unit = currentUnified.unit.toString() === "" && unitStatic !== undefined ? unitStatic : currentUnified.unit.toString(); - unitStatic = unit !== "" && unitStatic === undefined || unit !== "" && order[0].unify().unit.toString() === "" ? unit : unitStatic; - unitClone = unit !== "" && unitClone === undefined ? current.unit.toString() : unitClone; - j = values[""] !== undefined && unit !== "" && unit === unitStatic ? values[""] : values[unit]; + currentUnified = current.unit.toString() === '' && unitClone !== undefined ? new Dimension(current.value, unitClone).unify() : current.unify(); + unit = currentUnified.unit.toString() === '' && unitStatic !== undefined ? unitStatic : currentUnified.unit.toString(); + unitStatic = unit !== '' && unitStatic === undefined || unit !== '' && order[0].unify().unit.toString() === '' ? unit : unitStatic; + unitClone = unit !== '' && unitClone === undefined ? current.unit.toString() : unitClone; + 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); continue; } - referenceUnified = order[j].unit.toString() === "" && unitClone !== undefined ? new Dimension(order[j].value, unitClone).unify() : order[j].unify(); + referenceUnified = order[j].unit.toString() === '' && unitClone !== undefined ? new Dimension(order[j].value, unitClone).unify() : order[j].unify(); if ( isMin && currentUnified.value < referenceUnified.value || !isMin && currentUnified.value > referenceUnified.value) { order[j] = current; @@ -42,8 +42,8 @@ var minMax = function (isMin, args) { if (order.length == 1) { return order[0]; } - args = order.map(function (a) { return a.toCSS(this.context); }).join(this.context.compress ? "," : ", "); - return new Anonymous((isMin ? "min" : "max") + "(" + args + ")"); + args = order.map(function (a) { return a.toCSS(this.context); }).join(this.context.compress ? ',' : ', '); + return new Anonymous((isMin ? 'min' : 'max') + '(' + args + ')'); }; functionRegistry.addMultiple({ min: function () { @@ -62,11 +62,11 @@ functionRegistry.addMultiple({ return new Dimension(a.value % b.value, a.unit); }, pow: function(x, y) { - if (typeof x === "number" && typeof y === "number") { + if (typeof x === 'number' && typeof y === 'number') { x = new Dimension(x); y = new Dimension(y); } else if (!(x instanceof Dimension) || !(y instanceof Dimension)) { - throw { type: "Argument", message: "arguments must be numbers" }; + throw { type: 'Argument', message: 'arguments must be numbers' }; } return new Dimension(Math.pow(x.value, y.value), x.unit); diff --git a/lib/less/functions/string.js b/lib/less/functions/string.js index 5ae13759..11930984 100644 --- a/lib/less/functions/string.js +++ b/lib/less/functions/string.js @@ -1,7 +1,7 @@ -var Quoted = require("../tree/quoted"), - Anonymous = require("../tree/anonymous"), - JavaScript = require("../tree/javascript"), - functionRegistry = require("./function-registry"); +var Quoted = require('../tree/quoted'), + Anonymous = require('../tree/anonymous'), + JavaScript = require('../tree/javascript'), + functionRegistry = require('./function-registry'); functionRegistry.addMultiple({ e: function (str) { @@ -9,12 +9,12 @@ functionRegistry.addMultiple({ }, escape: function (str) { return new Anonymous( - encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B") - .replace(/\(/g, "%28").replace(/\)/g, "%29")); + encodeURI(str.value).replace(/=/g, '%3D').replace(/:/g, '%3A').replace(/#/g, '%23').replace(/;/g, '%3B') + .replace(/\(/g, '%28').replace(/\)/g, '%29')); }, replace: function (string, pattern, replacement, flags) { var result = string.value; - replacement = (replacement.type === "Quoted") ? + replacement = (replacement.type === 'Quoted') ? replacement.value : replacement.toCSS(); result = result.replace(new RegExp(pattern.value, flags ? flags.value : ''), replacement); return new Quoted(string.quote || '', result, string.escaped); @@ -26,7 +26,7 @@ functionRegistry.addMultiple({ for (var i = 0; i < args.length; i++) { /* jshint loopfunc:true */ result = result.replace(/%[sda]/i, function(token) { - var value = ((args[i].type === "Quoted") && + var value = ((args[i].type === 'Quoted') && token.match(/s/i)) ? args[i].value : args[i].toCSS(); return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; }); diff --git a/lib/less/functions/svg.js b/lib/less/functions/svg.js index e5f0e357..6e24386b 100644 --- a/lib/less/functions/svg.js +++ b/lib/less/functions/svg.js @@ -1,16 +1,16 @@ module.exports = function(environment) { - var Dimension = require("../tree/dimension"), - Color = require("../tree/color"), - Expression = require("../tree/expression"), - Quoted = require("../tree/quoted"), - URL = require("../tree/url"), - functionRegistry = require("./function-registry"); + var Dimension = require('../tree/dimension'), + Color = require('../tree/color'), + Expression = require('../tree/expression'), + Quoted = require('../tree/quoted'), + URL = require('../tree/url'), + functionRegistry = require('./function-registry'); - functionRegistry.add("svg-gradient", function(direction) { + functionRegistry.add('svg-gradient', function(direction) { var stops, gradientDirectionSvg, - gradientType = "linear", + gradientType = 'linear', rectangleDimension = 'x="0" y="0" width="1" height="1"', renderEnv = {compress: false}, returner, @@ -18,9 +18,9 @@ module.exports = function(environment) { 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" }; + throw { type: 'Argument', + message: 'svg-gradient expects direction, start_color [start_position], [color position,]...,' + + ' end_color [end_position] or direction, color list' }; } if (arguments.length == 2) { @@ -35,27 +35,27 @@ module.exports = function(environment) { } switch (directionValue) { - case "to bottom": + case 'to bottom': gradientDirectionSvg = 'x1="0%" y1="0%" x2="0%" y2="100%"'; break; - case "to right": + case 'to right': gradientDirectionSvg = 'x1="0%" y1="0%" x2="100%" y2="0%"'; break; - case "to bottom right": + case 'to bottom right': gradientDirectionSvg = 'x1="0%" y1="0%" x2="100%" y2="100%"'; break; - case "to top right": + case 'to top right': gradientDirectionSvg = 'x1="0%" y1="100%" x2="100%" y2="0%"'; break; - case "ellipse": - case "ellipse at center": - gradientType = "radial"; + case 'ellipse': + case 'ellipse at center': + gradientType = 'radial'; gradientDirectionSvg = 'cx="50%" cy="50%" r="75%"'; rectangleDimension = 'x="-50" y="-50" width="101" height="101"'; break; default: - throw { type: "Argument", message: "svg-gradient direction must be 'to bottom', 'to right'," + - " 'to bottom right', 'to top right' or 'ellipse at center'" }; + throw { type: 'Argument', message: 'svg-gradient direction must be \'to bottom\', \'to right\',' + + ' \'to bottom right\', \'to top right\' or \'ellipse at center\'' }; } returner = '' + '' + @@ -73,7 +73,7 @@ module.exports = function(environment) { if (!(color instanceof Color) || (!((i === 0 || i + 1 === stops.length) && position === undefined) && !(position instanceof Dimension))) { throwArgumentDescriptor(); } - positionValue = position ? position.toCSS(renderEnv) : i === 0 ? "0%" : "100%"; + positionValue = position ? position.toCSS(renderEnv) : i === 0 ? '0%' : '100%'; alpha = color.alpha; returner += ''; } @@ -82,7 +82,7 @@ module.exports = function(environment) { returner = encodeURIComponent(returner); - returner = "data:image/svg+xml," + returner; - return new URL(new Quoted("'" + returner + "'", returner, false, this.index, this.currentFileInfo), this.index, this.currentFileInfo); + returner = 'data:image/svg+xml,' + returner; + return new URL(new Quoted('\'' + returner + '\'', returner, false, this.index, this.currentFileInfo), this.index, this.currentFileInfo); }); }; diff --git a/lib/less/functions/types.js b/lib/less/functions/types.js index f6bfae92..f1706d3b 100644 --- a/lib/less/functions/types.js +++ b/lib/less/functions/types.js @@ -1,23 +1,23 @@ -var Keyword = require("../tree/keyword"), - DetachedRuleset = require("../tree/detached-ruleset"), - Dimension = require("../tree/dimension"), - Color = require("../tree/color"), - Quoted = require("../tree/quoted"), - Anonymous = require("../tree/anonymous"), - URL = require("../tree/url"), - Operation = require("../tree/operation"), - functionRegistry = require("./function-registry"); +var Keyword = require('../tree/keyword'), + DetachedRuleset = require('../tree/detached-ruleset'), + Dimension = require('../tree/dimension'), + Color = require('../tree/color'), + Quoted = require('../tree/quoted'), + Anonymous = require('../tree/anonymous'), + URL = require('../tree/url'), + Operation = require('../tree/operation'), + functionRegistry = require('./function-registry'); var isa = function (n, Type) { return (n instanceof Type) ? Keyword.True : Keyword.False; }, isunit = function (n, unit) { if (unit === undefined) { - throw { type: "Argument", message: "missing the required second argument to isunit." }; + throw { type: 'Argument', message: 'missing the required second argument to isunit.' }; } - unit = typeof unit.value === "string" ? unit.value : unit; - if (typeof unit !== "string") { - throw { type: "Argument", message: "Second argument to isunit should be a unit or a string." }; + unit = typeof unit.value === 'string' ? unit.value : unit; + if (typeof unit !== 'string') { + throw { type: 'Argument', message: 'Second argument to isunit should be a unit or a string.' }; } return (n instanceof Dimension) && n.unit.is(unit) ? Keyword.True : Keyword.False; }, @@ -60,9 +60,9 @@ functionRegistry.addMultiple({ isunit: isunit, unit: function (val, unit) { if (!(val instanceof Dimension)) { - throw { type: "Argument", - message: "the first argument to unit must be a number" + - (val instanceof Operation ? ". Have you forgotten parenthesis?" : "") }; + throw { type: 'Argument', + message: 'the first argument to unit must be a number' + + (val instanceof Operation ? '. Have you forgotten parenthesis?' : '') }; } if (unit) { if (unit instanceof Keyword) { @@ -71,11 +71,11 @@ functionRegistry.addMultiple({ unit = unit.toCSS(); } } else { - unit = ""; + unit = ''; } return new Dimension(val.value, unit); }, - "get-unit": function (n) { + 'get-unit': function (n) { return new Anonymous(n.unit); }, extract: function(values, index) { @@ -85,5 +85,8 @@ functionRegistry.addMultiple({ }, length: function(values) { return new Dimension(getItemsFromNode(values).length); + }, + _SELF: function(n) { + return n; } }); diff --git a/lib/less/import-manager.js b/lib/less/import-manager.js index 4cff16f7..23b15ba4 100644 --- a/lib/less/import-manager.js +++ b/lib/less/import-manager.js @@ -1,4 +1,4 @@ -var contexts = require("./contexts"), +var contexts = require('./contexts'), Parser = require('./parser/parser'), LessError = require('./less-error'), utils = require('./utils'), @@ -50,7 +50,7 @@ module.exports = function(environment) { var importedEqualsRoot = fullPath === importManager.rootFilename; if (importOptions.optional && e) { callback(null, {rules:[]}, false, null); - logger.info("The file " + fullPath + " was skipped because it was not found and the import was marked optional."); + logger.info('The file ' + fullPath + ' was skipped because it was not found and the import was marked optional.'); } else { // Inline imports aren't cached here. @@ -74,7 +74,7 @@ module.exports = function(environment) { var fileManager = environment.getFileManager(path, currentFileInfo.currentDirectory, this.context, environment); if (!fileManager) { - fileParsedFunc({ message: "Could not find a file-manager for " + path }); + fileParsedFunc({ message: 'Could not find a file-manager for ' + path }); return; } @@ -94,7 +94,7 @@ module.exports = function(environment) { newFileInfo.currentDirectory = fileManager.getPath(resolvedFilename); if (newFileInfo.relativeUrls) { newFileInfo.rootpath = fileManager.join( - (importManager.context.rootpath || ""), + (importManager.context.rootpath || ''), fileManager.pathDiff(newFileInfo.currentDirectory, newFileInfo.entryPath)); if (!fileManager.isPathAbsolute(newFileInfo.rootpath) && fileManager.alwaysMakePathsAbsolute()) { @@ -142,7 +142,7 @@ module.exports = function(environment) { var promise, context = utils.clone(this.context); if (tryAppendExtension) { - context.ext = importOptions.isPlugin ? ".js" : ".less"; + context.ext = importOptions.isPlugin ? '.js' : '.less'; } if (importOptions.isPlugin) { diff --git a/lib/less/index.js b/lib/less/index.js index f60ca377..9a36c39f 100644 --- a/lib/less/index.js +++ b/lib/less/index.js @@ -2,23 +2,23 @@ module.exports = function(environment, fileManagers) { var SourceMapOutput, SourceMapBuilder, ParseTree, ImportManager, Environment; var initial = { - version: [3, 0, 4], + version: [3, 5, 3], 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 = 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'), functions: require('./functions')(environment), - contexts: require("./contexts"), + contexts: require('./contexts'), SourceMapOutput: (SourceMapOutput = require('./source-map-output')(environment)), SourceMapBuilder: (SourceMapBuilder = require('./source-map-builder')(SourceMapOutput, environment)), ParseTree: (ParseTree = require('./parse-tree')(SourceMapBuilder)), ImportManager: (ImportManager = require('./import-manager')(environment)), - render: require("./render")(environment, ParseTree, ImportManager), - parse: require("./parse")(environment, ParseTree, ImportManager), + render: require('./render')(environment, ParseTree, ImportManager), + parse: require('./parse')(environment, ParseTree, ImportManager), LessError: require('./less-error'), transformTree: require('./transform-tree'), utils: require('./utils'), @@ -39,7 +39,7 @@ module.exports = function(environment, fileManagers) { for (var n in initial.tree) { /* eslint guard-for-in: 0 */ t = initial.tree[n]; - if (typeof t === "function") { + if (typeof t === 'function') { api[n.toLowerCase()] = ctor(t); } else { diff --git a/lib/less/logger.js b/lib/less/logger.js index fbeb0238..621e57e2 100644 --- a/lib/less/logger.js +++ b/lib/less/logger.js @@ -1,15 +1,15 @@ module.exports = { error: function(msg) { - this._fireEvent("error", msg); + this._fireEvent('error', msg); }, warn: function(msg) { - this._fireEvent("warn", msg); + this._fireEvent('warn', msg); }, info: function(msg) { - this._fireEvent("info", msg); + this._fireEvent('info', msg); }, debug: function(msg) { - this._fireEvent("debug", msg); + this._fireEvent('debug', msg); }, addListener: function(listener) { this._listeners.push(listener); diff --git a/lib/less/parse-tree.js b/lib/less/parse-tree.js index de7800c6..d601af98 100644 --- a/lib/less/parse-tree.js +++ b/lib/less/parse-tree.js @@ -1,6 +1,6 @@ var LessError = require('./less-error'), - transformTree = require("./transform-tree"), - logger = require("./logger"); + transformTree = require('./transform-tree'), + logger = require('./logger'); module.exports = function(SourceMapBuilder) { var ParseTree = function(root, imports) { @@ -19,7 +19,7 @@ module.exports = function(SourceMapBuilder) { try { var compress = Boolean(options.compress); if (compress) { - logger.warn("The compress option has been deprecated. We recommend you use a dedicated css minifier, for instance see less-plugin-clean-css."); + logger.warn('The compress option has been deprecated. We recommend you use a dedicated css minifier, for instance see less-plugin-clean-css.'); } var toCSSOptions = { diff --git a/lib/less/parse.js b/lib/less/parse.js index e5baf005..d1c4fad5 100644 --- a/lib/less/parse.js +++ b/lib/less/parse.js @@ -1,5 +1,5 @@ var PromiseConstructor, - contexts = require("./contexts"), + contexts = require('./contexts'), Parser = require('./parser/parser'), PluginManager = require('./plugin-manager'), LessError = require('./less-error'), @@ -42,19 +42,19 @@ module.exports = function(environment, ParseTree, ImportManager) { if (options.rootFileInfo) { rootFileInfo = options.rootFileInfo; } else { - var filename = options.filename || "input"; - var entryPath = filename.replace(/[^\/\\]*$/, ""); + var filename = options.filename || 'input'; + var entryPath = filename.replace(/[^\/\\]*$/, ''); rootFileInfo = { filename: filename, relativeUrls: context.relativeUrls, - rootpath: context.rootpath || "", + rootpath: context.rootpath || '', currentDirectory: entryPath, entryPath: entryPath, rootFilename: filename }; // add in a missing trailing slash - if (rootFileInfo.rootpath && rootFileInfo.rootpath.slice(-1) !== "/") { - rootFileInfo.rootpath += "/"; + if (rootFileInfo.rootpath && rootFileInfo.rootpath.slice(-1) !== '/') { + rootFileInfo.rootpath += '/'; } } diff --git a/lib/less/parser/chunker.js b/lib/less/parser/chunker.js index a5ccaa96..6a674758 100644 --- a/lib/less/parser/chunker.js +++ b/lib/less/parser/chunker.js @@ -28,7 +28,7 @@ module.exports = function (input, fail) { continue; case 41: // ) if (--parenLevel < 0) { - return fail("missing opening `(`", chunkerCurrentIndex); + return fail('missing opening `(`', chunkerCurrentIndex); } continue; case 59: // ; @@ -40,13 +40,13 @@ module.exports = function (input, fail) { continue; case 125: // } if (--level < 0) { - return fail("missing opening `{`", chunkerCurrentIndex); + return fail('missing opening `{`', chunkerCurrentIndex); } if (!level && !parenLevel) { emitChunk(); } continue; case 92: // \ if (chunkerCurrentIndex < len - 1) { chunkerCurrentIndex++; continue; } - return fail("unescaped `\\`", chunkerCurrentIndex); + return fail('unescaped `\\`', chunkerCurrentIndex); case 34: case 39: case 96: // ", ' and ` @@ -58,13 +58,13 @@ module.exports = function (input, fail) { if (cc2 == cc) { matched = 1; break; } if (cc2 == 92) { // \ if (chunkerCurrentIndex == len - 1) { - return fail("unescaped `\\`", chunkerCurrentIndex); + return fail('unescaped `\\`', chunkerCurrentIndex); } chunkerCurrentIndex++; } } if (matched) { continue; } - return fail("unmatched `" + String.fromCharCode(cc) + "`", currentChunkStartIndex); + return fail('unmatched `' + String.fromCharCode(cc) + '`', currentChunkStartIndex); case 47: // /, check for comment if (parenLevel || (chunkerCurrentIndex == len - 1)) { continue; } cc2 = input.charCodeAt(chunkerCurrentIndex + 1); @@ -84,14 +84,14 @@ module.exports = function (input, fail) { if (input.charCodeAt(chunkerCurrentIndex + 1) == 47) { break; } } if (chunkerCurrentIndex == len - 1) { - return fail("missing closing `*/`", currentChunkStartIndex); + return fail('missing closing `*/`', currentChunkStartIndex); } chunkerCurrentIndex++; } continue; case 42: // *, check for unmatched */ if ((chunkerCurrentIndex < len - 1) && (input.charCodeAt(chunkerCurrentIndex + 1) == 47)) { - return fail("unmatched `/*`", chunkerCurrentIndex); + return fail('unmatched `/*`', chunkerCurrentIndex); } continue; } @@ -99,12 +99,12 @@ module.exports = function (input, fail) { if (level !== 0) { if ((lastMultiComment > lastOpening) && (lastMultiCommentEndBrace > lastMultiComment)) { - return fail("missing closing `}` or `*/`", lastOpening); + return fail('missing closing `}` or `*/`', lastOpening); } else { - return fail("missing closing `}`", lastOpening); + return fail('missing closing `}`', lastOpening); } } else if (parenLevel !== 0) { - return fail("missing closing `)`", lastOpeningParen); + return fail('missing closing `)`', lastOpeningParen); } emitChunk(true); diff --git a/lib/less/parser/parser-input.js b/lib/less/parser/parser-input.js index bf99ef78..436fd044 100644 --- a/lib/less/parser/parser-input.js +++ b/lib/less/parser/parser-input.js @@ -35,7 +35,7 @@ module.exports = function() { nextChar = inp.charAt(parserInput.i + 1); if (nextChar === '/') { comment = {index: parserInput.i, isLineComment: true}; - var nextNewLine = inp.indexOf("\n", parserInput.i + 2); + var nextNewLine = inp.indexOf('\n', parserInput.i + 2); if (nextNewLine < 0) { nextNewLine = endIndex; } @@ -44,7 +44,7 @@ module.exports = function() { parserInput.commentStore.push(comment); continue; } else if (nextChar === '*') { - var nextStarSlash = inp.indexOf("*/", parserInput.i + 2); + var nextStarSlash = inp.indexOf('*/', parserInput.i + 2); if (nextStarSlash >= 0) { comment = { index: parserInput.i, @@ -116,7 +116,7 @@ module.exports = function() { } skipWhitespace(m[0].length); - if (typeof m === "string") { + if (typeof m === 'string') { return m; } @@ -149,7 +149,7 @@ module.exports = function() { var pos = loc || parserInput.i, startChar = input.charAt(pos); - if (startChar !== "'" && startChar !== '"') { + if (startChar !== '\'' && startChar !== '"') { return; } var length = input.length, @@ -158,11 +158,11 @@ module.exports = function() { for (var i = 1; i + currentPosition < length; i++) { var nextChar = input.charAt(i + currentPosition); switch (nextChar) { - case "\\": + case '\\': i++; continue; - case "\r": - case "\n": + case '\r': + case '\n': break; case startChar: var str = input.substr(currentPosition, i + 1); @@ -211,17 +211,17 @@ module.exports = function() { returnVal = input.substr(lastPos, i - lastPos); if (returnVal) { parseGroups.push(returnVal); - returnVal = parseGroups; } else { - returnVal = [' ']; + parseGroups.push(' '); } + returnVal = parseGroups; skipWhitespace(i - startPos); loop = false } else { if (inComment) { - if (nextChar === "*" && - input.charAt(i + 1) === "/") { + if (nextChar === '*' && + input.charAt(i + 1) === '/') { i++; blockDepth--; inComment = false; @@ -236,15 +236,14 @@ module.exports = function() { parseGroups.push(input.substr(lastPos, i - lastPos + 1)); lastPos = i + 1; break; - case "/": - if (input.charAt(i + 1) === "*") { + case '/': + if (input.charAt(i + 1) === '*') { i++; - console.log(input.substr(lastPos, i - lastPos)); inComment = true; blockDepth++; } break; - case "'": + case '\'': case '"': quote = parserInput.$quoted(i); if (quote) { @@ -258,21 +257,21 @@ module.exports = function() { loop = false; } break; - case "{": - blockStack.push("}"); + case '{': + blockStack.push('}'); blockDepth++; break; - case "(": - blockStack.push(")"); + case '(': + blockStack.push(')'); blockDepth++; break; - case "[": - blockStack.push("]"); + case '[': + blockStack.push(']'); blockDepth++; break; - case "}": - case ")": - case "]": + case '}': + case ')': + case ']': var expected = blockStack.pop(); if (nextChar === expected) { blockDepth--; @@ -324,6 +323,10 @@ module.exports = function() { return input.charAt(parserInput.i); }; + parserInput.prevChar = function() { + return input.charAt(parserInput.i - 1); + }; + parserInput.getInput = function() { return input; }; diff --git a/lib/less/parser/parser.js b/lib/less/parser/parser.js index 811a65b9..1e9820e2 100644 --- a/lib/less/parser/parser.js +++ b/lib/less/parser/parser.js @@ -1,8 +1,8 @@ var LessError = require('../less-error'), - tree = require("../tree"), - visitors = require("../visitors"), - getParserInput = require("./parser-input"), - utils = require("../utils"), + tree = require('../tree'), + visitors = require('../visitors'), + getParserInput = require('./parser-input'), + utils = require('../utils'), functionRegistry = require('../functions/function-registry'); // @@ -60,8 +60,8 @@ var Parser = function Parser(context, imports, fileInfo) { if (result) { return result; } - error(msg || (typeof arg === 'string' ? "expected '" + arg + "' got '" + parserInput.currentChar() + "'" - : "unexpected token")); + error(msg || (typeof arg === 'string' ? 'expected \'' + arg + '\' got \'' + parserInput.currentChar() + '\'' + : 'unexpected token')); } // Specialization of expect() @@ -69,7 +69,7 @@ var Parser = function Parser(context, imports, fileInfo) { if (parserInput.$char(arg)) { return arg; } - error(msg || "expected '" + arg + "' got '" + parserInput.currentChar() + "'"); + error(msg || 'expected \'' + arg + '\' got \'' + parserInput.currentChar() + '\''); } function getDebugInfo(index) { @@ -143,7 +143,7 @@ var Parser = function Parser(context, imports, fileInfo) { // @param [additionalData] An optional map which can contains vars - a map (key, value) of variables to apply // parse: function (str, callback, additionalData) { - var root, error = null, globalVars, modifyVars, ignored, preText = ""; + var root, error = null, globalVars, modifyVars, ignored, preText = ''; globalVars = (additionalData && additionalData.globalVars) ? Parser.serializeVars(additionalData.globalVars) + '\n' : ''; modifyVars = (additionalData && additionalData.modifyVars) ? '\n' + Parser.serializeVars(additionalData.modifyVars) : ''; @@ -156,7 +156,7 @@ var Parser = function Parser(context, imports, fileInfo) { } if (globalVars || (additionalData && additionalData.banner)) { - preText = ((additionalData && additionalData.banner) ? additionalData.banner : "") + globalVars; + preText = ((additionalData && additionalData.banner) ? additionalData.banner : '') + globalVars; ignored = imports.contentsIgnoredChars; ignored[fileInfo.filename] = ignored[fileInfo.filename] || 0; ignored[fileInfo.filename] += preText.length; @@ -206,18 +206,18 @@ var Parser = function Parser(context, imports, fileInfo) { var message = endInfo.furthestPossibleErrorMessage; if (!message) { - message = "Unrecognised input"; + message = 'Unrecognised input'; if (endInfo.furthestChar === '}') { - message += ". Possibly missing opening '{'"; + message += '. Possibly missing opening \'{\''; } else if (endInfo.furthestChar === ')') { - message += ". Possibly missing opening '('"; + message += '. Possibly missing opening \'(\''; } else if (endInfo.furthestReachedEnd) { - message += ". Possibly missing something"; + message += '. Possibly missing something'; } } error = new LessError({ - type: "Parse", + type: 'Parse', message: message, index: endInfo.furthest, filename: fileInfo.filename @@ -316,12 +316,12 @@ var Parser = function Parser(context, imports, fileInfo) { } node = mixin.definition() || this.declaration() || this.ruleset() || - mixin.call() || this.variableCall() || this.entities.call() || this.atrule(); + mixin.call(false, false) || this.variableCall() || this.entities.call() || this.atrule(); if (node) { root.push(node); } else { var foundSemiColon = false; - while (parserInput.$char(";")) { + while (parserInput.$char(';')) { foundSemiColon = true; } if (!foundSemiColon) { @@ -346,18 +346,25 @@ var Parser = function Parser(context, imports, fileInfo) { // Entities are tokens which can be found inside an Expression // entities: { + mixinLookup: function() { + return parsers.mixin.call(true, true); + }, // // A string, which supports escaping " and ' // // "milky way" 'he\'s the one!' // - quoted: function () { + quoted: function (forceEscaped) { var str, index = parserInput.i, isEscaped = false; parserInput.save(); - if (parserInput.$char("~")) { + if (parserInput.$char('~')) { isEscaped = true; + } else if (forceEscaped) { + parserInput.restore(); + return; } + str = parserInput.$quoted(); if (!str) { parserInput.restore(); @@ -374,7 +381,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(/^\[?(?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+\]?/); if (k) { return tree.Color.fromKeyword(k) || new(tree.Keyword)(k); } @@ -416,7 +423,7 @@ var Parser = function Parser(context, imports, fileInfo) { args = this.arguments(args); if (!parserInput.$char(')')) { - parserInput.restore("Could not parse call arguments or missing ')'"); + parserInput.restore('Could not parse call arguments or missing \')\''); return; } @@ -542,13 +549,13 @@ var Parser = function Parser(context, imports, fileInfo) { parserInput.autoCommentAbsorb = false; - if (!parserInput.$str("url(")) { + if (!parserInput.$str('url(')) { parserInput.autoCommentAbsorb = true; return; } value = this.quoted() || this.variable() || this.property() || - parserInput.$re(/^(?:(?:\\[\(\)'"])|[^\(\)'"])+/) || ""; + parserInput.$re(/^(?:(?:\\[\(\)'"])|[^\(\)'"])+/) || ''; parserInput.autoCommentAbsorb = true; @@ -569,11 +576,23 @@ var Parser = function Parser(context, imports, fileInfo) { // see `parsers.variable`. // variable: function () { - var name, index = parserInput.i; + var ch, name, index = parserInput.i; + parserInput.save(); if (parserInput.currentChar() === '@' && (name = parserInput.$re(/^@@?[\w-]+/))) { + ch = parserInput.currentChar(); + if (ch === '(' || ch === '[' && !parserInput.prevChar().match(/^\s/)) { + // this may be a VariableCall lookup + var result = parsers.variableCall(name); + if (result) { + parserInput.forget(); + return result; + } + } + parserInput.forget(); return new(tree.Variable)(name, index, fileInfo); } + parserInput.restore(); }, // A variable entity using the protective {} e.g. @{var} @@ -581,7 +600,7 @@ var Parser = function Parser(context, imports, fileInfo) { var curly, index = parserInput.i; if (parserInput.currentChar() === '@' && (curly = parserInput.$re(/^@\{([\w-]+)\}/))) { - return new(tree.Variable)("@" + curly[1], index, fileInfo); + return new(tree.Variable)('@' + curly[1], index, fileInfo); } }, // @@ -602,7 +621,7 @@ var Parser = function Parser(context, imports, fileInfo) { var curly, index = parserInput.i; if (parserInput.currentChar() === '$' && (curly = parserInput.$re(/^\$\{([\w-]+)\}/))) { - return new(tree.Property)("$" + curly[1], index, fileInfo); + return new(tree.Property)('$' + curly[1], index, fileInfo); } }, // @@ -621,7 +640,7 @@ var Parser = function Parser(context, imports, fileInfo) { var colorCandidateString = rgb.input.match(/^#([\w]+).*/); colorCandidateString = colorCandidateString[1]; if (!colorCandidateString.match(/^[A-Fa-f0-9]+$/)) { // verify if candidate consists only of allowed HEX characters - error("Invalid HEX color code"); + error('Invalid HEX color code'); } return new(tree.Color)(rgb[1], undefined, '#' + colorCandidateString); } @@ -685,8 +704,8 @@ var Parser = function Parser(context, imports, fileInfo) { parserInput.save(); - var escape = parserInput.$char("~"); - var jsQuote = parserInput.$char("`"); + var escape = parserInput.$char('~'); + var jsQuote = parserInput.$char('`'); if (!jsQuote) { parserInput.restore(); @@ -698,7 +717,7 @@ var Parser = function Parser(context, imports, fileInfo) { parserInput.forget(); return new(tree.JavaScript)(js.substr(0, js.length - 1), Boolean(escape), index, fileInfo); } - parserInput.restore("invalid javascript definition"); + parserInput.restore('invalid javascript definition'); } }, @@ -714,18 +733,49 @@ var Parser = function Parser(context, imports, fileInfo) { }, // - // Call a variable value + // Call a variable value to retrieve a detached ruleset + // or a value from a detached ruleset's rules. // - // @fink() + // @fink(); + // @fink; + // color: @fink[@color]; // - variableCall: function () { - var name; + variableCall: function (parsedName) { + var lookups, important, i = parserInput.i, + inValue = !!parsedName, name = parsedName; - if (parserInput.currentChar() === '@' - && (name = parserInput.$re(/^(@[\w-]+)\(\s*\)/)) - && parsers.end()) { - return new tree.VariableCall(name[1]); + parserInput.save(); + + if (name || (parserInput.currentChar() === '@' + && (name = parserInput.$re(/^(@[\w-]+)(\(\s*\))?/)))) { + + lookups = this.mixin.ruleLookups(); + + if (!lookups && ((inValue && parserInput.$str('()') !== '()') || (name[2] !== '()'))) { + parserInput.restore('Missing \'[...]\' lookup in variable call'); + return; + } + + if (!inValue) { + name = name[1]; + } + + if (lookups && parsers.important()) { + important = true; + } + + var call = new tree.VariableCall(name, i, fileInfo); + if (!inValue && parsers.end()) { + parserInput.forget(); + return call; + } + else { + parserInput.forget(); + return new tree.NamespaceValue(call, lookups, important, i, fileInfo); + } } + + parserInput.restore(); }, // @@ -734,7 +784,7 @@ var Parser = function Parser(context, imports, fileInfo) { extend: function(isRule) { var elements, e, index = parserInput.i, option, extendList, extend; - if (!parserInput.$str(isRule ? "&:extend(" : ":extend(")) { + if (!parserInput.$str(isRule ? '&:extend(' : ':extend(')) { return; } @@ -755,7 +805,7 @@ var Parser = function Parser(context, imports, fileInfo) { option = option && option[1]; if (!elements) { - error("Missing target selector for :extend()."); + error('Missing target selector for :extend().'); } extend = new(tree.Extend)(new(tree.Selector)(elements), option, index, fileInfo); if (extendList) { @@ -763,7 +813,7 @@ var Parser = function Parser(context, imports, fileInfo) { } else { extendList = [ extend ]; } - } while (parserInput.$char(",")); + } while (parserInput.$char(',')); expect(/^\)/); @@ -789,28 +839,82 @@ var Parser = function Parser(context, imports, fileInfo) { // A Mixin call, with an optional argument list // // #mixins > .square(#fff); + // #mixins.square(#fff); // .rounded(4px, black); // .button; // + // We can lookup / return a value using the lookup syntax: + // + // color: #mixin.square(#fff)[@color]; + // // The `while` loop is there because mixins can be // namespaced, but we only support the child and descendant // selector for now. // - call: function () { - var s = parserInput.currentChar(), important = false, index = parserInput.i, elemIndex, - elements, elem, e, c, args; + call: function (inValue, getLookup) { + var s = parserInput.currentChar(), important = false, lookups, + index = parserInput.i, elements, args, hasParens; if (s !== '.' && s !== '#') { return; } parserInput.save(); // stop us absorbing part of an invalid selector + elements = this.elements(); + + if (elements) { + if (parserInput.$char('(')) { + args = this.args(true).args; + expectChar(')'); + hasParens = true; + } + + if (getLookup !== false) { + lookups = this.ruleLookups(); + } + if (getLookup === true && !lookups) { + parserInput.restore(); + return; + } + + if (inValue && !lookups && !hasParens) { + // This isn't a valid in-value mixin call + parserInput.restore(); + return; + } + + if (!inValue && parsers.important()) { + important = true; + } + + if (inValue || parsers.end()) { + parserInput.forget(); + var mixin = new(tree.mixin.Call)(elements, args, index, fileInfo, !lookups && important); + if (lookups) { + return new tree.NamespaceValue(mixin, lookups, important); + } + else { + return mixin; + } + } + } + + parserInput.restore(); + }, + /** + * Matching elements for mixins + * (Start with . or # and can have > ) + */ + elements: function() { + var elements, e, c, elem, elemIndex, + re = /^[#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/; while (true) { elemIndex = parserInput.i; - e = parserInput.$re(/^[#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/); + e = parserInput.$re(re); + if (!e) { break; } - elem = new(tree.Element)(c, e, elemIndex, fileInfo); + elem = new(tree.Element)(c, e, false, elemIndex, fileInfo); if (elements) { elements.push(elem); } else { @@ -818,24 +922,7 @@ var Parser = function Parser(context, imports, fileInfo) { } c = parserInput.$char('>'); } - - if (elements) { - if (parserInput.$char('(')) { - args = this.args(true).args; - expectChar(')'); - } - - if (parsers.important()) { - important = true; - } - - if (parsers.end()) { - parserInput.forget(); - return new(tree.mixin.Call)(elements, args, index, fileInfo, important); - } - } - - parserInput.restore(); + return elements; }, args: function (isCall) { var entities = parsers.entities, @@ -851,16 +938,16 @@ var Parser = function Parser(context, imports, fileInfo) { arg = parsers.detachedRuleset() || parsers.expression(); } else { parserInput.commentStore.length = 0; - if (parserInput.$str("...")) { + if (parserInput.$str('...')) { returner.variadic = true; - if (parserInput.$char(";") && !isSemiColonSeparated) { + if (parserInput.$char(';') && !isSemiColonSeparated) { isSemiColonSeparated = true; } (isSemiColonSeparated ? argsSemiColon : argsComma) .push({ variadic: true }); break; } - arg = entities.variable() || entities.property() || entities.literal() || entities.keyword(); + arg = entities.variable() || entities.property() || entities.literal() || entities.keyword() || this.call(true); } if (!arg) { @@ -887,7 +974,7 @@ var Parser = function Parser(context, imports, fileInfo) { if (parserInput.$char(':')) { if (expressions.length > 0) { if (isSemiColonSeparated) { - error("Cannot mix ; and , as delimiter types"); + error('Cannot mix ; and , as delimiter types'); } expressionContainsNamed = true; } @@ -896,7 +983,7 @@ var Parser = function Parser(context, imports, fileInfo) { if (!value) { if (isCall) { - error("could not understand value for named argument"); + error('could not understand value for named argument'); } else { parserInput.restore(); returner.args = []; @@ -904,10 +991,10 @@ var Parser = function Parser(context, imports, fileInfo) { } } nameLoop = (name = val.name); - } else if (parserInput.$str("...")) { + } else if (parserInput.$str('...')) { if (!isCall) { returner.variadic = true; - if (parserInput.$char(";") && !isSemiColonSeparated) { + if (parserInput.$char(';') && !isSemiColonSeparated) { isSemiColonSeparated = true; } (isSemiColonSeparated ? argsSemiColon : argsComma) @@ -935,7 +1022,7 @@ var Parser = function Parser(context, imports, fileInfo) { if (parserInput.$char(';') || isSemiColonSeparated) { if (expressionContainsNamed) { - error("Cannot mix ; and , as delimiter types"); + error('Cannot mix ; and , as delimiter types'); } isSemiColonSeparated = true; @@ -997,13 +1084,13 @@ var Parser = function Parser(context, imports, fileInfo) { // .mixincall(@a: {rule: set;}); // so we have to be nice and restore if (!parserInput.$char(')')) { - parserInput.restore("Missing closing ')'"); + parserInput.restore('Missing closing \')\''); return; } parserInput.commentStore.length = 0; - if (parserInput.$str("when")) { // Guard + if (parserInput.$str('when')) { // Guard cond = expect(parsers.conditions, 'expected condition'); } @@ -1018,9 +1105,54 @@ var Parser = function Parser(context, imports, fileInfo) { } else { parserInput.forget(); } + }, + + ruleLookups: function() { + var rule, args, lookups = []; + + if (parserInput.currentChar() !== '[') { + return; + } + + while (true) { + parserInput.save(); + args = null; + rule = this.lookupValue(); + if (!rule && rule !== '') { + parserInput.restore(); + break; + } + lookups.push(rule); + parserInput.forget(); + } + if (lookups.length > 0) { + return lookups; + } + }, + + lookupValue: function() { + parserInput.save(); + + if (!parserInput.$char('[')) { + parserInput.restore(); + return; + } + + var name = parserInput.$re(/^(?:[@$]{0,2})[_a-zA-Z0-9-]*/); + + if (!parserInput.$char(']')) { + parserInput.restore(); + return; + } + + if (name || name === '') { + parserInput.forget(); + return name; + } + + parserInput.restore(); } }, - // // Entities are the smallest recognized token, // and can be found inside a rule's value. @@ -1029,7 +1161,8 @@ var Parser = function Parser(context, imports, fileInfo) { var entities = this.entities; return this.comment() || entities.literal() || entities.variable() || entities.url() || - entities.property() || entities.call() || entities.keyword() || entities.javascript(); + entities.property() || entities.call() || entities.keyword() || this.mixin.call(true) || + entities.javascript(); }, // @@ -1053,7 +1186,7 @@ var Parser = function Parser(context, imports, fileInfo) { if (!parserInput.$re(/^opacity=/i)) { return; } value = parserInput.$re(/^\d+/); if (!value) { - value = expect(parsers.entities.variable, "Could not parse alpha"); + value = expect(parsers.entities.variable, 'Could not parse alpha'); value = '@{' + value.name.slice(1) + '}'; } expectChar(')'); @@ -1090,14 +1223,14 @@ var Parser = function Parser(context, imports, fileInfo) { e = new(tree.Paren)(v); parserInput.forget(); } else { - parserInput.restore("Missing closing ')'"); + parserInput.restore('Missing closing \')\''); } } else { parserInput.forget(); } } - if (e) { return new(tree.Element)(c, e, index, fileInfo); } + if (e) { return new(tree.Element)(c, e, e instanceof tree.Variable, index, fileInfo); } }, // @@ -1131,7 +1264,7 @@ var Parser = function Parser(context, imports, fileInfo) { while (parserInput.isWhitespace()) { parserInput.i++; } return new(tree.Combinator)(c); } else if (parserInput.isWhitespace(-1)) { - return new(tree.Combinator)(" "); + return new(tree.Combinator)(' '); } else { return new(tree.Combinator)(null); } @@ -1148,11 +1281,11 @@ 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())) { + while ((isLess && (extendList = this.extend())) || (isLess && (when = parserInput.$str('when'))) || (e = this.element())) { if (when) { condition = expect(this.conditions, 'expected condition'); } else if (condition) { - error("CSS guard can only be used at the end of selector"); + error('CSS guard can only be used at the end of selector'); } else if (extendList) { if (allExtends) { allExtends = allExtends.concat(extendList); @@ -1160,7 +1293,7 @@ var Parser = function Parser(context, imports, fileInfo) { allExtends = extendList; } } else { - if (allExtends) { error("Extend can only be used at the end of selector"); } + if (allExtends) { error('Extend can only be used at the end of selector'); } c = parserInput.currentChar(); if (elements) { elements.push(e); @@ -1175,7 +1308,31 @@ var Parser = function Parser(context, imports, fileInfo) { } if (elements) { return new(tree.Selector)(elements, allExtends, condition, index, fileInfo); } - if (allExtends) { error("Extend must be used to extend a selector, it cannot be used on its own"); } + if (allExtends) { error('Extend must be used to extend a selector, it cannot be used on its own'); } + }, + selectors: function () { + var s, selectors; + while (true) { + s = this.selector(); + if (!s) { + break; + } + if (selectors) { + selectors.push(s); + } else { + selectors = [ s ]; + } + parserInput.commentStore.length = 0; + if (s.condition && selectors.length > 1) { + error("Guards are only currently allowed on a single selector."); + } + if (!parserInput.$char(',')) { break; } + if (s.condition) { + error("Guards are only currently allowed on a single selector."); + } + parserInput.commentStore.length = 0; + } + return selectors; }, attribute: function () { if (!parserInput.$char('[')) { return; } @@ -1228,7 +1385,7 @@ var Parser = function Parser(context, imports, fileInfo) { // div, .class, body > p {...} // ruleset: function () { - var selectors, s, rules, debugInfo; + var selectors, rules, debugInfo; parserInput.save(); @@ -1236,26 +1393,7 @@ var Parser = function Parser(context, imports, fileInfo) { debugInfo = getDebugInfo(parserInput.i); } - while (true) { - s = this.selector(); - if (!s) { - break; - } - if (selectors) { - selectors.push(s); - } else { - selectors = [ s ]; - } - parserInput.commentStore.length = 0; - if (s.condition && selectors.length > 1) { - error("Guards are only currently allowed on a single selector."); - } - if (!parserInput.$char(',')) { break; } - if (s.condition) { - error("Guards are only currently allowed on a single selector."); - } - parserInput.commentStore.length = 0; - } + selectors = this.selectors(); if (selectors && (rules = this.block())) { parserInput.forget(); @@ -1269,7 +1407,7 @@ var Parser = function Parser(context, imports, fileInfo) { } }, declaration: function () { - var name, value, index = parserInput.i, + var name, value, index = parserInput.i, hasDR, c = parserInput.currentChar(), important, merge, isVariable; if (c === '.' || c === '#' || c === '&' || c === ':') { return; } @@ -1278,10 +1416,13 @@ var Parser = function Parser(context, imports, fileInfo) { name = this.variable() || this.ruleProperty(); if (name) { - isVariable = typeof name === "string"; + isVariable = typeof name === 'string'; if (isVariable) { value = this.detachedRuleset(); + if (value) { + hasDR = true; + } } parserInput.commentStore.length = 0; @@ -1293,7 +1434,7 @@ var Parser = function Parser(context, imports, fileInfo) { // Custom property values get permissive parsing if (name[0].value && name[0].value.slice(0, 2) === '--') { - value = this.permissiveValue(';'); + value = this.permissiveValue(); } // Try to store values as anonymous // If we need the value later we'll re-parse it in ruleset.parseValue @@ -1310,15 +1451,15 @@ var Parser = function Parser(context, imports, fileInfo) { value = this.value(); } - important = this.important(); - - // As a last resort, let a variable try to be parsed as a permissive value - if (!value && isVariable) { - value = this.permissiveValue(';'); + if (value) { + important = this.important(); + } else if (isVariable) { + // As a last resort, try permissiveValue + value = this.permissiveValue(); } } - if (value && this.end()) { + if (value && (this.end() || hasDR)) { parserInput.forget(); return new (tree.Declaration)(name, value, important, merge, index, fileInfo); } @@ -1331,48 +1472,98 @@ var Parser = function Parser(context, imports, fileInfo) { }, anonymousValue: function () { var index = parserInput.i; - var match = parserInput.$re(/^([^@\$+\/'"*`(;{}-]*);/); + var match = parserInput.$re(/^([^.#@\$+\/'"*`(;{}-]*);/); if (match) { return new(tree.Anonymous)(match[1], index); } }, /** - * Used for custom properties and custom at-rules + * Used for custom properties, at-rules, and variables (as fallback) * Parses almost anything inside of {} [] () "" blocks * until it reaches outer-most tokens. + * + * First, it will try to parse comments and entities to reach + * the end. This is mostly like the Expression parser except no + * math is allowed. */ permissiveValue: function (untilTokens) { - var i, index = parserInput.i, - value = parserInput.$parseUntil(untilTokens); + var i, e, done, value, + tok = untilTokens || ';', + index = parserInput.i, result = []; + + function testCurrentChar() { + var char = parserInput.currentChar(); + if (typeof tok === 'string') { + return char === tok; + } else { + return tok.test(char); + } + } + if (testCurrentChar()) { + return; + } + value = []; + do { + e = this.comment(); + if (e) { + value.push(e); + continue; + } + e = this.entity(); + if (e) { + value.push(e); + } + } while (e); + + done = testCurrentChar(); + + if (value.length > 0) { + value = new(tree.Expression)(value); + if (done) { + return value; + } + else { + result.push(value); + } + // Preserve space before $parseUntil as it will not + if (parserInput.prevChar() === ' ') { + result.push(new tree.Anonymous(' ', index)); + } + } + parserInput.save(); + + value = parserInput.$parseUntil(tok); if (value) { if (typeof value === 'string') { - error("Expected '" + value + "'", "Parse"); + error('Expected \'' + value + '\'', 'Parse'); } if (value.length === 1 && value[0] === ' ') { + parserInput.forget(); return new tree.Anonymous('', index); } - var item, args = []; + var item; for (i = 0; i < value.length; i++) { item = value[i]; if (Array.isArray(item)) { // Treat actual quotes as normal quoted values - args.push(new tree.Quoted(item[0], item[1], true, index, fileInfo)); + result.push(new tree.Quoted(item[0], item[1], true, index, fileInfo)); } else { if (i === value.length - 1) { item = item.trim(); } // Treat like quoted values, but replace vars like unquoted expressions - var quote = new tree.Quoted("'", item, true, index, fileInfo); + var quote = new tree.Quoted('\'', item, true, index, fileInfo); quote.variableRegex = /@([\w-]+)/g; quote.propRegex = /\$([\w-]+)/g; - quote.reparse = true; - args.push(quote); + result.push(quote); } } - return new tree.Expression(args, true); + parserInput.forget(); + return new tree.Expression(result, true); } + parserInput.restore(); }, // @@ -1385,7 +1576,7 @@ var Parser = function Parser(context, imports, fileInfo) { // file-system operation. The function used for importing is // stored in `import`, which we pass to the Import constructor. // - "import": function () { + 'import': function () { var path, features, index = parserInput.i; var dir = parserInput.$re(/^@import?\s+/); @@ -1398,14 +1589,14 @@ var Parser = function Parser(context, imports, fileInfo) { if (!parserInput.$char(';')) { parserInput.i = index; - error("missing semi-colon or unrecognised media features on import"); + error('missing semi-colon or unrecognised media features on import'); } features = features && new(tree.Value)(features); return new(tree.Import)(path, features, options, index, fileInfo); } else { parserInput.i = index; - error("malformed import statement"); + error('malformed import statement'); } } }, @@ -1421,12 +1612,12 @@ var Parser = function Parser(context, imports, fileInfo) { optionName = o; value = true; switch (optionName) { - case "css": - optionName = "less"; + case 'css': + optionName = 'less'; value = false; break; - case "once": - optionName = "multiple"; + case 'once': + optionName = 'multiple'; value = false; break; } @@ -1449,7 +1640,7 @@ var Parser = function Parser(context, imports, fileInfo) { var entities = this.entities, nodes = [], e, p; parserInput.save(); do { - e = entities.keyword() || entities.variable(); + e = entities.keyword() || entities.variable() || entities.mixinLookup(); if (e) { nodes.push(e); } else if (parserInput.$char('(')) { @@ -1461,10 +1652,10 @@ var Parser = function Parser(context, imports, fileInfo) { } else if (e) { nodes.push(new(tree.Paren)(e)); } else { - error("badly formed media feature definition"); + error('badly formed media feature definition'); } } else { - error("Missing closing ')'", "Parse"); + error('Missing closing \')\'', 'Parse'); } } } while (e); @@ -1483,7 +1674,7 @@ var Parser = function Parser(context, imports, fileInfo) { features.push(e); if (!parserInput.$char(',')) { break; } } else { - e = entities.variable(); + e = entities.variable() || entities.mixinLookup(); if (e) { features.push(e); if (!parserInput.$char(',')) { break; } @@ -1503,13 +1694,13 @@ var Parser = function Parser(context, imports, fileInfo) { parserInput.save(); - if (parserInput.$str("@media")) { + if (parserInput.$str('@media')) { features = this.mediaFeatures(); rules = this.block(); if (!rules) { - error("media definitions require block statements after any features"); + error('media definitions require block statements after any features'); } parserInput.forget(); @@ -1553,13 +1744,13 @@ var Parser = function Parser(context, imports, fileInfo) { 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'); } } }, @@ -1606,24 +1797,24 @@ var Parser = function Parser(context, imports, fileInfo) { nonVendorSpecificName = name; if (name.charAt(1) == '-' && name.indexOf('-', 2) > 0) { - nonVendorSpecificName = "@" + name.slice(name.indexOf('-', 2) + 1); + nonVendorSpecificName = '@' + name.slice(name.indexOf('-', 2) + 1); } switch (nonVendorSpecificName) { - case "@charset": + case '@charset': hasIdentifier = true; hasBlock = false; break; - case "@namespace": + case '@namespace': hasExpression = true; hasBlock = false; break; - case "@keyframes": - case "@counter-style": + case '@keyframes': + case '@counter-style': hasIdentifier = true; break; - case "@document": - case "@supports": + case '@document': + case '@supports': hasUnknown = true; isRooted = false; break; @@ -1637,19 +1828,19 @@ var Parser = function Parser(context, imports, fileInfo) { if (hasIdentifier) { value = this.entity(); if (!value) { - error("expected " + name + " identifier"); + error('expected ' + name + ' identifier'); } } else if (hasExpression) { value = this.expression(); if (!value) { - error("expected " + name + " expression"); + error('expected ' + name + ' expression'); } } else if (hasUnknown) { value = this.permissiveValue(/^[{;]/); hasBlock = (parserInput.currentChar() === '{'); if (!value) { if (!hasBlock && parserInput.currentChar() !== ';') { - error(name + " rule is missing block or ending semi-colon"); + error(name + ' rule is missing block or ending semi-colon'); } } else if (!value.value) { @@ -1669,7 +1860,7 @@ var Parser = function Parser(context, imports, fileInfo) { ); } - parserInput.restore("at-rule options not recognised"); + parserInput.restore('at-rule options not recognised'); }, // @@ -1712,7 +1903,7 @@ var Parser = function Parser(context, imports, fileInfo) { e.parens = true; return e; } - parserInput.restore("Expected ')'"); + parserInput.restore('Expected \')\''); return; } parserInput.restore(); @@ -1790,7 +1981,7 @@ var Parser = function Parser(context, imports, fileInfo) { condition: function () { var result, logical, next; function or() { - return parserInput.$str("or"); + return parserInput.$str('or'); } result = this.conditionAnd(this); @@ -1814,7 +2005,7 @@ var Parser = function Parser(context, imports, fileInfo) { return me.negatedCondition() || me.parenthesisCondition(); } function and() { - return parserInput.$str("and"); + return parserInput.$str('and'); } result = insideCondition(this); @@ -1833,7 +2024,7 @@ var Parser = function Parser(context, imports, fileInfo) { return result; }, negatedCondition: function () { - if (parserInput.$str("not")) { + if (parserInput.$str('not')) { var result = this.parenthesisCondition(); if (result) { result.negate = !result.negate; @@ -1860,7 +2051,7 @@ var Parser = function Parser(context, imports, fileInfo) { var body; parserInput.save(); - if (!parserInput.$str("(")) { + if (!parserInput.$str('(')) { parserInput.restore(); return ; } @@ -1876,7 +2067,7 @@ var Parser = function Parser(context, imports, fileInfo) { return ; } if (!parserInput.$char(')')) { - parserInput.restore("expected ')' got '" + parserInput.currentChar() + "'"); + parserInput.restore('expected \')\' got \'' + parserInput.currentChar() + '\''); return ; } parserInput.forget(); @@ -1885,25 +2076,30 @@ var Parser = function Parser(context, imports, fileInfo) { atomicCondition: function () { var entities = this.entities, index = parserInput.i, a, b, c, op; - a = this.addition() || entities.keyword() || entities.quoted(); + function cond() { + return this.addition() || entities.keyword() || entities.quoted() || entities.mixinLookup(); + } + cond = cond.bind(this); + + a = cond(); if (a) { if (parserInput.$char('>')) { if (parserInput.$char('=')) { - op = ">="; + op = '>='; } else { op = '>'; } } else if (parserInput.$char('<')) { if (parserInput.$char('=')) { - op = "<="; + op = '<='; } else { op = '<'; } } else if (parserInput.$char('=')) { if (parserInput.$char('>')) { - op = "=>"; + op = '=>'; } else if (parserInput.$char('<')) { op = '=<'; } else { @@ -1911,7 +2107,7 @@ var Parser = function Parser(context, imports, fileInfo) { } } if (op) { - b = this.addition() || entities.keyword() || entities.quoted(); + b = cond(); if (b) { c = new(tree.Condition)(op, a, b, index, false); } else { @@ -1938,7 +2134,8 @@ var Parser = function Parser(context, imports, fileInfo) { var o = this.sub() || entities.dimension() || entities.color() || entities.variable() || entities.property() || entities.call() || - entities.colorKeyword(); + entities.quoted(true) || entities.colorKeyword() || + entities.mixinLookup(); if (negate) { o.parensInOp = true; diff --git a/lib/less/source-map-builder.js b/lib/less/source-map-builder.js index 62f7cf23..14039676 100644 --- a/lib/less/source-map-builder.js +++ b/lib/less/source-map-builder.js @@ -37,15 +37,15 @@ module.exports = function (SourceMapOutput, environment) { var sourceMapURL = this.sourceMapURL; if (this.options.sourceMapFileInline) { if (this.sourceMap === undefined) { - return ""; + return ''; } - sourceMapURL = "data:application/json;base64," + environment.encodeBase64(this.sourceMap); + sourceMapURL = 'data:application/json;base64,' + environment.encodeBase64(this.sourceMap); } if (sourceMapURL) { - return "/*# sourceMappingURL=" + sourceMapURL + " */"; + return '/*# sourceMappingURL=' + sourceMapURL + ' */'; } - return ""; + return ''; }; SourceMapBuilder.prototype.getExternalSourceMap = function() { diff --git a/lib/less/source-map-output.js b/lib/less/source-map-output.js index cf0b862c..e89f5ddf 100644 --- a/lib/less/source-map-output.js +++ b/lib/less/source-map-output.js @@ -19,7 +19,7 @@ module.exports = function (environment) { this._sourceMapRootpath += '/'; } } else { - this._sourceMapRootpath = ""; + this._sourceMapRootpath = ''; } this._outputSourceFiles = options.outputSourceFiles; this._sourceMapGeneratorConstructor = environment.getSourceMapGenerator(); @@ -42,7 +42,7 @@ module.exports = function (environment) { SourceMapOutput.prototype.normalizeFilename = function(filename) { filename = filename.replace(/\\/g, '/'); filename = this.removeBasepath(filename); - return (this._sourceMapRootpath || "") + filename; + return (this._sourceMapRootpath || '') + filename; }; SourceMapOutput.prototype.add = function(chunk, fileInfo, index, mapLines) { @@ -70,11 +70,11 @@ module.exports = function (environment) { inputSource = inputSource.slice(this._contentsIgnoredCharsMap[fileInfo.filename]); } inputSource = inputSource.substring(0, index); - sourceLines = inputSource.split("\n"); + sourceLines = inputSource.split('\n'); sourceColumns = sourceLines[sourceLines.length - 1]; } - lines = chunk.split("\n"); + lines = chunk.split('\n'); columns = lines[lines.length - 1]; if (fileInfo) { diff --git a/lib/less/transform-tree.js b/lib/less/transform-tree.js index d690d693..3799da45 100644 --- a/lib/less/transform-tree.js +++ b/lib/less/transform-tree.js @@ -1,6 +1,6 @@ -var contexts = require("./contexts"), - visitor = require("./visitors"), - tree = require("./tree"); +var contexts = require('./contexts'), + visitor = require('./visitors'), + tree = require('./tree'); module.exports = function(root, options) { options = options || {}; @@ -41,29 +41,49 @@ module.exports = function(root, options) { new visitor.MarkVisibleSelectorsVisitor(true), new visitor.ExtendVisitor(), new visitor.ToCSSVisitor({compress: Boolean(options.compress)}) - ], v, visitorIterator; + ], preEvalVisitors = [], v, visitorIterator; - // first() / get() allows visitors to be added while visiting + /** + * first() / get() allows visitors to be added while visiting + * + * @todo Add scoping for visitors just like functions for @plugin; right now they're global + */ if (options.pluginManager) { visitorIterator = options.pluginManager.visitor(); - visitorIterator.first(); - while ((v = visitorIterator.get())) { - if (v.isPreEvalVisitor) { - v.run(root); + for (var i = 0; i < 2; i++) { + visitorIterator.first(); + while ((v = visitorIterator.get())) { + if (v.isPreEvalVisitor) { + if (i === 0 || preEvalVisitors.indexOf(v) === -1) { + preEvalVisitors.push(v); + v.run(root); + } + } + else { + if (i === 0 || visitors.indexOf(v) === -1) { + if (v.isPreVisitor) { + visitors.unshift(v); + } + else { + visitors.push(v); + } + } + } } } } - + evaldRoot = root.eval(evalEnv); for (var i = 0; i < visitors.length; i++) { visitors[i].run(evaldRoot); } + // Run any remaining visitors added after eval pass if (options.pluginManager) { visitorIterator.first(); while ((v = visitorIterator.get())) { - if (!v.isPreEvalVisitor) { + if (visitors.indexOf(v) === -1 && preEvalVisitors.indexOf(v) === -1) { v.run(evaldRoot); } } diff --git a/lib/less/tree/anonymous.js b/lib/less/tree/anonymous.js index 5775b2ea..2e8edee5 100644 --- a/lib/less/tree/anonymous.js +++ b/lib/less/tree/anonymous.js @@ -1,4 +1,4 @@ -var Node = require("./node"); +var Node = require('./node'); var Anonymous = function (value, index, currentFileInfo, mapLines, rulesetLike, visibilityInfo) { this.value = value; @@ -10,7 +10,7 @@ var Anonymous = function (value, index, currentFileInfo, mapLines, rulesetLike, this.copyVisibilityInfo(visibilityInfo); }; Anonymous.prototype = new Node(); -Anonymous.prototype.type = "Anonymous"; +Anonymous.prototype.type = 'Anonymous'; Anonymous.prototype.eval = function () { return new Anonymous(this.value, this._index, this._fileInfo, this.mapLines, this.rulesetLike, this.visibilityInfo()); }; diff --git a/lib/less/tree/assignment.js b/lib/less/tree/assignment.js index 9c38879d..56e06913 100644 --- a/lib/less/tree/assignment.js +++ b/lib/less/tree/assignment.js @@ -1,4 +1,4 @@ -var Node = require("./node"); +var Node = require('./node'); var Assignment = function (key, val) { this.key = key; @@ -6,7 +6,7 @@ var Assignment = function (key, val) { }; Assignment.prototype = new Node(); -Assignment.prototype.type = "Assignment"; +Assignment.prototype.type = 'Assignment'; Assignment.prototype.accept = function (visitor) { this.value = visitor.visit(this.value); }; diff --git a/lib/less/tree/atrule.js b/lib/less/tree/atrule.js index 62386b81..3dc30060 100644 --- a/lib/less/tree/atrule.js +++ b/lib/less/tree/atrule.js @@ -1,6 +1,6 @@ -var Node = require("./node"), - Selector = require("./selector"), - Ruleset = require("./ruleset"), +var Node = require('./node'), + Selector = require('./selector'), + Ruleset = require('./ruleset'), Anonymous = require('./anonymous'); var AtRule = function (name, value, rules, index, currentFileInfo, debugInfo, isRooted, visibilityInfo) { @@ -29,7 +29,7 @@ var AtRule = function (name, value, rules, index, currentFileInfo, debugInfo, is }; AtRule.prototype = new Node(); -AtRule.prototype.type = "AtRule"; +AtRule.prototype.type = 'AtRule'; AtRule.prototype.accept = function (visitor) { var value = this.value, rules = this.rules; if (rules) { @@ -43,7 +43,7 @@ AtRule.prototype.isRulesetLike = function() { return this.rules || !this.isCharset(); }; AtRule.prototype.isCharset = function() { - return "@charset" === this.name; + return '@charset' === this.name; }; AtRule.prototype.genCSS = function (context, output) { var value = this.value, rules = this.rules; @@ -118,11 +118,11 @@ AtRule.prototype.outputRuleset = function (context, output, rules) { } // Non-compressed - var tabSetStr = '\n' + Array(context.tabLevel).join(" "), tabRuleStr = tabSetStr + " "; + var tabSetStr = '\n' + Array(context.tabLevel).join(' '), tabRuleStr = tabSetStr + ' '; if (!ruleCnt) { - output.add(" {" + tabSetStr + '}'); + output.add(' {' + tabSetStr + '}'); } else { - output.add(" {" + tabRuleStr); + output.add(' {' + tabRuleStr); rules[0].genCSS(context, output); for (i = 1; i < ruleCnt; i++) { output.add(tabRuleStr); diff --git a/lib/less/tree/attribute.js b/lib/less/tree/attribute.js index 488ded79..fe01e697 100644 --- a/lib/less/tree/attribute.js +++ b/lib/less/tree/attribute.js @@ -1,4 +1,4 @@ -var Node = require("./node"); +var Node = require('./node'); var Attribute = function (key, op, value) { this.key = key; @@ -6,7 +6,7 @@ var Attribute = function (key, op, value) { this.value = value; }; Attribute.prototype = new Node(); -Attribute.prototype.type = "Attribute"; +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); diff --git a/lib/less/tree/call.js b/lib/less/tree/call.js index 00dc7b5d..627b13b8 100644 --- a/lib/less/tree/call.js +++ b/lib/less/tree/call.js @@ -1,18 +1,18 @@ -var Node = require("./node"), - Anonymous = require("./anonymous"), - FunctionCaller = require("../functions/function-caller"); +var Node = require('./node'), + Anonymous = require('./anonymous'), + FunctionCaller = require('../functions/function-caller'); // // A function call node. // var Call = function (name, args, index, currentFileInfo) { this.name = name; this.args = args; - this.mathOn = name === 'calc' ? false : true; + this.calc = name === 'calc'; this._index = index; this._fileInfo = currentFileInfo; }; Call.prototype = new Node(); -Call.prototype.type = "Call"; +Call.prototype.type = 'Call'; Call.prototype.accept = function (visitor) { if (this.args) { this.args = visitor.visitArray(this.args); @@ -30,13 +30,18 @@ Call.prototype.accept = function (visitor) { // The function should receive the value, not the variable. // Call.prototype.eval = function (context) { - /** * Turn off math for calc(), and switch back on for evaluating nested functions */ var currentMathContext = context.mathOn; - context.mathOn = this.mathOn; + context.mathOn = !this.calc; + if (this.calc || context.inCalc) { + context.enterCalc(); + } var args = this.args.map(function (a) { return a.eval(context); }); + if (this.calc || context.inCalc) { + context.exitCalc(); + } context.mathOn = currentMathContext; var result, funcCaller = new FunctionCaller(this.name, context, this.getIndex(), this.fileInfo()); @@ -46,8 +51,8 @@ Call.prototype.eval = function (context) { result = funcCaller.call(args); } catch (e) { throw { - type: e.type || "Runtime", - message: "error evaluating function `" + this.name + "`" + + type: e.type || 'Runtime', + message: 'error evaluating function `' + this.name + '`' + (e.message ? ': ' + e.message : ''), index: this.getIndex(), filename: this.fileInfo().filename, @@ -78,15 +83,15 @@ Call.prototype.eval = function (context) { return new Call(this.name, args, this.getIndex(), this.fileInfo()); }; Call.prototype.genCSS = function (context, output) { - output.add(this.name + "(", this.fileInfo(), this.getIndex()); + output.add(this.name + '(', this.fileInfo(), this.getIndex()); for (var i = 0; i < this.args.length; i++) { this.args[i].genCSS(context, output); if (i + 1 < this.args.length) { - output.add(", "); + output.add(', '); } } - output.add(")"); + output.add(')'); }; module.exports = Call; diff --git a/lib/less/tree/color.js b/lib/less/tree/color.js index 1910f459..aab77143 100644 --- a/lib/less/tree/color.js +++ b/lib/less/tree/color.js @@ -1,5 +1,5 @@ -var Node = require("./node"), - colors = require("../data/colors"); +var Node = require('./node'), + colors = require('../data/colors'); // // RGB Colors - #ff0014, #eee @@ -29,7 +29,7 @@ var Color = function (rgb, a, originalForm) { }; Color.prototype = new Node(); -Color.prototype.type = "Color"; +Color.prototype.type = 'Color'; function clamp(v, max) { return Math.min(Math.max(v, 0), max); @@ -72,10 +72,10 @@ Color.prototype.toCSS = function (context, doNotCompress) { // Values are capped between `0` and `255`, rounded and zero-padded. alpha = this.fround(context, this.alpha); if (alpha < 1) { - return "rgba(" + this.rgb.map(function (c) { + return 'rgba(' + this.rgb.map(function (c) { return clamp(Math.round(c), 255); }).concat(clamp(alpha, 1)) - .join(',' + (compress ? '' : ' ')) + ")"; + .join(',' + (compress ? '' : ' ')) + ')'; } color = this.toRGB(); @@ -177,7 +177,7 @@ Color.fromKeyword = function(keyword) { if (colors.hasOwnProperty(key)) { c = new Color(colors[key].slice(1)); } - else if (key === "transparent") { + else if (key === 'transparent') { c = new Color([0, 0, 0], 0); } diff --git a/lib/less/tree/combinator.js b/lib/less/tree/combinator.js index 323522dd..fcb2b776 100644 --- a/lib/less/tree/combinator.js +++ b/lib/less/tree/combinator.js @@ -1,16 +1,16 @@ -var Node = require("./node"); +var Node = require('./node'); var Combinator = function (value) { if (value === ' ') { this.value = ' '; this.emptyOrWhitespace = true; } else { - this.value = value ? value.trim() : ""; - this.emptyOrWhitespace = this.value === ""; + this.value = value ? value.trim() : ''; + this.emptyOrWhitespace = this.value === ''; } }; Combinator.prototype = new Node(); -Combinator.prototype.type = "Combinator"; +Combinator.prototype.type = 'Combinator'; var _noSpaceCombinators = { '': true, ' ': true, diff --git a/lib/less/tree/comment.js b/lib/less/tree/comment.js index a3cbfdca..ec029a6b 100644 --- a/lib/less/tree/comment.js +++ b/lib/less/tree/comment.js @@ -1,5 +1,5 @@ -var Node = require("./node"), - getDebugInfo = require("./debug-info"); +var Node = require('./node'), + getDebugInfo = require('./debug-info'); var Comment = function (value, isLineComment, index, currentFileInfo) { this.value = value; @@ -9,7 +9,7 @@ var Comment = function (value, isLineComment, index, currentFileInfo) { this.allowRoot = true; }; Comment.prototype = new Node(); -Comment.prototype.type = "Comment"; +Comment.prototype.type = 'Comment'; Comment.prototype.genCSS = function (context, output) { if (this.debugInfo) { output.add(getDebugInfo(context, this), this.fileInfo(), this.getIndex()); @@ -17,7 +17,7 @@ Comment.prototype.genCSS = function (context, output) { output.add(this.value); }; Comment.prototype.isSilent = function(context) { - var isCompressed = context.compress && this.value[2] !== "!"; + var isCompressed = context.compress && this.value[2] !== '!'; return this.isLineComment || isCompressed; }; module.exports = Comment; diff --git a/lib/less/tree/condition.js b/lib/less/tree/condition.js index 4c893089..64177f6e 100644 --- a/lib/less/tree/condition.js +++ b/lib/less/tree/condition.js @@ -1,4 +1,4 @@ -var Node = require("./node"); +var Node = require('./node'); var Condition = function (op, l, r, i, negate) { this.op = op.trim(); @@ -8,7 +8,7 @@ var Condition = function (op, l, r, i, negate) { this.negate = negate; }; Condition.prototype = new Node(); -Condition.prototype.type = "Condition"; +Condition.prototype.type = 'Condition'; Condition.prototype.accept = function (visitor) { this.lvalue = visitor.visit(this.lvalue); this.rvalue = visitor.visit(this.rvalue); diff --git a/lib/less/tree/debug-info.js b/lib/less/tree/debug-info.js index 5b1db51f..56fb2246 100644 --- a/lib/less/tree/debug-info.js +++ b/lib/less/tree/debug-info.js @@ -1,5 +1,5 @@ var debugInfo = function(context, ctx, lineSeparator) { - var result = ""; + var result = ''; if (context.dumpLineNumbers && !context.compress) { switch (context.dumpLineNumbers) { case 'comments': @@ -9,7 +9,7 @@ var debugInfo = function(context, ctx, lineSeparator) { result = debugInfo.asMediaQuery(ctx); break; case 'all': - result = debugInfo.asComment(ctx) + (lineSeparator || "") + debugInfo.asMediaQuery(ctx); + result = debugInfo.asComment(ctx) + (lineSeparator || '') + debugInfo.asMediaQuery(ctx); break; } } diff --git a/lib/less/tree/declaration.js b/lib/less/tree/declaration.js index 9a3d077c..10916029 100644 --- a/lib/less/tree/declaration.js +++ b/lib/less/tree/declaration.js @@ -1,7 +1,7 @@ -var Node = require("./node"), - Value = require("./value"), - Keyword = require("./keyword"), - Anonymous = require("./anonymous"); +var Node = require('./node'), + Value = require('./value'), + Keyword = require('./keyword'), + Anonymous = require('./anonymous'); var Declaration = function (name, value, important, merge, index, currentFileInfo, inline, variable) { this.name = name; @@ -18,7 +18,7 @@ var Declaration = function (name, value, important, merge, index, currentFileInf }; function evalName(context, name) { - var value = "", i, n = name.length, + 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); @@ -27,7 +27,7 @@ function evalName(context, name) { } Declaration.prototype = new Node(); -Declaration.prototype.type = "Declaration"; +Declaration.prototype.type = 'Declaration'; Declaration.prototype.genCSS = function (context, output) { output.add(this.name + (context.compress ? ':' : ': '), this.fileInfo(), this.getIndex()); try { @@ -38,18 +38,18 @@ Declaration.prototype.genCSS = function (context, output) { e.filename = this._fileInfo.filename; throw e; } - output.add(this.important + ((this.inline || (context.lastRule && context.compress)) ? "" : ";"), this._fileInfo, this._index); + output.add(this.important + ((this.inline || (context.lastRule && context.compress)) ? '' : ';'), this._fileInfo, this._index); }; Declaration.prototype.eval = function (context) { var strictMathBypass = false, prevMath, name = this.name, evaldValue, variable = this.variable; - if (typeof name !== "string") { + 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) { + if (name === 'font' && !context.strictMath) { strictMathBypass = true; prevMath = context.strictMath; context.strictMath = 'division'; @@ -58,8 +58,8 @@ Declaration.prototype.eval = function (context) { context.importantScope.push({}); evaldValue = this.value.eval(context); - if (!this.variable && evaldValue.type === "DetachedRuleset") { - throw { message: "Rulesets cannot be evaluated on a property.", + 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, @@ -91,7 +91,7 @@ Declaration.prototype.eval = function (context) { Declaration.prototype.makeImportant = function () { return new Declaration(this.name, this.value, - "!important", + '!important', this.merge, this.getIndex(), this.fileInfo(), this.inline); }; diff --git a/lib/less/tree/detached-ruleset.js b/lib/less/tree/detached-ruleset.js index 2805809f..c2c1f4c3 100644 --- a/lib/less/tree/detached-ruleset.js +++ b/lib/less/tree/detached-ruleset.js @@ -1,6 +1,6 @@ -var Node = require("./node"), - contexts = require("../contexts"), - utils = require("../utils"); +var Node = require('./node'), + contexts = require('../contexts'), + utils = require('../utils'); var DetachedRuleset = function (ruleset, frames) { this.ruleset = ruleset; @@ -8,7 +8,7 @@ var DetachedRuleset = function (ruleset, frames) { this.setParent(this.ruleset, this); }; DetachedRuleset.prototype = new Node(); -DetachedRuleset.prototype.type = "DetachedRuleset"; +DetachedRuleset.prototype.type = 'DetachedRuleset'; DetachedRuleset.prototype.evalFirst = true; DetachedRuleset.prototype.accept = function (visitor) { this.ruleset = visitor.visit(this.ruleset); diff --git a/lib/less/tree/dimension.js b/lib/less/tree/dimension.js index aead4df1..b850e8e8 100644 --- a/lib/less/tree/dimension.js +++ b/lib/less/tree/dimension.js @@ -1,7 +1,7 @@ -var Node = require("./node"), - unitConversions = require("../data/unit-conversions"), - Unit = require("./unit"), - Color = require("./color"); +var Node = require('./node'), + unitConversions = require('../data/unit-conversions'), + Unit = require('./unit'), + Color = require('./color'); // // A number with a unit @@ -9,7 +9,7 @@ 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."); + throw new Error('Dimension is not a number.'); } this.unit = (unit && unit instanceof Unit) ? unit : new Unit(unit ? [unit] : undefined); @@ -17,7 +17,7 @@ var Dimension = function (value, unit) { }; Dimension.prototype = new Node(); -Dimension.prototype.type = "Dimension"; +Dimension.prototype.type = 'Dimension'; Dimension.prototype.accept = function (visitor) { this.unit = visitor.visit(this.unit); }; @@ -29,7 +29,7 @@ Dimension.prototype.toColor = function () { }; Dimension.prototype.genCSS = function (context, output) { if ((context && context.strictUnits) && !this.unit.isSingular()) { - throw new Error("Multiple units in dimension. Correct the units or use the unit function. Bad unit: " + this.unit.toString()); + throw new Error('Multiple units in dimension. Correct the units or use the unit function. Bad unit: ' + this.unit.toString()); } var value = this.fround(context, this.value), @@ -37,7 +37,7 @@ Dimension.prototype.genCSS = function (context, output) { if (value !== 0 && value < 0.000001 && value > -0.000001) { // would be output 1e-6 etc. - strValue = value.toFixed(20).replace(/0+$/, ""); + strValue = value.toFixed(20).replace(/0+$/, ''); } if (context && context.compress) { @@ -77,8 +77,8 @@ Dimension.prototype.operate = function (context, op, other) { other = other.convertTo(this.unit.usedUnits()); if (context.strictUnits && other.unit.toString() !== unit.toString()) { - throw new Error("Incompatible units. Change the units or use the unit function. Bad units: '" + unit.toString() + - "' and '" + other.unit.toString() + "'."); + throw new Error('Incompatible units. Change the units or use the unit function. Bad units: \'' + unit.toString() + + '\' and \'' + other.unit.toString() + '\'.'); } value = this._operate(context, op, this.value, other.value); diff --git a/lib/less/tree/element.js b/lib/less/tree/element.js index c759f97f..13fa3b2b 100644 --- a/lib/less/tree/element.js +++ b/lib/less/tree/element.js @@ -1,8 +1,8 @@ -var Node = require("./node"), - Paren = require("./paren"), - Combinator = require("./combinator"); +var Node = require('./node'), + Paren = require('./paren'), + Combinator = require('./combinator'); -var Element = function (combinator, value, index, currentFileInfo, visibilityInfo) { +var Element = function (combinator, value, isVariable, index, currentFileInfo, visibilityInfo) { this.combinator = combinator instanceof Combinator ? combinator : new Combinator(combinator); @@ -11,31 +11,34 @@ var Element = function (combinator, value, index, currentFileInfo, visibilityInf } else if (value) { this.value = value; } else { - this.value = ""; + this.value = ''; } + this.isVariable = isVariable; this._index = index; this._fileInfo = currentFileInfo; this.copyVisibilityInfo(visibilityInfo); this.setParent(this.combinator, this); }; Element.prototype = new Node(); -Element.prototype.type = "Element"; +Element.prototype.type = 'Element'; Element.prototype.accept = function (visitor) { var value = this.value; this.combinator = visitor.visit(this.combinator); - if (typeof value === "object") { + if (typeof value === 'object') { this.value = visitor.visit(value); } }; Element.prototype.eval = function (context) { return new Element(this.combinator, this.value.eval ? this.value.eval(context) : this.value, + this.isVariable, this.getIndex(), this.fileInfo(), this.visibilityInfo()); }; Element.prototype.clone = function () { return new Element(this.combinator, this.value, + this.isVariable, this.getIndex(), this.fileInfo(), this.visibilityInfo()); }; diff --git a/lib/less/tree/expression.js b/lib/less/tree/expression.js index 257c93e3..92cad86c 100644 --- a/lib/less/tree/expression.js +++ b/lib/less/tree/expression.js @@ -1,21 +1,22 @@ -var Node = require("./node"), - Paren = require("./paren"), - Comment = require("./comment"); +var Node = require('./node'), + Paren = require('./paren'), + Comment = require('./comment'); var Expression = function (value, noSpacing) { this.value = value; this.noSpacing = noSpacing; if (!value) { - throw new Error("Expression requires an array parameter"); + throw new Error('Expression requires an array parameter'); } }; Expression.prototype = new Node(); -Expression.prototype.type = "Expression"; +Expression.prototype.type = 'Expression'; Expression.prototype.accept = function (visitor) { this.value = visitor.visitArray(this.value); }; Expression.prototype.eval = function (context) { var returnValue, + mathOn = context.isMathOn(), inParenthesis = this.parens && !this.parensInOp, doubleParen = false; if (inParenthesis) { @@ -23,10 +24,13 @@ Expression.prototype.eval = function (context) { } if (this.value.length > 1) { returnValue = new Expression(this.value.map(function (e) { + if (!e.eval) { + return e; + } return e.eval(context); }), this.noSpacing); } else if (this.value.length === 1) { - if (this.value[0].parens && !this.value[0].parensInOp) { + if (this.value[0].parens && !this.value[0].parensInOp && !context.inCalc) { doubleParen = true; } returnValue = this.value[0].eval(context); @@ -36,7 +40,7 @@ Expression.prototype.eval = function (context) { if (inParenthesis) { context.outOfParenthesis(); } - if (this.parens && this.parensInOp && !(context.isMathOn()) && !doubleParen) { + if (this.parens && this.parensInOp && !mathOn && !doubleParen) { returnValue = new Paren(returnValue); } return returnValue; @@ -45,7 +49,7 @@ Expression.prototype.genCSS = function (context, output) { for (var i = 0; i < this.value.length; i++) { this.value[i].genCSS(context, output); if (!this.noSpacing && i + 1 < this.value.length) { - output.add(" "); + output.add(' '); } } }; diff --git a/lib/less/tree/extend.js b/lib/less/tree/extend.js index 8d2c3745..a716fc74 100644 --- a/lib/less/tree/extend.js +++ b/lib/less/tree/extend.js @@ -1,5 +1,5 @@ -var Node = require("./node"), - Selector = require("./selector"); +var Node = require('./node'), + Selector = require('./selector'); var Extend = function Extend(selector, option, index, currentFileInfo, visibilityInfo) { this.selector = selector; @@ -12,7 +12,7 @@ var Extend = function Extend(selector, option, index, currentFileInfo, visibilit this.allowRoot = true; switch (option) { - case "all": + case 'all': this.allowBefore = true; this.allowAfter = true; break; @@ -26,7 +26,7 @@ var Extend = function Extend(selector, option, index, currentFileInfo, visibilit Extend.next_id = 0; Extend.prototype = new Node(); -Extend.prototype.type = "Extend"; +Extend.prototype.type = 'Extend'; Extend.prototype.accept = function (visitor) { this.selector = visitor.visit(this.selector); }; @@ -46,7 +46,7 @@ Extend.prototype.findSelfSelectors = function (selectors) { selectorElements = selectors[i].elements; // duplicate the logic in genCSS function inside the selector node. // future TODO - move both logics into the selector joiner visitor - if (i > 0 && selectorElements.length && selectorElements[0].combinator.value === "") { + if (i > 0 && selectorElements.length && selectorElements[0].combinator.value === '') { selectorElements[0].combinator.value = ' '; } selfElements = selfElements.concat(selectors[i].elements); diff --git a/lib/less/tree/import.js b/lib/less/tree/import.js index b459bb39..53d3f55d 100644 --- a/lib/less/tree/import.js +++ b/lib/less/tree/import.js @@ -1,11 +1,11 @@ -var Node = require("./node"), - Media = require("./media"), - URL = require("./url"), - Quoted = require("./quoted"), - Ruleset = require("./ruleset"), - Anonymous = require("./anonymous"), - utils = require("../utils"), - LessError = require("../less-error"); +var Node = require('./node'), + Media = require('./media'), + URL = require('./url'), + Quoted = require('./quoted'), + Ruleset = require('./ruleset'), + Anonymous = require('./anonymous'), + utils = require('../utils'), + LessError = require('../less-error'); // // CSS @import node @@ -50,7 +50,7 @@ var Import = function (path, features, options, index, currentFileInfo, visibili // ruleset. // Import.prototype = new Node(); -Import.prototype.type = "Import"; +Import.prototype.type = 'Import'; Import.prototype.accept = function (visitor) { if (this.features) { this.features = visitor.visit(this.features); @@ -62,10 +62,10 @@ Import.prototype.accept = function (visitor) { }; Import.prototype.genCSS = function (context, output) { if (this.css && this.path._fileInfo.reference === undefined) { - output.add("@import ", this._fileInfo, this._index); + output.add('@import ', this._fileInfo, this._index); this.path.genCSS(context, output); if (this.features) { - output.add(" "); + output.add(' '); this.features.genCSS(context, output); } output.add(';'); @@ -136,7 +136,7 @@ Import.prototype.doEval = function (context) { this.root.eval(context); } catch (e) { - e.message = "Plugin error during evaluation"; + e.message = 'Plugin error during evaluation'; throw new LessError(e, this.root.imports, this.root.filename); } } @@ -149,7 +149,7 @@ Import.prototype.doEval = function (context) { } if (this.skip) { - if (typeof this.skip === "function") { + if (typeof this.skip === 'function') { this.skip = this.skip(); } if (this.skip) { diff --git a/lib/less/tree/index.js b/lib/less/tree/index.js index 349cb3fb..d5972a60 100644 --- a/lib/less/tree/index.js +++ b/lib/less/tree/index.js @@ -37,5 +37,6 @@ tree.UnicodeDescriptor = require('./unicode-descriptor'); tree.Negative = require('./negative'); tree.Extend = require('./extend'); tree.VariableCall = require('./variable-call'); +tree.NamespaceValue = require('./namespace-value'); module.exports = tree; diff --git a/lib/less/tree/javascript.js b/lib/less/tree/javascript.js index e2ee0137..9e77e797 100644 --- a/lib/less/tree/javascript.js +++ b/lib/less/tree/javascript.js @@ -1,7 +1,7 @@ -var JsEvalNode = require("./js-eval-node"), - Dimension = require("./dimension"), - Quoted = require("./quoted"), - Anonymous = require("./anonymous"); +var JsEvalNode = require('./js-eval-node'), + Dimension = require('./dimension'), + Quoted = require('./quoted'), + Anonymous = require('./anonymous'); var JavaScript = function (string, escaped, index, currentFileInfo) { this.escaped = escaped; @@ -10,13 +10,14 @@ var JavaScript = function (string, escaped, index, currentFileInfo) { this._fileInfo = currentFileInfo; }; JavaScript.prototype = new JsEvalNode(); -JavaScript.prototype.type = "JavaScript"; +JavaScript.prototype.type = 'JavaScript'; JavaScript.prototype.eval = function(context) { var result = this.evaluateJavaScript(this.expression, context); + var type = typeof result; - if (typeof result === 'number') { + if (type === 'number' && !isNaN(result)) { return new Dimension(result); - } else if (typeof result === 'string') { + } else if (type === 'string') { return new Quoted('"' + result + '"', result, this.escaped, this._index); } else if (Array.isArray(result)) { return new Anonymous(result.join(', ')); diff --git a/lib/less/tree/js-eval-node.js b/lib/less/tree/js-eval-node.js index 24d6594d..f168fe9d 100644 --- a/lib/less/tree/js-eval-node.js +++ b/lib/less/tree/js-eval-node.js @@ -1,5 +1,5 @@ -var Node = require("./node"), - Variable = require("./variable"); +var Node = require('./node'), + Variable = require('./variable'); var JsEvalNode = function() { }; @@ -11,7 +11,7 @@ JsEvalNode.prototype.evaluateJavaScript = function (expression, context) { evalContext = {}; if (!context.javascriptEnabled) { - throw { message: "Inline JavaScript is not enabled. Is it set in your options?", + throw { message: 'Inline JavaScript is not enabled. Is it set in your options?', filename: this.fileInfo().filename, index: this.getIndex() }; } @@ -23,7 +23,7 @@ JsEvalNode.prototype.evaluateJavaScript = function (expression, context) { try { expression = new Function('return (' + expression + ')'); } catch (e) { - throw { message: "JavaScript evaluation error: " + e.message + " from `" + expression + "`" , + throw { message: 'JavaScript evaluation error: ' + e.message + ' from `' + expression + '`' , filename: this.fileInfo().filename, index: this.getIndex() }; } @@ -44,7 +44,7 @@ JsEvalNode.prototype.evaluateJavaScript = function (expression, context) { try { result = expression.call(evalContext); } catch (e) { - throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message.replace(/["]/g, "'") + "'" , + throw { message: 'JavaScript evaluation error: \'' + e.name + ': ' + e.message.replace(/["]/g, '\'') + '\'' , filename: this.fileInfo().filename, index: this.getIndex() }; } diff --git a/lib/less/tree/keyword.js b/lib/less/tree/keyword.js index cbb508e0..16c0b870 100644 --- a/lib/less/tree/keyword.js +++ b/lib/less/tree/keyword.js @@ -1,10 +1,10 @@ -var Node = require("./node"); +var Node = require('./node'); var Keyword = function (value) { this.value = value; }; Keyword.prototype = new Node(); -Keyword.prototype.type = "Keyword"; +Keyword.prototype.type = 'Keyword'; Keyword.prototype.genCSS = function (context, output) { - if (this.value === '%') { throw { type: "Syntax", message: "Invalid % without number" }; } + if (this.value === '%') { throw { type: 'Syntax', message: 'Invalid % without number' }; } output.add(this.value); }; diff --git a/lib/less/tree/media.js b/lib/less/tree/media.js index 6cd82143..cda55266 100644 --- a/lib/less/tree/media.js +++ b/lib/less/tree/media.js @@ -1,10 +1,10 @@ -var Ruleset = require("./ruleset"), - Value = require("./value"), - Selector = require("./selector"), - Anonymous = require("./anonymous"), - Expression = require("./expression"), - AtRule = require("./atrule"), - utils = require("../utils"); +var Ruleset = require('./ruleset'), + Value = require('./value'), + Selector = require('./selector'), + Anonymous = require('./anonymous'), + Expression = require('./expression'), + AtRule = require('./atrule'), + utils = require('../utils'); var Media = function (value, features, index, currentFileInfo, visibilityInfo) { this._index = index; @@ -22,7 +22,7 @@ var Media = function (value, features, index, currentFileInfo, visibilityInfo) { this.setParent(this.rules, this); }; Media.prototype = new AtRule(); -Media.prototype.type = "Media"; +Media.prototype.type = 'Media'; Media.prototype.isRulesetLike = function() { return true; }; Media.prototype.accept = function (visitor) { if (this.features) { @@ -105,7 +105,7 @@ Media.prototype.evalNested = function (context) { }); for (i = path.length - 1; i > 0; i--) { - path.splice(i, 0, new Anonymous("and")); + path.splice(i, 0, new Anonymous('and')); } return new Expression(path); diff --git a/lib/less/tree/mixin-call.js b/lib/less/tree/mixin-call.js index 7b1d0c0b..49784f02 100644 --- a/lib/less/tree/mixin-call.js +++ b/lib/less/tree/mixin-call.js @@ -1,7 +1,7 @@ -var Node = require("./node"), - Selector = require("./selector"), - MixinDefinition = require("./mixin-definition"), - defaultFunc = require("../functions/default"); +var Node = require('./node'), + Selector = require('./selector'), + MixinDefinition = require('./mixin-definition'), + defaultFunc = require('../functions/default'); var MixinCall = function (elements, args, index, currentFileInfo, important) { this.selector = new Selector(elements); @@ -13,7 +13,7 @@ var MixinCall = function (elements, args, index, currentFileInfo, important) { this.setParent(this.selector, this); }; MixinCall.prototype = new Node(); -MixinCall.prototype.type = "MixinCall"; +MixinCall.prototype.type = 'MixinCall'; MixinCall.prototype.accept = function (visitor) { if (this.selector) { this.selector = visitor.visit(this.selector); @@ -28,6 +28,8 @@ MixinCall.prototype.eval = function (context) { candidates = [], candidate, conditionResult = [], defaultResult, defFalseEitherCase = -1, defNone = 0, defTrue = 1, defFalse = 2, count, originalRuleset, noArgumentsFilter; + this.selector = this.selector.eval(context); + function calcDefGroup(mixin, mixinPath) { var f, p, namespace; @@ -129,7 +131,7 @@ MixinCall.prototype.eval = function (context) { mixin = candidates[m].mixin; if (!(mixin instanceof MixinDefinition)) { originalRuleset = mixin.originalRuleset || mixin; - mixin = new MixinDefinition("", [], mixin.rules, null, false, null, originalRuleset.visibilityInfo()); + mixin = new MixinDefinition('', [], mixin.rules, null, false, null, originalRuleset.visibilityInfo()); mixin.originalRuleset = originalRuleset; } var newRules = mixin.evalCall(context, args, this.important).rules; @@ -152,7 +154,7 @@ MixinCall.prototype.eval = function (context) { index: this.getIndex(), filename: this.fileInfo().filename }; } else { throw { type: 'Name', - message: this.selector.toCSS().trim() + " is undefined", + message: this.selector.toCSS().trim() + ' is undefined', index: this.getIndex(), filename: this.fileInfo().filename }; } }; @@ -169,16 +171,16 @@ MixinCall.prototype._setVisibilityToReplacement = function (replacement) { MixinCall.prototype.format = function (args) { return this.selector.toCSS().trim() + '(' + (args ? args.map(function (a) { - var argValue = ""; + var argValue = ''; if (a.name) { - argValue += a.name + ":"; + argValue += a.name + ':'; } if (a.value.toCSS) { argValue += a.value.toCSS(); } else { - argValue += "???"; + argValue += '???'; } return argValue; - }).join(', ') : "") + ")"; + }).join(', ') : '') + ')'; }; module.exports = MixinCall; diff --git a/lib/less/tree/mixin-definition.js b/lib/less/tree/mixin-definition.js index 31b3b39a..b2b5661d 100644 --- a/lib/less/tree/mixin-definition.js +++ b/lib/less/tree/mixin-definition.js @@ -1,14 +1,15 @@ -var Selector = require("./selector"), - Element = require("./element"), - Ruleset = require("./ruleset"), - Declaration = require("./declaration"), - Expression = require("./expression"), - contexts = require("../contexts"), - utils = require("../utils"); +var Selector = require('./selector'), + Element = require('./element'), + Ruleset = require('./ruleset'), + Declaration = require('./declaration'), + DetachedRuleset = require('./detached-ruleset'), + Expression = require('./expression'), + 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._fileInfo)])]; + this.selectors = [new Selector([new Element(null, name, false, this._index, this._fileInfo)])]; this.params = params; this.condition = condition; this.variadic = variadic; @@ -31,7 +32,7 @@ var Definition = function (name, params, rules, condition, variadic, frames, vis this.allowRoot = true; }; Definition.prototype = new Ruleset(); -Definition.prototype.type = "MixinDefinition"; +Definition.prototype.type = 'MixinDefinition'; Definition.prototype.evalFirst = true; Definition.prototype.accept = function (visitor) { if (this.params && this.params.length) { @@ -75,7 +76,7 @@ Definition.prototype.evalParams = function (context, mixinEnv, args, evaldArgume i--; continue; } else { - throw { type: 'Runtime', message: "Named argument for " + this.name + + throw { type: 'Runtime', message: 'Named argument for ' + this.name + ' ' + args[i].name + ' not found' }; } } @@ -97,12 +98,18 @@ Definition.prototype.evalParams = function (context, mixinEnv, args, evaldArgume } else { val = arg && arg.value; if (val) { - val = val.eval(context); + // This was a mixin call, pass in a detached ruleset of it's eval'd rules + if (Array.isArray(val)) { + val = new DetachedRuleset(new Ruleset('', val)); + } + else { + val = val.eval(context); + } } else if (params[i].value) { val = params[i].value.eval(mixinEnv); frame.resetCache(); } else { - throw { type: 'Runtime', message: "wrong number of arguments for " + this.name + + throw { type: 'Runtime', message: 'wrong number of arguments for ' + this.name + ' (' + argsLength + ' for ' + this.arity + ')' }; } diff --git a/lib/less/tree/namespace-value.js b/lib/less/tree/namespace-value.js new file mode 100644 index 00000000..3ef109cc --- /dev/null +++ b/lib/less/tree/namespace-value.js @@ -0,0 +1,79 @@ +var Node = require('./node'), + Variable = require('./variable'), + Ruleset = require('./ruleset'), + Selector = require('./selector'); + +var NamespaceValue = function (ruleCall, lookups, important, index, fileInfo) { + this.value = ruleCall; + this.lookups = lookups; + this.important = important; + this._index = index; + this._fileInfo = fileInfo; +}; +NamespaceValue.prototype = new Node(); +NamespaceValue.prototype.type = 'NamespaceValue'; +NamespaceValue.prototype.eval = function (context) { + var i, j, name, rules = this.value.eval(context); + + for (i = 0; i < this.lookups.length; i++) { + name = this.lookups[i]; + + /** + * Eval'd DRs return rulesets. + * Eval'd mixins return rules, so let's make a ruleset if we need it. + * We need to do this because of late parsing of values + */ + if (Array.isArray(rules)) { + rules = new Ruleset([new Selector()], rules); + } + + if (name === '') { + rules = rules.lastDeclaration(); + } + else if (name.charAt(0) === '@') { + if (name.charAt(1) === '@') { + name = '@' + new Variable(name.substr(1)).eval(context).value; + } + if (rules.variables) { + rules = rules.variable(name); + } + + if (!rules) { + throw { type: 'Name', + message: 'variable ' + name + ' not found', + filename: this.fileInfo().filename, + index: this.getIndex() }; + } + } + else { + if (name.substring(0, 2) === '$@') { + name = '$' + new Variable(name.substr(1)).eval(context).value; + } + else { + name = name.charAt(0) === '$' ? name : '$' + name; + } + if (rules.properties) { + rules = rules.property(name); + } + + if (!rules) { + throw { type: 'Name', + message: 'property "' + name.substr(1) + '" not found', + filename: this.fileInfo().filename, + index: this.getIndex() }; + } + // Properties are an array of values, since a ruleset can have multiple props. + // We pick the last one (the "cascaded" value) + rules = rules[rules.length - 1]; + } + + if (rules.value) { + rules = rules.eval(context).value; + } + if (rules.ruleset) { + rules = rules.ruleset.eval(context); + } + } + return rules; +}; +module.exports = NamespaceValue; diff --git a/lib/less/tree/negative.js b/lib/less/tree/negative.js index 228e8a66..5052dddb 100644 --- a/lib/less/tree/negative.js +++ b/lib/less/tree/negative.js @@ -1,12 +1,12 @@ -var Node = require("./node"), - Operation = require("./operation"), - Dimension = require("./dimension"); +var Node = require('./node'), + Operation = require('./operation'), + Dimension = require('./dimension'); var Negative = function (node) { this.value = node; }; Negative.prototype = new Node(); -Negative.prototype.type = "Negative"; +Negative.prototype.type = 'Negative'; Negative.prototype.genCSS = function (context, output) { output.add('-'); this.value.genCSS(context, output); diff --git a/lib/less/tree/node.js b/lib/less/tree/node.js index 2de98c6c..fe9e5231 100644 --- a/lib/less/tree/node.js +++ b/lib/less/tree/node.js @@ -6,10 +6,10 @@ var Node = function() { this.parsed = null; var self = this; - Object.defineProperty(this, "currentFileInfo", { + Object.defineProperty(this, 'currentFileInfo', { get: function() { return self.fileInfo(); } }); - Object.defineProperty(this, "index", { + Object.defineProperty(this, 'index', { get: function() { return self.getIndex(); } }); @@ -76,7 +76,7 @@ Node.compare = function (a, b) { if ((a.compare) && // for "symmetric results" force toCSS-based comparison // of Quoted or Anonymous if either value is one of those - !(b.type === "Quoted" || b.type === "Anonymous")) { + !(b.type === 'Quoted' || b.type === 'Anonymous')) { return a.compare(b); } else if (b.compare) { return -b.compare(a); diff --git a/lib/less/tree/operation.js b/lib/less/tree/operation.js index 6974c742..e7bafb56 100644 --- a/lib/less/tree/operation.js +++ b/lib/less/tree/operation.js @@ -1,6 +1,6 @@ -var Node = require("./node"), - Color = require("./color"), - Dimension = require("./dimension"); +var Node = require('./node'), + Color = require('./color'), + Dimension = require('./dimension'); var Operation = function (op, operands, isSpaced) { this.op = op.trim(); @@ -8,7 +8,7 @@ var Operation = function (op, operands, isSpaced) { this.isSpaced = isSpaced; }; Operation.prototype = new Node(); -Operation.prototype.type = "Operation"; +Operation.prototype.type = 'Operation'; Operation.prototype.accept = function (visitor) { this.operands = visitor.visit(this.operands); }; @@ -26,8 +26,8 @@ Operation.prototype.eval = function (context) { b = b.toColor(); } if (!a.operate) { - throw { type: "Operation", - message: "Operation on an invalid type" }; + throw { type: 'Operation', + message: 'Operation on an invalid type' }; } return a.operate(context, op, b); @@ -38,11 +38,11 @@ Operation.prototype.eval = function (context) { Operation.prototype.genCSS = function (context, output) { this.operands[0].genCSS(context, output); if (this.isSpaced) { - output.add(" "); + output.add(' '); } output.add(this.op); if (this.isSpaced) { - output.add(" "); + output.add(' '); } this.operands[1].genCSS(context, output); }; diff --git a/lib/less/tree/paren.js b/lib/less/tree/paren.js index a02ae325..d77956f1 100644 --- a/lib/less/tree/paren.js +++ b/lib/less/tree/paren.js @@ -1,10 +1,10 @@ -var Node = require("./node"); +var Node = require('./node'); var Paren = function (node) { this.value = node; }; Paren.prototype = new Node(); -Paren.prototype.type = "Paren"; +Paren.prototype.type = 'Paren'; Paren.prototype.genCSS = function (context, output) { output.add('('); this.value.genCSS(context, output); diff --git a/lib/less/tree/property.js b/lib/less/tree/property.js index 86d5f498..34572197 100644 --- a/lib/less/tree/property.js +++ b/lib/less/tree/property.js @@ -1,5 +1,5 @@ -var Node = require("./node"), - Declaration = require("./declaration"); +var Node = require('./node'), + Declaration = require('./declaration'); var Property = function (name, index, currentFileInfo) { this.name = name; @@ -7,7 +7,7 @@ var Property = function (name, index, currentFileInfo) { this._fileInfo = currentFileInfo; }; Property.prototype = new Node(); -Property.prototype.type = "Property"; +Property.prototype.type = 'Property'; Property.prototype.eval = function (context) { var property, name = this.name; // TODO: shorten this reference @@ -15,7 +15,7 @@ Property.prototype.eval = function (context) { if (this.evaluating) { throw { type: 'Name', - message: "Recursive property reference for " + name, + message: 'Recursive property reference for ' + name, filename: this.fileInfo().filename, index: this.getIndex() }; } @@ -55,7 +55,7 @@ Property.prototype.eval = function (context) { return property; } else { throw { type: 'Name', - message: "Property '" + name + "' is undefined", + message: 'Property \'' + name + '\' is undefined', filename: this.currentFileInfo.filename, index: this.index }; } diff --git a/lib/less/tree/quoted.js b/lib/less/tree/quoted.js index e1ef8dce..c19d7414 100644 --- a/lib/less/tree/quoted.js +++ b/lib/less/tree/quoted.js @@ -1,6 +1,6 @@ -var Node = require("./node"), - Variable = require("./variable"), - Property = require("./property"); +var Node = require('./node'), + Variable = require('./variable'), + Property = require('./property'); var Quoted = function (str, content, escaped, index, currentFileInfo) { this.escaped = (escaped == null) ? true : escaped; @@ -12,7 +12,7 @@ var Quoted = function (str, content, escaped, index, currentFileInfo) { this.propRegex = /\$\{([\w-]+)\}/g; }; Quoted.prototype = new Node(); -Quoted.prototype.type = "Quoted"; +Quoted.prototype.type = 'Quoted'; Quoted.prototype.genCSS = function (context, output) { if (!this.escaped) { output.add(this.quote, this.fileInfo(), this.getIndex()); @@ -49,7 +49,7 @@ Quoted.prototype.eval = function (context) { }; Quoted.prototype.compare = function (other) { // when comparing quoted strings allow the quote to differ - if (other.type === "Quoted" && !this.escaped && !other.escaped) { + if (other.type === 'Quoted' && !this.escaped && !other.escaped) { return Node.numericCompare(this.value, other.value); } else { return other.toCSS && this.toCSS() === other.toCSS() ? 0 : undefined; diff --git a/lib/less/tree/ruleset.js b/lib/less/tree/ruleset.js index ccb23d53..89622afb 100644 --- a/lib/less/tree/ruleset.js +++ b/lib/less/tree/ruleset.js @@ -1,16 +1,16 @@ -var Node = require("./node"), - Declaration = require("./declaration"), - Keyword = require("./keyword"), - Comment = require("./comment"), - Paren = require("./paren"), - Selector = require("./selector"), - Element = require("./element"), - Anonymous = require("./anonymous"), - contexts = require("../contexts"), - globalFunctionRegistry = require("../functions/function-registry"), - defaultFunc = require("../functions/default"), - getDebugInfo = require("./debug-info"), - utils = require("../utils"); +var Node = require('./node'), + Declaration = require('./declaration'), + Keyword = require('./keyword'), + Comment = require('./comment'), + Paren = require('./paren'), + Selector = require('./selector'), + Element = require('./element'), + Anonymous = require('./anonymous'), + contexts = require('../contexts'), + globalFunctionRegistry = require('../functions/function-registry'), + defaultFunc = require('../functions/default'), + getDebugInfo = require('./debug-info'), + utils = require('../utils'); var Ruleset = function (selectors, rules, strictImports, visibilityInfo) { this.selectors = selectors; @@ -27,7 +27,7 @@ var Ruleset = function (selectors, rules, strictImports, visibilityInfo) { }; Ruleset.prototype = new Node(); -Ruleset.prototype.type = "Ruleset"; +Ruleset.prototype.type = 'Ruleset'; Ruleset.prototype.isRuleset = true; Ruleset.prototype.isRulesetLike = function() { return true; }; Ruleset.prototype.accept = function (visitor) { @@ -41,22 +41,47 @@ Ruleset.prototype.accept = function (visitor) { } }; Ruleset.prototype.eval = function (context) { - var thisSelectors = this.selectors, selectors, - selCnt, selector, i, hasOnePassingSelector = false; + var that = this, selectors, selCnt, selector, i, hasVariable, hasOnePassingSelector = false; - if (thisSelectors && (selCnt = thisSelectors.length)) { + if (this.selectors && (selCnt = this.selectors.length)) { selectors = new Array(selCnt); defaultFunc.error({ - type: "Syntax", - message: "it is currently only allowed in parametric mixin guards," + type: 'Syntax', + message: 'it is currently only allowed in parametric mixin guards,' }); + for (i = 0; i < selCnt; i++) { - selector = thisSelectors[i].eval(context); + selector = this.selectors[i].eval(context); + for (var j = 0; j < selector.elements.length; j++) { + if (selector.elements[j].isVariable) { + hasVariable = true; + break; + } + } selectors[i] = selector; if (selector.evaldCondition) { hasOnePassingSelector = true; } } + + if (hasVariable) { + var toParseSelectors = new Array(selCnt); + for (i = 0; i < selCnt; i++) { + selector = selectors[i]; + toParseSelectors[i] = selector.toCSS(context); + } + this.parse.parseNode( + toParseSelectors.join(','), + ["selectors"], + selectors[0].getIndex(), + selectors[0].fileInfo(), + function(err, result) { + if (result) { + selectors = utils.flattenArray(result); + } + }); + } + defaultFunc.reset(); } else { hasOnePassingSelector = true; @@ -121,7 +146,7 @@ Ruleset.prototype.eval = function (context) { // Evaluate mixin calls. for (i = 0; (rule = rsRules[i]); i++) { - if (rule.type === "MixinCall") { + if (rule.type === 'MixinCall') { /* jshint loopfunc:true */ rules = rule.eval(context).filter(function(r) { if ((r instanceof Declaration) && r.variable) { @@ -135,7 +160,7 @@ Ruleset.prototype.eval = function (context) { rsRules.splice.apply(rsRules, [i, 1].concat(rules)); i += rules.length - 1; ruleset.resetCache(); - } else if (rule.type === "VariableCall") { + } else if (rule.type === 'VariableCall') { /* jshint loopfunc:true */ rules = rule.eval(context).rules.filter(function(r) { if ((r instanceof Declaration) && r.variable) { @@ -162,7 +187,7 @@ Ruleset.prototype.eval = function (context) { // 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()) { + if (rule.selectors[0] && rule.selectors[0].isJustParentSelector()) { rsRules.splice(i--, 1); for (var j = 0; (subRule = rule.rules[j]); j++) { @@ -194,7 +219,7 @@ Ruleset.prototype.evalImports = function(context) { if (!rules) { return; } for (i = 0; i < rules.length; i++) { - if (rules[i].type === "Import") { + if (rules[i].type === 'Import') { importRules = rules[i].eval(context); if (importRules && (importRules.length || importRules.length === 0)) { rules.splice.apply(rules, [i, 1].concat(importRules)); @@ -249,11 +274,11 @@ Ruleset.prototype.variables = function () { // when evaluating variables in an import statement, imports have not been eval'd // so we need to go inside import statements. // guard against root being a string (in the case of inlined less) - if (r.type === "Import" && r.root && r.root.variables) { + if (r.type === 'Import' && r.root && r.root.variables) { var vars = r.root.variables(); for (var name in vars) { if (vars.hasOwnProperty(name)) { - hash[name] = vars[name]; + hash[name] = r.root.variable(name); } } } @@ -293,14 +318,22 @@ Ruleset.prototype.property = function (name) { return this.parseValue(decl); } }; +Ruleset.prototype.lastDeclaration = function () { + for (var i = this.rules.length; i > 0; i--) { + var decl = this.rules[i - 1]; + if (decl instanceof Declaration) { + return this.parseValue(decl); + } + } +}; Ruleset.prototype.parseValue = function(toParse) { var self = this; function transformDeclaration(decl) { if (decl.value instanceof Anonymous && !decl.parsed) { - if (typeof decl.value.value === "string") { + if (typeof decl.value.value === 'string') { this.parse.parseNode( decl.value.value, - ["value", "important"], + ['value', 'important'], decl.value.getIndex(), decl.fileInfo(), function(err, result) { @@ -402,8 +435,8 @@ Ruleset.prototype.genCSS = function (context, output) { context.tabLevel++; } - var tabRuleStr = context.compress ? '' : Array(context.tabLevel + 1).join(" "), - tabSetStr = context.compress ? '' : Array(context.tabLevel).join(" "), + var tabRuleStr = context.compress ? '' : Array(context.tabLevel + 1).join(' '), + tabSetStr = context.compress ? '' : Array(context.tabLevel).join(' '), sep; var charsetNodeIndex = 0; @@ -418,7 +451,7 @@ Ruleset.prototype.genCSS = function (context, output) { ruleNodes.splice(charsetNodeIndex, 0, rule); charsetNodeIndex++; importNodeIndex++; - } else if (rule.type === "Import") { + } else if (rule.type === 'Import') { ruleNodes.splice(importNodeIndex, 0, rule); importNodeIndex++; } else { @@ -511,7 +544,13 @@ Ruleset.prototype.joinSelector = function (paths, context, selector) { } else { var insideParent = new Array(elementsToPak.length); for (j = 0; j < elementsToPak.length; j++) { - insideParent[j] = new Element(null, elementsToPak[j], originalElement._index, originalElement._fileInfo); + insideParent[j] = new Element( + null, + elementsToPak[j], + originalElement.isVariable, + originalElement._index, + originalElement._fileInfo + ); } replacementParen = new Paren(new Selector(insideParent)); } @@ -520,7 +559,7 @@ Ruleset.prototype.joinSelector = function (paths, context, selector) { function createSelector(containedElement, originalElement) { var element, selector; - element = new Element(null, containedElement, originalElement._index, originalElement._fileInfo); + element = new Element(null, containedElement, originalElement.isVariable, originalElement._index, originalElement._fileInfo); selector = new Selector([element]); return selector; } @@ -545,7 +584,8 @@ Ruleset.prototype.joinSelector = function (paths, context, selector) { } if (addPath.length > 0) { - // /deep/ is a combinator that is valid without anything in front of it + // /deep/ is a CSS4 selector - (removed, so should deprecate) + // that is valid without anything in front of it // so if the & does not have a combinator that is "" or " " then // and there is a combinator on the parent, then grab that. // this also allows + a { & .b { .a & { ... though not sure why you would want to do that @@ -554,7 +594,13 @@ 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._fileInfo)); + newJoinedSelector.elements.push(new Element( + combinator, + parentEl.value, + replacedElement.isVariable, + replacedElement._index, + replacedElement._fileInfo + )); newJoinedSelector.elements = newJoinedSelector.elements.concat(addPath[0].elements.slice(1)); } @@ -648,7 +694,7 @@ Ruleset.prototype.joinSelector = function (paths, context, selector) { for (i = 0; (el = inSelector.elements[i]); i++) { // non parent reference elements just get added - if (el.value !== "&") { + if (el.value !== '&') { var nestedSelector = findNestedSelector(el); if (nestedSelector != null) { // merge the current list of non parent selector elements @@ -688,7 +734,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._fileInfo)); + sel[0].elements.push(new Element(el.combinator, '', el.isVariable, el._index, el._fileInfo)); } selectorsMultiplied.push(sel); } diff --git a/lib/less/tree/selector.js b/lib/less/tree/selector.js index fb866a9b..16ac803c 100644 --- a/lib/less/tree/selector.js +++ b/lib/less/tree/selector.js @@ -1,6 +1,6 @@ -var Node = require("./node"), - Element = require("./element"), - LessError = require("../less-error"); +var Node = require('./node'), + Element = require('./element'), + LessError = require('../less-error'); var Selector = function (elements, extendList, condition, index, currentFileInfo, visibilityInfo) { this.extendList = extendList; @@ -14,7 +14,7 @@ var Selector = function (elements, extendList, condition, index, currentFileInfo this.setParent(this.elements, this); }; Selector.prototype = new Node(); -Selector.prototype.type = "Selector"; +Selector.prototype.type = 'Selector'; Selector.prototype.accept = function (visitor) { if (this.elements) { this.elements = visitor.visitArray(this.elements); @@ -35,10 +35,13 @@ Selector.prototype.createDerived = function(elements, extendList, evaldCondition return newSelector; }; Selector.prototype.getElements = function(els) { - if (typeof els === "string") { + if (!els) { + return [new Element('', '&', false, this._index, this._fileInfo)]; + } + if (typeof els === 'string') { this.parse.parseNode( els, - ["selector"], + ['selector'], this._index, this._fileInfo, function(err, result) { @@ -54,7 +57,7 @@ Selector.prototype.getElements = function(els) { return els; }; Selector.prototype.createEmptySelectors = function() { - var el = new Element('', '&', this._index, this._fileInfo), + var el = new Element('', '&', false, this._index, this._fileInfo), sels = [new Selector([el], null, null, this._index, this._fileInfo)]; sels[0].mediaEmpty = true; return sels; @@ -85,10 +88,10 @@ Selector.prototype.mixinElements = function() { var elements = this.elements.map( function(v) { return v.combinator.value + (v.value.value || v.value); - }).join("").match(/[,&#\*\.\w-]([\w-]|(\\.))*/g); + }).join('').match(/[,&#\*\.\w-]([\w-]|(\\.))*/g); if (elements) { - if (elements[0] === "&") { + if (elements[0] === '&') { elements.shift(); } } else { @@ -114,7 +117,7 @@ Selector.prototype.eval = function (context) { }; Selector.prototype.genCSS = function (context, output) { var i, element; - if ((!context || !context.firstSelector) && this.elements[0].combinator.value === "") { + if ((!context || !context.firstSelector) && this.elements[0].combinator.value === '') { output.add(' ', this.fileInfo(), this.getIndex()); } for (i = 0; i < this.elements.length; i++) { diff --git a/lib/less/tree/unicode-descriptor.js b/lib/less/tree/unicode-descriptor.js index ff87b54d..5fd846b2 100644 --- a/lib/less/tree/unicode-descriptor.js +++ b/lib/less/tree/unicode-descriptor.js @@ -1,9 +1,9 @@ -var Node = require("./node"); +var Node = require('./node'); var UnicodeDescriptor = function (value) { this.value = value; }; UnicodeDescriptor.prototype = new Node(); -UnicodeDescriptor.prototype.type = "UnicodeDescriptor"; +UnicodeDescriptor.prototype.type = 'UnicodeDescriptor'; module.exports = UnicodeDescriptor; diff --git a/lib/less/tree/unit.js b/lib/less/tree/unit.js index 9b1ea9fc..91c2e27a 100644 --- a/lib/less/tree/unit.js +++ b/lib/less/tree/unit.js @@ -1,6 +1,6 @@ -var Node = require("./node"), - unitConversions = require("../data/unit-conversions"), - utils = require("../utils"); +var Node = require('./node'), + unitConversions = require('../data/unit-conversions'), + utils = require('../utils'); var Unit = function (numerator, denominator, backupUnit) { this.numerator = numerator ? utils.copyArray(numerator).sort() : []; @@ -13,7 +13,7 @@ var Unit = function (numerator, denominator, backupUnit) { }; Unit.prototype = new Node(); -Unit.prototype.type = "Unit"; +Unit.prototype.type = 'Unit'; Unit.prototype.clone = function () { return new Unit(utils.copyArray(this.numerator), utils.copyArray(this.denominator), this.backupUnit); }; @@ -29,9 +29,9 @@ Unit.prototype.genCSS = function (context, output) { } }; Unit.prototype.toString = function () { - var i, returnStr = this.numerator.join("*"); + var i, returnStr = this.numerator.join('*'); for (i = 0; i < this.denominator.length; i++) { - returnStr += "/" + this.denominator[i]; + returnStr += '/' + this.denominator[i]; } return returnStr; }; diff --git a/lib/less/tree/url.js b/lib/less/tree/url.js index fa0d4c87..40d342bf 100644 --- a/lib/less/tree/url.js +++ b/lib/less/tree/url.js @@ -1,4 +1,4 @@ -var Node = require("./node"); +var Node = require('./node'); var URL = function (val, index, currentFileInfo, isEvald) { this.value = val; @@ -7,14 +7,14 @@ var URL = function (val, index, currentFileInfo, isEvald) { this.isEvald = isEvald; }; URL.prototype = new Node(); -URL.prototype.type = "Url"; +URL.prototype.type = 'Url'; URL.prototype.accept = function (visitor) { this.value = visitor.visit(this.value); }; URL.prototype.genCSS = function (context, output) { - output.add("url("); + output.add('url('); this.value.genCSS(context, output); - output.add(")"); + output.add(')'); }; URL.prototype.eval = function (context) { var val = this.value.eval(context), @@ -24,11 +24,11 @@ URL.prototype.eval = function (context) { // Add the base path if the URL is relative rootpath = this.fileInfo() && this.fileInfo().rootpath; if (rootpath && - typeof val.value === "string" && + typeof val.value === 'string' && context.isPathRelative(val.value)) { if (!val.quote) { - rootpath = rootpath.replace(/[\(\)'"\s]/g, function(match) { return "\\" + match; }); + rootpath = rootpath.replace(/[\(\)'"\s]/g, function(match) { return '\\' + match; }); } val.value = rootpath + val.value; } diff --git a/lib/less/tree/value.js b/lib/less/tree/value.js index 1e2d9b0b..cd3fa390 100644 --- a/lib/less/tree/value.js +++ b/lib/less/tree/value.js @@ -1,8 +1,8 @@ -var Node = require("./node"); +var Node = require('./node'); var Value = function (value) { if (!value) { - throw new Error("Value requires an array argument"); + throw new Error('Value requires an array argument'); } if (!Array.isArray(value)) { this.value = [ value ]; @@ -12,7 +12,7 @@ var Value = function (value) { } }; Value.prototype = new Node(); -Value.prototype.type = "Value"; +Value.prototype.type = 'Value'; Value.prototype.accept = function (visitor) { if (this.value) { this.value = visitor.visitArray(this.value); diff --git a/lib/less/tree/variable-call.js b/lib/less/tree/variable-call.js index b24fd7d5..f1b4f0c1 100644 --- a/lib/less/tree/variable-call.js +++ b/lib/less/tree/variable-call.js @@ -1,14 +1,36 @@ -var Node = require("./node"), - Variable = require("./variable"); +var Node = require('./node'), + Variable = require('./variable'), + Ruleset = require('./ruleset'), + DetachedRuleset = require('./detached-ruleset'), + LessError = require('../less-error'); -var VariableCall = function (variable) { +var VariableCall = function (variable, index, currentFileInfo) { this.variable = variable; + this._index = index; + this._fileInfo = currentFileInfo; this.allowRoot = true; }; VariableCall.prototype = new Node(); -VariableCall.prototype.type = "VariableCall"; +VariableCall.prototype.type = 'VariableCall'; VariableCall.prototype.eval = function (context) { - var detachedRuleset = new Variable(this.variable).eval(context); - return detachedRuleset.callEval(context); + var rules, detachedRuleset = new Variable(this.variable, this.getIndex(), this.fileInfo()).eval(context), + error = new LessError({message: 'Could not evaluate variable call ' + this.variable}); + + if (!detachedRuleset.ruleset) { + if (Array.isArray(detachedRuleset)) { + rules = detachedRuleset; + } + else if (Array.isArray(detachedRuleset.value)) { + rules = detachedRuleset.value; + } + else { + throw error; + } + detachedRuleset = new DetachedRuleset(new Ruleset('', rules)); + } + if (detachedRuleset.ruleset) { + return detachedRuleset.callEval(context); + } + throw error; }; module.exports = VariableCall; diff --git a/lib/less/tree/variable.js b/lib/less/tree/variable.js index f590711f..9ead289c 100644 --- a/lib/less/tree/variable.js +++ b/lib/less/tree/variable.js @@ -1,4 +1,5 @@ -var Node = require("./node"); +var Node = require('./node'), + Call = require('./call'); var Variable = function (name, index, currentFileInfo) { this.name = name; @@ -6,7 +7,7 @@ var Variable = function (name, index, currentFileInfo) { this._fileInfo = currentFileInfo; }; Variable.prototype = new Node(); -Variable.prototype.type = "Variable"; +Variable.prototype.type = 'Variable'; Variable.prototype.eval = function (context) { var variable, name = this.name; @@ -16,7 +17,7 @@ Variable.prototype.eval = function (context) { if (this.evaluating) { throw { type: 'Name', - message: "Recursive variable definition for " + name, + message: 'Recursive variable definition for ' + name, filename: this.fileInfo().filename, index: this.getIndex() }; } @@ -30,7 +31,13 @@ Variable.prototype.eval = function (context) { var importantScope = context.importantScope[context.importantScope.length - 1]; importantScope.important = v.important; } - return v.value.eval(context); + // If in calc, wrap vars in a function call to cascade evaluate args first + if (context.inCalc) { + return (new Call('_SELF', [v.value])).eval(context); + } + else { + return v.value.eval(context); + } } }); if (variable) { @@ -38,7 +45,7 @@ Variable.prototype.eval = function (context) { return variable; } else { throw { type: 'Name', - message: "variable " + name + " is undefined", + message: 'variable ' + name + ' is undefined', filename: this.fileInfo().filename, index: this.getIndex() }; } diff --git a/lib/less/utils.js b/lib/less/utils.js index c90d6e69..1c830e7c 100644 --- a/lib/less/utils.js +++ b/lib/less/utils.js @@ -1,5 +1,5 @@ /* jshint proto: true */ -module.exports = { +var utils = { getLocation: function(index, inputStream) { var n = index + 1, line = null, @@ -10,7 +10,7 @@ module.exports = { } if (typeof index === 'number') { - line = (inputStream.slice(0, index).match(/\n/g) || "").length; + line = (inputStream.slice(0, index).match(/\n/g) || '').length; } return { @@ -65,5 +65,21 @@ module.exports = { } } return obj1; + }, + flattenArray: function(arr, result) { + result = result || []; + for (var i = 0, length = arr.length; i < length; i++) { + var value = arr[i]; + if (Array.isArray(value)) { + utils.flattenArray(value, result); + } else { + if (value !== undefined) { + result.push(value); + } + } + } + return result; } }; + +module.exports = utils; \ No newline at end of file diff --git a/lib/less/visitors/extend-visitor.js b/lib/less/visitors/extend-visitor.js index 5c412882..be13f824 100644 --- a/lib/less/visitors/extend-visitor.js +++ b/lib/less/visitors/extend-visitor.js @@ -1,7 +1,7 @@ -var tree = require("../tree"), - Visitor = require("./visitor"), - logger = require("../logger"), - utils = require("../utils"); +var tree = require('../tree'), + Visitor = require('./visitor'), + logger = require('../logger'), + utils = require('../utils'); /* jshint loopfunc:true */ @@ -110,7 +110,7 @@ ProcessExtendsVisitor.prototype = { extendList.filter(function(extend) { return !extend.hasFoundMatches && extend.parent_ids.length == 1; }).forEach(function(extend) { - var selector = "_unknown_"; + var selector = '_unknown_'; try { selector = extend.selector.toCSS({}); } @@ -118,7 +118,7 @@ ProcessExtendsVisitor.prototype = { if (!indices[extend.index + ' ' + selector]) { indices[extend.index + ' ' + selector] = true; - logger.warn("extend '" + selector + "' has no matches"); + logger.warn('extend \'' + selector + '\' has no matches'); } }); }, @@ -177,7 +177,7 @@ ProcessExtendsVisitor.prototype = { extendsToAdd.push(newExtend); newExtend.ruleset = targetExtend.ruleset; - //remember its parents for circular references + // remember its parents for circular references newExtend.parent_ids = newExtend.parent_ids.concat(targetExtend.parent_ids, extend.parent_ids); // only process the selector once.. if we have :extend(.a,.b) then multiple @@ -197,15 +197,15 @@ ProcessExtendsVisitor.prototype = { // may no longer be needed. this.extendChainCount++; if (iterationCount > 100) { - var selectorOne = "{unable to calculate}"; - var selectorTwo = "{unable to calculate}"; + var selectorOne = '{unable to calculate}'; + var selectorTwo = '{unable to calculate}'; try { selectorOne = extendsToAdd[0].selfSelectors[0].toCSS(); selectorTwo = extendsToAdd[0].selector.toCSS(); } catch (e) {} - throw { message: "extend circular reference detected. One of the circular extends is currently:" + - selectorOne + ":extend(" + selectorTwo + ")"}; + throw { message: 'extend circular reference detected. One of the circular extends is currently:' + + selectorOne + ':extend(' + selectorTwo + ')'}; } // now process the new extends on the existing rules so that we can handle a extending b extending c extending @@ -329,7 +329,7 @@ ProcessExtendsVisitor.prototype = { return matches; }, isElementValuesEqual: function(elementValue1, elementValue2) { - if (typeof elementValue1 === "string" || typeof elementValue2 === "string") { + if (typeof elementValue1 === 'string' || typeof elementValue2 === 'string') { return elementValue1 === elementValue2; } if (elementValue1 instanceof tree.Attribute) { @@ -385,6 +385,7 @@ ProcessExtendsVisitor.prototype = { firstElement = new tree.Element( match.initialCombinator, replacementSelector.elements[0].value, + replacementSelector.elements[0].isVariable, replacementSelector.elements[0].getIndex(), replacementSelector.elements[0].fileInfo() ); diff --git a/lib/less/visitors/import-visitor.js b/lib/less/visitors/import-visitor.js index 9fe266b0..25cc6810 100644 --- a/lib/less/visitors/import-visitor.js +++ b/lib/less/visitors/import-visitor.js @@ -1,7 +1,7 @@ -var contexts = require("../contexts"), - Visitor = require("./visitor"), - ImportSequencer = require("./import-sequencer"), - utils = require("../utils"); +var contexts = require('../contexts'), + Visitor = require('./visitor'), + ImportSequencer = require('./import-sequencer'), + utils = require('../utils'); var ImportVisitor = function(importer, finish) { @@ -151,14 +151,14 @@ ImportVisitor.prototype = { } }, visitDeclaration: function (declNode, visitArgs) { - if (declNode.value.type === "DetachedRuleset") { + if (declNode.value.type === 'DetachedRuleset') { this.context.frames.unshift(declNode); } else { visitArgs.visitDeeper = false; } }, visitDeclarationOut: function(declNode) { - if (declNode.value.type === "DetachedRuleset") { + if (declNode.value.type === 'DetachedRuleset') { this.context.frames.shift(); } }, diff --git a/lib/less/visitors/index.js b/lib/less/visitors/index.js index 85837b00..2176e49c 100644 --- a/lib/less/visitors/index.js +++ b/lib/less/visitors/index.js @@ -1,7 +1,7 @@ var visitors = { - Visitor: require("./visitor"), + Visitor: require('./visitor'), ImportVisitor: require('./import-visitor'), - MarkVisibleSelectorsVisitor: require("./set-tree-visibility-visitor"), + MarkVisibleSelectorsVisitor: require('./set-tree-visibility-visitor'), ExtendVisitor: require('./extend-visitor'), JoinSelectorVisitor: require('./join-selector-visitor'), ToCSSVisitor: require('./to-css-visitor') diff --git a/lib/less/visitors/join-selector-visitor.js b/lib/less/visitors/join-selector-visitor.js index c1fcd0cf..1ea83052 100644 --- a/lib/less/visitors/join-selector-visitor.js +++ b/lib/less/visitors/join-selector-visitor.js @@ -1,4 +1,4 @@ -var Visitor = require("./visitor"); +var Visitor = require('./visitor'); var JoinSelectorVisitor = function() { this.contexts = [[]]; diff --git a/lib/less/visitors/to-css-visitor.js b/lib/less/visitors/to-css-visitor.js index 861242b1..6b6d3f1c 100644 --- a/lib/less/visitors/to-css-visitor.js +++ b/lib/less/visitors/to-css-visitor.js @@ -1,5 +1,5 @@ -var tree = require("../tree"), - Visitor = require("./visitor"); +var tree = require('../tree'), + Visitor = require('./visitor'); var CSSVisitorUtils = function(context) { this._visitor = new Visitor(this); @@ -180,13 +180,13 @@ ToCSSVisitor.prototype = { return; } - if (atRuleNode.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 atrule would // be considered illegal css as it has to be on the first line if (this.charset) { if (atRuleNode.debugInfo) { - var comment = new tree.Comment("/* " + atRuleNode.toCSS(this._context).replace(/\n/g, "") + " */\n"); + var comment = new tree.Comment('/* ' + atRuleNode.toCSS(this._context).replace(/\n/g, '') + ' */\n'); comment.debugInfo = atRuleNode.debugInfo; return this._visitor.visit(comment); } @@ -206,15 +206,15 @@ ToCSSVisitor.prototype = { for (var i = 0; i < rules.length; i++) { var ruleNode = rules[i]; if (isRoot && ruleNode instanceof tree.Declaration && !ruleNode.variable) { - throw { message: "Properties must be inside selector blocks. They cannot be in the root", + throw { message: 'Properties must be inside selector blocks. They cannot be in the root', index: ruleNode.getIndex(), filename: ruleNode.fileInfo() && ruleNode.fileInfo().filename}; } if (ruleNode instanceof tree.Call) { - throw { message: "Function '" + ruleNode.name + "' is undefined", + throw { message: 'Function \'' + ruleNode.name + '\' is undefined', 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", + throw { message: ruleNode.type + ' node returned by a function is not valid here', index: ruleNode.getIndex(), filename: ruleNode.fileInfo() && ruleNode.fileInfo().filename}; } } diff --git a/lib/less/visitors/visitor.js b/lib/less/visitors/visitor.js index cf67040c..e857eb28 100644 --- a/lib/less/visitors/visitor.js +++ b/lib/less/visitors/visitor.js @@ -1,4 +1,4 @@ -var tree = require("../tree"); +var tree = require('../tree'); var _visitArgs = { visitDeeper: true }, _hasIndexed = false; @@ -14,14 +14,14 @@ function indexNodeTypes(parent, ticker) { /* eslint guard-for-in: 0 */ child = parent[key]; switch (typeof child) { - case "function": + 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": + case 'object': ticker = indexNodeTypes(child, ticker); break; @@ -32,7 +32,8 @@ function indexNodeTypes(parent, ticker) { var Visitor = function(implementation) { this._implementation = implementation; - this._visitFnCache = []; + this._visitInCache = {}; + this._visitOutCache = {}; if (!_hasIndexed) { indexNodeTypes(tree, 1); @@ -48,31 +49,32 @@ Visitor.prototype = { var nodeTypeIndex = node.typeIndex; if (!nodeTypeIndex) { + // MixinCall args aren't a node type? + if (node.value && node.value.typeIndex) { + this.visit(node.value); + } return node; } - var visitFnCache = this._visitFnCache, - impl = this._implementation, - aryIndx = nodeTypeIndex << 1, - outAryIndex = aryIndx | 1, - func = visitFnCache[aryIndx], - funcOut = visitFnCache[outAryIndex], + var impl = this._implementation, + func = this._visitInCache[nodeTypeIndex], + funcOut = this._visitOutCache[nodeTypeIndex], visitArgs = _visitArgs, fnName; visitArgs.visitDeeper = true; if (!func) { - fnName = "visit" + node.type; + fnName = 'visit' + node.type; func = impl[fnName] || _noop; - funcOut = impl[fnName + "Out"] || _noop; - visitFnCache[aryIndx] = func; - visitFnCache[outAryIndex] = funcOut; + funcOut = impl[fnName + 'Out'] || _noop; + this._visitInCache[nodeTypeIndex] = func; + this._visitOutCache[nodeTypeIndex] = funcOut; } if (func !== _noop) { var newNode = func.call(impl, node, visitArgs); - if (impl.isReplacing) { + if (node && impl.isReplacing) { node = newNode; } } diff --git a/package-lock.json b/package-lock.json index d1bf9489..9b5c3c5b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,19 +1,9 @@ { "name": "less", - "version": "3.0.2", + "version": "3.0.4", "lockfileVersion": 1, "requires": true, "dependencies": { - "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" - } - }, "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", @@ -400,9 +390,9 @@ "integrity": "sha1-+GzWzvT1MAyOY+B6TVEvZfv/RTE=", "dev": true, "requires": { - "JSONStream": "1.3.1", "combine-source-map": "0.7.2", "defined": "1.0.0", + "JSONStream": "1.3.1", "through2": "2.0.3", "umd": "3.0.1" } @@ -430,7 +420,6 @@ "integrity": "sha1-CJo0Y69Y0OSNjNQHCz90ZU1avKk=", "dev": true, "requires": { - "JSONStream": "1.3.1", "assert": "1.4.1", "browser-pack": "6.0.2", "browser-resolve": "1.11.2", @@ -452,6 +441,7 @@ "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", @@ -565,12 +555,18 @@ "integrity": "sha1-BxPLdYckemMqnwjPG9FpuHi2Koo=", "dev": true, "requires": { - "JSONStream": "0.10.0", "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", @@ -580,12 +576,6 @@ "jsonparse": "0.0.5", "through": "2.3.8" } - }, - "jsonparse": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-0.0.5.tgz", - "integrity": "sha1-MwVCrT8KZUZlt3jz6y2an6UHrGQ=", - "dev": true } } }, @@ -688,6 +678,12 @@ "map-obj": "1.0.1" } }, + "caniuse-db": { + "version": "1.0.30000858", + "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000858.tgz", + "integrity": "sha1-FTyTSDUGQdxiTRUOwXQmLCrZheU=", + "dev": true + }, "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", @@ -1206,6 +1202,12 @@ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", "dev": true }, + "electron-to-chromium": { + "version": "1.3.50", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.50.tgz", + "integrity": "sha1-dDi3b5K0G5GfP73TUPvQdX2s3fc=", + "dev": true + }, "elliptic": { "version": "6.4.0", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz", @@ -2635,6 +2637,14 @@ } } }, + "string_decoder": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "5.0.1" + } + }, "string-width": { "version": "1.0.2", "bundled": true, @@ -2645,14 +2655,6 @@ "strip-ansi": "3.0.1" } }, - "string_decoder": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "requires": { - "safe-buffer": "5.0.1" - } - }, "stringstream": { "version": "0.0.5", "bundled": true, @@ -2995,6 +2997,66 @@ } } }, + "grunt-cli": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/grunt-cli/-/grunt-cli-1.2.0.tgz", + "integrity": "sha1-VisRnrsGndtGSs4oRVAb6Xs1tqg=", + "dev": true, + "requires": { + "findup-sync": "0.3.0", + "grunt-known-options": "1.1.0", + "nopt": "3.0.6", + "resolve": "1.1.7" + }, + "dependencies": { + "findup-sync": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.3.0.tgz", + "integrity": "sha1-N5MKpdgWt3fANEXhlmzGeQpMCxY=", + "dev": true, + "requires": { + "glob": "5.0.15" + } + }, + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "requires": { + "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" + } + }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "dev": true, + "requires": { + "abbrev": "1.1.1" + } + }, + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + } + } + }, "grunt-contrib-clean": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/grunt-contrib-clean/-/grunt-contrib-clean-1.1.0.tgz", @@ -3141,6 +3203,12 @@ "eslint": "3.19.0" } }, + "grunt-known-options": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/grunt-known-options/-/grunt-known-options-1.1.0.tgz", + "integrity": "sha1-pCdO6zL6dl2lp6OxcSYXzjsUQUk=", + "dev": true + }, "grunt-legacy-log": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/grunt-legacy-log/-/grunt-legacy-log-0.1.3.tgz", @@ -3585,10 +3653,10 @@ "integrity": "sha1-wDv04BywhtW15azorQr+eInWOMM=", "dev": true, "requires": { - "JSONStream": "1.3.1", "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", @@ -3812,6 +3880,12 @@ "integrity": "sha1-AIw6f+Hpa9DYTiYOofoXg0V/ecI=", "dev": true }, + "js-base64": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.5.tgz", + "integrity": "sha512-aUnNwqMOXw3yvErjMPSQu6qIIzUmT1e5KcU1OZxRDU1g/am6mzBvcrmLAYwzmB59BHPrh5/tKaiF4OPhqRWESQ==", + "dev": true + }, "js-tokens": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", @@ -3885,6 +3959,16 @@ "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", @@ -3945,6 +4029,75 @@ "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", "dev": true }, + "less-plugin-autoprefix": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/less-plugin-autoprefix/-/less-plugin-autoprefix-1.5.1.tgz", + "integrity": "sha1-vKTlsuSMrGlloXgxQuOzLDwAzgc=", + "dev": true, + "requires": { + "autoprefixer": "6.7.7", + "postcss": "5.2.18" + }, + "dependencies": { + "autoprefixer": { + "version": "6.7.7", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-6.7.7.tgz", + "integrity": "sha1-Hb0cg1ZY41zj+ZhAmdsAWFx4IBQ=", + "dev": true, + "requires": { + "browserslist": "1.7.7", + "caniuse-db": "1.0.30000858", + "normalize-range": "0.1.2", + "num2fraction": "1.2.2", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" + } + }, + "browserslist": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz", + "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", + "dev": true, + "requires": { + "caniuse-db": "1.0.30000858", + "electron-to-chromium": "1.3.50" + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.5", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, "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", @@ -4176,7 +4329,6 @@ "integrity": "sha1-IyFYM/HaE/1gbMuAh7RIUty4If0=", "dev": true, "requires": { - "JSONStream": "1.3.1", "browser-resolve": "1.11.2", "cached-path-relative": "1.0.1", "concat-stream": "1.5.2", @@ -4184,6 +4336,7 @@ "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", @@ -4267,6 +4420,12 @@ "remove-trailing-separator": "1.1.0" } }, + "normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", + "dev": true + }, "npm-run-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-1.0.0.tgz", @@ -4276,6 +4435,12 @@ "path-key": "1.0.0" } }, + "num2fraction": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", + "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=", + "dev": true + }, "number-is-nan": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", @@ -4329,7 +4494,7 @@ }, "onetime": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", "dev": true }, @@ -4749,6 +4914,12 @@ } } }, + "postcss-value-parser": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz", + "integrity": "sha1-h/OPnxj3dKSrTIojL1xc6IcqnRU=", + "dev": true + }, "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", @@ -5470,6 +5641,15 @@ "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", @@ -5481,15 +5661,6 @@ "strip-ansi": "3.0.1" } }, - "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" - } - }, "stringstream": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", diff --git a/package.json b/package.json index 4da8c84d..ff1cb4c1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "less", - "version": "3.0.4", + "version": "3.5.3", "description": "Leaner CSS", "homepage": "http://lesscss.org", "author": { @@ -66,9 +66,10 @@ "grunt-shell": "^1.3.0", "import-module": "file:test/import-module", "jit-grunt": "^0.10.0", + "less-plugin-autoprefix": "^1.5.1", "less-plugin-clean-css": "^1.5.1", "performance-now": "^0.2.0", - "phantomjs-prebuilt": "^2.1.7", + "phantomjs-prebuilt": "^2.1.16", "phin": "^2.2.3", "promise": "^7.1.1", "time-grunt": "^1.3.0" diff --git a/test/.eslintrc.json b/test/.eslintrc.json new file mode 100644 index 00000000..2be2e791 --- /dev/null +++ b/test/.eslintrc.json @@ -0,0 +1,9 @@ +{ + "env": { + "node": true, + "browser": true + }, + "parserOptions": { + "ecmaVersion": 6 + } +} diff --git a/test/browser/common.js b/test/browser/common.js index 9fd69fff..fe83fea2 100644 --- a/test/browser/common.js +++ b/test/browser/common.js @@ -111,7 +111,7 @@ ieFormat = function(text) { styleNode.innerText = text; } } catch (e) { - throw new Error("Couldn't reassign styleSheet.cssText."); + throw new Error('Couldn\'t reassign styleSheet.cssText.'); } var transformedText = styleNode.styleSheet ? styleNode.styleSheet.cssText : styleNode.innerText; headNode.removeChild(styleNode); @@ -119,9 +119,9 @@ ieFormat = function(text) { }; testSheet = function (sheet) { - it(sheet.id + " should match the expected output", function (done) { - var lessOutputId = sheet.id.replace("original-", ""), - expectedOutputId = "expected-" + lessOutputId, + it(sheet.id + ' should match the expected output', function (done) { + var lessOutputId = sheet.id.replace('original-', ''), + expectedOutputId = 'expected-' + lessOutputId, lessOutputObj, lessOutput, expectedOutputHref = document.getElementById(expectedOutputId).href, @@ -136,8 +136,8 @@ testSheet = function (sheet) { expectedOutput .then(function (text) { - if (window.navigator.userAgent.indexOf("MSIE") >= 0 || - window.navigator.userAgent.indexOf("Trident/") >= 0) { + if (window.navigator.userAgent.indexOf('MSIE') >= 0 || + window.navigator.userAgent.indexOf('Trident/') >= 0) { text = ieFormat(text); } expect(lessOutput).toEqual(text); @@ -169,10 +169,10 @@ waitFor = function (waitFunc) { }; testErrorSheet = function (sheet) { - it(sheet.id + " should match an error", function (done) { + it(sheet.id + ' should match an error', function (done) { var lessHref = sheet.href, - id = "less-error-message:" + extractId(lessHref), - errorHref = lessHref.replace(/.less$/, ".txt"), + id = 'less-error-message:' + extractId(lessHref), + errorHref = lessHref.replace(/.less$/, '.txt'), errorFile = loadFile(errorHref), actualErrorElement, actualErrorMsg; @@ -183,35 +183,35 @@ testErrorSheet = function (sheet) { return actualErrorElement !== null; }).then(function () { var innerText = (actualErrorElement.innerHTML - .replace(/

    |<\/?p>||<\/a>|