diff --git a/lib/less/parser.js b/lib/less/parser.js index c6c993e6..62321666 100644 --- a/lib/less/parser.js +++ b/lib/less/parser.js @@ -785,7 +785,7 @@ less.Parser = function Parser(env) { memo = i; if ($(/^when/)) { // Guard - cond = expect(this.condition, 'expected condition'); + cond = expect(this.conditions, 'expected condition'); } ruleset = $(this.block); @@ -1158,22 +1158,33 @@ less.Parser = function Parser(env) { return operation || m; } }, + conditions: function () { + var a, b, index = i, condition; + + if (a = $(this.condition)) { + while ($(',') && (b = $(this.condition))) { + condition = new(tree.Condition)('or', condition || a, b, index); + } + return condition || a; + } + }, condition: function () { - var a, b, op, index = i, negate = false; + var a, b, c, op, index = i, negate = false; + expect('('); if ($('!')) { negate = true } if (a = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { if (op = $(/^(?:>=|=<|\!=|[<=>])/)) { if (b = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { - expect(')'); - return new(tree.Condition)(op, a, b, index); + c = new(tree.Condition)(op, a, b, index); } else { error('expected expression'); } } else { - expect(')'); - return new(tree.Condition)(negate ? '!=' : '=', a, new(tree.Keyword)('true'), index); + c = new(tree.Condition)(negate ? '!=' : '=', a, new(tree.Keyword)('true'), index); } + expect(')'); + return $(/^and/) ? new(tree.Condition)('and', c, $(this.condition)) : c; } }, diff --git a/lib/less/tree/condition.js b/lib/less/tree/condition.js index e6737a85..9dcdbf70 100644 --- a/lib/less/tree/condition.js +++ b/lib/less/tree/condition.js @@ -11,20 +11,27 @@ tree.Condition.prototype.eval = function (env) { b = this.rvalue.eval(env); var i = this.index, result - - if (a.compare) { - result = a.compare(b); - } else if (b.compare) { - result = b.compare(a); - } else { - throw { type: "Type", - message: "Unable to perform comparison", - index: i }; - } - switch (result) { - case -1: return this.op === '<' || this.op === '=<' || this.op === '!='; - case 0: return this.op === '=' || this.op === '>=' || this.op === '=<'; - case 1: return this.op === '>' || this.op === '>=' || this.op === '!='; + + switch (this.op) { + case 'and': + return a && b; + case 'or': + return a || b; + default: + if (a.compare) { + result = a.compare(b); + } else if (b.compare) { + result = b.compare(a); + } else { + throw { type: "Type", + message: "Unable to perform comparison", + index: i }; + } + switch (result) { + case -1: return this.op === '<' || this.op === '=<' || this.op === '!='; + case 0: return this.op === '=' || this.op === '>=' || this.op === '=<'; + case 1: return this.op === '>' || this.op === '>=' || this.op === '!='; + } } }; diff --git a/test/css/mixins-guards.css b/test/css/mixins-guards.css index 034ed67c..d7e92db3 100644 --- a/test/css/mixins-guards.css +++ b/test/css/mixins-guards.css @@ -45,3 +45,12 @@ .test5 { content: "false."; } +.bool1 { + content: true and true; + content: true; + content: false, true; + content: false and true and true, true; + content: false, true and true; + content: false, false, true; + content: false, true and true and true, false; +} diff --git a/test/less/mixins-guards.less b/test/less/mixins-guards.less index c6b5a316..c131c287 100644 --- a/test/less/mixins-guards.less +++ b/test/less/mixins-guards.less @@ -72,3 +72,19 @@ .test3 { .test(1) } .test4 { .test(boo) } .test5 { .test("true") } + +// Boolean expressions + +.bool () when (true) and (false) { content: true and false } // FALSE +.bool () when (true) and (true) { content: true and true } // TRUE +.bool () when (true) { content: true } // TRUE +.bool () when (false) and (false) { content: true } // FALSE +.bool () when (false), (true) { content: false, true } // TRUE +.bool () when (false) and (true) and (true), (true) { content: false and true and true, true } // TRUE +.bool () when (true) and (true) and (false), (false) { content: true and true and false, false } // FALSE +.bool () when (false), (true) and (true) { content: false, true and true } // TRUE +.bool () when (false), (false), (true) { content: false, false, true } // TRUE +.bool () when (false), (false) and (true), (false) { content: false, false and true, false } // FALSE +.bool () when (false), (true) and (true) and (true), (false) { content: false, true and true and true, false } // TRUE + +.bool1 { .bool }