less 4.9.1 → 5.0.0-alpha.10

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 (134) hide show
  1. package/README.md +23 -5
  2. package/V5-STATUS.md +71 -0
  3. package/bin/lessc +302 -626
  4. package/dist/less-browser-dev.js +2550 -0
  5. package/dist/less-node.cjs +480 -14561
  6. package/index.cjs +5 -2
  7. package/lib/browser-dev.js +86 -0
  8. package/lib/index.js +164 -0
  9. package/lib/lessc-helper.js +64 -0
  10. package/lib/logger.js +76 -0
  11. package/lib/options.d.ts +82 -0
  12. package/lib/options.js +227 -0
  13. package/lib/types.js +20 -0
  14. package/lib/version.js +19 -0
  15. package/package.json +36 -40
  16. package/dist/less.cjs +0 -15218
  17. package/dist/less.js +0 -15218
  18. package/dist/less.min.js +0 -11
  19. package/dist/less.min.js.map +0 -1
  20. package/lib/less/constants.js +0 -13
  21. package/lib/less/contexts.js +0 -165
  22. package/lib/less/data/colors.js +0 -150
  23. package/lib/less/data/index.js +0 -4
  24. package/lib/less/data/unit-conversions.js +0 -21
  25. package/lib/less/default-options.js +0 -89
  26. package/lib/less/deprecation.js +0 -82
  27. package/lib/less/environment/abstract-file-manager.js +0 -140
  28. package/lib/less/environment/abstract-plugin-loader.js +0 -185
  29. package/lib/less/environment/environment-api.ts +0 -21
  30. package/lib/less/environment/environment.js +0 -59
  31. package/lib/less/environment/file-manager-api.ts +0 -77
  32. package/lib/less/functions/boolean.js +0 -29
  33. package/lib/less/functions/color-blending.js +0 -85
  34. package/lib/less/functions/color.js +0 -452
  35. package/lib/less/functions/data-uri.js +0 -74
  36. package/lib/less/functions/default.js +0 -26
  37. package/lib/less/functions/function-caller.js +0 -55
  38. package/lib/less/functions/function-registry.js +0 -36
  39. package/lib/less/functions/index.js +0 -35
  40. package/lib/less/functions/list.js +0 -158
  41. package/lib/less/functions/math-helper.js +0 -22
  42. package/lib/less/functions/math.js +0 -30
  43. package/lib/less/functions/number.js +0 -95
  44. package/lib/less/functions/string.js +0 -39
  45. package/lib/less/functions/style.js +0 -29
  46. package/lib/less/functions/svg.js +0 -87
  47. package/lib/less/functions/types.js +0 -70
  48. package/lib/less/import-manager.js +0 -183
  49. package/lib/less/index.js +0 -95
  50. package/lib/less/less-error.js +0 -166
  51. package/lib/less/logger.js +0 -34
  52. package/lib/less/parse-tree.js +0 -124
  53. package/lib/less/parse.js +0 -87
  54. package/lib/less/parser/lookup-pattern.js +0 -26
  55. package/lib/less/parser/parser-input.js +0 -400
  56. package/lib/less/parser/parser.js +0 -2998
  57. package/lib/less/plugin-manager.js +0 -168
  58. package/lib/less/render.js +0 -41
  59. package/lib/less/source-map-builder.js +0 -82
  60. package/lib/less/source-map-output.js +0 -151
  61. package/lib/less/transform-tree.js +0 -102
  62. package/lib/less/tree/anonymous.js +0 -61
  63. package/lib/less/tree/assignment.js +0 -48
  64. package/lib/less/tree/atrule-syntax.js +0 -8
  65. package/lib/less/tree/atrule.js +0 -340
  66. package/lib/less/tree/attribute.js +0 -63
  67. package/lib/less/tree/call.js +0 -132
  68. package/lib/less/tree/color.js +0 -285
  69. package/lib/less/tree/combinator.js +0 -38
  70. package/lib/less/tree/comment.js +0 -48
  71. package/lib/less/tree/condition.js +0 -65
  72. package/lib/less/tree/container.js +0 -104
  73. package/lib/less/tree/debug-info.js +0 -80
  74. package/lib/less/tree/declaration.js +0 -142
  75. package/lib/less/tree/detached-ruleset.js +0 -45
  76. package/lib/less/tree/dimension.js +0 -215
  77. package/lib/less/tree/element.js +0 -93
  78. package/lib/less/tree/expression.js +0 -100
  79. package/lib/less/tree/extend.js +0 -88
  80. package/lib/less/tree/import.js +0 -299
  81. package/lib/less/tree/index.js +0 -56
  82. package/lib/less/tree/interpolated-variable.js +0 -106
  83. package/lib/less/tree/javascript.js +0 -45
  84. package/lib/less/tree/js-eval-node.js +0 -80
  85. package/lib/less/tree/keyword.js +0 -28
  86. package/lib/less/tree/media.js +0 -90
  87. package/lib/less/tree/merge-rules.js +0 -47
  88. package/lib/less/tree/mixin-call.js +0 -283
  89. package/lib/less/tree/mixin-definition.js +0 -319
  90. package/lib/less/tree/namespace-value.js +0 -95
  91. package/lib/less/tree/negative.js +0 -37
  92. package/lib/less/tree/nested-at-rule.js +0 -239
  93. package/lib/less/tree/node.js +0 -310
  94. package/lib/less/tree/operation.js +0 -81
  95. package/lib/less/tree/paren.js +0 -41
  96. package/lib/less/tree/property.js +0 -96
  97. package/lib/less/tree/query-in-parens.js +0 -64
  98. package/lib/less/tree/quoted.js +0 -131
  99. package/lib/less/tree/ruleset.js +0 -1068
  100. package/lib/less/tree/selector.js +0 -201
  101. package/lib/less/tree/unicode-descriptor.js +0 -14
  102. package/lib/less/tree/unit.js +0 -170
  103. package/lib/less/tree/url.js +0 -83
  104. package/lib/less/tree/value.js +0 -60
  105. package/lib/less/tree/variable-call.js +0 -60
  106. package/lib/less/tree/variable.js +0 -85
  107. package/lib/less/utils.js +0 -126
  108. package/lib/less/visitors/extend-visitor.js +0 -505
  109. package/lib/less/visitors/import-sequencer.js +0 -56
  110. package/lib/less/visitors/import-visitor.js +0 -203
  111. package/lib/less/visitors/index.js +0 -15
  112. package/lib/less/visitors/join-selector-visitor.js +0 -65
  113. package/lib/less/visitors/set-tree-visibility-visitor.js +0 -57
  114. package/lib/less/visitors/to-css-visitor.js +0 -332
  115. package/lib/less/visitors/visitor.js +0 -165
  116. package/lib/less-browser/add-default-options.js +0 -53
  117. package/lib/less-browser/bootstrap.js +0 -67
  118. package/lib/less-browser/browser.js +0 -65
  119. package/lib/less-browser/cache.js +0 -43
  120. package/lib/less-browser/error-reporting.js +0 -170
  121. package/lib/less-browser/file-manager.js +0 -112
  122. package/lib/less-browser/image-size.js +0 -28
  123. package/lib/less-browser/index.js +0 -284
  124. package/lib/less-browser/log-listener.js +0 -42
  125. package/lib/less-browser/plugin-loader.js +0 -24
  126. package/lib/less-browser/utils.js +0 -30
  127. package/lib/less-node/environment.js +0 -43
  128. package/lib/less-node/file-manager.js +0 -156
  129. package/lib/less-node/fs.js +0 -14
  130. package/lib/less-node/image-size.js +0 -78
  131. package/lib/less-node/index.js +0 -31
  132. package/lib/less-node/lessc-helper.js +0 -95
  133. package/lib/less-node/plugin-loader.js +0 -62
  134. package/lib/less-node/url-file-manager.js +0 -60
@@ -1,340 +0,0 @@
1
- // @ts-check
2
- /** @import { EvalContext, CSSOutput, TreeVisitor, FileInfo, VisibilityInfo } from './node.js' */
3
- /** @import { FunctionRegistry } from './nested-at-rule.js' */
4
- import Node from './node.js';
5
- import Selector from './selector.js';
6
- import Ruleset from './ruleset.js';
7
- import Anonymous from './anonymous.js';
8
- import NestableAtRulePrototype from './nested-at-rule.js';
9
- import mergeRules from './merge-rules.js';
10
-
11
- /**
12
- * @typedef {Node & {
13
- * rules?: Node[],
14
- * selectors?: Selector[],
15
- * root?: boolean,
16
- * allowImports?: boolean,
17
- * functionRegistry?: FunctionRegistry,
18
- * merge?: boolean,
19
- * debugInfo?: { lineNumber: number, fileName: string },
20
- * elements?: import('./element.js').default[]
21
- * }} RulesetLikeNode
22
- */
23
-
24
- class AtRule extends Node {
25
- get type() { return 'AtRule'; }
26
-
27
- /**
28
- * @param {string} [name]
29
- * @param {Node | string} [value]
30
- * @param {Node[] | Ruleset} [rules]
31
- * @param {number} [index]
32
- * @param {FileInfo} [currentFileInfo]
33
- * @param {{ lineNumber: number, fileName: string }} [debugInfo]
34
- * @param {boolean} [isRooted]
35
- * @param {VisibilityInfo} [visibilityInfo]
36
- */
37
- constructor(
38
- name,
39
- value,
40
- rules,
41
- index,
42
- currentFileInfo,
43
- debugInfo,
44
- isRooted,
45
- visibilityInfo
46
- ) {
47
- super();
48
- let i;
49
- var selectors = (new Selector([], null, null, index, currentFileInfo)).createEmptySelectors();
50
-
51
- /** @type {string | undefined} */
52
- this.name = name;
53
- this.value = (value instanceof Node) ? value : (value ? new Anonymous(value) : value);
54
- /** @type {boolean | undefined} */
55
- this.simpleBlock = undefined;
56
- /** @type {RulesetLikeNode[] | undefined} */
57
- this.declarations = undefined;
58
- /** @type {RulesetLikeNode[] | undefined} */
59
- this.rules = undefined;
60
- if (rules) {
61
- if (Array.isArray(rules)) {
62
- const allDeclarations = this.declarationsBlock(rules);
63
-
64
- let allRulesetDeclarations = true;
65
- rules.forEach(rule => {
66
- if (rule.type === 'Ruleset' && /** @type {RulesetLikeNode} */ (rule).rules) allRulesetDeclarations = allRulesetDeclarations && this.declarationsBlock(/** @type {Node[]} */ (/** @type {RulesetLikeNode} */ (rule).rules), true);
67
- });
68
-
69
- if (allDeclarations && !isRooted) {
70
- this.simpleBlock = true;
71
- this.declarations = rules;
72
- } else if (allRulesetDeclarations && rules.length === 1 && !isRooted && !value) {
73
- this.simpleBlock = true;
74
- this.declarations = /** @type {RulesetLikeNode} */ (rules[0]).rules ? /** @type {RulesetLikeNode} */ (rules[0]).rules : rules;
75
- } else {
76
- this.rules = rules;
77
- }
78
- } else {
79
- const allDeclarations = this.declarationsBlock(/** @type {Node[]} */ (rules.rules));
80
-
81
- if (allDeclarations && !isRooted && !value) {
82
- this.simpleBlock = true;
83
- this.declarations = rules.rules;
84
- } else {
85
- this.rules = [rules];
86
- /** @type {RulesetLikeNode} */ (this.rules[0]).selectors = (new Selector([], null, null, index, currentFileInfo)).createEmptySelectors();
87
- }
88
- }
89
- if (!this.simpleBlock) {
90
- for (i = 0; i < this.rules.length; i++) {
91
- /** @type {RulesetLikeNode} */ (this.rules[i]).allowImports = true;
92
- }
93
- }
94
- if (this.declarations) {
95
- this.setParent(this.declarations, /** @type {Node} */ (/** @type {unknown} */ (this)));
96
- }
97
- if (this.rules) {
98
- this.setParent(this.rules, /** @type {Node} */ (/** @type {unknown} */ (this)));
99
- }
100
- }
101
- this._index = index;
102
- this._fileInfo = currentFileInfo;
103
- /** @type {{ lineNumber: number, fileName: string } | undefined} */
104
- this.debugInfo = debugInfo;
105
- /** @type {boolean} */
106
- this.isRooted = isRooted || false;
107
- this.copyVisibilityInfo(visibilityInfo);
108
- this.allowRoot = true;
109
- }
110
-
111
- /**
112
- * @param {Node[]} rules
113
- * @param {boolean} [mergeable]
114
- * @returns {boolean}
115
- */
116
- declarationsBlock(rules, mergeable = false) {
117
- if (!mergeable) {
118
- return rules.filter(function (/** @type {Node & { merge?: boolean }} */ node) { return (node.type === 'Declaration' || node.type === 'Comment') && !node.merge}).length === rules.length;
119
- } else {
120
- return rules.filter(function (/** @type {Node} */ node) { return (node.type === 'Declaration' || node.type === 'Comment'); }).length === rules.length;
121
- }
122
- }
123
-
124
- /**
125
- * @param {Node[]} rules
126
- * @returns {boolean}
127
- */
128
- keywordList(rules) {
129
- if (!Array.isArray(rules)) {
130
- return false;
131
- } else {
132
- return rules.filter(function (/** @type {Node} */ node) { return (node.type === 'Keyword' || node.type === 'Comment'); }).length === rules.length;
133
- }
134
- }
135
-
136
- /** @param {TreeVisitor} visitor */
137
- accept(visitor) {
138
- const value = this.value, rules = this.rules, declarations = this.declarations;
139
-
140
- if (rules) {
141
- this.rules = visitor.visitArray(rules);
142
- } else if (declarations) {
143
- this.declarations = visitor.visitArray(declarations);
144
- }
145
- if (value) {
146
- this.value = visitor.visit(/** @type {Node} */ (value));
147
- }
148
- }
149
-
150
- /** @override @returns {boolean} */
151
- isRulesetLike() {
152
- return /** @type {boolean} */ (/** @type {unknown} */ (this.rules || !this.isCharset()));
153
- }
154
-
155
- isCharset() {
156
- return '@charset' === this.name;
157
- }
158
-
159
- /**
160
- * @param {EvalContext} context
161
- * @param {CSSOutput} output
162
- */
163
- genCSS(context, output) {
164
- const value = this.value, rules = this.rules || this.declarations;
165
- output.add(/** @type {string} */ (this.name), this.fileInfo(), this.getIndex());
166
- if (value) {
167
- output.add(' ');
168
- /** @type {Node} */ (value).genCSS(context, output);
169
- }
170
- if (this.simpleBlock) {
171
- this.outputRuleset(context, output, /** @type {Node[]} */ (this.declarations));
172
- } else if (rules) {
173
- this.outputRuleset(context, output, rules);
174
- } else {
175
- output.add(';');
176
- }
177
- }
178
-
179
- /**
180
- * @param {EvalContext} context
181
- * @returns {Node}
182
- */
183
- eval(context) {
184
- let mediaPathBackup, mediaBlocksBackup, value = this.value, rules = this.rules || this.declarations;
185
-
186
- // media stored inside other atrule should not bubble over it
187
- // backpup media bubbling information
188
- mediaPathBackup = context.mediaPath;
189
- mediaBlocksBackup = context.mediaBlocks;
190
- // deleted media bubbling information
191
- context.mediaPath = [];
192
- context.mediaBlocks = [];
193
-
194
- if (value) {
195
- value = /** @type {Node} */ (value).eval(context);
196
- }
197
-
198
- if (rules) {
199
- rules = this.evalRoot(context, rules);
200
- }
201
- if (Array.isArray(rules) && /** @type {RulesetLikeNode} */ (rules[0]).rules && Array.isArray(/** @type {RulesetLikeNode} */ (rules[0]).rules) && /** @type {Node[]} */ (/** @type {RulesetLikeNode} */ (rules[0]).rules).length) {
202
- const allMergeableDeclarations = this.declarationsBlock(/** @type {Node[]} */ (/** @type {RulesetLikeNode} */ (rules[0]).rules), true);
203
- if (allMergeableDeclarations && !this.isRooted && !value) {
204
- mergeRules(/** @type {Node[]} */ (/** @type {RulesetLikeNode} */ (rules[0]).rules));
205
- rules = /** @type {RulesetLikeNode[]} */ (/** @type {RulesetLikeNode} */ (rules[0]).rules);
206
- rules.forEach(/** @param {RulesetLikeNode} rule */ rule => { rule.merge = false; });
207
- }
208
- }
209
- if (this.simpleBlock && rules) {
210
- /** @type {RulesetLikeNode} */ (rules[0]).functionRegistry = /** @type {RulesetLikeNode} */ (context.frames[0]).functionRegistry.inherit();
211
- rules = rules.map(function (/** @type {Node} */ rule) { return rule.eval(context); });
212
- }
213
-
214
- // restore media bubbling information
215
- context.mediaPath = mediaPathBackup;
216
- context.mediaBlocks = mediaBlocksBackup;
217
- return /** @type {Node} */ (/** @type {unknown} */ (new AtRule(this.name, value, rules, this.getIndex(), this.fileInfo(), this.debugInfo, this.isRooted, this.visibilityInfo())));
218
- }
219
-
220
- /**
221
- * @param {EvalContext} context
222
- * @param {Node[]} rules
223
- * @returns {Node[]}
224
- */
225
- evalRoot(context, rules) {
226
- let ampersandCount = 0;
227
- let noAmpersandCount = 0;
228
- let noAmpersands = true;
229
-
230
- if (!this.simpleBlock) {
231
- rules = [rules[0].eval(context)];
232
- }
233
-
234
- /** @type {Selector[]} */
235
- let precedingSelectors = [];
236
- if (context.frames.length > 0) {
237
- for (let index = 0; index < context.frames.length; index++) {
238
- const frame = /** @type {RulesetLikeNode} */ (context.frames[index]);
239
- if (
240
- frame.type === 'Ruleset' &&
241
- frame.rules &&
242
- frame.rules.length > 0
243
- ) {
244
- if (frame && !frame.root && frame.selectors && frame.selectors.length > 0) {
245
- precedingSelectors = precedingSelectors.concat(frame.selectors);
246
- }
247
- }
248
- if (precedingSelectors.length > 0) {
249
- const allAmpersandElements = precedingSelectors.every(
250
- sel => sel.elements && sel.elements.length > 0 && sel.elements.every(
251
- /** @param {import('./element.js').default} el */
252
- el => el.value === '&'
253
- )
254
- );
255
- if (allAmpersandElements) {
256
- noAmpersands = false;
257
- noAmpersandCount++;
258
- } else {
259
- ampersandCount++;
260
- }
261
- }
262
- }
263
- }
264
-
265
- const mixedAmpersands = ampersandCount > 0 && noAmpersandCount > 0 && !noAmpersands;
266
- if (
267
- (this.isRooted && ampersandCount > 0 && noAmpersandCount === 0 && noAmpersands)
268
- || !mixedAmpersands
269
- ) {
270
- /** @type {RulesetLikeNode} */ (rules[0]).root = true;
271
- }
272
- return rules;
273
- }
274
-
275
- /** @param {string} name */
276
- variable(name) {
277
- if (this.rules) {
278
- // assuming that there is only one rule at this point - that is how parser constructs the rule
279
- return Ruleset.prototype.variable.call(this.rules[0], name);
280
- }
281
- }
282
-
283
- find() {
284
- if (this.rules) {
285
- // assuming that there is only one rule at this point - that is how parser constructs the rule
286
- return Ruleset.prototype.find.apply(this.rules[0], arguments);
287
- }
288
- }
289
-
290
- rulesets() {
291
- if (this.rules) {
292
- // assuming that there is only one rule at this point - that is how parser constructs the rule
293
- return Ruleset.prototype.rulesets.apply(this.rules[0]);
294
- }
295
- }
296
-
297
- /**
298
- * @param {EvalContext} context
299
- * @param {CSSOutput} output
300
- * @param {Node[]} rules
301
- */
302
- outputRuleset(context, output, rules) {
303
- const ruleCnt = rules.length;
304
- let i;
305
- context.tabLevel = (context.tabLevel | 0) + 1;
306
-
307
- // Compressed
308
- if (context.compress) {
309
- output.add('{');
310
- for (i = 0; i < ruleCnt; i++) {
311
- rules[i].genCSS(context, output);
312
- }
313
- output.add('}');
314
- context.tabLevel--;
315
- return;
316
- }
317
-
318
- // Non-compressed
319
- const tabSetStr = `\n${Array(context.tabLevel).join(' ')}`, tabRuleStr = `${tabSetStr} `;
320
- if (!ruleCnt) {
321
- output.add(` {${tabSetStr}}`);
322
- } else {
323
- output.add(` {${tabRuleStr}`);
324
- rules[0].genCSS(context, output);
325
- for (i = 1; i < ruleCnt; i++) {
326
- output.add(tabRuleStr);
327
- rules[i].genCSS(context, output);
328
- }
329
- output.add(`${tabSetStr}}`);
330
- }
331
-
332
- context.tabLevel--;
333
- }
334
- }
335
-
336
- // Apply shared methods from NestableAtRulePrototype that AtRule doesn't override
337
- const { evalFunction, evalTop, evalNested, permute, bubbleSelectors } = NestableAtRulePrototype;
338
- Object.assign(AtRule.prototype, { evalFunction, evalTop, evalNested, permute, bubbleSelectors });
339
-
340
- export default AtRule;
@@ -1,63 +0,0 @@
1
- // @ts-check
2
- /** @import { EvalContext, CSSOutput } from './node.js' */
3
- import Node from './node.js';
4
-
5
- class Attribute extends Node {
6
- get type() { return 'Attribute'; }
7
-
8
- /**
9
- * @param {string | Node} key
10
- * @param {string} op
11
- * @param {string | Node} value
12
- * @param {string} cif
13
- */
14
- constructor(key, op, value, cif) {
15
- super();
16
- this.key = key;
17
- this.op = op;
18
- this.value = value;
19
- this.cif = cif;
20
- }
21
-
22
- /**
23
- * @param {EvalContext} context
24
- * @returns {Attribute}
25
- */
26
- eval(context) {
27
- return new Attribute(
28
- /** @type {Node} */ (this.key).eval ? /** @type {Node} */ (this.key).eval(context) : /** @type {string} */ (this.key),
29
- this.op,
30
- (this.value && /** @type {Node} */ (this.value).eval) ? /** @type {Node} */ (this.value).eval(context) : this.value,
31
- this.cif
32
- );
33
- }
34
-
35
- /**
36
- * @param {EvalContext} context
37
- * @param {CSSOutput} output
38
- */
39
- genCSS(context, output) {
40
- output.add(this.toCSS(context));
41
- }
42
-
43
- /**
44
- * @param {EvalContext} context
45
- * @returns {string}
46
- */
47
- toCSS(context) {
48
- let value = /** @type {Node} */ (this.key).toCSS ? /** @type {Node} */ (this.key).toCSS(context) : /** @type {string} */ (this.key);
49
-
50
- if (this.op) {
51
- value += this.op;
52
- value += (/** @type {Node} */ (this.value).toCSS ? /** @type {Node} */ (this.value).toCSS(context) : /** @type {string} */ (this.value));
53
- }
54
-
55
- if (this.cif) {
56
- value = value + ' ' + this.cif;
57
- }
58
-
59
- return `[${value}]`;
60
- }
61
- }
62
-
63
- export default Attribute;
@@ -1,132 +0,0 @@
1
- // @ts-check
2
- /** @import { EvalContext, CSSOutput, TreeVisitor, FileInfo } from './node.js' */
3
- import Node from './node.js';
4
- import Anonymous from './anonymous.js';
5
- import FunctionCaller from '../functions/function-caller.js';
6
-
7
- //
8
- // A function call node.
9
- //
10
- class Call extends Node {
11
- get type() { return 'Call'; }
12
-
13
- /**
14
- * @param {string} name
15
- * @param {Node[]} args
16
- * @param {number} index
17
- * @param {FileInfo} currentFileInfo
18
- */
19
- constructor(name, args, index, currentFileInfo) {
20
- super();
21
- this.name = name;
22
- this.args = args;
23
- this.calc = name === 'calc';
24
- this._index = index;
25
- this._fileInfo = currentFileInfo;
26
- }
27
-
28
- /** @param {TreeVisitor} visitor */
29
- accept(visitor) {
30
- if (this.args) {
31
- this.args = visitor.visitArray(this.args);
32
- }
33
- }
34
-
35
- //
36
- // When evaluating a function call,
37
- // we either find the function in the functionRegistry,
38
- // in which case we call it, passing the evaluated arguments,
39
- // if this returns null or we cannot find the function, we
40
- // simply print it out as it appeared originally [2].
41
- //
42
- // The reason why we evaluate the arguments, is in the case where
43
- // we try to pass a variable to a function, like: `saturate(@color)`.
44
- // The function should receive the value, not the variable.
45
- //
46
- /**
47
- * @param {EvalContext} context
48
- * @returns {Node}
49
- */
50
- eval(context) {
51
- /**
52
- * Turn off math for calc(), and switch back on for evaluating nested functions
53
- */
54
- const currentMathContext = context.mathOn;
55
- context.mathOn = !this.calc;
56
- if (this.calc || context.inCalc) {
57
- context.enterCalc();
58
- }
59
-
60
- const exitCalc = () => {
61
- if (this.calc || context.inCalc) {
62
- context.exitCalc();
63
- }
64
- context.mathOn = currentMathContext;
65
- };
66
-
67
- /** @type {Node | string | boolean | null | undefined} */
68
- let result;
69
- const funcCaller = new FunctionCaller(this.name, context, this.getIndex(), this.fileInfo());
70
-
71
- if (funcCaller.isValid()) {
72
- try {
73
- result = funcCaller.call(this.args);
74
- exitCalc();
75
- } catch (e) {
76
- // eslint-disable-next-line no-prototype-builtins
77
- if (/** @type {Record<string, unknown>} */ (e).hasOwnProperty('line') && /** @type {Record<string, unknown>} */ (e).hasOwnProperty('column')) {
78
- throw e;
79
- }
80
- throw {
81
- type: /** @type {Record<string, string>} */ (e).type || 'Runtime',
82
- message: `Error evaluating function \`${this.name}\`${/** @type {Error} */ (e).message ? `: ${/** @type {Error} */ (e).message}` : ''}`,
83
- index: this.getIndex(),
84
- filename: this.fileInfo().filename,
85
- line: /** @type {Record<string, number>} */ (e).lineNumber,
86
- column: /** @type {Record<string, number>} */ (e).columnNumber
87
- };
88
- }
89
- }
90
-
91
- if (result !== null && result !== undefined) {
92
- // Results that that are not nodes are cast as Anonymous nodes
93
- // Falsy values or booleans are returned as empty nodes
94
- if (!(result instanceof Node)) {
95
- if (!result || result === true) {
96
- result = new Anonymous(null);
97
- }
98
- else {
99
- result = new Anonymous(result.toString());
100
- }
101
-
102
- }
103
- result._index = this._index;
104
- result._fileInfo = this._fileInfo;
105
- return result;
106
- }
107
-
108
- const args = this.args.map(a => a.eval(context));
109
- exitCalc();
110
-
111
- return new Call(this.name, args, this.getIndex(), this.fileInfo());
112
- }
113
-
114
- /**
115
- * @param {EvalContext} context
116
- * @param {CSSOutput} output
117
- */
118
- genCSS(context, output) {
119
- output.add(`${this.name}(`, this.fileInfo(), this.getIndex());
120
-
121
- for (let i = 0; i < this.args.length; i++) {
122
- this.args[i].genCSS(context, output);
123
- if (i + 1 < this.args.length) {
124
- output.add(', ');
125
- }
126
- }
127
-
128
- output.add(')');
129
- }
130
- }
131
-
132
- export default Call;