[Pkg-javascript-commits] [less.js] 23/285: add browserify (not yet working) and refactor tree nodes to not be dependent on their parent (currently breaks browser build)

Jonas Smedegaard dr at jones.dk
Mon Oct 26 23:23:33 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 08bd23dc2ae76b4a36504d5b069d8ef7b6467287
Author: Luke Page <luke.a.page at gmail.com>
Date:   Mon Feb 24 21:22:52 2014 +0000

    add browserify (not yet working) and refactor tree nodes to not be dependent on their parent (currently breaks browser build)
---
 Gruntfile.js                        |   8 +
 build/build.yml                     |   2 +-
 lib/less/colors.js                  |   4 +-
 lib/less/encoder.js                 |   4 -
 lib/less/env.js                     |   4 +-
 lib/less/environments/node.js       |   3 +
 lib/less/extend-visitor.js          |   4 +-
 lib/less/functions.js               |  25 +--
 lib/less/import-visitor.js          |   4 +-
 lib/less/index.js                   | 192 +++++++++-------------
 lib/less/join-selector-visitor.js   |   4 +-
 lib/less/non-node-index.js          |  18 +++
 lib/less/parser.js                  |  18 +--
 lib/less/source-map-output.js       |   4 +-
 lib/less/to-css-visitor.js          |   5 +-
 lib/less/tree.js                    |  45 +++++-
 lib/less/tree/alpha.js              |  12 +-
 lib/less/tree/anonymous.js          |  12 +-
 lib/less/tree/assignment.js         |  12 +-
 lib/less/tree/attribute.js          |  29 ++++
 lib/less/tree/call.js               |  12 +-
 lib/less/tree/color.js              |  18 +--
 lib/less/tree/combinator.js         |  40 +++++
 lib/less/tree/comment.js            |  10 +-
 lib/less/tree/condition.js          |  10 +-
 lib/less/tree/detached-ruleset.js   |  11 +-
 lib/less/tree/dimension.js          | 177 ++------------------
 lib/less/tree/directive.js          |  12 +-
 lib/less/tree/element.js            |  73 +--------
 lib/less/tree/expression.js         |  12 +-
 lib/less/tree/extend.js             |  18 +--
 lib/less/tree/import.js             |  14 +-
 lib/less/tree/javascript.js         |  11 +-
 lib/less/tree/keyword.js            |  17 +-
 lib/less/tree/media.js              |  12 +-
 lib/less/tree/mixin-call.js         | 152 +++++++++++++++++
 lib/less/tree/mixin-definition.js   | 165 +++++++++++++++++++
 lib/less/tree/mixin.js              | 315 ------------------------------------
 lib/less/tree/negative.js           |  12 +-
 lib/less/tree/operation.js          |  13 +-
 lib/less/tree/paren.js              |  13 +-
 lib/less/tree/quoted.js             |  10 +-
 lib/less/tree/rule.js               |  14 +-
 lib/less/tree/ruleset-call.js       |  10 +-
 lib/less/tree/ruleset.js            |  19 +--
 lib/less/tree/selector.js           |  12 +-
 lib/less/tree/unicode-descriptor.js |  10 +-
 lib/less/tree/unit-conversions.js   |  21 +++
 lib/less/tree/unit.js               | 137 ++++++++++++++++
 lib/less/tree/url.js                |  12 +-
 lib/less/tree/value.js              |  12 +-
 lib/less/tree/variable.js           |  12 +-
 lib/less/visitor.js                 |   4 +-
 package.json                        |   3 +-
 54 files changed, 921 insertions(+), 881 deletions(-)

diff --git a/Gruntfile.js b/Gruntfile.js
index 3fba33e..b47a0dc 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -47,6 +47,14 @@ module.exports = function(grunt) {
             'node node_modules/http-server/bin/http-server test/sourcemaps -p 8084'].join('&&')
       }
     },
+
+    browserify: {
+      dist: {
+          files: {
+              'dist/less.js': ['lib/less/non-node-index.js', 'lib/less/browser.js', 'lib/less/environment/browser.js']
+          }
+      }
+    },
     concat: {
       options: {
         stripBanners: 'all',
diff --git a/build/build.yml b/build/build.yml
index 2dd328e..098901e 100644
--- a/build/build.yml
+++ b/build/build.yml
@@ -137,7 +137,7 @@ tree:
   - <%= build.lib %>/tree/javascript.js
   - <%= build.lib %>/tree/keyword.js
   - <%= build.lib %>/tree/media.js
-  - <%= build.lib %>/tree/mixin.js
+  - <%= build.lib %>/tree/mixin-call.js
   - <%= build.lib %>/tree/negative.js
   - <%= build.lib %>/tree/operation.js
   - <%= build.lib %>/tree/paren.js
diff --git a/lib/less/colors.js b/lib/less/colors.js
index e509b60..dd213f2 100644
--- a/lib/less/colors.js
+++ b/lib/less/colors.js
@@ -1,4 +1,4 @@
-(function (tree) {
+module.exports = function (tree) {
     tree.colors = {
         'aliceblue':'#f0f8ff',
         'antiquewhite':'#faebd7',
@@ -148,4 +148,4 @@
         'yellow':'#ffff00',
         'yellowgreen':'#9acd32'
     };
-})(require('./tree'));
+};
diff --git a/lib/less/encoder.js b/lib/less/encoder.js
deleted file mode 100644
index 65902f7..0000000
--- a/lib/less/encoder.js
+++ /dev/null
@@ -1,4 +0,0 @@
-// base64 encoder implementation for node
-exports.encodeBase64 = function(str) {
-    return new Buffer(str).toString('base64');
-};
diff --git a/lib/less/env.js b/lib/less/env.js
index 41eabe5..8019294 100644
--- a/lib/less/env.js
+++ b/lib/less/env.js
@@ -1,4 +1,4 @@
-(function (tree) {
+module.exports = function (tree) {
 
     var parseCopyProperties = [
         'paths',            // option - unmodified - paths to search for imports on
@@ -132,4 +132,4 @@
         }
     };
 
-})(require('./tree'));
+};
diff --git a/lib/less/environments/node.js b/lib/less/environments/node.js
index 7aab317..a4cae9b 100644
--- a/lib/less/environments/node.js
+++ b/lib/less/environments/node.js
@@ -8,6 +8,9 @@ module.exports = {
     warn: function(env, msg) {
         console.warn(msg);
     },
+    encodeBase64: function encodeBase64(env, str) {
+        return new Buffer(str).toString('base64');
+    },
     getPath: function (env, filename) {
         var j = filename.lastIndexOf('/');
         if (j < 0) {
diff --git a/lib/less/extend-visitor.js b/lib/less/extend-visitor.js
index 4b397a9..211e6ad 100644
--- a/lib/less/extend-visitor.js
+++ b/lib/less/extend-visitor.js
@@ -1,4 +1,4 @@
-(function (tree) {
+module.exports = function (tree) {
     /*jshint loopfunc:true */
 
     tree.extendFinderVisitor = function() {
@@ -413,4 +413,4 @@
         }
     };
 
-})(require('./tree'));
+};
diff --git a/lib/less/functions.js b/lib/less/functions.js
index 5d4c0eb..8fac47a 100644
--- a/lib/less/functions.js
+++ b/lib/less/functions.js
@@ -1,6 +1,6 @@
-(function (tree) {
+module.exports = function (less, tree) {
 
-tree.functions = {
+var functions = {
     rgb: function (r, g, b) {
         return this.rgba(r, g, b, 1.0);
     },
@@ -530,7 +530,7 @@ tree.functions = {
 
         if (useBase64) {
             try {
-                returner = require('./encoder').encodeBase64(returner); // TODO browser implementation
+                returner = less.Parser.environment.encodeBase64(this.env, returner);
             } catch(e) {
                 useBase64 = false;
             }
@@ -687,30 +687,30 @@ tree.defaultFunc = {
 };
 
 function initFunctions() {
-    var f, tf = tree.functions;
+    var f;
     
     // math
     for (f in mathFunctions) {
         if (mathFunctions.hasOwnProperty(f)) {
-            tf[f] = _math.bind(null, Math[f], mathFunctions[f]);
+            functions[f] = _math.bind(null, Math[f], mathFunctions[f]);
         }
     }
     
     // color blending
     for (f in colorBlendMode) {
         if (colorBlendMode.hasOwnProperty(f)) {
-            tf[f] = colorBlend.bind(null, colorBlendMode[f]);
+            functions[f] = colorBlend.bind(null, colorBlendMode[f]);
         }
     }
     
     // default
     f = tree.defaultFunc;
-    tf["default"] = f.eval.bind(f);
+    functions["default"] = f.eval.bind(f);
     
 } initFunctions();
 
 function hsla(color) {
-    return tree.functions.hsla(color.h, color.s, color.l, color.a);
+    return functions.hsla(color.h, color.s, color.l, color.a);
 }
 
 function scaled(n, size) {
@@ -748,11 +748,14 @@ tree.fround = function(env, value) {
     }
 };
 
-tree.functionCall = function(env, currentFileInfo) {
+tree.functionCall = function(env, currentFileInfo, environment) {
     this.env = env;
+    this.environment = environment;
     this.currentFileInfo = currentFileInfo;
 };
 
-tree.functionCall.prototype = tree.functions;
+tree.functionCall.prototype = functions;
 
-})(require('./tree'));
+return functions;
+    
+};
diff --git a/lib/less/import-visitor.js b/lib/less/import-visitor.js
index 0d773ca..7b1cbcc 100644
--- a/lib/less/import-visitor.js
+++ b/lib/less/import-visitor.js
@@ -1,4 +1,4 @@
-(function (tree) {
+module.exports = function (tree) {
     tree.importVisitor = function(importer, finish, evalEnv) {
         this._visitor = new tree.visitor(this);
         this._importer = importer;
@@ -115,4 +115,4 @@
         }
     };
 
-})(require('./tree'));
\ No newline at end of file
+};
diff --git a/lib/less/index.js b/lib/less/index.js
index 0138cd3..a2c6917 100644
--- a/lib/less/index.js
+++ b/lib/less/index.js
@@ -1,137 +1,95 @@
-var less = {
-    version: [1, 6, 3],
-    Parser: require('./parser').Parser,
-    tree: require('./tree'),
-    render: function (input, options, callback) {
-        options = options || {};
-
-        if (typeof(options) === 'function') {
-            callback = options;
-            options = {};
-        }
+var less = require("./non-node-index.js");
+
+less.render = function (input, options, callback) {
+    options = options || {};
 
-        var parser = new(less.Parser)(options),
-            ee;
+    if (typeof(options) === 'function') {
+        callback = options;
+        options = {};
+    }
 
-        if (callback) {
+    var parser = new(less.Parser)(options),
+        ee;
+
+    if (callback) {
+        parser.parse(input, function (e, root) {
+            if (e) { callback(e); return; }
+            var css;
+            try {
+                css = root && root.toCSS && root.toCSS(options);
+            } 
+            catch (err) { callback(err); return; }
+            callback(null, css);
+        });
+    } else {
+        ee = new (require('events').EventEmitter)();
+
+        process.nextTick(function () {
             parser.parse(input, function (e, root) {
-                if (e) { callback(e); return; }
-                var css;
-                try {
-                    css = root && root.toCSS && root.toCSS(options);
-                } 
-                catch (err) { callback(err); return; }
-                callback(null, css);
+                if (e) { return ee.emit('error', e); }
+                try { ee.emit('success', root.toCSS(options)); } 
+                catch (err) { ee.emit('error', err); }
             });
-        } else {
-            ee = new (require('events').EventEmitter)();
-
-            process.nextTick(function () {
-                parser.parse(input, function (e, root) {
-                    if (e) { return ee.emit('error', e); }
-                    try { ee.emit('success', root.toCSS(options)); } 
-                    catch (err) { ee.emit('error', err); }
-                });
-            });
-            return ee;
-        }
-    },
-    formatError: function(ctx, options) {
-        options = options || {};
-
-        var message = "";
-        var extract = ctx.extract;
-        var error = [];
-        var stylize = options.color ? require('./lessc_helper').stylize : function (str) { return str; };
+        });
+        return ee;
+    }
+};
+less.formatError = function(ctx, options) {
+    options = options || {};
 
-        // only output a stack if it isn't a less error
-        if (ctx.stack && !ctx.type) { return stylize(ctx.stack, 'red'); }
+    var message = "";
+    var extract = ctx.extract;
+    var error = [];
+    var stylize = options.color ? require('./lessc_helper').stylize : function (str) { return str; };
 
-        if (!ctx.hasOwnProperty('index') || !extract) {
-            return ctx.stack || ctx.message;
-        }
+    // only output a stack if it isn't a less error
+    if (ctx.stack && !ctx.type) { return stylize(ctx.stack, 'red'); }
 
-        if (typeof(extract[0]) === 'string') {
-            error.push(stylize((ctx.line - 1) + ' ' + extract[0], 'grey'));
-        }
+    if (!ctx.hasOwnProperty('index') || !extract) {
+        return ctx.stack || ctx.message;
+    }
 
-        if (typeof(extract[1]) === 'string') {
-            var errorTxt = ctx.line + ' ';
-            if (extract[1]) {
-                errorTxt += extract[1].slice(0, ctx.column) +
-                                stylize(stylize(stylize(extract[1][ctx.column], 'bold') +
-                                extract[1].slice(ctx.column + 1), 'red'), 'inverse');
-            }
-            error.push(errorTxt);
-        }
+    if (typeof(extract[0]) === 'string') {
+        error.push(stylize((ctx.line - 1) + ' ' + extract[0], 'grey'));
+    }
 
-        if (typeof(extract[2]) === 'string') {
-            error.push(stylize((ctx.line + 1) + ' ' + extract[2], 'grey'));
+    if (typeof(extract[1]) === 'string') {
+        var errorTxt = ctx.line + ' ';
+        if (extract[1]) {
+            errorTxt += extract[1].slice(0, ctx.column) +
+                            stylize(stylize(stylize(extract[1][ctx.column], 'bold') +
+                            extract[1].slice(ctx.column + 1), 'red'), 'inverse');
         }
-        error = error.join('\n') + stylize('', 'reset') + '\n';
+        error.push(errorTxt);
+    }
 
-        message += stylize(ctx.type + 'Error: ' + ctx.message, 'red');
-        if (ctx.filename) {
-            message += stylize(' in ', 'red') + ctx.filename +
-                stylize(' on line ' + ctx.line + ', column ' + (ctx.column + 1) + ':', 'grey');
-        }
+    if (typeof(extract[2]) === 'string') {
+        error.push(stylize((ctx.line + 1) + ' ' + extract[2], 'grey'));
+    }
+    error = error.join('\n') + stylize('', 'reset') + '\n';
 
-        message += '\n' + error;
+    message += stylize(ctx.type + 'Error: ' + ctx.message, 'red');
+    if (ctx.filename) {
+        message += stylize(' in ', 'red') + ctx.filename +
+            stylize(' on line ' + ctx.line + ', column ' + (ctx.column + 1) + ':', 'grey');
+    }
 
-        if (ctx.callLine) {
-            message += stylize('from ', 'red') + (ctx.filename || '') + '/n';
-            message += stylize(ctx.callLine, 'grey') + ' ' + ctx.callExtract + '/n';
-        }
+    message += '\n' + error;
 
-        return message;
-    },
-    writeError: function (ctx, options) {
-        options = options || {};
-        if (options.silent) { return; }
-        console.error(less.formatError(ctx, options));
+    if (ctx.callLine) {
+        message += stylize('from ', 'red') + (ctx.filename || '') + '/n';
+        message += stylize(ctx.callLine, 'grey') + ' ' + ctx.callExtract + '/n';
     }
+
+    return message;
+};
+    
+less.writeError = function (ctx, options) {
+    options = options || {};
+    if (options.silent) { return; }
+    console.error(less.formatError(ctx, options));
 };
 
 less.Parser.environment = require("./environments/node");
 
-require('./tree/color');
-require('./tree/directive');
-require('./tree/detached-ruleset');
-require('./tree/operation');
-require('./tree/dimension');
-require('./tree/keyword');
-require('./tree/variable');
-require('./tree/ruleset');
-require('./tree/element');
-require('./tree/selector');
-require('./tree/quoted');
-require('./tree/expression');
-require('./tree/rule');
-require('./tree/call');
-require('./tree/url');
-require('./tree/alpha');
-require('./tree/import');
-require('./tree/mixin');
-require('./tree/comment');
-require('./tree/anonymous');
-require('./tree/value');
-require('./tree/javascript');
-require('./tree/assignment');
-require('./tree/condition');
-require('./tree/paren');
-require('./tree/media');
-require('./tree/unicode-descriptor');
-require('./tree/negative');
-require('./tree/extend');
-require('./tree/ruleset-call');
-require('./env');
-require('./functions');
-require('./colors');
-require('./visitor.js');
-require('./import-visitor.js');
-require('./extend-visitor.js');
-require('./join-selector-visitor.js');
-require('./to-css-visitor.js');
-require('./source-map-output.js');
-
 module.exports = less;
diff --git a/lib/less/join-selector-visitor.js b/lib/less/join-selector-visitor.js
index 75a61d6..13b3a59 100644
--- a/lib/less/join-selector-visitor.js
+++ b/lib/less/join-selector-visitor.js
@@ -1,4 +1,4 @@
-(function (tree) {
+module.exports = function (tree) {
     tree.joinSelectorVisitor = function() {
         this.contexts = [[]];
         this._visitor = new tree.visitor(this);
@@ -41,4 +41,4 @@
         }
     };
 
-})(require('./tree'));
\ No newline at end of file
+};
\ No newline at end of file
diff --git a/lib/less/non-node-index.js b/lib/less/non-node-index.js
new file mode 100644
index 0000000..5c3f8c7
--- /dev/null
+++ b/lib/less/non-node-index.js
@@ -0,0 +1,18 @@
+var less = {
+    version: [1, 6, 3]
+};
+
+less.tree = (require('./tree'))(less);
+less.Parser = (require('./parser'))(less, less.tree);
+less.tree.functions = (require('./functions'))(less, less.tree);
+require('./env')(less.tree);
+
+require('./colors')(less.tree);
+require('./visitor.js')(less.tree);
+require('./import-visitor.js')(less.tree);
+require('./extend-visitor.js')(less.tree);
+require('./join-selector-visitor.js')(less.tree);
+require('./to-css-visitor.js')(less.tree);
+require('./source-map-output.js')(less.tree);
+
+module.exports = less;
diff --git a/lib/less/parser.js b/lib/less/parser.js
index f357b87..8c94f8b 100644
--- a/lib/less/parser.js
+++ b/lib/less/parser.js
@@ -1,11 +1,4 @@
-var less, tree;
-
-// Node.js does not have a header file added which defines less
-if (less === undefined) {
-    less = exports;
-    tree = require('./tree');
-    less.mode = 'node';
-}
+module.exports = function(less, tree) {
 //
 // less.js - parser
 //
@@ -39,7 +32,7 @@ if (less === undefined) {
 //    It also takes care of moving all the indices forwards.
 //
 //
-less.Parser = function Parser(env) {
+var Parser = function Parser(env) {
     var input,       // LeSS input string
         i,           // current index in `input`
         j,           // current chunk
@@ -2064,16 +2057,19 @@ less.Parser = function Parser(env) {
     };
     return parser;
 };
-less.Parser.serializeVars = function(vars) {
+Parser.serializeVars = function(vars) {
     var s = '';
 
     for (var name in vars) {
         if (Object.hasOwnProperty.call(vars, name)) {
             var value = vars[name];
             s += ((name[0] === '@') ? '' : '@') + name +': '+ value +
-                    ((('' + value).slice(-1) === ';') ? '' : ';');
+                ((('' + value).slice(-1) === ';') ? '' : ';');
         }
     }
 
     return s;
 };
+
+return Parser;
+};
\ No newline at end of file
diff --git a/lib/less/source-map-output.js b/lib/less/source-map-output.js
index 9a090d4..2fd10ec 100644
--- a/lib/less/source-map-output.js
+++ b/lib/less/source-map-output.js
@@ -1,4 +1,4 @@
-(function (tree) {
+module.exports = function (tree) {
 
     tree.sourceMapOutput = function (options) {
         this._css = [];
@@ -138,4 +138,4 @@
         return this._css.join('');
     };
 
-})(require('./tree'));
+};
diff --git a/lib/less/to-css-visitor.js b/lib/less/to-css-visitor.js
index 53f4ee0..c58f11a 100644
--- a/lib/less/to-css-visitor.js
+++ b/lib/less/to-css-visitor.js
@@ -1,4 +1,4 @@
-(function (tree) {
+module.exports = function (tree) {
     tree.toCSSVisitor = function(env) {
         this._visitor = new tree.visitor(this);
         this._env = env;
@@ -236,5 +236,4 @@
             });
         }
     };
-
-})(require('./tree'));
\ No newline at end of file
+};
diff --git a/lib/less/tree.js b/lib/less/tree.js
index cd1352f..fac177b 100644
--- a/lib/less/tree.js
+++ b/lib/less/tree.js
@@ -1,5 +1,7 @@
-(function (tree) {
+module.exports = function (less) {
 
+var tree = {};
+  
 tree.debugInfo = function(env, ctx, lineSeperator) {
     var result="";
     if (env.dumpLineNumbers && !env.compress) {
@@ -94,4 +96,43 @@ tree.outputRuleset = function (env, output, rules) {
     env.tabLevel--;
 };
 
-})(require('./tree'));
+tree.Alpha = require('./tree/alpha')(tree);
+tree.Color = require('./tree/color')(tree);
+tree.Directive = require('./tree/directive')(tree);
+tree.DetachedRuleset = require('./tree/detached-ruleset')(tree);
+tree.Operation = require('./tree/operation')(tree);
+tree.Dimension = require('./tree/dimension')(tree, require('./tree/unit-conversions')); //todo move conversions
+tree.Unit = require('./tree/unit')(tree, require('./tree/unit-conversions'));
+tree.Keyword = require('./tree/keyword')(tree);
+tree.Variable = require('./tree/variable')(tree);
+tree.Ruleset = require('./tree/ruleset')(tree);
+tree.Element = require('./tree/element')(tree);
+tree.Attribute = require('./tree/attribute')(tree);
+tree.Combinator = require('./tree/combinator')(tree);
+tree.Selector = require('./tree/selector')(tree);
+tree.Quoted = require('./tree/quoted')(tree);
+tree.Expression = require('./tree/expression')(tree);
+tree.Rule = require('./tree/rule')(tree);
+tree.Call = require('./tree/call')(tree);
+tree.URL = require('./tree/url')(tree);
+tree.Import = require('./tree/import')(tree);
+tree.mixin = {
+    Call: require('./tree/mixin-call')(tree),
+    Definition: require('./tree/mixin-definition')(tree)
+};
+tree.Comment = require('./tree/comment')(tree);
+tree.Anonymous = require('./tree/anonymous')(tree);
+tree.Value = require('./tree/value')(tree);
+tree.JavaScript = require('./tree/javascript')(tree);
+tree.Assignment = require('./tree/assignment')(tree);
+tree.Condition = require('./tree/condition')(tree);
+tree.Paren = require('./tree/paren')(tree);
+tree.Media = require('./tree/media')(tree);
+tree.UnicodeDescriptor = require('./tree/unicode-descriptor')(tree);
+tree.Negative = require('./tree/negative')(tree);
+tree.Extend = require('./tree/extend')(tree);
+tree.RulesetCall = require('./tree/ruleset-call')(tree);    
+
+return tree;
+
+};
\ No newline at end of file
diff --git a/lib/less/tree/alpha.js b/lib/less/tree/alpha.js
index e827fd0..eb247ad 100644
--- a/lib/less/tree/alpha.js
+++ b/lib/less/tree/alpha.js
@@ -1,15 +1,15 @@
-(function (tree) {
+module.exports = function (tree) {
 
-tree.Alpha = function (val) {
+var Alpha = function (val) {
     this.value = val;
 };
-tree.Alpha.prototype = {
+Alpha.prototype = {
     type: "Alpha",
     accept: function (visitor) {
         this.value = visitor.visit(this.value);
     },
     eval: function (env) {
-        if (this.value.eval) { return new tree.Alpha(this.value.eval(env)); }
+        if (this.value.eval) { return new Alpha(this.value.eval(env)); }
         return this;
     },
     genCSS: function (env, output) {
@@ -25,5 +25,5 @@ tree.Alpha.prototype = {
     },
     toCSS: tree.toCSS
 };
-
-})(require('../tree'));
+return Alpha;
+};
diff --git a/lib/less/tree/anonymous.js b/lib/less/tree/anonymous.js
index 3cfae77..e6be3f0 100644
--- a/lib/less/tree/anonymous.js
+++ b/lib/less/tree/anonymous.js
@@ -1,15 +1,15 @@
-(function (tree) {
+module.exports = function (tree) {
 
-tree.Anonymous = function (string, index, currentFileInfo, mapLines) {
+var Anonymous = function (string, index, currentFileInfo, mapLines) {
     this.value = string.value || string;
     this.index = index;
     this.mapLines = mapLines;
     this.currentFileInfo = currentFileInfo;
 };
-tree.Anonymous.prototype = {
+Anonymous.prototype = {
     type: "Anonymous",
     eval: function () { 
-        return new tree.Anonymous(this.value, this.index, this.currentFileInfo, this.mapLines);
+        return new Anonymous(this.value, this.index, this.currentFileInfo, this.mapLines);
     },
     compare: function (x) {
         if (!x.toCSS) {
@@ -30,5 +30,5 @@ tree.Anonymous.prototype = {
     },
     toCSS: tree.toCSS
 };
-
-})(require('../tree'));
+return Anonymous;
+};
diff --git a/lib/less/tree/assignment.js b/lib/less/tree/assignment.js
index 61d22fc..afe6293 100644
--- a/lib/less/tree/assignment.js
+++ b/lib/less/tree/assignment.js
@@ -1,17 +1,17 @@
-(function (tree) {
+module.exports = function (tree) {
 
-tree.Assignment = function (key, val) {
+var Assignment = function (key, val) {
     this.key = key;
     this.value = val;
 };
-tree.Assignment.prototype = {
+Assignment.prototype = {
     type: "Assignment",
     accept: function (visitor) {
         this.value = visitor.visit(this.value);
     },
     eval: function (env) {
         if (this.value.eval) {
-            return new(tree.Assignment)(this.key, this.value.eval(env));
+            return new(Assignment)(this.key, this.value.eval(env));
         }
         return this;
     },
@@ -25,5 +25,5 @@ tree.Assignment.prototype = {
     },
     toCSS: tree.toCSS
 };
-
-})(require('../tree'));
+return Assignment;
+};
diff --git a/lib/less/tree/attribute.js b/lib/less/tree/attribute.js
new file mode 100644
index 0000000..4103bfc
--- /dev/null
+++ b/lib/less/tree/attribute.js
@@ -0,0 +1,29 @@
+module.exports = function (tree) {
+
+var Attribute = function (key, op, value) {
+    this.key = key;
+    this.op = op;
+    this.value = value;
+};
+Attribute.prototype = {
+    type: "Attribute",
+    eval: function (env) {
+        return new(Attribute)(this.key.eval ? this.key.eval(env) : this.key,
+            this.op, (this.value && this.value.eval) ? this.value.eval(env) : this.value);
+    },
+    genCSS: function (env, output) {
+        output.add(this.toCSS(env));
+    },
+    toCSS: function (env) {
+        var value = this.key.toCSS ? this.key.toCSS(env) : this.key;
+
+        if (this.op) {
+            value += this.op;
+            value += (this.value.toCSS ? this.value.toCSS(env) : this.value);
+        }
+
+        return '[' + value + ']';
+    }
+};
+return Attribute;
+};
diff --git a/lib/less/tree/call.js b/lib/less/tree/call.js
index aa6acb9..e4a5101 100644
--- a/lib/less/tree/call.js
+++ b/lib/less/tree/call.js
@@ -1,15 +1,15 @@
-(function (tree) {
+module.exports = function (tree) {
 
 //
 // A function call node.
 //
-tree.Call = function (name, args, index, currentFileInfo) {
+var Call = function (name, args, index, currentFileInfo) {
     this.name = name;
     this.args = args;
     this.index = index;
     this.currentFileInfo = currentFileInfo;
 };
-tree.Call.prototype = {
+Call.prototype = {
     type: "Call",
     accept: function (visitor) {
         if (this.args) {
@@ -49,7 +49,7 @@ tree.Call.prototype = {
             }
         }
 
-        return new tree.Call(this.name, args, this.index, this.currentFileInfo);
+        return new Call(this.name, args, this.index, this.currentFileInfo);
     },
 
     genCSS: function (env, output) {
@@ -67,5 +67,5 @@ tree.Call.prototype = {
 
     toCSS: tree.toCSS
 };
-
-})(require('../tree'));
+return Call;
+};
diff --git a/lib/less/tree/color.js b/lib/less/tree/color.js
index 3d841b6..c902a13 100644
--- a/lib/less/tree/color.js
+++ b/lib/less/tree/color.js
@@ -1,8 +1,8 @@
-(function (tree) {
+module.exports = function (tree) {
 //
 // RGB Colors - #ff0014, #eee
 //
-tree.Color = function (rgb, a) {
+var Color = function (rgb, a) {
     //
     // The end goal here, is to parse the arguments
     // into an integer triplet, such as `128, 255, 0`
@@ -23,7 +23,7 @@ tree.Color = function (rgb, a) {
     this.alpha = typeof(a) === 'number' ? a : 1;
 };
 
-tree.Color.prototype = {
+Color.prototype = {
     type: "Color",
     eval: function () { return this; },
     luma: function () { return (0.2126 * this.rgb[0] / 255) + (0.7152 * this.rgb[1] / 255) + (0.0722 * this.rgb[2] / 255); },
@@ -79,7 +79,7 @@ tree.Color.prototype = {
         for (var c = 0; c < 3; c++) {
             rgb[c] = tree.operate(env, op, this.rgb[c], other.rgb[c]);
         }
-        return new(tree.Color)(rgb, alpha);
+        return new(Color)(rgb, alpha);
     },
 
     toRGB: function () {
@@ -153,13 +153,13 @@ tree.Color.prototype = {
     }
 };
 
-tree.Color.fromKeyword = function(keyword) {
+Color.fromKeyword = function(keyword) {
     var c, key = keyword.toLowerCase();
     if (tree.colors.hasOwnProperty(key)) {
-        c = new(tree.Color)(tree.colors[key].slice(1));
+        c = new(Color)(tree.colors[key].slice(1));
     }
     else if (key === "transparent") {
-        c = new(tree.Color)([0, 0, 0], 0); 
+        c = new(Color)([0, 0, 0], 0); 
     }
     
     if (c) {
@@ -178,5 +178,5 @@ function toHex(v) {
 function clamp(v, max) {
     return Math.min(Math.max(v, 0), max); 
 }
-
-})(require('../tree'));
+return Color;
+};
diff --git a/lib/less/tree/combinator.js b/lib/less/tree/combinator.js
new file mode 100644
index 0000000..0fd4dd8
--- /dev/null
+++ b/lib/less/tree/combinator.js
@@ -0,0 +1,40 @@
+module.exports = function (tree) {
+
+var Combinator = function (value) {
+    if (value === ' ') {
+        this.value = ' ';
+    } else {
+        this.value = value ? value.trim() : "";
+    }
+};
+Combinator.prototype = {
+    type: "Combinator",
+    _outputMap: {
+        ''  : '',
+        ' ' : ' ',
+        ':' : ' :',
+        '+' : ' + ',
+        '~' : ' ~ ',
+        '>' : ' > ',
+        '|' : '|',
+        '^' : ' ^ ',
+        '^^' : ' ^^ '
+    },
+    _outputMapCompressed: {
+        ''  : '',
+        ' ' : ' ',
+        ':' : ' :',
+        '+' : '+',
+        '~' : '~',
+        '>' : '>',
+        '|' : '|',
+        '^' : '^',
+        '^^' : '^^'
+    },
+    genCSS: function (env, output) {
+        output.add((env.compress ? this._outputMapCompressed : this._outputMap)[this.value]);
+    },
+    toCSS: tree.toCSS
+};
+return Combinator;
+};
diff --git a/lib/less/tree/comment.js b/lib/less/tree/comment.js
index c39606e..05bc220 100644
--- a/lib/less/tree/comment.js
+++ b/lib/less/tree/comment.js
@@ -1,11 +1,11 @@
-(function (tree) {
+module.exports = function (tree) {
 
-tree.Comment = function (value, silent, index, currentFileInfo) {
+var Comment = function (value, silent, index, currentFileInfo) {
     this.value = value;
     this.silent = !!silent;
     this.currentFileInfo = currentFileInfo;
 };
-tree.Comment.prototype = {
+Comment.prototype = {
     type: "Comment",
     genCSS: function (env, output) {
         if (this.debugInfo) {
@@ -24,5 +24,5 @@ tree.Comment.prototype = {
         this.isReferenced = true;
     }
 };
-
-})(require('../tree'));
+return Comment;
+};
diff --git a/lib/less/tree/condition.js b/lib/less/tree/condition.js
index 56d221e..fdc7981 100644
--- a/lib/less/tree/condition.js
+++ b/lib/less/tree/condition.js
@@ -1,13 +1,13 @@
-(function (tree) {
+module.exports = function (tree) {
 
-tree.Condition = function (op, l, r, i, negate) {
+var Condition = function (op, l, r, i, negate) {
     this.op = op.trim();
     this.lvalue = l;
     this.rvalue = r;
     this.index = i;
     this.negate = negate;
 };
-tree.Condition.prototype = {
+Condition.prototype = {
     type: "Condition",
     accept: function (visitor) {
         this.lvalue = visitor.visit(this.lvalue);
@@ -45,5 +45,5 @@ tree.Condition.prototype = {
         return this.negate ? !result : result;
     }
 };
-
-})(require('../tree'));
+return Condition;
+};
diff --git a/lib/less/tree/detached-ruleset.js b/lib/less/tree/detached-ruleset.js
index 0a5512a..a58029c 100644
--- a/lib/less/tree/detached-ruleset.js
+++ b/lib/less/tree/detached-ruleset.js
@@ -1,20 +1,21 @@
-(function (tree) {
+module.exports = function (tree) {
 
-tree.DetachedRuleset = function (ruleset, frames) {
+var DetachedRuleset = function (ruleset, frames) {
     this.ruleset = ruleset;
     this.frames = frames;
 };
-tree.DetachedRuleset.prototype = {
+DetachedRuleset.prototype = {
     type: "DetachedRuleset",
     accept: function (visitor) {
         this.ruleset = visitor.visit(this.ruleset);
     },
     eval: function (env) {
         var frames = this.frames || env.frames.slice(0);
-        return new tree.DetachedRuleset(this.ruleset, frames);
+        return new DetachedRuleset(this.ruleset, frames);
     },
     callEval: function (env) {
         return this.ruleset.eval(this.frames ? new(tree.evalEnv)(env, this.frames.concat(env.frames)) : env);
     }
 };
-})(require('../tree'));
+return DetachedRuleset;
+};
diff --git a/lib/less/tree/dimension.js b/lib/less/tree/dimension.js
index aecec13..b74becc 100644
--- a/lib/less/tree/dimension.js
+++ b/lib/less/tree/dimension.js
@@ -1,15 +1,15 @@
-(function (tree) {
+module.exports = function (tree, unitConversions) {
 
 //
 // A number with a unit
 //
-tree.Dimension = function (value, unit) {
+var Dimension = function (value, unit) {
     this.value = parseFloat(value);
     this.unit = (unit && unit instanceof tree.Unit) ? unit :
       new(tree.Unit)(unit ? [unit] : undefined);
 };
 
-tree.Dimension.prototype = {
+Dimension.prototype = {
     type: "Dimension",
     accept: function (visitor) {
         this.unit = visitor.visit(this.unit);
@@ -84,11 +84,11 @@ tree.Dimension.prototype = {
             unit.denominator = unit.denominator.concat(other.unit.numerator).sort();
             unit.cancel();
         }
-        return new(tree.Dimension)(value, unit);
+        return new(Dimension)(value, unit);
     },
 
     compare: function (other) {
-        if (other instanceof tree.Dimension) {
+        if (other instanceof Dimension) {
             var a, b,
                 aValue, bValue;
             
@@ -126,8 +126,8 @@ tree.Dimension.prototype = {
             i, groupName, group, targetUnit, derivedConversions = {}, applyUnit;
 
         if (typeof conversions === 'string') {
-            for(i in tree.UnitConversions) {
-                if (tree.UnitConversions[i].hasOwnProperty(conversions)) {
+            for(i in unitConversions) {
+                if (unitConversions[i].hasOwnProperty(conversions)) {
                     derivedConversions = {};
                     derivedConversions[i] = conversions;
                 }
@@ -152,7 +152,7 @@ tree.Dimension.prototype = {
         for (groupName in conversions) {
             if (conversions.hasOwnProperty(groupName)) {
                 targetUnit = conversions[groupName];
-                group = tree.UnitConversions[groupName];
+                group = unitConversions[groupName];
 
                 unit.map(applyUnit);
             }
@@ -160,165 +160,8 @@ tree.Dimension.prototype = {
 
         unit.cancel();
 
-        return new(tree.Dimension)(value, unit);
+        return new(Dimension)(value, unit);
     }
 };
-
-// http://www.w3.org/TR/css3-values/#absolute-lengths
-tree.UnitConversions = {
-    length: {
-         'm': 1,
-        'cm': 0.01,
-        'mm': 0.001,
-        'in': 0.0254,
-        'px': 0.0254 / 96,
-        'pt': 0.0254 / 72,
-        'pc': 0.0254 / 72 * 12
-    },
-    duration: {
-        's': 1,
-        'ms': 0.001
-    },
-    angle: {
-        'rad': 1/(2*Math.PI),
-        'deg': 1/360,
-        'grad': 1/400,
-        'turn': 1
-    }
-};
-
-tree.Unit = function (numerator, denominator, backupUnit) {
-    this.numerator = numerator ? numerator.slice(0).sort() : [];
-    this.denominator = denominator ? denominator.slice(0).sort() : [];
-    this.backupUnit = backupUnit;
-};
-
-tree.Unit.prototype = {
-    type: "Unit",
-    clone: function () {
-        return new tree.Unit(this.numerator.slice(0), this.denominator.slice(0), this.backupUnit);
-    },
-    genCSS: function (env, output) {
-        if (this.numerator.length >= 1) {
-            output.add(this.numerator[0]);
-        } else
-        if (this.denominator.length >= 1) {
-            output.add(this.denominator[0]);
-        } else
-        if ((!env || !env.strictUnits) && this.backupUnit) {
-            output.add(this.backupUnit);
-        }
-    },
-    toCSS: tree.toCSS,
-
-    toString: function () {
-      var i, returnStr = this.numerator.join("*");
-      for (i = 0; i < this.denominator.length; i++) {
-          returnStr += "/" + this.denominator[i];
-      }
-      return returnStr;
-    },
-
-    compare: function (other) {
-        return this.is(other.toString()) ? 0 : -1;
-    },
-
-    is: function (unitString) {
-        return this.toString() === unitString;
-    },
-
-    isLength: function () {
-        return Boolean(this.toCSS().match(/px|em|%|in|cm|mm|pc|pt|ex/));
-    },
-
-    isEmpty: function () {
-        return this.numerator.length === 0 && this.denominator.length === 0;
-    },
-
-    isSingular: function() {
-        return this.numerator.length <= 1 && this.denominator.length === 0;
-    },
-
-    map: function(callback) {
-        var i;
-
-        for (i = 0; i < this.numerator.length; i++) {
-            this.numerator[i] = callback(this.numerator[i], false);
-        }
-
-        for (i = 0; i < this.denominator.length; i++) {
-            this.denominator[i] = callback(this.denominator[i], true);
-        }
-    },
-
-    usedUnits: function() {
-        var group, result = {}, mapUnit;
-
-        mapUnit = function (atomicUnit) {
-        /*jshint loopfunc:true */
-            if (group.hasOwnProperty(atomicUnit) && !result[groupName]) {
-                result[groupName] = atomicUnit;
-            }
-
-            return atomicUnit;
-        };
-
-        for (var groupName in tree.UnitConversions) {
-            if (tree.UnitConversions.hasOwnProperty(groupName)) {
-                group = tree.UnitConversions[groupName];
-
-                this.map(mapUnit);
-            }
-        }
-
-        return result;
-    },
-
-    cancel: function () {
-        var counter = {}, atomicUnit, i, backup;
-
-        for (i = 0; i < this.numerator.length; i++) {
-            atomicUnit = this.numerator[i];
-            if (!backup) {
-                backup = atomicUnit;
-            }
-            counter[atomicUnit] = (counter[atomicUnit] || 0) + 1;
-        }
-
-        for (i = 0; i < this.denominator.length; i++) {
-            atomicUnit = this.denominator[i];
-            if (!backup) {
-                backup = atomicUnit;
-            }
-            counter[atomicUnit] = (counter[atomicUnit] || 0) - 1;
-        }
-
-        this.numerator = [];
-        this.denominator = [];
-
-        for (atomicUnit in counter) {
-            if (counter.hasOwnProperty(atomicUnit)) {
-                var count = counter[atomicUnit];
-
-                if (count > 0) {
-                    for (i = 0; i < count; i++) {
-                        this.numerator.push(atomicUnit);
-                    }
-                } else if (count < 0) {
-                    for (i = 0; i < -count; i++) {
-                        this.denominator.push(atomicUnit);
-                    }
-                }
-            }
-        }
-
-        if (this.numerator.length === 0 && this.denominator.length === 0 && backup) {
-            this.backupUnit = backup;
-        }
-
-        this.numerator.sort();
-        this.denominator.sort();
-    }
+return Dimension;
 };
-
-})(require('../tree'));
diff --git a/lib/less/tree/directive.js b/lib/less/tree/directive.js
index b59a16b..1bb9b6c 100644
--- a/lib/less/tree/directive.js
+++ b/lib/less/tree/directive.js
@@ -1,6 +1,6 @@
-(function (tree) {
+module.exports = function (tree) {
 
-tree.Directive = function (name, value, rules, index, currentFileInfo, debugInfo) {
+var Directive = function (name, value, rules, index, currentFileInfo, debugInfo) {
     this.name  = name;
     this.value = value;
     if (rules) {
@@ -12,7 +12,7 @@ tree.Directive = function (name, value, rules, index, currentFileInfo, debugInfo
     this.debugInfo = debugInfo;
 };
 
-tree.Directive.prototype = {
+Directive.prototype = {
     type: "Directive",
     accept: function (visitor) {
         var value = this.value, rules = this.rules;
@@ -46,7 +46,7 @@ tree.Directive.prototype = {
             rules = rules.eval(env);
             rules.root = true;
         }
-        return new(tree.Directive)(this.name, value, rules,
+        return new(Directive)(this.name, value, rules,
             this.index, this.currentFileInfo, this.debugInfo);
     },
     variable: function (name) { if (this.rules) return tree.Ruleset.prototype.variable.call(this.rules, name); },
@@ -65,5 +65,5 @@ tree.Directive.prototype = {
         }
     }
 };
-
-})(require('../tree'));
+return Directive;
+};
diff --git a/lib/less/tree/element.js b/lib/less/tree/element.js
index 3869f6c..925b4b9 100644
--- a/lib/less/tree/element.js
+++ b/lib/less/tree/element.js
@@ -1,6 +1,6 @@
-(function (tree) {
+module.exports = function (tree) {
 
-tree.Element = function (combinator, value, index, currentFileInfo) {
+var Element = function (combinator, value, index, currentFileInfo) {
     this.combinator = combinator instanceof tree.Combinator ?
                       combinator : new(tree.Combinator)(combinator);
 
@@ -14,7 +14,7 @@ tree.Element = function (combinator, value, index, currentFileInfo) {
     this.index = index;
     this.currentFileInfo = currentFileInfo;
 };
-tree.Element.prototype = {
+Element.prototype = {
     type: "Element",
     accept: function (visitor) {
         var value = this.value;
@@ -24,7 +24,7 @@ tree.Element.prototype = {
         }
     },
     eval: function (env) {
-        return new(tree.Element)(this.combinator,
+        return new(Element)(this.combinator,
                                  this.value.eval ? this.value.eval(env) : this.value,
                                  this.index,
                                  this.currentFileInfo);
@@ -41,68 +41,5 @@ tree.Element.prototype = {
         }
     }
 };
-
-tree.Attribute = function (key, op, value) {
-    this.key = key;
-    this.op = op;
-    this.value = value;
-};
-tree.Attribute.prototype = {
-    type: "Attribute",
-    eval: function (env) {
-        return new(tree.Attribute)(this.key.eval ? this.key.eval(env) : this.key,
-            this.op, (this.value && this.value.eval) ? this.value.eval(env) : this.value);
-    },
-    genCSS: function (env, output) {
-        output.add(this.toCSS(env));
-    },
-    toCSS: function (env) {
-        var value = this.key.toCSS ? this.key.toCSS(env) : this.key;
-
-        if (this.op) {
-            value += this.op;
-            value += (this.value.toCSS ? this.value.toCSS(env) : this.value);
-        }
-
-        return '[' + value + ']';
-    }
+return Element;
 };
-
-tree.Combinator = function (value) {
-    if (value === ' ') {
-        this.value = ' ';
-    } else {
-        this.value = value ? value.trim() : "";
-    }
-};
-tree.Combinator.prototype = {
-    type: "Combinator",
-    _outputMap: {
-        ''  : '',
-        ' ' : ' ',
-        ':' : ' :',
-        '+' : ' + ',
-        '~' : ' ~ ',
-        '>' : ' > ',
-        '|' : '|',
-        '^' : ' ^ ',
-        '^^' : ' ^^ '
-    },
-    _outputMapCompressed: {
-        ''  : '',
-        ' ' : ' ',
-        ':' : ' :',
-        '+' : '+',
-        '~' : '~',
-        '>' : '>',
-        '|' : '|',
-        '^' : '^',
-        '^^' : '^^'
-    },
-    genCSS: function (env, output) {
-        output.add((env.compress ? this._outputMapCompressed : this._outputMap)[this.value]);
-    },
-    toCSS: tree.toCSS
-};
-
-})(require('../tree'));
diff --git a/lib/less/tree/expression.js b/lib/less/tree/expression.js
index a3d1e4a..4614e15 100644
--- a/lib/less/tree/expression.js
+++ b/lib/less/tree/expression.js
@@ -1,7 +1,7 @@
-(function (tree) {
+module.exports = function (tree) {
 
-tree.Expression = function (value) { this.value = value; };
-tree.Expression.prototype = {
+var Expression = function (value) { this.value = value; };
+Expression.prototype = {
     type: "Expression",
     accept: function (visitor) {
         if (this.value) {
@@ -16,7 +16,7 @@ tree.Expression.prototype = {
             env.inParenthesis();
         }
         if (this.value.length > 1) {
-            returnValue = new(tree.Expression)(this.value.map(function (e) {
+            returnValue = new(Expression)(this.value.map(function (e) {
                 return e.eval(env);
             }));
         } else if (this.value.length === 1) {
@@ -50,5 +50,5 @@ tree.Expression.prototype = {
         });
     }
 };
-
-})(require('../tree'));
+return Expression;
+};
diff --git a/lib/less/tree/extend.js b/lib/less/tree/extend.js
index ef9d88e..746bdeb 100644
--- a/lib/less/tree/extend.js
+++ b/lib/less/tree/extend.js
@@ -1,10 +1,10 @@
-(function (tree) {
+module.exports = function (tree) {
 
-tree.Extend = function Extend(selector, option, index) {
+var Extend = function Extend(selector, option, index) {
     this.selector = selector;
     this.option = option;
     this.index = index;
-    this.object_id = tree.Extend.next_id++;
+    this.object_id = Extend.next_id++;
     this.parent_ids = [this.object_id];
 
     switch(option) {
@@ -18,18 +18,18 @@ tree.Extend = function Extend(selector, option, index) {
         break;
     }
 };
-tree.Extend.next_id = 0;
+Extend.next_id = 0;
 
-tree.Extend.prototype = {
+Extend.prototype = {
     type: "Extend",
     accept: function (visitor) {
         this.selector = visitor.visit(this.selector);
     },
     eval: function (env) {
-        return new(tree.Extend)(this.selector.eval(env), this.option, this.index);
+        return new(Extend)(this.selector.eval(env), this.option, this.index);
     },
     clone: function (env) {
-        return new(tree.Extend)(this.selector, this.option, this.index);
+        return new(Extend)(this.selector, this.option, this.index);
     },
     findSelfSelectors: function (selectors) {
         var selfElements = [],
@@ -49,5 +49,5 @@ tree.Extend.prototype = {
         this.selfSelectors = [{ elements: selfElements }];
     }
 };
-
-})(require('../tree'));
+return Extend;
+};
diff --git a/lib/less/tree/import.js b/lib/less/tree/import.js
index 910fc11..4f586ad 100644
--- a/lib/less/tree/import.js
+++ b/lib/less/tree/import.js
@@ -1,4 +1,4 @@
-(function (tree) {
+module.exports = function (tree) {
 //
 // CSS @import node
 //
@@ -11,7 +11,7 @@
 // `import,push`, we also pass it a callback, which it'll call once
 // the file has been fetched, and parsed.
 //
-tree.Import = function (path, features, options, index, currentFileInfo) {
+var Import = function (path, features, options, index, currentFileInfo) {
     this.options = options;
     this.index = index;
     this.path = path;
@@ -37,7 +37,7 @@ tree.Import = function (path, features, options, index, currentFileInfo) {
 // we end up with a flat structure, which can easily be imported in the parent
 // ruleset.
 //
-tree.Import.prototype = {
+Import.prototype = {
     type: "Import",
     accept: function (visitor) {
         if (this.features) {
@@ -70,7 +70,7 @@ tree.Import.prototype = {
         return null;
     },
     evalForImport: function (env) {
-        return new(tree.Import)(this.path.eval(env), this.features, this.options, this.index, this.currentFileInfo);
+        return new(Import)(this.path.eval(env), this.features, this.options, this.index, this.currentFileInfo);
     },
     evalPath: function (env) {
         var path = this.path.eval(env);
@@ -99,7 +99,7 @@ tree.Import.prototype = {
             var contents = new(tree.Anonymous)(this.root, 0, {filename: this.importedFilename}, true);
             return this.features ? new(tree.Media)([contents], this.features.value) : [contents];
         } else if (this.css) {
-            var newImport = new(tree.Import)(this.evalPath(env), features, this.options, this.index);
+            var newImport = new(Import)(this.evalPath(env), features, this.options, this.index);
             if (!newImport.css && this.error) {
                 throw this.error;
             }
@@ -113,5 +113,5 @@ tree.Import.prototype = {
         }
     }
 };
-
-})(require('../tree'));
+return Import;
+};
diff --git a/lib/less/tree/javascript.js b/lib/less/tree/javascript.js
index 30a8559..fdca7bf 100644
--- a/lib/less/tree/javascript.js
+++ b/lib/less/tree/javascript.js
@@ -1,11 +1,11 @@
-(function (tree) {
+module.exports = function (tree) {
 
-tree.JavaScript = function (string, index, escaped) {
+var JavaScript = function (string, index, escaped) {
     this.escaped = escaped;
     this.expression = string;
     this.index = index;
 };
-tree.JavaScript.prototype = {
+JavaScript.prototype = {
     type: "JavaScript",
     eval: function (env) {
         var result,
@@ -53,6 +53,5 @@ tree.JavaScript.prototype = {
         }
     }
 };
-
-})(require('../tree'));
-
+return JavaScript;
+};
diff --git a/lib/less/tree/keyword.js b/lib/less/tree/keyword.js
index 830594d..46f5648 100644
--- a/lib/less/tree/keyword.js
+++ b/lib/less/tree/keyword.js
@@ -1,7 +1,7 @@
-(function (tree) {
+module.exports = function (tree) {
 
-tree.Keyword = function (value) { this.value = value; };
-tree.Keyword.prototype = {
+var Keyword = function (value) { this.value = value; };
+Keyword.prototype = {
     type: "Keyword",
     eval: function () { return this; },
     genCSS: function (env, output) {
@@ -10,7 +10,7 @@ tree.Keyword.prototype = {
     },
     toCSS: tree.toCSS,
     compare: function (other) {
-        if (other instanceof tree.Keyword) {
+        if (other instanceof Keyword) {
             return other.value === this.value ? 0 : 1;
         } else {
             return -1;
@@ -18,7 +18,10 @@ tree.Keyword.prototype = {
     }
 };
 
-tree.True = new(tree.Keyword)('true');
-tree.False = new(tree.Keyword)('false');
+//TODO move?
+tree.True = new(Keyword)('true');
+tree.False = new(Keyword)('false');
 
-})(require('../tree'));
+return Keyword;
+
+};
diff --git a/lib/less/tree/media.js b/lib/less/tree/media.js
index 095e43e..34c07bb 100644
--- a/lib/less/tree/media.js
+++ b/lib/less/tree/media.js
@@ -1,6 +1,6 @@
-(function (tree) {
+module.exports = function (tree) {
 
-tree.Media = function (value, features, index, currentFileInfo) {
+var Media = function (value, features, index, currentFileInfo) {
     this.index = index;
     this.currentFileInfo = currentFileInfo;
 
@@ -10,7 +10,7 @@ tree.Media = function (value, features, index, currentFileInfo) {
     this.rules = [new(tree.Ruleset)(selectors, value)];
     this.rules[0].allowImports = true;
 };
-tree.Media.prototype = {
+Media.prototype = {
     type: "Media",
     accept: function (visitor) {
         if (this.features) {
@@ -32,7 +32,7 @@ tree.Media.prototype = {
             env.mediaPath = [];
         }
         
-        var media = new(tree.Media)(null, [], this.index, this.currentFileInfo);
+        var media = new(Media)(null, [], this.index, this.currentFileInfo);
         if(this.debugInfo) {
             this.rules[0].debugInfo = this.debugInfo;
             media.debugInfo = this.debugInfo;
@@ -153,5 +153,5 @@ tree.Media.prototype = {
       this.rules = [new(tree.Ruleset)(selectors.slice(0), [this.rules[0]])];
     }
 };
-
-})(require('../tree'));
+return Media;
+};
diff --git a/lib/less/tree/mixin-call.js b/lib/less/tree/mixin-call.js
new file mode 100644
index 0000000..606600a
--- /dev/null
+++ b/lib/less/tree/mixin-call.js
@@ -0,0 +1,152 @@
+module.exports = function (tree) {
+
+var Call = function (elements, args, index, currentFileInfo, important) {
+    this.selector = new(tree.Selector)(elements);
+    this.arguments = (args && args.length) ? args : null;
+    this.index = index;
+    this.currentFileInfo = currentFileInfo;
+    this.important = important;
+};
+Call.prototype = {
+    type: "MixinCall",
+    accept: function (visitor) {
+        if (this.selector) {
+            this.selector = visitor.visit(this.selector);
+        }
+        if (this.arguments) {
+            this.arguments = visitor.visitArray(this.arguments);
+        }
+    },
+    eval: function (env) {
+        var mixins, mixin, args, rules = [], match = false, i, m, f, isRecursive, isOneFound, rule,
+            candidates = [], candidate, conditionResult = [], defaultFunc = tree.defaultFunc,
+            defaultResult, defNone = 0, defTrue = 1, defFalse = 2, count; 
+
+        args = this.arguments && this.arguments.map(function (a) {
+            return { name: a.name, value: a.value.eval(env) };
+        });
+
+        for (i = 0; i < env.frames.length; i++) {
+            if ((mixins = env.frames[i].find(this.selector)).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];
+                    isRecursive = false;
+                    for(f = 0; f < env.frames.length; f++) {
+                        if ((!(mixin instanceof tree.mixin.Definition)) && mixin === (env.frames[f].originalRuleset || env.frames[f])) {
+                            isRecursive = true;
+                            break;
+                        }
+                    }
+                    if (isRecursive) {
+                        continue;
+                    }
+                    
+                    if (mixin.matchArgs(args, env)) {  
+                        candidate = {mixin: mixin, group: defNone};
+                        
+                        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 {
+                            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 tree.mixin.Definition)) {
+                                mixin = new tree.mixin.Definition("", [], mixin.rules, null, false);
+                                mixin.originalRuleset = mixins[m].originalRuleset || mixins[m];
+                            }
+                            Array.prototype.push.apply(
+                                  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 };
+        } else {
+            throw { type:    'Name',
+                    message: this.selector.toCSS().trim() + " is undefined",
+                    index:   this.index, filename: this.currentFileInfo.filename };
+        }
+    },
+    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(', ') : "") + ")";
+    }
+};
+return Call;
+};
diff --git a/lib/less/tree/mixin-definition.js b/lib/less/tree/mixin-definition.js
new file mode 100644
index 0000000..b661c31
--- /dev/null
+++ b/lib/less/tree/mixin-definition.js
@@ -0,0 +1,165 @@
+module.exports = function (tree) {
+
+var Definition = function (name, params, rules, condition, variadic, frames) {
+    this.name = name;
+    this.selectors = [new(tree.Selector)([new(tree.Element)(null, name, this.index, this.currentFileInfo)])];
+    this.params = params;
+    this.condition = condition;
+    this.variadic = variadic;
+    this.arity = params.length;
+    this.rules = rules;
+    this._lookups = {};
+    this.required = params.reduce(function (count, p) {
+        if (!p.name || (p.name && !p.value)) { return count + 1; }
+        else                                 { return count; }
+    }, 0);
+    this.parent = tree.Ruleset.prototype;
+    this.frames = frames;
+};
+Definition.prototype = {
+    type: "MixinDefinition",
+    accept: function (visitor) {
+        if (this.params && this.params.length) {
+            this.params = visitor.visitArray(this.params);
+        }
+        this.rules = visitor.visitArray(this.rules);
+        if (this.condition) {
+            this.condition = visitor.visit(this.condition);
+        }
+    },
+    variable:  function (name) { return this.parent.variable.call(this, name); },
+    variables: function ()     { return this.parent.variables.call(this); },
+    find:      function ()     { return this.parent.find.apply(this, arguments); },
+    rulesets:  function ()     { return this.parent.rulesets.apply(this); },
+
+    evalParams: function (env, mixinEnv, args, evaldArguments) {
+        /*jshint boss:true */
+        var frame = new(tree.Ruleset)(null, null),
+            varargs, arg,
+            params = this.params.slice(0),
+            i, j, val, name, isNamedFound, argIndex, argsLength = 0;
+
+        mixinEnv = new tree.evalEnv(mixinEnv, [frame].concat(mixinEnv.frames));
+
+        if (args) {
+            args = args.slice(0);
+            argsLength = args.length;
+
+            for(i = 0; i < argsLength; i++) {
+                arg = args[i];
+                if (name = (arg && arg.name)) {
+                    isNamedFound = false;
+                    for(j = 0; j < params.length; j++) {
+                        if (!evaldArguments[j] && name === params[j].name) {
+                            evaldArguments[j] = arg.value.eval(env);
+                            frame.prependRule(new(tree.Rule)(name, arg.value.eval(env)));
+                            isNamedFound = true;
+                            break;
+                        }
+                    }
+                    if (isNamedFound) {
+                        args.splice(i, 1);
+                        i--;
+                        continue;
+                    } else {
+                        throw { type: 'Runtime', message: "Named argument for " + this.name +
+                            ' ' + args[i].name + ' not found' };
+                    }
+                }
+            }
+        }
+        argIndex = 0;
+        for (i = 0; i < params.length; i++) {
+            if (evaldArguments[i]) { continue; }
+
+            arg = args && args[argIndex];
+
+            if (name = params[i].name) {
+                if (params[i].variadic) {
+                    varargs = [];
+                    for (j = argIndex; j < argsLength; j++) {
+                        varargs.push(args[j].value.eval(env));
+                    }
+                    frame.prependRule(new(tree.Rule)(name, new(tree.Expression)(varargs).eval(env)));
+                } else {
+                    val = arg && arg.value;
+                    if (val) {
+                        val = val.eval(env);
+                    } else if (params[i].value) {
+                        val = params[i].value.eval(mixinEnv);
+                        frame.resetCache();
+                    } else {
+                        throw { type: 'Runtime', message: "wrong number of arguments for " + this.name +
+                            ' (' + argsLength + ' for ' + this.arity + ')' };
+                    }
+                    
+                    frame.prependRule(new(tree.Rule)(name, val));
+                    evaldArguments[i] = val;
+                }
+            }
+
+            if (params[i].variadic && args) {
+                for (j = argIndex; j < argsLength; j++) {
+                    evaldArguments[j] = args[j].value.eval(env);
+                }
+            }
+            argIndex++;
+        }
+
+        return frame;
+    },
+    eval: function (env) {
+        return new tree.mixin.Definition(this.name, this.params, this.rules, this.condition, this.variadic, this.frames || env.frames.slice(0));
+    },
+    evalCall: function (env, args, important) {
+        var _arguments = [],
+            mixinFrames = this.frames ? this.frames.concat(env.frames) : env.frames,
+            frame = this.evalParams(env, new(tree.evalEnv)(env, mixinFrames), args, _arguments),
+            rules, ruleset;
+
+        frame.prependRule(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env)));
+
+        rules = this.rules.slice(0);
+
+        ruleset = new(tree.Ruleset)(null, rules);
+        ruleset.originalRuleset = this;
+        ruleset = ruleset.eval(new(tree.evalEnv)(env, [this, frame].concat(mixinFrames)));
+        if (important) {
+            ruleset = this.parent.makeImportant.apply(ruleset);
+        }
+        return ruleset;
+    },
+    matchCondition: function (args, env) {
+        if (this.condition && !this.condition.eval(
+            new(tree.evalEnv)(env,
+                [this.evalParams(env, new(tree.evalEnv)(env, this.frames.concat(env.frames)), args, [])] // the parameter variables
+                    .concat(this.frames) // the parent namespace/mixin frames
+                    .concat(env.frames)))) { // the current environment frames
+            return false;
+        }
+        return true;
+    },
+    matchArgs: function (args, env) {
+        var argsLength = (args && args.length) || 0, len;
+
+        if (! this.variadic) {
+            if (argsLength < this.required)                               { return false; }
+            if (argsLength > this.params.length)                          { return false; }
+        } else {
+            if (argsLength < (this.required - 1))                         { return false; }
+        }
+
+        len = Math.min(argsLength, this.arity);
+
+        for (var i = 0; i < len; i++) {
+            if (!this.params[i].name && !this.params[i].variadic) {
+                if (args[i].value.eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+};
+return Definition;
+};
diff --git a/lib/less/tree/mixin.js b/lib/less/tree/mixin.js
deleted file mode 100644
index 506561b..0000000
--- a/lib/less/tree/mixin.js
+++ /dev/null
@@ -1,315 +0,0 @@
-(function (tree) {
-
-tree.mixin = {};
-tree.mixin.Call = function (elements, args, index, currentFileInfo, important) {
-    this.selector = new(tree.Selector)(elements);
-    this.arguments = (args && args.length) ? args : null;
-    this.index = index;
-    this.currentFileInfo = currentFileInfo;
-    this.important = important;
-};
-tree.mixin.Call.prototype = {
-    type: "MixinCall",
-    accept: function (visitor) {
-        if (this.selector) {
-            this.selector = visitor.visit(this.selector);
-        }
-        if (this.arguments) {
-            this.arguments = visitor.visitArray(this.arguments);
-        }
-    },
-    eval: function (env) {
-        var mixins, mixin, args, rules = [], match = false, i, m, f, isRecursive, isOneFound, rule,
-            candidates = [], candidate, conditionResult = [], defaultFunc = tree.defaultFunc,
-            defaultResult, defNone = 0, defTrue = 1, defFalse = 2, count; 
-
-        args = this.arguments && this.arguments.map(function (a) {
-            return { name: a.name, value: a.value.eval(env) };
-        });
-
-        for (i = 0; i < env.frames.length; i++) {
-            if ((mixins = env.frames[i].find(this.selector)).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];
-                    isRecursive = false;
-                    for(f = 0; f < env.frames.length; f++) {
-                        if ((!(mixin instanceof tree.mixin.Definition)) && mixin === (env.frames[f].originalRuleset || env.frames[f])) {
-                            isRecursive = true;
-                            break;
-                        }
-                    }
-                    if (isRecursive) {
-                        continue;
-                    }
-                    
-                    if (mixin.matchArgs(args, env)) {  
-                        candidate = {mixin: mixin, group: defNone};
-                        
-                        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 {
-                            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 tree.mixin.Definition)) {
-                                mixin = new tree.mixin.Definition("", [], mixin.rules, null, false);
-                                mixin.originalRuleset = mixins[m].originalRuleset || mixins[m];
-                            }
-                            Array.prototype.push.apply(
-                                  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 };
-        } else {
-            throw { type:    'Name',
-                    message: this.selector.toCSS().trim() + " is undefined",
-                    index:   this.index, filename: this.currentFileInfo.filename };
-        }
-    },
-    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(', ') : "") + ")";
-    }
-};
-
-tree.mixin.Definition = function (name, params, rules, condition, variadic, frames) {
-    this.name = name;
-    this.selectors = [new(tree.Selector)([new(tree.Element)(null, name, this.index, this.currentFileInfo)])];
-    this.params = params;
-    this.condition = condition;
-    this.variadic = variadic;
-    this.arity = params.length;
-    this.rules = rules;
-    this._lookups = {};
-    this.required = params.reduce(function (count, p) {
-        if (!p.name || (p.name && !p.value)) { return count + 1; }
-        else                                 { return count; }
-    }, 0);
-    this.parent = tree.Ruleset.prototype;
-    this.frames = frames;
-};
-tree.mixin.Definition.prototype = {
-    type: "MixinDefinition",
-    accept: function (visitor) {
-        if (this.params && this.params.length) {
-            this.params = visitor.visitArray(this.params);
-        }
-        this.rules = visitor.visitArray(this.rules);
-        if (this.condition) {
-            this.condition = visitor.visit(this.condition);
-        }
-    },
-    variable:  function (name) { return this.parent.variable.call(this, name); },
-    variables: function ()     { return this.parent.variables.call(this); },
-    find:      function ()     { return this.parent.find.apply(this, arguments); },
-    rulesets:  function ()     { return this.parent.rulesets.apply(this); },
-
-    evalParams: function (env, mixinEnv, args, evaldArguments) {
-        /*jshint boss:true */
-        var frame = new(tree.Ruleset)(null, null),
-            varargs, arg,
-            params = this.params.slice(0),
-            i, j, val, name, isNamedFound, argIndex, argsLength = 0;
-
-        mixinEnv = new tree.evalEnv(mixinEnv, [frame].concat(mixinEnv.frames));
-
-        if (args) {
-            args = args.slice(0);
-            argsLength = args.length;
-
-            for(i = 0; i < argsLength; i++) {
-                arg = args[i];
-                if (name = (arg && arg.name)) {
-                    isNamedFound = false;
-                    for(j = 0; j < params.length; j++) {
-                        if (!evaldArguments[j] && name === params[j].name) {
-                            evaldArguments[j] = arg.value.eval(env);
-                            frame.prependRule(new(tree.Rule)(name, arg.value.eval(env)));
-                            isNamedFound = true;
-                            break;
-                        }
-                    }
-                    if (isNamedFound) {
-                        args.splice(i, 1);
-                        i--;
-                        continue;
-                    } else {
-                        throw { type: 'Runtime', message: "Named argument for " + this.name +
-                            ' ' + args[i].name + ' not found' };
-                    }
-                }
-            }
-        }
-        argIndex = 0;
-        for (i = 0; i < params.length; i++) {
-            if (evaldArguments[i]) { continue; }
-
-            arg = args && args[argIndex];
-
-            if (name = params[i].name) {
-                if (params[i].variadic) {
-                    varargs = [];
-                    for (j = argIndex; j < argsLength; j++) {
-                        varargs.push(args[j].value.eval(env));
-                    }
-                    frame.prependRule(new(tree.Rule)(name, new(tree.Expression)(varargs).eval(env)));
-                } else {
-                    val = arg && arg.value;
-                    if (val) {
-                        val = val.eval(env);
-                    } else if (params[i].value) {
-                        val = params[i].value.eval(mixinEnv);
-                        frame.resetCache();
-                    } else {
-                        throw { type: 'Runtime', message: "wrong number of arguments for " + this.name +
-                            ' (' + argsLength + ' for ' + this.arity + ')' };
-                    }
-                    
-                    frame.prependRule(new(tree.Rule)(name, val));
-                    evaldArguments[i] = val;
-                }
-            }
-
-            if (params[i].variadic && args) {
-                for (j = argIndex; j < argsLength; j++) {
-                    evaldArguments[j] = args[j].value.eval(env);
-                }
-            }
-            argIndex++;
-        }
-
-        return frame;
-    },
-    eval: function (env) {
-        return new tree.mixin.Definition(this.name, this.params, this.rules, this.condition, this.variadic, this.frames || env.frames.slice(0));
-    },
-    evalCall: function (env, args, important) {
-        var _arguments = [],
-            mixinFrames = this.frames ? this.frames.concat(env.frames) : env.frames,
-            frame = this.evalParams(env, new(tree.evalEnv)(env, mixinFrames), args, _arguments),
-            rules, ruleset;
-
-        frame.prependRule(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env)));
-
-        rules = this.rules.slice(0);
-
-        ruleset = new(tree.Ruleset)(null, rules);
-        ruleset.originalRuleset = this;
-        ruleset = ruleset.eval(new(tree.evalEnv)(env, [this, frame].concat(mixinFrames)));
-        if (important) {
-            ruleset = this.parent.makeImportant.apply(ruleset);
-        }
-        return ruleset;
-    },
-    matchCondition: function (args, env) {
-        if (this.condition && !this.condition.eval(
-            new(tree.evalEnv)(env,
-                [this.evalParams(env, new(tree.evalEnv)(env, this.frames.concat(env.frames)), args, [])] // the parameter variables
-                    .concat(this.frames) // the parent namespace/mixin frames
-                    .concat(env.frames)))) { // the current environment frames
-            return false;
-        }
-        return true;
-    },
-    matchArgs: function (args, env) {
-        var argsLength = (args && args.length) || 0, len;
-
-        if (! this.variadic) {
-            if (argsLength < this.required)                               { return false; }
-            if (argsLength > this.params.length)                          { return false; }
-        } else {
-            if (argsLength < (this.required - 1))                         { return false; }
-        }
-
-        len = Math.min(argsLength, this.arity);
-
-        for (var i = 0; i < len; i++) {
-            if (!this.params[i].name && !this.params[i].variadic) {
-                if (args[i].value.eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) {
-                    return false;
-                }
-            }
-        }
-        return true;
-    }
-};
-
-})(require('../tree'));
diff --git a/lib/less/tree/negative.js b/lib/less/tree/negative.js
index 12dbcc6..6f3e9af 100644
--- a/lib/less/tree/negative.js
+++ b/lib/less/tree/negative.js
@@ -1,9 +1,9 @@
-(function (tree) {
+module.exports = function (tree) {
 
-tree.Negative = function (node) {
+var Negative = function (node) {
     this.value = node;
 };
-tree.Negative.prototype = {
+Negative.prototype = {
     type: "Negative",
     accept: function (visitor) {
         this.value = visitor.visit(this.value);
@@ -17,8 +17,8 @@ tree.Negative.prototype = {
         if (env.isMathOn()) {
             return (new(tree.Operation)('*', [new(tree.Dimension)(-1), this.value])).eval(env);
         }
-        return new(tree.Negative)(this.value.eval(env));
+        return new(Negative)(this.value.eval(env));
     }
 };
-
-})(require('../tree'));
+return Negative;
+};
diff --git a/lib/less/tree/operation.js b/lib/less/tree/operation.js
index 8f1dd65..53dc37b 100644
--- a/lib/less/tree/operation.js
+++ b/lib/less/tree/operation.js
@@ -1,11 +1,11 @@
-(function (tree) {
+module.exports = function (tree) {
 
-tree.Operation = function (op, operands, isSpaced) {
+var Operation = function (op, operands, isSpaced) {
     this.op = op.trim();
     this.operands = operands;
     this.isSpaced = isSpaced;
 };
-tree.Operation.prototype = {
+Operation.prototype = {
     type: "Operation",
     accept: function (visitor) {
         this.operands = visitor.visit(this.operands);
@@ -28,7 +28,7 @@ tree.Operation.prototype = {
 
             return a.operate(env, this.op, b);
         } else {
-            return new(tree.Operation)(this.op, [a, b], this.isSpaced);
+            return new(Operation)(this.op, [a, b], this.isSpaced);
         }
     },
     genCSS: function (env, output) {
@@ -45,6 +45,7 @@ tree.Operation.prototype = {
     toCSS: tree.toCSS
 };
 
+// todo move!
 tree.operate = function (env, op, a, b) {
     switch (op) {
         case '+': return a + b;
@@ -53,5 +54,7 @@ tree.operate = function (env, op, a, b) {
         case '/': return a / b;
     }
 };
+    
+return Operation;
 
-})(require('../tree'));
+};
diff --git a/lib/less/tree/paren.js b/lib/less/tree/paren.js
index e27b8d6..5c7dca8 100644
--- a/lib/less/tree/paren.js
+++ b/lib/less/tree/paren.js
@@ -1,10 +1,9 @@
+module.exports = function (tree) {
 
-(function (tree) {
-
-tree.Paren = function (node) {
+var Paren = function (node) {
     this.value = node;
 };
-tree.Paren.prototype = {
+Paren.prototype = {
     type: "Paren",
     accept: function (visitor) {
         this.value = visitor.visit(this.value);
@@ -16,8 +15,8 @@ tree.Paren.prototype = {
     },
     toCSS: tree.toCSS,
     eval: function (env) {
-        return new(tree.Paren)(this.value.eval(env));
+        return new(Paren)(this.value.eval(env));
     }
 };
-
-})(require('../tree'));
+return Paren;
+};
diff --git a/lib/less/tree/quoted.js b/lib/less/tree/quoted.js
index 131bfad..738737a 100644
--- a/lib/less/tree/quoted.js
+++ b/lib/less/tree/quoted.js
@@ -1,13 +1,13 @@
-(function (tree) {
+module.exports = function (tree) {
 
-tree.Quoted = function (str, content, escaped, index, currentFileInfo) {
+var Quoted = function (str, content, escaped, index, currentFileInfo) {
     this.escaped = escaped;
     this.value = content || '';
     this.quote = str.charAt(0);
     this.index = index;
     this.currentFileInfo = currentFileInfo;
 };
-tree.Quoted.prototype = {
+Quoted.prototype = {
     type: "Quoted",
     genCSS: function (env, output) {
         if (!this.escaped) {
@@ -44,5 +44,5 @@ tree.Quoted.prototype = {
         return left < right ? -1 : 1;
     }
 };
-
-})(require('../tree'));
+return Quoted;
+};
diff --git a/lib/less/tree/rule.js b/lib/less/tree/rule.js
index 4e1ccde..f3cbcff 100644
--- a/lib/less/tree/rule.js
+++ b/lib/less/tree/rule.js
@@ -1,6 +1,6 @@
-(function (tree) {
+module.exports = function (tree) {
 
-tree.Rule = function (name, value, important, merge, index, currentFileInfo, inline) {
+var Rule = function (name, value, important, merge, index, currentFileInfo, inline) {
     this.name = name;
     this.value = (value instanceof tree.Value || value instanceof tree.Ruleset) ? value : new(tree.Value)([value]);
     this.important = important ? ' ' + important.trim() : '';
@@ -11,7 +11,7 @@ tree.Rule = function (name, value, important, merge, index, currentFileInfo, inl
     this.variable = name.charAt && (name.charAt(0) === '@');
 };
 
-tree.Rule.prototype = {
+Rule.prototype = {
     type: "Rule",
     accept: function (visitor) {
         this.value = visitor.visit(this.value);
@@ -50,7 +50,7 @@ tree.Rule.prototype = {
                         index: this.index, filename: this.currentFileInfo.filename };
             }
 
-            return new(tree.Rule)(name,
+            return new(Rule)(name,
                               evaldValue,
                               this.important,
                               this.merge,
@@ -70,7 +70,7 @@ tree.Rule.prototype = {
         }
     },
     makeImportant: function () {
-        return new(tree.Rule)(this.name,
+        return new(Rule)(this.name,
                               this.value,
                               "!important",
                               this.merge,
@@ -86,5 +86,7 @@ function evalName(env, name) {
     }
     return value;
 }
+    
+return Rule;
 
-})(require('../tree'));
+};
diff --git a/lib/less/tree/ruleset-call.js b/lib/less/tree/ruleset-call.js
index a543c55..e7d998c 100644
--- a/lib/less/tree/ruleset-call.js
+++ b/lib/less/tree/ruleset-call.js
@@ -1,9 +1,9 @@
-(function (tree) {
+module.exports = function (tree) {
 
-tree.RulesetCall = function (variable) {
+var RulesetCall = function (variable) {
     this.variable = variable;
 };
-tree.RulesetCall.prototype = {
+RulesetCall.prototype = {
     type: "RulesetCall",
     accept: function (visitor) {
     },
@@ -12,5 +12,5 @@ tree.RulesetCall.prototype = {
         return detachedRuleset.callEval(env);
     }
 };
-
-})(require('../tree'));
+return RulesetCall;
+};
diff --git a/lib/less/tree/ruleset.js b/lib/less/tree/ruleset.js
index 1902300..76a8d2a 100644
--- a/lib/less/tree/ruleset.js
+++ b/lib/less/tree/ruleset.js
@@ -1,12 +1,12 @@
-(function (tree) {
+module.exports = function (tree) {
 
-tree.Ruleset = function (selectors, rules, strictImports) {
+var Ruleset = function (selectors, rules, strictImports) {
     this.selectors = selectors;
     this.rules = rules;
     this._lookups = {};
     this.strictImports = strictImports;
 };
-tree.Ruleset.prototype = {
+Ruleset.prototype = {
     type: "Ruleset",
     accept: function (visitor) {
         if (this.paths) {
@@ -41,7 +41,7 @@ tree.Ruleset.prototype = {
         }
 
         var rules = this.rules ? this.rules.slice(0) : null,
-            ruleset = new(tree.Ruleset)(selectors, rules, this.strictImports),
+            ruleset = new(Ruleset)(selectors, rules, this.strictImports),
             rule, subRule;
 
         ruleset.originalRuleset = this;
@@ -129,7 +129,7 @@ tree.Ruleset.prototype = {
         for (i = 0; i < rsRules.length; i++) {
             rule = rsRules[i];
             // for rulesets, check if it is a css guard and can be removed
-            if (rule instanceof tree.Ruleset && rule.selectors && rule.selectors.length === 1) {
+            if (rule instanceof Ruleset && rule.selectors && rule.selectors.length === 1) {
                 // check if it can be folded in (e.g. & where)
                 if (rule.selectors[0].isJustParentSelector()) {
                     rsRules.splice(i--, 1);
@@ -174,7 +174,7 @@ tree.Ruleset.prototype = {
         }
     },
     makeImportant: function() {
-        return new tree.Ruleset(this.selectors, this.rules.map(function (r) {
+        return new Ruleset(this.selectors, this.rules.map(function (r) {
                     if (r.makeImportant) {
                         return r.makeImportant();
                     } else {
@@ -221,13 +221,13 @@ tree.Ruleset.prototype = {
     rulesets: function () {
         if (!this.rules) { return null; }
 
-        var _Ruleset = tree.Ruleset, _MixinDefinition = tree.mixin.Definition,
+        var _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)) {
+            if ((rule instanceof Ruleset) || (rule instanceof _MixinDefinition)) {
                 filtRules.push(rule);
             }
         }
@@ -551,4 +551,5 @@ tree.Ruleset.prototype = {
         }
     }
 };
-})(require('../tree'));
+return Ruleset;
+};
diff --git a/lib/less/tree/selector.js b/lib/less/tree/selector.js
index f38934e..ffcc8e8 100644
--- a/lib/less/tree/selector.js
+++ b/lib/less/tree/selector.js
@@ -1,6 +1,6 @@
-(function (tree) {
+module.exports = function (tree) {
 
-tree.Selector = function (elements, extendList, condition, index, currentFileInfo, isReferenced) {
+var Selector = function (elements, extendList, condition, index, currentFileInfo, isReferenced) {
     this.elements = elements;
     this.extendList = extendList;
     this.condition = condition;
@@ -10,7 +10,7 @@ tree.Selector = function (elements, extendList, condition, index, currentFileInf
         this.evaldCondition = true;
     }
 };
-tree.Selector.prototype = {
+Selector.prototype = {
     type: "Selector",
     accept: function (visitor) {
         if (this.elements) {
@@ -25,7 +25,7 @@ tree.Selector.prototype = {
     },
     createDerived: function(elements, extendList, evaldCondition) {
         evaldCondition = (evaldCondition != null) ? evaldCondition : this.evaldCondition;
-        var newSelector = new(tree.Selector)(elements, extendList || this.extendList, null, this.index, this.currentFileInfo, this.isReferenced);
+        var newSelector = new(Selector)(elements, extendList || this.extendList, null, this.index, this.currentFileInfo, this.isReferenced);
         newSelector.evaldCondition = evaldCondition;
         newSelector.mediaEmpty = this.mediaEmpty;
         return newSelector;
@@ -125,5 +125,5 @@ tree.Selector.prototype = {
         return this.evaldCondition;
     }
 };
-
-})(require('../tree'));
+return Selector;
+};
diff --git a/lib/less/tree/unicode-descriptor.js b/lib/less/tree/unicode-descriptor.js
index 7bf98ea..674ac98 100644
--- a/lib/less/tree/unicode-descriptor.js
+++ b/lib/less/tree/unicode-descriptor.js
@@ -1,9 +1,9 @@
-(function (tree) {
+module.exports = function (tree) {
 
-tree.UnicodeDescriptor = function (value) {
+var UnicodeDescriptor = function (value) {
     this.value = value;
 };
-tree.UnicodeDescriptor.prototype = {
+UnicodeDescriptor.prototype = {
     type: "UnicodeDescriptor",
     genCSS: function (env, output) {
         output.add(this.value);
@@ -11,5 +11,5 @@ tree.UnicodeDescriptor.prototype = {
     toCSS: tree.toCSS,
     eval: function () { return this; }
 };
-
-})(require('../tree'));
+return UnicodeDescriptor;
+};
diff --git a/lib/less/tree/unit-conversions.js b/lib/less/tree/unit-conversions.js
new file mode 100644
index 0000000..628f13d
--- /dev/null
+++ b/lib/less/tree/unit-conversions.js
@@ -0,0 +1,21 @@
+module.exports = {
+    length: {
+        'm': 1,
+        'cm': 0.01,
+        'mm': 0.001,
+        'in': 0.0254,
+        'px': 0.0254 / 96,
+        'pt': 0.0254 / 72,
+        'pc': 0.0254 / 72 * 12
+    },
+    duration: {
+        's': 1,
+        'ms': 0.001
+    },
+    angle: {
+        'rad': 1/(2*Math.PI),
+        'deg': 1/360,
+        'grad': 1/400,
+        'turn': 1
+    }
+};
\ No newline at end of file
diff --git a/lib/less/tree/unit.js b/lib/less/tree/unit.js
new file mode 100644
index 0000000..c25a717
--- /dev/null
+++ b/lib/less/tree/unit.js
@@ -0,0 +1,137 @@
+module.exports = function(tree, unitConversions) {
+
+var Unit = function (numerator, denominator, backupUnit) {
+    this.numerator = numerator ? numerator.slice(0).sort() : [];
+    this.denominator = denominator ? denominator.slice(0).sort() : [];
+    this.backupUnit = backupUnit;
+};
+
+Unit.prototype = {
+    type: "Unit",
+    clone: function () {
+        return new Unit(this.numerator.slice(0), this.denominator.slice(0), this.backupUnit);
+    },
+    genCSS: function (env, output) {
+        if (this.numerator.length >= 1) {
+            output.add(this.numerator[0]);
+        } else
+        if (this.denominator.length >= 1) {
+            output.add(this.denominator[0]);
+        } else
+        if ((!env || !env.strictUnits) && this.backupUnit) {
+            output.add(this.backupUnit);
+        }
+    },
+    toCSS: tree.toCSS,
+
+    toString: function () {
+        var i, returnStr = this.numerator.join("*");
+        for (i = 0; i < this.denominator.length; i++) {
+            returnStr += "/" + this.denominator[i];
+        }
+        return returnStr;
+    },
+
+    compare: function (other) {
+        return this.is(other.toString()) ? 0 : -1;
+    },
+
+    is: function (unitString) {
+        return this.toString() === unitString;
+    },
+
+    isLength: function () {
+        return Boolean(this.toCSS().match(/px|em|%|in|cm|mm|pc|pt|ex/));
+    },
+
+    isEmpty: function () {
+        return this.numerator.length === 0 && this.denominator.length === 0;
+    },
+
+    isSingular: function() {
+        return this.numerator.length <= 1 && this.denominator.length === 0;
+    },
+
+    map: function(callback) {
+        var i;
+
+        for (i = 0; i < this.numerator.length; i++) {
+            this.numerator[i] = callback(this.numerator[i], false);
+        }
+
+        for (i = 0; i < this.denominator.length; i++) {
+            this.denominator[i] = callback(this.denominator[i], true);
+        }
+    },
+
+    usedUnits: function() {
+        var group, result = {}, mapUnit;
+
+        mapUnit = function (atomicUnit) {
+            /*jshint loopfunc:true */
+            if (group.hasOwnProperty(atomicUnit) && !result[groupName]) {
+                result[groupName] = atomicUnit;
+            }
+
+            return atomicUnit;
+        };
+
+        for (var groupName in unitConversions) {
+            if (unitConversions.hasOwnProperty(groupName)) {
+                group = unitConversions[groupName];
+
+                this.map(mapUnit);
+            }
+        }
+
+        return result;
+    },
+
+    cancel: function () {
+        var counter = {}, atomicUnit, i, backup;
+
+        for (i = 0; i < this.numerator.length; i++) {
+            atomicUnit = this.numerator[i];
+            if (!backup) {
+                backup = atomicUnit;
+            }
+            counter[atomicUnit] = (counter[atomicUnit] || 0) + 1;
+        }
+
+        for (i = 0; i < this.denominator.length; i++) {
+            atomicUnit = this.denominator[i];
+            if (!backup) {
+                backup = atomicUnit;
+            }
+            counter[atomicUnit] = (counter[atomicUnit] || 0) - 1;
+        }
+
+        this.numerator = [];
+        this.denominator = [];
+
+        for (atomicUnit in counter) {
+            if (counter.hasOwnProperty(atomicUnit)) {
+                var count = counter[atomicUnit];
+
+                if (count > 0) {
+                    for (i = 0; i < count; i++) {
+                        this.numerator.push(atomicUnit);
+                    }
+                } else if (count < 0) {
+                    for (i = 0; i < -count; i++) {
+                        this.denominator.push(atomicUnit);
+                    }
+                }
+            }
+        }
+
+        if (this.numerator.length === 0 && this.denominator.length === 0 && backup) {
+            this.backupUnit = backup;
+        }
+
+        this.numerator.sort();
+        this.denominator.sort();
+    }
+};
+return Unit;
+};
\ No newline at end of file
diff --git a/lib/less/tree/url.js b/lib/less/tree/url.js
index 9056268..28e37d2 100644
--- a/lib/less/tree/url.js
+++ b/lib/less/tree/url.js
@@ -1,11 +1,11 @@
-(function (tree) {
+module.exports = function (tree) {
 
-tree.URL = function (val, currentFileInfo, isEvald) {
+var URL = function (val, currentFileInfo, isEvald) {
     this.value = val;
     this.currentFileInfo = currentFileInfo;
     this.isEvald = isEvald;
 };
-tree.URL.prototype = {
+URL.prototype = {
     type: "Url",
     accept: function (visitor) {
         this.value = visitor.visit(this.value);
@@ -46,8 +46,8 @@ tree.URL.prototype = {
             }
         }
 
-        return new(tree.URL)(val, this.currentFileInfo, true);
+        return new(URL)(val, this.currentFileInfo, true);
     }
 };
-
-})(require('../tree'));
+return URL;
+};
diff --git a/lib/less/tree/value.js b/lib/less/tree/value.js
index f95e7b5..ea07367 100644
--- a/lib/less/tree/value.js
+++ b/lib/less/tree/value.js
@@ -1,9 +1,9 @@
-(function (tree) {
+module.exports = function (tree) {
 
-tree.Value = function (value) {
+var Value = function (value) {
     this.value = value;
 };
-tree.Value.prototype = {
+Value.prototype = {
     type: "Value",
     accept: function (visitor) {
         if (this.value) {
@@ -14,7 +14,7 @@ tree.Value.prototype = {
         if (this.value.length === 1) {
             return this.value[0].eval(env);
         } else {
-            return new(tree.Value)(this.value.map(function (v) {
+            return new(Value)(this.value.map(function (v) {
                 return v.eval(env);
             }));
         }
@@ -30,5 +30,5 @@ tree.Value.prototype = {
     },
     toCSS: tree.toCSS
 };
-
-})(require('../tree'));
+return Value;
+};
diff --git a/lib/less/tree/variable.js b/lib/less/tree/variable.js
index 90d8627..1e152e4 100644
--- a/lib/less/tree/variable.js
+++ b/lib/less/tree/variable.js
@@ -1,17 +1,17 @@
-(function (tree) {
+module.exports = function (tree) {
 
-tree.Variable = function (name, index, currentFileInfo) {
+var Variable = function (name, index, currentFileInfo) {
     this.name = name;
     this.index = index;
     this.currentFileInfo = currentFileInfo || {};
 };
-tree.Variable.prototype = {
+Variable.prototype = {
     type: "Variable",
     eval: function (env) {
         var variable, name = this.name;
 
         if (name.indexOf('@@') === 0) {
-            name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value;
+            name = '@' + new(Variable)(name.slice(1)).eval(env).value;
         }
         
         if (this.evaluating) {
@@ -40,5 +40,5 @@ tree.Variable.prototype = {
         }
     }
 };
-
-})(require('../tree'));
+return Variable;
+};
diff --git a/lib/less/visitor.js b/lib/less/visitor.js
index 75b9975..d4696e7 100644
--- a/lib/less/visitor.js
+++ b/lib/less/visitor.js
@@ -1,4 +1,4 @@
-(function (tree) {
+module.exports = function (tree) {
 
     var _visitArgs = { visitDeeper: true },
         _hasIndexed = false;
@@ -143,4 +143,4 @@
         }
     };
 
-})(require('./tree'));
\ No newline at end of file
+};
diff --git a/package.json b/package.json
index 8e91bbf..95ccd88 100644
--- a/package.json
+++ b/package.json
@@ -59,7 +59,8 @@
     "http-server": "~0.6.1",
     "matchdep": "~0.3.0",
     "time-grunt": "~0.2.9",
-    "grunt-contrib-copy": "~0.4.1"
+    "browserify": "~3.30.2",
+    "grunt-browserify": "~1.3.1"
   },
   "keywords": [
     "compile less",

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