[Pkg-javascript-commits] [less.js] 67/285: Also remove dep-injection from visitors, none of which use environment. make functions used as classes TitleCase

Jonas Smedegaard dr at jones.dk
Mon Oct 26 23:23:39 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 e325aec74d396f8bc0a412f80a5107a1f6f4af05
Author: Luke Page <luke.a.page at gmail.com>
Date:   Sun Aug 24 18:47:25 2014 +0100

    Also remove dep-injection from visitors, none of which use environment. make functions used as classes TitleCase
---
 lib/less/non-node-index.js                |   2 +-
 lib/less/parser.js                        |   8 +-
 lib/less/visitor/extend-visitor.js        | 733 +++++++++++++++---------------
 lib/less/visitor/import-visitor.js        | 246 +++++-----
 lib/less/visitor/index.js                 |  20 +-
 lib/less/visitor/join-selector-visitor.js |  78 ++--
 lib/less/visitor/to-css-visitor.js        | 409 ++++++++---------
 lib/less/visitor/visitor.js               | 239 +++++-----
 8 files changed, 866 insertions(+), 869 deletions(-)

diff --git a/lib/less/non-node-index.js b/lib/less/non-node-index.js
index a14c1c3..8c1abfc 100644
--- a/lib/less/non-node-index.js
+++ b/lib/less/non-node-index.js
@@ -4,7 +4,7 @@ var less = {
 };
 
 less.tree = require('./tree/index.js');
-less.visitor = require('./visitor/index.js')(less, less.tree);
+less.visitor = require('./visitor/index.js');
 less.Parser = (require('./parser'))(less, less.tree, less.visitor);
 less.functions = require('./functions/index.js')(less);
 less.contexts = require("./contexts.js");
diff --git a/lib/less/parser.js b/lib/less/parser.js
index 7a8744e..e909957 100644
--- a/lib/less/parser.js
+++ b/lib/less/parser.js
@@ -485,9 +485,9 @@ var Parser = function Parser(env) {
                     try {
                         var preEvalVisitors = [],
                             visitors = [
-                                new(visitor.joinSelectorVisitor)(),
-                                new(visitor.extendVisitor)(),
-                                new(visitor.toCSSVisitor)({compress: Boolean(options.compress)})
+                                new(visitor.JoinSelectorVisitor)(),
+                                new(visitor.ExtendVisitor)(),
+                                new(visitor.ToCSSVisitor)({compress: Boolean(options.compress)})
                             ], i, root = this;
 
                         if (options.plugins) {
@@ -623,7 +623,7 @@ var Parser = function Parser(env) {
             };
 
             if (env.processImports !== false) {
-                new visitor.importVisitor(this.imports, finish)
+                new visitor.ImportVisitor(this.imports, finish)
                     .run(root);
             } else {
                 return finish();
diff --git a/lib/less/visitor/extend-visitor.js b/lib/less/visitor/extend-visitor.js
index bd63614..9616cd6 100644
--- a/lib/less/visitor/extend-visitor.js
+++ b/lib/less/visitor/extend-visitor.js
@@ -1,417 +1,418 @@
-module.exports = function (visitor, tree) {
-    /*jshint loopfunc:true */
-
-    var extendFinderVisitor = function() {
-        this._visitor = new visitor(this);
-        this.contexts = [];
-        this.allExtendsStack = [[]];
-    };
-
-    extendFinderVisitor.prototype = {
-        run: function (root) {
-            root = this._visitor.visit(root);
-            root.allExtends = this.allExtendsStack[0];
-            return root;
-        },
-        visitRule: function (ruleNode, visitArgs) {
-            visitArgs.visitDeeper = false;
-        },
-        visitMixinDefinition: function (mixinDefinitionNode, visitArgs) {
-            visitArgs.visitDeeper = false;
-        },
-        visitRuleset: function (rulesetNode, visitArgs) {
-            if (rulesetNode.root) {
-                return;
-            }
+var tree = require("../tree/index.js"),
+    Visitor = require("./visitor.js");
 
-            var i, j, extend, allSelectorsExtendList = [], extendList;
+/*jshint loopfunc:true */
 
-            // get &:extend(.a); rules which apply to all selectors in this ruleset
-            var rules = rulesetNode.rules, ruleCnt = rules ? rules.length : 0;
-            for(i = 0; i < ruleCnt; i++) {
-                if (rulesetNode.rules[i] instanceof tree.Extend) {
-                    allSelectorsExtendList.push(rules[i]);
-                    rulesetNode.extendOnEveryPath = true;
-                }
-            }
+var ExtendFinderVisitor = function() {
+    this._visitor = new Visitor(this);
+    this.contexts = [];
+    this.allExtendsStack = [[]];
+};
 
-            // now find every selector and apply the extends that apply to all extends
-            // and the ones which apply to an individual extend
-            var paths = rulesetNode.paths;
-            for(i = 0; i < paths.length; i++) {
-                var selectorPath = paths[i],
-                    selector = selectorPath[selectorPath.length - 1],
-                    selExtendList = selector.extendList;
+ExtendFinderVisitor.prototype = {
+    run: function (root) {
+        root = this._visitor.visit(root);
+        root.allExtends = this.allExtendsStack[0];
+        return root;
+    },
+    visitRule: function (ruleNode, visitArgs) {
+        visitArgs.visitDeeper = false;
+    },
+    visitMixinDefinition: function (mixinDefinitionNode, visitArgs) {
+        visitArgs.visitDeeper = false;
+    },
+    visitRuleset: function (rulesetNode, visitArgs) {
+        if (rulesetNode.root) {
+            return;
+        }
 
-                extendList = selExtendList ? selExtendList.slice(0).concat(allSelectorsExtendList)
-                                           : allSelectorsExtendList;
+        var i, j, extend, allSelectorsExtendList = [], extendList;
 
-                if (extendList) {
-                    extendList = extendList.map(function(allSelectorsExtend) {
-                        return allSelectorsExtend.clone();
-                    });
-                }
+        // get &:extend(.a); rules which apply to all selectors in this ruleset
+        var rules = rulesetNode.rules, ruleCnt = rules ? rules.length : 0;
+        for(i = 0; i < ruleCnt; i++) {
+            if (rulesetNode.rules[i] instanceof tree.Extend) {
+                allSelectorsExtendList.push(rules[i]);
+                rulesetNode.extendOnEveryPath = true;
+            }
+        }
 
-                for(j = 0; j < extendList.length; j++) {
-                    this.foundExtends = true;
-                    extend = extendList[j];
-                    extend.findSelfSelectors(selectorPath);
-                    extend.ruleset = rulesetNode;
-                    if (j === 0) { extend.firstExtendOnThisSelectorPath = true; }
-                    this.allExtendsStack[this.allExtendsStack.length-1].push(extend);
-                }
+        // now find every selector and apply the extends that apply to all extends
+        // and the ones which apply to an individual extend
+        var paths = rulesetNode.paths;
+        for(i = 0; i < paths.length; i++) {
+            var selectorPath = paths[i],
+                selector = selectorPath[selectorPath.length - 1],
+                selExtendList = selector.extendList;
+
+            extendList = selExtendList ? selExtendList.slice(0).concat(allSelectorsExtendList)
+                                       : allSelectorsExtendList;
+
+            if (extendList) {
+                extendList = extendList.map(function(allSelectorsExtend) {
+                    return allSelectorsExtend.clone();
+                });
             }
 
-            this.contexts.push(rulesetNode.selectors);
-        },
-        visitRulesetOut: function (rulesetNode) {
-            if (!rulesetNode.root) {
-                this.contexts.length = this.contexts.length - 1;
+            for(j = 0; j < extendList.length; j++) {
+                this.foundExtends = true;
+                extend = extendList[j];
+                extend.findSelfSelectors(selectorPath);
+                extend.ruleset = rulesetNode;
+                if (j === 0) { extend.firstExtendOnThisSelectorPath = true; }
+                this.allExtendsStack[this.allExtendsStack.length-1].push(extend);
             }
-        },
-        visitMedia: function (mediaNode, visitArgs) {
-            mediaNode.allExtends = [];
-            this.allExtendsStack.push(mediaNode.allExtends);
-        },
-        visitMediaOut: function (mediaNode) {
-            this.allExtendsStack.length = this.allExtendsStack.length - 1;
-        },
-        visitDirective: function (directiveNode, visitArgs) {
-            directiveNode.allExtends = [];
-            this.allExtendsStack.push(directiveNode.allExtends);
-        },
-        visitDirectiveOut: function (directiveNode) {
-            this.allExtendsStack.length = this.allExtendsStack.length - 1;
         }
-    };
-
-    var processExtendsVisitor = function() {
-        this._visitor = new visitor(this);
-    };
-
-    processExtendsVisitor.prototype = {
-        run: function(root) {
-            var extendFinder = new extendFinderVisitor();
-            extendFinder.run(root);
-            if (!extendFinder.foundExtends) { return root; }
-            root.allExtends = root.allExtends.concat(this.doExtendChaining(root.allExtends, root.allExtends));
-            this.allExtendsStack = [root.allExtends];
-            return this._visitor.visit(root);
-        },
-        doExtendChaining: function (extendsList, extendsListTarget, iterationCount) {
-            //
-            // chaining is different from normal extension.. if we extend an extend then we are not just copying, altering and pasting
-            // the selector we would do normally, but we are also adding an extend with the same target selector
-            // this means this new extend can then go and alter other extends
-            //
-            // this method deals with all the chaining work - without it, extend is flat and doesn't work on other extend selectors
-            // this is also the most expensive.. and a match on one selector can cause an extension of a selector we had already processed if
-            // we look at each selector at a time, as is done in visitRuleset
-
-            var extendIndex, targetExtendIndex, matches, extendsToAdd = [], newSelector, extendVisitor = this, selectorPath, extend, targetExtend, newExtend;
-
-            iterationCount = iterationCount || 0;
-
-            //loop through comparing every extend with every target extend.
-            // a target extend is the one on the ruleset we are looking at copy/edit/pasting in place
-            // e.g.  .a:extend(.b) {}  and .b:extend(.c) {} then the first extend extends the second one
-            // and the second is the target.
-            // the seperation into two lists allows us to process a subset of chains with a bigger set, as is the
-            // case when processing media queries
-            for(extendIndex = 0; extendIndex < extendsList.length; extendIndex++){
-                for(targetExtendIndex = 0; targetExtendIndex < extendsListTarget.length; targetExtendIndex++){
-
-                    extend = extendsList[extendIndex];
-                    targetExtend = extendsListTarget[targetExtendIndex];
-
-                    // look for circular references
-                    if( extend.parent_ids.indexOf( targetExtend.object_id ) >= 0 ){ continue; }
-
-                    // find a match in the target extends self selector (the bit before :extend)
-                    selectorPath = [targetExtend.selfSelectors[0]];
-                    matches = extendVisitor.findMatch(extend, selectorPath);
-
-                    if (matches.length) {
-
-                        // we found a match, so for each self selector..
-                        extend.selfSelectors.forEach(function(selfSelector) {
-
-                            // process the extend as usual
-                            newSelector = extendVisitor.extendSelector(matches, selectorPath, selfSelector);
-
-                            // but now we create a new extend from it
-                            newExtend = new(tree.Extend)(targetExtend.selector, targetExtend.option, 0);
-                            newExtend.selfSelectors = newSelector;
-
-                            // add the extend onto the list of extends for that selector
-                            newSelector[newSelector.length-1].extendList = [newExtend];
-
-                            // record that we need to add it.
-                            extendsToAdd.push(newExtend);
-                            newExtend.ruleset = targetExtend.ruleset;
-
-                            //remember its parents for circular references
-                            newExtend.parent_ids = newExtend.parent_ids.concat(targetExtend.parent_ids, extend.parent_ids);
-
-                            // only process the selector once.. if we have :extend(.a,.b) then multiple
-                            // extends will look at the same selector path, so when extending
-                            // we know that any others will be duplicates in terms of what is added to the css
-                            if (targetExtend.firstExtendOnThisSelectorPath) {
-                                newExtend.firstExtendOnThisSelectorPath = true;
-                                targetExtend.ruleset.paths.push(newSelector);
-                            }
-                        });
-                    }
+
+        this.contexts.push(rulesetNode.selectors);
+    },
+    visitRulesetOut: function (rulesetNode) {
+        if (!rulesetNode.root) {
+            this.contexts.length = this.contexts.length - 1;
+        }
+    },
+    visitMedia: function (mediaNode, visitArgs) {
+        mediaNode.allExtends = [];
+        this.allExtendsStack.push(mediaNode.allExtends);
+    },
+    visitMediaOut: function (mediaNode) {
+        this.allExtendsStack.length = this.allExtendsStack.length - 1;
+    },
+    visitDirective: function (directiveNode, visitArgs) {
+        directiveNode.allExtends = [];
+        this.allExtendsStack.push(directiveNode.allExtends);
+    },
+    visitDirectiveOut: function (directiveNode) {
+        this.allExtendsStack.length = this.allExtendsStack.length - 1;
+    }
+};
+
+var ProcessExtendsVisitor = function() {
+    this._visitor = new Visitor(this);
+};
+
+ProcessExtendsVisitor.prototype = {
+    run: function(root) {
+        var extendFinder = new ExtendFinderVisitor();
+        extendFinder.run(root);
+        if (!extendFinder.foundExtends) { return root; }
+        root.allExtends = root.allExtends.concat(this.doExtendChaining(root.allExtends, root.allExtends));
+        this.allExtendsStack = [root.allExtends];
+        return this._visitor.visit(root);
+    },
+    doExtendChaining: function (extendsList, extendsListTarget, iterationCount) {
+        //
+        // chaining is different from normal extension.. if we extend an extend then we are not just copying, altering and pasting
+        // the selector we would do normally, but we are also adding an extend with the same target selector
+        // this means this new extend can then go and alter other extends
+        //
+        // this method deals with all the chaining work - without it, extend is flat and doesn't work on other extend selectors
+        // this is also the most expensive.. and a match on one selector can cause an extension of a selector we had already processed if
+        // we look at each selector at a time, as is done in visitRuleset
+
+        var extendIndex, targetExtendIndex, matches, extendsToAdd = [], newSelector, extendVisitor = this, selectorPath, extend, targetExtend, newExtend;
+
+        iterationCount = iterationCount || 0;
+
+        //loop through comparing every extend with every target extend.
+        // a target extend is the one on the ruleset we are looking at copy/edit/pasting in place
+        // e.g.  .a:extend(.b) {}  and .b:extend(.c) {} then the first extend extends the second one
+        // and the second is the target.
+        // the seperation into two lists allows us to process a subset of chains with a bigger set, as is the
+        // case when processing media queries
+        for(extendIndex = 0; extendIndex < extendsList.length; extendIndex++){
+            for(targetExtendIndex = 0; targetExtendIndex < extendsListTarget.length; targetExtendIndex++){
+
+                extend = extendsList[extendIndex];
+                targetExtend = extendsListTarget[targetExtendIndex];
+
+                // look for circular references
+                if( extend.parent_ids.indexOf( targetExtend.object_id ) >= 0 ){ continue; }
+
+                // find a match in the target extends self selector (the bit before :extend)
+                selectorPath = [targetExtend.selfSelectors[0]];
+                matches = extendVisitor.findMatch(extend, selectorPath);
+
+                if (matches.length) {
+
+                    // we found a match, so for each self selector..
+                    extend.selfSelectors.forEach(function(selfSelector) {
+
+                        // process the extend as usual
+                        newSelector = extendVisitor.extendSelector(matches, selectorPath, selfSelector);
+
+                        // but now we create a new extend from it
+                        newExtend = new(tree.Extend)(targetExtend.selector, targetExtend.option, 0);
+                        newExtend.selfSelectors = newSelector;
+
+                        // add the extend onto the list of extends for that selector
+                        newSelector[newSelector.length-1].extendList = [newExtend];
+
+                        // record that we need to add it.
+                        extendsToAdd.push(newExtend);
+                        newExtend.ruleset = targetExtend.ruleset;
+
+                        //remember its parents for circular references
+                        newExtend.parent_ids = newExtend.parent_ids.concat(targetExtend.parent_ids, extend.parent_ids);
+
+                        // only process the selector once.. if we have :extend(.a,.b) then multiple
+                        // extends will look at the same selector path, so when extending
+                        // we know that any others will be duplicates in terms of what is added to the css
+                        if (targetExtend.firstExtendOnThisSelectorPath) {
+                            newExtend.firstExtendOnThisSelectorPath = true;
+                            targetExtend.ruleset.paths.push(newSelector);
+                        }
+                    });
                 }
             }
+        }
 
-            if (extendsToAdd.length) {
-                // try to detect circular references to stop a stack overflow.
-                // may no longer be needed.
-                this.extendChainCount++;
-                if (iterationCount > 100) {
-                    var selectorOne = "{unable to calculate}";
-                    var selectorTwo = "{unable to calculate}";
-                    try
-                    {
-                        selectorOne = extendsToAdd[0].selfSelectors[0].toCSS();
-                        selectorTwo = extendsToAdd[0].selector.toCSS();
-                    }
-                    catch(e) {}
-                    throw {message: "extend circular reference detected. One of the circular extends is currently:"+selectorOne+":extend(" + selectorTwo+")"};
+        if (extendsToAdd.length) {
+            // try to detect circular references to stop a stack overflow.
+            // may no longer be needed.
+            this.extendChainCount++;
+            if (iterationCount > 100) {
+                var selectorOne = "{unable to calculate}";
+                var selectorTwo = "{unable to calculate}";
+                try
+                {
+                    selectorOne = extendsToAdd[0].selfSelectors[0].toCSS();
+                    selectorTwo = extendsToAdd[0].selector.toCSS();
                 }
-
-                // now process the new extends on the existing rules so that we can handle a extending b extending c ectending d extending e...
-                return extendsToAdd.concat(extendVisitor.doExtendChaining(extendsToAdd, extendsListTarget, iterationCount+1));
-            } else {
-                return extendsToAdd;
-            }
-        },
-        visitRule: function (ruleNode, visitArgs) {
-            visitArgs.visitDeeper = false;
-        },
-        visitMixinDefinition: function (mixinDefinitionNode, visitArgs) {
-            visitArgs.visitDeeper = false;
-        },
-        visitSelector: function (selectorNode, visitArgs) {
-            visitArgs.visitDeeper = false;
-        },
-        visitRuleset: function (rulesetNode, visitArgs) {
-            if (rulesetNode.root) {
-                return;
+                catch(e) {}
+                throw {message: "extend circular reference detected. One of the circular extends is currently:"+selectorOne+":extend(" + selectorTwo+")"};
             }
-            var matches, pathIndex, extendIndex, allExtends = this.allExtendsStack[this.allExtendsStack.length-1], selectorsToAdd = [], extendVisitor = this, selectorPath;
 
-            // look at each selector path in the ruleset, find any extend matches and then copy, find and replace
+            // now process the new extends on the existing rules so that we can handle a extending b extending c ectending d extending e...
+            return extendsToAdd.concat(extendVisitor.doExtendChaining(extendsToAdd, extendsListTarget, iterationCount+1));
+        } else {
+            return extendsToAdd;
+        }
+    },
+    visitRule: function (ruleNode, visitArgs) {
+        visitArgs.visitDeeper = false;
+    },
+    visitMixinDefinition: function (mixinDefinitionNode, visitArgs) {
+        visitArgs.visitDeeper = false;
+    },
+    visitSelector: function (selectorNode, visitArgs) {
+        visitArgs.visitDeeper = false;
+    },
+    visitRuleset: function (rulesetNode, visitArgs) {
+        if (rulesetNode.root) {
+            return;
+        }
+        var matches, pathIndex, extendIndex, allExtends = this.allExtendsStack[this.allExtendsStack.length-1], selectorsToAdd = [], extendVisitor = this, selectorPath;
 
-            for(extendIndex = 0; extendIndex < allExtends.length; extendIndex++) {
-                for(pathIndex = 0; pathIndex < rulesetNode.paths.length; pathIndex++) {
-                    selectorPath = rulesetNode.paths[pathIndex];
+        // look at each selector path in the ruleset, find any extend matches and then copy, find and replace
 
-                    // extending extends happens initially, before the main pass
-                    if (rulesetNode.extendOnEveryPath) { continue; }
-                    var extendList = selectorPath[selectorPath.length-1].extendList;
-                    if (extendList && extendList.length) { continue; }
+        for(extendIndex = 0; extendIndex < allExtends.length; extendIndex++) {
+            for(pathIndex = 0; pathIndex < rulesetNode.paths.length; pathIndex++) {
+                selectorPath = rulesetNode.paths[pathIndex];
 
-                    matches = this.findMatch(allExtends[extendIndex], selectorPath);
+                // extending extends happens initially, before the main pass
+                if (rulesetNode.extendOnEveryPath) { continue; }
+                var extendList = selectorPath[selectorPath.length-1].extendList;
+                if (extendList && extendList.length) { continue; }
 
-                    if (matches.length) {
+                matches = this.findMatch(allExtends[extendIndex], selectorPath);
 
-                        allExtends[extendIndex].selfSelectors.forEach(function(selfSelector) {
-                            selectorsToAdd.push(extendVisitor.extendSelector(matches, selectorPath, selfSelector));
-                        });
-                    }
+                if (matches.length) {
+
+                    allExtends[extendIndex].selfSelectors.forEach(function(selfSelector) {
+                        selectorsToAdd.push(extendVisitor.extendSelector(matches, selectorPath, selfSelector));
+                    });
                 }
             }
-            rulesetNode.paths = rulesetNode.paths.concat(selectorsToAdd);
-        },
-        findMatch: function (extend, haystackSelectorPath) {
-            //
-            // look through the haystack selector path to try and find the needle - extend.selector
-            // returns an array of selector matches that can then be replaced
-            //
-            var haystackSelectorIndex, hackstackSelector, hackstackElementIndex, haystackElement,
-                targetCombinator, i,
-                extendVisitor = this,
-                needleElements = extend.selector.elements,
-                potentialMatches = [], potentialMatch, matches = [];
-
-            // loop through the haystack elements
-            for(haystackSelectorIndex = 0; haystackSelectorIndex < haystackSelectorPath.length; haystackSelectorIndex++) {
-                hackstackSelector = haystackSelectorPath[haystackSelectorIndex];
-
-                for(hackstackElementIndex = 0; hackstackElementIndex < hackstackSelector.elements.length; hackstackElementIndex++) {
-
-                    haystackElement = hackstackSelector.elements[hackstackElementIndex];
-
-                    // if we allow elements before our match we can add a potential match every time. otherwise only at the first element.
-                    if (extend.allowBefore || (haystackSelectorIndex === 0 && hackstackElementIndex === 0)) {
-                        potentialMatches.push({pathIndex: haystackSelectorIndex, index: hackstackElementIndex, matched: 0, initialCombinator: haystackElement.combinator});
-                    }
+        }
+        rulesetNode.paths = rulesetNode.paths.concat(selectorsToAdd);
+    },
+    findMatch: function (extend, haystackSelectorPath) {
+        //
+        // look through the haystack selector path to try and find the needle - extend.selector
+        // returns an array of selector matches that can then be replaced
+        //
+        var haystackSelectorIndex, hackstackSelector, hackstackElementIndex, haystackElement,
+            targetCombinator, i,
+            extendVisitor = this,
+            needleElements = extend.selector.elements,
+            potentialMatches = [], potentialMatch, matches = [];
+
+        // loop through the haystack elements
+        for(haystackSelectorIndex = 0; haystackSelectorIndex < haystackSelectorPath.length; haystackSelectorIndex++) {
+            hackstackSelector = haystackSelectorPath[haystackSelectorIndex];
+
+            for(hackstackElementIndex = 0; hackstackElementIndex < hackstackSelector.elements.length; hackstackElementIndex++) {
+
+                haystackElement = hackstackSelector.elements[hackstackElementIndex];
+
+                // if we allow elements before our match we can add a potential match every time. otherwise only at the first element.
+                if (extend.allowBefore || (haystackSelectorIndex === 0 && hackstackElementIndex === 0)) {
+                    potentialMatches.push({pathIndex: haystackSelectorIndex, index: hackstackElementIndex, matched: 0, initialCombinator: haystackElement.combinator});
+                }
 
-                    for(i = 0; i < potentialMatches.length; i++) {
-                        potentialMatch = potentialMatches[i];
+                for(i = 0; i < potentialMatches.length; i++) {
+                    potentialMatch = potentialMatches[i];
 
-                        // selectors add " " onto the first element. When we use & it joins the selectors together, but if we don't
-                        // then each selector in haystackSelectorPath has a space before it added in the toCSS phase. so we need to work out
-                        // what the resulting combinator will be
-                        targetCombinator = haystackElement.combinator.value;
-                        if (targetCombinator === '' && hackstackElementIndex === 0) {
-                            targetCombinator = ' ';
-                        }
+                    // selectors add " " onto the first element. When we use & it joins the selectors together, but if we don't
+                    // then each selector in haystackSelectorPath has a space before it added in the toCSS phase. so we need to work out
+                    // what the resulting combinator will be
+                    targetCombinator = haystackElement.combinator.value;
+                    if (targetCombinator === '' && hackstackElementIndex === 0) {
+                        targetCombinator = ' ';
+                    }
 
-                        // if we don't match, null our match to indicate failure
-                        if (!extendVisitor.isElementValuesEqual(needleElements[potentialMatch.matched].value, haystackElement.value) ||
-                            (potentialMatch.matched > 0 && needleElements[potentialMatch.matched].combinator.value !== targetCombinator)) {
-                            potentialMatch = null;
-                        } else {
-                            potentialMatch.matched++;
-                        }
+                    // if we don't match, null our match to indicate failure
+                    if (!extendVisitor.isElementValuesEqual(needleElements[potentialMatch.matched].value, haystackElement.value) ||
+                        (potentialMatch.matched > 0 && needleElements[potentialMatch.matched].combinator.value !== targetCombinator)) {
+                        potentialMatch = null;
+                    } else {
+                        potentialMatch.matched++;
+                    }
 
-                        // if we are still valid and have finished, test whether we have elements after and whether these are allowed
-                        if (potentialMatch) {
-                            potentialMatch.finished = potentialMatch.matched === needleElements.length;
-                            if (potentialMatch.finished &&
-                                (!extend.allowAfter && (hackstackElementIndex+1 < hackstackSelector.elements.length || haystackSelectorIndex+1 < haystackSelectorPath.length))) {
-                                potentialMatch = null;
-                            }
+                    // if we are still valid and have finished, test whether we have elements after and whether these are allowed
+                    if (potentialMatch) {
+                        potentialMatch.finished = potentialMatch.matched === needleElements.length;
+                        if (potentialMatch.finished &&
+                            (!extend.allowAfter && (hackstackElementIndex+1 < hackstackSelector.elements.length || haystackSelectorIndex+1 < haystackSelectorPath.length))) {
+                            potentialMatch = null;
                         }
-                        // if null we remove, if not, we are still valid, so either push as a valid match or continue
-                        if (potentialMatch) {
-                            if (potentialMatch.finished) {
-                                potentialMatch.length = needleElements.length;
-                                potentialMatch.endPathIndex = haystackSelectorIndex;
-                                potentialMatch.endPathElementIndex = hackstackElementIndex + 1; // index after end of match
-                                potentialMatches.length = 0; // we don't allow matches to overlap, so start matching again
-                                matches.push(potentialMatch);
-                            }
-                        } else {
-                            potentialMatches.splice(i, 1);
-                            i--;
+                    }
+                    // if null we remove, if not, we are still valid, so either push as a valid match or continue
+                    if (potentialMatch) {
+                        if (potentialMatch.finished) {
+                            potentialMatch.length = needleElements.length;
+                            potentialMatch.endPathIndex = haystackSelectorIndex;
+                            potentialMatch.endPathElementIndex = hackstackElementIndex + 1; // index after end of match
+                            potentialMatches.length = 0; // we don't allow matches to overlap, so start matching again
+                            matches.push(potentialMatch);
                         }
+                    } else {
+                        potentialMatches.splice(i, 1);
+                        i--;
                     }
                 }
             }
-            return matches;
-        },
-        isElementValuesEqual: function(elementValue1, elementValue2) {
-            if (typeof elementValue1 === "string" || typeof elementValue2 === "string") {
-                return elementValue1 === elementValue2;
+        }
+        return matches;
+    },
+    isElementValuesEqual: function(elementValue1, elementValue2) {
+        if (typeof elementValue1 === "string" || typeof elementValue2 === "string") {
+            return elementValue1 === elementValue2;
+        }
+        if (elementValue1 instanceof tree.Attribute) {
+            if (elementValue1.op !== elementValue2.op || elementValue1.key !== elementValue2.key) {
+                return false;
             }
-            if (elementValue1 instanceof tree.Attribute) {
-                if (elementValue1.op !== elementValue2.op || elementValue1.key !== elementValue2.key) {
+            if (!elementValue1.value || !elementValue2.value) {
+                if (elementValue1.value || elementValue2.value) {
                     return false;
                 }
-                if (!elementValue1.value || !elementValue2.value) {
-                    if (elementValue1.value || elementValue2.value) {
+                return true;
+            }
+            elementValue1 = elementValue1.value.value || elementValue1.value;
+            elementValue2 = elementValue2.value.value || elementValue2.value;
+            return elementValue1 === elementValue2;
+        }
+        elementValue1 = elementValue1.value;
+        elementValue2 = elementValue2.value;
+        if (elementValue1 instanceof tree.Selector) {
+            if (!(elementValue2 instanceof tree.Selector) || elementValue1.elements.length !== elementValue2.elements.length) {
+                return false;
+            }
+            for(var i = 0; i <elementValue1.elements.length; i++) {
+                if (elementValue1.elements[i].combinator.value !== elementValue2.elements[i].combinator.value) {
+                    if (i !== 0 || (elementValue1.elements[i].combinator.value || ' ') !== (elementValue2.elements[i].combinator.value || ' ')) {
                         return false;
                     }
-                    return true;
                 }
-                elementValue1 = elementValue1.value.value || elementValue1.value;
-                elementValue2 = elementValue2.value.value || elementValue2.value;
-                return elementValue1 === elementValue2;
-            }
-            elementValue1 = elementValue1.value;
-            elementValue2 = elementValue2.value;
-            if (elementValue1 instanceof tree.Selector) {
-                if (!(elementValue2 instanceof tree.Selector) || elementValue1.elements.length !== elementValue2.elements.length) {
+                if (!this.isElementValuesEqual(elementValue1.elements[i].value, elementValue2.elements[i].value)) {
                     return false;
                 }
-                for(var i = 0; i <elementValue1.elements.length; i++) {
-                    if (elementValue1.elements[i].combinator.value !== elementValue2.elements[i].combinator.value) {
-                        if (i !== 0 || (elementValue1.elements[i].combinator.value || ' ') !== (elementValue2.elements[i].combinator.value || ' ')) {
-                            return false;
-                        }
-                    }
-                    if (!this.isElementValuesEqual(elementValue1.elements[i].value, elementValue2.elements[i].value)) {
-                        return false;
-                    }
-                }
-                return true;
             }
-            return false;
-        },
-        extendSelector:function (matches, selectorPath, replacementSelector) {
-
-            //for a set of matches, replace each match with the replacement selector
-
-            var currentSelectorPathIndex = 0,
-                currentSelectorPathElementIndex = 0,
-                path = [],
-                matchIndex,
-                selector,
-                firstElement,
-                match,
-                newElements;
-
-            for (matchIndex = 0; matchIndex < matches.length; matchIndex++) {
-                match = matches[matchIndex];
-                selector = selectorPath[match.pathIndex];
-                firstElement = new tree.Element(
-                    match.initialCombinator,
-                    replacementSelector.elements[0].value,
-                    replacementSelector.elements[0].index,
-                    replacementSelector.elements[0].currentFileInfo
-                );
-
-                if (match.pathIndex > currentSelectorPathIndex && currentSelectorPathElementIndex > 0) {
-                    path[path.length - 1].elements = path[path.length - 1].elements.concat(selectorPath[currentSelectorPathIndex].elements.slice(currentSelectorPathElementIndex));
-                    currentSelectorPathElementIndex = 0;
-                    currentSelectorPathIndex++;
-                }
+            return true;
+        }
+        return false;
+    },
+    extendSelector:function (matches, selectorPath, replacementSelector) {
+
+        //for a set of matches, replace each match with the replacement selector
+
+        var currentSelectorPathIndex = 0,
+            currentSelectorPathElementIndex = 0,
+            path = [],
+            matchIndex,
+            selector,
+            firstElement,
+            match,
+            newElements;
+
+        for (matchIndex = 0; matchIndex < matches.length; matchIndex++) {
+            match = matches[matchIndex];
+            selector = selectorPath[match.pathIndex];
+            firstElement = new tree.Element(
+                match.initialCombinator,
+                replacementSelector.elements[0].value,
+                replacementSelector.elements[0].index,
+                replacementSelector.elements[0].currentFileInfo
+            );
+
+            if (match.pathIndex > currentSelectorPathIndex && currentSelectorPathElementIndex > 0) {
+                path[path.length - 1].elements = path[path.length - 1].elements.concat(selectorPath[currentSelectorPathIndex].elements.slice(currentSelectorPathElementIndex));
+                currentSelectorPathElementIndex = 0;
+                currentSelectorPathIndex++;
+            }
 
-                newElements = selector.elements
-                    .slice(currentSelectorPathElementIndex, match.index)
-                    .concat([firstElement])
-                    .concat(replacementSelector.elements.slice(1));
+            newElements = selector.elements
+                .slice(currentSelectorPathElementIndex, match.index)
+                .concat([firstElement])
+                .concat(replacementSelector.elements.slice(1));
 
-                if (currentSelectorPathIndex === match.pathIndex && matchIndex > 0) {
-                    path[path.length - 1].elements =
-                        path[path.length - 1].elements.concat(newElements);
-                } else {
-                    path = path.concat(selectorPath.slice(currentSelectorPathIndex, match.pathIndex));
+            if (currentSelectorPathIndex === match.pathIndex && matchIndex > 0) {
+                path[path.length - 1].elements =
+                    path[path.length - 1].elements.concat(newElements);
+            } else {
+                path = path.concat(selectorPath.slice(currentSelectorPathIndex, match.pathIndex));
 
-                    path.push(new tree.Selector(
-                        newElements
-                    ));
-                }
-                currentSelectorPathIndex = match.endPathIndex;
-                currentSelectorPathElementIndex = match.endPathElementIndex;
-                if (currentSelectorPathElementIndex >= selectorPath[currentSelectorPathIndex].elements.length) {
-                    currentSelectorPathElementIndex = 0;
-                    currentSelectorPathIndex++;
-                }
+                path.push(new tree.Selector(
+                    newElements
+                ));
             }
-
-            if (currentSelectorPathIndex < selectorPath.length && currentSelectorPathElementIndex > 0) {
-                path[path.length - 1].elements = path[path.length - 1].elements.concat(selectorPath[currentSelectorPathIndex].elements.slice(currentSelectorPathElementIndex));
+            currentSelectorPathIndex = match.endPathIndex;
+            currentSelectorPathElementIndex = match.endPathElementIndex;
+            if (currentSelectorPathElementIndex >= selectorPath[currentSelectorPathIndex].elements.length) {
+                currentSelectorPathElementIndex = 0;
                 currentSelectorPathIndex++;
             }
+        }
 
-            path = path.concat(selectorPath.slice(currentSelectorPathIndex, selectorPath.length));
-
-            return path;
-        },
-        visitRulesetOut: function (rulesetNode) {
-        },
-        visitMedia: function (mediaNode, visitArgs) {
-            var newAllExtends = mediaNode.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length-1]);
-            newAllExtends = newAllExtends.concat(this.doExtendChaining(newAllExtends, mediaNode.allExtends));
-            this.allExtendsStack.push(newAllExtends);
-        },
-        visitMediaOut: function (mediaNode) {
-            this.allExtendsStack.length = this.allExtendsStack.length - 1;
-        },
-        visitDirective: function (directiveNode, visitArgs) {
-            var newAllExtends = directiveNode.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length-1]);
-            newAllExtends = newAllExtends.concat(this.doExtendChaining(newAllExtends, directiveNode.allExtends));
-            this.allExtendsStack.push(newAllExtends);
-        },
-        visitDirectiveOut: function (directiveNode) {
-            this.allExtendsStack.length = this.allExtendsStack.length - 1;
+        if (currentSelectorPathIndex < selectorPath.length && currentSelectorPathElementIndex > 0) {
+            path[path.length - 1].elements = path[path.length - 1].elements.concat(selectorPath[currentSelectorPathIndex].elements.slice(currentSelectorPathElementIndex));
+            currentSelectorPathIndex++;
         }
-    };
 
-    return processExtendsVisitor;
+        path = path.concat(selectorPath.slice(currentSelectorPathIndex, selectorPath.length));
+
+        return path;
+    },
+    visitRulesetOut: function (rulesetNode) {
+    },
+    visitMedia: function (mediaNode, visitArgs) {
+        var newAllExtends = mediaNode.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length-1]);
+        newAllExtends = newAllExtends.concat(this.doExtendChaining(newAllExtends, mediaNode.allExtends));
+        this.allExtendsStack.push(newAllExtends);
+    },
+    visitMediaOut: function (mediaNode) {
+        this.allExtendsStack.length = this.allExtendsStack.length - 1;
+    },
+    visitDirective: function (directiveNode, visitArgs) {
+        var newAllExtends = directiveNode.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length-1]);
+        newAllExtends = newAllExtends.concat(this.doExtendChaining(newAllExtends, directiveNode.allExtends));
+        this.allExtendsStack.push(newAllExtends);
+    },
+    visitDirectiveOut: function (directiveNode) {
+        this.allExtendsStack.length = this.allExtendsStack.length - 1;
+    }
 };
+
+module.exports = ProcessExtendsVisitor;
diff --git a/lib/less/visitor/import-visitor.js b/lib/less/visitor/import-visitor.js
index efff072..f7068df 100644
--- a/lib/less/visitor/import-visitor.js
+++ b/lib/less/visitor/import-visitor.js
@@ -1,145 +1,145 @@
-var contexts = require("../contexts.js");
-module.exports = function (visitor, tree) {
-    var ImportVisitor = function(importer, finish, evalEnv, onceFileDetectionMap, recursionDetector) {
-        this._visitor = new visitor(this);
-        this._importer = importer;
-        this._finish = finish;
-        this.env = evalEnv || new contexts.evalEnv();
-        this.importCount = 0;
-        this.onceFileDetectionMap = onceFileDetectionMap || {};
-        this.recursionDetector = {};
-        if (recursionDetector) {
-            for(var fullFilename in recursionDetector) {
-                if (recursionDetector.hasOwnProperty(fullFilename)) {
-                    this.recursionDetector[fullFilename] = true;
-                }
+var contexts = require("../contexts.js"),
+    Visitor = require("./visitor.js");
+
+var ImportVisitor = function(importer, finish, evalEnv, onceFileDetectionMap, recursionDetector) {
+    this._visitor = new Visitor(this);
+    this._importer = importer;
+    this._finish = finish;
+    this.env = evalEnv || new contexts.evalEnv();
+    this.importCount = 0;
+    this.onceFileDetectionMap = onceFileDetectionMap || {};
+    this.recursionDetector = {};
+    if (recursionDetector) {
+        for(var fullFilename in recursionDetector) {
+            if (recursionDetector.hasOwnProperty(fullFilename)) {
+                this.recursionDetector[fullFilename] = true;
             }
         }
-    };
+    }
+};
 
-    ImportVisitor.prototype = {
-        isReplacing: true,
-        run: function (root) {
-            var error;
-            try {
-                // process the contents
-                this._visitor.visit(root);
-            }
-            catch(e) {
-                error = e;
-            }
+ImportVisitor.prototype = {
+    isReplacing: true,
+    run: function (root) {
+        var error;
+        try {
+            // process the contents
+            this._visitor.visit(root);
+        }
+        catch(e) {
+            error = e;
+        }
 
-            this.isFinished = true;
+        this.isFinished = true;
+
+        if (this.importCount === 0) {
+            this._finish(error);
+        }
+    },
+    visitImport: function (importNode, visitArgs) {
+        var importVisitor = this,
+            evaldImportNode,
+            inlineCSS = importNode.options.inline;
 
-            if (this.importCount === 0) {
-                this._finish(error);
+        if (!importNode.css || inlineCSS) {
+
+            try {
+                evaldImportNode = importNode.evalForImport(this.env);
+            } catch(e){
+                if (!e.filename) { e.index = importNode.index; e.filename = importNode.currentFileInfo.filename; }
+                // attempt to eval properly and treat as css
+                importNode.css = true;
+                // if that fails, this error will be thrown
+                importNode.error = e;
             }
-        },
-        visitImport: function (importNode, visitArgs) {
-            var importVisitor = this,
-                evaldImportNode,
-                inlineCSS = importNode.options.inline;
 
-            if (!importNode.css || inlineCSS) {
+            if (evaldImportNode && (!evaldImportNode.css || inlineCSS)) {
+                importNode = evaldImportNode;
+                this.importCount++;
+                var env = new contexts.evalEnv(this.env, this.env.frames.slice(0));
 
-                try {
-                    evaldImportNode = importNode.evalForImport(this.env);
-                } catch(e){
-                    if (!e.filename) { e.index = importNode.index; e.filename = importNode.currentFileInfo.filename; }
-                    // attempt to eval properly and treat as css
-                    importNode.css = true;
-                    // if that fails, this error will be thrown
-                    importNode.error = e;
+                if (importNode.options.multiple) {
+                    env.importMultiple = true;
                 }
 
-                if (evaldImportNode && (!evaldImportNode.css || inlineCSS)) {
-                    importNode = evaldImportNode;
-                    this.importCount++;
-                    var env = new contexts.evalEnv(this.env, this.env.frames.slice(0));
-
-                    if (importNode.options.multiple) {
-                        env.importMultiple = true;
+                this._importer.push(importNode.getPath(), importNode.currentFileInfo, importNode.options, function (e, root, importedAtRoot, fullPath) {
+                    if (e && !e.filename) {
+                        e.index = importNode.index; e.filename = importNode.currentFileInfo.filename;
                     }
 
-                    this._importer.push(importNode.getPath(), importNode.currentFileInfo, importNode.options, function (e, root, importedAtRoot, fullPath) {
-                        if (e && !e.filename) {
-                            e.index = importNode.index; e.filename = importNode.currentFileInfo.filename;
-                        }
-
-                        var duplicateImport = importedAtRoot || fullPath in importVisitor.recursionDetector;
-                        if (!env.importMultiple) {
-                            if (duplicateImport) {
-                                importNode.skip = true;
-                            } else {
-                                importNode.skip = function() {
-                                    if (fullPath in importVisitor.onceFileDetectionMap) {
-                                        return true;
-                                    }
-                                    importVisitor.onceFileDetectionMap[fullPath] = true;
-                                    return false;
-                                };
-                            }
+                    var duplicateImport = importedAtRoot || fullPath in importVisitor.recursionDetector;
+                    if (!env.importMultiple) {
+                        if (duplicateImport) {
+                            importNode.skip = true;
+                        } else {
+                            importNode.skip = function() {
+                                if (fullPath in importVisitor.onceFileDetectionMap) {
+                                    return true;
+                                }
+                                importVisitor.onceFileDetectionMap[fullPath] = true;
+                                return false;
+                            };
                         }
+                    }
 
-                        var subFinish = function(e) {
-                            importVisitor.importCount--;
+                    var subFinish = function(e) {
+                        importVisitor.importCount--;
 
-                            if (importVisitor.importCount === 0 && importVisitor.isFinished) {
-                                importVisitor._finish(e);
-                            }
-                        };
+                        if (importVisitor.importCount === 0 && importVisitor.isFinished) {
+                            importVisitor._finish(e);
+                        }
+                    };
 
-                        if (root) {
-                            importNode.root = root;
-                            importNode.importedFilename = fullPath;
+                    if (root) {
+                        importNode.root = root;
+                        importNode.importedFilename = fullPath;
 
-                            if (!inlineCSS && (env.importMultiple || !duplicateImport)) {
-                                importVisitor.recursionDetector[fullPath] = true;
-                                new(ImportVisitor)(importVisitor._importer, subFinish, env, importVisitor.onceFileDetectionMap, importVisitor.recursionDetector)
-                                    .run(root);
-                                return;
-                            }
+                        if (!inlineCSS && (env.importMultiple || !duplicateImport)) {
+                            importVisitor.recursionDetector[fullPath] = true;
+                            new(ImportVisitor)(importVisitor._importer, subFinish, env, importVisitor.onceFileDetectionMap, importVisitor.recursionDetector)
+                                .run(root);
+                            return;
                         }
+                    }
 
-                        subFinish();
-                    });
-                }
+                    subFinish();
+                });
             }
-            visitArgs.visitDeeper = false;
-            return importNode;
-        },
-        visitRule: function (ruleNode, visitArgs) {
-            visitArgs.visitDeeper = false;
-            return ruleNode;
-        },
-        visitDirective: function (directiveNode, visitArgs) {
-            this.env.frames.unshift(directiveNode);
-            return directiveNode;
-        },
-        visitDirectiveOut: function (directiveNode) {
-            this.env.frames.shift();
-        },
-        visitMixinDefinition: function (mixinDefinitionNode, visitArgs) {
-            this.env.frames.unshift(mixinDefinitionNode);
-            return mixinDefinitionNode;
-        },
-        visitMixinDefinitionOut: function (mixinDefinitionNode) {
-            this.env.frames.shift();
-        },
-        visitRuleset: function (rulesetNode, visitArgs) {
-            this.env.frames.unshift(rulesetNode);
-            return rulesetNode;
-        },
-        visitRulesetOut: function (rulesetNode) {
-            this.env.frames.shift();
-        },
-        visitMedia: function (mediaNode, visitArgs) {
-            this.env.frames.unshift(mediaNode.rules[0]);
-            return mediaNode;
-        },
-        visitMediaOut: function (mediaNode) {
-            this.env.frames.shift();
         }
-    };
-    return ImportVisitor;
+        visitArgs.visitDeeper = false;
+        return importNode;
+    },
+    visitRule: function (ruleNode, visitArgs) {
+        visitArgs.visitDeeper = false;
+        return ruleNode;
+    },
+    visitDirective: function (directiveNode, visitArgs) {
+        this.env.frames.unshift(directiveNode);
+        return directiveNode;
+    },
+    visitDirectiveOut: function (directiveNode) {
+        this.env.frames.shift();
+    },
+    visitMixinDefinition: function (mixinDefinitionNode, visitArgs) {
+        this.env.frames.unshift(mixinDefinitionNode);
+        return mixinDefinitionNode;
+    },
+    visitMixinDefinitionOut: function (mixinDefinitionNode) {
+        this.env.frames.shift();
+    },
+    visitRuleset: function (rulesetNode, visitArgs) {
+        this.env.frames.unshift(rulesetNode);
+        return rulesetNode;
+    },
+    visitRulesetOut: function (rulesetNode) {
+        this.env.frames.shift();
+    },
+    visitMedia: function (mediaNode, visitArgs) {
+        this.env.frames.unshift(mediaNode.rules[0]);
+        return mediaNode;
+    },
+    visitMediaOut: function (mediaNode) {
+        this.env.frames.shift();
+    }
 };
+module.exports = ImportVisitor;
diff --git a/lib/less/visitor/index.js b/lib/less/visitor/index.js
index 243910e..8a09617 100644
--- a/lib/less/visitor/index.js
+++ b/lib/less/visitor/index.js
@@ -1,13 +1,9 @@
-module.exports = function(less, tree) {
-    var visitor = require("./visitor")(tree),
-        visitors = {
-        visitor: visitor
-    };
- 
-    visitors.importVisitor = require('./import-visitor.js')(visitor, tree);
-    visitors.extendVisitor = require('./extend-visitor.js')(visitor, tree);
-    visitors.joinSelectorVisitor = require('./join-selector-visitor.js')(visitor);
-    visitors.toCSSVisitor = require('./to-css-visitor.js')(visitor, tree);
-    return visitors;
+var visitors = {
+    Visitor: require("./visitor"),
+    ImportVisitor: require('./import-visitor.js'),
+    ExtendVisitor: require('./extend-visitor.js'),
+    JoinSelectorVisitor: require('./join-selector-visitor.js'),
+    ToCSSVisitor: require('./to-css-visitor.js')
+};
 
-};
\ No newline at end of file
+module.exports = visitors;
diff --git a/lib/less/visitor/join-selector-visitor.js b/lib/less/visitor/join-selector-visitor.js
index bc511d9..05f8732 100644
--- a/lib/less/visitor/join-selector-visitor.js
+++ b/lib/less/visitor/join-selector-visitor.js
@@ -1,45 +1,45 @@
-module.exports = function (visitor) {
-    var joinSelectorVisitor = function() {
-        this.contexts = [[]];
-        this._visitor = new visitor(this);
-    };
+var Visitor = require("./visitor.js");
 
-    joinSelectorVisitor.prototype = {
-        run: function (root) {
-            return this._visitor.visit(root);
-        },
-        visitRule: function (ruleNode, visitArgs) {
-            visitArgs.visitDeeper = false;
-        },
-        visitMixinDefinition: function (mixinDefinitionNode, visitArgs) {
-            visitArgs.visitDeeper = false;
-        },
+var JoinSelectorVisitor = function() {
+    this.contexts = [[]];
+    this._visitor = new Visitor(this);
+};
 
-        visitRuleset: function (rulesetNode, visitArgs) {
-            var context = this.contexts[this.contexts.length - 1],
-                paths = [], selectors;
+JoinSelectorVisitor.prototype = {
+    run: function (root) {
+        return this._visitor.visit(root);
+    },
+    visitRule: function (ruleNode, visitArgs) {
+        visitArgs.visitDeeper = false;
+    },
+    visitMixinDefinition: function (mixinDefinitionNode, visitArgs) {
+        visitArgs.visitDeeper = false;
+    },
 
-            this.contexts.push(paths);
+    visitRuleset: function (rulesetNode, visitArgs) {
+        var context = this.contexts[this.contexts.length - 1],
+            paths = [], selectors;
 
-            if (! rulesetNode.root) {
-                selectors = rulesetNode.selectors;
-                if (selectors) {
-                    selectors = selectors.filter(function(selector) { return selector.getIsOutput(); });
-                    rulesetNode.selectors = selectors.length ? selectors : (selectors = null);
-                    if (selectors) { rulesetNode.joinSelectors(paths, context, selectors); }
-                }
-                if (!selectors) { rulesetNode.rules = null; }
-                rulesetNode.paths = paths;
+        this.contexts.push(paths);
+
+        if (! rulesetNode.root) {
+            selectors = rulesetNode.selectors;
+            if (selectors) {
+                selectors = selectors.filter(function(selector) { return selector.getIsOutput(); });
+                rulesetNode.selectors = selectors.length ? selectors : (selectors = null);
+                if (selectors) { rulesetNode.joinSelectors(paths, context, selectors); }
             }
-        },
-        visitRulesetOut: function (rulesetNode) {
-            this.contexts.length = this.contexts.length - 1;
-        },
-        visitMedia: function (mediaNode, visitArgs) {
-            var context = this.contexts[this.contexts.length - 1];
-            mediaNode.rules[0].root = (context.length === 0 || context[0].multiMedia);
+            if (!selectors) { rulesetNode.rules = null; }
+            rulesetNode.paths = paths;
         }
-    };
-    
-    return joinSelectorVisitor;
-};
\ No newline at end of file
+    },
+    visitRulesetOut: function (rulesetNode) {
+        this.contexts.length = this.contexts.length - 1;
+    },
+    visitMedia: function (mediaNode, visitArgs) {
+        var context = this.contexts[this.contexts.length - 1];
+        mediaNode.rules[0].root = (context.length === 0 || context[0].multiMedia);
+    }
+};
+
+module.exports = JoinSelectorVisitor;
diff --git a/lib/less/visitor/to-css-visitor.js b/lib/less/visitor/to-css-visitor.js
index cc3a900..1a8f5e2 100644
--- a/lib/less/visitor/to-css-visitor.js
+++ b/lib/less/visitor/to-css-visitor.js
@@ -1,244 +1,245 @@
-module.exports = function (visitor, tree) {
-    var toCSSVisitor = function(env) {
-        this._visitor = new visitor(this);
-        this._env = env;
-    };
-
-    toCSSVisitor.prototype = {
-        isReplacing: true,
-        run: function (root) {
-            return this._visitor.visit(root);
-        },
-
-        visitRule: function (ruleNode, visitArgs) {
-            if (ruleNode.variable) {
-                return [];
-            }
-            return ruleNode;
-        },
+var tree = require("../tree/index.js"),
+    Visitor = require("./visitor.js");
 
-        visitMixinDefinition: function (mixinNode, visitArgs) {
-            // mixin definitions do not get eval'd - this means they keep state
-            // so we have to clear that state here so it isn't used if toCSS is called twice
-            mixinNode.frames = [];
-            return [];
-        },
+var ToCSSVisitor = function(env) {
+    this._visitor = new Visitor(this);
+    this._env = env;
+};
+
+ToCSSVisitor.prototype = {
+    isReplacing: true,
+    run: function (root) {
+        return this._visitor.visit(root);
+    },
 
-        visitExtend: function (extendNode, visitArgs) {
+    visitRule: function (ruleNode, visitArgs) {
+        if (ruleNode.variable) {
             return [];
-        },
+        }
+        return ruleNode;
+    },
+
+    visitMixinDefinition: function (mixinNode, visitArgs) {
+        // mixin definitions do not get eval'd - this means they keep state
+        // so we have to clear that state here so it isn't used if toCSS is called twice
+        mixinNode.frames = [];
+        return [];
+    },
+
+    visitExtend: function (extendNode, visitArgs) {
+        return [];
+    },
+
+    visitComment: function (commentNode, visitArgs) {
+        if (commentNode.isSilent(this._env)) {
+            return [];
+        }
+        return commentNode;
+    },
 
-        visitComment: function (commentNode, visitArgs) {
-            if (commentNode.isSilent(this._env)) {
-                return [];
-            }
-            return commentNode;
-        },
+    visitMedia: function(mediaNode, visitArgs) {
+        mediaNode.accept(this._visitor);
+        visitArgs.visitDeeper = false;
 
-        visitMedia: function(mediaNode, visitArgs) {
-            mediaNode.accept(this._visitor);
-            visitArgs.visitDeeper = false;
+        if (!mediaNode.rules.length) {
+            return [];
+        }
+        return mediaNode;
+    },
 
-            if (!mediaNode.rules.length) {
+    visitDirective: function(directiveNode, visitArgs) {
+        if (directiveNode.currentFileInfo.reference && !directiveNode.isReferenced) {
+            return [];
+        }
+        if (directiveNode.name === "@charset") {
+            // Only output the debug info together with subsequent @charset definitions
+            // a comment (or @media statement) before the actual @charset directive would
+            // be considered illegal css as it has to be on the first line
+            if (this.charset) {
+                if (directiveNode.debugInfo) {
+                    var comment = new tree.Comment("/* " + directiveNode.toCSS(this._env).replace(/\n/g, "")+" */\n");
+                    comment.debugInfo = directiveNode.debugInfo;
+                    return this._visitor.visit(comment);
+                }
                 return [];
             }
-            return mediaNode;
-        },
+            this.charset = true;
+        }
+        if (directiveNode.rules && directiveNode.rules.rules) {
+            this._mergeRules(directiveNode.rules.rules);
+        }
+        return directiveNode;
+    },
+
+    checkPropertiesInRoot: function(rules) {
+        var ruleNode;
+        for(var i = 0; i < rules.length; i++) {
+            ruleNode = rules[i];
+            if (ruleNode instanceof tree.Rule && !ruleNode.variable) {
+                throw { message: "properties must be inside selector blocks, they cannot be in the root.",
+                    index: ruleNode.index, filename: ruleNode.currentFileInfo ? ruleNode.currentFileInfo.filename : null};
+            }
+        }
+    },
 
-        visitDirective: function(directiveNode, visitArgs) {
-            if (directiveNode.currentFileInfo.reference && !directiveNode.isReferenced) {
-                return [];
+    visitRuleset: function (rulesetNode, visitArgs) {
+        var rule, rulesets = [];
+        if (rulesetNode.firstRoot) {
+            this.checkPropertiesInRoot(rulesetNode.rules);
+        }
+        if (! rulesetNode.root) {
+            if (rulesetNode.paths) {
+                rulesetNode.paths = rulesetNode.paths
+                    .filter(function(p) {
+                        var i;
+                        if (p[0].elements[0].combinator.value === ' ') {
+                            p[0].elements[0].combinator = new(tree.Combinator)('');
+                        }
+                        for(i = 0; i < p.length; i++) {
+                            if (p[i].getIsReferenced() && p[i].getIsOutput()) {
+                                return true;
+                            }
+                        }
+                        return false;
+                    });
             }
-            if (directiveNode.name === "@charset") {
-                // Only output the debug info together with subsequent @charset definitions
-                // a comment (or @media statement) before the actual @charset directive would
-                // be considered illegal css as it has to be on the first line
-                if (this.charset) {
-                    if (directiveNode.debugInfo) {
-                        var comment = new tree.Comment("/* " + directiveNode.toCSS(this._env).replace(/\n/g, "")+" */\n");
-                        comment.debugInfo = directiveNode.debugInfo;
-                        return this._visitor.visit(comment);
-                    }
-                    return [];
+
+            // Compile rules and rulesets
+            var nodeRules = rulesetNode.rules, nodeRuleCnt = nodeRules ? nodeRules.length : 0;
+            for (var i = 0; i < nodeRuleCnt; ) {
+                rule = nodeRules[i];
+                if (rule && rule.rules) {
+                    // visit because we are moving them out from being a child
+                    rulesets.push(this._visitor.visit(rule));
+                    nodeRules.splice(i, 1);
+                    nodeRuleCnt--;
+                    continue;
                 }
-                this.charset = true;
-            }
-            if (directiveNode.rules && directiveNode.rules.rules) {
-                this._mergeRules(directiveNode.rules.rules);
+                i++;
             }
-            return directiveNode;
-        },
-
-        checkPropertiesInRoot: function(rules) {
-            var ruleNode;
-            for(var i = 0; i < rules.length; i++) {
-                ruleNode = rules[i];
-                if (ruleNode instanceof tree.Rule && !ruleNode.variable) {
-                    throw { message: "properties must be inside selector blocks, they cannot be in the root.",
-                        index: ruleNode.index, filename: ruleNode.currentFileInfo ? ruleNode.currentFileInfo.filename : null};
-                }
+            // accept the visitor to remove rules and refactor itself
+            // then we can decide now whether we want it or not
+            if (nodeRuleCnt > 0) {
+                rulesetNode.accept(this._visitor);
+            } else {
+                rulesetNode.rules = null;
             }
-        },
+            visitArgs.visitDeeper = false;
 
-        visitRuleset: function (rulesetNode, visitArgs) {
-            var rule, rulesets = [];
-            if (rulesetNode.firstRoot) {
-                this.checkPropertiesInRoot(rulesetNode.rules);
+            nodeRules = rulesetNode.rules;
+            if (nodeRules) {
+                this._mergeRules(nodeRules);
+                nodeRules = rulesetNode.rules;
             }
-            if (! rulesetNode.root) {
-                if (rulesetNode.paths) {
-                    rulesetNode.paths = rulesetNode.paths
-                        .filter(function(p) {
-                            var i;
-                            if (p[0].elements[0].combinator.value === ' ') {
-                                p[0].elements[0].combinator = new(tree.Combinator)('');
-                            }
-                            for(i = 0; i < p.length; i++) {
-                                if (p[i].getIsReferenced() && p[i].getIsOutput()) {
-                                    return true;
-                                }
-                            }
-                            return false;
-                        });
-                }
-
-                // Compile rules and rulesets
-                var nodeRules = rulesetNode.rules, nodeRuleCnt = nodeRules ? nodeRules.length : 0;
-                for (var i = 0; i < nodeRuleCnt; ) {
-                    rule = nodeRules[i];
-                    if (rule && rule.rules) {
-                        // visit because we are moving them out from being a child
-                        rulesets.push(this._visitor.visit(rule));
-                        nodeRules.splice(i, 1);
-                        nodeRuleCnt--;
-                        continue;
-                    }
-                    i++;
-                }
-                // accept the visitor to remove rules and refactor itself
-                // then we can decide now whether we want it or not
-                if (nodeRuleCnt > 0) {
-                    rulesetNode.accept(this._visitor);
-                } else {
-                    rulesetNode.rules = null;
-                }
-                visitArgs.visitDeeper = false;
-
+            if (nodeRules) {
+                this._removeDuplicateRules(nodeRules);
                 nodeRules = rulesetNode.rules;
-                if (nodeRules) {
-                    this._mergeRules(nodeRules);
-                    nodeRules = rulesetNode.rules;
-                }
-                if (nodeRules) {
-                    this._removeDuplicateRules(nodeRules);
-                    nodeRules = rulesetNode.rules;
-                }
+            }
 
-                // now decide whether we keep the ruleset
-                if (nodeRules && nodeRules.length > 0 && rulesetNode.paths.length > 0) {
-                    rulesets.splice(0, 0, rulesetNode);
-                }
-            } else {
-                rulesetNode.accept(this._visitor);
-                visitArgs.visitDeeper = false;
-                if (rulesetNode.firstRoot || (rulesetNode.rules && rulesetNode.rules.length > 0)) {
-                    rulesets.splice(0, 0, rulesetNode);
-                }
+            // now decide whether we keep the ruleset
+            if (nodeRules && nodeRules.length > 0 && rulesetNode.paths.length > 0) {
+                rulesets.splice(0, 0, rulesetNode);
             }
-            if (rulesets.length === 1) {
-                return rulesets[0];
+        } else {
+            rulesetNode.accept(this._visitor);
+            visitArgs.visitDeeper = false;
+            if (rulesetNode.firstRoot || (rulesetNode.rules && rulesetNode.rules.length > 0)) {
+                rulesets.splice(0, 0, rulesetNode);
             }
-            return rulesets;
-        },
+        }
+        if (rulesets.length === 1) {
+            return rulesets[0];
+        }
+        return rulesets;
+    },
 
-        _removeDuplicateRules: function(rules) {
-            if (!rules) { return; }
+    _removeDuplicateRules: function(rules) {
+        if (!rules) { return; }
 
-            // remove duplicates
-            var ruleCache = {},
-                ruleList, rule, i;
+        // remove duplicates
+        var ruleCache = {},
+            ruleList, rule, i;
 
-            for(i = rules.length - 1; i >= 0 ; i--) {
-                rule = rules[i];
-                if (rule instanceof tree.Rule) {
-                    if (!ruleCache[rule.name]) {
-                        ruleCache[rule.name] = rule;
+        for(i = rules.length - 1; i >= 0 ; i--) {
+            rule = rules[i];
+            if (rule instanceof tree.Rule) {
+                if (!ruleCache[rule.name]) {
+                    ruleCache[rule.name] = rule;
+                } else {
+                    ruleList = ruleCache[rule.name];
+                    if (ruleList instanceof tree.Rule) {
+                        ruleList = ruleCache[rule.name] = [ruleCache[rule.name].toCSS(this._env)];
+                    }
+                    var ruleCSS = rule.toCSS(this._env);
+                    if (ruleList.indexOf(ruleCSS) !== -1) {
+                        rules.splice(i, 1);
                     } else {
-                        ruleList = ruleCache[rule.name];
-                        if (ruleList instanceof tree.Rule) {
-                            ruleList = ruleCache[rule.name] = [ruleCache[rule.name].toCSS(this._env)];
-                        }
-                        var ruleCSS = rule.toCSS(this._env);
-                        if (ruleList.indexOf(ruleCSS) !== -1) {
-                            rules.splice(i, 1);
-                        } else {
-                            ruleList.push(ruleCSS);
-                        }
+                        ruleList.push(ruleCSS);
                     }
                 }
             }
-        },
+        }
+    },
 
-        _mergeRules: function (rules) {
-            if (!rules) { return; }
+    _mergeRules: function (rules) {
+        if (!rules) { return; }
 
-            var groups = {},
-                parts,
-                rule,
-                key;
+        var groups = {},
+            parts,
+            rule,
+            key;
 
-            for (var i = 0; i < rules.length; i++) {
-                rule = rules[i];
+        for (var i = 0; i < rules.length; i++) {
+            rule = rules[i];
 
-                if ((rule instanceof tree.Rule) && rule.merge) {
-                    key = [rule.name,
-                        rule.important ? "!" : ""].join(",");
+            if ((rule instanceof tree.Rule) && rule.merge) {
+                key = [rule.name,
+                    rule.important ? "!" : ""].join(",");
 
-                    if (!groups[key]) {
-                        groups[key] = [];
-                    } else {
-                        rules.splice(i--, 1);
-                    }
-
-                    groups[key].push(rule);
+                if (!groups[key]) {
+                    groups[key] = [];
+                } else {
+                    rules.splice(i--, 1);
                 }
+
+                groups[key].push(rule);
             }
+        }
 
-            Object.keys(groups).map(function (k) {
+        Object.keys(groups).map(function (k) {
 
-                function toExpression(values) {
-                    return new (tree.Expression)(values.map(function (p) {
-                        return p.value;
-                    }));
-                }
+            function toExpression(values) {
+                return new (tree.Expression)(values.map(function (p) {
+                    return p.value;
+                }));
+            }
 
-                function toValue(values) {
-                    return new (tree.Value)(values.map(function (p) {
-                        return p;
-                    }));
-                }
+            function toValue(values) {
+                return new (tree.Value)(values.map(function (p) {
+                    return p;
+                }));
+            }
 
-                parts = groups[k];
+            parts = groups[k];
 
-                if (parts.length > 1) {
-                    rule = parts[0];
-                    var spacedGroups = [];
-                    var lastSpacedGroup = [];
-                    parts.map(function (p) {
-                    if (p.merge==="+") {
-                        if (lastSpacedGroup.length > 0) {
-                                spacedGroups.push(toExpression(lastSpacedGroup));
-                            }
-                            lastSpacedGroup = [];
+            if (parts.length > 1) {
+                rule = parts[0];
+                var spacedGroups = [];
+                var lastSpacedGroup = [];
+                parts.map(function (p) {
+                if (p.merge==="+") {
+                    if (lastSpacedGroup.length > 0) {
+                            spacedGroups.push(toExpression(lastSpacedGroup));
                         }
-                        lastSpacedGroup.push(p);
-                    });
-                    spacedGroups.push(toExpression(lastSpacedGroup));
-                    rule.value = toValue(spacedGroups);
-                }
-            });
-        }
-    };
-    
-    return toCSSVisitor;
+                        lastSpacedGroup = [];
+                    }
+                    lastSpacedGroup.push(p);
+                });
+                spacedGroups.push(toExpression(lastSpacedGroup));
+                rule.value = toValue(spacedGroups);
+            }
+        });
+    }
 };
+
+module.exports = ToCSSVisitor;
diff --git a/lib/less/visitor/visitor.js b/lib/less/visitor/visitor.js
index d6cade4..cd0b328 100644
--- a/lib/less/visitor/visitor.js
+++ b/lib/less/visitor/visitor.js
@@ -1,146 +1,145 @@
-module.exports = function (tree) {
+var tree = require("../tree/index.js");
+
+var _visitArgs = { visitDeeper: true },
+    _hasIndexed = false;
+
+function _noop(node) {
+    return node;
+}
+
+function indexNodeTypes(parent, ticker) {
+    // add .typeIndex to tree node types for lookup table
+    var key, child;
+    for (key in parent) {
+        if (parent.hasOwnProperty(key)) {
+            child = parent[key];
+            switch (typeof child) {
+                case "function":
+                    // ignore bound functions directly on tree which do not have a prototype
+                    // or aren't nodes
+                    if (child.prototype && child.prototype.type) {
+                        child.prototype.typeIndex = ticker++;
+                    }
+                    break;
+                case "object":
+                    ticker = indexNodeTypes(child, ticker);
+                    break;
+            }
+        }
+    }
+    return ticker;
+}
 
-    var _visitArgs = { visitDeeper: true },
-        _hasIndexed = false;
+var Visitor = function(implementation) {
+    this._implementation = implementation;
+    this._visitFnCache = [];
 
-    function _noop(node) {
-        return node;
+    if (!_hasIndexed) {
+        indexNodeTypes(tree, 1);
+        _hasIndexed = true;
     }
+};
 
-    function indexNodeTypes(parent, ticker) {
-        // add .typeIndex to tree node types for lookup table
-        var key, child;
-        for (key in parent) {
-            if (parent.hasOwnProperty(key)) {
-                child = parent[key];
-                switch (typeof child) {
-                    case "function":
-                        // ignore bound functions directly on tree which do not have a prototype
-                        // or aren't nodes
-                        if (child.prototype && child.prototype.type) {
-                            child.prototype.typeIndex = ticker++;
-                        }
-                        break;
-                    case "object":
-                        ticker = indexNodeTypes(child, ticker);
-                        break;
-                }
-            }
+Visitor.prototype = {
+    visit: function(node) {
+        if (!node) {
+            return node;
         }
-        return ticker;
-    }
 
-    var visitor = function(implementation) {
-        this._implementation = implementation;
-        this._visitFnCache = [];
+        var nodeTypeIndex = node.typeIndex;
+        if (!nodeTypeIndex) {
+            return node;
+        }
 
-        if (!_hasIndexed) {
-            indexNodeTypes(tree, 1);
-            _hasIndexed = true;
+        var visitFnCache = this._visitFnCache,
+            impl = this._implementation,
+            aryIndx = nodeTypeIndex << 1,
+            outAryIndex = aryIndx | 1,
+            func = visitFnCache[aryIndx],
+            funcOut = visitFnCache[outAryIndex],
+            visitArgs = _visitArgs,
+            fnName;
+
+        visitArgs.visitDeeper = true;
+
+        if (!func) {
+            fnName = "visit" + node.type;
+            func = impl[fnName] || _noop;
+            funcOut = impl[fnName + "Out"] || _noop;
+            visitFnCache[aryIndx] = func;
+            visitFnCache[outAryIndex] = funcOut;
         }
-    };
 
-    visitor.prototype = {
-        visit: function(node) {
-            if (!node) {
-                return node;
+        if (func !== _noop) {
+            var newNode = func.call(impl, node, visitArgs);
+            if (impl.isReplacing) {
+                node = newNode;
             }
+        }
 
-            var nodeTypeIndex = node.typeIndex;
-            if (!nodeTypeIndex) {
-                return node;
-            }
+        if (visitArgs.visitDeeper && node && node.accept) {
+            node.accept(this);
+        }
 
-            var visitFnCache = this._visitFnCache,
-                impl = this._implementation,
-                aryIndx = nodeTypeIndex << 1,
-                outAryIndex = aryIndx | 1,
-                func = visitFnCache[aryIndx],
-                funcOut = visitFnCache[outAryIndex],
-                visitArgs = _visitArgs,
-                fnName;
-
-            visitArgs.visitDeeper = true;
-
-            if (!func) {
-                fnName = "visit" + node.type;
-                func = impl[fnName] || _noop;
-                funcOut = impl[fnName + "Out"] || _noop;
-                visitFnCache[aryIndx] = func;
-                visitFnCache[outAryIndex] = funcOut;
-            }
+        if (funcOut != _noop) {
+            funcOut.call(impl, node);
+        }
 
-            if (func !== _noop) {
-                var newNode = func.call(impl, node, visitArgs);
-                if (impl.isReplacing) {
-                    node = newNode;
-                }
-            }
+        return node;
+    },
+    visitArray: function(nodes, nonReplacing) {
+        if (!nodes) {
+            return nodes;
+        }
 
-            if (visitArgs.visitDeeper && node && node.accept) {
-                node.accept(this);
-            }
+        var cnt = nodes.length, i;
 
-            if (funcOut != _noop) {
-                funcOut.call(impl, node);
+        // Non-replacing
+        if (nonReplacing || !this._implementation.isReplacing) {
+            for (i = 0; i < cnt; i++) {
+                this.visit(nodes[i]);
             }
+            return nodes;
+        }
 
-            return node;
-        },
-        visitArray: function(nodes, nonReplacing) {
-            if (!nodes) {
-                return nodes;
+        // Replacing
+        var out = [];
+        for (i = 0; i < cnt; i++) {
+            var evald = this.visit(nodes[i]);
+            if (!evald.splice) {
+                out.push(evald);
+            } else if (evald.length) {
+                this.flatten(evald, out);
             }
+        }
+        return out;
+    },
+    flatten: function(arr, out) {
+        if (!out) {
+            out = [];
+        }
 
-            var cnt = nodes.length, i;
-
-            // Non-replacing
-            if (nonReplacing || !this._implementation.isReplacing) {
-                for (i = 0; i < cnt; i++) {
-                    this.visit(nodes[i]);
-                }
-                return nodes;
-            }
+        var cnt, i, item,
+            nestedCnt, j, nestedItem;
 
-            // Replacing
-            var out = [];
-            for (i = 0; i < cnt; i++) {
-                var evald = this.visit(nodes[i]);
-                if (!evald.splice) {
-                    out.push(evald);
-                } else if (evald.length) {
-                    this.flatten(evald, out);
-                }
-            }
-            return out;
-        },
-        flatten: function(arr, out) {
-            if (!out) {
-                out = [];
+        for (i = 0, cnt = arr.length; i < cnt; i++) {
+            item = arr[i];
+            if (!item.splice) {
+                out.push(item);
+                continue;
             }
 
-            var cnt, i, item,
-                nestedCnt, j, nestedItem;
-
-            for (i = 0, cnt = arr.length; i < cnt; i++) {
-                item = arr[i];
-                if (!item.splice) {
-                    out.push(item);
-                    continue;
-                }
-
-                for (j = 0, nestedCnt = item.length; j < nestedCnt; j++) {
-                    nestedItem = item[j];
-                    if (!nestedItem.splice) {
-                        out.push(nestedItem);
-                    } else if (nestedItem.length) {
-                        this.flatten(nestedItem, out);
-                    }
+            for (j = 0, nestedCnt = item.length; j < nestedCnt; j++) {
+                nestedItem = item[j];
+                if (!nestedItem.splice) {
+                    out.push(nestedItem);
+                } else if (nestedItem.length) {
+                    this.flatten(nestedItem, out);
                 }
             }
-
-            return out;
         }
-    };
-    return visitor;
+
+        return out;
+    }
 };
+module.exports = Visitor;

-- 
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