mirror of
https://github.com/less/less.js.git
synced 2026-05-01 03:00:22 -04:00
special functions: add boolean and if, clean up alpha
This commit is contained in:
15
lib/less/functions/boolean.js
Normal file
15
lib/less/functions/boolean.js
Normal file
@@ -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);
|
||||
}
|
||||
});
|
||||
@@ -5,6 +5,7 @@ module.exports = function(environment) {
|
||||
};
|
||||
|
||||
// register functions
|
||||
require("./boolean");
|
||||
require("./default");
|
||||
require("./color");
|
||||
require("./color-blending");
|
||||
|
||||
@@ -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)) {
|
||||
@@ -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 ')'");
|
||||
@@ -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;
|
||||
|
||||
//
|
||||
// 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(...)`)
|
||||
//
|
||||
|
||||
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')];
|
||||
}
|
||||
},
|
||||
|
||||
arguments: function (prevArgs) {
|
||||
var argsComma = prevArgs || [],
|
||||
argsSemiColon = [],
|
||||
isSemiColonSeparated, value;
|
||||
|
||||
parserInput.save();
|
||||
|
||||
while (true) {
|
||||
if (prevArgs) {
|
||||
prevArgs = false;
|
||||
} else {
|
||||
value = parsers.detachedRuleset() || this.assignment() || parsers.expression();
|
||||
if (!value) {
|
||||
break;
|
||||
}
|
||||
|
||||
arg = parsers.detachedRuleset() || this.assignment() || parsers.expression();
|
||||
if (value.value && value.value.length == 1) {
|
||||
value = value.value[0];
|
||||
}
|
||||
|
||||
if (!arg) {
|
||||
break;
|
||||
argsComma.push(value);
|
||||
}
|
||||
|
||||
value = arg;
|
||||
|
||||
if (arg.value && arg.value.length == 1) {
|
||||
value = arg.value[0];
|
||||
}
|
||||
|
||||
if (value) {
|
||||
expressions.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 = [];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 + ')');
|
||||
},
|
||||
|
||||
//
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
var Node = require("./node");
|
||||
|
||||
var Alpha = function (val) {
|
||||
this.value = val;
|
||||
};
|
||||
Alpha.prototype = new Node();
|
||||
Alpha.prototype.type = "Alpha";
|
||||
|
||||
Alpha.prototype.accept = function (visitor) {
|
||||
this.value = visitor.visit(this.value);
|
||||
};
|
||||
Alpha.prototype.eval = function (context) {
|
||||
if (this.value.eval) { return new Alpha(this.value.eval(context)); }
|
||||
return this;
|
||||
};
|
||||
Alpha.prototype.genCSS = function (context, output) {
|
||||
output.add("alpha(opacity=");
|
||||
|
||||
if (this.value.genCSS) {
|
||||
this.value.genCSS(context, output);
|
||||
} else {
|
||||
output.add(this.value);
|
||||
}
|
||||
|
||||
output.add(")");
|
||||
};
|
||||
|
||||
module.exports = Alpha;
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
}
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
@plugin "../plugin/plugin-tree-nodes";
|
||||
test-alpha();
|
||||
@@ -1,3 +0,0 @@
|
||||
SyntaxError: Alpha node returned by a function is not valid here in {path}functions-2-alpha.less on line 2, column 1:
|
||||
1 @plugin "../plugin/plugin-tree-nodes";
|
||||
2 test-alpha();
|
||||
@@ -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 */
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user