mirror of
https://github.com/less/less.js.git
synced 2026-05-01 03:00:22 -04:00
properly support @media and @import features
This commit is contained in:
@@ -82,7 +82,7 @@ var less = {
|
||||
'selector', 'quoted', 'expression', 'rule',
|
||||
'call', 'url', 'alpha', 'import',
|
||||
'mixin', 'comment', 'anonymous', 'value',
|
||||
'javascript', 'assignment', 'condition'
|
||||
'javascript', 'assignment', 'condition', 'paren'
|
||||
].forEach(function (n) {
|
||||
require('./tree/' + n);
|
||||
});
|
||||
|
||||
@@ -824,13 +824,15 @@ less.Parser = function Parser(env) {
|
||||
// and an element name, such as a tag a class, or `*`.
|
||||
//
|
||||
element: function () {
|
||||
var e, t, c;
|
||||
var e, t, c, v;
|
||||
|
||||
c = $(this.combinator);
|
||||
e = $(/^(?:\d+\.\d+|\d+)%/) || $(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/) ||
|
||||
$('*') || $(this.attribute) || $(/^\([^)@]+\)/);
|
||||
|
||||
e || ($('(') && (e = $(this.entities.variable)) && $(')'));
|
||||
if (! e) {
|
||||
$('(') && (v = $(this.entities.variable)) && $(')') && (e = new(tree.Paren)(v));
|
||||
}
|
||||
|
||||
if (e) { return new(tree.Element)(c, e, i) }
|
||||
|
||||
@@ -984,11 +986,60 @@ less.Parser = function Parser(env) {
|
||||
// stored in `import`, which we pass to the Import constructor.
|
||||
//
|
||||
"import": function () {
|
||||
var path;
|
||||
var path, features;
|
||||
if ($(/^@import\s+/) &&
|
||||
(path = $(this.entities.quoted) || $(this.entities.url)) &&
|
||||
$(';')) {
|
||||
return new(tree.Import)(path, imports);
|
||||
(path = $(this.entities.quoted) || $(this.entities.url))) {
|
||||
features = $(this.mediaFeatures);
|
||||
if ($(';')) {
|
||||
return new(tree.Import)(path, imports, features);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
mediaFeature: function () {
|
||||
var nodes = [];
|
||||
|
||||
do {
|
||||
if (e = $(this.entities.keyword)) {
|
||||
nodes.push(e);
|
||||
} else if ($('(')) {
|
||||
p = $(this.property);
|
||||
e = $(this.entity);
|
||||
if ($(')')) {
|
||||
if (p && e) {
|
||||
nodes.push(new(tree.Paren)(new(tree.Rule)(p, e, null, i, true)));
|
||||
} else if (e) {
|
||||
nodes.push(new(tree.Paren)(e));
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} else { return null }
|
||||
}
|
||||
} while (e);
|
||||
|
||||
if (nodes.length > 0) {
|
||||
return new(tree.Expression)(nodes);
|
||||
}
|
||||
},
|
||||
|
||||
mediaFeatures: function () {
|
||||
var f, features = [];
|
||||
while (f = $(this.mediaFeature)) {
|
||||
features.push(f);
|
||||
if (! $(',')) { break }
|
||||
}
|
||||
return features.length > 0 ? features : null;
|
||||
},
|
||||
|
||||
media: function () {
|
||||
var features;
|
||||
|
||||
if ($(/^@media/)) {
|
||||
features = $(this.mediaFeatures);
|
||||
|
||||
if (rules = $(this.block)) {
|
||||
return new(tree.Directive)('@media', rules, features);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -998,13 +1049,13 @@ less.Parser = function Parser(env) {
|
||||
// @charset "utf-8";
|
||||
//
|
||||
directive: function () {
|
||||
var name, value, rules, types;
|
||||
var name, value, rules, types, e, nodes;
|
||||
|
||||
if (input.charAt(i) !== '@') return;
|
||||
|
||||
if (value = $(this['import'])) {
|
||||
if (value = $(this['import']) || $(this.media)) {
|
||||
return value;
|
||||
} else if (name = $(/^@media|@page|@keyframes/) || $(/^@(?:-webkit-|-moz-|-o-|-ms-)[a-z0-9-]+/)) {
|
||||
} else if (name = $(/^@page|@keyframes/) || $(/^@(?:-webkit-|-moz-|-o-|-ms-)[a-z0-9-]+/)) {
|
||||
types = ($(/^[^{]+/) || '').trim();
|
||||
if (rules = $(this.block)) {
|
||||
return new(tree.Directive)(name + " " + types, rules);
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
(function (tree) {
|
||||
|
||||
tree.Directive = function (name, value) {
|
||||
tree.Directive = function (name, value, features) {
|
||||
this.name = name;
|
||||
this.features = features && new(tree.Value)(features);
|
||||
|
||||
if (Array.isArray(value)) {
|
||||
this.ruleset = new(tree.Ruleset)([], value);
|
||||
} else {
|
||||
@@ -10,9 +12,11 @@ tree.Directive = function (name, value) {
|
||||
};
|
||||
tree.Directive.prototype = {
|
||||
toCSS: function (ctx, env) {
|
||||
var features = this.features ? ' ' + this.features.toCSS(env) : '';
|
||||
|
||||
if (this.ruleset) {
|
||||
this.ruleset.root = true;
|
||||
return this.name + (env.compress ? '{' : ' {\n ') +
|
||||
return this.name + features + (env.compress ? '{' : ' {\n ') +
|
||||
this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') +
|
||||
(env.compress ? '}': '\n}\n');
|
||||
} else {
|
||||
@@ -20,6 +24,7 @@ tree.Directive.prototype = {
|
||||
}
|
||||
},
|
||||
eval: function (env) {
|
||||
this.features = this.features && this.features.eval(env);
|
||||
env.frames.unshift(this);
|
||||
this.ruleset = this.ruleset && this.ruleset.eval(env);
|
||||
env.frames.shift();
|
||||
|
||||
@@ -19,7 +19,7 @@ tree.Element.prototype.eval = function (env) {
|
||||
this.index);
|
||||
};
|
||||
tree.Element.prototype.toCSS = function (env) {
|
||||
return this.combinator.toCSS(env || {}) + (this.value.toCSS ? '(' + this.value.toCSS(env) + ')' : this.value);
|
||||
return this.combinator.toCSS(env || {}) + (this.value.toCSS ? this.value.toCSS(env) : this.value);
|
||||
};
|
||||
|
||||
tree.Combinator = function (value) {
|
||||
|
||||
@@ -11,10 +11,11 @@
|
||||
// `import,push`, we also pass it a callback, which it'll call once
|
||||
// the file has been fetched, and parsed.
|
||||
//
|
||||
tree.Import = function (path, imports) {
|
||||
tree.Import = function (path, imports, features) {
|
||||
var that = this;
|
||||
|
||||
this._path = path;
|
||||
this.features = features && new(tree.Value)(features);
|
||||
|
||||
// The '.less' extension is optional
|
||||
if (path instanceof tree.Quoted) {
|
||||
@@ -46,9 +47,11 @@ tree.Import = function (path, imports) {
|
||||
// ruleset.
|
||||
//
|
||||
tree.Import.prototype = {
|
||||
toCSS: function () {
|
||||
toCSS: function (env) {
|
||||
var features = this.features ? ' ' + this.features.toCSS(env) : '';
|
||||
|
||||
if (this.css) {
|
||||
return "@import " + this._path.toCSS() + ';\n';
|
||||
return "@import " + this._path.toCSS() + features + ';\n';
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
@@ -57,6 +60,7 @@ tree.Import.prototype = {
|
||||
var ruleset;
|
||||
|
||||
if (this.css) {
|
||||
this.features = this.features && this.features.eval(env);
|
||||
return this;
|
||||
} else {
|
||||
ruleset = new(tree.Ruleset)(null, this.root.rules.slice(0));
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
(function (tree) {
|
||||
|
||||
tree.Rule = function (name, value, important, index) {
|
||||
tree.Rule = function (name, value, important, index, inline) {
|
||||
this.name = name;
|
||||
this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]);
|
||||
this.important = important ? ' ' + important.trim() : '';
|
||||
this.index = index;
|
||||
this.inline = inline || false;
|
||||
|
||||
if (name.charAt(0) === '@') {
|
||||
this.variable = true;
|
||||
@@ -15,12 +16,15 @@ tree.Rule.prototype.toCSS = function (env) {
|
||||
else {
|
||||
return this.name + (env.compress ? ':' : ': ') +
|
||||
this.value.toCSS(env) +
|
||||
this.important + ";";
|
||||
this.important + (this.inline ? "" : ";");
|
||||
}
|
||||
};
|
||||
|
||||
tree.Rule.prototype.eval = function (context) {
|
||||
return new(tree.Rule)(this.name, this.value.eval(context), this.important, this.index);
|
||||
return new(tree.Rule)(this.name,
|
||||
this.value.eval(context),
|
||||
this.important,
|
||||
this.index, this.inline);
|
||||
};
|
||||
|
||||
tree.Shorthand = function (a, b) {
|
||||
|
||||
Reference in New Issue
Block a user