Added support for variables in certain at-rules (keyframes, namespace, charset).

This commit is contained in:
seven-phases-max
2014-02-09 13:42:01 +04:00
parent 72c0cff78b
commit 09c4311594
9 changed files with 118 additions and 56 deletions

View File

@@ -1662,7 +1662,7 @@ less.Parser = function Parser(env) {
//
directive: function () {
var index = i, name, value, rules, nonVendorSpecificName,
hasBlock, hasIdentifier, hasExpression, identifier;
hasIdentifier, hasExpression, hasUnknown, hasBlock = true;
if (input.charAt(i) !== '@') { return; }
@@ -1683,9 +1683,8 @@ less.Parser = function Parser(env) {
}
switch(nonVendorSpecificName) {
/*
case "@font-face":
hasBlock = true;
break;
case "@viewport":
case "@top-left":
case "@top-left-corner":
@@ -1705,42 +1704,55 @@ less.Parser = function Parser(env) {
case "@right-bottom":
hasBlock = true;
break;
*/
case "@charset":
hasIdentifier = true;
hasBlock = false;
break;
case "@namespace":
hasExpression = true;
hasBlock = false;
break;
case "@keyframes":
hasIdentifier = true;
break;
case "@host":
case "@page":
case "@document":
case "@supports":
case "@keyframes":
hasBlock = true;
hasIdentifier = true;
break;
case "@namespace":
hasExpression = true;
hasUnknown = true;
break;
}
if (hasIdentifier) {
identifier = ($re(/^[^{]+/) || '').trim();
if (identifier) {
name += " " + identifier;
value = this.entity();
if (!value) {
error("expected " + name + " identifier");
}
} else if (hasExpression) {
value = this.expression();
if (!value) {
error("expected " + name + " expression");
}
} else if (hasUnknown) {
value = ($re(/^[^{;]+/) || '').trim();
if (value) {
value = new(tree.Anonymous)(value);
}
}
if (hasBlock) {
rules = this.block();
if (rules) {
return new(tree.Directive)(name, rules, index, env.currentFileInfo);
}
} else {
value = hasExpression ? this.expression() : this.entity();
if (value && $char(';')) {
var directive = new(tree.Directive)(name, value, index, env.currentFileInfo);
if (env.dumpLineNumbers) {
directive.debugInfo = getDebugInfo(i, input, env);
}
return directive;
if (rules) {
rules = new(tree.Ruleset)(null, rules);
}
}
if (rules || (!hasBlock && value && $char(';'))) {
return new(tree.Directive)(name, value, rules, index, env.currentFileInfo,
env.dumpLineNumbers ? getDebugInfo(index, input, env) : null);
}
restore();
},

View File

@@ -1,58 +1,62 @@
(function (tree) {
tree.Directive = function (name, value, index, currentFileInfo) {
this.name = name;
if (Array.isArray(value)) {
this.rules = [new(tree.Ruleset)(null, value)];
this.rules[0].allowImports = true;
} else {
this.value = value;
tree.Directive = function (name, value, rules, index, currentFileInfo, debugInfo) {
this.name = name;
this.value = value;
if (rules) {
this.rules = rules;
this.rules.allowImports = true;
}
this.index = index;
this.currentFileInfo = currentFileInfo;
this.debugInfo = debugInfo;
};
tree.Directive.prototype = {
type: "Directive",
accept: function (visitor) {
if (this.rules) {
this.rules = visitor.visitArray(this.rules);
var value = this.value, rules = this.rules;
if (rules) {
rules = visitor.visit(rules);
}
if (this.value) {
this.value = visitor.visit(this.value);
if (value) {
value = visitor.visit(value);
}
},
genCSS: function (env, output) {
var value = this.value, rules = this.rules;
output.add(this.name, this.currentFileInfo, this.index);
if (this.rules) {
tree.outputRuleset(env, output, this.rules);
} else {
if (value) {
output.add(' ');
this.value.genCSS(env, output);
value.genCSS(env, output);
}
if (rules) {
tree.outputRuleset(env, output, [rules]);
} else {
output.add(';');
}
},
toCSS: tree.toCSS,
eval: function (env) {
var evaldDirective = this;
if (this.rules) {
env.frames.unshift(this);
evaldDirective = new(tree.Directive)(this.name, null, this.index, this.currentFileInfo);
evaldDirective.rules = [this.rules[0].eval(env)];
evaldDirective.rules[0].root = true;
env.frames.shift();
var value = this.value, rules = this.rules;
if (value) {
value = value.eval(env);
}
return evaldDirective;
if (rules) {
rules = rules.eval(env);
rules.root = true;
}
return new(tree.Directive)(this.name, value, rules,
this.index, this.currentFileInfo, this.debugInfo);
},
variable: function (name) { return tree.Ruleset.prototype.variable.call(this.rules[0], name); },
find: function () { return tree.Ruleset.prototype.find.apply(this.rules[0], arguments); },
rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.rules[0]); },
variable: function (name) { if (this.rules) return tree.Ruleset.prototype.variable.call(this.rules, name); },
find: function () { if (this.rules) return tree.Ruleset.prototype.find.apply(this.rules, arguments); },
rulesets: function () { if (this.rules) return tree.Ruleset.prototype.rulesets.apply(this.rules); },
markReferenced: function () {
var i, rules;
this.isReferenced = true;
if (this.rules) {
rules = this.rules[0].rules;
rules = this.rules.rules;
for (i = 0; i < rules.length; i++) {
if (rules[i].markReferenced) {
rules[i].markReferenced();