less 3.0.0-pre.2 → 3.0.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.
Files changed (205) hide show
  1. package/.eslintrc.json +88 -0
  2. package/.github/stale.yml +17 -0
  3. package/.project +17 -0
  4. package/.settings/org.eclipse.buildship.core.prefs +2 -0
  5. package/.travis.yml +22 -3
  6. package/.vscode/launch.json +14 -0
  7. package/CHANGELOG.md +27 -0
  8. package/Gruntfile.js +191 -86
  9. package/README.md +5 -7
  10. package/appveyor.yml +9 -10
  11. package/bin/lessc +37 -50
  12. package/dist/less.js +1357 -1269
  13. package/dist/less.min.js +7 -7
  14. package/lib/less/contexts.js +20 -16
  15. package/lib/less/default-options.js +65 -0
  16. package/lib/less/environment/abstract-file-manager.js +13 -14
  17. package/lib/less/environment/abstract-plugin-loader.js +45 -36
  18. package/lib/less/environment/environment.js +5 -0
  19. package/lib/less/functions/boolean.js +15 -0
  20. package/lib/less/functions/color.js +54 -24
  21. package/lib/less/functions/data-uri.js +5 -2
  22. package/lib/less/functions/function-registry.js +1 -1
  23. package/lib/less/functions/index.js +2 -1
  24. package/lib/less/functions/number.js +2 -2
  25. package/lib/less/functions/string.js +2 -2
  26. package/lib/less/functions/svg.js +4 -4
  27. package/lib/less/import-manager.js +41 -29
  28. package/lib/less/index.js +28 -3
  29. package/lib/less/less-error.js +112 -13
  30. package/lib/less/parse.js +18 -15
  31. package/lib/less/parser/parser-input.js +4 -4
  32. package/lib/less/parser/parser.js +208 -114
  33. package/lib/less/plugin-manager.js +8 -33
  34. package/lib/less/render.js +6 -2
  35. package/lib/less/source-map-builder.js +3 -0
  36. package/lib/less/source-map-output.js +13 -8
  37. package/lib/less/transform-tree.js +2 -2
  38. package/lib/less/tree/anonymous.js +4 -1
  39. package/lib/less/tree/atrule.js +7 -6
  40. package/lib/less/tree/call.js +25 -3
  41. package/lib/less/tree/color.js +2 -2
  42. package/lib/less/tree/debug-info.js +1 -1
  43. package/lib/less/tree/declaration.js +6 -5
  44. package/lib/less/tree/dimension.js +4 -1
  45. package/lib/less/tree/extend.js +2 -2
  46. package/lib/less/tree/import.js +17 -9
  47. package/lib/less/tree/index.js +3 -7
  48. package/lib/less/tree/js-eval-node.js +1 -1
  49. package/lib/less/tree/media.js +3 -14
  50. package/lib/less/tree/mixin-definition.js +3 -3
  51. package/lib/less/tree/node.js +9 -6
  52. package/lib/less/tree/operation.js +1 -1
  53. package/lib/less/tree/property.js +70 -0
  54. package/lib/less/tree/quoted.js +11 -10
  55. package/lib/less/tree/ruleset.js +115 -71
  56. package/lib/less/tree/selector.js +38 -23
  57. package/lib/less/tree/unit.js +1 -1
  58. package/lib/less/tree/value.js +6 -1
  59. package/lib/less/tree/{ruleset-call.js → variable-call.js} +5 -5
  60. package/lib/less/tree/variable.js +6 -6
  61. package/lib/less/utils.js +40 -0
  62. package/lib/less/visitors/extend-visitor.js +14 -14
  63. package/lib/less/visitors/import-visitor.js +2 -2
  64. package/lib/less/visitors/join-selector-visitor.js +1 -1
  65. package/lib/less/visitors/to-css-visitor.js +51 -84
  66. package/lib/less/visitors/visitor.js +15 -15
  67. package/lib/less-browser/bootstrap.js +21 -5
  68. package/lib/less-browser/cache.js +2 -2
  69. package/lib/less-browser/error-reporting.js +5 -5
  70. package/lib/less-browser/file-manager.js +27 -35
  71. package/lib/less-browser/index.js +12 -17
  72. package/lib/less-browser/plugin-loader.js +8 -45
  73. package/lib/less-browser/utils.js +1 -1
  74. package/lib/less-node/file-manager.js +99 -69
  75. package/lib/less-node/fs.js +1 -1
  76. package/lib/less-node/image-size.js +2 -2
  77. package/lib/less-node/index.js +7 -57
  78. package/lib/less-node/lessc-helper.js +38 -38
  79. package/lib/less-node/plugin-loader.js +18 -79
  80. package/lib/less-node/url-file-manager.js +1 -1
  81. package/lib/less-rhino/index.js +29 -44
  82. package/package.json +16 -9
  83. package/test/browser/common.js +54 -18
  84. package/test/browser/css/plugin/plugin.css +3 -0
  85. package/test/browser/jasmine-jsreporter.js +4 -4
  86. package/test/browser/less/plugin/plugin.js +7 -0
  87. package/test/browser/less/plugin/plugin.less +4 -0
  88. package/test/browser/less.js +11685 -13
  89. package/test/browser/runner-browser-options.js +6 -1
  90. package/test/browser/runner-filemanagerPlugin-options.js +3 -2
  91. package/test/browser/runner-legacy-options.js +2 -1
  92. package/test/browser/runner-main-options.js +0 -1
  93. package/test/browser/runner-modify-vars-spec.js +2 -2
  94. package/test/browser/test-runner-template.tmpl +38 -14
  95. package/test/copy-bom.js +1 -1
  96. package/test/css/calc.css +5 -0
  97. package/test/css/comments2.css +1 -1
  98. package/test/css/compression/compression.css +1 -1
  99. package/test/css/css-grid.css +11 -0
  100. package/test/css/debug/linenumbers-all.css +0 -1
  101. package/test/css/debug/linenumbers-comments.css +0 -1
  102. package/test/css/debug/linenumbers-mediaquery.css +0 -1
  103. package/test/css/functions.css +16 -3
  104. package/test/css/import-module.css +9 -0
  105. package/test/css/import.css +0 -1
  106. package/test/css/legacy/legacy.css +1 -1
  107. package/test/css/merge.css +5 -4
  108. package/test/css/plugin-module.css +1 -0
  109. package/test/css/plugin.css +20 -0
  110. package/test/css/property-accessors.css +49 -0
  111. package/test/css/{css.css → strict-math/css.css} +0 -0
  112. package/test/css/{mixins-args.css → strict-math/mixins-args.css} +0 -0
  113. package/test/css/{parens.css → strict-math/parens.css} +0 -0
  114. package/test/import-module/one/1.less +3 -0
  115. package/test/import-module/one/two/2.less +3 -0
  116. package/test/import-module/one/two/three/3.less +3 -0
  117. package/test/import-module/package.json +11 -0
  118. package/test/index.js +55 -49
  119. package/test/less/calc.less +7 -0
  120. package/test/less/css-grid.less +15 -0
  121. package/test/less/detached-rulesets.less +2 -2
  122. package/test/less/errors/color-invalid-hex-code.less +1 -0
  123. package/test/less/errors/color-invalid-hex-code.txt +1 -1
  124. package/test/less/errors/color-invalid-hex-code2.less +1 -0
  125. package/test/less/errors/color-invalid-hex-code2.txt +1 -1
  126. package/test/less/errors/import-missing.txt +1 -1
  127. package/test/less/errors/plugin/plugin-error-2.js +5 -0
  128. package/test/less/errors/plugin/plugin-error-3.js +5 -0
  129. package/test/less/errors/plugin/plugin-error.js +1 -0
  130. package/test/less/errors/plugin-1.less +1 -0
  131. package/test/less/errors/plugin-1.txt +2 -0
  132. package/test/less/errors/plugin-2.less +1 -0
  133. package/test/less/errors/plugin-2.txt +5 -0
  134. package/test/less/errors/plugin-3.less +1 -0
  135. package/test/less/errors/plugin-3.txt +5 -0
  136. package/test/less/functions.less +18 -0
  137. package/test/less/import-module.less +3 -0
  138. package/test/less/import.less +0 -2
  139. package/test/less/legacy/legacy.less +1 -1
  140. package/test/less/media.less +2 -2
  141. package/test/less/merge.less +6 -3
  142. package/test/less/plugin/plugin-collection.js +9 -0
  143. package/test/less/plugin/plugin-local.js +2 -2
  144. package/test/less/plugin/plugin-scope1.js +3 -0
  145. package/test/less/plugin/plugin-scope2.js +3 -0
  146. package/test/less/plugin/plugin-simple.js +7 -0
  147. package/test/less/plugin/plugin-tree-nodes.js +33 -31
  148. package/test/less/plugin-module.less +7 -0
  149. package/test/less/plugin.less +33 -3
  150. package/test/less/property-accessors.less +67 -0
  151. package/test/less/root-registry/file.less +1 -0
  152. package/test/less/root-registry/root.less +3 -0
  153. package/test/less/{css.less → strict-math/css.less} +0 -0
  154. package/test/less/{mixins-args.less → strict-math/mixins-args.less} +0 -0
  155. package/test/less/{parens.less → strict-math/parens.less} +0 -0
  156. package/test/less-bom/calc.less +7 -0
  157. package/test/less-bom/css-grid.less +15 -0
  158. package/test/less-bom/detached-rulesets.less +2 -2
  159. package/test/less-bom/errors/color-invalid-hex-code.less +1 -0
  160. package/test/less-bom/errors/color-invalid-hex-code.txt +1 -1
  161. package/test/less-bom/errors/color-invalid-hex-code2.less +1 -0
  162. package/test/less-bom/errors/color-invalid-hex-code2.txt +1 -1
  163. package/test/less-bom/errors/import-missing.txt +1 -1
  164. package/test/less-bom/errors/plugin/plugin-error-2.js +5 -0
  165. package/test/less-bom/errors/plugin/plugin-error-3.js +5 -0
  166. package/test/less-bom/errors/plugin/plugin-error.js +1 -0
  167. package/test/less-bom/errors/plugin-1.less +1 -0
  168. package/test/less-bom/errors/plugin-1.txt +2 -0
  169. package/test/less-bom/errors/plugin-2.less +1 -0
  170. package/test/less-bom/errors/plugin-2.txt +5 -0
  171. package/test/less-bom/errors/plugin-3.less +1 -0
  172. package/test/less-bom/errors/plugin-3.txt +5 -0
  173. package/test/less-bom/functions.less +18 -0
  174. package/test/less-bom/import-module.less +3 -0
  175. package/test/less-bom/import.less +0 -2
  176. package/test/less-bom/legacy/legacy.less +1 -1
  177. package/test/less-bom/media.less +2 -2
  178. package/test/less-bom/merge.less +6 -3
  179. package/test/less-bom/plugin/plugin-collection.js +9 -0
  180. package/test/less-bom/plugin/plugin-local.js +2 -2
  181. package/test/less-bom/plugin/plugin-scope1.js +3 -0
  182. package/test/less-bom/plugin/plugin-scope2.js +3 -0
  183. package/test/less-bom/plugin/plugin-simple.js +7 -0
  184. package/test/less-bom/plugin/plugin-tree-nodes.js +33 -31
  185. package/test/less-bom/plugin-module.less +7 -0
  186. package/test/less-bom/plugin.less +33 -3
  187. package/test/less-bom/property-accessors.less +67 -0
  188. package/test/less-bom/root-registry/file.less +1 -0
  189. package/test/less-bom/root-registry/root.less +3 -0
  190. package/test/less-bom/{css.less → strict-math/css.less} +0 -0
  191. package/test/less-bom/{mixins-args.less → strict-math/mixins-args.less} +0 -0
  192. package/test/less-bom/{parens.less → strict-math/parens.less} +0 -0
  193. package/test/less-test.js +75 -17
  194. package/test/modify-vars.js +1 -1
  195. package/test/plugins/visitor/index.js +1 -1
  196. package/.jscsrc +0 -73
  197. package/.jshintrc +0 -11
  198. package/lib/less/tree/alpha.js +0 -28
  199. package/lib/less/tree/directive.js +0 -12
  200. package/lib/less/tree/rule.js +0 -12
  201. package/test/less/errors/functions-2-alpha.less +0 -2
  202. package/test/less/errors/functions-2-alpha.txt +0 -3
  203. package/test/less-bom/errors/functions-2-alpha.less +0 -2
  204. package/test/less-bom/errors/functions-2-alpha.txt +0 -3
  205. package/test/sourcemaps/maps/import-map.map +0 -1
@@ -3,7 +3,7 @@ var tree = require("../tree"),
3
3
  logger = require("../logger"),
4
4
  utils = require("../utils");
5
5
 
6
- /*jshint loopfunc:true */
6
+ /* jshint loopfunc:true */
7
7
 
8
8
  var ExtendFinderVisitor = function() {
9
9
  this._visitor = new Visitor(this);
@@ -110,17 +110,17 @@ ProcessExtendsVisitor.prototype = {
110
110
  extendList.filter(function(extend) {
111
111
  return !extend.hasFoundMatches && extend.parent_ids.length == 1;
112
112
  }).forEach(function(extend) {
113
- var selector = "_unknown_";
114
- try {
115
- selector = extend.selector.toCSS({});
116
- }
117
- catch(_) {}
113
+ var selector = "_unknown_";
114
+ try {
115
+ selector = extend.selector.toCSS({});
116
+ }
117
+ catch (_) {}
118
118
 
119
- if (!indices[extend.index + ' ' + selector]) {
120
- indices[extend.index + ' ' + selector] = true;
121
- logger.warn("extend '" + selector + "' has no matches");
122
- }
123
- });
119
+ if (!indices[extend.index + ' ' + selector]) {
120
+ indices[extend.index + ' ' + selector] = true;
121
+ logger.warn("extend '" + selector + "' has no matches");
122
+ }
123
+ });
124
124
  },
125
125
  doExtendChaining: function (extendsList, extendsListTarget, iterationCount) {
126
126
  //
@@ -137,7 +137,7 @@ ProcessExtendsVisitor.prototype = {
137
137
 
138
138
  iterationCount = iterationCount || 0;
139
139
 
140
- //loop through comparing every extend with every target extend.
140
+ // loop through comparing every extend with every target extend.
141
141
  // a target extend is the one on the ruleset we are looking at copy/edit/pasting in place
142
142
  // e.g. .a:extend(.b) {} and .b:extend(.c) {} then the first extend extends the second one
143
143
  // and the second is the target.
@@ -203,7 +203,7 @@ ProcessExtendsVisitor.prototype = {
203
203
  selectorOne = extendsToAdd[0].selfSelectors[0].toCSS();
204
204
  selectorTwo = extendsToAdd[0].selector.toCSS();
205
205
  }
206
- catch(e) {}
206
+ catch (e) {}
207
207
  throw { message: "extend circular reference detected. One of the circular extends is currently:" +
208
208
  selectorOne + ":extend(" + selectorTwo + ")"};
209
209
  }
@@ -368,7 +368,7 @@ ProcessExtendsVisitor.prototype = {
368
368
  },
369
369
  extendSelector:function (matches, selectorPath, replacementSelector, isVisible) {
370
370
 
371
- //for a set of matches, replace each match with the replacement selector
371
+ // for a set of matches, replace each match with the replacement selector
372
372
 
373
373
  var currentSelectorPathIndex = 0,
374
374
  currentSelectorPathElementIndex = 0,
@@ -22,7 +22,7 @@ ImportVisitor.prototype = {
22
22
  // process the contents
23
23
  this._visitor.visit(root);
24
24
  }
25
- catch(e) {
25
+ catch (e) {
26
26
  this.error = e;
27
27
  }
28
28
 
@@ -58,7 +58,7 @@ ImportVisitor.prototype = {
58
58
 
59
59
  try {
60
60
  evaldImportNode = importNode.evalForImport(context);
61
- } catch(e) {
61
+ } catch (e) {
62
62
  if (!e.filename) { e.index = importNode.getIndex(); e.filename = importNode.fileInfo().filename; }
63
63
  // attempt to eval properly and treat as css
64
64
  importNode.css = true;
@@ -22,7 +22,7 @@ JoinSelectorVisitor.prototype = {
22
22
 
23
23
  this.contexts.push(paths);
24
24
 
25
- if (! rulesetNode.root) {
25
+ if (!rulesetNode.root) {
26
26
  selectors = rulesetNode.selectors;
27
27
  if (selectors) {
28
28
  selectors = selectors.filter(function(selector) { return selector.getIsOutput(); });
@@ -9,14 +9,14 @@ var CSSVisitorUtils = function(context) {
9
9
  CSSVisitorUtils.prototype = {
10
10
  containsSilentNonBlockedChild: function(bodyRules) {
11
11
  var rule;
12
- if (bodyRules == null) {
12
+ if (!bodyRules) {
13
13
  return false;
14
14
  }
15
15
  for (var r = 0; r < bodyRules.length; r++) {
16
16
  rule = bodyRules[r];
17
17
  if (rule.isSilent && rule.isSilent(this._context) && !rule.blocksVisibility()) {
18
- //the atrule contains something that was referenced (likely by extend)
19
- //therefore it needs to be shown in output too
18
+ // the atrule contains something that was referenced (likely by extend)
19
+ // therefore it needs to be shown in output too
20
20
  return true;
21
21
  }
22
22
  }
@@ -24,28 +24,21 @@ CSSVisitorUtils.prototype = {
24
24
  },
25
25
 
26
26
  keepOnlyVisibleChilds: function(owner) {
27
- if (owner == null || owner.rules == null) {
28
- return ;
29
- }
30
-
31
- owner.rules = owner.rules.filter(function(thing) {
27
+ if (owner && owner.rules) {
28
+ owner.rules = owner.rules.filter(function(thing) {
32
29
  return thing.isVisible();
33
- }
34
- );
30
+ });
31
+ }
35
32
  },
36
33
 
37
34
  isEmpty: function(owner) {
38
- if (owner == null || owner.rules == null) {
39
- return true;
40
- }
41
- return owner.rules.length === 0;
35
+ return (owner && owner.rules)
36
+ ? (owner.rules.length === 0) : true;
42
37
  },
43
38
 
44
39
  hasVisibleSelector: function(rulesetNode) {
45
- if (rulesetNode == null || rulesetNode.paths == null) {
46
- return false;
47
- }
48
- return rulesetNode.paths.length > 0;
40
+ return (rulesetNode && rulesetNode.paths)
41
+ ? (rulesetNode.paths.length > 0) : false;
49
42
  },
50
43
 
51
44
  resolveVisibility: function (node, originalRules) {
@@ -146,9 +139,16 @@ ToCSSVisitor.prototype = {
146
139
  }
147
140
  },
148
141
 
142
+ visitAnonymous: function(anonymousNode, visitArgs) {
143
+ if (!anonymousNode.blocksVisibility()) {
144
+ anonymousNode.accept(this._visitor);
145
+ return anonymousNode;
146
+ }
147
+ },
148
+
149
149
  visitAtRuleWithBody: function(atRuleNode, visitArgs) {
150
- //if there is only one nested ruleset and that one has no path, then it is
151
- //just fake ruleset
150
+ // if there is only one nested ruleset and that one has no path, then it is
151
+ // just fake ruleset
152
152
  function hasFakeRuleset(atRuleNode) {
153
153
  var bodyRules = atRuleNode.rules;
154
154
  return bodyRules.length === 1 && (!bodyRules[0].paths || bodyRules[0].paths.length === 0);
@@ -161,9 +161,9 @@ ToCSSVisitor.prototype = {
161
161
 
162
162
  return nodeRules;
163
163
  }
164
- //it is still true that it is only one ruleset in array
165
- //this is last such moment
166
- //process childs
164
+ // it is still true that it is only one ruleset in array
165
+ // this is last such moment
166
+ // process childs
167
167
  var originalRules = getBodyRules(atRuleNode);
168
168
  atRuleNode.accept(this._visitor);
169
169
  visitArgs.visitDeeper = false;
@@ -221,13 +221,13 @@ ToCSSVisitor.prototype = {
221
221
  },
222
222
 
223
223
  visitRuleset: function (rulesetNode, visitArgs) {
224
- //at this point rulesets are nested into each other
224
+ // at this point rulesets are nested into each other
225
225
  var rule, rulesets = [];
226
226
 
227
227
  this.checkValidNodes(rulesetNode.rules, rulesetNode.firstRoot);
228
228
 
229
- if (! rulesetNode.root) {
230
- //remove invisible paths
229
+ if (!rulesetNode.root) {
230
+ // remove invisible paths
231
231
  this._compileRulesetPaths(rulesetNode);
232
232
 
233
233
  // remove rulesets from this ruleset body and compile them separately
@@ -253,7 +253,7 @@ ToCSSVisitor.prototype = {
253
253
  }
254
254
  visitArgs.visitDeeper = false;
255
255
 
256
- } else { //if (! rulesetNode.root) {
256
+ } else { // if (! rulesetNode.root) {
257
257
  rulesetNode.accept(this._visitor);
258
258
  visitArgs.visitDeeper = false;
259
259
  }
@@ -263,7 +263,7 @@ ToCSSVisitor.prototype = {
263
263
  this._removeDuplicateRules(rulesetNode.rules);
264
264
  }
265
265
 
266
- //now decide whether we keep the ruleset
266
+ // now decide whether we keep the ruleset
267
267
  if (this.utils.isVisibleRuleset(rulesetNode)) {
268
268
  rulesetNode.ensureVisibility();
269
269
  rulesets.splice(0, 0, rulesetNode);
@@ -321,72 +321,39 @@ ToCSSVisitor.prototype = {
321
321
  }
322
322
  },
323
323
 
324
- _mergeRules: function (rules) {
325
- if (!rules) { return; }
326
-
327
- var groups = {},
328
- parts,
329
- rule,
330
- key;
324
+ _mergeRules: function(rules) {
325
+ if (!rules) {
326
+ return;
327
+ }
331
328
 
329
+ var groups = {},
330
+ groupsArr = [];
331
+
332
332
  for (var i = 0; i < rules.length; i++) {
333
- rule = rules[i];
334
-
335
- if ((rule instanceof tree.Declaration) && rule.merge) {
336
- key = [rule.name,
337
- rule.important ? "!" : ""].join(",");
338
-
339
- if (!groups[key]) {
340
- groups[key] = [];
341
- } else {
342
- rules.splice(i--, 1);
343
- }
344
-
333
+ var rule = rules[i];
334
+ if (rule.merge) {
335
+ var key = rule.name;
336
+ groups[key] ? rules.splice(i--, 1) :
337
+ groupsArr.push(groups[key] = []);
345
338
  groups[key].push(rule);
346
339
  }
347
340
  }
348
341
 
349
- Object.keys(groups).map(function (k) {
350
-
351
- function toExpression(values) {
352
- return new (tree.Expression)(values.map(function (p) {
353
- return p.value;
354
- }));
355
- }
356
-
357
- function toValue(values) {
358
- return new (tree.Value)(values.map(function (p) {
359
- return p;
360
- }));
361
- }
362
-
363
- parts = groups[k];
364
-
365
- if (parts.length > 1) {
366
- rule = parts[0];
367
- var spacedGroups = [];
368
- var lastSpacedGroup = [];
369
- parts.map(function (p) {
370
- if (p.merge === "+") {
371
- if (lastSpacedGroup.length > 0) {
372
- spacedGroups.push(toExpression(lastSpacedGroup));
373
- }
374
- lastSpacedGroup = [];
342
+ groupsArr.forEach(function(group) {
343
+ if (group.length > 0) {
344
+ var result = group[0],
345
+ space = [],
346
+ comma = [new tree.Expression(space)];
347
+ group.forEach(function(rule) {
348
+ if ((rule.merge === '+') && (space.length > 0)) {
349
+ comma.push(new tree.Expression(space = []));
375
350
  }
376
- lastSpacedGroup.push(p);
351
+ space.push(rule.value);
352
+ result.important = result.important || rule.important;
377
353
  });
378
- spacedGroups.push(toExpression(lastSpacedGroup));
379
- rule.value = toValue(spacedGroups);
354
+ result.value = new tree.Value(comma);
380
355
  }
381
356
  });
382
- },
383
-
384
- visitAnonymous: function(anonymousNode, visitArgs) {
385
- if (anonymousNode.blocksVisibility()) {
386
- return ;
387
- }
388
- anonymousNode.accept(this._visitor);
389
- return anonymousNode;
390
357
  }
391
358
  };
392
359
 
@@ -10,21 +10,21 @@ function _noop(node) {
10
10
  function indexNodeTypes(parent, ticker) {
11
11
  // add .typeIndex to tree node types for lookup table
12
12
  var key, child;
13
- for (key in parent) {
14
- if (parent.hasOwnProperty(key)) {
15
- child = parent[key];
16
- switch (typeof child) {
17
- case "function":
18
- // ignore bound functions directly on tree which do not have a prototype
19
- // or aren't nodes
20
- if (child.prototype && child.prototype.type) {
21
- child.prototype.typeIndex = ticker++;
22
- }
23
- break;
24
- case "object":
25
- ticker = indexNodeTypes(child, ticker);
26
- break;
27
- }
13
+ for (key in parent) {
14
+ /* eslint guard-for-in: 0 */
15
+ child = parent[key];
16
+ switch (typeof child) {
17
+ case "function":
18
+ // ignore bound functions directly on tree which do not have a prototype
19
+ // or aren't nodes
20
+ if (child.prototype && child.prototype.type) {
21
+ child.prototype.typeIndex = ticker++;
22
+ }
23
+ break;
24
+ case "object":
25
+ ticker = indexNodeTypes(child, ticker);
26
+ break;
27
+
28
28
  }
29
29
  }
30
30
  return ticker;
@@ -3,14 +3,30 @@
3
3
  * used in the browser distributed version of less
4
4
  * to kick-start less using the browser api
5
5
  */
6
- /*global window, document */
6
+ /* global window, document */
7
7
 
8
- // shim Promise if required
9
- require('promise/polyfill.js');
8
+ // TODO - consider switching this out for a recommendation for this polyfill?
9
+ // <script src="https://cdn.polyfill.io/v2/polyfill.min.js"></script>
10
+ // Browsers have good Promise support
11
+ require("promise/polyfill");
10
12
 
11
- var options = window.less || {};
13
+ var options = require('../less/default-options')();
14
+
15
+ if (window.less) {
16
+ for (key in window.less) {
17
+ if (window.less.hasOwnProperty(key)) {
18
+ options[key] = window.less[key];
19
+ }
20
+ }
21
+ }
12
22
  require("./add-default-options")(window, options);
13
23
 
24
+ options.plugins = options.plugins || [];
25
+
26
+ if (window.LESS_PLUGINS) {
27
+ options.plugins = options.plugins.concat(window.LESS_PLUGINS);
28
+ }
29
+
14
30
  var less = module.exports = require("./index")(window, options);
15
31
 
16
32
  window.less = less;
@@ -31,7 +47,7 @@ if (options.onReady) {
31
47
  if (/!watch/.test(window.location.hash)) {
32
48
  less.watch();
33
49
  }
34
- // Simulate synchronous stylesheet loading by blocking page rendering
50
+ // Simulate synchronous stylesheet loading by hiding page rendering
35
51
  if (!options.async) {
36
52
  css = 'body { display: none !important }';
37
53
  head = document.head || document.getElementsByTagName('head')[0];
@@ -17,8 +17,8 @@ module.exports = function(window, options, logger) {
17
17
  if (modifyVars) {
18
18
  cache.setItem(path + ':vars', JSON.stringify(modifyVars));
19
19
  }
20
- } catch(e) {
21
- //TODO - could do with adding more robust error handling
20
+ } catch (e) {
21
+ // TODO - could do with adding more robust error handling
22
22
  logger.error('failed to save "' + path + '" to local storage for caching.');
23
23
  }
24
24
  }
@@ -24,7 +24,7 @@ module.exports = function(window, less, options) {
24
24
  }
25
25
  };
26
26
 
27
- if (e.extract) {
27
+ if (e.line) {
28
28
  errorline(e, 0, '');
29
29
  errorline(e, 1, 'line');
30
30
  errorline(e, 2, '');
@@ -112,7 +112,7 @@ module.exports = function(window, less, options) {
112
112
  }
113
113
 
114
114
  function removeErrorConsole(path) {
115
- //no action
115
+ // no action
116
116
  }
117
117
 
118
118
  function removeError(path) {
@@ -130,7 +130,7 @@ module.exports = function(window, less, options) {
130
130
  var filename = e.filename || rootHref;
131
131
  var errors = [];
132
132
  var content = (e.type || "Syntax") + "Error: " + (e.message || 'There is an error in your .less file') +
133
- " in " + filename + " ";
133
+ " in " + filename;
134
134
 
135
135
  var errorline = function (e, i, classname) {
136
136
  if (e.extract[i] !== undefined) {
@@ -140,11 +140,11 @@ module.exports = function(window, less, options) {
140
140
  }
141
141
  };
142
142
 
143
- if (e.extract) {
143
+ if (e.line) {
144
144
  errorline(e, 0, '');
145
145
  errorline(e, 1, 'line');
146
146
  errorline(e, 2, '');
147
- content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':\n' +
147
+ content += ' on line ' + e.line + ', column ' + (e.column + 1) + ':\n' +
148
148
  errors.join('\n');
149
149
  }
150
150
  if (e.stack && (e.extract || options.logLevel >= 4)) {
@@ -1,4 +1,4 @@
1
- /*global window, XMLHttpRequest */
1
+ /* global window, XMLHttpRequest */
2
2
 
3
3
  module.exports = function(options, logger) {
4
4
 
@@ -6,22 +6,7 @@ module.exports = function(options, logger) {
6
6
 
7
7
  var fileCache = {};
8
8
 
9
- //TODOS - move log somewhere. pathDiff and doing something similar in node. use pathDiff in the other browser file for the initial load
10
-
11
- function getXMLHttpRequest() {
12
- if (window.XMLHttpRequest && (window.location.protocol !== "file:" || !("ActiveXObject" in window))) {
13
- return new XMLHttpRequest();
14
- } else {
15
- try {
16
- /*global ActiveXObject */
17
- return new ActiveXObject("Microsoft.XMLHTTP");
18
- } catch (e) {
19
- logger.error("browser doesn't support AJAX.");
20
- return null;
21
- }
22
- }
23
- }
24
-
9
+ // TODOS - move log somewhere. pathDiff and doing something similar in node. use pathDiff in the other browser file for the initial load
25
10
  var FileManager = function() {
26
11
  };
27
12
 
@@ -38,7 +23,7 @@ module.exports = function(options, logger) {
38
23
  };
39
24
  FileManager.prototype.doXHR = function doXHR(url, type, callback, errback) {
40
25
 
41
- var xhr = getXMLHttpRequest();
26
+ var xhr = new XMLHttpRequest();
42
27
  var async = options.isFileProtocol ? options.fileAsync : true;
43
28
 
44
29
  if (typeof xhr.overrideMimeType === 'function') {
@@ -82,36 +67,43 @@ module.exports = function(options, logger) {
82
67
  fileCache = {};
83
68
  };
84
69
 
85
- FileManager.prototype.loadFile = function loadFile(filename, currentDirectory, options, environment, callback) {
70
+ FileManager.prototype.loadFile = function loadFile(filename, currentDirectory, options, environment) {
71
+ // TODO: Add prefix support like less-node?
72
+ // What about multiple paths?
73
+
86
74
  if (currentDirectory && !this.isPathAbsolute(filename)) {
87
75
  filename = currentDirectory + filename;
88
76
  }
89
77
 
78
+ filename = options.ext ? this.tryAppendExtension(filename, options.ext) : filename;
79
+
90
80
  options = options || {};
91
81
 
92
82
  // sheet may be set to the stylesheet for the initial load or a collection of properties including
93
83
  // some context variables for imports
94
84
  var hrefParts = this.extractUrlParts(filename, window.location.href);
95
85
  var href = hrefParts.url;
96
-
97
- if (options.useFileCache && fileCache[href]) {
98
- try {
99
- var lessText = fileCache[href];
100
- callback(null, { contents: lessText, filename: href, webInfo: { lastModified: new Date() }});
101
- } catch (e) {
102
- callback({filename: href, message: "Error loading file " + href + " error was " + e.message});
86
+ var self = this;
87
+
88
+ return new Promise(function(resolve, reject) {
89
+ if (options.useFileCache && fileCache[href]) {
90
+ try {
91
+ var lessText = fileCache[href];
92
+ return resolve({ contents: lessText, filename: href, webInfo: { lastModified: new Date() }});
93
+ } catch (e) {
94
+ return reject({ filename: href, message: "Error loading file " + href + " error was " + e.message });
95
+ }
103
96
  }
104
- return;
105
- }
106
97
 
107
- this.doXHR(href, options.mime, function doXHRCallback(data, lastModified) {
108
- // per file cache
109
- fileCache[href] = data;
98
+ self.doXHR(href, options.mime, function doXHRCallback(data, lastModified) {
99
+ // per file cache
100
+ fileCache[href] = data;
110
101
 
111
- // Use remote copy (re-parse)
112
- callback(null, { contents: data, filename: href, webInfo: { lastModified: lastModified }});
113
- }, function doXHRError(status, url) {
114
- callback({ type: 'File', message: "'" + url + "' wasn't found (" + status + ")", href: href });
102
+ // Use remote copy (re-parse)
103
+ resolve({ contents: data, filename: href, webInfo: { lastModified: lastModified }});
104
+ }, function doXHRError(status, url) {
105
+ reject({ type: 'File', message: "'" + url + "' wasn't found (" + status + ")", href: href });
106
+ });
115
107
  });
116
108
  };
117
109
 
@@ -22,7 +22,7 @@ module.exports = function(window, options) {
22
22
  var cache = less.cache = options.cache || require("./cache")(window, options, less.logger);
23
23
  require('./image-size')(less.environment);
24
24
 
25
- //Setup user functions - Deprecate?
25
+ // Setup user functions - Deprecate?
26
26
  if (options.functions) {
27
27
  less.functions.functionRegistry.addMultiple(options.functions);
28
28
  }
@@ -30,13 +30,7 @@ module.exports = function(window, options) {
30
30
  var typePattern = /^text\/(x-)?less$/;
31
31
 
32
32
  function clone(obj) {
33
- var cloned = {};
34
- for (var prop in obj) {
35
- if (obj.hasOwnProperty(prop)) {
36
- cloned[prop] = obj[prop];
37
- }
38
- }
39
- return cloned;
33
+ return JSON.parse(JSON.stringify(obj || {}));
40
34
  }
41
35
 
42
36
  // only really needed for phantom
@@ -60,7 +54,7 @@ module.exports = function(window, options) {
60
54
  var lessText = style.innerHTML || '';
61
55
  instanceOptions.filename = document.location.href.replace(/#.*$/, '');
62
56
 
63
- /*jshint loopfunc:true */
57
+ /* jshint loopfunc:true */
64
58
  // use closure to store current style
65
59
  less.render(lessText, instanceOptions,
66
60
  bind(function(style, e, result) {
@@ -116,7 +110,7 @@ module.exports = function(window, options) {
116
110
 
117
111
  }
118
112
 
119
- //TODO add tests around how this behaves when reloading
113
+ // TODO add tests around how this behaves when reloading
120
114
  errors.remove(path);
121
115
 
122
116
  instanceOptions.rootFileInfo = newFileInfo;
@@ -131,13 +125,14 @@ module.exports = function(window, options) {
131
125
  });
132
126
  }
133
127
 
134
- fileManager.loadFile(sheet.href, null, instanceOptions, environment, function(e, loadedFile) {
135
- if (e) {
136
- callback(e);
137
- return;
138
- }
139
- loadInitialFileCallback(loadedFile);
140
- });
128
+ fileManager.loadFile(sheet.href, null, instanceOptions, environment)
129
+ .then(function(loadedFile) {
130
+ loadInitialFileCallback(loadedFile);
131
+ }).catch(function(err) {
132
+ console.log(err);
133
+ callback(err);
134
+ });
135
+
141
136
  }
142
137
 
143
138
  function loadStyleSheets(callback, reload, modifyVars) {