diff --git a/bin/lessc b/bin/lessc index 4d3c190c..25cab56c 100755 --- a/bin/lessc +++ b/bin/lessc @@ -19,25 +19,9 @@ var less = require('../lib/less-node'), args = process.argv.slice(1), silent = false, verbose = false, - options = { - depends: false, - compress: false, - max_line_len: -1, - lint: false, - paths: [], - color: true, - strictImports: false, - insecure: false, - rootpath: '', - relativeUrls: false, - ieCompat: true, - strictMath: false, - strictUnits: false, - globalVars: null, - modifyVars: null, - urlArgs: '', - plugins: plugins - }; + options = require('../lib/less/default-options')(); + +options.plugins = plugins; if (less.options) { for (var i = 0, keys = Object.keys(options); i < keys.length; i++) { @@ -431,8 +415,8 @@ function processPluginQueue() { case 'no-color': options.color = false; break; - case 'no-ie-compat': - options.ieCompat = false; + case 'ie-compat': + options.ieCompat = true; break; case 'js': options.javascriptEnabled = true; @@ -475,10 +459,12 @@ function processPluginQueue() { sourceMapOptions.sourceMapBasepath = match[2]; } break; + case 'source-map-inline': case 'source-map-map-inline': sourceMapFileInline = true; options.sourceMap = true; break; + case 'source-map-include-source': case 'source-map-less-inline': sourceMapOptions.outputSourceFiles = true; break; diff --git a/lib/less-browser/bootstrap.js b/lib/less-browser/bootstrap.js index 72b02c16..e1a35ba6 100644 --- a/lib/less-browser/bootstrap.js +++ b/lib/less-browser/bootstrap.js @@ -5,13 +5,27 @@ */ /*global window, document */ -// TODO - consider switching this out for a recommendation for this polyfill: +// TODO - consider switching this out for a recommendation for this polyfill? // require("promise/polyfill"); -var options = window.less || {}; +var options = require('../less/default-options'); + +if (window.less) { + for (key in window.less) { + if (window.less.hasOwnProperty(key)) { + options[key] = window.less[key]; + } + } +} require("./add-default-options")(window, options); +options.plugins = options.plugins || []; + +if (window.LESS_PLUGINS) { + options.plugins = options.plugins.concat(window.LESS_PLUGINS); +} + var less = module.exports = require("./index")(window, options); window.less = less; @@ -32,7 +46,7 @@ if (options.onReady) { if (/!watch/.test(window.location.hash)) { less.watch(); } - // Simulate synchronous stylesheet loading by blocking page rendering + // Simulate synchronous stylesheet loading by hiding page rendering if (!options.async) { css = 'body { display: none !important }'; head = document.head || document.getElementsByTagName('head')[0]; diff --git a/lib/less-node/index.js b/lib/less-node/index.js index 4e379845..153f54b5 100644 --- a/lib/less-node/index.js +++ b/lib/less-node/index.js @@ -12,7 +12,7 @@ less.PluginLoader = require("./plugin-loader"); less.fs = require("./fs"); less.FileManager = FileManager; less.UrlFileManager = UrlFileManager; -less.options = less.options || {}; +less.options = require('../less/default-options'); // provide image-size functionality require('./image-size')(less.environment); diff --git a/lib/less-node/lessc-helper.js b/lib/less-node/lessc-helper.js index e9fbd843..f283421c 100644 --- a/lib/less-node/lessc-helper.js +++ b/lib/less-node/lessc-helper.js @@ -26,42 +26,42 @@ var lessc_helper = { console.log("If source is set to `-' (dash or hyphen-minus), input is read from stdin."); console.log(""); console.log("options:"); - console.log(" -h, --help Prints help (this message) and exit."); - console.log(" --include-path=PATHS Sets include paths. Separated by `:'. `;' also supported on windows."); - console.log(" -M, --depends Outputs a makefile import dependency list to stdout."); - console.log(" --no-color Disables colorized output."); - console.log(" --no-ie-compat Disables IE compatibility checks."); - console.log(" --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-less-inline Puts the less files into the map instead of referencing them."); - console.log(" --source-map-map-inline Puts the map (and any less files) as a base64 data uri into the output css file."); - console.log(" --source-map-url=URL Sets a custom URL to map file, for sourceMappingURL comment"); - console.log(" in generated CSS file."); - console.log(" -rp, --rootpath=URL Sets rootpath for url rewriting in relative imports and urls"); - console.log(" Works with or without the relative-urls option."); - console.log(" -ru, --relative-urls Re-writes relative urls to the base less file."); - console.log(" -sm=on|off Turns on or off strict math, where in strict mode, math."); - console.log(" --strict-math=on|off Requires brackets. This option may default to on and then"); - console.log(" be removed in the future."); - console.log(" -su=on|off Allows mixed units, e.g. 1px+1em or 1px*1px which have units"); - console.log(" --strict-units=on|off that cannot be represented."); - console.log(" --global-var='VAR=VALUE' Defines a variable that can be referenced by the file."); - console.log(" --modify-var='VAR=VALUE' Modifies a variable already declared in the file."); - console.log(" --url-args='QUERYSTRING' Adds params into url tokens (e.g. 42, cb=42 or 'a=1&b=2')"); - console.log(" --plugin=PLUGIN=OPTIONS Loads a plugin. You can also omit the --plugin= if the plugin begins"); - console.log(" less-plugin. E.g. the clean css plugin is called less-plugin-clean-css"); - console.log(" once installed (npm install less-plugin-clean-css), use either with"); - console.log(" --plugin=less-plugin-clean-css or just --clean-css"); - console.log(" specify options afterwards e.g. --plugin=less-plugin-clean-css=\"advanced\""); - console.log(" or --clean-css=\"advanced\""); + console.log(" -h, --help Prints help (this message) and exit."); + console.log(" --include-path=PATHS Sets include paths. Separated by `:'. `;' also supported on windows."); + console.log(" -M, --depends Outputs a makefile import dependency list to stdout."); + console.log(" --no-color Disables colorized output."); + console.log(" --ie-compat Enables IE8 compatibility checks."); + console.log(" --js Enables inline JavaScript in less files"); + console.log(" -l, --lint Syntax check only (lint)."); + console.log(" -s, --silent Suppresses output of error messages."); + console.log(" --strict-imports Forces evaluation of imports."); + console.log(" --insecure Allows imports from insecure https hosts."); + console.log(" -v, --version Prints version number and exit."); + console.log(" --verbose Be verbose."); + console.log(" --source-map[=FILENAME] Outputs a v3 sourcemap to the filename (or output filename.map)."); + console.log(" --source-map-rootpath=X Adds this path onto the sourcemap filename and less file paths."); + console.log(" --source-map-basepath=X Sets sourcemap base path, defaults to current working directory."); + console.log(" --source-map-include-source Puts the less files into the map instead of referencing them."); + console.log(" --source-map-inline Puts the map (and any less files) as a base64 data uri into the output css file."); + console.log(" --source-map-url=URL Sets a custom URL to map file, for sourceMappingURL comment"); + console.log(" in generated CSS file."); + console.log(" -rp, --rootpath=URL Sets rootpath for url rewriting in relative imports and urls"); + console.log(" Works with or without the relative-urls option."); + console.log(" -ru, --relative-urls Re-writes relative urls to the base less file."); + console.log(" -sm=on|off Turns on or off strict math, where in strict mode, math."); + console.log(" --strict-math=on|off Requires brackets. This option may default to on and then"); + console.log(" be removed in the future."); + console.log(" -su=on|off Allows mixed units, e.g. 1px+1em or 1px*1px which have units"); + console.log(" --strict-units=on|off that cannot be represented."); + console.log(" --global-var='VAR=VALUE' Defines a variable that can be referenced by the file."); + console.log(" --modify-var='VAR=VALUE' Modifies a variable already declared in the file."); + console.log(" --url-args='QUERYSTRING' Adds params into url tokens (e.g. 42, cb=42 or 'a=1&b=2')"); + console.log(" --plugin=PLUGIN=OPTIONS Loads a plugin. You can also omit the --plugin= if the plugin begins"); + console.log(" less-plugin. E.g. the clean css plugin is called less-plugin-clean-css"); + console.log(" once installed (npm install less-plugin-clean-css), use either with"); + console.log(" --plugin=less-plugin-clean-css or just --clean-css"); + console.log(" specify options afterwards e.g. --plugin=less-plugin-clean-css=\"advanced\""); + console.log(" or --clean-css=\"advanced\""); console.log(""); console.log("-------------------------- Deprecated ----------------"); console.log(" --line-numbers=TYPE Outputs filename and line numbers."); diff --git a/lib/less-rhino/index.js b/lib/less-rhino/index.js index b59fae51..b0b745dc 100644 --- a/lib/less-rhino/index.js +++ b/lib/less-rhino/index.js @@ -146,23 +146,8 @@ function writeFile(filename, content) { // Command line integration via Rhino (function (args) { - var options = { - depends: false, - compress: false, - cleancss: false, - max_line_len: -1, - silent: false, - verbose: false, - lint: false, - paths: [], - color: true, - strictImports: false, - rootpath: '', - relativeUrls: false, - ieCompat: true, - strictMath: false, - strictUnits: false - }; + var options = require('../default-options'); + var continueProcessing = true, currentErrorcode; diff --git a/lib/less/default-options.js b/lib/less/default-options.js new file mode 100644 index 00000000..09c0b3cf --- /dev/null +++ b/lib/less/default-options.js @@ -0,0 +1,65 @@ +// Export a new default each time +module.exports = function() { + return { + /* Outputs a makefile import dependency list to stdout. */ + depends: false, + + /* Compress using less built-in compression. + * This does an okay job but does not utilise all the tricks of + * dedicated css compression. */ + compress: false, + + /* Runs the less parser and just reports errors without any output. */ + lint: false, + + /* Sets available include paths. + * If the file in an @import rule does not exist at that exact location, + * less will look for it at the location(s) passed to this option. + * You might use this for instance to specify a path to a library which + * you want to be referenced simply and relatively in the less files. */ + paths: [], + + /* color output in the terminal */ + color: true, + + /* The strictImports controls whether the compiler will allow an @import inside of either + * @media blocks or (a later addition) other selector blocks. + * See: https://github.com/less/less.js/issues/656 */ + strictImports: false, + + /* Allow Imports from Insecure HTTPS Hosts */ + insecure: false, + + /* Allows you to add a path to every generated import and url in your css. + * This does not affect less import statements that are processed, just ones + * that are left in the output css. */ + rootpath: '', + + /* By default URLs are kept as-is, so if you import a file in a sub-directory + * that references an image, exactly the same URL will be output in the css. + * This option allows you to re-write URL's in imported files so that the + * URL is always relative to the base imported file */ + relativeUrls: false, + + /* Compatibility with IE8. Used for limiting data-uri length */ + ieCompat: false, // true until 3.0 + + /* Without this option on, Less will try and process all math in your css */ + strictMath: false, + + /* Without this option, less attempts to guess at the output unit when it does maths. */ + strictUnits: false, + + /* Effectively the declaration is put at the top of your base Less file, + * meaning it can be used but it also can be overridden if this variable + * is defined in the file. */ + globalVars: null, + + /* As opposed to the global variable option, this puts the declaration at the + * end of your base file, meaning it will override anything defined in your Less file. */ + modifyVars: null, + + /* This option allows you to specify a argument to go on to every URL. */ + urlArgs: '' + } +} \ No newline at end of file diff --git a/lib/less/parse.js b/lib/less/parse.js index b83441e1..125bdff4 100644 --- a/lib/less/parse.js +++ b/lib/less/parse.js @@ -58,6 +58,9 @@ module.exports = function(environment, ParseTree, ImportManager) { var imports = new ImportManager(this, context, rootFileInfo); this.importManager = imports; + // TODO: allow the plugins to be just a list of paths or names + // Do an async plugin queue like lessc + if (options.plugins) { options.plugins.forEach(function(plugin) { var evalResult, contents; diff --git a/lib/less/plugin-api.js b/lib/less/plugin-api.js index 8ef84f14..3338becf 100644 --- a/lib/less/plugin-api.js +++ b/lib/less/plugin-api.js @@ -1,12 +1,10 @@ -(function (root, registerPlugin) { +(function (root, factory) { if (typeof define === 'function' && define.amd) { - define([], registerPlugin); + define([], factory); } else if (typeof module === 'object' && module.exports) { - module.exports = registerPlugin(); + module.exports = factory(); } else { - if (!root.less) { root.less = {}; } - if (!root.less.plugins) { root.less.plugins = []; } - root.less.plugins.push(registerPlugin()); + (root.LESS_PLUGINS = root.LESS_PLUGINS || []).push(factory()); } }(this, function () { // Less.js Plugin object diff --git a/lib/less/tree/dimension.js b/lib/less/tree/dimension.js index db979a93..34b23a5b 100644 --- a/lib/less/tree/dimension.js +++ b/lib/less/tree/dimension.js @@ -8,6 +8,9 @@ var Node = require("./node"), // var Dimension = function (value, unit) { this.value = parseFloat(value); + if (isNaN(this.value)) { + throw new Error("Dimension is not a number."); + } this.unit = (unit && unit instanceof Unit) ? unit : new Unit(unit ? [unit] : undefined); this.setParent(this.unit, this); diff --git a/test/css/plugin.css b/test/css/plugin.css index 0c6ebe71..9dafc439 100644 --- a/test/css/plugin.css +++ b/test/css/plugin.css @@ -52,5 +52,18 @@ } .test-simple { value: 3.141592653589793; + value: 6.28318531; +} +.test-conflicts { + value: foo; +} +.test-conflicts { + value: bar; +} +.test-conflicts { + value: foo; +} +.test-collection { + list: 32, 5, "bird"; } @arbitrary value after (); diff --git a/test/index.js b/test/index.js index 4e13259a..09f24a14 100644 --- a/test/index.js +++ b/test/index.js @@ -20,7 +20,7 @@ var testMap = [ function(name) { return name + '-all'; }], [{strictMath: true, relativeUrls: false, rootpath: "folder (1)/"}, "static-urls/"], [{strictMath: true, compress: true}, "compression/"], - [{strictMath: true, strictUnits: true}, "strict-units/"], + [{strictMath: false, strictUnits: true}, "strict-units/"], [{}, "legacy/"], [{strictMath: true, strictUnits: true, sourceMap: true, globalVars: true }, "sourcemaps/", lessTester.testSourcemap, null, null, diff --git a/test/less/functions.less b/test/less/functions.less index 4866bdca..74a2b206 100644 --- a/test/less/functions.less +++ b/test/less/functions.less @@ -230,3 +230,4 @@ html { color: mix(blue, @color1, 50%); color: mix(blue, @color2, 50%); } + diff --git a/test/less/plugin.less b/test/less/plugin.less index 285c1649..1bf155d4 100644 --- a/test/less/plugin.less +++ b/test/less/plugin.less @@ -93,7 +93,28 @@ } .test-simple { @plugin "./plugin/plugin-simple"; - value: pi(); + value: pi-anon(); + value: (pi() * 2); +} +.test-conflicts { + @plugin "./plugin/plugin-scope1"; + value: foo(); +} +.test-conflicts { + @plugin "./plugin/plugin-scope2"; + value: foo(); +} +.test-conflicts { + @plugin "./plugin/plugin-scope1"; + value: foo(); +} +.test-collection { + @plugin "./plugin/plugin-collection"; + @var: 32; + store(@var); + store(5); + store("bird"); + list: list(); } test-atrule("@charset"; '"utf-8"'); diff --git a/test/less/plugin/plugin-collection.js b/test/less/plugin/plugin-collection.js new file mode 100644 index 00000000..d8deb98c --- /dev/null +++ b/test/less/plugin/plugin-collection.js @@ -0,0 +1,9 @@ +var collection = []; + +functions.add('store', function(val) { + collection.push(val); // imma store this for later + return false; +}); +functions.add('list', function() { + return less.Value(collection); +}); \ No newline at end of file diff --git a/test/less/plugin/plugin-scope1.js b/test/less/plugin/plugin-scope1.js new file mode 100644 index 00000000..b9aa5804 --- /dev/null +++ b/test/less/plugin/plugin-scope1.js @@ -0,0 +1,3 @@ +functions.add('foo', function() { + return "foo"; +}); \ No newline at end of file diff --git a/test/less/plugin/plugin-scope2.js b/test/less/plugin/plugin-scope2.js new file mode 100644 index 00000000..a7faa74d --- /dev/null +++ b/test/less/plugin/plugin-scope2.js @@ -0,0 +1,3 @@ +functions.add('foo', function() { + return "bar"; +}); \ No newline at end of file diff --git a/test/less/plugin/plugin-simple.js b/test/less/plugin/plugin-simple.js index 340b9b3a..6c059e35 100644 --- a/test/less/plugin/plugin-simple.js +++ b/test/less/plugin/plugin-simple.js @@ -1,3 +1,7 @@ -functions.add('pi', function() { +functions.add('pi-anon', function() { return Math.PI; +}); + +functions.add('pi', function() { + return less.Dimension(Math.PI); }); \ No newline at end of file