I am finding that LESS has a hobbled JavaScript evaluator, at least the way I am using it, which is to compile *.less files into *.css on a client before uploading them to the web server.
I'm aware that compilation may be more often done server-side, but for performance & simplicity we only want CSS files on the server. I'm compiling the LESS files on Fedora Linux with the lessc
ruby gem installed into Node Package Manager as in these instructions.
The compiler is working perfectly, but as far as I can tell the JavaScript expression evaluation is sorely limited. I believe this also applies to server-side JavaScript expression evaluation based on this posting which suggests uncertainty about how the JavaScript engine is plugged into the LESS environment.
All I can use are simple, comma-separated expressions, like the following:
@bar: `
"ignored-string-expression"
,
5
`;
div.test-thing { content: ~"@{bar}"; }
which compiles into:
div.test-thing {
content: 5;
}
When I try to define a function, the compiler barfs (whether or not the semicolon in the expression is backslash-escaped):
[719] anjaneya% cat testfunc.less
@bar: `function foo() {return 5}; foo()`;
div.test-thing { content: ~"@{bar}"; }
[720] anjaneya% lessc testfunc.less
SyntaxError: JavaScript evaluation error: `function foo() {return 5}; foo()` ...
There also doesn't seem to be any way of looping, even if you try to trick it into evaluating a loop as you would the "ignored-string-expression" above, like:
@foo: `x = 0,
for (var n = 0; n <= 10; n++) { x++; },
x
`;
div.test-thing { content: ~"@{bar}"; }
which says:
ParseError: Syntax Error on line 1 ...
Why bother? To be able to compile this LESS:
@svgSource: '<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%"><linearGradient id="g" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="@{start}" /><stop offset="1" stop-color="@{end}" /></linearGradient><rect x="0" y="0" width="100%" height="100%" fill="url(#g)" /></svg>';
into this CSS:
background: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiPjxsaW5lYXJHcmFkaWVudCBpZD0iZyIgeDE9IjAiIHkxPSIwIiB4Mj0iMCIgeTI9IjEiPjxzdG9wIG9mZnNldD0iMCIgc3RvcC1jb2xvcj0iIzU3OWRkYiIgLz48c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiMwMDAwMjIiIC8+PC9saW5lYXJHcmFkaWVudD48cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSJ1cmwoI2cpIiAvPjwvc3ZnPg==);
using a program like this, whether the algorithm is implemented in JavaScript, PHP, Perl, UNIX shell, or anything else. This processing might be done without function definitions but not without looping, and without functions you can't even have recursion.
Given that both functions and looping are compound statements that probably aren't evaluated as expressions (it's not LISP), that is probably the basis for the failure... it's not really a full JavaScript interpreter. So I'm hoping someone who really knows the LESS compiler will:
- clarify the limitation above, so I can use JavaScript & LESS portably for this task
- say how this problem can be worked around (e.g., with a "shell escape" or any evaluation environment that can process strings iteratively) and/or
- say how to extend the LESS compiler with such text processing capabilities, like a "real" JavaScript engine.