less 3.6.0 → 3.8.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 (142) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/Gruntfile.js +43 -6
  3. package/bin/lessc +32 -3
  4. package/dist/less.js +2810 -326
  5. package/dist/less.min.js +7 -7
  6. package/lib/less/constants.js +13 -0
  7. package/lib/less/contexts.js +45 -10
  8. package/lib/less/default-options.js +12 -4
  9. package/lib/less/functions/color.js +84 -41
  10. package/lib/less/functions/data-uri.js +1 -1
  11. package/lib/less/functions/index.js +1 -0
  12. package/lib/less/functions/list.js +101 -0
  13. package/lib/less/functions/types.js +1 -19
  14. package/lib/less/import-manager.js +3 -3
  15. package/lib/less/index.js +1 -1
  16. package/lib/less/parse.js +3 -3
  17. package/lib/less/parser/parser.js +31 -13
  18. package/lib/less/render.js +2 -2
  19. package/lib/less/source-map-output.js +2 -2
  20. package/lib/less/tree/color.js +58 -18
  21. package/lib/less/tree/declaration.js +11 -7
  22. package/lib/less/tree/expression.js +7 -3
  23. package/lib/less/tree/import.js +9 -8
  24. package/lib/less/tree/mixin-definition.js +1 -1
  25. package/lib/less/tree/operation.js +10 -4
  26. package/lib/less/tree/url.js +12 -8
  27. package/lib/less/utils.js +54 -19
  28. package/lib/less-browser/add-default-options.js +3 -3
  29. package/lib/less-browser/index.js +9 -2
  30. package/lib/less-node/image-size.js +1 -1
  31. package/lib/less-node/lessc-helper.js +12 -4
  32. package/package.json +5 -2
  33. package/test/browser/css/rewrite-urls/urls.css +36 -0
  34. package/test/browser/css/rootpath-rewrite-urls/urls.css +35 -0
  35. package/test/browser/less/rewrite-urls/urls.less +34 -0
  36. package/test/browser/less/rootpath-rewrite-urls/urls.less +33 -0
  37. package/test/browser/less.js +2810 -326
  38. package/test/browser/runner-browser-options.js +1 -1
  39. package/test/browser/runner-errors-options.js +1 -1
  40. package/test/browser/runner-legacy-options.js +1 -1
  41. package/test/browser/runner-rewrite-urls-options.js +3 -0
  42. package/test/browser/runner-rewrite-urls-spec.js +3 -0
  43. package/test/browser/runner-rootpath-relative-spec.js +1 -1
  44. package/test/browser/runner-rootpath-rewrite-urls-options.js +4 -0
  45. package/test/browser/runner-rootpath-rewrite-urls-spec.js +3 -0
  46. package/test/css/calc.css +2 -2
  47. package/test/css/colors.css +20 -3
  48. package/test/css/css-3.css +0 -8
  49. package/test/css/css-escapes.css +3 -0
  50. package/test/css/functions-each.css +48 -0
  51. package/test/css/functions.css +6 -4
  52. package/test/css/math/parens-division/media-math.css +10 -0
  53. package/test/css/math/parens-division/mixins-args.css +169 -0
  54. package/test/css/math/parens-division/new-division.css +16 -0
  55. package/test/css/math/parens-division/parens.css +37 -0
  56. package/test/css/math/strict/css.css +95 -0
  57. package/test/css/math/strict/media-math.css +10 -0
  58. package/test/css/math/strict/mixins-args.css +169 -0
  59. package/test/css/math/strict/parens.css +37 -0
  60. package/test/css/{strict-math → math/strict-legacy}/css.css +0 -0
  61. package/test/css/math/strict-legacy/media-math.css +10 -0
  62. package/test/css/{strict-math → math/strict-legacy}/mixins-args.css +0 -0
  63. package/test/css/{strict-math → math/strict-legacy}/parens.css +5 -1
  64. package/test/css/no-strict-math/no-sm-operations.css +3 -0
  65. package/test/css/rewrite-urls-all/rewrite-urls-all.css +17 -0
  66. package/test/css/rewrite-urls-local/rewrite-urls-local.css +17 -0
  67. package/test/css/rootpath-rewrite-urls-all/rootpath-rewrite-urls-all.css +17 -0
  68. package/test/css/rootpath-rewrite-urls-local/rootpath-rewrite-urls-local.css +17 -0
  69. package/test/css/static-urls/urls.css +2 -2
  70. package/test/css/urls.css +2 -2
  71. package/test/index.js +28 -15
  72. package/test/less/colors.less +18 -0
  73. package/test/less/css-3.less +0 -9
  74. package/test/less/css-escapes.less +4 -0
  75. package/test/less/errors/color-func-invalid-color.txt +1 -1
  76. package/test/less/errors/mixin-not-defined-2.less +7 -0
  77. package/test/less/errors/mixin-not-defined-2.txt +4 -0
  78. package/test/less/functions-each.less +81 -0
  79. package/test/less/functions.less +14 -2
  80. package/test/less/math/parens-division/media-math.less +9 -0
  81. package/test/less/math/parens-division/mixins-args.less +264 -0
  82. package/test/less/math/parens-division/new-division.less +17 -0
  83. package/test/less/{strict-math → math/parens-division}/parens.less +2 -1
  84. package/test/less/math/strict/css.less +108 -0
  85. package/test/less/math/strict/media-math.less +9 -0
  86. package/test/less/math/strict/mixins-args.less +264 -0
  87. package/test/less/math/strict/parens.less +46 -0
  88. package/test/less/{strict-math → math/strict-legacy}/css.less +0 -0
  89. package/test/less/math/strict-legacy/media-math.less +9 -0
  90. package/test/less/{strict-math → math/strict-legacy}/mixins-args.less +0 -0
  91. package/test/less/math/strict-legacy/parens.less +50 -0
  92. package/test/less/no-strict-math/no-sm-operations.less +3 -0
  93. package/test/less/rewrite-urls-all/folder/file.less +8 -0
  94. package/test/less/rewrite-urls-all/rewrite-urls-all.less +11 -0
  95. package/test/less/rewrite-urls-local/folder/file.less +8 -0
  96. package/test/less/rewrite-urls-local/rewrite-urls-local.less +11 -0
  97. package/test/less/rootpath-rewrite-urls-all/folder/file.less +8 -0
  98. package/test/less/rootpath-rewrite-urls-all/rootpath-rewrite-urls-all.less +11 -0
  99. package/test/less/rootpath-rewrite-urls-local/folder/file.less +8 -0
  100. package/test/less/rootpath-rewrite-urls-local/rootpath-rewrite-urls-local.less +11 -0
  101. package/test/less/sourcemaps/custom-props.less +8 -0
  102. package/test/less-bom/colors.less +18 -0
  103. package/test/less-bom/css-3.less +0 -9
  104. package/test/less-bom/css-escapes.less +4 -0
  105. package/test/less-bom/errors/color-func-invalid-color.txt +1 -1
  106. package/test/less-bom/errors/mixin-not-defined-2.less +7 -0
  107. package/test/less-bom/errors/mixin-not-defined-2.txt +4 -0
  108. package/test/less-bom/functions-each.less +81 -0
  109. package/test/less-bom/functions.less +14 -2
  110. package/test/less-bom/math/parens-division/media-math.less +9 -0
  111. package/test/less-bom/math/parens-division/mixins-args.less +264 -0
  112. package/test/less-bom/math/parens-division/new-division.less +17 -0
  113. package/test/less-bom/{strict-math → math/parens-division}/parens.less +2 -1
  114. package/test/less-bom/math/strict/css.less +108 -0
  115. package/test/less-bom/math/strict/media-math.less +9 -0
  116. package/test/less-bom/math/strict/mixins-args.less +264 -0
  117. package/test/less-bom/math/strict/parens.less +46 -0
  118. package/test/less-bom/{strict-math → math/strict-legacy}/css.less +0 -0
  119. package/test/less-bom/math/strict-legacy/media-math.less +9 -0
  120. package/test/less-bom/{strict-math → math/strict-legacy}/mixins-args.less +0 -0
  121. package/test/less-bom/math/strict-legacy/parens.less +50 -0
  122. package/test/less-bom/no-strict-math/no-sm-operations.less +3 -0
  123. package/test/less-bom/rewrite-urls-all/folder/file.less +8 -0
  124. package/test/less-bom/rewrite-urls-all/rewrite-urls-all.less +11 -0
  125. package/test/less-bom/rewrite-urls-local/folder/file.less +8 -0
  126. package/test/less-bom/rewrite-urls-local/rewrite-urls-local.less +11 -0
  127. package/test/less-bom/rootpath-rewrite-urls-all/folder/file.less +8 -0
  128. package/test/less-bom/rootpath-rewrite-urls-all/rootpath-rewrite-urls-all.less +11 -0
  129. package/test/less-bom/rootpath-rewrite-urls-local/folder/file.less +8 -0
  130. package/test/less-bom/rootpath-rewrite-urls-local/rootpath-rewrite-urls-local.less +11 -0
  131. package/test/less-bom/sourcemaps/custom-props.less +8 -0
  132. package/test/less-test.js +26 -12
  133. package/test/sourcemaps/custom-props.json +1 -0
  134. package/.npmignore +0 -8
  135. package/test/less/errors/color-invalid-hex-code.less +0 -4
  136. package/test/less/errors/color-invalid-hex-code.txt +0 -4
  137. package/test/less/errors/color-invalid-hex-code2.less +0 -4
  138. package/test/less/errors/color-invalid-hex-code2.txt +0 -4
  139. package/test/less-bom/errors/color-invalid-hex-code.less +0 -4
  140. package/test/less-bom/errors/color-invalid-hex-code.txt +0 -4
  141. package/test/less-bom/errors/color-invalid-hex-code2.less +0 -4
  142. package/test/less-bom/errors/color-invalid-hex-code2.txt +0 -4
@@ -0,0 +1,13 @@
1
+ module.exports = {
2
+ Math: {
3
+ ALWAYS: 0,
4
+ PARENS_DIVISION: 1,
5
+ PARENS: 2,
6
+ STRICT_LEGACY: 3
7
+ },
8
+ RewriteUrls: {
9
+ OFF: 0,
10
+ LOCAL: 1,
11
+ ALL: 2
12
+ }
13
+ };
@@ -1,5 +1,6 @@
1
1
  var contexts = {};
2
2
  module.exports = contexts;
3
+ var Constants = require('./constants');
3
4
 
4
5
  var copyFromOriginal = function copyFromOriginal(original, destination, propertiesToCopy) {
5
6
  if (!original) { return; }
@@ -17,7 +18,7 @@ var copyFromOriginal = function copyFromOriginal(original, destination, properti
17
18
  var parseCopyProperties = [
18
19
  // options
19
20
  'paths', // option - unmodified - paths to search for imports on
20
- 'relativeUrls', // option - whether to adjust URL's to be relative
21
+ 'rewriteUrls', // option - whether to adjust URL's to be relative
21
22
  'rootpath', // option - rootpath to append to URL's
22
23
  'strictImports', // option -
23
24
  'insecure', // option - whether to allow imports from insecure ssl hosts
@@ -43,14 +44,15 @@ var evalCopyProperties = [
43
44
  'paths', // additional include paths
44
45
  'compress', // whether to compress
45
46
  'ieCompat', // whether to enforce IE compatibility (IE8 data-uri)
46
- 'strictMath', // whether math has to be within parenthesis
47
+ 'math', // whether math has to be within parenthesis
47
48
  'strictUnits', // whether units need to evaluate correctly
48
49
  'sourceMap', // whether to output a source map
49
50
  'importMultiple', // whether we are currently importing multiple copies
50
51
  'urlArgs', // whether to add args into url tokens
51
52
  'javascriptEnabled', // option - whether Inline JavaScript is enabled. if undefined, defaults to false
52
53
  'pluginManager', // Used as the plugin manager for the session
53
- 'importantScope' // used to bubble up !important statements
54
+ 'importantScope', // used to bubble up !important statements
55
+ 'rewriteUrls' // option - whether to adjust URL's to be relative
54
56
  ];
55
57
 
56
58
  contexts.Eval = function(options, frames) {
@@ -90,24 +92,49 @@ contexts.Eval.prototype.outOfParenthesis = function () {
90
92
 
91
93
  contexts.Eval.prototype.inCalc = false;
92
94
  contexts.Eval.prototype.mathOn = true;
93
- contexts.Eval.prototype.isMathOn = function () {
95
+ contexts.Eval.prototype.isMathOn = function (op) {
94
96
  if (!this.mathOn) {
95
97
  return false;
96
98
  }
97
- return this.strictMath ? (this.parensStack && this.parensStack.length) : true;
99
+ if (op === '/' && this.math !== Constants.Math.ALWAYS && (!this.parensStack || !this.parensStack.length)) {
100
+ return false;
101
+ }
102
+ if (this.math > Constants.Math.PARENS_DIVISION) {
103
+ return this.parensStack && this.parensStack.length;
104
+ }
105
+ return true;
98
106
  };
99
107
 
100
- contexts.Eval.prototype.isPathRelative = function (path) {
101
- return !/^(?:[a-z-]+:|\/|#)/i.test(path);
108
+ contexts.Eval.prototype.pathRequiresRewrite = function (path) {
109
+ var isRelative = this.rewriteUrls === Constants.RewriteUrls.LOCAL ? isPathLocalRelative : isPathRelative;
110
+
111
+ return isRelative(path);
112
+ };
113
+
114
+ contexts.Eval.prototype.rewritePath = function (path, rootpath) {
115
+ var newPath;
116
+
117
+ rootpath = rootpath || '';
118
+ newPath = this.normalizePath(rootpath + path);
119
+
120
+ // If a path was explicit relative and the rootpath was not an absolute path
121
+ // we must ensure that the new path is also explicit relative.
122
+ if (isPathLocalRelative(path) &&
123
+ isPathRelative(rootpath) &&
124
+ isPathLocalRelative(newPath) === false) {
125
+ newPath = './' + newPath;
126
+ }
127
+
128
+ return newPath;
102
129
  };
103
130
 
104
- contexts.Eval.prototype.normalizePath = function( path ) {
131
+ contexts.Eval.prototype.normalizePath = function (path) {
105
132
  var
106
133
  segments = path.split('/').reverse(),
107
134
  segment;
108
135
 
109
136
  path = [];
110
- while (segments.length !== 0 ) {
137
+ while (segments.length !== 0) {
111
138
  segment = segments.pop();
112
139
  switch ( segment ) {
113
140
  case '.':
@@ -120,7 +147,7 @@ contexts.Eval.prototype.normalizePath = function( path ) {
120
147
  }
121
148
  break;
122
149
  default:
123
- path.push( segment );
150
+ path.push(segment);
124
151
  break;
125
152
  }
126
153
  }
@@ -128,4 +155,12 @@ contexts.Eval.prototype.normalizePath = function( path ) {
128
155
  return path.join('/');
129
156
  };
130
157
 
158
+ function isPathRelative(path) {
159
+ return !/^(?:[a-z-]+:|\/|#)/i.test(path);
160
+ }
161
+
162
+ function isPathLocalRelative(path) {
163
+ return path.charAt(0) === '.';
164
+ }
165
+
131
166
  // todo - do the same for the toCSS ?
@@ -1,10 +1,13 @@
1
1
  // Export a new default each time
2
2
  module.exports = function() {
3
3
  return {
4
+ /* Inline Javascript - @plugin still allowed */
5
+ javascriptEnabled: false,
6
+
4
7
  /* Outputs a makefile import dependency list to stdout. */
5
8
  depends: false,
6
9
 
7
- /* Compress using less built-in compression.
10
+ /* (DEPRECATED) Compress using less built-in compression.
8
11
  * This does an okay job but does not utilise all the tricks of
9
12
  * dedicated css compression. */
10
13
  compress: false,
@@ -39,13 +42,18 @@ module.exports = function() {
39
42
  * that references an image, exactly the same URL will be output in the css.
40
43
  * This option allows you to re-write URL's in imported files so that the
41
44
  * URL is always relative to the base imported file */
42
- relativeUrls: false,
45
+ rewriteUrls: false,
43
46
 
44
47
  /* Compatibility with IE8. Used for limiting data-uri length */
45
48
  ieCompat: false, // true until 3.0
46
49
 
47
- /* Without this option on, Less will try and process all math in your css */
48
- strictMath: false,
50
+ /* How to process math
51
+ * 0 always - eagerly try to solve all operations
52
+ * 1 parens-division - require parens for division "/"
53
+ * 2 parens | strict - require parens for all operations
54
+ * 3 strict-legacy - legacy strict behavior (super-strict)
55
+ */
56
+ math: 0,
49
57
 
50
58
  /* Without this option, less attempts to guess at the output unit when it does maths. */
51
59
  strictUnits: false,
@@ -8,8 +8,17 @@ var Dimension = require('../tree/dimension'),
8
8
  function clamp(val) {
9
9
  return Math.min(1, Math.max(0, val));
10
10
  }
11
- function hsla(color) {
12
- return colorFunctions.hsla(color.h, color.s, color.l, color.a);
11
+ function hsla(origColor, hsl) {
12
+ var color = colorFunctions.hsla(hsl.h, hsl.s, hsl.l, hsl.a);
13
+ if (color) {
14
+ if (origColor.value &&
15
+ /^(rgb|hsl)/.test(origColor.value)) {
16
+ color.value = origColor.value;
17
+ } else {
18
+ color.value = 'rgb';
19
+ }
20
+ return color;
21
+ }
13
22
  }
14
23
  function number(n) {
15
24
  if (n instanceof Dimension) {
@@ -32,46 +41,79 @@ function scaled(n, size) {
32
41
  }
33
42
  colorFunctions = {
34
43
  rgb: function (r, g, b) {
35
- return colorFunctions.rgba(r, g, b, 1.0);
44
+ var color = colorFunctions.rgba(r, g, b, 1.0);
45
+ if (color) {
46
+ color.value = 'rgb';
47
+ return color;
48
+ }
36
49
  },
37
50
  rgba: function (r, g, b, a) {
38
- var rgb = [r, g, b].map(function (c) { return scaled(c, 255); });
39
- a = number(a);
40
- return new Color(rgb, a);
51
+ try {
52
+ if (r instanceof Color) {
53
+ if (g) {
54
+ a = number(g);
55
+ } else {
56
+ a = r.alpha;
57
+ }
58
+ return new Color(r.rgb, a, 'rgba');
59
+ }
60
+ var rgb = [r, g, b].map(function (c) { return scaled(c, 255); });
61
+ a = number(a);
62
+ return new Color(rgb, a, 'rgba');
63
+ }
64
+ catch (e) {}
41
65
  },
42
66
  hsl: function (h, s, l) {
43
- return colorFunctions.hsla(h, s, l, 1.0);
67
+ var color = colorFunctions.hsla(h, s, l, 1.0);
68
+ if (color) {
69
+ color.value = 'hsl';
70
+ return color;
71
+ }
44
72
  },
45
73
  hsla: function (h, s, l, a) {
74
+ try {
75
+ if (h instanceof Color) {
76
+ if (s) {
77
+ a = number(s);
78
+ } else {
79
+ a = h.alpha;
80
+ }
81
+ return new Color(h.rgb, a, 'hsla');
82
+ }
46
83
 
47
- var m1, m2;
84
+ var m1, m2;
48
85
 
49
- function hue(h) {
50
- h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h);
51
- if (h * 6 < 1) {
52
- return m1 + (m2 - m1) * h * 6;
53
- }
54
- else if (h * 2 < 1) {
55
- return m2;
56
- }
57
- else if (h * 3 < 2) {
58
- return m1 + (m2 - m1) * (2 / 3 - h) * 6;
59
- }
60
- else {
61
- return m1;
86
+ function hue(h) {
87
+ h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h);
88
+ if (h * 6 < 1) {
89
+ return m1 + (m2 - m1) * h * 6;
90
+ }
91
+ else if (h * 2 < 1) {
92
+ return m2;
93
+ }
94
+ else if (h * 3 < 2) {
95
+ return m1 + (m2 - m1) * (2 / 3 - h) * 6;
96
+ }
97
+ else {
98
+ return m1;
99
+ }
62
100
  }
63
- }
64
101
 
65
- h = (number(h) % 360) / 360;
66
- s = clamp(number(s)); l = clamp(number(l)); a = clamp(number(a));
102
+ h = (number(h) % 360) / 360;
103
+ s = clamp(number(s)); l = clamp(number(l)); a = clamp(number(a));
67
104
 
68
- m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s;
69
- m1 = l * 2 - m2;
105
+ m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s;
106
+ m1 = l * 2 - m2;
70
107
 
71
- return colorFunctions.rgba(hue(h + 1 / 3) * 255,
72
- hue(h) * 255,
73
- hue(h - 1 / 3) * 255,
74
- a);
108
+ var rgb = [
109
+ hue(h + 1 / 3) * 255,
110
+ hue(h) * 255,
111
+ hue(h - 1 / 3) * 255
112
+ ];
113
+ a = number(a);
114
+ return new Color(rgb, a, 'hsla');
115
+ }
116
+ catch (e) {}
75
117
  },
76
118
 
77
119
  hsv: function(h, s, v) {
@@ -159,7 +201,7 @@ colorFunctions = {
159
201
  hsl.s += amount.value / 100;
160
202
  }
161
203
  hsl.s = clamp(hsl.s);
162
- return hsla(hsl);
204
+ return hsla(color, hsl);
163
205
  },
164
206
  desaturate: function (color, amount, method) {
165
207
  var hsl = color.toHSL();
@@ -171,7 +213,7 @@ colorFunctions = {
171
213
  hsl.s -= amount.value / 100;
172
214
  }
173
215
  hsl.s = clamp(hsl.s);
174
- return hsla(hsl);
216
+ return hsla(color, hsl);
175
217
  },
176
218
  lighten: function (color, amount, method) {
177
219
  var hsl = color.toHSL();
@@ -183,7 +225,7 @@ colorFunctions = {
183
225
  hsl.l += amount.value / 100;
184
226
  }
185
227
  hsl.l = clamp(hsl.l);
186
- return hsla(hsl);
228
+ return hsla(color, hsl);
187
229
  },
188
230
  darken: function (color, amount, method) {
189
231
  var hsl = color.toHSL();
@@ -195,7 +237,7 @@ colorFunctions = {
195
237
  hsl.l -= amount.value / 100;
196
238
  }
197
239
  hsl.l = clamp(hsl.l);
198
- return hsla(hsl);
240
+ return hsla(color, hsl);
199
241
  },
200
242
  fadein: function (color, amount, method) {
201
243
  var hsl = color.toHSL();
@@ -207,7 +249,7 @@ colorFunctions = {
207
249
  hsl.a += amount.value / 100;
208
250
  }
209
251
  hsl.a = clamp(hsl.a);
210
- return hsla(hsl);
252
+ return hsla(color, hsl);
211
253
  },
212
254
  fadeout: function (color, amount, method) {
213
255
  var hsl = color.toHSL();
@@ -219,14 +261,14 @@ colorFunctions = {
219
261
  hsl.a -= amount.value / 100;
220
262
  }
221
263
  hsl.a = clamp(hsl.a);
222
- return hsla(hsl);
264
+ return hsla(color, hsl);
223
265
  },
224
266
  fade: function (color, amount) {
225
267
  var hsl = color.toHSL();
226
268
 
227
269
  hsl.a = amount.value / 100;
228
270
  hsl.a = clamp(hsl.a);
229
- return hsla(hsl);
271
+ return hsla(color, hsl);
230
272
  },
231
273
  spin: function (color, amount) {
232
274
  var hsl = color.toHSL();
@@ -234,7 +276,7 @@ colorFunctions = {
234
276
 
235
277
  hsl.h = hue < 0 ? 360 + hue : hue;
236
278
 
237
- return hsla(hsl);
279
+ return hsla(color, hsl);
238
280
  },
239
281
  //
240
282
  // Copyright (c) 2006-2009 Hampton Catlin, Natalie Weizenbaum, and Chris Eppstein
@@ -338,8 +380,9 @@ colorFunctions = {
338
380
  },
339
381
  color: function(c) {
340
382
  if ((c instanceof Quoted) &&
341
- (/^#([a-f0-9]{6}|[a-f0-9]{3})$/i.test(c.value))) {
342
- return new Color(c.value.slice(1));
383
+ (/^#([A-Fa-f0-9]{8}|[A-Fa-f0-9]{6}|[A-Fa-f0-9]{3,4})$/i.test(c.value))) {
384
+ var val = c.value.slice(1);
385
+ return new Color(val, undefined, '#' + val);
343
386
  }
344
387
  if ((c instanceof Color) || (c = Color.fromKeyword(c.value))) {
345
388
  c.value = undefined;
@@ -347,7 +390,7 @@ colorFunctions = {
347
390
  }
348
391
  throw {
349
392
  type: 'Argument',
350
- message: 'argument must be a color keyword or 3/6 digit hex e.g. #FFF'
393
+ message: 'argument must be a color keyword or 3|4|6|8 digit hex e.g. #FFF'
351
394
  };
352
395
  },
353
396
  tint: function(color, amount) {
@@ -18,7 +18,7 @@ module.exports = function(environment) {
18
18
  var mimetype = mimetypeNode && mimetypeNode.value;
19
19
  var filePath = filePathNode.value;
20
20
  var currentFileInfo = this.currentFileInfo;
21
- var currentDirectory = currentFileInfo.relativeUrls ?
21
+ var currentDirectory = currentFileInfo.rewriteUrls ?
22
22
  currentFileInfo.currentDirectory : currentFileInfo.entryPath;
23
23
 
24
24
  var fragmentStart = filePath.indexOf('#');
@@ -10,6 +10,7 @@ module.exports = function(environment) {
10
10
  require('./color');
11
11
  require('./color-blending');
12
12
  require('./data-uri')(environment);
13
+ require('./list');
13
14
  require('./math');
14
15
  require('./number');
15
16
  require('./string');
@@ -0,0 +1,101 @@
1
+ var Dimension = require('../tree/dimension'),
2
+ Declaration = require('../tree/declaration'),
3
+ Ruleset = require('../tree/ruleset'),
4
+ Selector = require('../tree/selector'),
5
+ Element = require('../tree/element'),
6
+ functionRegistry = require('./function-registry');
7
+
8
+ var getItemsFromNode = function(node) {
9
+ // handle non-array values as an array of length 1
10
+ // return 'undefined' if index is invalid
11
+ var items = Array.isArray(node.value) ?
12
+ node.value : Array(node);
13
+
14
+ return items;
15
+ };
16
+
17
+ functionRegistry.addMultiple({
18
+ _SELF: function(n) {
19
+ return n;
20
+ },
21
+ extract: function(values, index) {
22
+ index = index.value - 1; // (1-based index)
23
+
24
+ return getItemsFromNode(values)[index];
25
+ },
26
+ length: function(values) {
27
+ return new Dimension(getItemsFromNode(values).length);
28
+ },
29
+ each: function(list, rs) {
30
+ var i = 0, rules = [], newRules, iterator;
31
+
32
+ if (list.value) {
33
+ if (Array.isArray(list.value)) {
34
+ iterator = list.value;
35
+ } else {
36
+ iterator = [list.value];
37
+ }
38
+ } else if (list.ruleset) {
39
+ iterator = list.ruleset.rules;
40
+ } else if (Array.isArray(list)) {
41
+ iterator = list;
42
+ } else {
43
+ iterator = [list];
44
+ }
45
+
46
+ var valueName = '@value',
47
+ keyName = '@key',
48
+ indexName = '@index';
49
+
50
+ if (rs.params) {
51
+ valueName = rs.params[0] && rs.params[0].name;
52
+ keyName = rs.params[1] && rs.params[1].name;
53
+ indexName = rs.params[2] && rs.params[2].name;
54
+ rs = rs.rules;
55
+ } else {
56
+ rs = rs.ruleset;
57
+ }
58
+
59
+ iterator.forEach(function(item) {
60
+ i = i + 1;
61
+ var key, value;
62
+ if (item instanceof Declaration) {
63
+ key = typeof item.name === 'string' ? item.name : item.name[0].value;
64
+ value = item.value;
65
+ } else {
66
+ key = new Dimension(i);
67
+ value = item;
68
+ }
69
+
70
+ newRules = rs.rules.slice(0);
71
+ if (valueName) {
72
+ newRules.push(new Declaration(valueName,
73
+ value,
74
+ false, false, this.index, this.currentFileInfo));
75
+ }
76
+ if (indexName) {
77
+ newRules.push(new Declaration(indexName,
78
+ new Dimension(i),
79
+ false, false, this.index, this.currentFileInfo));
80
+ }
81
+ if (keyName) {
82
+ newRules.push(new Declaration(keyName,
83
+ key,
84
+ false, false, this.index, this.currentFileInfo));
85
+ }
86
+
87
+ rules.push(new Ruleset([ new(Selector)([ new Element("", '&') ]) ],
88
+ newRules,
89
+ rs.strictImports,
90
+ rs.visibilityInfo()
91
+ ));
92
+ });
93
+
94
+ return new Ruleset([ new(Selector)([ new Element("", '&') ]) ],
95
+ rules,
96
+ rs.strictImports,
97
+ rs.visibilityInfo()
98
+ ).eval(this.context);
99
+
100
+ }
101
+ });
@@ -20,15 +20,8 @@ var isa = function (n, Type) {
20
20
  throw { type: 'Argument', message: 'Second argument to isunit should be a unit or a string.' };
21
21
  }
22
22
  return (n instanceof Dimension) && n.unit.is(unit) ? Keyword.True : Keyword.False;
23
- },
24
- getItemsFromNode = function(node) {
25
- // handle non-array values as an array of length 1
26
- // return 'undefined' if index is invalid
27
- var items = Array.isArray(node.value) ?
28
- node.value : Array(node);
29
-
30
- return items;
31
23
  };
24
+
32
25
  functionRegistry.addMultiple({
33
26
  isruleset: function (n) {
34
27
  return isa(n, DetachedRuleset);
@@ -77,16 +70,5 @@ functionRegistry.addMultiple({
77
70
  },
78
71
  'get-unit': function (n) {
79
72
  return new Anonymous(n.unit);
80
- },
81
- extract: function(values, index) {
82
- index = index.value - 1; // (1-based index)
83
-
84
- return getItemsFromNode(values)[index];
85
- },
86
- length: function(values) {
87
- return new Dimension(getItemsFromNode(values).length);
88
- },
89
- _SELF: function(n) {
90
- return n;
91
73
  }
92
74
  });
@@ -8,7 +8,7 @@ var contexts = require('./contexts'),
8
8
  module.exports = function(environment) {
9
9
 
10
10
  // FileInfo = {
11
- // 'relativeUrls' - option - whether to adjust URL's to be relative
11
+ // 'rewriteUrls' - option - whether to adjust URL's to be relative
12
12
  // 'filename' - full resolved filename of current file
13
13
  // 'rootpath' - path to append to normal URLs for this node
14
14
  // 'currentDirectory' - path to the current file, absolute
@@ -65,7 +65,7 @@ module.exports = function(environment) {
65
65
  };
66
66
 
67
67
  var newFileInfo = {
68
- relativeUrls: this.context.relativeUrls,
68
+ rewriteUrls: this.context.rewriteUrls,
69
69
  entryPath: currentFileInfo.entryPath,
70
70
  rootpath: currentFileInfo.rootpath,
71
71
  rootFilename: currentFileInfo.rootFilename
@@ -92,7 +92,7 @@ module.exports = function(environment) {
92
92
  // - If path of imported file is '../mixins.less' and rootpath is 'less/',
93
93
  // then rootpath should become 'less/../'
94
94
  newFileInfo.currentDirectory = fileManager.getPath(resolvedFilename);
95
- if (newFileInfo.relativeUrls) {
95
+ if (newFileInfo.rewriteUrls) {
96
96
  newFileInfo.rootpath = fileManager.join(
97
97
  (importManager.context.rootpath || ''),
98
98
  fileManager.pathDiff(newFileInfo.currentDirectory, newFileInfo.entryPath));
package/lib/less/index.js CHANGED
@@ -2,7 +2,7 @@ module.exports = function(environment, fileManagers) {
2
2
  var SourceMapOutput, SourceMapBuilder, ParseTree, ImportManager, Environment;
3
3
 
4
4
  var initial = {
5
- version: [3, 6, 0],
5
+ version: [3, 8, 1],
6
6
  data: require('./data'),
7
7
  tree: require('./tree'),
8
8
  Environment: (Environment = require('./environment/environment')),
package/lib/less/parse.js CHANGED
@@ -10,10 +10,10 @@ module.exports = function(environment, ParseTree, ImportManager) {
10
10
 
11
11
  if (typeof options === 'function') {
12
12
  callback = options;
13
- options = utils.defaults(this.options, {});
13
+ options = utils.copyOptions(this.options, {});
14
14
  }
15
15
  else {
16
- options = utils.defaults(this.options, options || {});
16
+ options = utils.copyOptions(this.options, options || {});
17
17
  }
18
18
 
19
19
  if (!callback) {
@@ -46,7 +46,7 @@ module.exports = function(environment, ParseTree, ImportManager) {
46
46
  var entryPath = filename.replace(/[^\/\\]*$/, '');
47
47
  rootFileInfo = {
48
48
  filename: filename,
49
- relativeUrls: context.relativeUrls,
49
+ rewriteUrls: context.rewriteUrls,
50
50
  rootpath: context.rootpath || '',
51
51
  currentDirectory: entryPath,
52
52
  entryPath: entryPath,