less 2.6.0 → 2.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,12 @@
1
+ # 2.6.1
2
+
3
+ 2016-03-04
4
+
5
+ - Update Less.js dependencies
6
+ - Fix comments after named color regression
7
+ - use instanceof operator instead of class comparison optimization
8
+ - disallow whitespace in variable calls
9
+
1
10
  # 2.6.0
2
11
 
3
12
  2016-01-29
@@ -10,7 +19,7 @@
10
19
  - Fixed extend leaking through nested parent selector. #2586
11
20
  - Added "or" keyword and allowed arbitrary logical expression in guards
12
21
  - Fixing #2124 - Parsing Error "Unrecognised input" for color operations
13
- - Logical operator and now has higher precence then logical operator or.
22
+ - Logical operator ```and``` now has higher precedence than logical operator ```or```.
14
23
  - Allow unknown at-rules w/o {} block
15
24
 
16
25
  # 2.5.3
package/README.md CHANGED
@@ -4,12 +4,12 @@
4
4
 
5
5
  # [Less.js](http://lesscss.org)
6
6
 
7
- [![Join the chat at https://gitter.im/less/less.js](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/less/less.js?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
8
-
9
7
  > The **dynamic** stylesheet language. [http://lesscss.org](http://lesscss.org).
10
8
 
11
9
  This is the JavaScript, official, stable version of Less.
12
10
 
11
+ ###### :point_right: [![Join the chat at https://gitter.im/less/less.js](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/less/less.js?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) <sup>Chat with Less.js users</sup>
12
+
13
13
 
14
14
  ## Getting Started
15
15
 
package/dist/less.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Less - Leaner CSS v2.6.0
2
+ * Less - Leaner CSS v2.6.1
3
3
  * http://lesscss.org
4
4
  *
5
5
  * Copyright (c) 2009-2016, Alexis Sellier <self@cloudhead.net>
@@ -328,16 +328,6 @@ module.exports = function(window, less, options) {
328
328
  }
329
329
  }
330
330
 
331
- function error(e, rootHref) {
332
- if (!options.errorReporting || options.errorReporting === "html") {
333
- errorHTML(e, rootHref);
334
- } else if (options.errorReporting === "console") {
335
- errorConsole(e, rootHref);
336
- } else if (typeof options.errorReporting === 'function') {
337
- options.errorReporting("add", e, rootHref);
338
- }
339
- }
340
-
341
331
  function removeErrorHTML(path) {
342
332
  var node = window.document.getElementById('less-error-message:' + utils.extractId(path));
343
333
  if (node) {
@@ -387,6 +377,16 @@ module.exports = function(window, less, options) {
387
377
  less.logger.error(content);
388
378
  }
389
379
 
380
+ function error(e, rootHref) {
381
+ if (!options.errorReporting || options.errorReporting === "html") {
382
+ errorHTML(e, rootHref);
383
+ } else if (options.errorReporting === "console") {
384
+ errorConsole(e, rootHref);
385
+ } else if (typeof options.errorReporting === 'function') {
386
+ options.errorReporting("add", e, rootHref);
387
+ }
388
+ }
389
+
390
390
  return {
391
391
  add: error,
392
392
  remove: removeError
@@ -1472,6 +1472,9 @@ colorFunctions = {
1472
1472
  return colorFunctions.hsla(h, s, l, 1.0);
1473
1473
  },
1474
1474
  hsla: function (h, s, l, a) {
1475
+
1476
+ var m1, m2;
1477
+
1475
1478
  function hue(h) {
1476
1479
  h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h);
1477
1480
  if (h * 6 < 1) {
@@ -1491,8 +1494,8 @@ colorFunctions = {
1491
1494
  h = (number(h) % 360) / 360;
1492
1495
  s = clamp(number(s)); l = clamp(number(l)); a = clamp(number(a));
1493
1496
 
1494
- var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s;
1495
- var m1 = l * 2 - m2;
1497
+ m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s;
1498
+ m1 = l * 2 - m2;
1496
1499
 
1497
1500
  return colorFunctions.rgba(hue(h + 1 / 3) * 255,
1498
1501
  hue(h) * 255,
@@ -2451,7 +2454,7 @@ module.exports = function(environment, fileManagers) {
2451
2454
  var SourceMapOutput, SourceMapBuilder, ParseTree, ImportManager, Environment;
2452
2455
 
2453
2456
  var less = {
2454
- version: [2, 6, 0],
2457
+ version: [2, 6, 1],
2455
2458
  data: require('./data'),
2456
2459
  tree: require('./tree'),
2457
2460
  Environment: (Environment = require("./environment/environment")),
@@ -2817,6 +2820,74 @@ module.exports = function() {
2817
2820
  currentPos, // index of current chunk, in `input`
2818
2821
  parserInput = {};
2819
2822
 
2823
+ var CHARCODE_SPACE = 32,
2824
+ CHARCODE_TAB = 9,
2825
+ CHARCODE_LF = 10,
2826
+ CHARCODE_CR = 13,
2827
+ CHARCODE_PLUS = 43,
2828
+ CHARCODE_COMMA = 44,
2829
+ CHARCODE_FORWARD_SLASH = 47,
2830
+ CHARCODE_9 = 57;
2831
+
2832
+ function skipWhitespace(length) {
2833
+ var oldi = parserInput.i, oldj = j,
2834
+ curr = parserInput.i - currentPos,
2835
+ endIndex = parserInput.i + current.length - curr,
2836
+ mem = (parserInput.i += length),
2837
+ inp = input,
2838
+ c, nextChar, comment;
2839
+
2840
+ for (; parserInput.i < endIndex; parserInput.i++) {
2841
+ c = inp.charCodeAt(parserInput.i);
2842
+
2843
+ if (parserInput.autoCommentAbsorb && c === CHARCODE_FORWARD_SLASH) {
2844
+ nextChar = inp.charAt(parserInput.i + 1);
2845
+ if (nextChar === '/') {
2846
+ comment = {index: parserInput.i, isLineComment: true};
2847
+ var nextNewLine = inp.indexOf("\n", parserInput.i + 2);
2848
+ if (nextNewLine < 0) {
2849
+ nextNewLine = endIndex;
2850
+ }
2851
+ parserInput.i = nextNewLine;
2852
+ comment.text = inp.substr(comment.i, parserInput.i - comment.i);
2853
+ parserInput.commentStore.push(comment);
2854
+ continue;
2855
+ } else if (nextChar === '*') {
2856
+ var nextStarSlash = inp.indexOf("*/", parserInput.i + 2);
2857
+ if (nextStarSlash >= 0) {
2858
+ comment = {
2859
+ index: parserInput.i,
2860
+ text: inp.substr(parserInput.i, nextStarSlash + 2 - parserInput.i),
2861
+ isLineComment: false
2862
+ };
2863
+ parserInput.i += comment.text.length - 1;
2864
+ parserInput.commentStore.push(comment);
2865
+ continue;
2866
+ }
2867
+ }
2868
+ break;
2869
+ }
2870
+
2871
+ if ((c !== CHARCODE_SPACE) && (c !== CHARCODE_LF) && (c !== CHARCODE_TAB) && (c !== CHARCODE_CR)) {
2872
+ break;
2873
+ }
2874
+ }
2875
+
2876
+ current = current.slice(length + parserInput.i - mem + curr);
2877
+ currentPos = parserInput.i;
2878
+
2879
+ if (!current.length) {
2880
+ if (j < chunks.length - 1) {
2881
+ current = chunks[++j];
2882
+ skipWhitespace(0); // skip space at the beginning of a chunk
2883
+ return true; // things changed
2884
+ }
2885
+ parserInput.finished = true;
2886
+ }
2887
+
2888
+ return oldi !== parserInput.i || oldj !== j;
2889
+ }
2890
+
2820
2891
  parserInput.save = function() {
2821
2892
  currentPos = parserInput.i;
2822
2893
  saveStack.push( { current: current, i: parserInput.i, j: j });
@@ -2911,78 +2982,10 @@ module.exports = function() {
2911
2982
  return null;
2912
2983
  };
2913
2984
 
2914
- var CHARCODE_SPACE = 32,
2915
- CHARCODE_TAB = 9,
2916
- CHARCODE_LF = 10,
2917
- CHARCODE_CR = 13,
2918
- CHARCODE_PLUS = 43,
2919
- CHARCODE_COMMA = 44,
2920
- CHARCODE_FORWARD_SLASH = 47,
2921
- CHARCODE_9 = 57;
2922
-
2923
2985
  parserInput.autoCommentAbsorb = true;
2924
2986
  parserInput.commentStore = [];
2925
2987
  parserInput.finished = false;
2926
2988
 
2927
- var skipWhitespace = function(length) {
2928
- var oldi = parserInput.i, oldj = j,
2929
- curr = parserInput.i - currentPos,
2930
- endIndex = parserInput.i + current.length - curr,
2931
- mem = (parserInput.i += length),
2932
- inp = input,
2933
- c, nextChar, comment;
2934
-
2935
- for (; parserInput.i < endIndex; parserInput.i++) {
2936
- c = inp.charCodeAt(parserInput.i);
2937
-
2938
- if (parserInput.autoCommentAbsorb && c === CHARCODE_FORWARD_SLASH) {
2939
- nextChar = inp.charAt(parserInput.i + 1);
2940
- if (nextChar === '/') {
2941
- comment = {index: parserInput.i, isLineComment: true};
2942
- var nextNewLine = inp.indexOf("\n", parserInput.i + 2);
2943
- if (nextNewLine < 0) {
2944
- nextNewLine = endIndex;
2945
- }
2946
- parserInput.i = nextNewLine;
2947
- comment.text = inp.substr(comment.i, parserInput.i - comment.i);
2948
- parserInput.commentStore.push(comment);
2949
- continue;
2950
- } else if (nextChar === '*') {
2951
- var nextStarSlash = inp.indexOf("*/", parserInput.i + 2);
2952
- if (nextStarSlash >= 0) {
2953
- comment = {
2954
- index: parserInput.i,
2955
- text: inp.substr(parserInput.i, nextStarSlash + 2 - parserInput.i),
2956
- isLineComment: false
2957
- };
2958
- parserInput.i += comment.text.length - 1;
2959
- parserInput.commentStore.push(comment);
2960
- continue;
2961
- }
2962
- }
2963
- break;
2964
- }
2965
-
2966
- if ((c !== CHARCODE_SPACE) && (c !== CHARCODE_LF) && (c !== CHARCODE_TAB) && (c !== CHARCODE_CR)) {
2967
- break;
2968
- }
2969
- }
2970
-
2971
- current = current.slice(length + parserInput.i - mem + curr);
2972
- currentPos = parserInput.i;
2973
-
2974
- if (!current.length) {
2975
- if (j < chunks.length - 1) {
2976
- current = chunks[++j];
2977
- skipWhitespace(0); // skip space at the beginning of a chunk
2978
- return true; // things changed
2979
- }
2980
- parserInput.finished = true;
2981
- }
2982
-
2983
- return oldi !== parserInput.i || oldj !== j;
2984
- };
2985
-
2986
2989
  // Same as $(), but don't change the state of the parser,
2987
2990
  // just return the match.
2988
2991
  parserInput.peek = function(tok) {
@@ -3108,9 +3111,21 @@ var Parser = function Parser(context, imports, fileInfo) {
3108
3111
  var parsers,
3109
3112
  parserInput = getParserInput();
3110
3113
 
3114
+ function error(msg, type) {
3115
+ throw new LessError(
3116
+ {
3117
+ index: parserInput.i,
3118
+ filename: fileInfo.filename,
3119
+ type: type || 'Syntax',
3120
+ message: msg
3121
+ },
3122
+ imports
3123
+ );
3124
+ }
3125
+
3111
3126
  function expect(arg, msg, index) {
3112
3127
  // some older browsers return typeof 'function' for RegExp
3113
- var result = (Object.prototype.toString.call(arg) === '[object Function]') ? arg.call(parsers) : parserInput.$re(arg);
3128
+ var result = (arg instanceof Function) ? arg.call(parsers) : parserInput.$re(arg);
3114
3129
  if (result) {
3115
3130
  return result;
3116
3131
  }
@@ -3126,18 +3141,6 @@ var Parser = function Parser(context, imports, fileInfo) {
3126
3141
  error(msg || "expected '" + arg + "' got '" + parserInput.currentChar() + "'");
3127
3142
  }
3128
3143
 
3129
- function error(msg, type) {
3130
- throw new LessError(
3131
- {
3132
- index: parserInput.i,
3133
- filename: fileInfo.filename,
3134
- type: type || 'Syntax',
3135
- message: msg
3136
- },
3137
- imports
3138
- );
3139
- }
3140
-
3141
3144
  function getDebugInfo(index) {
3142
3145
  var filename = fileInfo.filename;
3143
3146
 
@@ -3392,26 +3395,6 @@ var Parser = function Parser(context, imports, fileInfo) {
3392
3395
  }
3393
3396
  },
3394
3397
 
3395
- namedColor: function () {
3396
- parserInput.save();
3397
- var autoCommentAbsorb = parserInput.autoCommentAbsorb;
3398
- parserInput.autoCommentAbsorb = false;
3399
- var k = parserInput.$re(/^[_A-Za-z-][_A-Za-z0-9-]*/);
3400
- parserInput.autoCommentAbsorb = autoCommentAbsorb;
3401
- if (!k) {
3402
- parserInput.forget();
3403
- return ;
3404
- }
3405
- var result = tree.Color.fromKeyword(k);
3406
- if (!result) {
3407
- parserInput.restore();
3408
- } else {
3409
- parserInput.forget();
3410
- return result;
3411
- }
3412
-
3413
- },
3414
-
3415
3398
  //
3416
3399
  // A function call
3417
3400
  //
@@ -3578,8 +3561,24 @@ var Parser = function Parser(context, imports, fileInfo) {
3578
3561
  }
3579
3562
  return new(tree.Color)(rgb[1], undefined, '#' + colorCandidateString);
3580
3563
  }
3564
+ },
3581
3565
 
3582
- return this.namedColor();
3566
+ colorKeyword: function () {
3567
+ parserInput.save();
3568
+ var autoCommentAbsorb = parserInput.autoCommentAbsorb;
3569
+ parserInput.autoCommentAbsorb = false;
3570
+ var k = parserInput.$re(/^[A-Za-z]+/);
3571
+ parserInput.autoCommentAbsorb = autoCommentAbsorb;
3572
+ if (!k) {
3573
+ parserInput.forget();
3574
+ return;
3575
+ }
3576
+ parserInput.restore();
3577
+ var color = tree.Color.fromKeyword(k);
3578
+ if (color) {
3579
+ parserInput.$str(k);
3580
+ return color;
3581
+ }
3583
3582
  },
3584
3583
 
3585
3584
  //
@@ -3658,7 +3657,7 @@ var Parser = function Parser(context, imports, fileInfo) {
3658
3657
  rulesetCall: function () {
3659
3658
  var name;
3660
3659
 
3661
- if (parserInput.currentChar() === '@' && (name = parserInput.$re(/^(@[\w-]+)\s*\(\s*\)\s*;/))) {
3660
+ if (parserInput.currentChar() === '@' && (name = parserInput.$re(/^(@[\w-]+)\(\s*\)\s*;/))) {
3662
3661
  return new tree.RulesetCall(name[1]);
3663
3662
  }
3664
3663
  },
@@ -4711,12 +4710,44 @@ var Parser = function Parser(context, imports, fileInfo) {
4711
4710
  }
4712
4711
  },
4713
4712
  parenthesisCondition: function () {
4713
+ function tryConditionFollowedByParenthesis(me) {
4714
+ var body;
4715
+ parserInput.save();
4716
+ body = me.condition();
4717
+ if (!body) {
4718
+ parserInput.restore();
4719
+ return ;
4720
+ }
4721
+ if (!parserInput.$char(')')) {
4722
+ parserInput.restore();
4723
+ return ;
4724
+ }
4725
+ parserInput.forget();
4726
+ return body;
4727
+ }
4728
+
4714
4729
  var body;
4730
+ parserInput.save();
4715
4731
  if (!parserInput.$str("(")) {
4732
+ parserInput.restore();
4716
4733
  return ;
4717
4734
  }
4718
- body = this.condition() || this.atomicCondition();
4719
- expectChar(')');
4735
+ body = tryConditionFollowedByParenthesis(this);
4736
+ if (body) {
4737
+ parserInput.forget();
4738
+ return body;
4739
+ }
4740
+
4741
+ body = this.atomicCondition();
4742
+ if (!body) {
4743
+ parserInput.restore();
4744
+ return ;
4745
+ }
4746
+ if (!parserInput.$char(')')) {
4747
+ parserInput.restore("expected ')' got '" + parserInput.currentChar() + "'");
4748
+ return ;
4749
+ }
4750
+ parserInput.forget();
4720
4751
  return body;
4721
4752
  },
4722
4753
  atomicCondition: function () {
@@ -4773,8 +4804,8 @@ var Parser = function Parser(context, imports, fileInfo) {
4773
4804
  }
4774
4805
 
4775
4806
  var o = this.sub() || entities.dimension() ||
4776
- entities.variable() ||
4777
- entities.call() || entities.color();
4807
+ entities.color() || entities.variable() ||
4808
+ entities.call() || entities.colorKeyword();
4778
4809
 
4779
4810
  if (negate) {
4780
4811
  o.parensInOp = true;
@@ -7144,7 +7175,7 @@ Definition.prototype.makeImportant = function() {
7144
7175
  return r;
7145
7176
  }
7146
7177
  });
7147
- var result = new Definition (this.name, this.params, rules, this.condition, this.variadic, this.frames);
7178
+ var result = new Definition(this.name, this.params, rules, this.condition, this.variadic, this.frames);
7148
7179
  return result;
7149
7180
  };
7150
7181
  Definition.prototype.eval = function (context) {
@@ -8065,6 +8096,91 @@ Ruleset.prototype.joinSelector = function (paths, context, selector) {
8065
8096
  return selector;
8066
8097
  }
8067
8098
 
8099
+ // joins selector path from `beginningPath` with selector path in `addPath`
8100
+ // `replacedElement` contains element that is being replaced by `addPath`
8101
+ // returns concatenated path
8102
+ function addReplacementIntoPath(beginningPath, addPath, replacedElement, originalSelector) {
8103
+ var newSelectorPath, lastSelector, newJoinedSelector;
8104
+ // our new selector path
8105
+ newSelectorPath = [];
8106
+
8107
+ //construct the joined selector - if & is the first thing this will be empty,
8108
+ // if not newJoinedSelector will be the last set of elements in the selector
8109
+ if (beginningPath.length > 0) {
8110
+ newSelectorPath = beginningPath.slice(0);
8111
+ lastSelector = newSelectorPath.pop();
8112
+ newJoinedSelector = originalSelector.createDerived(lastSelector.elements.slice(0));
8113
+ }
8114
+ else {
8115
+ newJoinedSelector = originalSelector.createDerived([]);
8116
+ }
8117
+
8118
+ if (addPath.length > 0) {
8119
+ // /deep/ is a combinator that is valid without anything in front of it
8120
+ // so if the & does not have a combinator that is "" or " " then
8121
+ // and there is a combinator on the parent, then grab that.
8122
+ // this also allows + a { & .b { .a & { ... though not sure why you would want to do that
8123
+ var combinator = replacedElement.combinator, parentEl = addPath[0].elements[0];
8124
+ if (combinator.emptyOrWhitespace && !parentEl.combinator.emptyOrWhitespace) {
8125
+ combinator = parentEl.combinator;
8126
+ }
8127
+ // join the elements so far with the first part of the parent
8128
+ newJoinedSelector.elements.push(new Element(combinator, parentEl.value, replacedElement.index, replacedElement.currentFileInfo));
8129
+ newJoinedSelector.elements = newJoinedSelector.elements.concat(addPath[0].elements.slice(1));
8130
+ }
8131
+
8132
+ // now add the joined selector - but only if it is not empty
8133
+ if (newJoinedSelector.elements.length !== 0) {
8134
+ newSelectorPath.push(newJoinedSelector);
8135
+ }
8136
+
8137
+ //put together the parent selectors after the join (e.g. the rest of the parent)
8138
+ if (addPath.length > 1) {
8139
+ var restOfPath = addPath.slice(1);
8140
+ restOfPath = restOfPath.map(function (selector) {
8141
+ return selector.createDerived(selector.elements, []);
8142
+ });
8143
+ newSelectorPath = newSelectorPath.concat(restOfPath);
8144
+ }
8145
+ return newSelectorPath;
8146
+ }
8147
+
8148
+ // joins selector path from `beginningPath` with every selector path in `addPaths` array
8149
+ // `replacedElement` contains element that is being replaced by `addPath`
8150
+ // returns array with all concatenated paths
8151
+ function addAllReplacementsIntoPath( beginningPath, addPaths, replacedElement, originalSelector, result) {
8152
+ var j;
8153
+ for (j = 0; j < beginningPath.length; j++) {
8154
+ var newSelectorPath = addReplacementIntoPath(beginningPath[j], addPaths, replacedElement, originalSelector);
8155
+ result.push(newSelectorPath);
8156
+ }
8157
+ return result;
8158
+ }
8159
+
8160
+ function mergeElementsOnToSelectors(elements, selectors) {
8161
+ var i, sel;
8162
+
8163
+ if (elements.length === 0) {
8164
+ return ;
8165
+ }
8166
+ if (selectors.length === 0) {
8167
+ selectors.push([ new Selector(elements) ]);
8168
+ return;
8169
+ }
8170
+
8171
+ for (i = 0; i < selectors.length; i++) {
8172
+ sel = selectors[i];
8173
+
8174
+ // if the previous thing in sel is a parent this needs to join on to it
8175
+ if (sel.length > 0) {
8176
+ sel[sel.length - 1] = sel[sel.length - 1].createDerived(sel[sel.length - 1].elements.concat(elements));
8177
+ }
8178
+ else {
8179
+ sel.push(new Selector(elements));
8180
+ }
8181
+ }
8182
+ }
8183
+
8068
8184
  // replace all parent selectors inside `inSelector` by content of `context` array
8069
8185
  // resulting selectors are returned inside `paths` array
8070
8186
  // returns true if `inSelector` contained at least one parent selector
@@ -8185,91 +8301,6 @@ Ruleset.prototype.joinSelector = function (paths, context, selector) {
8185
8301
  return hadParentSelector;
8186
8302
  }
8187
8303
 
8188
- // joins selector path from `beginningPath` with selector path in `addPath`
8189
- // `replacedElement` contains element that is being replaced by `addPath`
8190
- // returns concatenated path
8191
- function addReplacementIntoPath(beginningPath, addPath, replacedElement, originalSelector) {
8192
- var newSelectorPath, lastSelector, newJoinedSelector;
8193
- // our new selector path
8194
- newSelectorPath = [];
8195
-
8196
- //construct the joined selector - if & is the first thing this will be empty,
8197
- // if not newJoinedSelector will be the last set of elements in the selector
8198
- if (beginningPath.length > 0) {
8199
- newSelectorPath = beginningPath.slice(0);
8200
- lastSelector = newSelectorPath.pop();
8201
- newJoinedSelector = originalSelector.createDerived(lastSelector.elements.slice(0));
8202
- }
8203
- else {
8204
- newJoinedSelector = originalSelector.createDerived([]);
8205
- }
8206
-
8207
- if (addPath.length > 0) {
8208
- // /deep/ is a combinator that is valid without anything in front of it
8209
- // so if the & does not have a combinator that is "" or " " then
8210
- // and there is a combinator on the parent, then grab that.
8211
- // this also allows + a { & .b { .a & { ... though not sure why you would want to do that
8212
- var combinator = replacedElement.combinator, parentEl = addPath[0].elements[0];
8213
- if (combinator.emptyOrWhitespace && !parentEl.combinator.emptyOrWhitespace) {
8214
- combinator = parentEl.combinator;
8215
- }
8216
- // join the elements so far with the first part of the parent
8217
- newJoinedSelector.elements.push(new Element(combinator, parentEl.value, replacedElement.index, replacedElement.currentFileInfo));
8218
- newJoinedSelector.elements = newJoinedSelector.elements.concat(addPath[0].elements.slice(1));
8219
- }
8220
-
8221
- // now add the joined selector - but only if it is not empty
8222
- if (newJoinedSelector.elements.length !== 0) {
8223
- newSelectorPath.push(newJoinedSelector);
8224
- }
8225
-
8226
- //put together the parent selectors after the join (e.g. the rest of the parent)
8227
- if (addPath.length > 1) {
8228
- var restOfPath = addPath.slice(1);
8229
- restOfPath = restOfPath.map(function (selector) {
8230
- return selector.createDerived(selector.elements, []);
8231
- });
8232
- newSelectorPath = newSelectorPath.concat(restOfPath);
8233
- }
8234
- return newSelectorPath;
8235
- }
8236
-
8237
- // joins selector path from `beginningPath` with every selector path in `addPaths` array
8238
- // `replacedElement` contains element that is being replaced by `addPath`
8239
- // returns array with all concatenated paths
8240
- function addAllReplacementsIntoPath( beginningPath, addPaths, replacedElement, originalSelector, result) {
8241
- var j;
8242
- for (j = 0; j < beginningPath.length; j++) {
8243
- var newSelectorPath = addReplacementIntoPath(beginningPath[j], addPaths, replacedElement, originalSelector);
8244
- result.push(newSelectorPath);
8245
- }
8246
- return result;
8247
- }
8248
-
8249
- function mergeElementsOnToSelectors(elements, selectors) {
8250
- var i, sel;
8251
-
8252
- if (elements.length === 0) {
8253
- return ;
8254
- }
8255
- if (selectors.length === 0) {
8256
- selectors.push([ new Selector(elements) ]);
8257
- return;
8258
- }
8259
-
8260
- for (i = 0; i < selectors.length; i++) {
8261
- sel = selectors[i];
8262
-
8263
- // if the previous thing in sel is a parent this needs to join on to it
8264
- if (sel.length > 0) {
8265
- sel[sel.length - 1] = sel[sel.length - 1].createDerived(sel[sel.length - 1].elements.concat(elements));
8266
- }
8267
- else {
8268
- sel.push(new Selector(elements));
8269
- }
8270
- }
8271
- }
8272
-
8273
8304
  function deriveSelector(visibilityInfo, deriveFrom) {
8274
8305
  var newSelector = deriveFrom.createDerived(deriveFrom.elements, deriveFrom.extendList, deriveFrom.evaldCondition);
8275
8306
  newSelector.copyVisibilityInfo(visibilityInfo);
@@ -8498,7 +8529,7 @@ Unit.prototype.map = function(callback) {
8498
8529
  }
8499
8530
  };
8500
8531
  Unit.prototype.usedUnits = function() {
8501
- var group, result = {}, mapUnit;
8532
+ var group, result = {}, mapUnit, groupName;
8502
8533
 
8503
8534
  mapUnit = function (atomicUnit) {
8504
8535
  /*jshint loopfunc:true */
@@ -8509,7 +8540,7 @@ Unit.prototype.usedUnits = function() {
8509
8540
  return atomicUnit;
8510
8541
  };
8511
8542
 
8512
- for (var groupName in unitConversions) {
8543
+ for (groupName in unitConversions) {
8513
8544
  if (unitConversions.hasOwnProperty(groupName)) {
8514
8545
  group = unitConversions[groupName];
8515
8546