mirror of
https://github.com/less/less.js.git
synced 2026-04-09 03:00:20 -04:00
Add modified (self altering) visitor pattern and class
This commit is contained in:
2
Makefile
2
Makefile
@@ -39,6 +39,7 @@ less:
|
||||
${SRC}/tree/*.js\
|
||||
${SRC}/tree.js\
|
||||
${SRC}/env.js\
|
||||
${SRC}/visitor.js\
|
||||
${SRC}/browser.js\
|
||||
build/amd.js >> ${DIST}
|
||||
@@echo "})(window);" >> ${DIST}
|
||||
@@ -60,6 +61,7 @@ rhino:
|
||||
build/ecma-5.js\
|
||||
${SRC}/parser.js\
|
||||
${SRC}/env.js\
|
||||
${SRC}/visitor.js\
|
||||
${SRC}/functions.js\
|
||||
${SRC}/colors.js\
|
||||
${SRC}/tree/*.js\
|
||||
|
||||
@@ -213,5 +213,6 @@ less.Parser.importer = function (file, paths, callback, env) {
|
||||
require('./env');
|
||||
require('./functions');
|
||||
require('./colors');
|
||||
require('./visitor.js');
|
||||
|
||||
for (var k in less) { exports[k] = less[k] }
|
||||
for (var k in less) { exports[k] = less[k]; }
|
||||
|
||||
@@ -4,13 +4,17 @@ tree.Alpha = function (val) {
|
||||
this.value = val;
|
||||
};
|
||||
tree.Alpha.prototype = {
|
||||
toCSS: function () {
|
||||
return "alpha(opacity=" +
|
||||
(this.value.toCSS ? this.value.toCSS() : this.value) + ")";
|
||||
type: "Alpha",
|
||||
accept: function (visitor) {
|
||||
this.value = visitor.visit(this.value);
|
||||
},
|
||||
eval: function (env) {
|
||||
if (this.value.eval) { this.value = this.value.eval(env) }
|
||||
return this;
|
||||
},
|
||||
toCSS: function () {
|
||||
return "alpha(opacity=" +
|
||||
(this.value.toCSS ? this.value.toCSS() : this.value) + ")";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ tree.Anonymous = function (string) {
|
||||
this.value = string.value || string;
|
||||
};
|
||||
tree.Anonymous.prototype = {
|
||||
type: "Anonymous",
|
||||
toCSS: function () {
|
||||
return this.value;
|
||||
},
|
||||
|
||||
@@ -5,6 +5,10 @@ tree.Assignment = function (key, val) {
|
||||
this.value = val;
|
||||
};
|
||||
tree.Assignment.prototype = {
|
||||
type: "Assignment",
|
||||
accept: function (visitor) {
|
||||
this.value = visitor.visit(this.value);
|
||||
},
|
||||
toCSS: function () {
|
||||
return this.key + '=' + (this.value.toCSS ? this.value.toCSS() : this.value);
|
||||
},
|
||||
|
||||
@@ -12,6 +12,10 @@ tree.Call = function (name, args, index, filename, rootpath, currentDirectory) {
|
||||
this.currentDirectory = currentDirectory;
|
||||
};
|
||||
tree.Call.prototype = {
|
||||
type: "Call",
|
||||
accept: function (visitor) {
|
||||
this.args = visitor.visit(this.args);
|
||||
},
|
||||
//
|
||||
// When evaluating a function call,
|
||||
// we either find the function in `tree.functions` [1],
|
||||
|
||||
@@ -23,6 +23,7 @@ tree.Color = function (rgb, a) {
|
||||
this.alpha = typeof(a) === 'number' ? a : 1;
|
||||
};
|
||||
tree.Color.prototype = {
|
||||
type: "Color",
|
||||
eval: function () { return this },
|
||||
luma: function () { return (0.2126 * this.rgb[0] / 255) + (0.7152 * this.rgb[1] / 255) + (0.0722 * this.rgb[2] / 255); },
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ tree.Comment = function (value, silent) {
|
||||
this.silent = !!silent;
|
||||
};
|
||||
tree.Comment.prototype = {
|
||||
type: "Comment",
|
||||
toCSS: function (env) {
|
||||
return env.compress ? '' : this.value;
|
||||
},
|
||||
|
||||
@@ -7,36 +7,43 @@ tree.Condition = function (op, l, r, i, negate) {
|
||||
this.index = i;
|
||||
this.negate = negate;
|
||||
};
|
||||
tree.Condition.prototype.eval = function (env) {
|
||||
var a = this.lvalue.eval(env),
|
||||
b = this.rvalue.eval(env);
|
||||
tree.Condition.prototype = {
|
||||
type: "Condition",
|
||||
accept: function (visitor) {
|
||||
this.lvalue = visitor.visit(this.lvalue);
|
||||
this.rvalue = visitor.visit(this.rvalue);
|
||||
},
|
||||
eval: function (env) {
|
||||
var a = this.lvalue.eval(env),
|
||||
b = this.rvalue.eval(env);
|
||||
|
||||
var i = this.index, result;
|
||||
var i = this.index, result;
|
||||
|
||||
var result = (function (op) {
|
||||
switch (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 op === '<' || op === '=<';
|
||||
case 0: return op === '=' || op === '>=' || op === '=<';
|
||||
case 1: return op === '>' || op === '>=';
|
||||
}
|
||||
}
|
||||
})(this.op);
|
||||
return this.negate ? !result : result;
|
||||
var result = (function (op) {
|
||||
switch (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 op === '<' || op === '=<';
|
||||
case 0: return op === '=' || op === '>=' || op === '=<';
|
||||
case 1: return op === '>' || op === '>=';
|
||||
}
|
||||
}
|
||||
})(this.op);
|
||||
return this.negate ? !result : result;
|
||||
}
|
||||
};
|
||||
|
||||
})(require('../tree'));
|
||||
|
||||
@@ -10,6 +10,10 @@ tree.Dimension = function (value, unit) {
|
||||
};
|
||||
|
||||
tree.Dimension.prototype = {
|
||||
type: "Dimension",
|
||||
accept: function (visitor) {
|
||||
this.unit = visitor.visit(this.unit);
|
||||
},
|
||||
eval: function (env) {
|
||||
return this;
|
||||
},
|
||||
@@ -172,6 +176,7 @@ tree.Unit = function (numerator, denominator) {
|
||||
};
|
||||
|
||||
tree.Unit.prototype = {
|
||||
type: "Unit",
|
||||
clone: function () {
|
||||
return new tree.Unit(this.numerator.slice(0), this.denominator.slice(0));
|
||||
},
|
||||
|
||||
@@ -11,6 +11,11 @@ tree.Directive = function (name, value) {
|
||||
}
|
||||
};
|
||||
tree.Directive.prototype = {
|
||||
type: "Directive",
|
||||
accept: function (visitor) {
|
||||
this.ruleset = visitor.visit(this.ruleset);
|
||||
this.value = visitor.visit(this.value);
|
||||
},
|
||||
toCSS: function (ctx, env) {
|
||||
if (this.ruleset) {
|
||||
this.ruleset.root = true;
|
||||
|
||||
@@ -13,17 +13,24 @@ tree.Element = function (combinator, value, index) {
|
||||
}
|
||||
this.index = index;
|
||||
};
|
||||
tree.Element.prototype.eval = function (env) {
|
||||
return new(tree.Element)(this.combinator,
|
||||
this.value.eval ? this.value.eval(env) : this.value,
|
||||
this.index);
|
||||
};
|
||||
tree.Element.prototype.toCSS = function (env) {
|
||||
var value = (this.value.toCSS ? this.value.toCSS(env) : this.value);
|
||||
if (value == '' && this.combinator.value.charAt(0) == '&') {
|
||||
return '';
|
||||
} else {
|
||||
return this.combinator.toCSS(env || {}) + value;
|
||||
tree.Element.prototype = {
|
||||
type: "Element",
|
||||
accept: function (visitor) {
|
||||
this.combinator = visitor.visit(this.combinator);
|
||||
this.value = visitor.visit(this.value);
|
||||
},
|
||||
eval: function (env) {
|
||||
return new(tree.Element)(this.combinator,
|
||||
this.value.eval ? this.value.eval(env) : this.value,
|
||||
this.index);
|
||||
},
|
||||
toCSS: function (env) {
|
||||
var value = (this.value.toCSS ? this.value.toCSS(env) : this.value);
|
||||
if (value == '' && this.combinator.value.charAt(0) == '&') {
|
||||
return '';
|
||||
} else {
|
||||
return this.combinator.toCSS(env || {}) + value;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -34,16 +41,19 @@ tree.Combinator = function (value) {
|
||||
this.value = value ? value.trim() : "";
|
||||
}
|
||||
};
|
||||
tree.Combinator.prototype.toCSS = function (env) {
|
||||
return {
|
||||
'' : '',
|
||||
' ' : ' ',
|
||||
':' : ' :',
|
||||
'+' : env.compress ? '+' : ' + ',
|
||||
'~' : env.compress ? '~' : ' ~ ',
|
||||
'>' : env.compress ? '>' : ' > ',
|
||||
'|' : env.compress ? '|' : ' | '
|
||||
}[this.value];
|
||||
tree.Combinator.prototype = {
|
||||
type: "Combinator",
|
||||
toCSS: function (env) {
|
||||
return {
|
||||
'' : '',
|
||||
' ' : ' ',
|
||||
':' : ' :',
|
||||
'+' : env.compress ? '+' : ' + ',
|
||||
'~' : env.compress ? '~' : ' ~ ',
|
||||
'>' : env.compress ? '>' : ' > ',
|
||||
'|' : env.compress ? '|' : ' | '
|
||||
}[this.value];
|
||||
}
|
||||
};
|
||||
|
||||
})(require('../tree'));
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
|
||||
tree.Expression = function (value) { this.value = value; };
|
||||
tree.Expression.prototype = {
|
||||
type: "Expression",
|
||||
accept: function (visitor) {
|
||||
this.value = visitor.visit(this.value);
|
||||
},
|
||||
eval: function (env) {
|
||||
var returnValue,
|
||||
inParenthesis = this.parens && !this.parensInOp,
|
||||
|
||||
@@ -6,34 +6,40 @@ tree.Extend = function Extend(elements, option, index) {
|
||||
this.index = index;
|
||||
};
|
||||
|
||||
tree.Extend.prototype.eval = function Extend_eval(env, selectors) {
|
||||
var selfSelectors = findSelfSelectors(selectors || env.selectors),
|
||||
targetValue = this.selector.elements[0].value;
|
||||
tree.Extend.prototype = {
|
||||
type: "Extend",
|
||||
accept: function (visitor) {
|
||||
this.selector = visitor.visit(this.ruleset);
|
||||
},
|
||||
eval: function (env, selectors) {
|
||||
var selfSelectors = findSelfSelectors(selectors || env.selectors),
|
||||
targetValue = this.selector.elements[0].value;
|
||||
|
||||
env.frames.forEach(function(frame) {
|
||||
frame.rulesets().forEach(function(rule) {
|
||||
rule.selectors.forEach(function(selector) {
|
||||
selector.elements.forEach(function(element, idx) {
|
||||
if (element.value === targetValue) {
|
||||
selfSelectors.forEach(function(_selector) {
|
||||
_selector.elements[0] = new tree.Element(
|
||||
element.combinator,
|
||||
_selector.elements[0].value,
|
||||
_selector.elements[0].index
|
||||
);
|
||||
rule.selectors.push(new tree.Selector(
|
||||
selector.elements
|
||||
.slice(0, idx)
|
||||
.concat(_selector.elements)
|
||||
.concat(selector.elements.slice(idx + 1))
|
||||
));
|
||||
});
|
||||
}
|
||||
env.frames.forEach(function(frame) {
|
||||
frame.rulesets().forEach(function(rule) {
|
||||
rule.selectors.forEach(function(selector) {
|
||||
selector.elements.forEach(function(element, idx) {
|
||||
if (element.value === targetValue) {
|
||||
selfSelectors.forEach(function(_selector) {
|
||||
_selector.elements[0] = new tree.Element(
|
||||
element.combinator,
|
||||
_selector.elements[0].value,
|
||||
_selector.elements[0].index
|
||||
);
|
||||
rule.selectors.push(new tree.Selector(
|
||||
selector.elements
|
||||
.slice(0, idx)
|
||||
.concat(_selector.elements)
|
||||
.concat(selector.elements.slice(idx + 1))
|
||||
));
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
return this;
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
function findSelfSelectors(selectors) {
|
||||
@@ -53,5 +59,4 @@ function findSelfSelectors(selectors) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
})(require('../tree'));
|
||||
|
||||
@@ -49,6 +49,11 @@ tree.Import = function (path, imports, features, once, index, rootpath) {
|
||||
// ruleset.
|
||||
//
|
||||
tree.Import.prototype = {
|
||||
type: "Import",
|
||||
accept: function (visitor) {
|
||||
this.features = visitor.visit(this.features);
|
||||
this._path = visitor.visit(this._path);
|
||||
},
|
||||
toCSS: function (env) {
|
||||
var features = this.features ? ' ' + this.features.toCSS(env) : '';
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ tree.JavaScript = function (string, index, escaped) {
|
||||
this.index = index;
|
||||
};
|
||||
tree.JavaScript.prototype = {
|
||||
type: "JavaScript",
|
||||
eval: function (env) {
|
||||
var result,
|
||||
that = this,
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
|
||||
tree.Keyword = function (value) { this.value = value };
|
||||
tree.Keyword.prototype = {
|
||||
eval: function () { return this },
|
||||
toCSS: function () { return this.value },
|
||||
type: "Keyword",
|
||||
eval: function () { return this; },
|
||||
toCSS: function () { return this.value; },
|
||||
compare: function (other) {
|
||||
if (other instanceof tree.Keyword) {
|
||||
return other.value === this.value ? 0 : 1;
|
||||
|
||||
@@ -8,6 +8,11 @@ tree.Media = function (value, features) {
|
||||
this.ruleset.allowImports = true;
|
||||
};
|
||||
tree.Media.prototype = {
|
||||
type: "Media",
|
||||
accept: function (visitor) {
|
||||
this.features = visitor.visit(this.features);
|
||||
this.ruleset = visitor.visit(this.ruleset);
|
||||
},
|
||||
toCSS: function (ctx, env) {
|
||||
var features = this.features.toCSS(env);
|
||||
|
||||
|
||||
@@ -9,6 +9,11 @@ tree.mixin.Call = function (elements, args, index, filename, important) {
|
||||
this.important = important;
|
||||
};
|
||||
tree.mixin.Call.prototype = {
|
||||
type: "MixinCall",
|
||||
accept: function (visitor) {
|
||||
this.selector = visitor.visit(this.selector);
|
||||
this.arguments = visitor.visit(this.arguments);
|
||||
},
|
||||
eval: function (env) {
|
||||
var mixins, mixin, args, rules = [], match = false, i, m, f, isRecursive, isOneFound;
|
||||
|
||||
@@ -90,11 +95,17 @@ tree.mixin.Definition = function (name, params, rules, condition, variadic) {
|
||||
this.frames = [];
|
||||
};
|
||||
tree.mixin.Definition.prototype = {
|
||||
toCSS: function () { return "" },
|
||||
variable: function (name) { return this.parent.variable.call(this, name) },
|
||||
variables: function () { return this.parent.variables.call(this) },
|
||||
find: function () { return this.parent.find.apply(this, arguments) },
|
||||
rulesets: function () { return this.parent.rulesets.apply(this) },
|
||||
type: "MixinDefinition",
|
||||
accept: function (visitor) {
|
||||
this.params = visitor.visit(this.params);
|
||||
this.rules = visitor.visit(this.rules);
|
||||
this.condition = visitor.visit(this.condition);
|
||||
},
|
||||
toCSS: function () { return ""; },
|
||||
variable: function (name) { return this.parent.variable.call(this, name); },
|
||||
variables: function () { return this.parent.variables.call(this); },
|
||||
find: function () { return this.parent.find.apply(this, arguments); },
|
||||
rulesets: function () { return this.parent.rulesets.apply(this); },
|
||||
|
||||
evalParams: function (env, mixinEnv, args, evaldArguments) {
|
||||
var frame = new(tree.Ruleset)(null, []),
|
||||
|
||||
@@ -4,6 +4,10 @@ tree.Negative = function (node) {
|
||||
this.value = node;
|
||||
};
|
||||
tree.Negative.prototype = {
|
||||
type: "Negative",
|
||||
accept: function (visitor) {
|
||||
this.value = visitor.visit(this.value);
|
||||
},
|
||||
toCSS: function (env) {
|
||||
return '-' + this.value.toCSS(env);
|
||||
},
|
||||
|
||||
@@ -5,34 +5,40 @@ tree.Operation = function (op, operands, isSpaced) {
|
||||
this.operands = operands;
|
||||
this.isSpaced = isSpaced;
|
||||
};
|
||||
tree.Operation.prototype.eval = function (env) {
|
||||
var a = this.operands[0].eval(env),
|
||||
b = this.operands[1].eval(env),
|
||||
temp;
|
||||
tree.Operation.prototype = {
|
||||
type: "Operation",
|
||||
accept: function (visitor) {
|
||||
this.operands = visitor.visit(this.operands);
|
||||
},
|
||||
eval: function (env) {
|
||||
var a = this.operands[0].eval(env),
|
||||
b = this.operands[1].eval(env),
|
||||
temp;
|
||||
|
||||
if (env.isMathsOn()) {
|
||||
if (a instanceof tree.Dimension && b instanceof tree.Color) {
|
||||
if (this.op === '*' || this.op === '+') {
|
||||
temp = b, b = a, a = temp;
|
||||
} else {
|
||||
throw { type: "Operation",
|
||||
message: "Can't substract or divide a color from a number" };
|
||||
if (env.isMathsOn()) {
|
||||
if (a instanceof tree.Dimension && b instanceof tree.Color) {
|
||||
if (this.op === '*' || this.op === '+') {
|
||||
temp = b, b = a, a = temp;
|
||||
} else {
|
||||
throw { type: "Operation",
|
||||
message: "Can't substract or divide a color from a number" };
|
||||
}
|
||||
}
|
||||
if (!a.operate) {
|
||||
throw { type: "Operation",
|
||||
message: "Operation on an invalid type" };
|
||||
}
|
||||
}
|
||||
if (!a.operate) {
|
||||
throw { type: "Operation",
|
||||
message: "Operation on an invalid type" };
|
||||
}
|
||||
|
||||
return a.operate(env, this.op, b);
|
||||
} else {
|
||||
return new(tree.Operation)(this.op, [a, b], this.isSpaced);
|
||||
return a.operate(env, this.op, b);
|
||||
} else {
|
||||
return new(tree.Operation)(this.op, [a, b], this.isSpaced);
|
||||
}
|
||||
},
|
||||
toCSS: function (env) {
|
||||
var separator = this.isSpaced ? " " : "";
|
||||
return this.operands[0].toCSS() + separator + this.op + separator + this.operands[1].toCSS();
|
||||
}
|
||||
};
|
||||
tree.Operation.prototype.toCSS = function (env) {
|
||||
var separator = this.isSpaced ? " " : "";
|
||||
return this.operands[0].toCSS() + separator + this.op + separator + this.operands[1].toCSS();
|
||||
};
|
||||
|
||||
tree.operate = function (env, op, a, b) {
|
||||
switch (op) {
|
||||
|
||||
@@ -5,6 +5,10 @@ tree.Paren = function (node) {
|
||||
this.value = node;
|
||||
};
|
||||
tree.Paren.prototype = {
|
||||
type: "Paren",
|
||||
accept: function (visitor) {
|
||||
this.value = visitor.visit(this.value);
|
||||
},
|
||||
toCSS: function (env) {
|
||||
return '(' + this.value.toCSS(env).trim() + ')';
|
||||
},
|
||||
|
||||
@@ -7,6 +7,7 @@ tree.Quoted = function (str, content, escaped, i) {
|
||||
this.index = i;
|
||||
};
|
||||
tree.Quoted.prototype = {
|
||||
type: "Quoted",
|
||||
toCSS: function () {
|
||||
if (this.escaped) {
|
||||
return this.value;
|
||||
|
||||
@@ -11,39 +11,44 @@ tree.Rule = function (name, value, important, index, inline) {
|
||||
this.variable = true;
|
||||
} else { this.variable = false }
|
||||
};
|
||||
tree.Rule.prototype.toCSS = function (env) {
|
||||
if (this.variable) { return "" }
|
||||
else {
|
||||
return this.name + (env.compress ? ':' : ': ') +
|
||||
this.value.toCSS(env) +
|
||||
this.important + (this.inline ? "" : ";");
|
||||
}
|
||||
};
|
||||
|
||||
tree.Rule.prototype.eval = function (env) {
|
||||
var strictMathsBypass = false;
|
||||
if (this.name === "font" && env.strictMaths === false) {
|
||||
strictMathsBypass = true;
|
||||
env.strictMaths = true;
|
||||
}
|
||||
try {
|
||||
return new(tree.Rule)(this.name,
|
||||
this.value.eval(env),
|
||||
this.important,
|
||||
this.index, this.inline);
|
||||
}
|
||||
finally {
|
||||
if (strictMathsBypass) {
|
||||
env.strictMaths = false;
|
||||
tree.Rule.prototype = {
|
||||
type: "Rule",
|
||||
accept: function (visitor) {
|
||||
this.value = visitor.visit(this.value);
|
||||
},
|
||||
toCSS: function (env) {
|
||||
if (this.variable) { return "" }
|
||||
else {
|
||||
return this.name + (env.compress ? ':' : ': ') +
|
||||
this.value.toCSS(env) +
|
||||
this.important + (this.inline ? "" : ";");
|
||||
}
|
||||
},
|
||||
eval: function (env) {
|
||||
var strictMathsBypass = false;
|
||||
if (this.name === "font" && env.strictMaths === false) {
|
||||
strictMathsBypass = true;
|
||||
env.strictMaths = true;
|
||||
}
|
||||
try {
|
||||
return new(tree.Rule)(this.name,
|
||||
this.value.eval(env),
|
||||
this.important,
|
||||
this.index, this.inline);
|
||||
}
|
||||
finally {
|
||||
if (strictMathsBypass) {
|
||||
env.strictMaths = false;
|
||||
}
|
||||
}
|
||||
},
|
||||
makeImportant: function () {
|
||||
return new(tree.Rule)(this.name,
|
||||
this.value,
|
||||
"!important",
|
||||
this.index, this.inline);
|
||||
}
|
||||
};
|
||||
|
||||
tree.Rule.prototype.makeImportant = function () {
|
||||
return new(tree.Rule)(this.name,
|
||||
this.value,
|
||||
"!important",
|
||||
this.index, this.inline);
|
||||
};
|
||||
|
||||
})(require('../tree'));
|
||||
|
||||
@@ -7,6 +7,11 @@ tree.Ruleset = function (selectors, rules, strictImports) {
|
||||
this.strictImports = strictImports;
|
||||
};
|
||||
tree.Ruleset.prototype = {
|
||||
type: "Ruleset",
|
||||
accept: function (visitor) {
|
||||
this.selectors = visitor.visit(this.selectors);
|
||||
this.rules = visitor.visit(this.rules);
|
||||
},
|
||||
eval: function (env) {
|
||||
var selectors = this.selectors && this.selectors.map(function (s) { return s.eval(env) });
|
||||
var ruleset = new(tree.Ruleset)(selectors, this.rules.slice(0), this.strictImports);
|
||||
|
||||
@@ -4,50 +4,56 @@ tree.Selector = function (elements, extend) {
|
||||
this.elements = elements;
|
||||
this.extend = extend;
|
||||
};
|
||||
tree.Selector.prototype.match = function (other) {
|
||||
var elements = this.elements,
|
||||
len = elements.length,
|
||||
oelements, olen, max, i;
|
||||
tree.Selector.prototype = {
|
||||
type: "Selector",
|
||||
accept: function (visitor) {
|
||||
this.elements = visitor.visit(this.elements);
|
||||
},
|
||||
match: function (other) {
|
||||
var elements = this.elements,
|
||||
len = elements.length,
|
||||
oelements, olen, max, i;
|
||||
|
||||
oelements = other.elements.slice(
|
||||
(other.elements.length && other.elements[0].value === "&") ? 1 : 0);
|
||||
olen = oelements.length;
|
||||
max = Math.min(len, olen)
|
||||
oelements = other.elements.slice(
|
||||
(other.elements.length && other.elements[0].value === "&") ? 1 : 0);
|
||||
olen = oelements.length;
|
||||
max = Math.min(len, olen);
|
||||
|
||||
if (olen === 0 || len < olen) {
|
||||
return false;
|
||||
} else {
|
||||
for (i = 0; i < max; i++) {
|
||||
if (elements[i].value !== oelements[i].value) {
|
||||
return false;
|
||||
if (olen === 0 || len < olen) {
|
||||
return false;
|
||||
} else {
|
||||
for (i = 0; i < max; i++) {
|
||||
if (elements[i].value !== oelements[i].value) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
tree.Selector.prototype.eval = function (env) {
|
||||
return new(tree.Selector)(this.elements.map(function (e) {
|
||||
return e.eval(env);
|
||||
}), this.extend);
|
||||
};
|
||||
tree.Selector.prototype.toCSS = function (env) {
|
||||
if (this._css) { return this._css }
|
||||
|
||||
if (this.elements[0].combinator.value === "") {
|
||||
this._css = ' ';
|
||||
} else {
|
||||
this._css = '';
|
||||
}
|
||||
|
||||
this._css += this.elements.map(function (e) {
|
||||
if (typeof(e) === 'string') {
|
||||
return ' ' + e.trim();
|
||||
return true;
|
||||
},
|
||||
eval: function (env) {
|
||||
return new(tree.Selector)(this.elements.map(function (e) {
|
||||
return e.eval(env);
|
||||
}), this.extend);
|
||||
},
|
||||
toCSS: function (env) {
|
||||
if (this._css) { return this._css }
|
||||
|
||||
if (this.elements[0].combinator.value === "") {
|
||||
this._css = ' ';
|
||||
} else {
|
||||
return e.toCSS(env);
|
||||
this._css = '';
|
||||
}
|
||||
}).join('');
|
||||
|
||||
return this._css;
|
||||
|
||||
this._css += this.elements.map(function (e) {
|
||||
if (typeof(e) === 'string') {
|
||||
return ' ' + e.trim();
|
||||
} else {
|
||||
return e.toCSS(env);
|
||||
}
|
||||
}).join('');
|
||||
|
||||
return this._css;
|
||||
}
|
||||
};
|
||||
|
||||
})(require('../tree'));
|
||||
|
||||
@@ -4,6 +4,7 @@ tree.UnicodeDescriptor = function (value) {
|
||||
this.value = value;
|
||||
};
|
||||
tree.UnicodeDescriptor.prototype = {
|
||||
type: "UnicodeDescriptor",
|
||||
toCSS: function (env) {
|
||||
return this.value;
|
||||
},
|
||||
|
||||
@@ -5,6 +5,10 @@ tree.URL = function (val, rootpath) {
|
||||
this.rootpath = rootpath;
|
||||
};
|
||||
tree.URL.prototype = {
|
||||
type: "Url",
|
||||
accept: function (visitor) {
|
||||
this.value = visitor.visit(this.value);
|
||||
},
|
||||
toCSS: function () {
|
||||
return "url(" + this.value.toCSS() + ")";
|
||||
},
|
||||
|
||||
@@ -2,9 +2,12 @@
|
||||
|
||||
tree.Value = function (value) {
|
||||
this.value = value;
|
||||
this.is = 'value';
|
||||
};
|
||||
tree.Value.prototype = {
|
||||
type: "Value",
|
||||
accept: function (visitor) {
|
||||
this.value = visitor.visit(this.value);
|
||||
},
|
||||
eval: function (env) {
|
||||
if (this.value.length === 1) {
|
||||
return this.value[0].eval(env);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
tree.Variable = function (name, index, file) { this.name = name, this.index = index, this.file = file };
|
||||
tree.Variable.prototype = {
|
||||
type: "Variable",
|
||||
eval: function (env) {
|
||||
var variable, v, name = this.name;
|
||||
|
||||
|
||||
44
lib/less/visitor.js
Normal file
44
lib/less/visitor.js
Normal file
@@ -0,0 +1,44 @@
|
||||
(function (tree) {
|
||||
|
||||
tree.visitor = function(implementation) {
|
||||
this._implementation = implementation;
|
||||
};
|
||||
|
||||
tree.visitor.prototype = {
|
||||
visit: function(node) {
|
||||
|
||||
if (node instanceof Array) {
|
||||
return this.visitArray(node);
|
||||
}
|
||||
|
||||
if (!node || !node.type) {
|
||||
return node;
|
||||
}
|
||||
|
||||
var funcName = "visit" + node.type,
|
||||
func = this._implementation[funcName],
|
||||
visitArgs;
|
||||
if (func) {
|
||||
visitArgs = {visitDeeper: true};
|
||||
node = func(node);
|
||||
}
|
||||
if ((!visitArgs || visitArgs.visitDeeper) && node.accept) {
|
||||
node.accept(this);
|
||||
}
|
||||
return node;
|
||||
},
|
||||
visitArray: function(nodes) {
|
||||
var i, newNodes;
|
||||
for(i = 0; i < nodes.length; i++) {
|
||||
var evald = this.visit(nodes[i]);
|
||||
if (evald instanceof Array) {
|
||||
newNodes = newNodes.concat(evald);
|
||||
} else {
|
||||
newNodes.push(evald);
|
||||
}
|
||||
}
|
||||
return newNodes;
|
||||
}
|
||||
};
|
||||
|
||||
})(require('./tree'));
|
||||
Reference in New Issue
Block a user