mirror of
https://github.com/less/less.js.git
synced 2026-04-09 03:00:20 -04:00
detached rulesets
This commit is contained in:
@@ -143,6 +143,7 @@ tree:
|
||||
- <%= build.lib %>/tree/quoted.js
|
||||
- <%= build.lib %>/tree/rule.js
|
||||
- <%= build.lib %>/tree/ruleset.js
|
||||
- <%= build.lib %>/tree/ruleset-call.js
|
||||
- <%= build.lib %>/tree/selector.js
|
||||
- <%= build.lib %>/tree/unicode-descriptor.js
|
||||
- <%= build.lib %>/tree/url.js
|
||||
|
||||
@@ -120,6 +120,7 @@ require('./tree/media');
|
||||
require('./tree/unicode-descriptor');
|
||||
require('./tree/negative');
|
||||
require('./tree/extend');
|
||||
require('./tree/ruleset-call');
|
||||
|
||||
|
||||
var isUrlRe = /^(?:https?:)?\/\//i;
|
||||
|
||||
@@ -729,7 +729,7 @@ less.Parser = function Parser(env) {
|
||||
while (current)
|
||||
{
|
||||
node = this.extendRule() || mixin.definition() || this.rule() || this.ruleset() ||
|
||||
mixin.call() || this.comment() || this.directive();
|
||||
mixin.call() || this.comment() || this.rulesetCall() || this.directive();
|
||||
if (node) {
|
||||
root.push(node);
|
||||
} else {
|
||||
@@ -1027,6 +1027,19 @@ less.Parser = function Parser(env) {
|
||||
if (input.charAt(i) === '@' && (name = $re(/^(@[\w-]+)\s*:/))) { return name[1]; }
|
||||
},
|
||||
|
||||
//
|
||||
// The variable part of a variable definition. Used in the `rule` parser
|
||||
//
|
||||
// @fink();
|
||||
//
|
||||
rulesetCall: function () {
|
||||
var name;
|
||||
|
||||
if (input.charAt(i) === '@' && (name = $re(/^(@[\w-]+)\s*\(\s*\)\s*;/))) {
|
||||
return new tree.RulesetCall(name[1]);
|
||||
}
|
||||
},
|
||||
|
||||
//
|
||||
// extend syntax - used to extend selectors
|
||||
//
|
||||
@@ -1126,7 +1139,7 @@ less.Parser = function Parser(env) {
|
||||
|
||||
while (true) {
|
||||
if (isCall) {
|
||||
arg = parsers.expression();
|
||||
arg = parsers.blockRuleset() || parsers.expression();
|
||||
} else {
|
||||
parsers.comments();
|
||||
if (input.charAt(i) === '.' && $re(/^\.{3}/)) {
|
||||
@@ -1154,7 +1167,7 @@ less.Parser = function Parser(env) {
|
||||
|
||||
if (isCall) {
|
||||
// Variable
|
||||
if (arg.value.length == 1) {
|
||||
if (arg.value && arg.value.length == 1) {
|
||||
val = arg.value[0];
|
||||
}
|
||||
} else {
|
||||
@@ -1442,6 +1455,14 @@ less.Parser = function Parser(env) {
|
||||
}
|
||||
},
|
||||
|
||||
blockRuleset: function() {
|
||||
var block = this.block();
|
||||
if (block) {
|
||||
block = new tree.Ruleset(null, block);
|
||||
}
|
||||
return block;
|
||||
},
|
||||
|
||||
//
|
||||
// div, .class, body > p {...}
|
||||
//
|
||||
@@ -1484,25 +1505,33 @@ less.Parser = function Parser(env) {
|
||||
}
|
||||
},
|
||||
rule: function (tryAnonymous) {
|
||||
var name, value, c = input.charAt(i), important, merge;
|
||||
var name, value, c = input.charAt(i), important, merge, isVariable;
|
||||
save();
|
||||
|
||||
if (c === '.' || c === '#' || c === '&') { return; }
|
||||
|
||||
name = this.variable() || this.ruleProperty();
|
||||
if (name) {
|
||||
// prefer to try to parse first if its a variable or we are compressing
|
||||
// but always fallback on the other one
|
||||
value = !tryAnonymous && (env.compress || (name.charAt && (name.charAt(0) === '@'))) ?
|
||||
(this.value() || this.anonymousValue()) :
|
||||
(this.anonymousValue() || this.value());
|
||||
|
||||
important = this.important();
|
||||
isVariable = typeof name === "string";
|
||||
|
||||
// a name returned by this.ruleProperty() is always an array of the form:
|
||||
// [string-1, ..., string-n, ""] or [string-1, ..., string-n, "+"]
|
||||
// where each item is a tree.Keyword or tree.Variable
|
||||
merge = name.pop && name.pop().value;
|
||||
if (isVariable) {
|
||||
value = this.blockRuleset();
|
||||
}
|
||||
|
||||
if (!value) {
|
||||
// prefer to try to parse first if its a variable or we are compressing
|
||||
// but always fallback on the other one
|
||||
value = !tryAnonymous && (env.compress || isVariable) ?
|
||||
(this.value() || this.anonymousValue()) :
|
||||
(this.anonymousValue() || this.value());
|
||||
|
||||
important = this.important();
|
||||
|
||||
// a name returned by this.ruleProperty() is always an array of the form:
|
||||
// [string-1, ..., string-n, ""] or [string-1, ..., string-n, "+"]
|
||||
// where each item is a tree.Keyword or tree.Variable
|
||||
merge = !isVariable && name.pop().value;
|
||||
}
|
||||
|
||||
if (value && this.end()) {
|
||||
return new (tree.Rule)(name, value, important, merge, memo, env.currentFileInfo);
|
||||
|
||||
15
lib/less/tree/ruleset-call.js
Normal file
15
lib/less/tree/ruleset-call.js
Normal file
@@ -0,0 +1,15 @@
|
||||
(function (tree) {
|
||||
|
||||
tree.RulesetCall = function (variable) {
|
||||
this.variable = variable;
|
||||
};
|
||||
tree.RulesetCall.prototype = {
|
||||
type: "RulesetCall",
|
||||
accept: function (visitor) {
|
||||
},
|
||||
eval: function (env) {
|
||||
return new(tree.Variable)(this.variable).eval(env);
|
||||
}
|
||||
};
|
||||
|
||||
})(require('../tree'));
|
||||
@@ -90,6 +90,19 @@ tree.Ruleset.prototype = {
|
||||
rsRuleCnt += rules.length - 1;
|
||||
i += rules.length-1;
|
||||
ruleset.resetCache();
|
||||
} else if (rsRules[i] instanceof tree.RulesetCall) {
|
||||
/*jshint loopfunc:true */
|
||||
rules = rsRules[i].eval(env).rules.filter(function(r) {
|
||||
if ((r instanceof tree.Rule) && r.variable) {
|
||||
// do not pollute the scope at all
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
rsRules.splice.apply(rsRules, [i, 1].concat(rules));
|
||||
rsRuleCnt += rules.length - 1;
|
||||
i += rules.length-1;
|
||||
ruleset.resetCache();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
7
test/css/detached-rulesets.css
Normal file
7
test/css/detached-rulesets.css
Normal file
@@ -0,0 +1,7 @@
|
||||
.wrap-selector {
|
||||
color: black;
|
||||
}
|
||||
.wrap-selector {
|
||||
color: black;
|
||||
background: white;
|
||||
}
|
||||
16
test/less/detached-rulesets.less
Normal file
16
test/less/detached-rulesets.less
Normal file
@@ -0,0 +1,16 @@
|
||||
@ruleset: {
|
||||
color: black;
|
||||
background: white;
|
||||
};
|
||||
|
||||
.wrap-mixin(@ruleset) {
|
||||
.wrap-selector {
|
||||
@ruleset();
|
||||
}
|
||||
};
|
||||
|
||||
.wrap-mixin({
|
||||
color: black;
|
||||
});
|
||||
|
||||
.wrap-mixin(@ruleset);
|
||||
Reference in New Issue
Block a user