I'm using client-side less.js. Is there a way to get all variables from my less file. I know how to modify variables:
less.modifyVars({
"@var": "#fff"
});
But I want to get all of them, like (don't work):
var variables = less.getVars();
I'm using client-side less.js. Is there a way to get all variables from my less file. I know how to modify variables:
less.modifyVars({
"@var": "#fff"
});
But I want to get all of them, like (don't work):
var variables = less.getVars();
This is going to be an unconventional answer as it seems that this data isn't publicly exposed as part of the browser facing API.
tl;dr
less.js
file.Add this function definition somewhere
function exposeVars(root) {
var r=root._variables,n=Object.keys(r),m={}
for(var k of n){m[k]=r[k].value}
less.variables = m;
}
Add the following call exposeVars(evaldRoot)
just before return result
on line ~2556.
less.variables
contains all the variables from your file.Disclaimer: Doing this is not a good idea! It's fine if you're just playing around, debugging or testing something, but don't depend on this hack for anything serious!
The basic aim here was to find the point in the source where the .less
files are turned into abstract syntax trees (or some other formal structure).
Jumping straight into the source, I found a ParseTree
class. It's a reasonable assumption to guess that it will contain the result of parsing the less file.
I wrote a quick test file and added it to the browser with the appropriate tag. It looks like this:
@myvar: red;
@othervar: 12px;
body {
padding: @othervar;
background: @myvar;
}
I've downloaded a local copy of less.js and added a breakpoint added to line 2556.
I had a poke around in the local scope to see what was available and found the variables in an object called evaldRoot
.
evaldRoot = {
_variables: {
@myvar: {
name: '@myvar',
value: Color
},
@othervar: {
name: '@othervar',
value: Dimension
}
}
}
Next job was to work out where this data goes. It seems like the evaldRoot
variable is used to generate the resulting CSS (which would make sense, as it contains information such as variables).
if (options.sourceMap) {
sourceMapBuilder = new SourceMapBuilder(options.sourceMap);
result.css = sourceMapBuilder.toCSS(evaldRoot, toCSSOptions, this.imports);
} else {
result.css = evaldRoot.toCSS(toCSSOptions);
}
Whatever happens, the variables goes out of scope after it is used to generate a string of CSS as result.css
.
To expose of these variables, the script needs a small modification. You'll have to expose the variables publicly somehow. Here's an example of doing that.
function exposeVars(root) {
var varNames = Object.keys(root._variables);
var variables = varNames.reduce(function(varMap, varName) {
varMap[varName] = root._variables[varName].value;
}, {});
less.variables = variables;
}
This can be added just before the return statement with the breakpoint.
exposeVars(evaldRoot);
return result;
Now the variables will be available in a name: value
object on the global less
object.
You could even modify the expose function to return the variables from a call to less.getVars()
. Just like your initial suggestion.
function exposeVars(root) {
// ...
less.getVars = function() {
return variables;
};
}