[Pkg-javascript-commits] [less.js] 110/285: Merge branch 'SomMeri-namespaces-guards-1418' into 2_0_0
Jonas Smedegaard
dr at jones.dk
Mon Oct 26 23:23:44 UTC 2015
This is an automated email from the git hooks/post-receive script.
js pushed a commit to annotated tag v2.0.0
in repository less.js.
commit 723b410db0f2cc8986876251081b487b930372f3
Merge: cf0ac69 518887e
Author: Luke Page <luke.a.page at gmail.com>
Date: Sat Sep 6 13:27:11 2014 +0100
Merge branch 'SomMeri-namespaces-guards-1418' into 2_0_0
Conflicts:
lib/less/tree/mixin.js
lib/less/tree/ruleset.js
lib/less/tree/mixin-call.js | 68 +++++++++++++++++++++++++++-----------------
lib/less/tree/ruleset.js | 15 ++++++----
test/css/mixins-guards.css | 8 ++++++
test/less/mixins-guards.less | 55 +++++++++++++++++++++++++++++++++++
4 files changed, 115 insertions(+), 31 deletions(-)
diff --cc lib/less/tree/mixin-call.js
index e577b87,0000000..358dd2c
mode 100644,000000..100644
--- a/lib/less/tree/mixin-call.js
+++ b/lib/less/tree/mixin-call.js
@@@ -1,154 -1,0 +1,170 @@@
+var Node = require("./node.js"),
+ Selector = require("./selector.js"),
+ MixinDefinition = require("./mixin-definition.js"),
+ defaultFunc = require("../functions/default.js");
+
+var MixinCall = function (elements, args, index, currentFileInfo, important) {
+ this.selector = new(Selector)(elements);
+ this.arguments = (args && args.length) ? args : null;
+ this.index = index;
+ this.currentFileInfo = currentFileInfo;
+ this.important = important;
+};
+MixinCall.prototype = new Node();
+MixinCall.prototype.type = "MixinCall";
+MixinCall.prototype.accept = function (visitor) {
+ if (this.selector) {
+ this.selector = visitor.visit(this.selector);
+ }
+ if (this.arguments) {
+ this.arguments = visitor.visitArray(this.arguments);
+ }
+};
+MixinCall.prototype.eval = function (env) {
- var mixins, mixin, args, rules = [], match = false, i, m, f, isRecursive, isOneFound, rule,
- candidates = [], candidate, conditionResult = [],
- defaultResult, defNone = 0, defTrue = 1, defFalse = 2, count, originalRuleset;
++ var mixins, mixin, mixinPath, args, rules = [], match = false, i, m, f, isRecursive, isOneFound, rule,
++ candidates = [], candidate, conditionResult = [], defaultResult, defFalseEitherCase=-1,
++ defNone = 0, defTrue = 1, defFalse = 2, count, originalRuleset, noArgumentsFilter;
++
++ function calcDefGroup(mixin, mixinPath) {
++ var p, namespace;
++
++ for (f = 0; f < 2; f++) {
++ conditionResult[f] = true;
++ defaultFunc.value(f);
++ for(p = 0; p < mixinPath.length && conditionResult[f]; p++) {
++ namespace = mixinPath[p];
++ if (namespace.matchCondition) {
++ conditionResult[f] = conditionResult[f] && namespace.matchCondition(null, env);
++ }
++ }
++ if (mixin.matchCondition) {
++ conditionResult[f] = conditionResult[f] && mixin.matchCondition(args, env);
++ }
++ }
++ if (conditionResult[0] || conditionResult[1]) {
++ if (conditionResult[0] != conditionResult[1]) {
++ return conditionResult[1] ?
++ defTrue : defFalse;
++ }
++
++ return defNone;
++ }
++ return defFalseEitherCase;
++ }
+
+ args = this.arguments && this.arguments.map(function (a) {
+ return { name: a.name, value: a.value.eval(env) };
+ });
+
++ noArgumentsFilter = function(rule) {return rule.matchArgs(null, env);};
++
+ for (i = 0; i < env.frames.length; i++) {
- if ((mixins = env.frames[i].find(this.selector)).length > 0) {
++ if ((mixins = env.frames[i].find(this.selector, null, noArgumentsFilter)).length > 0) {
+ isOneFound = true;
+
+ // To make `default()` function independent of definition order we have two "subpasses" here.
+ // At first we evaluate each guard *twice* (with `default() == true` and `default() == false`),
+ // and build candidate list with corresponding flags. Then, when we know all possible matches,
+ // we make a final decision.
+
+ for (m = 0; m < mixins.length; m++) {
- mixin = mixins[m];
++ mixin = mixins[m].rule;
++ mixinPath = mixins[m].path;
+ isRecursive = false;
+ for(f = 0; f < env.frames.length; f++) {
+ if ((!(mixin instanceof MixinDefinition)) && mixin === (env.frames[f].originalRuleset || env.frames[f])) {
+ isRecursive = true;
+ break;
+ }
+ }
+ if (isRecursive) {
+ continue;
+ }
+
+ if (mixin.matchArgs(args, env)) {
- candidate = {mixin: mixin, group: defNone};
++ candidate = {mixin: mixin, group: calcDefGroup(mixin, mixinPath)};
+
- if (mixin.matchCondition) {
- for (f = 0; f < 2; f++) {
- defaultFunc.value(f);
- conditionResult[f] = mixin.matchCondition(args, env);
- }
- if (conditionResult[0] || conditionResult[1]) {
- if (conditionResult[0] != conditionResult[1]) {
- candidate.group = conditionResult[1] ?
- defTrue : defFalse;
- }
-
- candidates.push(candidate);
- }
- }
- else {
++ if (candidate.group!==defFalseEitherCase) {
+ candidates.push(candidate);
+ }
+
+ match = true;
+ }
+ }
+
+ defaultFunc.reset();
+
+ count = [0, 0, 0];
+ for (m = 0; m < candidates.length; m++) {
+ count[candidates[m].group]++;
+ }
+
+ if (count[defNone] > 0) {
+ defaultResult = defFalse;
+ } else {
+ defaultResult = defTrue;
+ if ((count[defTrue] + count[defFalse]) > 1) {
+ throw { type: 'Runtime',
+ message: 'Ambiguous use of `default()` found when matching for `'
+ + this.format(args) + '`',
+ index: this.index, filename: this.currentFileInfo.filename };
+ }
+ }
+
+ for (m = 0; m < candidates.length; m++) {
+ candidate = candidates[m].group;
+ if ((candidate === defNone) || (candidate === defaultResult)) {
+ try {
+ mixin = candidates[m].mixin;
+ if (!(mixin instanceof MixinDefinition)) {
+ originalRuleset = mixin.originalRuleset || mixin;
+ mixin = new MixinDefinition("", [], mixin.rules, null, false);
+ mixin.originalRuleset = originalRuleset;
+ }
+ Array.prototype.push.apply(
- rules, mixin.evalCall(env, args, this.important).rules);
++ rules, mixin.evalCall(env, args, this.important).rules);
+ } catch (e) {
+ throw { message: e.message, index: this.index, filename: this.currentFileInfo.filename, stack: e.stack };
+ }
+ }
+ }
+
+ if (match) {
+ if (!this.currentFileInfo || !this.currentFileInfo.reference) {
+ for (i = 0; i < rules.length; i++) {
+ rule = rules[i];
+ if (rule.markReferenced) {
+ rule.markReferenced();
+ }
+ }
+ }
+ return rules;
+ }
+ }
+ }
+ if (isOneFound) {
+ throw { type: 'Runtime',
- message: 'No matching definition was found for `' + this.format(args) + '`',
- index: this.index, filename: this.currentFileInfo.filename };
++ message: 'No matching definition was found for `' + this.format(args) + '`',
++ index: this.index, filename: this.currentFileInfo.filename };
+ } else {
+ throw { type: 'Name',
- message: this.selector.toCSS().trim() + " is undefined",
- index: this.index, filename: this.currentFileInfo.filename };
++ message: this.selector.toCSS().trim() + " is undefined",
++ index: this.index, filename: this.currentFileInfo.filename };
+ }
+};
+MixinCall.prototype.format = function (args) {
+ return this.selector.toCSS().trim() + '(' +
+ (args ? args.map(function (a) {
+ var argValue = "";
+ if (a.name) {
+ argValue += a.name + ":";
+ }
+ if (a.value.toCSS) {
+ argValue += a.value.toCSS();
+ } else {
+ argValue += "???";
+ }
+ return argValue;
+ }).join(', ') : "") + ")";
+};
+module.exports = MixinCall;
diff --cc lib/less/tree/ruleset.js
index bc0c262,f5cdf1f..6e4e690
--- a/lib/less/tree/ruleset.js
+++ b/lib/less/tree/ruleset.js
@@@ -150,427 -143,441 +150,432 @@@ Ruleset.prototype.eval = function (env
}
}
}
+ }
- // Pop the stack
- envFrames.shift();
- envSelectors.shift();
-
- if (env.mediaBlocks) {
- for (i = mediaBlockCount; i < env.mediaBlocks.length; i++) {
- env.mediaBlocks[i].bubbleSelectors(selectors);
- }
+ // Pop the stack
+ envFrames.shift();
+ envSelectors.shift();
+
+ if (env.mediaBlocks) {
+ for (i = mediaBlockCount; i < env.mediaBlocks.length; i++) {
+ env.mediaBlocks[i].bubbleSelectors(selectors);
}
+ }
- return ruleset;
- },
- evalImports: function(env) {
- var rules = this.rules, i, importRules;
- if (!rules) { return; }
-
- for (i = 0; i < rules.length; i++) {
- if (rules[i] instanceof tree.Import) {
- importRules = rules[i].eval(env);
- if (importRules && importRules.length) {
- rules.splice.apply(rules, [i, 1].concat(importRules));
- i+= importRules.length-1;
- } else {
- rules.splice(i, 1, importRules);
- }
- this.resetCache();
+ return ruleset;
+};
+Ruleset.prototype.evalImports = function(env) {
+ var rules = this.rules, i, importRules;
+ if (!rules) { return; }
+
+ for (i = 0; i < rules.length; i++) {
+ if (rules[i].type === "Import") {
+ importRules = rules[i].eval(env);
+ if (importRules && importRules.length) {
+ rules.splice.apply(rules, [i, 1].concat(importRules));
+ i+= importRules.length-1;
+ } else {
+ rules.splice(i, 1, importRules);
}
+ this.resetCache();
}
- },
- makeImportant: function() {
- return new tree.Ruleset(this.selectors, this.rules.map(function (r) {
- if (r.makeImportant) {
- return r.makeImportant();
- } else {
- return r;
- }
- }), this.strictImports);
- },
- matchArgs: function (args) {
- return !args || args.length === 0;
- },
- // lets you call a css selector with a guard
- matchCondition: function (args, env) {
- var lastSelector = this.selectors[this.selectors.length-1];
- if (!lastSelector.evaldCondition) {
- return false;
- }
- if (lastSelector.condition &&
- !lastSelector.condition.eval(
- new(tree.evalEnv)(env,
- env.frames))) {
- return false;
- }
- return true;
- },
- resetCache: function () {
- this._rulesets = null;
- this._variables = null;
- this._lookups = {};
- },
- variables: function () {
- if (!this._variables) {
- this._variables = !this.rules ? {} : this.rules.reduce(function (hash, r) {
- if (r instanceof tree.Rule && r.variable === true) {
- hash[r.name] = r;
+ }
+};
+Ruleset.prototype.makeImportant = function() {
+ return new Ruleset(this.selectors, this.rules.map(function (r) {
+ if (r.makeImportant) {
+ return r.makeImportant();
+ } else {
+ return r;
}
- return hash;
- }, {});
- }
- return this._variables;
- },
- variable: function (name) {
- return this.variables()[name];
- },
- rulesets: function () {
- if (!this.rules) { return null; }
-
- var _Ruleset = tree.Ruleset, _MixinDefinition = tree.mixin.Definition,
- filtRules = [], rules = this.rules, cnt = rules.length,
- i, rule;
-
- for (i = 0; i < cnt; i++) {
- rule = rules[i];
- if ((rule instanceof _Ruleset) || (rule instanceof _MixinDefinition)) {
- filtRules.push(rule);
+ }), this.strictImports);
+};
+Ruleset.prototype.matchArgs = function (args) {
+ return !args || args.length === 0;
+};
+// lets you call a css selector with a guard
+Ruleset.prototype.matchCondition = function (args, env) {
+ var lastSelector = this.selectors[this.selectors.length-1];
+ if (!lastSelector.evaldCondition) {
+ return false;
+ }
+ if (lastSelector.condition &&
+ !lastSelector.condition.eval(
+ new(contexts.evalEnv)(env,
+ env.frames))) {
+ return false;
+ }
+ return true;
+};
+Ruleset.prototype.resetCache = function () {
+ this._rulesets = null;
+ this._variables = null;
+ this._lookups = {};
+};
+Ruleset.prototype.variables = function () {
+ if (!this._variables) {
+ this._variables = !this.rules ? {} : this.rules.reduce(function (hash, r) {
+ if (r instanceof Rule && r.variable === true) {
+ hash[r.name] = r;
}
+ return hash;
+ }, {});
+ }
+ return this._variables;
+};
+Ruleset.prototype.variable = function (name) {
+ return this.variables()[name];
+};
+Ruleset.prototype.rulesets = function () {
+ if (!this.rules) { return null; }
+
+ var filtRules = [], rules = this.rules, cnt = rules.length,
+ i, rule;
+
+ for (i = 0; i < cnt; i++) {
+ rule = rules[i];
+ if (rule.isRuleset) {
+ filtRules.push(rule);
}
+ }
- return filtRules;
- },
- prependRule: function (rule) {
- var rules = this.rules;
- if (rules) { rules.unshift(rule); } else { this.rules = [ rule ]; }
- },
- find: function (selector, self, filter) {
- self = self || this;
- var rules = [], match, foundMixins,
- key = selector.toCSS();
-
- if (key in this._lookups) { return this._lookups[key]; }
-
- this.rulesets().forEach(function (rule) {
- if (rule !== self) {
- for (var j = 0; j < rule.selectors.length; j++) {
- match = selector.match(rule.selectors[j]);
- if (match) {
- if (selector.elements.length > match) {
- if (!filter || filter(rule)) {
- foundMixins = rule.find(new(tree.Selector)(selector.elements.slice(match)), self, filter);
- for (var i = 0; i < foundMixins.length; ++i) {
- foundMixins[i].path.push(rule);
- }
- Array.prototype.push.apply(rules, foundMixins);
- }
- } else {
- rules.push({ rule: rule, path: []});
+ return filtRules;
+};
+Ruleset.prototype.prependRule = function (rule) {
+ var rules = this.rules;
+ if (rules) { rules.unshift(rule); } else { this.rules = [ rule ]; }
+};
- Ruleset.prototype.find = function (selector, self) {
++Ruleset.prototype.find = function (selector, self, filter) {
+ self = self || this;
- var rules = [], match,
++ var rules = [], match, foundMixins,
+ key = selector.toCSS();
+
+ if (key in this._lookups) { return this._lookups[key]; }
+
+ this.rulesets().forEach(function (rule) {
+ if (rule !== self) {
+ for (var j = 0; j < rule.selectors.length; j++) {
+ match = selector.match(rule.selectors[j]);
+ if (match) {
+ if (selector.elements.length > match) {
- Array.prototype.push.apply(rules, rule.find(
- new(Selector)(selector.elements.slice(match)), self));
++ if (!filter || filter(rule)) {
++ foundMixins = rule.find(new(Selector)(selector.elements.slice(match)), self, filter);
++ for (var i = 0; i < foundMixins.length; ++i) {
++ foundMixins[i].path.push(rule);
+ }
- break;
++ Array.prototype.push.apply(rules, foundMixins);
++ }
+ } else {
- rules.push(rule);
++ rules.push({ rule: rule, path: []});
}
+ break;
}
}
- });
- this._lookups[key] = rules;
- return rules;
- },
- genCSS: function (env, output) {
- var i, j,
- charsetRuleNodes = [],
- ruleNodes = [],
- rulesetNodes = [],
- rulesetNodeCnt,
- debugInfo, // Line number debugging
- rule,
- path;
-
- env.tabLevel = (env.tabLevel || 0);
-
- if (!this.root) {
- env.tabLevel++;
}
+ });
+ this._lookups[key] = rules;
+ return rules;
+};
+Ruleset.prototype.genCSS = function (env, output) {
+ var i, j,
+ charsetRuleNodes = [],
+ ruleNodes = [],
+ rulesetNodes = [],
+ rulesetNodeCnt,
+ debugInfo, // Line number debugging
+ rule,
+ path;
+
+ env.tabLevel = (env.tabLevel || 0);
+
+ if (!this.root) {
+ env.tabLevel++;
+ }
- var tabRuleStr = env.compress ? '' : Array(env.tabLevel + 1).join(" "),
- tabSetStr = env.compress ? '' : Array(env.tabLevel).join(" "),
- sep;
-
- function isRulesetLikeNode(rule, root) {
- // if it has nested rules, then it should be treated like a ruleset
- if (rule.rules)
- return true;
-
- // medias and comments do not have nested rules, but should be treated like rulesets anyway
- if ( (rule instanceof tree.Media) || (root && rule instanceof tree.Comment))
- return true;
-
- // some directives and anonumoust nodes are ruleset like, others are not
- if ((rule instanceof tree.Directive) || (rule instanceof tree.Anonymous)) {
- return rule.isRulesetLike();
- }
-
- //anything else is assumed to be a rule
- return false;
- }
+ var tabRuleStr = env.compress ? '' : Array(env.tabLevel + 1).join(" "),
+ tabSetStr = env.compress ? '' : Array(env.tabLevel).join(" "),
+ sep;
+
+ function isRulesetLikeNode(rule, root) {
+ // if it has nested rules, then it should be treated like a ruleset
+ // medias and comments do not have nested rules, but should be treated like rulesets anyway
+ // some directives and anonymous nodes are ruleset like, others are not
+ if (typeof rule.isRulesetLike === "boolean")
+ {
+ return rule.isRulesetLike;
+ } else if (typeof rule.isRulesetLike === "function")
+ {
+ return rule.isRulesetLike(root);
+ }
+
+ //anything else is assumed to be a rule
+ return false;
+ }
- for (i = 0; i < this.rules.length; i++) {
- rule = this.rules[i];
- if (isRulesetLikeNode(rule, this.root)) {
- rulesetNodes.push(rule);
+ for (i = 0; i < this.rules.length; i++) {
+ rule = this.rules[i];
+ if (isRulesetLikeNode(rule, this.root)) {
+ rulesetNodes.push(rule);
+ } else {
+ //charsets should float on top of everything
+ if (rule.isCharset && rule.isCharset()) {
+ charsetRuleNodes.push(rule);
} else {
- //charsets should float on top of everything
- if (rule.isCharset && rule.isCharset()) {
- charsetRuleNodes.push(rule);
- } else {
- ruleNodes.push(rule);
- }
+ ruleNodes.push(rule);
}
}
- ruleNodes = charsetRuleNodes.concat(ruleNodes);
+ }
+ ruleNodes = charsetRuleNodes.concat(ruleNodes);
- // If this is the root node, we don't render
- // a selector, or {}.
- if (!this.root) {
- debugInfo = tree.debugInfo(env, this, tabSetStr);
+ // If this is the root node, we don't render
+ // a selector, or {}.
+ if (!this.root) {
+ debugInfo = getDebugInfo(env, this, tabSetStr);
- if (debugInfo) {
- output.add(debugInfo);
- output.add(tabSetStr);
- }
+ if (debugInfo) {
+ output.add(debugInfo);
+ output.add(tabSetStr);
+ }
- var paths = this.paths, pathCnt = paths.length,
- pathSubCnt;
+ var paths = this.paths, pathCnt = paths.length,
+ pathSubCnt;
- sep = env.compress ? ',' : (',\n' + tabSetStr);
+ sep = env.compress ? ',' : (',\n' + tabSetStr);
- for (i = 0; i < pathCnt; i++) {
- path = paths[i];
- if (!(pathSubCnt = path.length)) { continue; }
- if (i > 0) { output.add(sep); }
+ for (i = 0; i < pathCnt; i++) {
+ path = paths[i];
+ if (!(pathSubCnt = path.length)) { continue; }
+ if (i > 0) { output.add(sep); }
- env.firstSelector = true;
- path[0].genCSS(env, output);
+ env.firstSelector = true;
+ path[0].genCSS(env, output);
- env.firstSelector = false;
- for (j = 1; j < pathSubCnt; j++) {
- path[j].genCSS(env, output);
- }
+ env.firstSelector = false;
+ for (j = 1; j < pathSubCnt; j++) {
+ path[j].genCSS(env, output);
}
-
- output.add((env.compress ? '{' : ' {\n') + tabRuleStr);
}
- // Compile rules and rulesets
- for (i = 0; i < ruleNodes.length; i++) {
- rule = ruleNodes[i];
-
- // @page{ directive ends up with root elements inside it, a mix of rules and rulesets
- // In this instance we do not know whether it is the last property
- if (i + 1 === ruleNodes.length && (!this.root || rulesetNodes.length === 0 || this.firstRoot)) {
- env.lastRule = true;
- }
+ output.add((env.compress ? '{' : ' {\n') + tabRuleStr);
+ }
- if (rule.genCSS) {
- rule.genCSS(env, output);
- } else if (rule.value) {
- output.add(rule.value.toString());
- }
+ // Compile rules and rulesets
+ for (i = 0; i < ruleNodes.length; i++) {
+ rule = ruleNodes[i];
- if (!env.lastRule) {
- output.add(env.compress ? '' : ('\n' + tabRuleStr));
- } else {
- env.lastRule = false;
- }
+ // @page{ directive ends up with root elements inside it, a mix of rules and rulesets
+ // In this instance we do not know whether it is the last property
+ if (i + 1 === ruleNodes.length && (!this.root || rulesetNodes.length === 0 || this.firstRoot)) {
+ env.lastRule = true;
}
- if (!this.root) {
- output.add((env.compress ? '}' : '\n' + tabSetStr + '}'));
- env.tabLevel--;
+ if (rule.genCSS) {
+ rule.genCSS(env, output);
+ } else if (rule.value) {
+ output.add(rule.value.toString());
}
- sep = (env.compress ? "" : "\n") + (this.root ? tabRuleStr : tabSetStr);
- rulesetNodeCnt = rulesetNodes.length;
- if (rulesetNodeCnt) {
- if (ruleNodes.length && sep) { output.add(sep); }
- rulesetNodes[0].genCSS(env, output);
- for (i = 1; i < rulesetNodeCnt; i++) {
- if (sep) { output.add(sep); }
- rulesetNodes[i].genCSS(env, output);
- }
+ if (!env.lastRule) {
+ output.add(env.compress ? '' : ('\n' + tabRuleStr));
+ } else {
+ env.lastRule = false;
}
+ }
- if (!output.isEmpty() && !env.compress && this.firstRoot) {
- output.add('\n');
+ if (!this.root) {
+ output.add((env.compress ? '}' : '\n' + tabSetStr + '}'));
+ env.tabLevel--;
+ }
+
+ sep = (env.compress ? "" : "\n") + (this.root ? tabRuleStr : tabSetStr);
+ rulesetNodeCnt = rulesetNodes.length;
+ if (rulesetNodeCnt) {
+ if (ruleNodes.length && sep) { output.add(sep); }
+ rulesetNodes[0].genCSS(env, output);
+ for (i = 1; i < rulesetNodeCnt; i++) {
+ if (sep) { output.add(sep); }
+ rulesetNodes[i].genCSS(env, output);
}
- },
+ }
- toCSS: tree.toCSS,
+ if (!output.isEmpty() && !env.compress && this.firstRoot) {
+ output.add('\n');
+ }
+};
+Ruleset.prototype.markReferenced = function () {
+ if (!this.selectors) {
+ return;
+ }
+ for (var s = 0; s < this.selectors.length; s++) {
+ this.selectors[s].markReferenced();
+ }
+};
+Ruleset.prototype.joinSelectors = function (paths, context, selectors) {
+ for (var s = 0; s < selectors.length; s++) {
+ this.joinSelector(paths, context, selectors[s]);
+ }
+};
+Ruleset.prototype.joinSelector = function (paths, context, selector) {
- markReferenced: function () {
- if (!this.selectors) {
- return;
- }
- for (var s = 0; s < this.selectors.length; s++) {
- this.selectors[s].markReferenced();
- }
- },
+ var i, j, k,
+ hasParentSelector, newSelectors, el, sel, parentSel,
+ newSelectorPath, afterParentJoin, newJoinedSelector,
+ newJoinedSelectorEmpty, lastSelector, currentElements,
+ selectorsMultiplied;
- joinSelectors: function (paths, context, selectors) {
- for (var s = 0; s < selectors.length; s++) {
- this.joinSelector(paths, context, selectors[s]);
+ for (i = 0; i < selector.elements.length; i++) {
+ el = selector.elements[i];
+ if (el.value === '&') {
+ hasParentSelector = true;
}
- },
-
- joinSelector: function (paths, context, selector) {
-
- var i, j, k,
- hasParentSelector, newSelectors, el, sel, parentSel,
- newSelectorPath, afterParentJoin, newJoinedSelector,
- newJoinedSelectorEmpty, lastSelector, currentElements,
- selectorsMultiplied;
-
- for (i = 0; i < selector.elements.length; i++) {
- el = selector.elements[i];
- if (el.value === '&') {
- hasParentSelector = true;
+ }
+
+ if (!hasParentSelector) {
+ if (context.length > 0) {
+ for (i = 0; i < context.length; i++) {
+ paths.push(context[i].concat(selector));
}
}
-
- if (!hasParentSelector) {
- if (context.length > 0) {
- for (i = 0; i < context.length; i++) {
- paths.push(context[i].concat(selector));
- }
- }
- else {
- paths.push([selector]);
- }
- return;
+ else {
+ paths.push([selector]);
}
+ return;
+ }
- // The paths are [[Selector]]
- // The first list is a list of comma seperated selectors
- // The inner list is a list of inheritance seperated selectors
- // e.g.
- // .a, .b {
- // .c {
- // }
- // }
- // == [[.a] [.c]] [[.b] [.c]]
- //
-
- // the elements from the current selector so far
- currentElements = [];
- // the current list of new selectors to add to the path.
- // We will build it up. We initiate it with one empty selector as we "multiply" the new selectors
- // by the parents
- newSelectors = [[]];
-
- for (i = 0; i < selector.elements.length; i++) {
- el = selector.elements[i];
- // non parent reference elements just get added
- if (el.value !== "&") {
- currentElements.push(el);
- } else {
- // the new list of selectors to add
- selectorsMultiplied = [];
+ // The paths are [[Selector]]
+ // The first list is a list of comma seperated selectors
+ // The inner list is a list of inheritance seperated selectors
+ // e.g.
+ // .a, .b {
+ // .c {
+ // }
+ // }
+ // == [[.a] [.c]] [[.b] [.c]]
+ //
+
+ // the elements from the current selector so far
+ currentElements = [];
+ // the current list of new selectors to add to the path.
+ // We will build it up. We initiate it with one empty selector as we "multiply" the new selectors
+ // by the parents
+ newSelectors = [[]];
+
+ for (i = 0; i < selector.elements.length; i++) {
+ el = selector.elements[i];
+ // non parent reference elements just get added
+ if (el.value !== "&") {
+ currentElements.push(el);
+ } else {
+ // the new list of selectors to add
+ selectorsMultiplied = [];
- // merge the current list of non parent selector elements
- // on to the current list of selectors to add
- if (currentElements.length > 0) {
- this.mergeElementsOnToSelectors(currentElements, newSelectors);
- }
+ // merge the current list of non parent selector elements
+ // on to the current list of selectors to add
+ if (currentElements.length > 0) {
+ this.mergeElementsOnToSelectors(currentElements, newSelectors);
+ }
- // loop through our current selectors
- for (j = 0; j < newSelectors.length; j++) {
- sel = newSelectors[j];
- // if we don't have any parent paths, the & might be in a mixin so that it can be used
- // whether there are parents or not
- if (context.length === 0) {
- // the combinator used on el should now be applied to the next element instead so that
- // it is not lost
+ // loop through our current selectors
+ for (j = 0; j < newSelectors.length; j++) {
+ sel = newSelectors[j];
+ // if we don't have any parent paths, the & might be in a mixin so that it can be used
+ // whether there are parents or not
+ if (context.length === 0) {
+ // the combinator used on el should now be applied to the next element instead so that
+ // it is not lost
+ if (sel.length > 0) {
+ sel[0].elements = sel[0].elements.slice(0);
+ sel[0].elements.push(new(Element)(el.combinator, '', el.index, el.currentFileInfo));
+ }
+ selectorsMultiplied.push(sel);
+ }
+ else {
+ // and the parent selectors
+ for (k = 0; k < context.length; k++) {
+ parentSel = context[k];
+ // We need to put the current selectors
+ // then join the last selector's elements on to the parents selectors
+
+ // our new selector path
+ newSelectorPath = [];
+ // selectors from the parent after the join
+ afterParentJoin = [];
+ newJoinedSelectorEmpty = true;
+
+ //construct the joined selector - if & is the first thing this will be empty,
+ // if not newJoinedSelector will be the last set of elements in the selector
if (sel.length > 0) {
- sel[0].elements = sel[0].elements.slice(0);
- sel[0].elements.push(new(tree.Element)(el.combinator, '', el.index, el.currentFileInfo));
+ newSelectorPath = sel.slice(0);
+ lastSelector = newSelectorPath.pop();
+ newJoinedSelector = selector.createDerived(lastSelector.elements.slice(0));
+ newJoinedSelectorEmpty = false;
}
- selectorsMultiplied.push(sel);
- }
- else {
- // and the parent selectors
- for (k = 0; k < context.length; k++) {
- parentSel = context[k];
- // We need to put the current selectors
- // then join the last selector's elements on to the parents selectors
-
- // our new selector path
- newSelectorPath = [];
- // selectors from the parent after the join
- afterParentJoin = [];
- newJoinedSelectorEmpty = true;
-
- //construct the joined selector - if & is the first thing this will be empty,
- // if not newJoinedSelector will be the last set of elements in the selector
- if (sel.length > 0) {
- newSelectorPath = sel.slice(0);
- lastSelector = newSelectorPath.pop();
- newJoinedSelector = selector.createDerived(lastSelector.elements.slice(0));
- newJoinedSelectorEmpty = false;
- }
- else {
- newJoinedSelector = selector.createDerived([]);
- }
-
- //put together the parent selectors after the join
- if (parentSel.length > 1) {
- afterParentJoin = afterParentJoin.concat(parentSel.slice(1));
- }
-
- if (parentSel.length > 0) {
- newJoinedSelectorEmpty = false;
-
- // join the elements so far with the first part of the parent
- newJoinedSelector.elements.push(new(tree.Element)(el.combinator, parentSel[0].elements[0].value, el.index, el.currentFileInfo));
- newJoinedSelector.elements = newJoinedSelector.elements.concat(parentSel[0].elements.slice(1));
- }
-
- if (!newJoinedSelectorEmpty) {
- // now add the joined selector
- newSelectorPath.push(newJoinedSelector);
- }
-
- // and the rest of the parent
- newSelectorPath = newSelectorPath.concat(afterParentJoin);
-
- // add that to our new set of selectors
- selectorsMultiplied.push(newSelectorPath);
+ else {
+ newJoinedSelector = selector.createDerived([]);
+ }
+
+ //put together the parent selectors after the join
+ if (parentSel.length > 1) {
+ afterParentJoin = afterParentJoin.concat(parentSel.slice(1));
}
+
+ if (parentSel.length > 0) {
+ newJoinedSelectorEmpty = false;
+
+ // join the elements so far with the first part of the parent
+ newJoinedSelector.elements.push(new(Element)(el.combinator, parentSel[0].elements[0].value, el.index, el.currentFileInfo));
+ newJoinedSelector.elements = newJoinedSelector.elements.concat(parentSel[0].elements.slice(1));
+ }
+
+ if (!newJoinedSelectorEmpty) {
+ // now add the joined selector
+ newSelectorPath.push(newJoinedSelector);
+ }
+
+ // and the rest of the parent
+ newSelectorPath = newSelectorPath.concat(afterParentJoin);
+
+ // add that to our new set of selectors
+ selectorsMultiplied.push(newSelectorPath);
}
}
-
- // our new selectors has been multiplied, so reset the state
- newSelectors = selectorsMultiplied;
- currentElements = [];
}
- }
- // if we have any elements left over (e.g. .a& .b == .b)
- // add them on to all the current selectors
- if (currentElements.length > 0) {
- this.mergeElementsOnToSelectors(currentElements, newSelectors);
+ // our new selectors has been multiplied, so reset the state
+ newSelectors = selectorsMultiplied;
+ currentElements = [];
}
+ }
- for (i = 0; i < newSelectors.length; i++) {
- if (newSelectors[i].length > 0) {
- paths.push(newSelectors[i]);
- }
- }
- },
-
- mergeElementsOnToSelectors: function(elements, selectors) {
- var i, sel;
-
- if (selectors.length === 0) {
- selectors.push([ new(tree.Selector)(elements) ]);
- return;
+ // if we have any elements left over (e.g. .a& .b == .b)
+ // add them on to all the current selectors
+ if (currentElements.length > 0) {
+ this.mergeElementsOnToSelectors(currentElements, newSelectors);
+ }
+
+ for (i = 0; i < newSelectors.length; i++) {
+ if (newSelectors[i].length > 0) {
+ paths.push(newSelectors[i]);
}
+ }
+};
+Ruleset.prototype.mergeElementsOnToSelectors = function(elements, selectors) {
+ var i, sel;
+
+ if (selectors.length === 0) {
+ selectors.push([ new(Selector)(elements) ]);
+ return;
+ }
- for (i = 0; i < selectors.length; i++) {
- sel = selectors[i];
+ for (i = 0; i < selectors.length; i++) {
+ sel = selectors[i];
- // if the previous thing in sel is a parent this needs to join on to it
- if (sel.length > 0) {
- sel[sel.length - 1] = sel[sel.length - 1].createDerived(sel[sel.length - 1].elements.concat(elements));
- }
- else {
- sel.push(new(tree.Selector)(elements));
- }
+ // if the previous thing in sel is a parent this needs to join on to it
+ if (sel.length > 0) {
+ sel[sel.length - 1] = sel[sel.length - 1].createDerived(sel[sel.length - 1].elements.concat(elements));
+ }
+ else {
+ sel.push(new(Selector)(elements));
}
}
};
diff --cc test/less/mixins-guards.less
index 1b27417,33a3583..0426cf4
--- a/test/less/mixins-guards.less
+++ b/test/less/mixins-guards.less
@@@ -214,3 -171,58 +214,58 @@@
}
#ns > .mixin-for-root-usage(1);
+
+ @namespaceGuard: 1;
+ #guarded when (@namespaceGuard>0) {
+ #deeper {
+ .mixin() {
+ guarded: namespace;
+ }
+ }
+ }
+ #guarded() when (@namespaceGuard>0) {
+ #deeper {
+ .mixin() {
+ silent: namespace;
+ }
+ }
+ }
+ #guarded(@variable) when (@namespaceGuard>0) {
+ #deeper {
+ .mixin() {
+ should: not match because namespace argument;
+ }
+ }
+ }
+ #guarded(@variable: default) when (@namespaceGuard>0) {
+ #deeper {
+ .mixin() {
+ guarded: with default;
+ }
+ }
+ }
+ #guarded when (@namespaceGuard<0) {
+ #deeper {
+ .mixin() {
+ should: not match because namespace guard;
+ }
+ }
+ }
+ #guarded-caller {
+ #guarded > #deeper > .mixin();
+ }
+ #top {
+ #deeper when (@namespaceGuard<0) {
+ .mixin(@a) {
+ should: not match because namespace guard;
+ }
+ }
+ #deeper() when (@namespaceGuard>0) {
+ .mixin(@a) {
+ should: match @a;
+ }
+ }
+ }
+ #guarded-deeper {
+ #top > #deeper > .mixin(1);
-}
++}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/less.js.git
More information about the Pkg-javascript-commits
mailing list