mirror of
https://github.com/less/less.js.git
synced 2026-02-07 05:25:04 -05:00
preliminary support for evaluating JavaScript code inside LESS
This commit is contained in:
@@ -78,7 +78,7 @@ var less = {
|
||||
'keyword', 'variable', 'ruleset', 'element',
|
||||
'selector', 'quoted', 'expression', 'rule',
|
||||
'call', 'url', 'alpha', 'import',
|
||||
'mixin', 'comment', 'anonymous', 'value'
|
||||
'mixin', 'comment', 'anonymous', 'value', 'javascript'
|
||||
].forEach(function (n) {
|
||||
require(path.join('less', 'tree', n));
|
||||
});
|
||||
|
||||
@@ -574,6 +574,21 @@ less.Parser = function Parser(env) {
|
||||
if (value = $(/^(-?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm)?/)) {
|
||||
return new(tree.Dimension)(value[1], value[2]);
|
||||
}
|
||||
},
|
||||
|
||||
//
|
||||
// JavaScript code to be evaluated
|
||||
//
|
||||
// `window.location.href`
|
||||
//
|
||||
javascript: function () {
|
||||
var str;
|
||||
|
||||
if (input.charAt(i) !== '`') { return }
|
||||
|
||||
if (str = $(/^`([^`]*)`/)) {
|
||||
return new(tree.JavaScript)(str[1], i);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -699,7 +714,7 @@ less.Parser = function Parser(env) {
|
||||
//
|
||||
entity: function () {
|
||||
return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) ||
|
||||
$(this.entities.call) || $(this.entities.keyword);
|
||||
$(this.entities.call) || $(this.entities.keyword) || $(this.entities.javascript);
|
||||
},
|
||||
|
||||
//
|
||||
@@ -858,7 +873,7 @@ less.Parser = function Parser(env) {
|
||||
if (c === '.' || c === '#' || c === '&') { return }
|
||||
|
||||
if (name = $(this.variable) || $(this.property)) {
|
||||
if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*(;{}-]*);/.exec(chunks[j]))) {
|
||||
if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j]))) {
|
||||
i += match[0].length - 1;
|
||||
value = new(tree.Anonymous)(match[1]);
|
||||
} else if (name === "font") {
|
||||
|
||||
32
lib/less/tree/javascript.js
Normal file
32
lib/less/tree/javascript.js
Normal file
@@ -0,0 +1,32 @@
|
||||
(function (tree) {
|
||||
|
||||
tree.JavaScript = function (string, index) {
|
||||
this.expression = string;
|
||||
this.index = index;
|
||||
};
|
||||
tree.JavaScript.prototype = {
|
||||
toCSS: function () {
|
||||
return this.evaluated;
|
||||
},
|
||||
eval: function (env) {
|
||||
var result,
|
||||
expression = new(Function)('return (' + this.expression + ')'),
|
||||
context = {};
|
||||
|
||||
for (var k in env.frames[0].variables()) {
|
||||
context[k.slice(1)] = env.frames[0].variables()[k].value.eval(env).toCSS();
|
||||
}
|
||||
|
||||
try {
|
||||
result = expression.call(context);
|
||||
this.evaluated = JSON.stringify(result);
|
||||
} catch (e) {
|
||||
throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" ,
|
||||
index: this.index };
|
||||
}
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
})(require('less/tree'));
|
||||
|
||||
@@ -55,10 +55,11 @@ tree.mixin.Definition = function (name, params, rules) {
|
||||
this.frames = [];
|
||||
};
|
||||
tree.mixin.Definition.prototype = {
|
||||
toCSS: function () { return "" },
|
||||
variable: function (name) { return this.parent.variable.call(this, name) },
|
||||
find: function () { return this.parent.find.apply(this, arguments) },
|
||||
rulesets: function () { return this.parent.rulesets.apply(this) },
|
||||
toCSS: function () { return "" },
|
||||
variable: function (name) { return this.parent.variable.call(this, name) },
|
||||
variables: function () { return this.parent.variables.call(this) },
|
||||
find: function () { return this.parent.find.apply(this, arguments) },
|
||||
rulesets: function () { return this.parent.rulesets.apply(this) },
|
||||
|
||||
eval: function (env, args) {
|
||||
var frame = new(tree.Ruleset)(null, []), context;
|
||||
|
||||
@@ -56,17 +56,20 @@ tree.Ruleset.prototype = {
|
||||
match: function (args) {
|
||||
return !args || args.length === 0;
|
||||
},
|
||||
variable: function (name) {
|
||||
if (this._variables) { return this._variables[name] }
|
||||
variables: function () {
|
||||
if (this._variables) { return this._variables }
|
||||
else {
|
||||
return (this._variables = this.rules.reduce(function (hash, r) {
|
||||
return this._variables = this.rules.reduce(function (hash, r) {
|
||||
if (r instanceof tree.Rule && r.variable === true) {
|
||||
hash[r.name] = r;
|
||||
}
|
||||
return hash;
|
||||
}, {}))[name];
|
||||
}, {});
|
||||
}
|
||||
},
|
||||
variable: function (name) {
|
||||
return this.variables()[name];
|
||||
},
|
||||
rulesets: function () {
|
||||
if (this._rulesets) { return this._rulesets }
|
||||
else {
|
||||
|
||||
Reference in New Issue
Block a user