Support for pattern-matching on mixin calls.

This commit is contained in:
cloudhead
2010-04-25 00:09:40 -04:00
parent 2ebbf37c4b
commit d56feee6f0
6 changed files with 155 additions and 14 deletions

View File

@@ -533,15 +533,21 @@ less.Parser = function Parser(env) {
if (match = $(/([#.][a-zA-Z0-9_-]+)\s*\(/g)) {
name = match[1];
while (param = $(/@[\w-]+/g)) {
if ($(':')) {
if (value = $(this.expression)) {
params.push({ name: param, value: value });
while (param = $(/@[\w-]+/g) || $(this.entities.literal)
|| $(this.entities.keyword)) {
// Variable
if (param[0] === '@') {
if ($(':')) {
if (value = $(this.expression)) {
params.push({ name: param, value: value });
} else {
throw new(Error)("Expected value");
}
} else {
throw new(Error)("Expected value");
params.push({ name: param });
}
} else {
params.push({ name: param });
params.push({ value: param });
}
if (! $(',')) { break }
}

View File

@@ -12,8 +12,10 @@ tree.mixin.Call.prototype = {
for (var i = 0; i < env.frames.length; i++) {
if ((mixins = env.frames[i].find(this.selector)).length > 0) {
for (var m = 0; m < mixins.length; m++) {
Array.prototype.push.apply(
rules, mixins[m].eval(this.arguments, env).rules);
if (mixins[m].match(this.arguments, env)) {
Array.prototype.push.apply(
rules, mixins[m].eval(this.arguments, env).rules);
}
}
return rules;
}
@@ -26,8 +28,13 @@ tree.mixin.Definition = function MixinDefinition(name, params, rules) {
this.name = name;
this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])];
this.params = params;
this.arity = params.length;
this.rules = rules;
this._lookups = {};
this.required = params.reduce(function (count, p) {
if (p.name && p.value) { return count }
else { return count + 1 }
}, 0);
};
tree.mixin.Definition.prototype = {
toCSS: function () { return "" },
@@ -39,14 +46,32 @@ tree.mixin.Definition.prototype = {
var frame = new(tree.Ruleset)(null, []), context;
for (var i = 0, val; i < this.params.length; i++) {
if (val = (args && args[i]) || this.params[i].value) {
frame.rules.unshift(new(tree.Rule)(this.params[i].name, val));
} else {
throw new(Error)("wrong number of arguments for " + this.name);
if (this.params[i].name) {
if (val = (args && args[i]) || this.params[i].value) {
frame.rules.unshift(new(tree.Rule)(this.params[i].name, val));
} else {
throw new(Error)("wrong number of arguments for " + this.name);
}
}
}
return new(tree.Ruleset)(null, this.rules).evalRules({
frames: [this, frame].concat(env.frames)
});
},
match: function (args, env) {
var argsLength = (args && args.length) || 0;
if (argsLength < this.required || argsLength > this.arity) {
return false;
}
for (var i = 0; i < argsLength; i++) {
if (!this.params[i].name) {
if (args[i].toCSS(env) != this.params[i].value.toCSS(env)) {
return false;
}
}
}
return true;
}
};

View File

@@ -27,7 +27,8 @@ tree.Value = function Value(value) {
tree.Value.prototype = {
eval: function (env) {
if (this.value.length === 1) {
return this.value[0].eval(env);
return this.value[0].eval ? this.value[0].eval(env)
: this.value[0];
} else {
return this;
}

View File

@@ -16,12 +16,15 @@ tree.Ruleset.prototype = {
} else if (rule instanceof tree.mixin.Call) {
Array.prototype.push.apply(rules, rule.eval(context));
} else {
rules.push(rule.eval(context));
rules.push(rule.eval ? rule.eval(context) : rule);
}
});
this.rules = rules;
return this;
},
match: function (args) {
return !args || args.length === 0;
},
variables: function (name) {
if (this._variables) { return this._variables[name] }
else {