Skip to content

Commit c583ace

Browse files
committed
Fix default variables containing comma when semi-colon seperated mixin definition. Fixes less#1211
1 parent 10caaac commit c583ace

File tree

3 files changed

+93
-46
lines changed

3 files changed

+93
-46
lines changed

lib/less/parser.js

+65-46
Original file line numberDiff line numberDiff line change
@@ -846,7 +846,7 @@ less.Parser = function Parser(env) {
846846
c = $('>');
847847
}
848848
if ($('(')) {
849-
args = this.mixin.args.call(this, true);
849+
args = this.mixin.args.call(this, true).args;
850850
expect(')');
851851
}
852852

@@ -863,30 +863,73 @@ less.Parser = function Parser(env) {
863863
restore();
864864
},
865865
args: function (isCall) {
866-
var expressions = [], argsSemiColon = [], isSemiColonSeperated, argsComma = [], expressionContainsNamed, name, nameLoop, value, arg, args;
867-
while (arg = $(this.expression)) {
866+
var expressions = [], argsSemiColon = [], isSemiColonSeperated, argsComma = [], expressionContainsNamed, name, nameLoop, value, arg,
867+
returner = {args:null, variadic: false};
868+
while (true) {
869+
if (isCall) {
870+
arg = $(this.expression);
871+
} else {
872+
$(this.comment);
873+
if (input.charAt(i) === '.' && $(/^\.{3}/)) {
874+
returner.variadic = true;
875+
if ($(";") && !isSemiColonSeperated) {
876+
isSemiColonSeperated = true;
877+
}
878+
(isSemiColonSeperated ? argsSemiColon : argsComma)
879+
.push({ variadic: true });
880+
break;
881+
}
882+
arg = $(this.entities.variable) || $(this.entities.literal)
883+
|| $(this.entities.keyword);
884+
}
885+
886+
if (!arg) {
887+
break;
888+
}
889+
868890
nameLoop = null;
869-
arg.throwAwayComments();
891+
if (arg.throwAwayComments) {
892+
arg.throwAwayComments();
893+
}
870894
value = arg;
895+
var val = null;
896+
897+
if (isCall) {
898+
// Variable
899+
if (arg.value.length == 1) {
900+
var val = arg.value[0];
901+
}
902+
} else {
903+
val = arg;
904+
}
871905

872-
// Variable
873-
if (arg.value.length == 1) {
874-
var val = arg.value[0];
875-
if (val instanceof tree.Variable) {
876-
if ($(':')) {
877-
if (expressions.length > 0) {
878-
if (isSemiColonSeperated) {
879-
error("Cannot mix ; and , as delimiter types");
880-
}
881-
expressionContainsNamed = true;
906+
if (val && val instanceof tree.Variable) {
907+
if ($(':')) {
908+
if (expressions.length > 0) {
909+
if (isSemiColonSeperated) {
910+
error("Cannot mix ; and , as delimiter types");
882911
}
883-
value = expect(this.expression);
884-
nameLoop = (name = val.name);
912+
expressionContainsNamed = true;
885913
}
914+
value = expect(this.expression);
915+
nameLoop = (name = val.name);
916+
} else if (!isCall && $(/^\.{3}/)) {
917+
returner.variadic = true;
918+
if ($(";") && !isSemiColonSeperated) {
919+
isSemiColonSeperated = true;
920+
}
921+
(isSemiColonSeperated ? argsSemiColon : argsComma)
922+
.push({ name: arg.name, variadic: true });
923+
break;
924+
} else if (!isCall) {
925+
name = nameLoop = val.name;
926+
value = null;
886927
}
887928
}
888929

889-
expressions.push(value);
930+
if (value) {
931+
expressions.push(value);
932+
}
890933

891934
argsComma.push({ name:nameLoop, value:value });
892935

@@ -913,8 +956,8 @@ less.Parser = function Parser(env) {
913956
}
914957
}
915958

916-
args = isSemiColonSeperated ? argsSemiColon : argsComma;
917-
return args;
959+
returner.args = isSemiColonSeperated ? argsSemiColon : argsComma;
960+
return returner;
918961
},
919962
//
920963
// A Mixin definition, with a list of parameters
@@ -945,33 +988,9 @@ less.Parser = function Parser(env) {
945988
if (match = $(/^([#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+)\s*\(/)) {
946989
name = match[1];
947990

948-
do {
949-
$(this.comment);
950-
if (input.charAt(i) === '.' && $(/^\.{3}/)) {
951-
variadic = true;
952-
params.push({ variadic: true });
953-
break;
954-
} else if (param = $(this.entities.variable) || $(this.entities.literal)
955-
|| $(this.entities.keyword)) {
956-
// Variable
957-
if (param instanceof tree.Variable) {
958-
if ($(':')) {
959-
value = expect(this.expression, 'expected expression');
960-
params.push({ name: param.name, value: value });
961-
} else if ($(/^\.{3}/)) {
962-
params.push({ name: param.name, variadic: true });
963-
variadic = true;
964-
break;
965-
} else {
966-
params.push({ name: param.name });
967-
}
968-
} else {
969-
params.push({ value: param });
970-
}
971-
} else {
972-
break;
973-
}
974-
} while ($(',') || $(';'))
991+
var argInfo = this.mixin.args.call(this, false);
992+
params = argInfo.args;
993+
variadic = argInfo.variadic;
975994

976995
// .mixincall("@{a}");
977996
// looks a bit like a mixin definition.. so we have to be nice and restore

test/css/mixins-args.css

+9
Original file line numberDiff line numberDiff line change
@@ -102,3 +102,12 @@ body {
102102
defaults: 1px 1px 1px;
103103
defaults: 2px 2px 2px;
104104
}
105+
.selector {
106+
margin: 2, 2, 2, 2;
107+
}
108+
.selector2 {
109+
margin: 2, 2, 2, 2;
110+
}
111+
.selector3 {
112+
margin: 4;
113+
}

test/less/mixins-args.less

+19
Original file line numberDiff line numberDiff line change
@@ -183,4 +183,23 @@ body {
183183
.test-mixin-default-arg {
184184
.mixin-default-arg();
185185
.mixin-default-arg(2px);
186+
}
187+
188+
.mixin-comma-default1(@color; @padding; @margin: 2, 2, 2, 2) {
189+
margin: @margin;
190+
}
191+
.selector {
192+
.mixin-comma-default1(#33acfe; 4);
193+
}
194+
.mixin-comma-default2(@margin: 2, 2, 2, 2;) {
195+
margin: @margin;
196+
}
197+
.selector2 {
198+
.mixin-comma-default2();
199+
}
200+
.mixin-comma-default3(@margin: 2, 2, 2, 2) {
201+
margin: @margin;
202+
}
203+
.selector3 {
204+
.mixin-comma-default3(4,2,2,2);
186205
}

0 commit comments

Comments
 (0)