less 4.9.0 → 5.0.0-alpha.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.
- package/README.md +19 -5
- package/bin/lessc +190 -630
- package/dist/less-node.cjs +399 -14570
- package/index.cjs +5 -2
- package/lib/index.js +164 -0
- package/lib/lessc-helper.js +52 -0
- package/lib/logger.js +76 -0
- package/lib/options.d.ts +46 -0
- package/lib/options.js +145 -0
- package/lib/types.js +20 -0
- package/lib/version.js +19 -0
- package/package.json +34 -40
- package/dist/less.cjs +0 -15215
- package/dist/less.js +0 -15215
- package/dist/less.min.js +0 -11
- package/dist/less.min.js.map +0 -1
- package/lib/less/constants.js +0 -13
- package/lib/less/contexts.js +0 -165
- package/lib/less/data/colors.js +0 -150
- package/lib/less/data/index.js +0 -4
- package/lib/less/data/unit-conversions.js +0 -21
- package/lib/less/default-options.js +0 -89
- package/lib/less/deprecation.js +0 -82
- package/lib/less/environment/abstract-file-manager.js +0 -140
- package/lib/less/environment/abstract-plugin-loader.js +0 -185
- package/lib/less/environment/environment-api.ts +0 -21
- package/lib/less/environment/environment.js +0 -59
- package/lib/less/environment/file-manager-api.ts +0 -77
- package/lib/less/functions/boolean.js +0 -29
- package/lib/less/functions/color-blending.js +0 -85
- package/lib/less/functions/color.js +0 -452
- package/lib/less/functions/data-uri.js +0 -74
- package/lib/less/functions/default.js +0 -26
- package/lib/less/functions/function-caller.js +0 -55
- package/lib/less/functions/function-registry.js +0 -36
- package/lib/less/functions/index.js +0 -35
- package/lib/less/functions/list.js +0 -158
- package/lib/less/functions/math-helper.js +0 -22
- package/lib/less/functions/math.js +0 -30
- package/lib/less/functions/number.js +0 -95
- package/lib/less/functions/string.js +0 -39
- package/lib/less/functions/style.js +0 -29
- package/lib/less/functions/svg.js +0 -87
- package/lib/less/functions/types.js +0 -70
- package/lib/less/import-manager.js +0 -183
- package/lib/less/index.js +0 -95
- package/lib/less/less-error.js +0 -166
- package/lib/less/logger.js +0 -34
- package/lib/less/parse-tree.js +0 -124
- package/lib/less/parse.js +0 -87
- package/lib/less/parser/lookup-pattern.js +0 -26
- package/lib/less/parser/parser-input.js +0 -400
- package/lib/less/parser/parser.js +0 -2998
- package/lib/less/plugin-manager.js +0 -168
- package/lib/less/render.js +0 -41
- package/lib/less/source-map-builder.js +0 -82
- package/lib/less/source-map-output.js +0 -151
- package/lib/less/transform-tree.js +0 -102
- package/lib/less/tree/anonymous.js +0 -61
- package/lib/less/tree/assignment.js +0 -48
- package/lib/less/tree/atrule-syntax.js +0 -8
- package/lib/less/tree/atrule.js +0 -340
- package/lib/less/tree/attribute.js +0 -63
- package/lib/less/tree/call.js +0 -132
- package/lib/less/tree/color.js +0 -285
- package/lib/less/tree/combinator.js +0 -38
- package/lib/less/tree/comment.js +0 -48
- package/lib/less/tree/condition.js +0 -65
- package/lib/less/tree/container.js +0 -104
- package/lib/less/tree/debug-info.js +0 -80
- package/lib/less/tree/declaration.js +0 -139
- package/lib/less/tree/detached-ruleset.js +0 -45
- package/lib/less/tree/dimension.js +0 -215
- package/lib/less/tree/element.js +0 -93
- package/lib/less/tree/expression.js +0 -100
- package/lib/less/tree/extend.js +0 -88
- package/lib/less/tree/import.js +0 -299
- package/lib/less/tree/index.js +0 -56
- package/lib/less/tree/interpolated-variable.js +0 -106
- package/lib/less/tree/javascript.js +0 -45
- package/lib/less/tree/js-eval-node.js +0 -80
- package/lib/less/tree/keyword.js +0 -28
- package/lib/less/tree/media.js +0 -90
- package/lib/less/tree/merge-rules.js +0 -47
- package/lib/less/tree/mixin-call.js +0 -283
- package/lib/less/tree/mixin-definition.js +0 -319
- package/lib/less/tree/namespace-value.js +0 -95
- package/lib/less/tree/negative.js +0 -37
- package/lib/less/tree/nested-at-rule.js +0 -239
- package/lib/less/tree/node.js +0 -310
- package/lib/less/tree/operation.js +0 -81
- package/lib/less/tree/paren.js +0 -41
- package/lib/less/tree/property.js +0 -96
- package/lib/less/tree/query-in-parens.js +0 -64
- package/lib/less/tree/quoted.js +0 -131
- package/lib/less/tree/ruleset.js +0 -1068
- package/lib/less/tree/selector.js +0 -201
- package/lib/less/tree/unicode-descriptor.js +0 -14
- package/lib/less/tree/unit.js +0 -170
- package/lib/less/tree/url.js +0 -83
- package/lib/less/tree/value.js +0 -60
- package/lib/less/tree/variable-call.js +0 -60
- package/lib/less/tree/variable.js +0 -85
- package/lib/less/utils.js +0 -126
- package/lib/less/visitors/extend-visitor.js +0 -505
- package/lib/less/visitors/import-sequencer.js +0 -56
- package/lib/less/visitors/import-visitor.js +0 -203
- package/lib/less/visitors/index.js +0 -15
- package/lib/less/visitors/join-selector-visitor.js +0 -65
- package/lib/less/visitors/set-tree-visibility-visitor.js +0 -57
- package/lib/less/visitors/to-css-visitor.js +0 -332
- package/lib/less/visitors/visitor.js +0 -165
- package/lib/less-browser/add-default-options.js +0 -53
- package/lib/less-browser/bootstrap.js +0 -67
- package/lib/less-browser/browser.js +0 -65
- package/lib/less-browser/cache.js +0 -43
- package/lib/less-browser/error-reporting.js +0 -170
- package/lib/less-browser/file-manager.js +0 -112
- package/lib/less-browser/image-size.js +0 -28
- package/lib/less-browser/index.js +0 -284
- package/lib/less-browser/log-listener.js +0 -42
- package/lib/less-browser/plugin-loader.js +0 -24
- package/lib/less-browser/utils.js +0 -30
- package/lib/less-node/environment.js +0 -43
- package/lib/less-node/file-manager.js +0 -156
- package/lib/less-node/fs.js +0 -14
- package/lib/less-node/image-size.js +0 -78
- package/lib/less-node/index.js +0 -31
- package/lib/less-node/lessc-helper.js +0 -95
- package/lib/less-node/plugin-loader.js +0 -62
- package/lib/less-node/url-file-manager.js +0 -60
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
import tree from '../tree/index.js';
|
|
2
|
-
|
|
3
|
-
const _visitArgs = { visitDeeper: true };
|
|
4
|
-
let _hasIndexed = false;
|
|
5
|
-
|
|
6
|
-
function _noop(node) {
|
|
7
|
-
return node;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
function indexNodeTypes(parent, ticker) {
|
|
11
|
-
// add .typeIndex to tree node types for lookup table
|
|
12
|
-
let key, child;
|
|
13
|
-
for (key in parent) {
|
|
14
|
-
/* eslint guard-for-in: 0 */
|
|
15
|
-
child = parent[key];
|
|
16
|
-
switch (typeof child) {
|
|
17
|
-
case 'function':
|
|
18
|
-
// ignore bound functions directly on tree which do not have a prototype
|
|
19
|
-
// or aren't nodes
|
|
20
|
-
if (child.prototype && child.prototype.type) {
|
|
21
|
-
child.prototype.typeIndex = ticker++;
|
|
22
|
-
}
|
|
23
|
-
break;
|
|
24
|
-
case 'object':
|
|
25
|
-
ticker = indexNodeTypes(child, ticker);
|
|
26
|
-
break;
|
|
27
|
-
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
return ticker;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
class Visitor {
|
|
34
|
-
constructor(implementation) {
|
|
35
|
-
this._implementation = implementation;
|
|
36
|
-
this._visitInCache = {};
|
|
37
|
-
this._visitOutCache = {};
|
|
38
|
-
|
|
39
|
-
if (!_hasIndexed) {
|
|
40
|
-
indexNodeTypes(tree, 1);
|
|
41
|
-
_hasIndexed = true;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
visit(node) {
|
|
46
|
-
if (!node) {
|
|
47
|
-
return node;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const nodeTypeIndex = node.typeIndex;
|
|
51
|
-
if (!nodeTypeIndex) {
|
|
52
|
-
// MixinCall args aren't a node type?
|
|
53
|
-
if (node.value && node.value.typeIndex) {
|
|
54
|
-
this.visit(node.value);
|
|
55
|
-
}
|
|
56
|
-
return node;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
const impl = this._implementation;
|
|
60
|
-
let func = this._visitInCache[nodeTypeIndex];
|
|
61
|
-
let funcOut = this._visitOutCache[nodeTypeIndex];
|
|
62
|
-
const visitArgs = _visitArgs;
|
|
63
|
-
let fnName;
|
|
64
|
-
|
|
65
|
-
visitArgs.visitDeeper = true;
|
|
66
|
-
|
|
67
|
-
if (!func) {
|
|
68
|
-
fnName = `visit${node.type}`;
|
|
69
|
-
func = impl[fnName] || _noop;
|
|
70
|
-
funcOut = impl[`${fnName}Out`] || _noop;
|
|
71
|
-
this._visitInCache[nodeTypeIndex] = func;
|
|
72
|
-
this._visitOutCache[nodeTypeIndex] = funcOut;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
if (func !== _noop) {
|
|
76
|
-
const newNode = func.call(impl, node, visitArgs);
|
|
77
|
-
if (node && impl.isReplacing) {
|
|
78
|
-
node = newNode;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
if (visitArgs.visitDeeper && node) {
|
|
83
|
-
if (node.length) {
|
|
84
|
-
for (let i = 0, cnt = node.length; i < cnt; i++) {
|
|
85
|
-
if (node[i].accept) {
|
|
86
|
-
node[i].accept(this);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
} else if (node.accept) {
|
|
90
|
-
node.accept(this);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
if (funcOut != _noop) {
|
|
95
|
-
funcOut.call(impl, node);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
return node;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
visitArray(nodes, nonReplacing) {
|
|
102
|
-
if (!nodes) {
|
|
103
|
-
return nodes;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
const cnt = nodes.length;
|
|
107
|
-
let i;
|
|
108
|
-
|
|
109
|
-
// Non-replacing
|
|
110
|
-
if (nonReplacing || !this._implementation.isReplacing) {
|
|
111
|
-
for (i = 0; i < cnt; i++) {
|
|
112
|
-
this.visit(nodes[i]);
|
|
113
|
-
}
|
|
114
|
-
return nodes;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// Replacing
|
|
118
|
-
const out = [];
|
|
119
|
-
for (i = 0; i < cnt; i++) {
|
|
120
|
-
const evald = this.visit(nodes[i]);
|
|
121
|
-
if (evald === undefined) { continue; }
|
|
122
|
-
if (!evald.splice) {
|
|
123
|
-
out.push(evald);
|
|
124
|
-
} else if (evald.length) {
|
|
125
|
-
this.flatten(evald, out);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
return out;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
flatten(arr, out) {
|
|
132
|
-
if (!out) {
|
|
133
|
-
out = [];
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
let cnt, i, item, nestedCnt, j, nestedItem;
|
|
137
|
-
|
|
138
|
-
for (i = 0, cnt = arr.length; i < cnt; i++) {
|
|
139
|
-
item = arr[i];
|
|
140
|
-
if (item === undefined) {
|
|
141
|
-
continue;
|
|
142
|
-
}
|
|
143
|
-
if (!item.splice) {
|
|
144
|
-
out.push(item);
|
|
145
|
-
continue;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
for (j = 0, nestedCnt = item.length; j < nestedCnt; j++) {
|
|
149
|
-
nestedItem = item[j];
|
|
150
|
-
if (nestedItem === undefined) {
|
|
151
|
-
continue;
|
|
152
|
-
}
|
|
153
|
-
if (!nestedItem.splice) {
|
|
154
|
-
out.push(nestedItem);
|
|
155
|
-
} else if (nestedItem.length) {
|
|
156
|
-
this.flatten(nestedItem, out);
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
return out;
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
export default Visitor;
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import {addDataAttr} from './utils.js';
|
|
2
|
-
import browser from './browser.js';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* @param {Window} window
|
|
6
|
-
* @param {Record<string, *>} options
|
|
7
|
-
*/
|
|
8
|
-
export default (window, options) => {
|
|
9
|
-
|
|
10
|
-
// use options from the current script tag data attribues
|
|
11
|
-
addDataAttr(options, browser.currentScript(window));
|
|
12
|
-
|
|
13
|
-
if (options.isFileProtocol === undefined) {
|
|
14
|
-
options.isFileProtocol = /^(file|(chrome|safari)(-extension)?|resource|qrc|app):/.test(window.location.protocol);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
// Load styles asynchronously (default: false)
|
|
18
|
-
//
|
|
19
|
-
// This is set to `false` by default, so that the body
|
|
20
|
-
// doesn't start loading before the stylesheets are parsed.
|
|
21
|
-
// Setting this to `true` can result in flickering.
|
|
22
|
-
//
|
|
23
|
-
options.async = options.async || false;
|
|
24
|
-
options.fileAsync = options.fileAsync || false;
|
|
25
|
-
|
|
26
|
-
// Interval between watch polls
|
|
27
|
-
options.poll = options.poll || (options.isFileProtocol ? 1000 : 1500);
|
|
28
|
-
|
|
29
|
-
options.env = options.env || (window.location.hostname == '127.0.0.1' ||
|
|
30
|
-
window.location.hostname == '0.0.0.0' ||
|
|
31
|
-
window.location.hostname == 'localhost' ||
|
|
32
|
-
(window.location.port &&
|
|
33
|
-
window.location.port.length > 0) ||
|
|
34
|
-
options.isFileProtocol ? 'development'
|
|
35
|
-
: 'production');
|
|
36
|
-
|
|
37
|
-
const dumpLineNumbers = /!dumpLineNumbers:(comments|mediaquery|all)/.exec(window.location.hash);
|
|
38
|
-
if (dumpLineNumbers) {
|
|
39
|
-
options.dumpLineNumbers = dumpLineNumbers[1];
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
if (options.useFileCache === undefined) {
|
|
43
|
-
options.useFileCache = true;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
if (options.onReady === undefined) {
|
|
47
|
-
options.onReady = true;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
if (options.relativeUrls) {
|
|
51
|
-
options.rewriteUrls = 'all';
|
|
52
|
-
}
|
|
53
|
-
};
|
|
@@ -1,67 +0,0 @@
|
|
|
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
|
-
import defaultOptions from '../less/default-options.js';
|
|
7
|
-
import addDefaultOptions from './add-default-options.js';
|
|
8
|
-
import root from './index.js';
|
|
9
|
-
|
|
10
|
-
const options = defaultOptions();
|
|
11
|
-
|
|
12
|
-
if (window.less) {
|
|
13
|
-
for (const key in window.less) {
|
|
14
|
-
if (Object.prototype.hasOwnProperty.call(window.less, key)) {
|
|
15
|
-
options[key] = window.less[key];
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
addDefaultOptions(window, options);
|
|
20
|
-
|
|
21
|
-
options.plugins = options.plugins || [];
|
|
22
|
-
|
|
23
|
-
if (window.LESS_PLUGINS) {
|
|
24
|
-
options.plugins = options.plugins.concat(window.LESS_PLUGINS);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const less = root(window, options);
|
|
28
|
-
export default less;
|
|
29
|
-
|
|
30
|
-
window.less = less;
|
|
31
|
-
|
|
32
|
-
let css;
|
|
33
|
-
let head;
|
|
34
|
-
let style;
|
|
35
|
-
|
|
36
|
-
// Always restore page visibility
|
|
37
|
-
function resolveOrReject(data) {
|
|
38
|
-
if (data.filename) {
|
|
39
|
-
console.warn(data);
|
|
40
|
-
}
|
|
41
|
-
if (!options.async) {
|
|
42
|
-
head.removeChild(style);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
if (options.onReady) {
|
|
47
|
-
if (/!watch/.test(window.location.hash)) {
|
|
48
|
-
less.watch();
|
|
49
|
-
}
|
|
50
|
-
// Simulate synchronous stylesheet loading by hiding page rendering
|
|
51
|
-
if (!options.async) {
|
|
52
|
-
css = 'body { display: none !important }';
|
|
53
|
-
head = document.head || document.getElementsByTagName('head')[0];
|
|
54
|
-
style = document.createElement('style');
|
|
55
|
-
|
|
56
|
-
style.type = 'text/css';
|
|
57
|
-
if (style.styleSheet) {
|
|
58
|
-
style.styleSheet.cssText = css;
|
|
59
|
-
} else {
|
|
60
|
-
style.appendChild(document.createTextNode(css));
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
head.appendChild(style);
|
|
64
|
-
}
|
|
65
|
-
less.registerStylesheetsImmediately();
|
|
66
|
-
less.pageLoadFinished = less.refresh(less.env === 'development').then(resolveOrReject, resolveOrReject);
|
|
67
|
-
}
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import * as utils from './utils.js';
|
|
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
|
-
};
|
|
@@ -1,43 +0,0 @@
|
|
|
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
|
-
};
|
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
import * as utils from './utils.js';
|
|
2
|
-
import browser from './browser.js';
|
|
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() {
|
|
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
|
-
};
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
import AbstractFileManager from '../less/environment/abstract-file-manager.js';
|
|
2
|
-
|
|
3
|
-
let options;
|
|
4
|
-
let logger;
|
|
5
|
-
let fileCache = {};
|
|
6
|
-
|
|
7
|
-
// TODOS - move log somewhere. pathDiff and doing something similar in node. use pathDiff in the other browser file for the initial load
|
|
8
|
-
const FileManager = function() {}
|
|
9
|
-
FileManager.prototype = Object.assign(new AbstractFileManager(), {
|
|
10
|
-
alwaysMakePathsAbsolute() {
|
|
11
|
-
return true;
|
|
12
|
-
},
|
|
13
|
-
|
|
14
|
-
join(basePath, laterPath) {
|
|
15
|
-
if (!basePath) {
|
|
16
|
-
return laterPath;
|
|
17
|
-
}
|
|
18
|
-
return this.extractUrlParts(laterPath, basePath).path;
|
|
19
|
-
},
|
|
20
|
-
|
|
21
|
-
doXHR(url, type, callback, errback) {
|
|
22
|
-
const xhr = new XMLHttpRequest();
|
|
23
|
-
const async = options.isFileProtocol ? options.fileAsync : true;
|
|
24
|
-
|
|
25
|
-
if (typeof xhr.overrideMimeType === 'function') {
|
|
26
|
-
xhr.overrideMimeType('text/css');
|
|
27
|
-
}
|
|
28
|
-
logger.debug(`XHR: Getting '${url}'`);
|
|
29
|
-
xhr.open('GET', url, async);
|
|
30
|
-
xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5');
|
|
31
|
-
xhr.send(null);
|
|
32
|
-
|
|
33
|
-
function handleResponse(xhr, callback, errback) {
|
|
34
|
-
if (xhr.status >= 200 && xhr.status < 300) {
|
|
35
|
-
callback(xhr.responseText,
|
|
36
|
-
xhr.getResponseHeader('Last-Modified'));
|
|
37
|
-
} else if (typeof errback === 'function') {
|
|
38
|
-
errback(xhr.status, url);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
if (options.isFileProtocol && !options.fileAsync) {
|
|
43
|
-
if (xhr.status === 0 || (xhr.status >= 200 && xhr.status < 300)) {
|
|
44
|
-
callback(xhr.responseText);
|
|
45
|
-
} else {
|
|
46
|
-
errback(xhr.status, url);
|
|
47
|
-
}
|
|
48
|
-
} else if (async) {
|
|
49
|
-
xhr.onreadystatechange = () => {
|
|
50
|
-
if (xhr.readyState == 4) {
|
|
51
|
-
handleResponse(xhr, callback, errback);
|
|
52
|
-
}
|
|
53
|
-
};
|
|
54
|
-
} else {
|
|
55
|
-
handleResponse(xhr, callback, errback);
|
|
56
|
-
}
|
|
57
|
-
},
|
|
58
|
-
|
|
59
|
-
supports() {
|
|
60
|
-
return true;
|
|
61
|
-
},
|
|
62
|
-
|
|
63
|
-
clearFileCache() {
|
|
64
|
-
fileCache = {};
|
|
65
|
-
},
|
|
66
|
-
|
|
67
|
-
loadFile(filename, currentDirectory, options) {
|
|
68
|
-
// TODO: Add prefix support like less-node?
|
|
69
|
-
// What about multiple paths?
|
|
70
|
-
|
|
71
|
-
if (currentDirectory && !this.isPathAbsolute(filename)) {
|
|
72
|
-
filename = currentDirectory + filename;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
filename = options.ext ? this.tryAppendExtension(filename, options.ext) : filename;
|
|
76
|
-
|
|
77
|
-
options = options || {};
|
|
78
|
-
|
|
79
|
-
// sheet may be set to the stylesheet for the initial load or a collection of properties including
|
|
80
|
-
// some context variables for imports
|
|
81
|
-
const hrefParts = this.extractUrlParts(filename, window.location.href);
|
|
82
|
-
const href = hrefParts.url;
|
|
83
|
-
const self = this;
|
|
84
|
-
|
|
85
|
-
return new Promise((resolve, reject) => {
|
|
86
|
-
if (options.useFileCache && fileCache[href]) {
|
|
87
|
-
try {
|
|
88
|
-
const lessText = fileCache[href];
|
|
89
|
-
return resolve({ contents: lessText, filename: href, webInfo: { lastModified: new Date() }});
|
|
90
|
-
} catch (e) {
|
|
91
|
-
return reject({ filename: href, message: `Error loading file ${href} error was ${e.message}` });
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
self.doXHR(href, options.mime, function doXHRCallback(data, lastModified) {
|
|
96
|
-
// per file cache
|
|
97
|
-
fileCache[href] = data;
|
|
98
|
-
|
|
99
|
-
// Use remote copy (re-parse)
|
|
100
|
-
resolve({ contents: data, filename: href, webInfo: { lastModified }});
|
|
101
|
-
}, function doXHRError(status, url) {
|
|
102
|
-
reject({ type: 'File', message: `'${url}' wasn't found (${status})`, href });
|
|
103
|
-
});
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
export default (opts, log) => {
|
|
109
|
-
options = opts;
|
|
110
|
-
logger = log;
|
|
111
|
-
return FileManager;
|
|
112
|
-
}
|