less 3.10.0-beta.2 → 3.10.3

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 (124) hide show
  1. package/.DS_Store +0 -0
  2. package/bin/lessc +6652 -5505
  3. package/dist/less.cjs.js +6593 -5448
  4. package/dist/less.js +10 -6
  5. package/dist/less.min.js +2 -2
  6. package/dist/less.min.js.map +1 -1
  7. package/lib/less/constants.js +13 -0
  8. package/lib/less/contexts.js +164 -0
  9. package/lib/less/data/colors.js +150 -0
  10. package/lib/less/data/index.js +4 -0
  11. package/lib/less/data/unit-conversions.js +21 -0
  12. package/lib/less/default-options.js +68 -0
  13. package/lib/less/environment/abstract-file-manager.js +127 -0
  14. package/lib/less/environment/abstract-plugin-loader.js +187 -0
  15. package/lib/less/environment/environment-api.js +25 -0
  16. package/lib/less/environment/environment.js +59 -0
  17. package/lib/less/environment/file-manager-api.js +103 -0
  18. package/lib/less/functions/boolean.js +13 -0
  19. package/lib/less/functions/color-blending.js +84 -0
  20. package/lib/less/functions/color.js +417 -0
  21. package/lib/less/functions/data-uri.js +74 -0
  22. package/lib/less/functions/default.js +25 -0
  23. package/lib/less/functions/function-caller.js +49 -0
  24. package/lib/less/functions/function-registry.js +35 -0
  25. package/lib/less/functions/index.js +33 -0
  26. package/lib/less/functions/list.js +143 -0
  27. package/lib/less/functions/math-helper.js +15 -0
  28. package/lib/less/functions/math.js +28 -0
  29. package/lib/less/functions/number.js +89 -0
  30. package/lib/less/functions/string.js +36 -0
  31. package/lib/less/functions/svg.js +87 -0
  32. package/lib/less/functions/types.js +70 -0
  33. package/lib/less/import-manager.js +169 -0
  34. package/lib/less/index.js +92 -0
  35. package/lib/less/less-error.js +140 -0
  36. package/lib/less/logger.js +34 -0
  37. package/lib/less/parse-tree.js +66 -0
  38. package/lib/less/parse.js +89 -0
  39. package/lib/less/parser/chunker.js +122 -0
  40. package/lib/less/parser/parser-input.js +390 -0
  41. package/lib/less/parser/parser.js +2418 -0
  42. package/lib/less/plugin-manager.js +168 -0
  43. package/lib/less/render.js +42 -0
  44. package/lib/less/source-map-builder.js +77 -0
  45. package/lib/less/source-map-output.js +149 -0
  46. package/lib/less/transform-tree.js +96 -0
  47. package/lib/less/tree/anonymous.js +37 -0
  48. package/lib/less/tree/assignment.js +33 -0
  49. package/lib/less/tree/atrule.js +165 -0
  50. package/lib/less/tree/attribute.js +34 -0
  51. package/lib/less/tree/call.js +105 -0
  52. package/lib/less/tree/color.js +246 -0
  53. package/lib/less/tree/combinator.js +29 -0
  54. package/lib/less/tree/comment.js +29 -0
  55. package/lib/less/tree/condition.js +43 -0
  56. package/lib/less/tree/debug-info.js +34 -0
  57. package/lib/less/tree/declaration.js +115 -0
  58. package/lib/less/tree/detached-ruleset.js +30 -0
  59. package/lib/less/tree/dimension.js +179 -0
  60. package/lib/less/tree/element.js +73 -0
  61. package/lib/less/tree/expression.js +74 -0
  62. package/lib/less/tree/extend.js +66 -0
  63. package/lib/less/tree/import.js +184 -0
  64. package/lib/less/tree/index.js +54 -0
  65. package/lib/less/tree/javascript.js +33 -0
  66. package/lib/less/tree/js-eval-node.js +58 -0
  67. package/lib/less/tree/keyword.js +21 -0
  68. package/lib/less/tree/media.js +154 -0
  69. package/lib/less/tree/mixin-call.js +215 -0
  70. package/lib/less/tree/mixin-definition.js +229 -0
  71. package/lib/less/tree/namespace-value.js +87 -0
  72. package/lib/less/tree/negative.js +26 -0
  73. package/lib/less/tree/node.js +178 -0
  74. package/lib/less/tree/operation.js +62 -0
  75. package/lib/less/tree/paren.js +22 -0
  76. package/lib/less/tree/property.js +77 -0
  77. package/lib/less/tree/quoted.js +70 -0
  78. package/lib/less/tree/ruleset.js +867 -0
  79. package/lib/less/tree/selector.js +146 -0
  80. package/lib/less/tree/unicode-descriptor.js +13 -0
  81. package/lib/less/tree/unit.js +141 -0
  82. package/lib/less/tree/url.js +65 -0
  83. package/lib/less/tree/value.js +44 -0
  84. package/lib/less/tree/variable-call.js +46 -0
  85. package/lib/less/tree/variable.js +67 -0
  86. package/lib/less/utils.js +122 -0
  87. package/lib/less/visitors/extend-visitor.js +505 -0
  88. package/lib/less/visitors/import-sequencer.js +58 -0
  89. package/lib/less/visitors/import-visitor.js +189 -0
  90. package/lib/less/visitors/index.js +15 -0
  91. package/lib/less/visitors/join-selector-visitor.js +57 -0
  92. package/lib/less/visitors/set-tree-visibility-visitor.js +45 -0
  93. package/lib/less/visitors/to-css-visitor.js +363 -0
  94. package/lib/less/visitors/visitor.js +163 -0
  95. package/lib/less-browser/add-default-options.js +49 -0
  96. package/lib/less-browser/bootstrap.js +69 -0
  97. package/lib/less-browser/browser.js +65 -0
  98. package/lib/less-browser/cache.js +43 -0
  99. package/lib/less-browser/error-reporting.js +170 -0
  100. package/lib/less-browser/file-manager.js +113 -0
  101. package/lib/less-browser/image-size.js +28 -0
  102. package/lib/less-browser/index.js +285 -0
  103. package/lib/less-browser/log-listener.js +42 -0
  104. package/lib/less-browser/plugin-loader.js +26 -0
  105. package/lib/less-browser/utils.js +24 -0
  106. package/lib/less-node/environment.js +16 -0
  107. package/lib/less-node/file-manager.js +177 -0
  108. package/lib/less-node/fs.js +10 -0
  109. package/lib/less-node/image-size.js +58 -0
  110. package/lib/less-node/index.js +27 -0
  111. package/lib/less-node/lessc-helper.js +89 -0
  112. package/lib/less-node/plugin-loader.js +53 -0
  113. package/lib/less-node/url-file-manager.js +49 -0
  114. package/lib/lessc.js +557 -0
  115. package/lib/source-map/source-map-0.1.31.js +1933 -0
  116. package/lib/source-map/source-map-footer.js +4 -0
  117. package/lib/source-map/source-map-header.js +3 -0
  118. package/package.json +1 -1
  119. package/test/.DS_Store +0 -0
  120. package/test/browser/less.min.js +11 -0
  121. package/test/browser/less.min.js.map +1 -0
  122. package/test/css/css-escapes.css +1 -0
  123. package/test/less/css-escapes.less +3 -1
  124. package/.git/index +0 -0
@@ -0,0 +1,163 @@
1
+ import tree from '../tree';
2
+ const _visitArgs = { visitDeeper: true };
3
+ let _hasIndexed = false;
4
+
5
+ function _noop(node) {
6
+ return node;
7
+ }
8
+
9
+ function indexNodeTypes(parent, ticker) {
10
+ // add .typeIndex to tree node types for lookup table
11
+ let key;
12
+
13
+ let child;
14
+ for (key in parent) {
15
+ /* eslint guard-for-in: 0 */
16
+ child = parent[key];
17
+ switch (typeof child) {
18
+ case 'function':
19
+ // ignore bound functions directly on tree which do not have a prototype
20
+ // or aren't nodes
21
+ if (child.prototype && child.prototype.type) {
22
+ child.prototype.typeIndex = ticker++;
23
+ }
24
+ break;
25
+ case 'object':
26
+ ticker = indexNodeTypes(child, ticker);
27
+ break;
28
+
29
+ }
30
+ }
31
+ return ticker;
32
+ }
33
+
34
+ class Visitor {
35
+ constructor(implementation) {
36
+ this._implementation = implementation;
37
+ this._visitInCache = {};
38
+ this._visitOutCache = {};
39
+
40
+ if (!_hasIndexed) {
41
+ indexNodeTypes(tree, 1);
42
+ _hasIndexed = true;
43
+ }
44
+ }
45
+
46
+ visit(node) {
47
+ if (!node) {
48
+ return node;
49
+ }
50
+
51
+ const nodeTypeIndex = node.typeIndex;
52
+ if (!nodeTypeIndex) {
53
+ // MixinCall args aren't a node type?
54
+ if (node.value && node.value.typeIndex) {
55
+ this.visit(node.value);
56
+ }
57
+ return node;
58
+ }
59
+
60
+ const impl = this._implementation;
61
+ let func = this._visitInCache[nodeTypeIndex];
62
+ let funcOut = this._visitOutCache[nodeTypeIndex];
63
+ const visitArgs = _visitArgs;
64
+ let fnName;
65
+
66
+ visitArgs.visitDeeper = true;
67
+
68
+ if (!func) {
69
+ fnName = `visit${node.type}`;
70
+ func = impl[fnName] || _noop;
71
+ funcOut = impl[`${fnName}Out`] || _noop;
72
+ this._visitInCache[nodeTypeIndex] = func;
73
+ this._visitOutCache[nodeTypeIndex] = funcOut;
74
+ }
75
+
76
+ if (func !== _noop) {
77
+ const newNode = func.call(impl, node, visitArgs);
78
+ if (node && impl.isReplacing) {
79
+ node = newNode;
80
+ }
81
+ }
82
+
83
+ if (visitArgs.visitDeeper && node && node.accept) {
84
+ node.accept(this);
85
+ }
86
+
87
+ if (funcOut != _noop) {
88
+ funcOut.call(impl, node);
89
+ }
90
+
91
+ return node;
92
+ }
93
+
94
+ visitArray(nodes, nonReplacing) {
95
+ if (!nodes) {
96
+ return nodes;
97
+ }
98
+
99
+ const cnt = nodes.length;
100
+ let i;
101
+
102
+ // Non-replacing
103
+ if (nonReplacing || !this._implementation.isReplacing) {
104
+ for (i = 0; i < cnt; i++) {
105
+ this.visit(nodes[i]);
106
+ }
107
+ return nodes;
108
+ }
109
+
110
+ // Replacing
111
+ const out = [];
112
+ for (i = 0; i < cnt; i++) {
113
+ const evald = this.visit(nodes[i]);
114
+ if (evald === undefined) { continue; }
115
+ if (!evald.splice) {
116
+ out.push(evald);
117
+ } else if (evald.length) {
118
+ this.flatten(evald, out);
119
+ }
120
+ }
121
+ return out;
122
+ }
123
+
124
+ flatten(arr, out) {
125
+ if (!out) {
126
+ out = [];
127
+ }
128
+
129
+ let cnt;
130
+ let i;
131
+ let item;
132
+ let nestedCnt;
133
+ let j;
134
+ let nestedItem;
135
+
136
+ for (i = 0, cnt = arr.length; i < cnt; i++) {
137
+ item = arr[i];
138
+ if (item === undefined) {
139
+ continue;
140
+ }
141
+ if (!item.splice) {
142
+ out.push(item);
143
+ continue;
144
+ }
145
+
146
+ for (j = 0, nestedCnt = item.length; j < nestedCnt; j++) {
147
+ nestedItem = item[j];
148
+ if (nestedItem === undefined) {
149
+ continue;
150
+ }
151
+ if (!nestedItem.splice) {
152
+ out.push(nestedItem);
153
+ } else if (nestedItem.length) {
154
+ this.flatten(nestedItem, out);
155
+ }
156
+ }
157
+ }
158
+
159
+ return out;
160
+ }
161
+ }
162
+
163
+ export default Visitor;
@@ -0,0 +1,49 @@
1
+ import {addDataAttr} from './utils';
2
+ import browser from './browser';
3
+
4
+ export default (window, options) => {
5
+
6
+ // use options from the current script tag data attribues
7
+ addDataAttr(options, browser.currentScript(window));
8
+
9
+ if (options.isFileProtocol === undefined) {
10
+ options.isFileProtocol = /^(file|(chrome|safari)(-extension)?|resource|qrc|app):/.test(window.location.protocol);
11
+ }
12
+
13
+ // Load styles asynchronously (default: false)
14
+ //
15
+ // This is set to `false` by default, so that the body
16
+ // doesn't start loading before the stylesheets are parsed.
17
+ // Setting this to `true` can result in flickering.
18
+ //
19
+ options.async = options.async || false;
20
+ options.fileAsync = options.fileAsync || false;
21
+
22
+ // Interval between watch polls
23
+ options.poll = options.poll || (options.isFileProtocol ? 1000 : 1500);
24
+
25
+ options.env = options.env || (window.location.hostname == '127.0.0.1' ||
26
+ window.location.hostname == '0.0.0.0' ||
27
+ window.location.hostname == 'localhost' ||
28
+ (window.location.port &&
29
+ window.location.port.length > 0) ||
30
+ options.isFileProtocol ? 'development'
31
+ : 'production');
32
+
33
+ const dumpLineNumbers = /!dumpLineNumbers:(comments|mediaquery|all)/.exec(window.location.hash);
34
+ if (dumpLineNumbers) {
35
+ options.dumpLineNumbers = dumpLineNumbers[1];
36
+ }
37
+
38
+ if (options.useFileCache === undefined) {
39
+ options.useFileCache = true;
40
+ }
41
+
42
+ if (options.onReady === undefined) {
43
+ options.onReady = true;
44
+ }
45
+
46
+ if (options.relativeUrls) {
47
+ options.rewriteUrls = 'all';
48
+ }
49
+ };
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Kicks off less and compiles any stylesheets
3
+ * used in the browser distributed version of less
4
+ * to kick-start less using the browser api
5
+ */
6
+ /* global window, document */
7
+
8
+ import defaultOptions from '../less/default-options';
9
+ import addDefaultOptions from './add-default-options';
10
+ import root from './index';
11
+
12
+ const options = defaultOptions();
13
+
14
+ if (window.less) {
15
+ for (const key in window.less) {
16
+ if (window.less.hasOwnProperty(key)) {
17
+ options[key] = window.less[key];
18
+ }
19
+ }
20
+ }
21
+ addDefaultOptions(window, options);
22
+
23
+ options.plugins = options.plugins || [];
24
+
25
+ if (window.LESS_PLUGINS) {
26
+ options.plugins = options.plugins.concat(window.LESS_PLUGINS);
27
+ }
28
+
29
+ const less = root(window, options);
30
+ export default less;
31
+
32
+ window.less = less;
33
+
34
+ let css;
35
+ let head;
36
+ let style;
37
+
38
+ // Always restore page visibility
39
+ function resolveOrReject(data) {
40
+ if (data.filename) {
41
+ console.warn(data);
42
+ }
43
+ if (!options.async) {
44
+ head.removeChild(style);
45
+ }
46
+ }
47
+
48
+ if (options.onReady) {
49
+ if (/!watch/.test(window.location.hash)) {
50
+ less.watch();
51
+ }
52
+ // Simulate synchronous stylesheet loading by hiding page rendering
53
+ if (!options.async) {
54
+ css = 'body { display: none !important }';
55
+ head = document.head || document.getElementsByTagName('head')[0];
56
+ style = document.createElement('style');
57
+
58
+ style.type = 'text/css';
59
+ if (style.styleSheet) {
60
+ style.styleSheet.cssText = css;
61
+ } else {
62
+ style.appendChild(document.createTextNode(css));
63
+ }
64
+
65
+ head.appendChild(style);
66
+ }
67
+ less.registerStylesheetsImmediately();
68
+ less.pageLoadFinished = less.refresh(less.env === 'development').then(resolveOrReject, resolveOrReject);
69
+ }
@@ -0,0 +1,65 @@
1
+ import * as utils from './utils';
2
+
3
+ export default {
4
+ createCSS: function (document, styles, sheet) {
5
+ // Strip the query-string
6
+ const href = sheet.href || '';
7
+
8
+ // If there is no title set, use the filename, minus the extension
9
+ const id = `less:${sheet.title || utils.extractId(href)}`;
10
+
11
+ // If this has already been inserted into the DOM, we may need to replace it
12
+ const oldStyleNode = document.getElementById(id);
13
+ let keepOldStyleNode = false;
14
+
15
+ // Create a new stylesheet node for insertion or (if necessary) replacement
16
+ const styleNode = document.createElement('style');
17
+ styleNode.setAttribute('type', 'text/css');
18
+ if (sheet.media) {
19
+ styleNode.setAttribute('media', sheet.media);
20
+ }
21
+ styleNode.id = id;
22
+
23
+ if (!styleNode.styleSheet) {
24
+ styleNode.appendChild(document.createTextNode(styles));
25
+
26
+ // If new contents match contents of oldStyleNode, don't replace oldStyleNode
27
+ keepOldStyleNode = (oldStyleNode !== null && oldStyleNode.childNodes.length > 0 && styleNode.childNodes.length > 0 &&
28
+ oldStyleNode.firstChild.nodeValue === styleNode.firstChild.nodeValue);
29
+ }
30
+
31
+ const head = document.getElementsByTagName('head')[0];
32
+
33
+ // If there is no oldStyleNode, just append; otherwise, only append if we need
34
+ // to replace oldStyleNode with an updated stylesheet
35
+ if (oldStyleNode === null || keepOldStyleNode === false) {
36
+ const nextEl = sheet && sheet.nextSibling || null;
37
+ if (nextEl) {
38
+ nextEl.parentNode.insertBefore(styleNode, nextEl);
39
+ } else {
40
+ head.appendChild(styleNode);
41
+ }
42
+ }
43
+ if (oldStyleNode && keepOldStyleNode === false) {
44
+ oldStyleNode.parentNode.removeChild(oldStyleNode);
45
+ }
46
+
47
+ // For IE.
48
+ // This needs to happen *after* the style element is added to the DOM, otherwise IE 7 and 8 may crash.
49
+ // See http://social.msdn.microsoft.com/Forums/en-US/7e081b65-878a-4c22-8e68-c10d39c2ed32/internet-explorer-crashes-appending-style-element-to-head
50
+ if (styleNode.styleSheet) {
51
+ try {
52
+ styleNode.styleSheet.cssText = styles;
53
+ } catch (e) {
54
+ throw new Error('Couldn\'t reassign styleSheet.cssText.');
55
+ }
56
+ }
57
+ },
58
+ currentScript: function(window) {
59
+ const document = window.document;
60
+ return document.currentScript || (() => {
61
+ const scripts = document.getElementsByTagName('script');
62
+ return scripts[scripts.length - 1];
63
+ })();
64
+ }
65
+ };
@@ -0,0 +1,43 @@
1
+ // Cache system is a bit outdated and could do with work
2
+
3
+ export default (window, options, logger) => {
4
+ let cache = null;
5
+ if (options.env !== 'development') {
6
+ try {
7
+ cache = (typeof window.localStorage === 'undefined') ? null : window.localStorage;
8
+ } catch (_) {}
9
+ }
10
+ return {
11
+ setCSS: function(path, lastModified, modifyVars, styles) {
12
+ if (cache) {
13
+ logger.info(`saving ${path} to cache.`);
14
+ try {
15
+ cache.setItem(path, styles);
16
+ cache.setItem(`${path}:timestamp`, lastModified);
17
+ if (modifyVars) {
18
+ cache.setItem(`${path}:vars`, JSON.stringify(modifyVars));
19
+ }
20
+ } catch (e) {
21
+ // TODO - could do with adding more robust error handling
22
+ logger.error(`failed to save "${path}" to local storage for caching.`);
23
+ }
24
+ }
25
+ },
26
+ getCSS: function(path, webInfo, modifyVars) {
27
+ const css = cache && cache.getItem(path);
28
+ const timestamp = cache && cache.getItem(`${path}:timestamp`);
29
+ let vars = cache && cache.getItem(`${path}:vars`);
30
+
31
+ modifyVars = modifyVars || {};
32
+ vars = vars || "{}"; // if not set, treat as the JSON representation of an empty object
33
+
34
+ if (timestamp && webInfo.lastModified &&
35
+ (new Date(webInfo.lastModified).valueOf() ===
36
+ new Date(timestamp).valueOf()) &&
37
+ JSON.stringify(modifyVars) === vars) {
38
+ // Use local copy
39
+ return css;
40
+ }
41
+ }
42
+ };
43
+ };
@@ -0,0 +1,170 @@
1
+ import * as utils from './utils';
2
+ import browser from './browser';
3
+
4
+ export default (window, less, options) => {
5
+
6
+ function errorHTML(e, rootHref) {
7
+ const id = `less-error-message:${utils.extractId(rootHref || '')}`;
8
+ const template = '<li><label>{line}</label><pre class="{class}">{content}</pre></li>';
9
+ const elem = window.document.createElement('div');
10
+ let timer;
11
+ let content;
12
+ const errors = [];
13
+ const filename = e.filename || rootHref;
14
+ const filenameNoPath = filename.match(/([^\/]+(\?.*)?)$/)[1];
15
+
16
+ elem.id = id;
17
+ elem.className = 'less-error-message';
18
+
19
+ content = `<h3>${e.type || 'Syntax'}Error: ${e.message || 'There is an error in your .less file'}` +
20
+ `</h3><p>in <a href="${filename}">${filenameNoPath}</a> `;
21
+
22
+ const errorline = (e, i, classname) => {
23
+ if (e.extract[i] !== undefined) {
24
+ errors.push(template.replace(/\{line\}/, (parseInt(e.line, 10) || 0) + (i - 1))
25
+ .replace(/\{class\}/, classname)
26
+ .replace(/\{content\}/, e.extract[i]));
27
+ }
28
+ };
29
+
30
+ if (e.line) {
31
+ errorline(e, 0, '');
32
+ errorline(e, 1, 'line');
33
+ errorline(e, 2, '');
34
+ content += `on line ${e.line}, column ${e.column + 1}:</p><ul>${errors.join('')}</ul>`;
35
+ }
36
+ if (e.stack && (e.extract || options.logLevel >= 4)) {
37
+ content += `<br/>Stack Trace</br />${e.stack.split('\n').slice(1).join('<br/>')}`;
38
+ }
39
+ elem.innerHTML = content;
40
+
41
+ // CSS for error messages
42
+ browser.createCSS(window.document, [
43
+ '.less-error-message ul, .less-error-message li {',
44
+ 'list-style-type: none;',
45
+ 'margin-right: 15px;',
46
+ 'padding: 4px 0;',
47
+ 'margin: 0;',
48
+ '}',
49
+ '.less-error-message label {',
50
+ 'font-size: 12px;',
51
+ 'margin-right: 15px;',
52
+ 'padding: 4px 0;',
53
+ 'color: #cc7777;',
54
+ '}',
55
+ '.less-error-message pre {',
56
+ 'color: #dd6666;',
57
+ 'padding: 4px 0;',
58
+ 'margin: 0;',
59
+ 'display: inline-block;',
60
+ '}',
61
+ '.less-error-message pre.line {',
62
+ 'color: #ff0000;',
63
+ '}',
64
+ '.less-error-message h3 {',
65
+ 'font-size: 20px;',
66
+ 'font-weight: bold;',
67
+ 'padding: 15px 0 5px 0;',
68
+ 'margin: 0;',
69
+ '}',
70
+ '.less-error-message a {',
71
+ 'color: #10a',
72
+ '}',
73
+ '.less-error-message .error {',
74
+ 'color: red;',
75
+ 'font-weight: bold;',
76
+ 'padding-bottom: 2px;',
77
+ 'border-bottom: 1px dashed red;',
78
+ '}'
79
+ ].join('\n'), { title: 'error-message' });
80
+
81
+ elem.style.cssText = [
82
+ 'font-family: Arial, sans-serif',
83
+ 'border: 1px solid #e00',
84
+ 'background-color: #eee',
85
+ 'border-radius: 5px',
86
+ '-webkit-border-radius: 5px',
87
+ '-moz-border-radius: 5px',
88
+ 'color: #e00',
89
+ 'padding: 15px',
90
+ 'margin-bottom: 15px'
91
+ ].join(';');
92
+
93
+ if (options.env === 'development') {
94
+ timer = setInterval(() => {
95
+ const document = window.document;
96
+ const body = document.body;
97
+ if (body) {
98
+ if (document.getElementById(id)) {
99
+ body.replaceChild(elem, document.getElementById(id));
100
+ } else {
101
+ body.insertBefore(elem, body.firstChild);
102
+ }
103
+ clearInterval(timer);
104
+ }
105
+ }, 10);
106
+ }
107
+ }
108
+
109
+ function removeErrorHTML(path) {
110
+ const node = window.document.getElementById(`less-error-message:${utils.extractId(path)}`);
111
+ if (node) {
112
+ node.parentNode.removeChild(node);
113
+ }
114
+ }
115
+
116
+ function removeErrorConsole(path) {
117
+ // no action
118
+ }
119
+
120
+ function removeError(path) {
121
+ if (!options.errorReporting || options.errorReporting === 'html') {
122
+ removeErrorHTML(path);
123
+ } else if (options.errorReporting === 'console') {
124
+ removeErrorConsole(path);
125
+ } else if (typeof options.errorReporting === 'function') {
126
+ options.errorReporting('remove', path);
127
+ }
128
+ }
129
+
130
+ function errorConsole(e, rootHref) {
131
+ const template = '{line} {content}';
132
+ const filename = e.filename || rootHref;
133
+ const errors = [];
134
+ let content = `${e.type || 'Syntax'}Error: ${e.message || 'There is an error in your .less file'} in ${filename}`;
135
+
136
+ const errorline = (e, i, classname) => {
137
+ if (e.extract[i] !== undefined) {
138
+ errors.push(template.replace(/\{line\}/, (parseInt(e.line, 10) || 0) + (i - 1))
139
+ .replace(/\{class\}/, classname)
140
+ .replace(/\{content\}/, e.extract[i]));
141
+ }
142
+ };
143
+
144
+ if (e.line) {
145
+ errorline(e, 0, '');
146
+ errorline(e, 1, 'line');
147
+ errorline(e, 2, '');
148
+ content += ` on line ${e.line}, column ${e.column + 1}:\n${errors.join('\n')}`;
149
+ }
150
+ if (e.stack && (e.extract || options.logLevel >= 4)) {
151
+ content += `\nStack Trace\n${e.stack}`;
152
+ }
153
+ less.logger.error(content);
154
+ }
155
+
156
+ function error(e, rootHref) {
157
+ if (!options.errorReporting || options.errorReporting === 'html') {
158
+ errorHTML(e, rootHref);
159
+ } else if (options.errorReporting === 'console') {
160
+ errorConsole(e, rootHref);
161
+ } else if (typeof options.errorReporting === 'function') {
162
+ options.errorReporting('add', e, rootHref);
163
+ }
164
+ }
165
+
166
+ return {
167
+ add: error,
168
+ remove: removeError
169
+ };
170
+ };
@@ -0,0 +1,113 @@
1
+ /* global window, XMLHttpRequest */
2
+
3
+ import AbstractFileManager from '../less/environment/abstract-file-manager.js';
4
+
5
+ let options;
6
+ let logger;
7
+ let fileCache = {};
8
+
9
+ // TODOS - move log somewhere. pathDiff and doing something similar in node. use pathDiff in the other browser file for the initial load
10
+ class FileManager extends AbstractFileManager {
11
+ alwaysMakePathsAbsolute() {
12
+ return true;
13
+ }
14
+
15
+ join(basePath, laterPath) {
16
+ if (!basePath) {
17
+ return laterPath;
18
+ }
19
+ return this.extractUrlParts(laterPath, basePath).path;
20
+ }
21
+
22
+ doXHR(url, type, callback, errback) {
23
+ const xhr = new XMLHttpRequest();
24
+ const async = options.isFileProtocol ? options.fileAsync : true;
25
+
26
+ if (typeof xhr.overrideMimeType === 'function') {
27
+ xhr.overrideMimeType('text/css');
28
+ }
29
+ logger.debug(`XHR: Getting '${url}'`);
30
+ xhr.open('GET', url, async);
31
+ xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5');
32
+ xhr.send(null);
33
+
34
+ function handleResponse(xhr, callback, errback) {
35
+ if (xhr.status >= 200 && xhr.status < 300) {
36
+ callback(xhr.responseText,
37
+ xhr.getResponseHeader('Last-Modified'));
38
+ } else if (typeof errback === 'function') {
39
+ errback(xhr.status, url);
40
+ }
41
+ }
42
+
43
+ if (options.isFileProtocol && !options.fileAsync) {
44
+ if (xhr.status === 0 || (xhr.status >= 200 && xhr.status < 300)) {
45
+ callback(xhr.responseText);
46
+ } else {
47
+ errback(xhr.status, url);
48
+ }
49
+ } else if (async) {
50
+ xhr.onreadystatechange = () => {
51
+ if (xhr.readyState == 4) {
52
+ handleResponse(xhr, callback, errback);
53
+ }
54
+ };
55
+ } else {
56
+ handleResponse(xhr, callback, errback);
57
+ }
58
+ }
59
+
60
+ supports() {
61
+ return true;
62
+ }
63
+
64
+ clearFileCache() {
65
+ fileCache = {};
66
+ }
67
+
68
+ loadFile(filename, currentDirectory, options, environment) {
69
+ // TODO: Add prefix support like less-node?
70
+ // What about multiple paths?
71
+
72
+ if (currentDirectory && !this.isPathAbsolute(filename)) {
73
+ filename = currentDirectory + filename;
74
+ }
75
+
76
+ filename = options.ext ? this.tryAppendExtension(filename, options.ext) : filename;
77
+
78
+ options = options || {};
79
+
80
+ // sheet may be set to the stylesheet for the initial load or a collection of properties including
81
+ // some context variables for imports
82
+ const hrefParts = this.extractUrlParts(filename, window.location.href);
83
+ const href = hrefParts.url;
84
+ const self = this;
85
+
86
+ return new Promise((resolve, reject) => {
87
+ if (options.useFileCache && fileCache[href]) {
88
+ try {
89
+ const lessText = fileCache[href];
90
+ return resolve({ contents: lessText, filename: href, webInfo: { lastModified: new Date() }});
91
+ } catch (e) {
92
+ return reject({ filename: href, message: `Error loading file ${href} error was ${e.message}` });
93
+ }
94
+ }
95
+
96
+ self.doXHR(href, options.mime, function doXHRCallback(data, lastModified) {
97
+ // per file cache
98
+ fileCache[href] = data;
99
+
100
+ // Use remote copy (re-parse)
101
+ resolve({ contents: data, filename: href, webInfo: { lastModified }});
102
+ }, function doXHRError(status, url) {
103
+ reject({ type: 'File', message: `'${url}' wasn't found (${status})`, href });
104
+ });
105
+ });
106
+ }
107
+ }
108
+
109
+ export default (opts, log) => {
110
+ options = opts;
111
+ logger = log;
112
+ return FileManager;
113
+ }