less 4.8.1 → 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.
Files changed (129) hide show
  1. package/README.md +19 -5
  2. package/bin/lessc +190 -630
  3. package/dist/less-node.cjs +398 -14282
  4. package/index.cjs +5 -2
  5. package/lib/index.js +164 -0
  6. package/lib/lessc-helper.js +52 -0
  7. package/lib/logger.js +76 -0
  8. package/lib/options.d.ts +46 -0
  9. package/lib/options.js +145 -0
  10. package/lib/types.js +20 -0
  11. package/lib/version.js +19 -0
  12. package/package.json +33 -40
  13. package/dist/less.cjs +0 -14929
  14. package/dist/less.js +0 -14929
  15. package/dist/less.min.js +0 -11
  16. package/dist/less.min.js.map +0 -1
  17. package/lib/less/constants.js +0 -13
  18. package/lib/less/contexts.js +0 -165
  19. package/lib/less/data/colors.js +0 -150
  20. package/lib/less/data/index.js +0 -4
  21. package/lib/less/data/unit-conversions.js +0 -21
  22. package/lib/less/default-options.js +0 -89
  23. package/lib/less/deprecation.js +0 -82
  24. package/lib/less/environment/abstract-file-manager.js +0 -140
  25. package/lib/less/environment/abstract-plugin-loader.js +0 -185
  26. package/lib/less/environment/environment-api.ts +0 -21
  27. package/lib/less/environment/environment.js +0 -59
  28. package/lib/less/environment/file-manager-api.ts +0 -77
  29. package/lib/less/functions/boolean.js +0 -29
  30. package/lib/less/functions/color-blending.js +0 -85
  31. package/lib/less/functions/color.js +0 -452
  32. package/lib/less/functions/data-uri.js +0 -74
  33. package/lib/less/functions/default.js +0 -26
  34. package/lib/less/functions/function-caller.js +0 -55
  35. package/lib/less/functions/function-registry.js +0 -36
  36. package/lib/less/functions/index.js +0 -35
  37. package/lib/less/functions/list.js +0 -158
  38. package/lib/less/functions/math-helper.js +0 -22
  39. package/lib/less/functions/math.js +0 -30
  40. package/lib/less/functions/number.js +0 -95
  41. package/lib/less/functions/string.js +0 -36
  42. package/lib/less/functions/style.js +0 -29
  43. package/lib/less/functions/svg.js +0 -87
  44. package/lib/less/functions/types.js +0 -70
  45. package/lib/less/import-manager.js +0 -183
  46. package/lib/less/index.js +0 -95
  47. package/lib/less/less-error.js +0 -166
  48. package/lib/less/logger.js +0 -34
  49. package/lib/less/parse-tree.js +0 -124
  50. package/lib/less/parse.js +0 -87
  51. package/lib/less/parser/parser-input.js +0 -400
  52. package/lib/less/parser/parser.js +0 -2894
  53. package/lib/less/plugin-manager.js +0 -168
  54. package/lib/less/render.js +0 -41
  55. package/lib/less/source-map-builder.js +0 -82
  56. package/lib/less/source-map-output.js +0 -151
  57. package/lib/less/transform-tree.js +0 -102
  58. package/lib/less/tree/anonymous.js +0 -57
  59. package/lib/less/tree/assignment.js +0 -48
  60. package/lib/less/tree/atrule-syntax.js +0 -8
  61. package/lib/less/tree/atrule.js +0 -340
  62. package/lib/less/tree/attribute.js +0 -63
  63. package/lib/less/tree/call.js +0 -132
  64. package/lib/less/tree/color.js +0 -285
  65. package/lib/less/tree/combinator.js +0 -38
  66. package/lib/less/tree/comment.js +0 -48
  67. package/lib/less/tree/condition.js +0 -65
  68. package/lib/less/tree/container.js +0 -104
  69. package/lib/less/tree/debug-info.js +0 -80
  70. package/lib/less/tree/declaration.js +0 -139
  71. package/lib/less/tree/detached-ruleset.js +0 -45
  72. package/lib/less/tree/dimension.js +0 -215
  73. package/lib/less/tree/element.js +0 -93
  74. package/lib/less/tree/expression.js +0 -100
  75. package/lib/less/tree/extend.js +0 -88
  76. package/lib/less/tree/import.js +0 -299
  77. package/lib/less/tree/index.js +0 -56
  78. package/lib/less/tree/javascript.js +0 -45
  79. package/lib/less/tree/js-eval-node.js +0 -74
  80. package/lib/less/tree/keyword.js +0 -28
  81. package/lib/less/tree/media.js +0 -90
  82. package/lib/less/tree/merge-rules.js +0 -47
  83. package/lib/less/tree/mixin-call.js +0 -283
  84. package/lib/less/tree/mixin-definition.js +0 -319
  85. package/lib/less/tree/namespace-value.js +0 -95
  86. package/lib/less/tree/negative.js +0 -37
  87. package/lib/less/tree/nested-at-rule.js +0 -198
  88. package/lib/less/tree/node.js +0 -310
  89. package/lib/less/tree/operation.js +0 -81
  90. package/lib/less/tree/paren.js +0 -41
  91. package/lib/less/tree/property.js +0 -96
  92. package/lib/less/tree/query-in-parens.js +0 -64
  93. package/lib/less/tree/quoted.js +0 -114
  94. package/lib/less/tree/ruleset.js +0 -1066
  95. package/lib/less/tree/selector.js +0 -201
  96. package/lib/less/tree/unicode-descriptor.js +0 -14
  97. package/lib/less/tree/unit.js +0 -170
  98. package/lib/less/tree/url.js +0 -83
  99. package/lib/less/tree/value.js +0 -60
  100. package/lib/less/tree/variable-call.js +0 -60
  101. package/lib/less/tree/variable.js +0 -85
  102. package/lib/less/utils.js +0 -126
  103. package/lib/less/visitors/extend-visitor.js +0 -505
  104. package/lib/less/visitors/import-sequencer.js +0 -56
  105. package/lib/less/visitors/import-visitor.js +0 -203
  106. package/lib/less/visitors/index.js +0 -15
  107. package/lib/less/visitors/join-selector-visitor.js +0 -65
  108. package/lib/less/visitors/set-tree-visibility-visitor.js +0 -57
  109. package/lib/less/visitors/to-css-visitor.js +0 -332
  110. package/lib/less/visitors/visitor.js +0 -165
  111. package/lib/less-browser/add-default-options.js +0 -53
  112. package/lib/less-browser/bootstrap.js +0 -67
  113. package/lib/less-browser/browser.js +0 -65
  114. package/lib/less-browser/cache.js +0 -43
  115. package/lib/less-browser/error-reporting.js +0 -170
  116. package/lib/less-browser/file-manager.js +0 -112
  117. package/lib/less-browser/image-size.js +0 -28
  118. package/lib/less-browser/index.js +0 -284
  119. package/lib/less-browser/log-listener.js +0 -42
  120. package/lib/less-browser/plugin-loader.js +0 -24
  121. package/lib/less-browser/utils.js +0 -30
  122. package/lib/less-node/environment.js +0 -43
  123. package/lib/less-node/file-manager.js +0 -156
  124. package/lib/less-node/fs.js +0 -14
  125. package/lib/less-node/image-size.js +0 -78
  126. package/lib/less-node/index.js +0 -31
  127. package/lib/less-node/lessc-helper.js +0 -95
  128. package/lib/less-node/plugin-loader.js +0 -62
  129. package/lib/less-node/url-file-manager.js +0 -60
@@ -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;
@@ -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,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,74 +0,0 @@
1
- // @ts-check
2
- /** @import { EvalContext } from './node.js' */
3
- import Node from './node.js';
4
- import Variable from './variable.js';
5
-
6
- class JsEvalNode extends Node {
7
- /**
8
- * @param {string} expression
9
- * @param {EvalContext} context
10
- * @returns {string | number | boolean}
11
- */
12
- evaluateJavaScript(expression, context) {
13
- let result;
14
- const that = this;
15
- /** @type {Record<string, { value: Node, toJS: () => string }>} */
16
- const evalContext = {};
17
-
18
- if (!context.javascriptEnabled) {
19
- throw { message: 'Inline JavaScript is not enabled. Is it set in your options?',
20
- filename: this.fileInfo().filename,
21
- index: this.getIndex() };
22
- }
23
-
24
- expression = expression.replace(/@\{([\w-]+)\}/g, function (_, name) {
25
- return that.jsify(new Variable(`@${name}`, that.getIndex(), that.fileInfo()).eval(context));
26
- });
27
-
28
- /** @type {Function} */
29
- let expressionFunc;
30
- try {
31
- expressionFunc = new Function(`return (${expression})`);
32
- } catch (e) {
33
- throw { message: `JavaScript evaluation error: ${/** @type {Error} */ (e).message} from \`${expression}\`` ,
34
- filename: this.fileInfo().filename,
35
- index: this.getIndex() };
36
- }
37
-
38
- const variables = /** @type {Node & { variables: () => Record<string, { value: Node }> }} */ (context.frames[0]).variables();
39
- for (const k in variables) {
40
- // eslint-disable-next-line no-prototype-builtins
41
- if (variables.hasOwnProperty(k)) {
42
- evalContext[k.slice(1)] = {
43
- value: variables[k].value,
44
- toJS: function () {
45
- return this.value.eval(context).toCSS(context);
46
- }
47
- };
48
- }
49
- }
50
-
51
- try {
52
- result = expressionFunc.call(evalContext);
53
- } catch (e) {
54
- throw { message: `JavaScript evaluation error: '${/** @type {Error} */ (e).name}: ${/** @type {Error} */ (e).message.replace(/["]/g, '\'')}'` ,
55
- filename: this.fileInfo().filename,
56
- index: this.getIndex() };
57
- }
58
- return result;
59
- }
60
-
61
- /**
62
- * @param {Node} obj
63
- * @returns {string}
64
- */
65
- jsify(obj) {
66
- if (Array.isArray(obj.value) && (obj.value.length > 1)) {
67
- return `[${obj.value.map(function (v) { return v.toCSS(/** @type {EvalContext} */ (undefined)); }).join(', ')}]`;
68
- } else {
69
- return obj.toCSS(/** @type {EvalContext} */ (undefined));
70
- }
71
- }
72
- }
73
-
74
- export default JsEvalNode;
@@ -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;
@@ -1,90 +0,0 @@
1
- // @ts-check
2
- /** @import { EvalContext, CSSOutput, FileInfo, VisibilityInfo } from './node.js' */
3
- /** @import { NestableAtRuleThis } from './nested-at-rule.js' */
4
- /** @import { RulesetLikeNode } from './atrule.js' */
5
- import Node from './node.js';
6
- import Ruleset from './ruleset.js';
7
- import Value from './value.js';
8
- import Selector from './selector.js';
9
- import AtRule from './atrule.js';
10
- import NestableAtRulePrototype from './nested-at-rule.js';
11
-
12
- class Media extends AtRule {
13
- get type() { return 'Media'; }
14
-
15
- /**
16
- * @param {Node[] | null} value
17
- * @param {Node[]} features
18
- * @param {number} [index]
19
- * @param {FileInfo} [currentFileInfo]
20
- * @param {VisibilityInfo} [visibilityInfo]
21
- */
22
- constructor(value, features, index, currentFileInfo, visibilityInfo) {
23
- super();
24
- this._index = index;
25
- this._fileInfo = currentFileInfo;
26
-
27
- const selectors = (new Selector([], null, null, this._index, this._fileInfo)).createEmptySelectors();
28
-
29
- /** @type {Value} */
30
- this.features = new Value(features);
31
- /** @type {RulesetLikeNode[]} */
32
- this.rules = [new Ruleset(selectors, value)];
33
- /** @type {RulesetLikeNode} */ (this.rules[0]).allowImports = true;
34
- this.copyVisibilityInfo(visibilityInfo);
35
- this.allowRoot = true;
36
- this.setParent(selectors, /** @type {Node} */ (/** @type {unknown} */ (this)));
37
- this.setParent(this.features, /** @type {Node} */ (/** @type {unknown} */ (this)));
38
- this.setParent(this.rules, /** @type {Node} */ (/** @type {unknown} */ (this)));
39
- }
40
-
41
- /**
42
- * @param {EvalContext} context
43
- * @param {CSSOutput} output
44
- */
45
- genCSS(context, output) {
46
- output.add('@media ', this._fileInfo, this._index);
47
- this.features.genCSS(context, output);
48
- this.outputRuleset(context, output, this.rules);
49
- }
50
-
51
- /**
52
- * @param {EvalContext} context
53
- * @returns {Node}
54
- */
55
- eval(context) {
56
- if (!context.mediaBlocks) {
57
- context.mediaBlocks = [];
58
- context.mediaPath = [];
59
- }
60
-
61
- const media = new Media(null, [], this._index, this._fileInfo, this.visibilityInfo());
62
- if (this.debugInfo) {
63
- /** @type {RulesetLikeNode} */ (this.rules[0]).debugInfo = this.debugInfo;
64
- media.debugInfo = this.debugInfo;
65
- }
66
-
67
- media.features = /** @type {Value} */ (this.features.eval(context));
68
-
69
- context.mediaPath.push(/** @type {Node} */ (/** @type {unknown} */ (media)));
70
- context.mediaBlocks.push(/** @type {Node} */ (/** @type {unknown} */ (media)));
71
-
72
- const fr = /** @type {RulesetLikeNode} */ (context.frames[0]).functionRegistry;
73
- if (fr) {
74
- /** @type {RulesetLikeNode} */ (this.rules[0]).functionRegistry = fr.inherit();
75
- }
76
- context.frames.unshift(this.rules[0]);
77
- media.rules = [/** @type {RulesetLikeNode} */ (this.rules[0].eval(context))];
78
- context.frames.shift();
79
-
80
- context.mediaPath.pop();
81
-
82
- return context.mediaPath.length === 0 ? /** @type {NestableAtRuleThis} */ (/** @type {unknown} */ (media)).evalTop(context) :
83
- /** @type {NestableAtRuleThis} */ (/** @type {unknown} */ (media)).evalNested(context);
84
- }
85
- }
86
-
87
- // Apply NestableAtRulePrototype methods (accept, isRulesetLike override AtRule's versions)
88
- Object.assign(Media.prototype, NestableAtRulePrototype);
89
-
90
- export default Media;
@@ -1,47 +0,0 @@
1
- // @ts-check
2
- import Expression from './expression.js';
3
- import Value from './value.js';
4
- import Node from './node.js';
5
-
6
- /**
7
- * Merges declarations with merge flags (+ or ,) into combined values.
8
- * Used by both the ToCSSVisitor and AtRule eval.
9
- * @param {Node[]} rules
10
- */
11
- export default function mergeRules(rules) {
12
- if (!rules) {
13
- return;
14
- }
15
-
16
- /** @type {Record<string, Array<Node & { merge: string, name: string, value: Node, important: string }>>} */
17
- const groups = {};
18
- /** @type {Array<Array<Node & { merge: string, name: string, value: Node, important: string }>>} */
19
- const groupsArr = [];
20
-
21
- for (let i = 0; i < rules.length; i++) {
22
- const rule = /** @type {Node & { merge: string, name: string }} */ (rules[i]);
23
- if (rule.merge) {
24
- const key = rule.name;
25
- groups[key] ? rules.splice(i--, 1) :
26
- groupsArr.push(groups[key] = []);
27
- groups[key].push(/** @type {Node & { merge: string, name: string, value: Node, important: string }} */ (rule));
28
- }
29
- }
30
-
31
- groupsArr.forEach(group => {
32
- if (group.length > 0) {
33
- const result = group[0];
34
- /** @type {Node[]} */
35
- let space = [];
36
- const comma = [new Expression(space)];
37
- group.forEach(rule => {
38
- if ((rule.merge === '+') && (space.length > 0)) {
39
- comma.push(new Expression(space = []));
40
- }
41
- space.push(rule.value);
42
- result.important = result.important || rule.important;
43
- });
44
- result.value = new Value(comma);
45
- }
46
- });
47
- }