[Pkg-javascript-commits] [less.js] 14/14: 2.3.1 release

Jonas Smedegaard dr at jones.dk
Mon Oct 26 23:29:18 UTC 2015


This is an automated email from the git hooks/post-receive script.

js pushed a commit to annotated tag v2.3.1
in repository less.js.

commit edca7f4cfa97c81e5664ec8ea13a904c9bdf469c
Author: Luke Page <luke.a.page at gmail.com>
Date:   Wed Jan 28 17:29:34 2015 +0000

    2.3.1 release
---
 CHANGELOG.md      |   7 +
 bower.json        |   2 +-
 dist/less.js      | 607 ++++++++++++++++++++++++++++++++----------------------
 dist/less.min.js  |  10 +-
 lib/less/index.js |   2 +-
 package.json      |   2 +-
 6 files changed, 377 insertions(+), 253 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index efce211..0bbc08b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,10 @@
+# 2.3.1
+
+2015-01-28
+
+ - Fix depends option (regression in 2.3.0)
+ - Support parent selector (`&`) used in sub element expression (e.g. `:not(.c_&)`)
+
 # 2.3.0
 
 2015-01-27
diff --git a/bower.json b/bower.json
index a17d295..73ceb2f 100644
--- a/bower.json
+++ b/bower.json
@@ -1,6 +1,6 @@
 {
   "name": "less",
-  "version": "2.3.0",
+  "version": "2.3.1",
   "main": "dist/less.js",
   "ignore": [
     "**/.*",
diff --git a/dist/less.js b/dist/less.js
index a3ec0f8..e602788 100644
--- a/dist/less.js
+++ b/dist/less.js
@@ -1,5 +1,5 @@
 /*!
- * Less - Leaner CSS v2.3.0
+ * Less - Leaner CSS v2.3.1
  * http://lesscss.org
  *
  * Copyright (c) 2009-2015, Alexis Sellier <self at cloudhead.net>
@@ -788,11 +788,11 @@ module.exports = function(less, options) {
 module.exports = {
     extractId: function(href) {
         return href.replace(/^[a-z-]+:\/+?[^\/]+/, '' )  // Remove protocol & domain
-            .replace(/[\?\&]livereload=\w+/,'' )  // Remove LiveReload cachebuster
-            .replace(/^\//,                 '' )  // Remove root /
-            .replace(/\.[a-zA-Z]+$/,        '' )  // Remove simple extension
-            .replace(/[^\.\w-]+/g,          '-')  // Replace illegal characters
-            .replace(/\./g,                 ':'); // Replace dots with colons(for valid id)
+            .replace(/[\?\&]livereload=\w+/, '' )  // Remove LiveReload cachebuster
+            .replace(/^\//,                  '' )  // Remove root /
+            .replace(/\.[a-zA-Z]+$/,         '' )  // Remove simple extension
+            .replace(/[^\.\w-]+/g,           '-')  // Replace illegal characters
+            .replace(/\./g,                  ':'); // Replace dots with colons(for valid id)
     },
     addDataAttr: function(options, tag) {
         for (var opt in tag.dataset) {
@@ -1095,9 +1095,9 @@ module.exports = {
         'ms': 0.001
     },
     angle: {
-        'rad': 1/(2*Math.PI),
-        'deg': 1/360,
-        'grad': 1/400,
+        'rad': 1 / (2 * Math.PI),
+        'deg': 1 / 360,
+        'grad': 1 / 400,
         'turn': 1
     }
 };
@@ -1157,10 +1157,10 @@ abstractFileManager.prototype.pathDiff = function pathDiff(url, baseUrl) {
     }
     baseUrlDirectories = baseUrlParts.directories.slice(i);
     urlDirectories = urlParts.directories.slice(i);
-    for(i = 0; i < baseUrlDirectories.length-1; i++) {
+    for(i = 0; i < baseUrlDirectories.length - 1; i++) {
         diff += "../";
     }
-    for(i = 0; i < urlDirectories.length-1; i++) {
+    for(i = 0; i < urlDirectories.length - 1; i++) {
         diff += urlDirectories[i] + "/";
     }
     return diff;
@@ -1185,7 +1185,7 @@ abstractFileManager.prototype.extractUrlParts = function extractUrlParts(url, ba
     if (baseUrl && (!urlParts[1] || urlParts[2])) {
         baseUrlParts = baseUrl.match(urlPartsRegex);
         if (!baseUrlParts) {
-            throw new Error("Could not parse page url - '"+baseUrl+"'");
+            throw new Error("Could not parse page url - '" + baseUrl + "'");
         }
         urlParts[1] = urlParts[1] || baseUrlParts[1] || "";
         if (!urlParts[2]) {
@@ -1206,7 +1206,7 @@ abstractFileManager.prototype.extractUrlParts = function extractUrlParts(url, ba
 
         for(i = 0; i < directories.length; i++) {
             if (directories[i] === ".." && i > 0) {
-                directories.splice(i-1, 2);
+                directories.splice(i - 1, 2);
                 i -= 2;
             }
         }
@@ -1311,9 +1311,9 @@ var colorBlendModeFunctions = {
     },
     overlay: function(cb, cs) {
         cb *= 2;
-        return (cb <= 1)
-            ? colorBlendModeFunctions.multiply(cb, cs)
-            : colorBlendModeFunctions.screen(cb - 1, cs);
+        return (cb <= 1) ?
+            colorBlendModeFunctions.multiply(cb, cs) :
+            colorBlendModeFunctions.screen(cb - 1, cs);
     },
     softlight: function(cb, cs) {
         var d = 1, e = cb;
@@ -1401,7 +1401,7 @@ colorFunctions = {
             h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h);
             if      (h * 6 < 1) { return m1 + (m2 - m1) * h * 6; }
             else if (h * 2 < 1) { return m2; }
-            else if (h * 3 < 2) { return m1 + (m2 - m1) * (2/3 - h) * 6; }
+            else if (h * 3 < 2) { return m1 + (m2 - m1) * (2 / 3 - h) * 6; }
             else                { return m1; }
         }
 
@@ -1411,9 +1411,9 @@ colorFunctions = {
         var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s;
         var m1 = l * 2 - m2;
 
-        return colorFunctions.rgba(hue(h + 1/3) * 255,
+        return colorFunctions.rgba(hue(h + 1 / 3) * 255,
             hue(h)       * 255,
-            hue(h - 1/3) * 255,
+            hue(h - 1 / 3) * 255,
             a);
     },
 
@@ -1481,9 +1481,9 @@ colorFunctions = {
     },
     luminance: function (color) {
         var luminance =
-            (0.2126 * color.rgb[0] / 255)
-                + (0.7152 * color.rgb[1] / 255)
-                + (0.0722 * color.rgb[2] / 255);
+            (0.2126 * color.rgb[0] / 255) +
+                (0.7152 * color.rgb[1] / 255) +
+                (0.0722 * color.rgb[2] / 255);
 
         return new Dimension(luminance * color.alpha * 100, '%');
     },
@@ -1622,7 +1622,7 @@ colorFunctions = {
         };
     },
     tint: function(color, amount) {
-        return colorFunctions.mix(colorFunctions.rgb(255,255,255), color, amount);
+        return colorFunctions.mix(colorFunctions.rgb(255, 255, 255), color, amount);
     },
     shade: function(color, amount) {
         return colorFunctions.mix(colorFunctions.rgb(0, 0, 0), color, amount);
@@ -1655,7 +1655,7 @@ module.exports = function(environment) {
 
         var fragmentStart = filePath.indexOf('#');
         var fragment = '';
-        if (fragmentStart!==-1) {
+        if (fragmentStart !== -1) {
             fragment = filePath.slice(fragmentStart);
             filePath = filePath.slice(0, fragmentStart);
         }
@@ -1706,7 +1706,8 @@ module.exports = function(environment) {
         if (uri.length >= DATA_URI_MAX) {
 
             if (this.context.ieCompat !== false) {
-                logger.warn("Skipped data-uri embedding of " + filePath + " because its size (" + uri.length + " characters) exceeds IE8-safe " + DATA_URI_MAX + " characters!");
+                logger.warn("Skipped data-uri embedding of " + filePath + " because its size (" + uri.length +
+                    " characters) exceeds IE8-safe " + DATA_URI_MAX + " characters!");
 
                 return fallback(this, filePathNode || mimetypeNode);
             }
@@ -1937,7 +1938,9 @@ functionRegistry.addMultiple({
         return new Anonymous(str instanceof JavaScript ? str.evaluated : str.value);
     },
     escape: function (str) {
-        return new Anonymous(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29"));
+        return new Anonymous(
+            encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B")
+                .replace(/\(/g, "%28").replace(/\)/g, "%29"));
     },
     replace: function (string, pattern, replacement, flags) {
         var result = string.value;
@@ -1973,7 +1976,9 @@ module.exports = function(environment) {
     functionRegistry.add("svg-gradient", function(direction) {
 
         function throwArgumentDescriptor() {
-            throw { type: "Argument", message: "svg-gradient expects direction, start_color [start_position], [color position,]..., end_color [end_position]" };
+            throw { type: "Argument",
+                message: "svg-gradient expects direction, start_color [start_position], [color position,]...," +
+                    " end_color [end_position]" };
         }
 
         if (arguments.length < 3) {
@@ -2008,7 +2013,8 @@ module.exports = function(environment) {
                 rectangleDimension = 'x="-50" y="-50" width="101" height="101"';
                 break;
             default:
-                throw { type: "Argument", message: "svg-gradient direction must be 'to bottom', 'to right', 'to bottom right', 'to top right' or 'ellipse at center'" };
+                throw { type: "Argument", message: "svg-gradient direction must be 'to bottom', 'to right'," +
+                    " 'to bottom right', 'to top right' or 'ellipse at center'" };
         }
         returner = '<?xml version="1.0" ?>' +
             '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100%" height="100%" viewBox="0 0 1 1" preserveAspectRatio="none">' +
@@ -2023,7 +2029,7 @@ module.exports = function(environment) {
                 position = undefined;
             }
 
-            if (!(color instanceof Color) || (!((i === 0 || i+1 === stops.length) && position === undefined) && !(position instanceof Dimension))) {
+            if (!(color instanceof Color) || (!((i === 0 || i + 1 === stops.length) && position === undefined) && !(position instanceof Dimension))) {
                 throwArgumentDescriptor();
             }
             positionValue = position ? position.toCSS(renderEnv) : i === 0 ? "0%" : "100%";
@@ -2095,7 +2101,9 @@ functionRegistry.addMultiple({
     isunit: isunit,
     unit: function (val, unit) {
         if(!(val instanceof Dimension)) {
-            throw { type: "Argument", message: "the first argument to unit must be a number" + (val instanceof Operation ? ". Have you forgotten parenthesis?" : "") };
+            throw { type: "Argument",
+                message: "the first argument to unit must be a number" +
+                    (val instanceof Operation ? ". Have you forgotten parenthesis?" : "") };
         }
         if (unit) {
             if (unit instanceof Keyword) {
@@ -2209,7 +2217,10 @@ module.exports = function(environment) {
             //   then rootpath should become 'less/../'
             newFileInfo.currentDirectory = fileManager.getPath(resolvedFilename);
             if(newFileInfo.relativeUrls) {
-                newFileInfo.rootpath = fileManager.join((importManager.context.rootpath || ""), fileManager.pathDiff(newFileInfo.currentDirectory, newFileInfo.entryPath));
+                newFileInfo.rootpath = fileManager.join(
+                    (importManager.context.rootpath || ""),
+                    fileManager.pathDiff(newFileInfo.currentDirectory, newFileInfo.entryPath));
+
                 if (!fileManager.isPathAbsolute(newFileInfo.rootpath) && fileManager.alwaysMakePathsAbsolute()) {
                     newFileInfo.rootpath = fileManager.join(newFileInfo.entryPath, newFileInfo.rootpath);
                 }
@@ -2254,7 +2265,7 @@ module.exports = function(environment, fileManagers) {
     var SourceMapOutput, SourceMapBuilder, ParseTree, ImportManager, Environment;
 
     var less = {
-        version: [2, 3, 0],
+        version: [2, 3, 1],
         data: require('./data'),
         tree: require('./tree'),
         Environment: (Environment = require("./environment/environment")),
@@ -3070,7 +3081,7 @@ var Parser = function Parser(context, imports, fileInfo) {
         //     Ruleset (Selector '.class', [
         //         Rule ("color",  Value ([Expression [Color #fff]]))
         //         Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]]))
-        //         Rule ("width",  Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]]))
+        //         Rule ("width",  Value ([Expression [Operation " + " [Variable "@w"][Dimension 4px]]]))
         //         Ruleset (Selector [Element '>', '.child'], [...])
         //     ])
         //
@@ -3320,7 +3331,9 @@ var Parser = function Parser(context, imports, fileInfo) {
                     var rgb;
 
                     if (parserInput.currentChar() === '#' && (rgb = parserInput.$re(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/))) {
-                        var colorCandidateString = rgb.input.match(/^#([\w]+).*/); // strip colons, brackets, whitespaces and other characters that should not definitely be part of color string
+                        // strip colons, brackets, whitespaces and other characters that should not
+                        // definitely be part of color string
+                        var colorCandidateString = rgb.input.match(/^#([\w]+).*/);
                         colorCandidateString = colorCandidateString[1];
                         if (!colorCandidateString.match(/^[A-Fa-f0-9]+$/)) { // verify if candidate consists only of allowed HEX characters
                             error("Invalid HEX color code");
@@ -3416,8 +3429,9 @@ var Parser = function Parser(context, imports, fileInfo) {
                     }
 
                     option = option && option[1];
-                    if (!elements)
+                    if (!elements) {
                         error("Missing target selector for :extend().");
+                    }
                     extend = new(tree.Extend)(new(tree.Selector)(elements), option, index);
                     if (extendList) { extendList.push(extend); } else { extendList = [ extend ]; }
 
@@ -3727,8 +3741,10 @@ var Parser = function Parser(context, imports, fileInfo) {
 
                 c = this.combinator();
 
-                e = parserInput.$re(/^(?:\d+\.\d+|\d+)%/) || parserInput.$re(/^(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/) ||
-                    parserInput.$char('*') || parserInput.$char('&') || this.attribute() || parserInput.$re(/^\([^()@]+\)/) || parserInput.$re(/^[\.#:](?=@)/) ||
+                e = parserInput.$re(/^(?:\d+\.\d+|\d+)%/) ||
+                    parserInput.$re(/^(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/) ||
+                    parserInput.$char('*') || parserInput.$char('&') || this.attribute() ||
+                    parserInput.$re(/^\([^&()@]+\)/) ||  parserInput.$re(/^[\.#:](?=@)/) ||
                     this.entities.variableCurly();
 
                 if (! e) {
@@ -4472,8 +4488,8 @@ Parser.serializeVars = function(vars) {
     for (var name in vars) {
         if (Object.hasOwnProperty.call(vars, name)) {
             var value = vars[name];
-            s += ((name[0] === '@') ? '' : '@') + name +': '+ value +
-                ((('' + value).slice(-1) === ';') ? '' : ';');
+            s += ((name[0] === '@') ? '' : '@') + name + ': ' + value +
+                ((String(value).slice(-1) === ';') ? '' : ';');
         }
     }
 
@@ -4696,7 +4712,7 @@ module.exports = function (environment) {
         }
         if (options.sourceMapRootpath) {
             this._sourceMapRootpath = options.sourceMapRootpath.replace(/\\/g, '/');
-            if (this._sourceMapRootpath.charAt(this._sourceMapRootpath.length-1) !== '/') {
+            if (this._sourceMapRootpath.charAt(this._sourceMapRootpath.length - 1) !== '/') {
                 this._sourceMapRootpath += '/';
             }
         } else {
@@ -4747,11 +4763,11 @@ module.exports = function (environment) {
             }
             inputSource = inputSource.substring(0, index);
             sourceLines = inputSource.split("\n");
-            sourceColumns = sourceLines[sourceLines.length-1];
+            sourceColumns = sourceLines[sourceLines.length - 1];
         }
 
         lines = chunk.split("\n");
-        columns = lines[lines.length-1];
+        columns = lines[lines.length - 1];
 
         if (fileInfo) {
             if (!mapLines) {
@@ -4867,7 +4883,7 @@ module.exports = function(root, options) {
 
     if (options.pluginManager) {
         var pluginVisitors = options.pluginManager.getVisitors();
-        for(i =0; i < pluginVisitors.length; i++) {
+        for(i = 0; i < pluginVisitors.length; i++) {
             var pluginVisitor = pluginVisitors[i];
             if (pluginVisitor.isPreEvalVisitor) {
                 preEvalVisitors.push(pluginVisitor);
@@ -5344,7 +5360,7 @@ Condition.prototype.eval = function (context) {
                         default: return false;
                 }
         }
-    }) (this.op, this.lvalue.eval(context), this.rvalue.eval(context));
+    })(this.op, this.lvalue.eval(context), this.rvalue.eval(context));
 
     return this.negate ? !result : result;
 };
@@ -5352,7 +5368,7 @@ module.exports = Condition;
 
 },{"./node":67}],51:[function(require,module,exports){
 var debugInfo = function(context, ctx, lineSeparator) {
-    var result="";
+    var result = "";
     if (context.dumpLineNumbers && !context.compress) {
         switch(context.dumpLineNumbers) {
             case 'comments':
@@ -5374,8 +5390,12 @@ debugInfo.asComment = function(ctx) {
 };
 
 debugInfo.asMediaQuery = function(ctx) {
+    var filenameWithProtocol = ctx.debugInfo.fileName;
+    if (!/^[a-z]+:\/\//i.test(filenameWithProtocol)) {
+        filenameWithProtocol = 'file://' + filenameWithProtocol;
+    }
     return '@media -sass-debug-info{filename{font-family:' +
-        ('file://' + ctx.debugInfo.fileName).replace(/([.:\/\\])/g, function (a) {
+        filenameWithProtocol.replace(/([.:\/\\])/g, function (a) {
             if (a == '\\') {
                 a = '\/';
             }
@@ -5437,7 +5457,7 @@ Dimension.prototype.toColor = function () {
 };
 Dimension.prototype.genCSS = function (context, output) {
     if ((context && context.strictUnits) && !this.unit.isSingular()) {
-        throw new Error("Multiple units in dimension. Correct the units or use the unit function. Bad unit: "+this.unit.toString());
+        throw new Error("Multiple units in dimension. Correct the units or use the unit function. Bad unit: " + this.unit.toString());
     }
 
     var value = this.fround(context, this.value),
@@ -5628,9 +5648,21 @@ Directive.prototype.eval = function (context) {
     return new Directive(this.name, value, rules,
         this.index, this.currentFileInfo, this.debugInfo, this.isReferenced);
 };
-Directive.prototype.variable = function (name) { if (this.rules) return Ruleset.prototype.variable.call(this.rules, name); };
-Directive.prototype.find = function () { if (this.rules) return Ruleset.prototype.find.apply(this.rules, arguments); };
-Directive.prototype.rulesets = function () { if (this.rules) return Ruleset.prototype.rulesets.apply(this.rules); };
+Directive.prototype.variable = function (name) {
+    if (this.rules) {
+        return Ruleset.prototype.variable.call(this.rules, name);
+    }
+};
+Directive.prototype.find = function () {
+    if (this.rules) {
+        return Ruleset.prototype.find.apply(this.rules, arguments);
+    }
+};
+Directive.prototype.rulesets = function () {
+    if (this.rules) {
+        return Ruleset.prototype.rulesets.apply(this.rules);
+    }
+};
 Directive.prototype.markReferenced = function () {
     var i, rules;
     this.isReferenced = true;
@@ -5948,7 +5980,7 @@ Import.prototype.evalPath = function (context) {
             var pathValue = path.value;
             // Add the base path if the import is relative
             if (pathValue && context.isPathRelative(pathValue)) {
-                path.value = rootpath +pathValue;
+                path.value = rootpath + pathValue;
             }
         }
         path.value = context.normalizePath(path.value);
@@ -6296,8 +6328,9 @@ Media.prototype.permute = function (arr) {
   }
 };
 Media.prototype.bubbleSelectors = function (selectors) {
-  if (!selectors)
-    return;
+  if (!selectors) {
+      return;
+  }
   this.rules = [new Ruleset(selectors.slice(0), [this.rules[0]])];
 };
 module.exports = Media;
@@ -6327,7 +6360,7 @@ MixinCall.prototype.accept = function (visitor) {
 };
 MixinCall.prototype.eval = function (context) {
     var mixins, mixin, mixinPath, args, rules = [], match = false, i, m, f, isRecursive, isOneFound, rule,
-        candidates = [], candidate, conditionResult = [], defaultResult, defFalseEitherCase=-1,
+        candidates = [], candidate, conditionResult = [], defaultResult, defFalseEitherCase = -1,
         defNone = 0, defTrue = 1, defFalse = 2, count, originalRuleset, noArgumentsFilter;
 
     function calcDefGroup(mixin, mixinPath) {
@@ -6389,7 +6422,7 @@ MixinCall.prototype.eval = function (context) {
                 if (mixin.matchArgs(args, context)) {
                     candidate = {mixin: mixin, group: calcDefGroup(mixin, mixinPath)};
 
-                    if (candidate.group!==defFalseEitherCase) {
+                    if (candidate.group !== defFalseEitherCase) {
                         candidates.push(candidate);
                     }
 
@@ -6410,8 +6443,7 @@ MixinCall.prototype.eval = function (context) {
                 defaultResult = defTrue;
                 if ((count[defTrue] + count[defFalse]) > 1) {
                     throw { type: 'Runtime',
-                        message: 'Ambiguous use of `default()` found when matching for `'
-                            + this.format(args) + '`',
+                        message: 'Ambiguous use of `default()` found when matching for `' + this.format(args) + '`',
                         index: this.index, filename: this.currentFileInfo.filename };
                 }
             }
@@ -6609,9 +6641,10 @@ Definition.prototype.evalCall = function (context, args, important) {
 Definition.prototype.matchCondition = function (args, context) {
     if (this.condition && !this.condition.eval(
         new contexts.Eval(context,
-            [this.evalParams(context, new contexts.Eval(context, this.frames ? this.frames.concat(context.frames) : context.frames), args, [])] // the parameter variables
-                .concat(this.frames) // the parent namespace/mixin frames
-                .concat(context.frames)))) { // the current environment frames
+            [this.evalParams(context, /* the parameter variables*/
+                new contexts.Eval(context, this.frames ? this.frames.concat(context.frames) : context.frames), args, [])]
+            .concat(this.frames) // the parent namespace/mixin frames
+            .concat(context.frames)))) { // the current environment frames
         return false;
     }
     return true;
@@ -6845,7 +6878,7 @@ Quoted.prototype.eval = function (context) {
         do {
           value = evaluatedValue;
           evaluatedValue = value.replace(regexp, replacementFnc);
-        } while  (value!==evaluatedValue);
+        } while  (value !== evaluatedValue);
         return evaluatedValue;
     }
     value = iterativeReplace(value, /`([^`]+)`/g, javascriptReplacement);
@@ -6907,9 +6940,8 @@ Rule.prototype.eval = function (context) {
     if (typeof name !== "string") {
         // expand 'primitive' name directly to get
         // things faster (~10% for benchmark.less):
-        name = (name.length === 1)
-            && (name[0] instanceof Keyword)
-                ? name[0].value : evalName(context, name);
+        name = (name.length === 1) && (name[0] instanceof Keyword) ?
+                name[0].value : evalName(context, name);
             variable = false; // never treat expanded interpolation as new variable name
     }
     if (name === "font" && !context.strictMath) {
@@ -6980,6 +7012,7 @@ var Node = require("./node"),
     Rule = require("./rule"),
     Selector = require("./selector"),
     Element = require("./element"),
+    Paren = require("./paren"),
     contexts = require("../contexts"),
     defaultFunc = require("../functions/default"),
     getDebugInfo = require("./debug-info");
@@ -7085,7 +7118,7 @@ Ruleset.prototype.eval = function (context) {
             });
             rsRules.splice.apply(rsRules, [i, 1].concat(rules));
             rsRuleCnt += rules.length - 1;
-            i += rules.length-1;
+            i += rules.length - 1;
             ruleset.resetCache();
         } else if (rsRules[i].type === "RulesetCall") {
             /*jshint loopfunc:true */
@@ -7098,7 +7131,7 @@ Ruleset.prototype.eval = function (context) {
             });
             rsRules.splice.apply(rsRules, [i, 1].concat(rules));
             rsRuleCnt += rules.length - 1;
-            i += rules.length-1;
+            i += rules.length - 1;
             ruleset.resetCache();
         }
     }
@@ -7151,7 +7184,7 @@ Ruleset.prototype.evalImports = function(context) {
             importRules = rules[i].eval(context);
             if (importRules && importRules.length) {
                 rules.splice.apply(rules, [i, 1].concat(importRules));
-                i+= importRules.length-1;
+                i+= importRules.length - 1;
             } else {
                 rules.splice(i, 1, importRules);
             }
@@ -7173,7 +7206,7 @@ Ruleset.prototype.makeImportant = function() {
 };
 // lets you call a css selector with a guard
 Ruleset.prototype.matchCondition = function (args, context) {
-    var lastSelector = this.selectors[this.selectors.length-1];
+    var lastSelector = this.selectors[this.selectors.length - 1];
     if (!lastSelector.evaldCondition) {
         return false;
     }
@@ -7401,8 +7434,9 @@ Ruleset.prototype.markReferenced = function () {
 
     if (this.rules) {
         for (s = 0; s < this.rules.length; s++) {
-            if (this.rules[s].markReferenced)
+            if (this.rules[s].markReferenced) {
                 this.rules[s].markReferenced();
+            }
         }
     }
 };
@@ -7410,20 +7444,22 @@ Ruleset.prototype.getIsReferenced = function() {
     var i, j, path, selector;
 
     if (this.paths) {
-        for (i=0; i<this.paths.length; i++) {
+        for (i = 0; i < this.paths.length; i++) {
             path = this.paths[i];
-            for (j=0; j<path.length; j++) {
-                if (path[j].getIsReferenced && path[j].getIsReferenced())
+            for (j = 0; j < path.length; j++) {
+                if (path[j].getIsReferenced && path[j].getIsReferenced()) {
                     return true;
+                }
             }
         }
     }
 
     if (this.selectors) {
-        for (i=0;i<this.selectors.length;i++) {
+        for (i = 0; i < this.selectors.length; i++) {
             selector = this.selectors[i];
-            if (selector.getIsReferenced && selector.getIsReferenced())
+            if (selector.getIsReferenced && selector.getIsReferenced()) {
                 return true;
+            }
         }
     }
     return false;
@@ -7437,180 +7473,250 @@ Ruleset.prototype.joinSelectors = function (paths, context, selectors) {
 
 Ruleset.prototype.joinSelector = function (paths, context, selector) {
 
-    var i, j, k,
-        hasParentSelector, newSelectors, el, sel, parentSel,
-        newSelectorPath, afterParentJoin, newJoinedSelector,
-        newJoinedSelectorEmpty, lastSelector, currentElements,
-        selectorsMultiplied;
-
-    for (i = 0; i < selector.elements.length; i++) {
-        el = selector.elements[i];
-        if (el.value === '&') {
-            hasParentSelector = true;
-        }
-    }
+    function createParenthesis(elementsToPak, originalElement) {
+        var replacementParen, j;
+        if (elementsToPak.length === 0) {
+            replacementParen = new Paren(elementsToPak[0]);
+        } else {
+            var insideParent = [];
+            for (j = 0; j < elementsToPak.length; j++) {
+                insideParent.push(new Element(null, elementsToPak[j], originalElement.index, originalElement.currentFileInfo));
+            }
+            replacementParen = new Paren(new Selector(insideParent));
+        }
+        return replacementParen;
+    }
+
+    function createSelector(containedElement, originalElement) {
+        var element, selector;
+        element = new Element(null, containedElement, originalElement.index, originalElement.currentFileInfo);
+        selector = new Selector([element]);
+        return selector;
+    }
+
+    // replace all parent selectors inside `inSelector` by content of `context` array
+    // resulting selectors are returned inside `paths` array
+    // returns true if `inSelector` contained at least one parent selector
+    function replaceParentSelector(paths, context, inSelector) {
+        // The paths are [[Selector]]
+        // The first list is a list of comma separated selectors
+        // The inner list is a list of inheritance separated selectors
+        // e.g.
+        // .a, .b {
+        //   .c {
+        //   }
+        // }
+        // == [[.a] [.c]] [[.b] [.c]]
+        //
+        var i, j, k, currentElements, newSelectors, selectorsMultiplied, sel, el, hadParentSelector = false;
+        function findNestedSelector(element) {
+            var maybeSelector;
+            if (element.value.type !== 'Paren') {
+                return null;
+            }
 
-    if (!hasParentSelector) {
-        if (context.length > 0) {
-            for (i = 0; i < context.length; i++) {
-                paths.push(context[i].concat(selector));
+            maybeSelector = element.value.value;
+            if (maybeSelector.type !== 'Selector') {
+                return null;
             }
+
+            return maybeSelector;
         }
-        else {
-            paths.push([selector]);
-        }
-        return;
-    }
 
-    // The paths are [[Selector]]
-    // The first list is a list of comma separated selectors
-    // The inner list is a list of inheritance separated selectors
-    // e.g.
-    // .a, .b {
-    //   .c {
-    //   }
-    // }
-    // == [[.a] [.c]] [[.b] [.c]]
-    //
+        // the elements from the current selector so far
+        currentElements = [];
+        // the current list of new selectors to add to the path.
+        // We will build it up. We initiate it with one empty selector as we "multiply" the new selectors
+        // by the parents
+        newSelectors = [
+            []
+        ];
 
-    // the elements from the current selector so far
-    currentElements = [];
-    // the current list of new selectors to add to the path.
-    // We will build it up. We initiate it with one empty selector as we "multiply" the new selectors
-    // by the parents
-    newSelectors = [[]];
-
-    for (i = 0; i < selector.elements.length; i++) {
-        el = selector.elements[i];
-        // non parent reference elements just get added
-        if (el.value !== "&") {
-            currentElements.push(el);
-        } else {
-            // the new list of selectors to add
-            selectorsMultiplied = [];
-
-            // merge the current list of non parent selector elements
-            // on to the current list of selectors to add
-            if (currentElements.length > 0) {
-                this.mergeElementsOnToSelectors(currentElements, newSelectors);
-            }
-
-            // loop through our current selectors
-            for (j = 0; j < newSelectors.length; j++) {
-                sel = newSelectors[j];
-                // if we don't have any parent paths, the & might be in a mixin so that it can be used
-                // whether there are parents or not
-                if (context.length === 0) {
-                    // the combinator used on el should now be applied to the next element instead so that
-                    // it is not lost
-                    if (sel.length > 0) {
-                        sel[0].elements = sel[0].elements.slice(0);
-                        sel[0].elements.push(new Element(el.combinator, '', el.index, el.currentFileInfo));
+        for (i = 0; i < inSelector.elements.length; i++) {
+            el = inSelector.elements[i];
+            // non parent reference elements just get added
+            if (el.value !== "&") {
+                var nestedSelector = findNestedSelector(el);
+                if (nestedSelector != null) {
+                    // merge the current list of non parent selector elements
+                    // on to the current list of selectors to add
+                    mergeElementsOnToSelectors(currentElements, newSelectors);
+
+                    var nestedPaths = [], replaced, replacedNewSelectors = [];
+                    replaced = replaceParentSelector(nestedPaths, context, nestedSelector);
+                    hadParentSelector = hadParentSelector || replaced;
+                    //the nestedPaths array should have only one member - replaceParentSelector does not multiply selectors
+                    for (k = 0; k < nestedPaths.length; k++) {
+                        var replacementSelector = createSelector(createParenthesis(nestedPaths[k], el), el);
+                        addAllReplacementsIntoPath(newSelectors, [replacementSelector], el, inSelector, replacedNewSelectors);
                     }
-                    selectorsMultiplied.push(sel);
+                    newSelectors = replacedNewSelectors;
+                    currentElements = [];
+
+                } else {
+                    currentElements.push(el);
                 }
-                else {
-                    // and the parent selectors
-                    for (k = 0; k < context.length; k++) {
-                        parentSel = context[k];
-                        // We need to put the current selectors
-                        // then join the last selector's elements on to the parents selectors
-
-                        // our new selector path
-                        newSelectorPath = [];
-                        // selectors from the parent after the join
-                        afterParentJoin = [];
-                        newJoinedSelectorEmpty = true;
-
-                        //construct the joined selector - if & is the first thing this will be empty,
-                        // if not newJoinedSelector will be the last set of elements in the selector
+
+            } else {
+                hadParentSelector = true;
+                // the new list of selectors to add
+                selectorsMultiplied = [];
+
+                // merge the current list of non parent selector elements
+                // on to the current list of selectors to add
+                mergeElementsOnToSelectors(currentElements, newSelectors);
+
+                // loop through our current selectors
+                for (j = 0; j < newSelectors.length; j++) {
+                    sel = newSelectors[j];
+                    // if we don't have any parent paths, the & might be in a mixin so that it can be used
+                    // whether there are parents or not
+                    if (context.length === 0) {
+                        // the combinator used on el should now be applied to the next element instead so that
+                        // it is not lost
                         if (sel.length > 0) {
-                            newSelectorPath = sel.slice(0);
-                            lastSelector = newSelectorPath.pop();
-                            newJoinedSelector = selector.createDerived(lastSelector.elements.slice(0));
-                            newJoinedSelectorEmpty = false;
+                            sel[0].elements.push(new Element(el.combinator, '', el.index, el.currentFileInfo));
                         }
-                        else {
-                            newJoinedSelector = selector.createDerived([]);
+                        selectorsMultiplied.push(sel);
+                    }
+                    else {
+                        // and the parent selectors
+                        for (k = 0; k < context.length; k++) {
+                            // We need to put the current selectors
+                            // then join the last selector's elements on to the parents selectors
+                            var newSelectorPath = addReplacementIntoPath(sel, context[k], el, inSelector);
+                            // add that to our new set of selectors
+                            selectorsMultiplied.push(newSelectorPath);
                         }
+                    }
+                }
 
-                        //put together the parent selectors after the join
-                        if (parentSel.length > 1) {
-                            afterParentJoin = afterParentJoin.concat(parentSel.slice(1));
-                        }
+                // our new selectors has been multiplied, so reset the state
+                newSelectors = selectorsMultiplied;
+                currentElements = [];
+            }
+        }
 
-                        if (parentSel.length > 0) {
-                            newJoinedSelectorEmpty = false;
-
-                            // /deep/ is a combinator that is valid without anything in front of it
-                            // so if the & does not have a combinator that is "" or " " then
-                            // and there is a combinator on the parent, then grab that.
-                            // this also allows + a { & .b { .a & { ... though not sure why you would want to do that
-                            var combinator = el.combinator,
-                                parentEl = parentSel[0].elements[0];
-                            if (combinator.emptyOrWhitespace && !parentEl.combinator.emptyOrWhitespace) {
-                                combinator = parentEl.combinator;
-                            }
-                            // join the elements so far with the first part of the parent
-                            newJoinedSelector.elements.push(new Element(combinator, parentEl.value, el.index, el.currentFileInfo));
-                            newJoinedSelector.elements = newJoinedSelector.elements.concat(parentSel[0].elements.slice(1));
-                        }
+        // if we have any elements left over (e.g. .a& .b == .b)
+        // add them on to all the current selectors
+        mergeElementsOnToSelectors(currentElements, newSelectors);
 
-                        if (!newJoinedSelectorEmpty) {
-                            // now add the joined selector
-                            newSelectorPath.push(newJoinedSelector);
-                        }
+        for (i = 0; i < newSelectors.length; i++) {
+            if (newSelectors[i].length > 0) {
+                paths.push(newSelectors[i]);
+            }
+        }
 
-                        // and the rest of the parent
-                        newSelectorPath = newSelectorPath.concat(afterParentJoin);
+        return hadParentSelector;
+    }
 
-                        // add that to our new set of selectors
-                        selectorsMultiplied.push(newSelectorPath);
-                    }
-                }
+    // joins selector path from `beginningPath` with selector path in `addPath`
+    // `replacedElement` contains element that is being replaced by `addPath`
+    // returns concatenated path
+    function addReplacementIntoPath(beginningPath, addPath, replacedElement, originalSelector) {
+        var newSelectorPath, lastSelector, newJoinedSelector;
+        // our new selector path
+        newSelectorPath = [];
+
+        //construct the joined selector - if & is the first thing this will be empty,
+        // if not newJoinedSelector will be the last set of elements in the selector
+        if (beginningPath.length > 0) {
+            newSelectorPath = beginningPath.slice(0);
+            lastSelector = newSelectorPath.pop();
+            newJoinedSelector = originalSelector.createDerived(lastSelector.elements.slice(0));
+        }
+        else {
+            newJoinedSelector = originalSelector.createDerived([]);
+        }
+
+        if (addPath.length > 0) {
+            // /deep/ is a combinator that is valid without anything in front of it
+            // so if the & does not have a combinator that is "" or " " then
+            // and there is a combinator on the parent, then grab that.
+            // this also allows + a { & .b { .a & { ... though not sure why you would want to do that
+            var combinator = replacedElement.combinator, parentEl = addPath[0].elements[0];
+            if (combinator.emptyOrWhitespace && !parentEl.combinator.emptyOrWhitespace) {
+                combinator = parentEl.combinator;
             }
+            // join the elements so far with the first part of the parent
+            newJoinedSelector.elements.push(new Element(combinator, parentEl.value, replacedElement.index, replacedElement.currentFileInfo));
+            newJoinedSelector.elements = newJoinedSelector.elements.concat(addPath[0].elements.slice(1));
+        }
 
-            // our new selectors has been multiplied, so reset the state
-            newSelectors = selectorsMultiplied;
-            currentElements = [];
+        // now add the joined selector - but only if it is not empty
+        if (newJoinedSelector.elements.length !== 0) {
+            newSelectorPath.push(newJoinedSelector);
         }
-    }
 
-    // if we have any elements left over (e.g. .a& .b == .b)
-    // add them on to all the current selectors
-    if (currentElements.length > 0) {
-        this.mergeElementsOnToSelectors(currentElements, newSelectors);
+        //put together the parent selectors after the join (e.g. the rest of the parent)
+        if (addPath.length > 1) {
+            newSelectorPath = newSelectorPath.concat(addPath.slice(1));
+        }
+        return newSelectorPath;
     }
 
-    for (i = 0; i < newSelectors.length; i++) {
-        if (newSelectors[i].length > 0) {
-            paths.push(newSelectors[i]);
+    // joins selector path from `beginningPath` with every selector path in `addPaths` array
+    // `replacedElement` contains element that is being replaced by `addPath`
+    // returns array with all concatenated paths
+    function addAllReplacementsIntoPath( beginningPath, addPaths, replacedElement, originalSelector, result) {
+        var j;
+        for (j = 0; j < beginningPath.length; j++) {
+            var newSelectorPath = addReplacementIntoPath(beginningPath[j], addPaths, replacedElement, originalSelector);
+            result.push(newSelectorPath);
         }
+        return result;
     }
-};
-Ruleset.prototype.mergeElementsOnToSelectors = function(elements, selectors) {
-    var i, sel;
 
-    if (selectors.length === 0) {
-        selectors.push([ new Selector(elements) ]);
-        return;
+    function mergeElementsOnToSelectors(elements, selectors) {
+        var i, sel;
+
+        if (elements.length === 0) {
+            return ;
+        }
+        if (selectors.length === 0) {
+            selectors.push([ new Selector(elements) ]);
+            return;
+        }
+
+        for (i = 0; i < selectors.length; i++) {
+            sel = selectors[i];
+
+            // if the previous thing in sel is a parent this needs to join on to it
+            if (sel.length > 0) {
+                sel[sel.length - 1] = sel[sel.length - 1].createDerived(sel[sel.length - 1].elements.concat(elements));
+            }
+            else {
+                sel.push(new Selector(elements));
+            }
+        }
     }
 
-    for (i = 0; i < selectors.length; i++) {
-        sel = selectors[i];
+    // joinSelector code follows
+    var i, newPaths, hadParentSelector;
+
+    newPaths = [];
+    hadParentSelector = replaceParentSelector(newPaths, context, selector);
 
-        // if the previous thing in sel is a parent this needs to join on to it
-        if (sel.length > 0) {
-            sel[sel.length - 1] = sel[sel.length - 1].createDerived(sel[sel.length - 1].elements.concat(elements));
+    if (!hadParentSelector) {
+        if (context.length > 0) {
+            newPaths = [];
+            for (i = 0; i < context.length; i++) {
+                newPaths.push(context[i].concat(selector));
+            }
         }
         else {
-            sel.push(new Selector(elements));
+            newPaths = [[selector]];
         }
     }
+
+    for (i = 0; i < newPaths.length; i++) {
+        paths.push(newPaths[i]);
+    }
+
 };
 module.exports = Ruleset;
 
-},{"../contexts":10,"../functions/default":19,"./debug-info":51,"./element":55,"./node":67,"./rule":71,"./selector":74}],74:[function(require,module,exports){
+},{"../contexts":10,"../functions/default":19,"./debug-info":51,"./element":55,"./node":67,"./paren":69,"./rule":71,"./selector":74}],74:[function(require,module,exports){
 var Node = require("./node");
 
 var Selector = function (elements, extendList, condition, index, currentFileInfo, isReferenced) {
@@ -7664,8 +7770,9 @@ Selector.prototype.match = function (other) {
     return olen; // return number of matched elements
 };
 Selector.prototype.CacheElements = function() {
-    if (this._elements)
+    if (this._elements) {
         return;
+    }
 
     var elements = this.elements.map( function(v) {
         return v.combinator.value + (v.value.value || v.value);
@@ -7882,7 +7989,7 @@ URL.prototype.eval = function (context) {
             context.isPathRelative(val.value)) {
 
             if (!val.quote) {
-                rootpath = rootpath.replace(/[\(\)'"\s]/g, function(match) { return "\\"+match; });
+                rootpath = rootpath.replace(/[\(\)'"\s]/g, function(match) { return "\\" + match; });
             }
             val.value = rootpath + val.value;
         }
@@ -7936,7 +8043,7 @@ Value.prototype.genCSS = function (context, output) {
     var i;
     for(i = 0; i < this.value.length; i++) {
         this.value[i].genCSS(context, output);
-        if (i+1 < this.value.length) {
+        if (i + 1 < this.value.length) {
             output.add((context && context.compress) ? ',' : ', ');
         }
     }
@@ -7973,7 +8080,7 @@ Variable.prototype.eval = function (context) {
         var v = frame.variable(name);
         if (v) {
             if (v.important) {
-                var importantScope = context.importantScope[context.importantScope.length-1];
+                var importantScope = context.importantScope[context.importantScope.length - 1];
                 importantScope.important = v.important;
             }
             return v.value.eval(context);
@@ -8084,7 +8191,7 @@ ExtendFinderVisitor.prototype = {
                 extend.findSelfSelectors(selectorPath);
                 extend.ruleset = rulesetNode;
                 if (j === 0) { extend.firstExtendOnThisSelectorPath = true; }
-                this.allExtendsStack[this.allExtendsStack.length-1].push(extend);
+                this.allExtendsStack[this.allExtendsStack.length - 1].push(extend);
             }
         }
 
@@ -8139,21 +8246,22 @@ ProcessExtendsVisitor.prototype = {
 
                 if(!indicies[extend.index + ' ' + selector]) {
                     indicies[extend.index + ' ' + selector] = true;
-                    logger.warn("extend '"+selector+"' has no matches");
+                    logger.warn("extend '" + selector + "' has no matches");
                 }
             });
     },
     doExtendChaining: function (extendsList, extendsListTarget, iterationCount) {
         //
-        // chaining is different from normal extension.. if we extend an extend then we are not just copying, altering and pasting
-        // the selector we would do normally, but we are also adding an extend with the same target selector
+        // chaining is different from normal extension.. if we extend an extend then we are not just copying, altering
+        // and pasting the selector we would do normally, but we are also adding an extend with the same target selector
         // this means this new extend can then go and alter other extends
         //
         // this method deals with all the chaining work - without it, extend is flat and doesn't work on other extend selectors
-        // this is also the most expensive.. and a match on one selector can cause an extension of a selector we had already processed if
-        // we look at each selector at a time, as is done in visitRuleset
+        // this is also the most expensive.. and a match on one selector can cause an extension of a selector we had already
+        // processed if we look at each selector at a time, as is done in visitRuleset
 
-        var extendIndex, targetExtendIndex, matches, extendsToAdd = [], newSelector, extendVisitor = this, selectorPath, extend, targetExtend, newExtend;
+        var extendIndex, targetExtendIndex, matches, extendsToAdd = [], newSelector, extendVisitor = this, selectorPath,
+            extend, targetExtend, newExtend;
 
         iterationCount = iterationCount || 0;
 
@@ -8191,7 +8299,7 @@ ProcessExtendsVisitor.prototype = {
                         newExtend.selfSelectors = newSelector;
 
                         // add the extend onto the list of extends for that selector
-                        newSelector[newSelector.length-1].extendList = [newExtend];
+                        newSelector[newSelector.length - 1].extendList = [newExtend];
 
                         // record that we need to add it.
                         extendsToAdd.push(newExtend);
@@ -8225,11 +8333,13 @@ ProcessExtendsVisitor.prototype = {
                     selectorTwo = extendsToAdd[0].selector.toCSS();
                 }
                 catch(e) {}
-                throw {message: "extend circular reference detected. One of the circular extends is currently:"+selectorOne+":extend(" + selectorTwo+")"};
+                throw { message: "extend circular reference detected. One of the circular extends is currently:" +
+                    selectorOne + ":extend(" + selectorTwo + ")"};
             }
 
-            // now process the new extends on the existing rules so that we can handle a extending b extending c ectending d extending e...
-            return extendsToAdd.concat(extendVisitor.doExtendChaining(extendsToAdd, extendsListTarget, iterationCount+1));
+            // now process the new extends on the existing rules so that we can handle a extending b extending c extending
+            // d extending e...
+            return extendsToAdd.concat(extendVisitor.doExtendChaining(extendsToAdd, extendsListTarget, iterationCount + 1));
         } else {
             return extendsToAdd;
         }
@@ -8247,7 +8357,8 @@ ProcessExtendsVisitor.prototype = {
         if (rulesetNode.root) {
             return;
         }
-        var matches, pathIndex, extendIndex, allExtends = this.allExtendsStack[this.allExtendsStack.length-1], selectorsToAdd = [], extendVisitor = this, selectorPath;
+        var matches, pathIndex, extendIndex, allExtends = this.allExtendsStack[this.allExtendsStack.length - 1],
+            selectorsToAdd = [], extendVisitor = this, selectorPath;
 
         // look at each selector path in the ruleset, find any extend matches and then copy, find and replace
 
@@ -8257,7 +8368,7 @@ ProcessExtendsVisitor.prototype = {
 
                 // extending extends happens initially, before the main pass
                 if (rulesetNode.extendOnEveryPath) { continue; }
-                var extendList = selectorPath[selectorPath.length-1].extendList;
+                var extendList = selectorPath[selectorPath.length - 1].extendList;
                 if (extendList && extendList.length) { continue; }
 
                 matches = this.findMatch(allExtends[extendIndex], selectorPath);
@@ -8294,15 +8405,16 @@ ProcessExtendsVisitor.prototype = {
 
                 // if we allow elements before our match we can add a potential match every time. otherwise only at the first element.
                 if (extend.allowBefore || (haystackSelectorIndex === 0 && hackstackElementIndex === 0)) {
-                    potentialMatches.push({pathIndex: haystackSelectorIndex, index: hackstackElementIndex, matched: 0, initialCombinator: haystackElement.combinator});
+                    potentialMatches.push({pathIndex: haystackSelectorIndex, index: hackstackElementIndex, matched: 0,
+                        initialCombinator: haystackElement.combinator});
                 }
 
                 for(i = 0; i < potentialMatches.length; i++) {
                     potentialMatch = potentialMatches[i];
 
                     // selectors add " " onto the first element. When we use & it joins the selectors together, but if we don't
-                    // then each selector in haystackSelectorPath has a space before it added in the toCSS phase. so we need to work out
-                    // what the resulting combinator will be
+                    // then each selector in haystackSelectorPath has a space before it added in the toCSS phase. so we need to
+                    // work out what the resulting combinator will be
                     targetCombinator = haystackElement.combinator.value;
                     if (targetCombinator === '' && hackstackElementIndex === 0) {
                         targetCombinator = ' ';
@@ -8320,7 +8432,8 @@ ProcessExtendsVisitor.prototype = {
                     if (potentialMatch) {
                         potentialMatch.finished = potentialMatch.matched === needleElements.length;
                         if (potentialMatch.finished &&
-                            (!extend.allowAfter && (hackstackElementIndex+1 < hackstackSelector.elements.length || haystackSelectorIndex+1 < haystackSelectorPath.length))) {
+                            (!extend.allowAfter &&
+                                (hackstackElementIndex + 1 < hackstackSelector.elements.length || haystackSelectorIndex + 1 < haystackSelectorPath.length))) {
                             potentialMatch = null;
                         }
                     }
@@ -8366,7 +8479,7 @@ ProcessExtendsVisitor.prototype = {
             if (!(elementValue2 instanceof tree.Selector) || elementValue1.elements.length !== elementValue2.elements.length) {
                 return false;
             }
-            for(var i = 0; i <elementValue1.elements.length; i++) {
+            for(var i = 0; i  < elementValue1.elements.length; i++) {
                 if (elementValue1.elements[i].combinator.value !== elementValue2.elements[i].combinator.value) {
                     if (i !== 0 || (elementValue1.elements[i].combinator.value || ' ') !== (elementValue2.elements[i].combinator.value || ' ')) {
                         return false;
@@ -8404,7 +8517,8 @@ ProcessExtendsVisitor.prototype = {
             );
 
             if (match.pathIndex > currentSelectorPathIndex && currentSelectorPathElementIndex > 0) {
-                path[path.length - 1].elements = path[path.length - 1].elements.concat(selectorPath[currentSelectorPathIndex].elements.slice(currentSelectorPathElementIndex));
+                path[path.length - 1].elements = path[path.length - 1]
+                    .elements.concat(selectorPath[currentSelectorPathIndex].elements.slice(currentSelectorPathElementIndex));
                 currentSelectorPathElementIndex = 0;
                 currentSelectorPathIndex++;
             }
@@ -8433,7 +8547,8 @@ ProcessExtendsVisitor.prototype = {
         }
 
         if (currentSelectorPathIndex < selectorPath.length && currentSelectorPathElementIndex > 0) {
-            path[path.length - 1].elements = path[path.length - 1].elements.concat(selectorPath[currentSelectorPathIndex].elements.slice(currentSelectorPathElementIndex));
+            path[path.length - 1].elements = path[path.length - 1]
+                .elements.concat(selectorPath[currentSelectorPathIndex].elements.slice(currentSelectorPathElementIndex));
             currentSelectorPathIndex++;
         }
 
@@ -8444,7 +8559,7 @@ ProcessExtendsVisitor.prototype = {
     visitRulesetOut: function (rulesetNode) {
     },
     visitMedia: function (mediaNode, visitArgs) {
-        var newAllExtends = mediaNode.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length-1]);
+        var newAllExtends = mediaNode.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length - 1]);
         newAllExtends = newAllExtends.concat(this.doExtendChaining(newAllExtends, mediaNode.allExtends));
         this.allExtendsStack.push(newAllExtends);
     },
@@ -8454,7 +8569,7 @@ ProcessExtendsVisitor.prototype = {
         this.allExtendsStack.length = lastIndex;
     },
     visitDirective: function (directiveNode, visitArgs) {
-        var newAllExtends = directiveNode.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length-1]);
+        var newAllExtends = directiveNode.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length - 1]);
         newAllExtends = newAllExtends.concat(this.doExtendChaining(newAllExtends, directiveNode.allExtends));
         this.allExtendsStack.push(newAllExtends);
     },
@@ -8610,7 +8725,8 @@ ImportVisitor.prototype = {
             var onImported = this.onImported.bind(this, evaldImportNode, context),
                 sequencedOnImported = this._sequencer.addImport(onImported);
 
-            this._importer.push(evaldImportNode.getPath(), tryAppendLessExtension, evaldImportNode.currentFileInfo, evaldImportNode.options, sequencedOnImported);
+            this._importer.push(evaldImportNode.getPath(), tryAppendLessExtension, evaldImportNode.currentFileInfo,
+                evaldImportNode.options, sequencedOnImported);
         } else {
             this.importCount--;
             if (this.isFinished) {
@@ -8814,7 +8930,7 @@ ToCSSVisitor.prototype = {
             // be considered illegal css as it has to be on the first line
             if (this.charset) {
                 if (directiveNode.debugInfo) {
-                    var comment = new tree.Comment("/* " + directiveNode.toCSS(this._context).replace(/\n/g, "")+" */\n");
+                    var comment = new tree.Comment("/* " + directiveNode.toCSS(this._context).replace(/\n/g, "") + " */\n");
                     comment.debugInfo = directiveNode.debugInfo;
                     return this._visitor.visit(comment);
                 }
@@ -8838,7 +8954,7 @@ ToCSSVisitor.prototype = {
             }
 
             //the directive was not directly referenced
-            for (var r = 0; r<directiveNode.rules.rules.length; r++) {
+            for (var r = 0; r < directiveNode.rules.rules.length; r++) {
                 var rule = directiveNode.rules.rules[r];
                 if (rule.getIsReferenced && rule.getIsReferenced()) {
                     //the directive contains something that was referenced (likely by extend)
@@ -8853,8 +8969,9 @@ ToCSSVisitor.prototype = {
             //was referenced. Therefore it must not be shown in output.
             return ;
         } else {
-            if (!directiveNode.getIsReferenced())
+            if (!directiveNode.getIsReferenced()) {
                 return;
+            }
         }
         return directiveNode;
     },
@@ -9015,7 +9132,7 @@ ToCSSVisitor.prototype = {
                 var spacedGroups = [];
                 var lastSpacedGroup = [];
                 parts.map(function (p) {
-                if (p.merge==="+") {
+                if (p.merge === "+") {
                     if (lastSpacedGroup.length > 0) {
                             spacedGroups.push(toExpression(lastSpacedGroup));
                         }
diff --git a/dist/less.min.js b/dist/less.min.js
index fa5dd8b..7a2e684 100644
--- a/dist/less.min.js
+++ b/dist/less.min.js
@@ -1,5 +1,5 @@
 /*!
- * Less - Leaner CSS v2.3.0
+ * Less - Leaner CSS v2.3.1
  * http://lesscss.org
  *
  * Copyright (c) 2009-2015, Alexis Sellier <self at cloudhead.net>
@@ -11,7 +11,7 @@
  */
 
 !function(a){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=a();else if("function"==typeof define&&define.amd)define([],a);else{var b;"undefined"!=typeof window?b=window:"undefined"!=typeof global?b=global:"undefined"!=typeof self&&(b=self),b.less=a()}}(function(){return function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);var j=new Error("Cannot find module '"+g+"'");throw j.co [...]
-if(c="string"==typeof c.value?c.value:c,"string"!=typeof c)throw{type:"Argument",message:"Second argument to isunit should be a unit or a string."};return a instanceof d&&a.unit.is(c)?b.True:b.False};j.addMultiple({isruleset:function(a){return k(a,c)},iscolor:function(a){return k(a,e)},isnumber:function(a){return k(a,d)},isstring:function(a){return k(a,f)},iskeyword:function(a){return k(a,b)},isurl:function(a){return k(a,h)},ispixel:function(a){return l(a,"px")},ispercentage:function(a){ [...]
-},d.prototype.eval=function(a){return this.value.eval?new d(this.value.eval(a)):this},d.prototype.genCSS=function(a,b){b.add("alpha(opacity="),this.value.genCSS?this.value.genCSS(a,b):b.add(this.value),b.add(")")},b.exports=d},{"./node":67}],43:[function(a,b){var c=a("./node"),d=function(a,b,c,d,e){this.value=a,this.index=b,this.mapLines=d,this.currentFileInfo=c,this.rulesetLike="undefined"==typeof e?!1:e};d.prototype=new c,d.prototype.type="Anonymous",d.prototype.eval=function(){return  [...]
-return g instanceof f?g.value:g.toCSS()};return d=b(d,/`([^`]+)`/g,g),d=b(d,/@\{([\w-]+)\}/g,h),new f(this.quote+d+this.quote,d,this.escaped,this.index,this.currentFileInfo)},f.prototype.compare=function(a){return"Quoted"!==a.type||this.escaped||a.escaped?a.toCSS&&this.toCSS()===a.toCSS()?0:void 0:c.numericCompare(this.value,a.value)},b.exports=f},{"./js-eval-node":61,"./node":67,"./variable":79}],71:[function(a,b){function c(a,b){var c,d="",e=b.length,f={add:function(a){d+=a}};for(c=0;e [...]
-},d.cwd=function(){return"/"},d.chdir=function(){throw new Error("process.chdir is not supported")}},{}],89:[function(a,b){"use strict";function c(a){function b(a){return null===i?void k.push(a):void f(function(){var b=i?a.onFulfilled:a.onRejected;if(null===b)return void(i?a.resolve:a.reject)(j);var c;try{c=b(j)}catch(d){return void a.reject(d)}a.resolve(c)})}function c(a){try{if(a===l)throw new TypeError("A promise cannot be resolved with itself.");if(a&&("object"==typeof a||"function"= [...]
\ No newline at end of file
+if(c="string"==typeof c.value?c.value:c,"string"!=typeof c)throw{type:"Argument",message:"Second argument to isunit should be a unit or a string."};return a instanceof d&&a.unit.is(c)?b.True:b.False};j.addMultiple({isruleset:function(a){return k(a,c)},iscolor:function(a){return k(a,e)},isnumber:function(a){return k(a,d)},isstring:function(a){return k(a,f)},iskeyword:function(a){return k(a,b)},isurl:function(a){return k(a,h)},ispixel:function(a){return l(a,"px")},ispercentage:function(a){ [...]
+},d.prototype.eval=function(a){return this.value.eval?new d(this.value.eval(a)):this},d.prototype.genCSS=function(a,b){b.add("alpha(opacity="),this.value.genCSS?this.value.genCSS(a,b):b.add(this.value),b.add(")")},b.exports=d},{"./node":67}],43:[function(a,b){var c=a("./node"),d=function(a,b,c,d,e){this.value=a,this.index=b,this.mapLines=d,this.currentFileInfo=c,this.rulesetLike="undefined"==typeof e?!1:e};d.prototype=new c,d.prototype.type="Anonymous",d.prototype.eval=function(){return  [...]
+return g instanceof f?g.value:g.toCSS()};return d=b(d,/`([^`]+)`/g,g),d=b(d,/@\{([\w-]+)\}/g,h),new f(this.quote+d+this.quote,d,this.escaped,this.index,this.currentFileInfo)},f.prototype.compare=function(a){return"Quoted"!==a.type||this.escaped||a.escaped?a.toCSS&&this.toCSS()===a.toCSS()?0:void 0:c.numericCompare(this.value,a.value)},b.exports=f},{"./js-eval-node":61,"./node":67,"./variable":79}],71:[function(a,b){function c(a,b){var c,d="",e=b.length,f={add:function(a){d+=a}};for(c=0;e [...]
+d.length=0,a.forEach(function(a){a()})});return f.observe(e,{attributes:!0}),function(a){d.length||e.setAttribute("yes","no"),d.push(a)}}return c?(window.addEventListener("message",function(a){var b=a.source;if((b===window||null===b)&&"process-tick"===a.data&&(a.stopPropagation(),d.length>0)){var c=d.shift();c()}},!0),function(a){d.push(a),window.postMessage("process-tick","*")}):function(a){setTimeout(a,0)}}(),d.title="browser",d.browser=!0,d.env={},d.argv=[],d.on=c,d.addListener=c,d.on [...]
\ No newline at end of file
diff --git a/lib/less/index.js b/lib/less/index.js
index 1b40fcc..d645e7a 100644
--- a/lib/less/index.js
+++ b/lib/less/index.js
@@ -2,7 +2,7 @@ module.exports = function(environment, fileManagers) {
     var SourceMapOutput, SourceMapBuilder, ParseTree, ImportManager, Environment;
 
     var less = {
-        version: [2, 3, 0],
+        version: [2, 3, 1],
         data: require('./data'),
         tree: require('./tree'),
         Environment: (Environment = require("./environment/environment")),
diff --git a/package.json b/package.json
index 1c9b06b..e2da2c8 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "less",
-  "version": "2.3.0",
+  "version": "2.3.1",
   "description": "Leaner CSS",
   "homepage": "http://lesscss.org",
   "author": {

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