less 2.3.0 → 2.3.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 (172) hide show
  1. checksums.yaml +4 -4
  2. data/lib/less/js/.gitignore +7 -0
  3. data/lib/less/js/.npmignore +1 -0
  4. data/lib/less/js/CHANGELOG.md +118 -0
  5. data/lib/less/js/CONTRIBUTING.md +50 -0
  6. data/lib/less/js/Makefile +14 -2
  7. data/lib/less/js/bin/lessc +72 -21
  8. data/lib/less/js/dist/less-1.3.1.js +4011 -0
  9. data/lib/less/js/dist/less-1.3.1.min.js +9 -0
  10. data/lib/less/js/dist/less-1.3.2.js +4401 -0
  11. data/lib/less/js/dist/less-1.3.2.min.js +9 -0
  12. data/lib/less/js/dist/less-1.3.3.js +4413 -0
  13. data/lib/less/js/dist/less-1.3.3.min.js +9 -0
  14. data/lib/less/js/dist/less-rhino-1.3.1.js +3725 -0
  15. data/lib/less/js/dist/less-rhino-1.3.2.js +3990 -0
  16. data/lib/less/js/dist/less-rhino-1.3.3.js +4002 -0
  17. data/lib/less/js/lib/less/browser.js +192 -53
  18. data/lib/less/js/lib/less/colors.js +1 -0
  19. data/lib/less/js/lib/less/functions.js +159 -10
  20. data/lib/less/js/lib/less/index.js +124 -56
  21. data/lib/less/js/lib/less/lessc_helper.js +62 -0
  22. data/lib/less/js/lib/less/parser.js +352 -135
  23. data/lib/less/js/lib/less/rhino.js +84 -23
  24. data/lib/less/js/lib/less/tree.js +28 -0
  25. data/lib/less/js/lib/less/tree/anonymous.js +15 -1
  26. data/lib/less/js/lib/less/tree/assignment.js +3 -1
  27. data/lib/less/js/lib/less/tree/call.js +12 -6
  28. data/lib/less/js/lib/less/tree/color.js +10 -0
  29. data/lib/less/js/lib/less/tree/dimension.js +3 -1
  30. data/lib/less/js/lib/less/tree/directive.js +9 -5
  31. data/lib/less/js/lib/less/tree/element.js +8 -6
  32. data/lib/less/js/lib/less/tree/import.js +16 -13
  33. data/lib/less/js/lib/less/tree/media.js +16 -9
  34. data/lib/less/js/lib/less/tree/mixin.js +123 -46
  35. data/lib/less/js/lib/less/tree/operation.js +5 -0
  36. data/lib/less/js/lib/less/tree/quoted.js +15 -1
  37. data/lib/less/js/lib/less/tree/ratio.js +13 -0
  38. data/lib/less/js/lib/less/tree/rule.js +7 -0
  39. data/lib/less/js/lib/less/tree/ruleset.js +232 -34
  40. data/lib/less/js/lib/less/tree/selector.js +21 -11
  41. data/lib/less/js/lib/less/tree/unicode-descriptor.js +13 -0
  42. data/lib/less/js/lib/less/tree/url.js +16 -14
  43. data/lib/less/js/lib/less/tree/variable.js +13 -1
  44. data/lib/less/js/package.json +13 -3
  45. data/lib/less/js/test/browser-test-prepare.js +29 -0
  46. data/lib/less/js/test/browser/common.js +74 -0
  47. data/lib/less/js/test/browser/css/relative-urls/urls.css +36 -0
  48. data/lib/less/js/test/browser/css/rootpath-relative/urls.css +36 -0
  49. data/lib/less/js/test/browser/css/rootpath/urls.css +36 -0
  50. data/lib/less/js/test/browser/css/urls.css +36 -0
  51. data/lib/less/js/test/browser/jasmine-html.js +681 -0
  52. data/lib/less/js/test/browser/jasmine.css +82 -0
  53. data/lib/less/js/test/browser/jasmine.js +2600 -0
  54. data/lib/less/js/test/browser/less/imports/urls.less +4 -0
  55. data/lib/less/js/test/browser/less/imports/urls2.less +4 -0
  56. data/lib/less/js/test/browser/less/relative-urls/urls.less +33 -0
  57. data/lib/less/js/test/browser/less/rootpath-relative/urls.less +33 -0
  58. data/lib/less/js/test/browser/less/rootpath/urls.less +33 -0
  59. data/lib/less/js/test/browser/less/urls.less +33 -0
  60. data/lib/less/js/test/browser/phantom-runner.js +139 -0
  61. data/lib/less/js/test/browser/runner-browser.js +3 -0
  62. data/lib/less/js/test/browser/runner-main.js +15 -0
  63. data/lib/less/js/test/browser/runner-relative-urls.js +4 -0
  64. data/lib/less/js/test/browser/runner-rootpath-relative.js +5 -0
  65. data/lib/less/js/test/browser/runner-rootpath.js +4 -0
  66. data/lib/less/js/test/browser/template.htm +10 -0
  67. data/lib/less/js/test/css/charsets.css +1 -0
  68. data/lib/less/js/test/css/colors.css +22 -0
  69. data/lib/less/js/test/css/comments.css +7 -0
  70. data/lib/less/js/test/css/css-3.css +57 -2
  71. data/lib/less/js/test/css/css-escapes.css +4 -0
  72. data/lib/less/js/test/css/css.css +11 -11
  73. data/lib/less/js/test/css/debug/linenumbers-all.css +43 -0
  74. data/lib/less/js/test/css/debug/linenumbers-comments.css +35 -0
  75. data/lib/less/js/test/css/debug/linenumbers-mediaquery.css +35 -0
  76. data/lib/less/js/test/css/functions.css +59 -2
  77. data/lib/less/js/test/css/ie-filters.css +7 -3
  78. data/lib/less/js/test/css/import-once.css +3 -0
  79. data/lib/less/js/test/css/import.css +7 -9
  80. data/lib/less/js/test/css/javascript.css +3 -2
  81. data/lib/less/js/test/css/media.css +116 -0
  82. data/lib/less/js/test/css/mixins-args.css +23 -4
  83. data/lib/less/js/test/css/mixins-guards.css +13 -0
  84. data/lib/less/js/test/css/mixins-important.css +21 -0
  85. data/lib/less/js/test/css/mixins-named-args.css +27 -0
  86. data/lib/less/js/test/css/mixins.css +50 -0
  87. data/lib/less/js/test/css/scope.css +20 -0
  88. data/lib/less/js/test/css/selectors.css +64 -0
  89. data/lib/less/js/test/css/static-urls/urls.css +42 -0
  90. data/lib/less/js/test/css/strings.css +2 -2
  91. data/lib/less/js/test/css/urls.css +42 -0
  92. data/lib/less/js/test/css/variables.css +0 -1
  93. data/lib/less/js/test/css/whitespace.css +4 -0
  94. data/lib/less/js/test/less-test.js +145 -36
  95. data/lib/less/js/test/less/charsets.less +3 -0
  96. data/lib/less/js/test/less/colors.less +27 -0
  97. data/lib/less/js/test/less/comments.less +12 -0
  98. data/lib/less/js/test/less/css-3.less +54 -6
  99. data/lib/less/js/test/less/css-escapes.less +6 -1
  100. data/lib/less/js/test/less/css.less +14 -12
  101. data/lib/less/js/test/less/debug/import/test.less +25 -0
  102. data/lib/less/js/test/less/debug/linenumbers.less +23 -0
  103. data/lib/less/js/test/less/errors/bad-variable-declaration1.less +1 -0
  104. data/lib/less/js/test/less/errors/bad-variable-declaration1.txt +2 -0
  105. data/lib/less/js/test/less/errors/comment-in-selector.less +1 -0
  106. data/lib/less/js/test/less/errors/comment-in-selector.txt +2 -0
  107. data/lib/less/js/test/less/errors/import-missing.less +1 -0
  108. data/lib/less/js/test/less/errors/import-missing.txt +3 -0
  109. data/lib/less/js/test/less/errors/import-no-semi.less +1 -0
  110. data/lib/less/js/test/less/errors/import-no-semi.txt +2 -0
  111. data/lib/less/js/test/less/errors/import-subfolder1.less +1 -0
  112. data/lib/less/js/test/less/errors/import-subfolder1.txt +3 -0
  113. data/lib/less/js/test/less/errors/import-subfolder2.less +1 -0
  114. data/lib/less/js/test/less/errors/import-subfolder2.txt +2 -0
  115. data/lib/less/js/test/less/errors/imports/import-subfolder1.less +1 -0
  116. data/lib/less/js/test/less/errors/imports/import-subfolder2.less +1 -0
  117. data/lib/less/js/test/less/errors/imports/import-test.less +4 -0
  118. data/lib/less/js/test/less/errors/imports/subfolder/mixin-not-defined.less +1 -0
  119. data/lib/less/js/test/less/errors/imports/subfolder/parse-error-curly-bracket.less +1 -0
  120. data/lib/less/js/test/less/errors/javascript-error.less +3 -0
  121. data/lib/less/js/test/less/errors/javascript-error.txt +4 -0
  122. data/lib/less/js/test/less/errors/mixed-mixin-definition-args-1.less +6 -0
  123. data/lib/less/js/test/less/errors/mixed-mixin-definition-args-1.txt +4 -0
  124. data/lib/less/js/test/less/errors/mixed-mixin-definition-args-2.less +6 -0
  125. data/lib/less/js/test/less/errors/mixed-mixin-definition-args-2.txt +4 -0
  126. data/lib/less/js/test/less/errors/mixin-not-defined.less +11 -0
  127. data/lib/less/js/test/less/errors/mixin-not-defined.txt +3 -0
  128. data/lib/less/js/test/less/errors/mixin-not-matched.less +6 -0
  129. data/lib/less/js/test/less/errors/mixin-not-matched.txt +3 -0
  130. data/lib/less/js/test/less/errors/mixin-not-matched2.less +6 -0
  131. data/lib/less/js/test/less/errors/mixin-not-matched2.txt +3 -0
  132. data/lib/less/js/test/less/errors/parse-error-curly-bracket.less +1 -0
  133. data/lib/less/js/test/less/errors/parse-error-curly-bracket.txt +2 -0
  134. data/lib/less/js/test/less/errors/parse-error-missing-bracket.less +2 -0
  135. data/lib/less/js/test/less/errors/parse-error-missing-bracket.txt +2 -0
  136. data/lib/less/js/test/less/errors/parse-error-with-import.less +13 -0
  137. data/lib/less/js/test/less/errors/parse-error-with-import.txt +4 -0
  138. data/lib/less/js/test/less/errors/property-ie5-hack.less +3 -0
  139. data/lib/less/js/test/less/errors/property-ie5-hack.txt +4 -0
  140. data/lib/less/js/test/less/errors/recursive-variable.less +1 -0
  141. data/lib/less/js/test/less/errors/recursive-variable.txt +2 -0
  142. data/lib/less/js/test/less/functions.less +64 -2
  143. data/lib/less/js/test/less/ie-filters.less +7 -0
  144. data/lib/less/js/test/less/import-once.less +4 -0
  145. data/lib/less/js/test/less/import.less +2 -1
  146. data/lib/less/js/test/less/import/deeper/import-once-test-a.less +1 -0
  147. data/lib/less/js/test/less/import/import-and-relative-paths-test.less +6 -0
  148. data/lib/less/js/test/less/import/import-charset-test.less +1 -0
  149. data/lib/less/js/test/less/import/import-once-test-c.less +6 -0
  150. data/lib/less/js/test/less/import/import-test-a.less +1 -0
  151. data/lib/less/js/test/less/import/import-test-c.less +0 -1
  152. data/lib/less/js/test/less/import/imports/font.less +8 -0
  153. data/lib/less/js/test/less/import/imports/logo.less +5 -0
  154. data/lib/less/js/test/less/import/urls.less +1 -0
  155. data/lib/less/js/test/less/javascript.less +4 -2
  156. data/lib/less/js/test/less/media.less +120 -0
  157. data/lib/less/js/test/less/mixins-args.less +40 -10
  158. data/lib/less/js/test/less/mixins-guards.less +30 -0
  159. data/lib/less/js/test/less/mixins-important.less +4 -0
  160. data/lib/less/js/test/less/mixins-named-args.less +36 -0
  161. data/lib/less/js/test/less/mixins.less +47 -0
  162. data/lib/less/js/test/less/scope.less +48 -1
  163. data/lib/less/js/test/less/selectors.less +81 -0
  164. data/lib/less/js/test/less/static-urls/urls.less +33 -0
  165. data/lib/less/js/test/less/strings.less +1 -1
  166. data/lib/less/js/test/less/urls.less +33 -0
  167. data/lib/less/js/test/less/variables.less +0 -1
  168. data/lib/less/js/test/less/whitespace.less +7 -0
  169. data/lib/less/version.rb +1 -1
  170. metadata +101 -4
  171. data/lib/less/js/CHANGELOG +0 -41
  172. data/lib/less/js/lib/less/cssmin.js +0 -355
@@ -2,10 +2,7 @@
2
2
  // browser.js - client-side engine
3
3
  //
4
4
 
5
- var isFileProtocol = (location.protocol === 'file:' ||
6
- location.protocol === 'chrome:' ||
7
- location.protocol === 'chrome-extension:' ||
8
- location.protocol === 'resource:');
5
+ var isFileProtocol = /^(file|chrome(-extension)?|resource|qrc|app):/.test(location.protocol);
9
6
 
10
7
  less.env = less.env || (location.hostname == '127.0.0.1' ||
11
8
  location.hostname == '0.0.0.0' ||
@@ -20,42 +17,64 @@ less.env = less.env || (location.hostname == '127.0.0.1' ||
20
17
  // doesn't start loading before the stylesheets are parsed.
21
18
  // Setting this to `true` can result in flickering.
22
19
  //
23
- less.async = false;
20
+ less.async = less.async || false;
21
+ less.fileAsync = less.fileAsync || false;
24
22
 
25
23
  // Interval between watch polls
26
24
  less.poll = less.poll || (isFileProtocol ? 1000 : 1500);
27
25
 
26
+ //Setup user functions
27
+ if (less.functions) {
28
+ for(var func in less.functions) {
29
+ less.tree.functions[func] = less.functions[func];
30
+ }
31
+ }
32
+
33
+ var dumpLineNumbers = /!dumpLineNumbers:(comments|mediaquery|all)/.exec(location.hash);
34
+ if (dumpLineNumbers) {
35
+ less.dumpLineNumbers = dumpLineNumbers[1];
36
+ }
37
+
28
38
  //
29
39
  // Watch mode
30
40
  //
31
- less.watch = function () { return this.watchMode = true };
32
- less.unwatch = function () { return this.watchMode = false };
41
+ less.watch = function () {
42
+ if (!less.watchMode ){
43
+ less.env = 'development';
44
+ initRunningMode();
45
+ }
46
+ return this.watchMode = true
47
+ };
33
48
 
34
- if (less.env === 'development') {
35
- less.optimization = 0;
49
+ less.unwatch = function () {clearInterval(less.watchTimer); return this.watchMode = false; };
50
+
51
+ function initRunningMode(){
52
+ if (less.env === 'development') {
53
+ less.optimization = 0;
54
+ less.watchTimer = setInterval(function () {
55
+ if (less.watchMode) {
56
+ loadStyleSheets(function (e, root, _, sheet, env) {
57
+ if (root) {
58
+ createCSS(root.toCSS(), sheet, env.lastModified);
59
+ }
60
+ });
61
+ }
62
+ }, less.poll);
63
+ } else {
64
+ less.optimization = 3;
65
+ }
66
+ }
36
67
 
37
- if (/!watch/.test(location.hash)) {
38
- less.watch();
39
- }
40
- less.watchTimer = setInterval(function () {
41
- if (less.watchMode) {
42
- loadStyleSheets(function (e, root, _, sheet, env) {
43
- if (root) {
44
- createCSS(root.toCSS(), sheet, env.lastModified);
45
- }
46
- });
47
- }
48
- }, less.poll);
49
- } else {
50
- less.optimization = 3;
68
+ if (/!watch/.test(location.hash)) {
69
+ less.watch();
51
70
  }
52
71
 
53
- var cache;
72
+ var cache = null;
54
73
 
55
- try {
56
- cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage;
57
- } catch (_) {
58
- cache = null;
74
+ if (less.env != 'development') {
75
+ try {
76
+ cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage;
77
+ } catch (_) {}
59
78
  }
60
79
 
61
80
  //
@@ -73,6 +92,21 @@ for (var i = 0; i < links.length; i++) {
73
92
  }
74
93
  }
75
94
 
95
+ //
96
+ // With this function, it's possible to alter variables and re-render
97
+ // CSS without reloading less-files
98
+ //
99
+ var session_cache = '';
100
+ less.modifyVars = function(record) {
101
+ var str = session_cache;
102
+ for (name in record) {
103
+ str += ((name.slice(0,1) === '@')? '' : '@') + name +': '+
104
+ ((record[name].slice(-1) === ';')? record[name] : record[name] +';');
105
+ }
106
+ new(less.Parser)().parse(str, function (e, root) {
107
+ createCSS(root.toCSS(), less.sheets[less.sheets.length - 1]);
108
+ });
109
+ };
76
110
 
77
111
  less.refresh = function (reload) {
78
112
  var startTime, endTime;
@@ -100,7 +134,10 @@ function loadStyles() {
100
134
  var styles = document.getElementsByTagName('style');
101
135
  for (var i = 0; i < styles.length; i++) {
102
136
  if (styles[i].type.match(typePattern)) {
103
- new(less.Parser)().parse(styles[i].innerHTML || '', function (e, tree) {
137
+ new(less.Parser)({
138
+ filename: document.location.href.replace(/#.*$/, ''),
139
+ dumpLineNumbers: less.dumpLineNumbers
140
+ }).parse(styles[i].innerHTML || '', function (e, tree) {
104
141
  var css = tree.toCSS();
105
142
  var style = styles[i];
106
143
  style.type = 'text/css';
@@ -120,42 +157,139 @@ function loadStyleSheets(callback, reload) {
120
157
  }
121
158
  }
122
159
 
160
+ function pathDiff(url, baseUrl) {
161
+ // diff between two paths to create a relative path
162
+
163
+ var urlParts = extractUrlParts(url),
164
+ baseUrlParts = extractUrlParts(baseUrl),
165
+ i, max, urlDirectories, baseUrlDirectories, diff = "";
166
+ if (urlParts.hostPart !== baseUrlParts.hostPart) {
167
+ return "";
168
+ }
169
+ max = Math.max(baseUrlParts.directories.length, urlParts.directories.length);
170
+ for(i = 0; i < max; i++) {
171
+ if (baseUrlParts.directories[i] !== urlParts.directories[i]) { break; }
172
+ }
173
+ baseUrlDirectories = baseUrlParts.directories.slice(i);
174
+ urlDirectories = urlParts.directories.slice(i);
175
+ for(i = 0; i < baseUrlDirectories.length-1; i++) {
176
+ diff += "../";
177
+ }
178
+ for(i = 0; i < urlDirectories.length-1; i++) {
179
+ diff += urlDirectories[i] + "/";
180
+ }
181
+ return diff;
182
+ }
183
+
184
+ function extractUrlParts(url, baseUrl) {
185
+ // urlParts[1] = protocol&hostname || /
186
+ // urlParts[2] = / if path relative to host base
187
+ // urlParts[3] = directories
188
+ // urlParts[4] = filename
189
+ // urlParts[5] = parameters
190
+
191
+ var urlPartsRegex = /^((?:[a-z-]+:)?\/\/(?:[^\/\?#]+\/)|([\/\\]))?((?:[^\/\\\?#]+[\/\\])*)([^\/\\\?#]*)([#\?].*)?$/,
192
+ urlParts = url.match(urlPartsRegex),
193
+ returner = {}, directories = [], i, baseUrlParts;
194
+
195
+ if (!urlParts) {
196
+ throw new Error("Could not parse sheet href - '"+url+"'");
197
+ }
198
+
199
+ // Stylesheets in IE don't always return the full path
200
+ if (!urlParts[1] || urlParts[2]) {
201
+ baseUrlParts = baseUrl.match(urlPartsRegex);
202
+ if (!baseUrlParts) {
203
+ throw new Error("Could not parse page url - '"+baseUrl+"'");
204
+ }
205
+ urlParts[1] = baseUrlParts[1];
206
+ if (!urlParts[2]) {
207
+ urlParts[3] = baseUrlParts[3] + urlParts[3];
208
+ }
209
+ }
210
+
211
+ if (urlParts[3]) {
212
+ directories = urlParts[3].replace("\\", "/").split("/");
213
+
214
+ for(i = 0; i < directories.length; i++) {
215
+ if (directories[i] === ".." && i > 0) {
216
+ directories.splice(i-1, 2);
217
+ i -= 2;
218
+ }
219
+ }
220
+ }
221
+
222
+ returner.hostPart = urlParts[1];
223
+ returner.directories = directories;
224
+ returner.path = urlParts[1] + directories.join("/");
225
+ returner.fileUrl = returner.path + (urlParts[4] || "");
226
+ returner.url = returner.fileUrl + (urlParts[5] || "");
227
+ return returner;
228
+ }
229
+
123
230
  function loadStyleSheet(sheet, callback, reload, remaining) {
124
- var url = window.location.href.replace(/[#?].*$/, '');
125
- var href = sheet.href.replace(/\?.*$/, '');
231
+ // sheet may be set to the stylesheet for the initial load or a collection of properties including
232
+ // some env variables for imports
233
+ var contents = sheet.contents || {};
234
+ var files = sheet.files || {};
235
+ var hrefParts = extractUrlParts(sheet.href, window.location.href);
236
+ var href = hrefParts.url;
126
237
  var css = cache && cache.getItem(href);
127
238
  var timestamp = cache && cache.getItem(href + ':timestamp');
128
239
  var styles = { css: css, timestamp: timestamp };
240
+ var rootpath;
129
241
 
130
- // Stylesheets in IE don't always return the full path
131
- if (! /^(https?|file):/.test(href)) {
132
- if (href.charAt(0) == "/") {
133
- href = window.location.protocol + "//" + window.location.host + href;
242
+ if (less.relativeUrls) {
243
+ if (less.rootpath) {
244
+ if (sheet.entryPath) {
245
+ rootpath = extractUrlParts(less.rootpath + pathDiff(hrefParts.path, sheet.entryPath)).path;
246
+ } else {
247
+ rootpath = less.rootpath;
248
+ }
134
249
  } else {
135
- href = url.slice(0, url.lastIndexOf('/') + 1) + href;
250
+ rootpath = hrefParts.path;
251
+ }
252
+ } else {
253
+ if (less.rootpath) {
254
+ rootpath = less.rootpath;
255
+ } else {
256
+ if (sheet.entryPath) {
257
+ rootpath = sheet.entryPath;
258
+ } else {
259
+ rootpath = hrefParts.path;
260
+ }
136
261
  }
137
262
  }
138
- var filename = href.match(/([^\/]+)$/)[1];
139
263
 
140
- xhr(sheet.href, sheet.type, function (data, lastModified) {
264
+ xhr(href, sheet.type, function (data, lastModified) {
265
+ // Store data this session
266
+ session_cache += data.replace(/@import .+?;/ig, '');
267
+
141
268
  if (!reload && styles && lastModified &&
142
269
  (new(Date)(lastModified).valueOf() ===
143
270
  new(Date)(styles.timestamp).valueOf())) {
144
271
  // Use local copy
145
272
  createCSS(styles.css, sheet);
146
- callback(null, null, data, sheet, { local: true, remaining: remaining });
273
+ callback(null, null, data, sheet, { local: true, remaining: remaining }, href);
147
274
  } else {
148
275
  // Use remote copy (re-parse)
149
276
  try {
277
+ contents[href] = data; // Updating top importing parser content cache
150
278
  new(less.Parser)({
151
279
  optimization: less.optimization,
152
- paths: [href.replace(/[\w\.-]+$/, '')],
280
+ paths: [hrefParts.path],
281
+ entryPath: sheet.entryPath || hrefParts.path,
153
282
  mime: sheet.type,
154
- filename: filename
283
+ filename: href,
284
+ rootpath: rootpath,
285
+ relativeUrls: sheet.relativeUrls,
286
+ contents: contents, // Passing top importing parser content cache ref down.
287
+ files: files,
288
+ dumpLineNumbers: less.dumpLineNumbers
155
289
  }).parse(data, function (e, root) {
156
290
  if (e) { return error(e, href) }
157
291
  try {
158
- callback(e, root, data, sheet, { local: false, lastModified: lastModified, remaining: remaining });
292
+ callback(e, root, data, sheet, { local: false, lastModified: lastModified, remaining: remaining }, href);
159
293
  removeNode(document.getElementById('less-error-message:' + extractId(href)));
160
294
  } catch (e) {
161
295
  error(e, href);
@@ -173,8 +307,7 @@ function loadStyleSheet(sheet, callback, reload, remaining) {
173
307
  function extractId(href) {
174
308
  return href.replace(/^[a-z]+:\/\/?[^\/]+/, '' ) // Remove protocol & domain
175
309
  .replace(/^\//, '' ) // Remove root /
176
- .replace(/\?.*$/, '' ) // Remove query
177
- .replace(/\.[^\.\/]+$/, '' ) // Remove file extension
310
+ .replace(/\.[a-zA-Z]+$/, '' ) // Remove simple extension
178
311
  .replace(/[^\.\w-]+/g, '-') // Replace illegal characters
179
312
  .replace(/\./g, ':'); // Replace dots with colons(for valid id)
180
313
  }
@@ -183,7 +316,7 @@ function createCSS(styles, sheet, lastModified) {
183
316
  var css;
184
317
 
185
318
  // Strip the query-string
186
- var href = sheet.href ? sheet.href.replace(/\?.*$/, '') : '';
319
+ var href = sheet.href || '';
187
320
 
188
321
  // If there is no title set, use the filename, minus the extension
189
322
  var id = 'less:' + (sheet.title || extractId(href));
@@ -192,9 +325,10 @@ function createCSS(styles, sheet, lastModified) {
192
325
  if ((css = document.getElementById(id)) === null) {
193
326
  css = document.createElement('style');
194
327
  css.type = 'text/css';
195
- css.media = sheet.media || 'screen';
328
+ if( sheet.media ){ css.media = sheet.media; }
196
329
  css.id = id;
197
- document.getElementsByTagName('head')[0].appendChild(css);
330
+ var nextEl = sheet && sheet.nextSibling || null;
331
+ (nextEl || document.getElementsByTagName('head')[0]).parentNode.insertBefore(css, nextEl);
198
332
  }
199
333
 
200
334
  if (css.styleSheet) { // IE
@@ -218,14 +352,19 @@ function createCSS(styles, sheet, lastModified) {
218
352
  // Don't update the local store if the file wasn't modified
219
353
  if (lastModified && cache) {
220
354
  log('saving ' + href + ' to cache.');
221
- cache.setItem(href, styles);
222
- cache.setItem(href + ':timestamp', lastModified);
355
+ try {
356
+ cache.setItem(href, styles);
357
+ cache.setItem(href + ':timestamp', lastModified);
358
+ } catch(e) {
359
+ //TODO - could do with adding more robust error handling
360
+ log('failed to save');
361
+ }
223
362
  }
224
363
  }
225
364
 
226
365
  function xhr(url, type, callback, errback) {
227
366
  var xhr = getXMLHttpRequest();
228
- var async = isFileProtocol ? false : less.async;
367
+ var async = isFileProtocol ? less.fileAsync : less.async;
229
368
 
230
369
  if (typeof(xhr.overrideMimeType) === 'function') {
231
370
  xhr.overrideMimeType('text/css');
@@ -234,7 +373,7 @@ function xhr(url, type, callback, errback) {
234
373
  xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5');
235
374
  xhr.send(null);
236
375
 
237
- if (isFileProtocol) {
376
+ if (isFileProtocol && !less.fileAsync) {
238
377
  if (xhr.status === 0 || (xhr.status >= 200 && xhr.status < 300)) {
239
378
  callback(xhr.responseText);
240
379
  } else {
@@ -286,12 +425,13 @@ function error(e, href) {
286
425
  var template = '<li><label>{line}</label><pre class="{class}">{content}</pre></li>';
287
426
  var elem = document.createElement('div'), timer, content, error = [];
288
427
  var filename = e.filename || href;
428
+ var filenameNoPath = filename.match(/([^\/]+(\?.*)?)$/)[1];
289
429
 
290
430
  elem.id = id;
291
431
  elem.className = "less-error-message";
292
432
 
293
433
  content = '<h3>' + (e.message || 'There is an error in your .less file') +
294
- '</h3>' + '<p>in <a href="' + filename + '">' + filename + "</a> ";
434
+ '</h3>' + '<p>in <a href="' + filename + '">' + filenameNoPath + "</a> ";
295
435
 
296
436
  var errorline = function (e, i, classname) {
297
437
  if (e.extract[i]) {
@@ -377,4 +517,3 @@ function error(e, href) {
377
517
  }, 10);
378
518
  }
379
519
  }
380
-
@@ -140,6 +140,7 @@
140
140
  'teal':'#008080',
141
141
  'thistle':'#d8bfd8',
142
142
  'tomato':'#ff6347',
143
+ // 'transparent':'rgba(0,0,0,0)',
143
144
  'turquoise':'#40e0d0',
144
145
  'violet':'#ee82ee',
145
146
  'wheat':'#f5deb3',
@@ -5,8 +5,8 @@ tree.functions = {
5
5
  return this.rgba(r, g, b, 1.0);
6
6
  },
7
7
  rgba: function (r, g, b, a) {
8
- var rgb = [r, g, b].map(function (c) { return number(c) }),
9
- a = number(a);
8
+ var rgb = [r, g, b].map(function (c) { return scaled(c, 256); });
9
+ a = number(a);
10
10
  return new(tree.Color)(rgb, a);
11
11
  },
12
12
  hsl: function (h, s, l) {
@@ -32,6 +32,36 @@ tree.functions = {
32
32
  else return m1;
33
33
  }
34
34
  },
35
+
36
+ hsv: function(h, s, v) {
37
+ return this.hsva(h, s, v, 1.0);
38
+ },
39
+
40
+ hsva: function(h, s, v, a) {
41
+ h = ((number(h) % 360) / 360) * 360;
42
+ s = number(s); v = number(v); a = number(a);
43
+
44
+ var i, f;
45
+ i = Math.floor((h / 60) % 6);
46
+ f = (h / 60) - i;
47
+
48
+ var vs = [v,
49
+ v * (1 - s),
50
+ v * (1 - f * s),
51
+ v * (1 - (1 - f) * s)];
52
+ var perm = [[0, 3, 1],
53
+ [2, 0, 1],
54
+ [1, 0, 3],
55
+ [1, 2, 0],
56
+ [3, 1, 0],
57
+ [0, 1, 2]];
58
+
59
+ return this.rgba(vs[perm[i][0]] * 255,
60
+ vs[perm[i][1]] * 255,
61
+ vs[perm[i][2]] * 255,
62
+ a);
63
+ },
64
+
35
65
  hue: function (color) {
36
66
  return new(tree.Dimension)(Math.round(color.toHSL().h));
37
67
  },
@@ -41,9 +71,24 @@ tree.functions = {
41
71
  lightness: function (color) {
42
72
  return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%');
43
73
  },
74
+ red: function (color) {
75
+ return new(tree.Dimension)(color.rgb[0]);
76
+ },
77
+ green: function (color) {
78
+ return new(tree.Dimension)(color.rgb[1]);
79
+ },
80
+ blue: function (color) {
81
+ return new(tree.Dimension)(color.rgb[2]);
82
+ },
44
83
  alpha: function (color) {
45
84
  return new(tree.Dimension)(color.toHSL().a);
46
85
  },
86
+ luma: function (color) {
87
+ return new(tree.Dimension)(Math.round((0.2126 * (color.rgb[0]/255) +
88
+ 0.7152 * (color.rgb[1]/255) +
89
+ 0.0722 * (color.rgb[2]/255)) *
90
+ color.alpha * 100), '%');
91
+ },
47
92
  saturate: function (color, amount) {
48
93
  var hsl = color.toHSL();
49
94
 
@@ -106,6 +151,9 @@ tree.functions = {
106
151
  // http://sass-lang.com
107
152
  //
108
153
  mix: function (color1, color2, weight) {
154
+ if (!weight) {
155
+ weight = new(tree.Dimension)(50);
156
+ }
109
157
  var p = weight.value / 100.0;
110
158
  var w = p * 2 - 1;
111
159
  var a = color1.toHSL().a - color2.toHSL().a;
@@ -124,6 +172,29 @@ tree.functions = {
124
172
  greyscale: function (color) {
125
173
  return this.desaturate(color, new(tree.Dimension)(100));
126
174
  },
175
+ contrast: function (color, dark, light, threshold) {
176
+ // filter: contrast(3.2);
177
+ // should be kept as is, so check for color
178
+ if (!color.rgb) {
179
+ return null;
180
+ }
181
+ if (typeof light === 'undefined') {
182
+ light = this.rgba(255, 255, 255, 1.0);
183
+ }
184
+ if (typeof dark === 'undefined') {
185
+ dark = this.rgba(0, 0, 0, 1.0);
186
+ }
187
+ if (typeof threshold === 'undefined') {
188
+ threshold = 0.43;
189
+ } else {
190
+ threshold = threshold.value;
191
+ }
192
+ if (((0.2126 * (color.rgb[0]/255) + 0.7152 * (color.rgb[1]/255) + 0.0722 * (color.rgb[2]/255)) * color.alpha) < threshold) {
193
+ return light;
194
+ } else {
195
+ return dark;
196
+ }
197
+ },
127
198
  e: function (str) {
128
199
  return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str);
129
200
  },
@@ -143,20 +214,24 @@ tree.functions = {
143
214
  str = str.replace(/%%/g, '%');
144
215
  return new(tree.Quoted)('"' + str + '"', str);
145
216
  },
146
- round: function (n) {
147
- return this._math('round', n);
217
+ unit: function (val, unit) {
218
+ return new(tree.Dimension)(val.value, unit ? unit.toCSS() : "");
219
+ },
220
+ round: function (n, f) {
221
+ var fraction = typeof(f) === "undefined" ? 0 : f.value;
222
+ return this._math(function(num) { return num.toFixed(fraction); }, n);
148
223
  },
149
224
  ceil: function (n) {
150
- return this._math('ceil', n);
225
+ return this._math(Math.ceil, n);
151
226
  },
152
227
  floor: function (n) {
153
- return this._math('floor', n);
228
+ return this._math(Math.floor, n);
154
229
  },
155
230
  _math: function (fn, n) {
156
231
  if (n instanceof tree.Dimension) {
157
- return new(tree.Dimension)(Math[fn](number(n)), n.unit);
232
+ return new(tree.Dimension)(fn(parseFloat(n.value)), n.unit);
158
233
  } else if (typeof(n) === 'number') {
159
- return Math[fn](n);
234
+ return fn(n);
160
235
  } else {
161
236
  throw { type: "Argument", message: "argument must be a number" };
162
237
  }
@@ -201,11 +276,85 @@ tree.functions = {
201
276
  },
202
277
  _isa: function (n, Type) {
203
278
  return (n instanceof Type) ? tree.True : tree.False;
279
+ },
280
+
281
+ /* Blending modes */
282
+
283
+ multiply: function(color1, color2) {
284
+ var r = color1.rgb[0] * color2.rgb[0] / 255;
285
+ var g = color1.rgb[1] * color2.rgb[1] / 255;
286
+ var b = color1.rgb[2] * color2.rgb[2] / 255;
287
+ return this.rgb(r, g, b);
288
+ },
289
+ screen: function(color1, color2) {
290
+ var r = 255 - (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255;
291
+ var g = 255 - (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255;
292
+ var b = 255 - (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255;
293
+ return this.rgb(r, g, b);
294
+ },
295
+ overlay: function(color1, color2) {
296
+ var r = color1.rgb[0] < 128 ? 2 * color1.rgb[0] * color2.rgb[0] / 255 : 255 - 2 * (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255;
297
+ var g = color1.rgb[1] < 128 ? 2 * color1.rgb[1] * color2.rgb[1] / 255 : 255 - 2 * (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255;
298
+ var b = color1.rgb[2] < 128 ? 2 * color1.rgb[2] * color2.rgb[2] / 255 : 255 - 2 * (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255;
299
+ return this.rgb(r, g, b);
300
+ },
301
+ softlight: function(color1, color2) {
302
+ var t = color2.rgb[0] * color1.rgb[0] / 255;
303
+ var r = t + color1.rgb[0] * (255 - (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255 - t) / 255;
304
+ t = color2.rgb[1] * color1.rgb[1] / 255;
305
+ var g = t + color1.rgb[1] * (255 - (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255 - t) / 255;
306
+ t = color2.rgb[2] * color1.rgb[2] / 255;
307
+ var b = t + color1.rgb[2] * (255 - (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255 - t) / 255;
308
+ return this.rgb(r, g, b);
309
+ },
310
+ hardlight: function(color1, color2) {
311
+ var r = color2.rgb[0] < 128 ? 2 * color2.rgb[0] * color1.rgb[0] / 255 : 255 - 2 * (255 - color2.rgb[0]) * (255 - color1.rgb[0]) / 255;
312
+ var g = color2.rgb[1] < 128 ? 2 * color2.rgb[1] * color1.rgb[1] / 255 : 255 - 2 * (255 - color2.rgb[1]) * (255 - color1.rgb[1]) / 255;
313
+ var b = color2.rgb[2] < 128 ? 2 * color2.rgb[2] * color1.rgb[2] / 255 : 255 - 2 * (255 - color2.rgb[2]) * (255 - color1.rgb[2]) / 255;
314
+ return this.rgb(r, g, b);
315
+ },
316
+ difference: function(color1, color2) {
317
+ var r = Math.abs(color1.rgb[0] - color2.rgb[0]);
318
+ var g = Math.abs(color1.rgb[1] - color2.rgb[1]);
319
+ var b = Math.abs(color1.rgb[2] - color2.rgb[2]);
320
+ return this.rgb(r, g, b);
321
+ },
322
+ exclusion: function(color1, color2) {
323
+ var r = color1.rgb[0] + color2.rgb[0] * (255 - color1.rgb[0] - color1.rgb[0]) / 255;
324
+ var g = color1.rgb[1] + color2.rgb[1] * (255 - color1.rgb[1] - color1.rgb[1]) / 255;
325
+ var b = color1.rgb[2] + color2.rgb[2] * (255 - color1.rgb[2] - color1.rgb[2]) / 255;
326
+ return this.rgb(r, g, b);
327
+ },
328
+ average: function(color1, color2) {
329
+ var r = (color1.rgb[0] + color2.rgb[0]) / 2;
330
+ var g = (color1.rgb[1] + color2.rgb[1]) / 2;
331
+ var b = (color1.rgb[2] + color2.rgb[2]) / 2;
332
+ return this.rgb(r, g, b);
333
+ },
334
+ negation: function(color1, color2) {
335
+ var r = 255 - Math.abs(255 - color2.rgb[0] - color1.rgb[0]);
336
+ var g = 255 - Math.abs(255 - color2.rgb[1] - color1.rgb[1]);
337
+ var b = 255 - Math.abs(255 - color2.rgb[2] - color1.rgb[2]);
338
+ return this.rgb(r, g, b);
339
+ },
340
+ tint: function(color, amount) {
341
+ return this.mix(this.rgb(255,255,255), color, amount);
342
+ },
343
+ shade: function(color, amount) {
344
+ return this.mix(this.rgb(0, 0, 0), color, amount);
204
345
  }
205
346
  };
206
347
 
207
- function hsla(hsla) {
208
- return tree.functions.hsla(hsla.h, hsla.s, hsla.l, hsla.a);
348
+ function hsla(color) {
349
+ return tree.functions.hsla(color.h, color.s, color.l, color.a);
350
+ }
351
+
352
+ function scaled(n, size) {
353
+ if (n instanceof tree.Dimension && n.unit == '%') {
354
+ return parseFloat(n.value * size / 100);
355
+ } else {
356
+ return number(n);
357
+ }
209
358
  }
210
359
 
211
360
  function number(n) {