diff --git a/lib/less/parser.js b/lib/less/parser.js index 26bc4978a..57f42b81c 100644 --- a/lib/less/parser.js +++ b/lib/less/parser.js @@ -752,7 +752,7 @@ less.Parser = function Parser(env) { // selector for now. // call: function () { - var elements = [], e, c, args, index = i, s = input.charAt(i), important = false; + var elements = [], e, c, args = [], arg, index = i, s = input.charAt(i), name, value, important = false; if (s !== '.' && s !== '#') { return } @@ -760,14 +760,38 @@ less.Parser = function Parser(env) { elements.push(new(tree.Element)(c, e, i)); c = $('>'); } - $('(') && (args = $(this.entities.arguments)) && $(')'); + if ($('(')) { + while (arg = $(this.expression)) { + value = arg; + name = null; + + // Variable + if (arg.value.length = 1) { + var val = arg.value[0]; + if (val instanceof tree.Variable) { + if ($(':')) { + if (value = $(this.expression)) { + name = val.name; + } else { + throw new(Error)("Expected value"); + } + } + } + } + + args.push({ name: name, value: value }); + + if (! $(',')) { break } + } + if (! $(')')) throw new(Error)("Expected )"); + } if ($(this.important)) { important = true; } if (elements.length > 0 && ($(';') || peek('}'))) { - return new(tree.mixin.Call)(elements, args || [], index, env.filename, important); + return new(tree.mixin.Call)(elements, args, index, env.filename, important); } }, diff --git a/lib/less/tree/mixin.js b/lib/less/tree/mixin.js index 4464bc6cd..45948a878 100644 --- a/lib/less/tree/mixin.js +++ b/lib/less/tree/mixin.js @@ -14,7 +14,9 @@ tree.mixin.Call.prototype = { for (var i = 0; i < env.frames.length; i++) { if ((mixins = env.frames[i].find(this.selector)).length > 0) { - args = this.arguments && this.arguments.map(function (a) { return a.eval(env) }); + args = this.arguments && this.arguments.map(function (a) { + return { name: a.name, value: a.value.eval(env) }; + }); for (var m = 0; m < mixins.length; m++) { if (mixins[m].match(args, env)) { try { @@ -69,9 +71,18 @@ tree.mixin.Definition.prototype = { rulesets: function () { return this.parent.rulesets.apply(this) }, evalParams: function (env, args) { - var frame = new(tree.Ruleset)(null, []), varargs; + var frame = new(tree.Ruleset)(null, []), varargs, arg; for (var i = 0, val, name; i < this.params.length; i++) { + arg = args && args[i] + + if (arg && arg.name) { + frame.rules.unshift(new(tree.Rule)(arg.name, arg.value.eval(env))); + args.splice(i, 1); + i--; + continue; + } + if (name = this.params[i].name) { if (this.params[i].variadic && args) { varargs = []; @@ -79,7 +90,7 @@ tree.mixin.Definition.prototype = { varargs.push(args[j].eval(env)); } frame.rules.unshift(new(tree.Rule)(name, new(tree.Expression)(varargs).eval(env))); - } else if (val = (args && args[i]) || this.params[i].value) { + } else if (val = (arg && arg.value) || this.params[i].value) { frame.rules.unshift(new(tree.Rule)(name, val.eval(env))); } else { throw { type: 'Runtime', message: "wrong number of arguments for " + this.name + @@ -93,7 +104,7 @@ tree.mixin.Definition.prototype = { var frame = this.evalParams(env, args), context, _arguments = [], rules, start; for (var i = 0; i < Math.max(this.params.length, args && args.length); i++) { - _arguments.push(args[i] || this.params[i].value); + _arguments.push((args[i] && args[i].value) || this.params[i].value); } frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); @@ -123,7 +134,7 @@ tree.mixin.Definition.prototype = { for (var i = 0; i < len; i++) { if (!this.params[i].name) { - if (args[i].eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { + if (args[i].value.eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { return false; } } diff --git a/test/css/mixins-named-args.css b/test/css/mixins-named-args.css new file mode 100644 index 000000000..1c1afaf8f --- /dev/null +++ b/test/css/mixins-named-args.css @@ -0,0 +1,20 @@ +.named-arg { + color: blue; + width: 5px; + height: 99%; + text-align: center; +} +.class { + width: 5px; + height: 19%; +} +.named-args2 { + width: 15px; + height: 49%; + color: #646464; +} +.named-args3 { + width: 5px; + height: 29%; + color: #123456; +} diff --git a/test/less/mixins-named-args.less b/test/less/mixins-named-args.less new file mode 100644 index 000000000..57b07d010 --- /dev/null +++ b/test/less/mixins-named-args.less @@ -0,0 +1,31 @@ +.mixin (@a: 1px, @b: 50%) { + width: @a * 5; + height: @b - 1%; +} +.mixin (@a: 1px, @b: 50%) when (@b > 75%){ + text-align: center; +} + +.named-arg { + color: blue; + .mixin(@b: 100%); +} + +.class { + @var: 20%; + .mixin(@b: @var); +} + +.mixin2 (@a: 1px, @b: 50%, @c: 50) { + width: @a * 5; + height: @b - 1%; + color: #000000 + @c; +} + +.named-args2 { + .mixin2(3px, @c: 100); +} + +.named-args3 { + .mixin2(@b: 30%, @c: #123456); +} \ No newline at end of file