[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