diff --git a/Gruntfile.js b/Gruntfile.js index 8ffcaeed4..cf8c96242 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -195,6 +195,14 @@ module.exports = function(grunt) { specs: 'test/browser/runner-modify-vars-spec.js', outfile: 'tmp/browser/test-runner-modify-vars.html' } + }, + globalVars: { + src: ['test/browser/less/global-vars/*.less'], + options: { + helpers: 'test/browser/runner-global-vars-options.js', + specs: 'test/browser/runner-global-vars-spec.js', + outfile: 'tmp/browser/test-runner-global-vars.html' + } } }, diff --git a/bin/lessc b/bin/lessc index 9ee3609a3..9b8b04ce9 100755 --- a/bin/lessc +++ b/bin/lessc @@ -25,7 +25,9 @@ var options = { relativeUrls: false, ieCompat: true, strictMath: false, - strictUnits: false + strictUnits: false, + globalVariables: '', + modifyVariables: '' }; var continueProcessing = true, currentErrorcode; @@ -53,6 +55,11 @@ var checkBooleanArg = function(arg) { return Boolean(onOff[2]); }; +var parseVariableOption = function(option) { + var parts = option.split('=', 2); + return '@' + parts[0] + ': ' + parts[1] + ';\n'; +}; + var warningMessages = ""; var sourceMapFileInline = false; @@ -64,7 +71,7 @@ args = args.filter(function (arg) { return false; } - if (match = arg.match(/^--?([a-z][0-9a-z-]*)(?:=([^\s]*))?$/i)) { arg = match[1] } + if (match = arg.match(/^--?([a-z][0-9a-z-]*)(?:=(.*))?$/i)) { arg = match[1] } else { return arg } switch (arg) { @@ -189,6 +196,16 @@ args = args.filter(function (arg) { options.strictUnits = checkBooleanArg(match[2]); } break; + case "global-var": + if (checkArgFunc(arg, match[2])) { + options.globalVariables += parseVariableOption(match[2]); + } + break; + case "modify-var": + if (checkArgFunc(arg, match[2])) { + options.modifyVariables += parseVariableOption(match[2]); + } + break; } }); @@ -267,6 +284,8 @@ var parseLessFile = function (e, data) { return; } + data = options.globalVariables + data + options.modifyVariables; + options.paths = [path.dirname(input)].concat(options.paths); options.filename = input; diff --git a/lib/less/browser.js b/lib/less/browser.js index 4e1c68cdd..e5a1dce2b 100644 --- a/lib/less/browser.js +++ b/lib/less/browser.js @@ -52,6 +52,7 @@ if (dumpLineNumbers) { var typePattern = /^text\/(x-)?less$/; var cache = null; var fileCache = {}; +var varsPre = ""; function log(str, level) { if (less.env == 'development' && typeof(console) !== 'undefined' && less.logLevel >= level) { @@ -294,9 +295,15 @@ function loadStyles(newVars) { var env = new less.tree.parseEnv(less), lessText = style.innerHTML || ''; env.filename = document.location.href.replace(/#.*$/, ''); - if (newVars) { + + if (newVars || varsPre) { env.useFileCache = true; - lessText += "\n" + newVars; + + lessText = varsPre + lessText; + + if (newVars) { + lessText += "\n" + newVars; + } } /*jshint loopfunc:true */ @@ -499,6 +506,8 @@ function loadFile(originalHref, currentFileInfo, callback, env, newVars) { } doXHR(href, env.mime, function (data, lastModified) { + data = varsPre + data; + // per file cache fileCache[href] = data; @@ -518,7 +527,7 @@ function loadStyleSheet(sheet, callback, reload, remaining, newVars) { var env = new less.tree.parseEnv(less); env.mime = sheet.type; - if (newVars) { + if (newVars || varsPre) { env.useFileCache = true; } @@ -585,6 +594,18 @@ function initRunningMode(){ } } +function serializeVars(vars) { + var s = ""; + + for (var name in vars) { + s += ((name.slice(0,1) === '@')? '' : '@') + name +': '+ + ((vars[name].slice(-1) === ';')? vars[name] : vars[name] +';'); + } + + return s; +} + + // // Watch mode // @@ -627,12 +648,7 @@ for (var i = 0; i < links.length; i++) { // CSS without reloading less-files // less.modifyVars = function(record) { - var newVars = ""; - for (var name in record) { - newVars += ((name.slice(0,1) === '@')? '' : '@') + name +': '+ - ((record[name].slice(-1) === ';')? record[name] : record[name] +';'); - } - less.refresh(false, newVars); + less.refresh(false, serializeVars(record)); }; less.refresh = function (reload, newVars) { @@ -659,6 +675,10 @@ less.refresh = function (reload, newVars) { loadStyles(newVars); }; +if (less.globalVars) { + varsPre = serializeVars(less.globalVars) + "\n"; +} + less.refreshStyles = loadStyles; less.Parser.fileLoader = loadFile; diff --git a/lib/less/lessc_helper.js b/lib/less/lessc_helper.js index 1581f3e82..be1e5a5c9 100644 --- a/lib/less/lessc_helper.js +++ b/lib/less/lessc_helper.js @@ -52,6 +52,8 @@ var lessc_helper = { console.log(" be removed in the future."); console.log(" -su=on|off Allow 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(""); console.log("-------------------------- Deprecated ----------------"); console.log(" -O0, -O1, -O2 Set the parser's optimization level. The lower"); diff --git a/test/browser/css/global-vars/simple.css b/test/browser/css/global-vars/simple.css new file mode 100644 index 000000000..05b9fb02f --- /dev/null +++ b/test/browser/css/global-vars/simple.css @@ -0,0 +1,3 @@ +.test { + color: #ff0000; +} diff --git a/test/browser/less/global-vars/simple.less b/test/browser/less/global-vars/simple.less new file mode 100644 index 000000000..00545b164 --- /dev/null +++ b/test/browser/less/global-vars/simple.less @@ -0,0 +1,3 @@ +.test { + color: @global-var; +} diff --git a/test/browser/runner-global-vars-options.js b/test/browser/runner-global-vars-options.js new file mode 100644 index 000000000..f313b2f77 --- /dev/null +++ b/test/browser/runner-global-vars-options.js @@ -0,0 +1,4 @@ +var less = {}; +less.globalVars = { + "@global-var": "red" +}; diff --git a/test/browser/runner-global-vars-spec.js b/test/browser/runner-global-vars-spec.js new file mode 100644 index 000000000..6dba89170 --- /dev/null +++ b/test/browser/runner-global-vars-spec.js @@ -0,0 +1,3 @@ +describe("less.js global vars", function() { + testLessEqualsInDocument(); +});