mirror of
https://github.com/less/less.js.git
synced 2026-01-23 14:18:00 -05:00
mixin guards
Allows functional-style guard expressions:
.mixin (@a) ? @a > 0 {...}
This commit is contained in:
@@ -73,12 +73,12 @@ var less = {
|
||||
}
|
||||
};
|
||||
|
||||
['color', 'directive', 'operation', 'dimension',
|
||||
'keyword', 'variable', 'ruleset', 'element',
|
||||
'selector', 'quoted', 'expression', 'rule',
|
||||
'call', 'url', 'alpha', 'import',
|
||||
'mixin', 'comment', 'anonymous', 'value',
|
||||
'javascript', 'assignment'
|
||||
['color', 'directive', 'operation', 'dimension',
|
||||
'keyword', 'variable', 'ruleset', 'element',
|
||||
'selector', 'quoted', 'expression', 'rule',
|
||||
'call', 'url', 'alpha', 'import',
|
||||
'mixin', 'comment', 'anonymous', 'value',
|
||||
'javascript', 'assignment', 'condition'
|
||||
].forEach(function (n) {
|
||||
require('./tree/' + n);
|
||||
});
|
||||
|
||||
@@ -733,7 +733,7 @@ less.Parser = function Parser(env) {
|
||||
// the `{...}` block.
|
||||
//
|
||||
definition: function () {
|
||||
var name, params = [], match, ruleset, param, value;
|
||||
var name, params = [], match, ruleset, param, value, cond, memo;
|
||||
|
||||
if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') ||
|
||||
peek(/^[^{]*(;|})/)) return;
|
||||
@@ -761,10 +761,17 @@ less.Parser = function Parser(env) {
|
||||
}
|
||||
if (! $(')')) throw new(Error)("Expected )");
|
||||
|
||||
memo = i;
|
||||
|
||||
if ($('?')) { // Guard
|
||||
cond = $(this.condition);
|
||||
if (! cond) { i = memo }
|
||||
}
|
||||
|
||||
ruleset = $(this.block);
|
||||
|
||||
if (ruleset) {
|
||||
return new(tree.mixin.Definition)(name, params, ruleset);
|
||||
return new(tree.mixin.Definition)(name, params, ruleset, cond);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1080,6 +1087,16 @@ less.Parser = function Parser(env) {
|
||||
return operation || m;
|
||||
}
|
||||
},
|
||||
condition: function () {
|
||||
var a, op, index = i;
|
||||
if (a = $(this.addition)) {
|
||||
if (op = $(/^[<=>]/)) {
|
||||
if (b = $(this.addition)) {
|
||||
return new(tree.Condition)(op, a, b, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
//
|
||||
// An operand is anything that can be part of an operation,
|
||||
|
||||
28
lib/less/tree/condition.js
Normal file
28
lib/less/tree/condition.js
Normal file
@@ -0,0 +1,28 @@
|
||||
(function (tree) {
|
||||
|
||||
tree.Condition = function (op, l, r, i) {
|
||||
this.op = op.trim();
|
||||
this.lvalue = l;
|
||||
this.rvalue = r;
|
||||
this.index = i;
|
||||
};
|
||||
tree.Condition.prototype.eval = function (env) {
|
||||
var a = this.lvalue.eval(env),
|
||||
b = this.rvalue.eval(env);
|
||||
|
||||
var i = this.index;
|
||||
|
||||
if (a.compare) {
|
||||
switch (a.compare(b)) {
|
||||
case -1: return this.op === '<';
|
||||
case 0: return this.op === '=';
|
||||
case 1: return this.op === '>';
|
||||
}
|
||||
} else {
|
||||
throw { type: "Type",
|
||||
message: "Unable to perform comparison",
|
||||
index: i };
|
||||
}
|
||||
};
|
||||
|
||||
})(require('../tree'));
|
||||
@@ -28,6 +28,19 @@ tree.Dimension.prototype = {
|
||||
return new(tree.Dimension)
|
||||
(tree.operate(op, this.value, other.value),
|
||||
this.unit || other.unit);
|
||||
},
|
||||
|
||||
// TODO: Perform unit conversion before comparing
|
||||
compare: function (other) {
|
||||
if (other instanceof tree.Dimension) {
|
||||
if (other.value > this.value) {
|
||||
return -1;
|
||||
} else if (other.value < this.value) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ tree.Expression.prototype = {
|
||||
},
|
||||
toCSS: function (env) {
|
||||
return this.value.map(function (e) {
|
||||
return e.toCSS(env);
|
||||
return e.toCSS ? e.toCSS(env) : '';
|
||||
}).join(' ');
|
||||
}
|
||||
};
|
||||
|
||||
@@ -41,10 +41,11 @@ tree.mixin.Call.prototype = {
|
||||
}
|
||||
};
|
||||
|
||||
tree.mixin.Definition = function (name, params, rules) {
|
||||
tree.mixin.Definition = function (name, params, rules, condition) {
|
||||
this.name = name;
|
||||
this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])];
|
||||
this.params = params;
|
||||
this.condition = condition;
|
||||
this.arity = params.length;
|
||||
this.rules = rules;
|
||||
this._lookups = {};
|
||||
@@ -62,8 +63,8 @@ tree.mixin.Definition.prototype = {
|
||||
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, _arguments = [];
|
||||
evalParams: function (env, args) {
|
||||
var frame = new(tree.Ruleset)(null, []);
|
||||
|
||||
for (var i = 0, val; i < this.params.length; i++) {
|
||||
if (this.params[i].name) {
|
||||
@@ -75,6 +76,11 @@ tree.mixin.Definition.prototype = {
|
||||
}
|
||||
}
|
||||
}
|
||||
return frame;
|
||||
},
|
||||
eval: function (env, args) {
|
||||
var frame = this.evalParams(env, args), context, _arguments = [];
|
||||
|
||||
for (var i = 0; i < Math.max(this.params.length, args && args.length); i++) {
|
||||
_arguments.push(args[i] || this.params[i].value);
|
||||
}
|
||||
@@ -85,10 +91,13 @@ tree.mixin.Definition.prototype = {
|
||||
});
|
||||
},
|
||||
match: function (args, env) {
|
||||
var argsLength = (args && args.length) || 0, len;
|
||||
var argsLength = (args && args.length) || 0, len, frame;
|
||||
|
||||
if (argsLength < this.required) { return false }
|
||||
if ((this.required > 0) && (argsLength > this.params.length)) { return false }
|
||||
if (this.condition && !this.condition.eval({
|
||||
frames: [this.evalParams(env, args)]
|
||||
})) { return false }
|
||||
|
||||
len = Math.min(argsLength, this.arity);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user