Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions lib/less/functions/boolean.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@

var functionRegistry = require("./function-registry"),
Anonymous = require("../tree/anonymous"),
Keyword = require("../tree/keyword");

functionRegistry.addMultiple({
boolean: function(condition) {
return condition ? Keyword.True : Keyword.False;
},

'if': function(condition, trueValue, falseValue) {
return condition ? trueValue
: (falseValue || new Anonymous);
}
});
1 change: 1 addition & 0 deletions lib/less/functions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ module.exports = function(environment) {
};

// register functions
require("./boolean");
require("./default");
require("./color");
require("./color-blending");
Expand Down
107 changes: 66 additions & 41 deletions lib/less/parser/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -383,13 +383,10 @@ var Parser = function Parser(context, imports, fileInfo) {
//
// rgb(255, 0, 255)
//
// We also try to catch IE's `alpha()`, but let the `alpha` parser
// deal with the details.
//
// The arguments are parsed with the `entities.arguments` parser.
//
call: function () {
var name, nameLC, args, alpha, index = parserInput.i;
var name, args, func, index = parserInput.i;

// http://jsperf.com/case-insensitive-regex-vs-strtolower-then-regex/18
if (parserInput.peek(/^url\(/i)) {
Expand All @@ -399,20 +396,22 @@ var Parser = function Parser(context, imports, fileInfo) {
parserInput.save();

name = parserInput.$re(/^([\w-]+|%|progid:[\w\.]+)\(/);
if (!name) { parserInput.forget(); return; }
if (!name) {
parserInput.forget();
return;
}

name = name[1];
nameLC = name.toLowerCase();

if (nameLC === 'alpha') {
alpha = parsers.alpha();
if (alpha) {
func = this.customFuncCall(name);
if (func) {
args = func.parse();
if (args && func.stop) {
parserInput.forget();
return alpha;
return args;
}
}

args = this.arguments();
args = this.arguments(args);

if (!parserInput.$char(')')) {
parserInput.restore("Could not parse call arguments or missing ')'");
Expand All @@ -422,47 +421,72 @@ var Parser = function Parser(context, imports, fileInfo) {
parserInput.forget();
return new(tree.Call)(name, args, index, fileInfo);
},
arguments: function () {
var argsSemiColon = [], argsComma = [],
expressions = [],
isSemiColonSeparated, value, arg;

parserInput.save();

//
// Parsing rules for functions with non-standard args, e.g.:
//
// boolean(not(2 > 1))
//
// This is a quick prototype, to be modified/improved when
// more custom-parsed funcs come (e.g. `selector(...)`)
//

while (true) {
customFuncCall: function (name) {
/* Ideally the table is to be moved out of here for faster perf.,
but it's quite tricky since it relies on all these `parsers`
and `expect` available only here */
return {
alpha: f(parsers.ieAlpha, true),
boolean: f(condition),
'if': f(condition)
}[name.toLowerCase()];

function f(parse, stop) {
return {
parse: parse, // parsing function
stop: stop // when true - stop after parse() and return its result,
// otherwise continue for plain args
};
}

function condition() {
return [expect(parsers.condition, 'expected condition')];
}
},

arg = parsers.detachedRuleset() || this.assignment() || parsers.expression();
arguments: function (prevArgs) {
var argsComma = prevArgs || [],
argsSemiColon = [],
isSemiColonSeparated, value;

if (!arg) {
break;
}
parserInput.save();

value = arg;
while (true) {
if (prevArgs) {
prevArgs = false;
} else {
value = parsers.detachedRuleset() || this.assignment() || parsers.expression();
if (!value) {
break;
}

if (arg.value && arg.value.length == 1) {
value = arg.value[0];
}
if (value.value && value.value.length == 1) {
value = value.value[0];
}

if (value) {
expressions.push(value);
argsComma.push(value);
}

argsComma.push(value);

if (parserInput.$char(',')) {
continue;
}

if (parserInput.$char(';') || isSemiColonSeparated) {

isSemiColonSeparated = true;

if (expressions.length > 1) {
value = new(tree.Value)(expressions);
}
value = (argsComma.length < 1) ? argsComma[0]
: new tree.Value(argsComma);
argsSemiColon.push(value);

expressions = [];
argsComma = [];
}
}

Expand Down Expand Up @@ -1019,17 +1043,18 @@ var Parser = function Parser(context, imports, fileInfo) {
//
// alpha(opacity=88)
//
alpha: function () {
ieAlpha: function () {
var value;

// http://jsperf.com/case-insensitive-regex-vs-strtolower-then-regex/18
if (!parserInput.$re(/^opacity=/i)) { return; }
value = parserInput.$re(/^\d+/);
if (!value) {
value = expect(this.entities.variable, "Could not parse alpha");
value = expect(parsers.entities.variable, "Could not parse alpha");
value = '@{' + value.name.slice(1) + '}';
}
expectChar(')');
return new(tree.Alpha)(value);
return new tree.Quoted('', 'alpha(opacity=' + value + ')');
},

//
Expand Down
28 changes: 0 additions & 28 deletions lib/less/tree/alpha.js

This file was deleted.

1 change: 0 additions & 1 deletion lib/less/tree/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
var tree = Object.create(null);

tree.Node = require('./node');
tree.Alpha = require('./alpha');
tree.Color = require('./color');
tree.AtRule = require('./atrule');
// Backwards compatibility
Expand Down
13 changes: 13 additions & 0 deletions test/css/functions.css
Original file line number Diff line number Diff line change
Expand Up @@ -199,3 +199,16 @@
html {
color: #8080ff;
}
#boolean {
a: true;
b: false;
c: false;
}
#if {
a: 1;
b: 2;
c: 3;
e: ;
f: 6;
/* results in void */
}
2 changes: 0 additions & 2 deletions test/less/errors/functions-2-alpha.less

This file was deleted.

3 changes: 0 additions & 3 deletions test/less/errors/functions-2-alpha.txt

This file was deleted.

17 changes: 17 additions & 0 deletions test/less/functions.less
Original file line number Diff line number Diff line change
Expand Up @@ -231,3 +231,20 @@ html {
color: mix(blue, @color2, 50%);
}

#boolean {
a: boolean(not(2 < 1));
b: boolean(not(2 > 1) and (true));
c: boolean(not(boolean((true))));
}

#if {
a: if(not(false), 1, 2);
b: if(not(true), 1, 2);
@1: if(not(false), {c: 3}, {d: 4}); @1();

e: if(not(true), 5);
@f: boolean((3 = 4));
f: if(not(@f), 6);

if((false), {g: 7}); /* results in void */
}
3 changes: 0 additions & 3 deletions test/less/plugin/plugin-tree-nodes.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,6 @@ functions.addMultiple({
return true;
},
// These cause root errors
"test-alpha": function() {
return less.Alpha(30);
},
"test-assignment": function() {
return less.Assignment("bird", "robin");
},
Expand Down