Skip to content

Commit

Permalink
Support specifying custom variables when calling lessc and less.js.
Browse files Browse the repository at this point in the history
Both lessc and less.js can now be provided with global variables that
all .less files will have immediate access to. This can be used to
provide, for example, a base path for an @import, signed URLs offering
temporary access to an image on S3, or anything else.

lessc has two new parameters, --global-var and --modify-var. Both take
a value of the form "varname=value". --global-var declares variables
immediately before the content of the .less files, and --modify-var
declares them after.

--global-var is used when rules, imports, or other variables will depend
on the provided variable.

--modify-var is used to override a variable declared within the .less
file.

less.js's equivalent for global variables is less.globalVars. This can
be set before loading less.js. There is no new requivalent to
--modify-var, as less.modifyVars can be used for that purpose.
  • Loading branch information
chipx86 committed Nov 14, 2013
1 parent 0213579 commit daec7df
Show file tree
Hide file tree
Showing 8 changed files with 73 additions and 11 deletions.
8 changes: 8 additions & 0 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -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'
}
}
},

Expand Down
23 changes: 21 additions & 2 deletions bin/lessc
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ var options = {
relativeUrls: false,
ieCompat: true,
strictMath: false,
strictUnits: false
strictUnits: false,
globalVariables: '',
modifyVariables: ''
};
var continueProcessing = true,
currentErrorcode;
Expand Down Expand Up @@ -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;

Expand All @@ -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) {
Expand Down Expand Up @@ -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;
}
});

Expand Down Expand Up @@ -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;

Expand Down
38 changes: 29 additions & 9 deletions lib/less/browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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;

Expand All @@ -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;
}

Expand Down Expand Up @@ -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
//
Expand Down Expand Up @@ -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) {
Expand All @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions lib/less/lessc_helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
3 changes: 3 additions & 0 deletions test/browser/css/global-vars/simple.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.test {
color: #ff0000;
}
3 changes: 3 additions & 0 deletions test/browser/less/global-vars/simple.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.test {
color: @global-var;
}
4 changes: 4 additions & 0 deletions test/browser/runner-global-vars-options.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
var less = {};
less.globalVars = {
"@global-var": "red"
};
3 changes: 3 additions & 0 deletions test/browser/runner-global-vars-spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
describe("less.js global vars", function() {
testLessEqualsInDocument();
});

5 comments on commit daec7df

@doowb
Copy link

@doowb doowb commented on daec7df Nov 27, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm looking for a way to call this when using less.js in node. Is there anyway to pass the globalVars in through the options or use a .lessrc file?

@jonschlinkert
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lukeapage, that's what I was wondering as well. Are @doowb and I overlooking something?

@lukeapage
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nope.. I wonder if it should be moved to the less core

@jonschlinkert
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that would be great, we'd love to see this feature available in assemble-less

@jonschlinkert
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lukeapage could you give pointers on where this would be implemented in less core? maybe @doowb or I could do a pr

Please sign in to comment.