less 4.9.0 → 5.0.0-alpha.2
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 +32 -39
- 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
package/lib/less/tree/import.js
DELETED
|
@@ -1,299 +0,0 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
/** @import { EvalContext, CSSOutput, TreeVisitor, FileInfo, VisibilityInfo } from './node.js' */
|
|
3
|
-
import Node from './node.js';
|
|
4
|
-
import Media from './media.js';
|
|
5
|
-
import URL from './url.js';
|
|
6
|
-
import Quoted from './quoted.js';
|
|
7
|
-
import Ruleset from './ruleset.js';
|
|
8
|
-
import Anonymous from './anonymous.js';
|
|
9
|
-
import Expression from './expression.js';
|
|
10
|
-
import * as utils from '../utils.js';
|
|
11
|
-
import LessError from '../less-error.js';
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* @typedef {object} ImportOptions
|
|
15
|
-
* @property {boolean} [less]
|
|
16
|
-
* @property {boolean} [inline]
|
|
17
|
-
* @property {boolean} [isPlugin]
|
|
18
|
-
* @property {boolean} [reference]
|
|
19
|
-
*/
|
|
20
|
-
|
|
21
|
-
//
|
|
22
|
-
// CSS @import node
|
|
23
|
-
//
|
|
24
|
-
// The general strategy here is that we don't want to wait
|
|
25
|
-
// for the parsing to be completed, before we start importing
|
|
26
|
-
// the file. That's because in the context of a browser,
|
|
27
|
-
// most of the time will be spent waiting for the server to respond.
|
|
28
|
-
//
|
|
29
|
-
// On creation, we push the import path to our import queue, though
|
|
30
|
-
// `import,push`, we also pass it a callback, which it'll call once
|
|
31
|
-
// the file has been fetched, and parsed.
|
|
32
|
-
//
|
|
33
|
-
class Import extends Node {
|
|
34
|
-
get type() { return 'Import'; }
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* @param {Node} path
|
|
38
|
-
* @param {Node | null} features
|
|
39
|
-
* @param {ImportOptions} options
|
|
40
|
-
* @param {number} index
|
|
41
|
-
* @param {FileInfo} [currentFileInfo]
|
|
42
|
-
* @param {VisibilityInfo} [visibilityInfo]
|
|
43
|
-
*/
|
|
44
|
-
constructor(path, features, options, index, currentFileInfo, visibilityInfo) {
|
|
45
|
-
super();
|
|
46
|
-
/** @type {ImportOptions} */
|
|
47
|
-
this.options = options;
|
|
48
|
-
this._index = index;
|
|
49
|
-
this._fileInfo = currentFileInfo;
|
|
50
|
-
this.path = path;
|
|
51
|
-
/** @type {Node | null} */
|
|
52
|
-
this.features = features;
|
|
53
|
-
/** @type {boolean} */
|
|
54
|
-
this.allowRoot = true;
|
|
55
|
-
|
|
56
|
-
/** @type {boolean | undefined} */
|
|
57
|
-
this.css = undefined;
|
|
58
|
-
/** @type {boolean | undefined} */
|
|
59
|
-
this.layerCss = undefined;
|
|
60
|
-
/** @type {(Ruleset & { imports?: object, filename?: string, functions?: object, functionRegistry?: { addMultiple: (fns: object) => void } }) | undefined} */
|
|
61
|
-
this.root = undefined;
|
|
62
|
-
/** @type {string | undefined} */
|
|
63
|
-
this.importedFilename = undefined;
|
|
64
|
-
/** @type {boolean | (() => boolean) | undefined} */
|
|
65
|
-
this.skip = undefined;
|
|
66
|
-
/** @type {{ message: string, index: number, filename: string } | undefined} */
|
|
67
|
-
this.error = undefined;
|
|
68
|
-
|
|
69
|
-
if (this.options.less !== undefined || this.options.inline) {
|
|
70
|
-
this.css = !this.options.less || this.options.inline;
|
|
71
|
-
} else {
|
|
72
|
-
const pathValue = this.getPath();
|
|
73
|
-
if (pathValue && /[#.&?]css([?;].*)?$/.test(pathValue)) {
|
|
74
|
-
this.css = true;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
this.copyVisibilityInfo(visibilityInfo);
|
|
78
|
-
if (this.features) {
|
|
79
|
-
this.setParent(this.features, /** @type {Node} */ (this));
|
|
80
|
-
}
|
|
81
|
-
this.setParent(this.path, /** @type {Node} */ (this));
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/** @param {TreeVisitor} visitor */
|
|
85
|
-
accept(visitor) {
|
|
86
|
-
if (this.features) {
|
|
87
|
-
this.features = visitor.visit(this.features);
|
|
88
|
-
}
|
|
89
|
-
this.path = visitor.visit(this.path);
|
|
90
|
-
if (!this.options.isPlugin && !this.options.inline && this.root) {
|
|
91
|
-
this.root = /** @type {Ruleset} */ (visitor.visit(this.root));
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* @param {EvalContext} context
|
|
97
|
-
* @param {CSSOutput} output
|
|
98
|
-
*/
|
|
99
|
-
genCSS(context, output) {
|
|
100
|
-
if (this.css && this.path._fileInfo.reference === undefined) {
|
|
101
|
-
output.add('@import ', this._fileInfo, this._index);
|
|
102
|
-
this.path.genCSS(context, output);
|
|
103
|
-
if (this.features) {
|
|
104
|
-
output.add(' ');
|
|
105
|
-
this.features.genCSS(context, output);
|
|
106
|
-
}
|
|
107
|
-
output.add(';');
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/** @returns {string | undefined} */
|
|
112
|
-
getPath() {
|
|
113
|
-
return (this.path instanceof URL) ?
|
|
114
|
-
/** @type {string} */ (/** @type {Node} */ (this.path.value).value) :
|
|
115
|
-
/** @type {string | undefined} */ (this.path.value);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/** @returns {boolean | RegExpMatchArray | null} */
|
|
119
|
-
isVariableImport() {
|
|
120
|
-
let path = this.path;
|
|
121
|
-
if (path instanceof URL) {
|
|
122
|
-
path = /** @type {Node} */ (path.value);
|
|
123
|
-
}
|
|
124
|
-
if (path instanceof Quoted) {
|
|
125
|
-
return path.containsVariables();
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
return true;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
/** @param {EvalContext} context */
|
|
132
|
-
evalForImport(context) {
|
|
133
|
-
let path = this.path;
|
|
134
|
-
|
|
135
|
-
if (path instanceof URL) {
|
|
136
|
-
path = /** @type {Node} */ (path.value);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
return new Import(path.eval(context), this.features, this.options, this._index || 0, this._fileInfo, this.visibilityInfo());
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
/** @param {EvalContext} context */
|
|
143
|
-
evalPath(context) {
|
|
144
|
-
const path = this.path.eval(context);
|
|
145
|
-
const fileInfo = this._fileInfo;
|
|
146
|
-
|
|
147
|
-
if (!(path instanceof URL)) {
|
|
148
|
-
// Add the rootpath if the URL requires a rewrite
|
|
149
|
-
const pathValue = /** @type {string} */ (path.value);
|
|
150
|
-
if (fileInfo &&
|
|
151
|
-
pathValue &&
|
|
152
|
-
context.pathRequiresRewrite(pathValue)) {
|
|
153
|
-
path.value = context.rewritePath(pathValue, fileInfo.rootpath);
|
|
154
|
-
} else {
|
|
155
|
-
path.value = context.normalizePath(/** @type {string} */ (path.value));
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
return path;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
/** @param {EvalContext} context */
|
|
163
|
-
// @ts-ignore - Import.eval returns Node | Node[] | Import (wider than Node.eval's Node return)
|
|
164
|
-
eval(context) {
|
|
165
|
-
const result = this.doEval(context);
|
|
166
|
-
if (this.options.reference || this.blocksVisibility()) {
|
|
167
|
-
if (Array.isArray(result)) {
|
|
168
|
-
result.forEach(function (node) {
|
|
169
|
-
node.addVisibilityBlock();
|
|
170
|
-
});
|
|
171
|
-
} else {
|
|
172
|
-
/** @type {Node} */ (result).addVisibilityBlock();
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
return result;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
/** @param {EvalContext} context */
|
|
179
|
-
doEval(context) {
|
|
180
|
-
/** @type {Ruleset | undefined} */
|
|
181
|
-
let ruleset;
|
|
182
|
-
const features = this.features && this.features.eval(context);
|
|
183
|
-
|
|
184
|
-
if (this.options.isPlugin) {
|
|
185
|
-
if (this.root && this.root.eval) {
|
|
186
|
-
try {
|
|
187
|
-
this.root.eval(context);
|
|
188
|
-
}
|
|
189
|
-
catch (e) {
|
|
190
|
-
const err = /** @type {{ message: string }} */ (e);
|
|
191
|
-
err.message = 'Plugin error during evaluation';
|
|
192
|
-
throw new LessError(
|
|
193
|
-
/** @type {{ message: string, index?: number, filename?: string }} */ (e),
|
|
194
|
-
/** @type {{ imports: object }} */ (/** @type {unknown} */ (this.root)).imports,
|
|
195
|
-
/** @type {{ filename: string }} */ (/** @type {unknown} */ (this.root)).filename
|
|
196
|
-
);
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
const frame0 = /** @type {Ruleset & { functionRegistry?: { addMultiple: (fns: object) => void } }} */ (context.frames[0]);
|
|
200
|
-
const registry = frame0 && frame0.functionRegistry;
|
|
201
|
-
if (registry && this.root && this.root.functions) {
|
|
202
|
-
registry.addMultiple(this.root.functions);
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
return [];
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
if (this.skip) {
|
|
209
|
-
if (typeof this.skip === 'function') {
|
|
210
|
-
this.skip = this.skip();
|
|
211
|
-
}
|
|
212
|
-
if (this.skip) {
|
|
213
|
-
return [];
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
if (this.features) {
|
|
217
|
-
let featureValue = /** @type {Node[]} */ (this.features.value);
|
|
218
|
-
if (Array.isArray(featureValue) && featureValue.length >= 1) {
|
|
219
|
-
const expr = featureValue[0];
|
|
220
|
-
if (expr.type === 'Expression' && Array.isArray(expr.value) && /** @type {Node[]} */ (expr.value).length >= 2) {
|
|
221
|
-
featureValue = /** @type {Node[]} */ (expr.value);
|
|
222
|
-
const isLayer = featureValue[0].type === 'Keyword' && featureValue[0].value === 'layer'
|
|
223
|
-
&& featureValue[1].type === 'Paren';
|
|
224
|
-
if (isLayer) {
|
|
225
|
-
this.css = false;
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
if (this.options.inline) {
|
|
231
|
-
const contents = new Anonymous(
|
|
232
|
-
/** @type {string} */ (/** @type {unknown} */ (this.root)),
|
|
233
|
-
0,
|
|
234
|
-
{
|
|
235
|
-
filename: this.importedFilename,
|
|
236
|
-
reference: this.path._fileInfo && this.path._fileInfo.reference
|
|
237
|
-
},
|
|
238
|
-
true,
|
|
239
|
-
true
|
|
240
|
-
);
|
|
241
|
-
|
|
242
|
-
return this.features ? new Media([contents], /** @type {Node[]} */ (this.features.value)) : [contents];
|
|
243
|
-
} else if (this.css || this.layerCss) {
|
|
244
|
-
const newImport = new Import(this.evalPath(context), features, this.options, this._index || 0);
|
|
245
|
-
if (this.layerCss) {
|
|
246
|
-
newImport.css = this.layerCss;
|
|
247
|
-
newImport.path._fileInfo = this._fileInfo;
|
|
248
|
-
}
|
|
249
|
-
if (!newImport.css && this.error) {
|
|
250
|
-
throw this.error;
|
|
251
|
-
}
|
|
252
|
-
return newImport;
|
|
253
|
-
} else if (this.root) {
|
|
254
|
-
if (this.features) {
|
|
255
|
-
let featureValue = /** @type {Node[]} */ (this.features.value);
|
|
256
|
-
if (Array.isArray(featureValue) && featureValue.length === 1) {
|
|
257
|
-
const expr = featureValue[0];
|
|
258
|
-
if (expr.type === 'Expression' && Array.isArray(expr.value) && /** @type {Node[]} */ (expr.value).length >= 2) {
|
|
259
|
-
featureValue = /** @type {Node[]} */ (expr.value);
|
|
260
|
-
const isLayer = featureValue[0].type === 'Keyword' && featureValue[0].value === 'layer'
|
|
261
|
-
&& featureValue[1].type === 'Paren';
|
|
262
|
-
if (isLayer) {
|
|
263
|
-
this.layerCss = true;
|
|
264
|
-
featureValue[0] = new Expression(/** @type {Node[]} */ (featureValue.slice(0, 2)));
|
|
265
|
-
featureValue.splice(1, 1);
|
|
266
|
-
/** @type {Expression} */ (featureValue[0]).noSpacing = true;
|
|
267
|
-
return this;
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
ruleset = new Ruleset(null, utils.copyArray(this.root.rules));
|
|
273
|
-
ruleset.evalImports(context);
|
|
274
|
-
|
|
275
|
-
return this.features ? new Media(ruleset.rules, /** @type {Node[]} */ (this.features.value)) : ruleset.rules;
|
|
276
|
-
} else {
|
|
277
|
-
if (this.features) {
|
|
278
|
-
let featureValue = /** @type {Node[]} */ (this.features.value);
|
|
279
|
-
if (Array.isArray(featureValue) && featureValue.length >= 1) {
|
|
280
|
-
featureValue = /** @type {Node[]} */ (featureValue[0].value);
|
|
281
|
-
if (Array.isArray(featureValue) && featureValue.length >= 2) {
|
|
282
|
-
const isLayer = featureValue[0].type === 'Keyword' && featureValue[0].value === 'layer'
|
|
283
|
-
&& featureValue[1].type === 'Paren';
|
|
284
|
-
if (isLayer) {
|
|
285
|
-
this.css = true;
|
|
286
|
-
featureValue[0] = new Expression(/** @type {Node[]} */ (featureValue.slice(0, 2)));
|
|
287
|
-
featureValue.splice(1, 1);
|
|
288
|
-
/** @type {Expression} */ (featureValue[0]).noSpacing = true;
|
|
289
|
-
return this;
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
return [];
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
export default Import;
|
package/lib/less/tree/index.js
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
import Node from './node.js';
|
|
3
|
-
import Color from './color.js';
|
|
4
|
-
import AtRule from './atrule.js';
|
|
5
|
-
import DetachedRuleset from './detached-ruleset.js';
|
|
6
|
-
import Operation from './operation.js';
|
|
7
|
-
import Dimension from './dimension.js';
|
|
8
|
-
import Unit from './unit.js';
|
|
9
|
-
import Keyword from './keyword.js';
|
|
10
|
-
import Variable from './variable.js';
|
|
11
|
-
import Property from './property.js';
|
|
12
|
-
import Ruleset from './ruleset.js';
|
|
13
|
-
import Element from './element.js';
|
|
14
|
-
import Attribute from './attribute.js';
|
|
15
|
-
import Combinator from './combinator.js';
|
|
16
|
-
import Selector from './selector.js';
|
|
17
|
-
import Quoted from './quoted.js';
|
|
18
|
-
import Expression from './expression.js';
|
|
19
|
-
import Declaration from './declaration.js';
|
|
20
|
-
import Call from './call.js';
|
|
21
|
-
import URL from './url.js';
|
|
22
|
-
import Import from './import.js';
|
|
23
|
-
import Comment from './comment.js';
|
|
24
|
-
import Anonymous from './anonymous.js';
|
|
25
|
-
import Value from './value.js';
|
|
26
|
-
import JavaScript from './javascript.js';
|
|
27
|
-
import Assignment from './assignment.js';
|
|
28
|
-
import Condition from './condition.js';
|
|
29
|
-
import QueryInParens from './query-in-parens.js';
|
|
30
|
-
import Paren from './paren.js';
|
|
31
|
-
import Media from './media.js';
|
|
32
|
-
import Container from './container.js';
|
|
33
|
-
import UnicodeDescriptor from './unicode-descriptor.js';
|
|
34
|
-
import Negative from './negative.js';
|
|
35
|
-
import Extend from './extend.js';
|
|
36
|
-
import VariableCall from './variable-call.js';
|
|
37
|
-
import NamespaceValue from './namespace-value.js';
|
|
38
|
-
|
|
39
|
-
// mixins
|
|
40
|
-
import MixinCall from './mixin-call.js';
|
|
41
|
-
import MixinDefinition from './mixin-definition.js';
|
|
42
|
-
|
|
43
|
-
export default {
|
|
44
|
-
Node, Color, AtRule, DetachedRuleset, Operation,
|
|
45
|
-
Dimension, Unit, Keyword, Variable, Property,
|
|
46
|
-
Ruleset, Element, Attribute, Combinator, Selector,
|
|
47
|
-
Quoted, Expression, Declaration, Call, URL, Import,
|
|
48
|
-
Comment, Anonymous, Value, JavaScript, Assignment,
|
|
49
|
-
Condition, Paren, Media, Container, QueryInParens,
|
|
50
|
-
UnicodeDescriptor, Negative, Extend, VariableCall,
|
|
51
|
-
NamespaceValue,
|
|
52
|
-
mixin: {
|
|
53
|
-
Call: MixinCall,
|
|
54
|
-
Definition: MixinDefinition
|
|
55
|
-
}
|
|
56
|
-
};
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
/** @import { FileInfo } from './node.js' */
|
|
3
|
-
/** @import Node from './node.js' */
|
|
4
|
-
import Variable from './variable.js';
|
|
5
|
-
import Property from './property.js';
|
|
6
|
-
import VariableCall from './variable-call.js';
|
|
7
|
-
import NamespaceValue from './namespace-value.js';
|
|
8
|
-
import { LOOKUP_KEY, VARIABLE_WITH_LOOKUPS } from '../parser/lookup-pattern.js';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Interpolation resolved by string replacement at eval time.
|
|
12
|
-
*
|
|
13
|
-
* The parser consumes `@{name[key]}` structurally via `entities.variableCurly`,
|
|
14
|
-
* but `Quoted` and inline JavaScript hold their contents as raw text and can only
|
|
15
|
-
* substitute at eval time. Both share this module so the two evaluation paths build
|
|
16
|
-
* identical nodes from identical patterns.
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
/** Matches `@{name}` and `@{name[a][b]}`, capturing the reference. */
|
|
20
|
-
export const VARIABLE_INTERPOLATION = new RegExp(`@\\{(${VARIABLE_WITH_LOOKUPS})\\}`, 'g');
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Matches `${name}`, capturing the reference.
|
|
24
|
-
*
|
|
25
|
-
* Deliberately narrower than {@link VARIABLE_INTERPOLATION}: a lookup chain is not
|
|
26
|
-
* part of the property grammar. `entities.property` parses `$name` with no lookup
|
|
27
|
-
* handling, so `$map[key]` is a property reference followed by the literal text
|
|
28
|
-
* `[key]`, and a property cannot hold a ruleset to look into in the first place
|
|
29
|
-
* (`prop: { … }` is a parse error in every scope). Accepting `${map[key]}` here
|
|
30
|
-
* would invent syntax the language does not have.
|
|
31
|
-
*/
|
|
32
|
-
export const PROPERTY_INTERPOLATION = /\$\{([\w-]+)\}/g;
|
|
33
|
-
|
|
34
|
-
const LOOKUP_SEGMENT = new RegExp(`\\[(${LOOKUP_KEY})\\]`, 'g');
|
|
35
|
-
|
|
36
|
-
// Non-global twins for membership tests. `RegExp.test` on a /g regex advances
|
|
37
|
-
// `lastIndex` and so returns alternating results across calls on shared instances.
|
|
38
|
-
const HAS_VARIABLE_INTERPOLATION = new RegExp(VARIABLE_INTERPOLATION.source);
|
|
39
|
-
const HAS_PROPERTY_INTERPOLATION = new RegExp(PROPERTY_INTERPOLATION.source);
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Whether text contains an `@{...}` or `${...}` interpolation.
|
|
43
|
-
*
|
|
44
|
-
* @param {string} text
|
|
45
|
-
* @returns {boolean}
|
|
46
|
-
*/
|
|
47
|
-
export function hasInterpolation(text) {
|
|
48
|
-
return HAS_VARIABLE_INTERPOLATION.test(text) || HAS_PROPERTY_INTERPOLATION.test(text);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Split a `name[a][b]` reference into its name and lookup keys.
|
|
53
|
-
*
|
|
54
|
-
* `lookups` is null for a plain reference, so callers keep using the cheaper
|
|
55
|
-
* `Variable`/`Property` node when there is no lookup to resolve.
|
|
56
|
-
*
|
|
57
|
-
* @param {string} raw
|
|
58
|
-
* @returns {{ name: string, lookups: string[] | null }}
|
|
59
|
-
*/
|
|
60
|
-
export function splitLookups(raw) {
|
|
61
|
-
const open = raw.indexOf('[');
|
|
62
|
-
if (open === -1) {
|
|
63
|
-
return { name: raw, lookups: null };
|
|
64
|
-
}
|
|
65
|
-
/** @type {string[]} */
|
|
66
|
-
const lookups = [];
|
|
67
|
-
const re = new RegExp(LOOKUP_SEGMENT.source, 'g');
|
|
68
|
-
let match;
|
|
69
|
-
while ((match = re.exec(raw)) !== null) {
|
|
70
|
-
lookups.push(match[1]);
|
|
71
|
-
}
|
|
72
|
-
return { name: raw.slice(0, open), lookups };
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Build the node for an interpolated `@variable` reference, with or without lookups.
|
|
77
|
-
*
|
|
78
|
-
* @param {string} raw - the reference text inside `@{...}`
|
|
79
|
-
* @param {number} index
|
|
80
|
-
* @param {FileInfo} fileInfo
|
|
81
|
-
* @returns {Node}
|
|
82
|
-
*/
|
|
83
|
-
export function resolveInterpolatedVariable(raw, index, fileInfo) {
|
|
84
|
-
const { name, lookups } = splitLookups(raw);
|
|
85
|
-
if (!lookups) {
|
|
86
|
-
return new Variable(`@${name}`, index, fileInfo);
|
|
87
|
-
}
|
|
88
|
-
return new NamespaceValue(
|
|
89
|
-
new VariableCall(`@${name}`, index, fileInfo), lookups, index, fileInfo
|
|
90
|
-
);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Build the node for an interpolated `$property` reference.
|
|
95
|
-
*
|
|
96
|
-
* No lookup handling: see {@link PROPERTY_INTERPOLATION}. Properties have no lookup
|
|
97
|
-
* grammar, so `raw` is always a bare name here.
|
|
98
|
-
*
|
|
99
|
-
* @param {string} raw - the reference text inside `${...}`
|
|
100
|
-
* @param {number} index
|
|
101
|
-
* @param {FileInfo} fileInfo
|
|
102
|
-
* @returns {Node}
|
|
103
|
-
*/
|
|
104
|
-
export function resolveInterpolatedProperty(raw, index, fileInfo) {
|
|
105
|
-
return new Property(`$${raw}`, index, fileInfo);
|
|
106
|
-
}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
/** @import { EvalContext, FileInfo } from './node.js' */
|
|
3
|
-
import JsEvalNode from './js-eval-node.js';
|
|
4
|
-
import Dimension from './dimension.js';
|
|
5
|
-
import Quoted from './quoted.js';
|
|
6
|
-
import Anonymous from './anonymous.js';
|
|
7
|
-
|
|
8
|
-
class JavaScript extends JsEvalNode {
|
|
9
|
-
get type() { return 'JavaScript'; }
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* @param {string} string
|
|
13
|
-
* @param {boolean} escaped
|
|
14
|
-
* @param {number} index
|
|
15
|
-
* @param {FileInfo} currentFileInfo
|
|
16
|
-
*/
|
|
17
|
-
constructor(string, escaped, index, currentFileInfo) {
|
|
18
|
-
super();
|
|
19
|
-
this.escaped = escaped;
|
|
20
|
-
this.expression = string;
|
|
21
|
-
this._index = index;
|
|
22
|
-
this._fileInfo = currentFileInfo;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* @param {EvalContext} context
|
|
27
|
-
* @returns {Dimension | Quoted | Anonymous}
|
|
28
|
-
*/
|
|
29
|
-
eval(context) {
|
|
30
|
-
const result = this.evaluateJavaScript(this.expression, context);
|
|
31
|
-
const type = typeof result;
|
|
32
|
-
|
|
33
|
-
if (type === 'number' && !isNaN(/** @type {number} */ (result))) {
|
|
34
|
-
return new Dimension(/** @type {number} */ (result));
|
|
35
|
-
} else if (type === 'string') {
|
|
36
|
-
return new Quoted(`"${result}"`, /** @type {string} */ (result), this.escaped, this._index);
|
|
37
|
-
} else if (Array.isArray(result)) {
|
|
38
|
-
return new Anonymous(/** @type {string[]} */ (result).join(', '));
|
|
39
|
-
} else {
|
|
40
|
-
return new Anonymous(/** @type {string} */ (result));
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export default JavaScript;
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
/** @import { EvalContext } from './node.js' */
|
|
3
|
-
import Node from './node.js';
|
|
4
|
-
import Variable from './variable.js';
|
|
5
|
-
import {
|
|
6
|
-
VARIABLE_INTERPOLATION,
|
|
7
|
-
resolveInterpolatedVariable
|
|
8
|
-
} from './interpolated-variable.js';
|
|
9
|
-
|
|
10
|
-
class JsEvalNode extends Node {
|
|
11
|
-
/**
|
|
12
|
-
* @param {string} expression
|
|
13
|
-
* @param {EvalContext} context
|
|
14
|
-
* @returns {string | number | boolean}
|
|
15
|
-
*/
|
|
16
|
-
evaluateJavaScript(expression, context) {
|
|
17
|
-
let result;
|
|
18
|
-
const that = this;
|
|
19
|
-
/** @type {Record<string, { value: Node, toJS: () => string }>} */
|
|
20
|
-
const evalContext = {};
|
|
21
|
-
|
|
22
|
-
if (!context.javascriptEnabled) {
|
|
23
|
-
throw { message: 'Inline JavaScript is not enabled. Is it set in your options?',
|
|
24
|
-
filename: this.fileInfo().filename,
|
|
25
|
-
index: this.getIndex() };
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
expression = expression.replace(VARIABLE_INTERPOLATION, function (_, raw) {
|
|
29
|
-
return that.jsify(resolveInterpolatedVariable(
|
|
30
|
-
raw, that.getIndex(), that.fileInfo()
|
|
31
|
-
).eval(context));
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
/** @type {Function} */
|
|
35
|
-
let expressionFunc;
|
|
36
|
-
try {
|
|
37
|
-
expressionFunc = new Function(`return (${expression})`);
|
|
38
|
-
} catch (e) {
|
|
39
|
-
throw { message: `JavaScript evaluation error: ${/** @type {Error} */ (e).message} from \`${expression}\`` ,
|
|
40
|
-
filename: this.fileInfo().filename,
|
|
41
|
-
index: this.getIndex() };
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const variables = /** @type {Node & { variables: () => Record<string, { value: Node }> }} */ (context.frames[0]).variables();
|
|
45
|
-
for (const k in variables) {
|
|
46
|
-
// eslint-disable-next-line no-prototype-builtins
|
|
47
|
-
if (variables.hasOwnProperty(k)) {
|
|
48
|
-
evalContext[k.slice(1)] = {
|
|
49
|
-
value: variables[k].value,
|
|
50
|
-
toJS: function () {
|
|
51
|
-
return this.value.eval(context).toCSS(context);
|
|
52
|
-
}
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
try {
|
|
58
|
-
result = expressionFunc.call(evalContext);
|
|
59
|
-
} catch (e) {
|
|
60
|
-
throw { message: `JavaScript evaluation error: '${/** @type {Error} */ (e).name}: ${/** @type {Error} */ (e).message.replace(/["]/g, '\'')}'` ,
|
|
61
|
-
filename: this.fileInfo().filename,
|
|
62
|
-
index: this.getIndex() };
|
|
63
|
-
}
|
|
64
|
-
return result;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* @param {Node} obj
|
|
69
|
-
* @returns {string}
|
|
70
|
-
*/
|
|
71
|
-
jsify(obj) {
|
|
72
|
-
if (Array.isArray(obj.value) && (obj.value.length > 1)) {
|
|
73
|
-
return `[${obj.value.map(function (v) { return v.toCSS(/** @type {EvalContext} */ (undefined)); }).join(', ')}]`;
|
|
74
|
-
} else {
|
|
75
|
-
return obj.toCSS(/** @type {EvalContext} */ (undefined));
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
export default JsEvalNode;
|
package/lib/less/tree/keyword.js
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
import Node from './node.js';
|
|
3
|
-
|
|
4
|
-
/** @import { EvalContext, CSSOutput } from './node.js' */
|
|
5
|
-
|
|
6
|
-
class Keyword extends Node {
|
|
7
|
-
get type() { return 'Keyword'; }
|
|
8
|
-
|
|
9
|
-
/** @param {string} value */
|
|
10
|
-
constructor(value) {
|
|
11
|
-
super();
|
|
12
|
-
this.value = value;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* @param {EvalContext} context
|
|
17
|
-
* @param {CSSOutput} output
|
|
18
|
-
*/
|
|
19
|
-
genCSS(context, output) {
|
|
20
|
-
if (this.value === '%') { throw { type: 'Syntax', message: 'Invalid % without number' }; }
|
|
21
|
-
output.add(/** @type {string} */ (this.value));
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
Keyword.True = new Keyword('true');
|
|
26
|
-
Keyword.False = new Keyword('false');
|
|
27
|
-
|
|
28
|
-
export default Keyword;
|