less 2.3.0 → 2.3.1

Sign up to get free protection for your applications and to get access to all the features.
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) {