Skip to content

Commit

Permalink
Variadic argument support
Browse files Browse the repository at this point in the history
   .mixin (...)   {} // matches any number of arguments
   .mixin ()      {} // matches exactly 0 arguments
   .mixin (@A: 1) {} // matches 0-1 arguments
  • Loading branch information
cloudhead committed Feb 28, 2012
1 parent 236f16b commit ac226c6
Show file tree
Hide file tree
Showing 6 changed files with 41 additions and 23 deletions.
33 changes: 20 additions & 13 deletions lib/less/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -787,7 +787,7 @@ less.Parser = function Parser(env) {
// the `{...}` block.
//
definition: function () {
var name, params = [], match, ruleset, param, value, cond;
var name, params = [], match, ruleset, param, value, cond, variadic = false;
if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') ||
peek(/^[^{]*(;|})/)) return;

Expand All @@ -796,21 +796,28 @@ less.Parser = function Parser(env) {
if (match = $(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)) {
name = match[1];

while (param = $(this.entities.variable) || $(this.entities.literal)
|| $(this.entities.keyword)) {
// Variable
if (param instanceof tree.Variable) {
if ($(':')) {
value = expect(this.expression, 'expected expression');
params.push({ name: param.name, value: value });
do {
if (input.charAt(i) === '.' && $(/^\.{3}/)) {
variadic = true;
break;
} else if (param = $(this.entities.variable) || $(this.entities.literal)
|| $(this.entities.keyword)) {
// Variable
if (param instanceof tree.Variable) {
if ($(':')) {
value = expect(this.expression, 'expected expression');
params.push({ name: param.name, value: value });
} else {
params.push({ name: param.name });
}
} else {
params.push({ name: param.name });
params.push({ value: param });
}
} else {
params.push({ value: param });
break;
}
if (! $(',')) { break }
}
} while ($(','))

expect(')');

if ($(/^when/)) { // Guard
Expand All @@ -820,7 +827,7 @@ less.Parser = function Parser(env) {
ruleset = $(this.block);

if (ruleset) {
return new(tree.mixin.Definition)(name, params, ruleset, cond);
return new(tree.mixin.Definition)(name, params, ruleset, cond, variadic);
} else {
restore();
}
Expand Down
11 changes: 8 additions & 3 deletions lib/less/tree/mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,12 @@ tree.mixin.Call.prototype = {
}
};

tree.mixin.Definition = function (name, params, rules, condition) {
tree.mixin.Definition = function (name, params, rules, condition, variadic) {
this.name = name;
this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])];
this.params = params;
this.condition = condition;
this.variadic = variadic;
this.arity = params.length;
this.rules = rules;
this._lookups = {};
Expand Down Expand Up @@ -102,8 +103,12 @@ tree.mixin.Definition.prototype = {
match: function (args, env) {
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.variadic) {
if (argsLength < this.required) { return false }
if (argsLength > this.params.length) { return false }
if ((this.required > 0) && (argsLength > this.params.length)) { return false }
}

if (this.condition && !this.condition.eval({
frames: [this.evalParams(env, args)].concat(env.frames)
})) { return false }
Expand Down
4 changes: 4 additions & 0 deletions test/css/mixins-args.css
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,17 @@ body {
}
.arguments {
border: 1px solid #000000;
width: 1px;
}
.arguments2 {
border: 0px;
width: 0px;
}
.arguments3 {
border: 0px;
width: 0px;
}
.edge-case {
border: "{";
width: "{";
}
10 changes: 4 additions & 6 deletions test/css/mixins-pattern.css
Original file line number Diff line number Diff line change
@@ -1,26 +1,24 @@
.zero {
variadic: true;
zero: 0;
one: 1;
two: 2;
three: 3;
}
.one {
zero: 0;
variadic: true;
one: 1;
one-req: 1;
two: 2;
three: 3;
}
.two {
zero: 0;
one: 1;
variadic: true;
two: 2;
three: 3;
}
.three {
zero: 0;
one: 1;
two: 2;
variadic: true;
three-req: 3;
three: 3;
}
Expand Down
3 changes: 2 additions & 1 deletion test/less/mixins-args.less
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,9 @@ body {
#id-mixin;
}

.mixin-arguments (@width: 0px) {
.mixin-arguments (@width: 0px, ...) {
border: @arguments;
width: @width;
}

.arguments {
Expand Down
3 changes: 3 additions & 0 deletions test/less/mixins-pattern.less
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
.mixin (...) {
variadic: true;
}
.mixin () {
zero: 0;
}
Expand Down

0 comments on commit ac226c6

Please sign in to comment.