iobroker.mywebui 1.37.21 → 1.37.22
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/io-package.json +1 -1
- package/package.json +1 -1
- package/www/node_modules/@node-projects/css-parser/LICENSE +11 -0
- package/www/node_modules/@node-projects/css-parser/README.md +161 -0
- package/www/node_modules/@node-projects/css-parser/dist/CssParseError.d.ts +8 -0
- package/www/node_modules/@node-projects/css-parser/dist/CssParseError.js +15 -0
- package/www/node_modules/@node-projects/css-parser/dist/CssPosition.d.ts +25 -0
- package/www/node_modules/@node-projects/css-parser/dist/CssPosition.js +13 -0
- package/www/node_modules/@node-projects/css-parser/dist/index-min.js +56 -0
- package/www/node_modules/@node-projects/css-parser/dist/index-min.js.map +7 -0
- package/www/node_modules/@node-projects/css-parser/dist/index.d.ts +12 -0
- package/www/node_modules/@node-projects/css-parser/dist/index.js +8 -0
- package/www/node_modules/@node-projects/css-parser/dist/parse/index.d.ts +8 -0
- package/www/node_modules/@node-projects/css-parser/dist/parse/index.js +1293 -0
- package/www/node_modules/@node-projects/css-parser/dist/parse/lexer.d.ts +118 -0
- package/www/node_modules/@node-projects/css-parser/dist/parse/lexer.js +248 -0
- package/www/node_modules/@node-projects/css-parser/dist/stringify/compiler.d.ts +172 -0
- package/www/node_modules/@node-projects/css-parser/dist/stringify/compiler.js +732 -0
- package/www/node_modules/@node-projects/css-parser/dist/stringify/index.d.ts +5 -0
- package/www/node_modules/@node-projects/css-parser/dist/stringify/index.js +5 -0
- package/www/node_modules/@node-projects/css-parser/dist/type.d.ts +205 -0
- package/www/node_modules/@node-projects/css-parser/dist/type.js +31 -0
- package/www/node_modules/@node-projects/css-parser/dist/utils/stringSearch.d.ts +53 -0
- package/www/node_modules/@node-projects/css-parser/dist/utils/stringSearch.js +166 -0
- package/www/node_modules/@node-projects/css-parser/docs/API.md +362 -0
- package/www/node_modules/@node-projects/css-parser/docs/AST.md +417 -0
- package/www/node_modules/@node-projects/css-parser/docs/CHANGELOG.md +205 -0
- package/www/node_modules/@node-projects/css-parser/docs/EXAMPLES.md +497 -0
- package/www/node_modules/@node-projects/css-parser/package.json +66 -0
|
@@ -0,0 +1,732 @@
|
|
|
1
|
+
import { CssTypes, } from '../type.js';
|
|
2
|
+
class Compiler {
|
|
3
|
+
level = 0;
|
|
4
|
+
indentation = ' ';
|
|
5
|
+
compress = false;
|
|
6
|
+
identity = false;
|
|
7
|
+
removeEmptyRules = false;
|
|
8
|
+
constructor(options) {
|
|
9
|
+
if (typeof options?.indent === 'string') {
|
|
10
|
+
this.indentation = options?.indent;
|
|
11
|
+
}
|
|
12
|
+
if (options?.compress) {
|
|
13
|
+
this.compress = true;
|
|
14
|
+
}
|
|
15
|
+
if (options?.identity) {
|
|
16
|
+
this.identity = true;
|
|
17
|
+
}
|
|
18
|
+
if (options?.removeEmptyRules) {
|
|
19
|
+
this.removeEmptyRules = true;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
// We disable no-unused-vars for _position. We keep position for potential reintroduction of source-map
|
|
23
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
24
|
+
emit(str, _position) {
|
|
25
|
+
return str;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Increase, decrease or return current indentation.
|
|
29
|
+
*/
|
|
30
|
+
indent(level) {
|
|
31
|
+
this.level = this.level || 1;
|
|
32
|
+
if (level) {
|
|
33
|
+
this.level += level;
|
|
34
|
+
return '';
|
|
35
|
+
}
|
|
36
|
+
return this.level > 1 ? this.indentation.repeat(this.level - 1) : '';
|
|
37
|
+
}
|
|
38
|
+
visit(node) {
|
|
39
|
+
switch (node.type) {
|
|
40
|
+
case CssTypes.stylesheet:
|
|
41
|
+
return this.stylesheet(node);
|
|
42
|
+
case CssTypes.rule:
|
|
43
|
+
return this.rule(node);
|
|
44
|
+
case CssTypes.declaration:
|
|
45
|
+
return this.declaration(node);
|
|
46
|
+
case CssTypes.comment:
|
|
47
|
+
return this.comment(node);
|
|
48
|
+
case CssTypes.whitespace:
|
|
49
|
+
return this.whitespace(node);
|
|
50
|
+
case CssTypes.container:
|
|
51
|
+
return this.container(node);
|
|
52
|
+
case CssTypes.charset:
|
|
53
|
+
return this.charset(node);
|
|
54
|
+
case CssTypes.counterStyle:
|
|
55
|
+
return this.counterStyle(node);
|
|
56
|
+
case CssTypes.document:
|
|
57
|
+
return this.document(node);
|
|
58
|
+
case CssTypes.customMedia:
|
|
59
|
+
return this.customMedia(node);
|
|
60
|
+
case CssTypes.fontFace:
|
|
61
|
+
return this.fontFace(node);
|
|
62
|
+
case CssTypes.fontFeatureValues:
|
|
63
|
+
return this.fontFeatureValues(node);
|
|
64
|
+
case CssTypes.host:
|
|
65
|
+
return this.host(node);
|
|
66
|
+
case CssTypes.import:
|
|
67
|
+
return this.import(node);
|
|
68
|
+
case CssTypes.keyframes:
|
|
69
|
+
return this.keyframes(node);
|
|
70
|
+
case CssTypes.keyframe:
|
|
71
|
+
return this.keyframe(node);
|
|
72
|
+
case CssTypes.layer:
|
|
73
|
+
return this.layer(node);
|
|
74
|
+
case CssTypes.media:
|
|
75
|
+
return this.media(node);
|
|
76
|
+
case CssTypes.namespace:
|
|
77
|
+
return this.namespace(node);
|
|
78
|
+
case CssTypes.page:
|
|
79
|
+
return this.page(node);
|
|
80
|
+
case CssTypes.pageMarginBox:
|
|
81
|
+
return this.pageMarginBox(node);
|
|
82
|
+
case CssTypes.positionTry:
|
|
83
|
+
return this.positionTry(node);
|
|
84
|
+
case CssTypes.property:
|
|
85
|
+
return this.property(node);
|
|
86
|
+
case CssTypes.scope:
|
|
87
|
+
return this.scope(node);
|
|
88
|
+
case CssTypes.startingStyle:
|
|
89
|
+
return this.startingStyle(node);
|
|
90
|
+
case CssTypes.supports:
|
|
91
|
+
return this.supports(node);
|
|
92
|
+
case CssTypes.viewTransition:
|
|
93
|
+
return this.viewTransition(node);
|
|
94
|
+
case CssTypes.atRule:
|
|
95
|
+
return this.genericAtRule(node);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
mapVisit(nodes, delim) {
|
|
99
|
+
let buf = '';
|
|
100
|
+
delim = delim || '';
|
|
101
|
+
for (let i = 0, length = nodes.length; i < length; i++) {
|
|
102
|
+
const str = this.visit(nodes[i]);
|
|
103
|
+
if (str) {
|
|
104
|
+
if (delim && buf) {
|
|
105
|
+
buf += this.emit(delim);
|
|
106
|
+
}
|
|
107
|
+
buf += str;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return buf;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Emit a block at-rule that contains nested rules (e.g. @media, @supports, @container).
|
|
114
|
+
*/
|
|
115
|
+
rulesBlock(header, rules, position, rawPrelude) {
|
|
116
|
+
if (this.identity && rawPrelude) {
|
|
117
|
+
this.indent(1);
|
|
118
|
+
const result = this.emit(rawPrelude, position) +
|
|
119
|
+
this.emit('{') +
|
|
120
|
+
this.identityVisitBlock(this.filterEmptyRules(rules), 'rules') +
|
|
121
|
+
this.emit('}');
|
|
122
|
+
this.indent(-1);
|
|
123
|
+
return result;
|
|
124
|
+
}
|
|
125
|
+
const filteredRules = this.filterEmptyRules(this.stripWhitespace(rules));
|
|
126
|
+
if (this.compress) {
|
|
127
|
+
return (this.emit(header, position) +
|
|
128
|
+
this.emit('{') +
|
|
129
|
+
this.mapVisit(filteredRules) +
|
|
130
|
+
this.emit('}'));
|
|
131
|
+
}
|
|
132
|
+
return (this.emit(`${this.indent()}${header}`, position) +
|
|
133
|
+
this.emit(` {\n${this.indent(1)}`) +
|
|
134
|
+
this.mapVisit(filteredRules, '\n\n') +
|
|
135
|
+
this.emit(`\n${this.indent(-1)}${this.indent()}}`));
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Emit a block at-rule that contains declarations (e.g. @font-face, @property).
|
|
139
|
+
*/
|
|
140
|
+
declsBlock(header, declarations, position, rawPrelude) {
|
|
141
|
+
if (this.identity && rawPrelude) {
|
|
142
|
+
this.indent(1);
|
|
143
|
+
const result = this.emit(rawPrelude, position) +
|
|
144
|
+
this.emit('{') +
|
|
145
|
+
this.identityVisitBlock(declarations, 'decls') +
|
|
146
|
+
this.emit('}');
|
|
147
|
+
this.indent(-1);
|
|
148
|
+
return result;
|
|
149
|
+
}
|
|
150
|
+
const stripped = this.stripWhitespace(declarations);
|
|
151
|
+
if (this.compress) {
|
|
152
|
+
return (this.emit(header, position) +
|
|
153
|
+
this.emit('{') +
|
|
154
|
+
this.mapVisit(stripped) +
|
|
155
|
+
this.emit('}'));
|
|
156
|
+
}
|
|
157
|
+
return (this.emit(`${header} `, position) +
|
|
158
|
+
this.emit('{\n') +
|
|
159
|
+
this.emit(this.indent(1)) +
|
|
160
|
+
this.mapVisit(stripped, '\n') +
|
|
161
|
+
this.emit(this.indent(-1)) +
|
|
162
|
+
this.emit('\n}'));
|
|
163
|
+
}
|
|
164
|
+
compile(node) {
|
|
165
|
+
if (this.identity) {
|
|
166
|
+
return this.identityCompile(node);
|
|
167
|
+
}
|
|
168
|
+
if (this.compress) {
|
|
169
|
+
return this.filterEmptyRules(this.stripWhitespace(node.stylesheet.rules))
|
|
170
|
+
.map(this.visit, this)
|
|
171
|
+
.join('');
|
|
172
|
+
}
|
|
173
|
+
return this.stylesheet(node);
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Identity mode: walk the AST including whitespace nodes.
|
|
177
|
+
* Falls back to beautified output when whitespace nodes are not available.
|
|
178
|
+
*/
|
|
179
|
+
identityCompile(node) {
|
|
180
|
+
const rules = node.stylesheet.rules;
|
|
181
|
+
const hasWhitespace = rules.some((r) => r.type === CssTypes.whitespace);
|
|
182
|
+
if (!hasWhitespace) {
|
|
183
|
+
// Fallback to beautified when preserveFormatting was not used
|
|
184
|
+
return this.stylesheet(node);
|
|
185
|
+
}
|
|
186
|
+
return this.identityVisitBlock(rules, 'stylesheet');
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Visit stylesheet node.
|
|
190
|
+
*/
|
|
191
|
+
stylesheet(node) {
|
|
192
|
+
return this.mapVisit(this.filterEmptyRules(this.stripWhitespace(node.stylesheet.rules)), '\n\n');
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Strip whitespace nodes from an array (used in beautified/compressed modes).
|
|
196
|
+
*/
|
|
197
|
+
stripWhitespace(nodes) {
|
|
198
|
+
return nodes.filter((n) => n.type !== CssTypes.whitespace);
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Filter out empty rules when removeEmptyRules is enabled.
|
|
202
|
+
*/
|
|
203
|
+
filterEmptyRules(rules) {
|
|
204
|
+
if (!this.removeEmptyRules) {
|
|
205
|
+
return rules;
|
|
206
|
+
}
|
|
207
|
+
return rules.filter((rule) => {
|
|
208
|
+
if (rule.type === CssTypes.rule) {
|
|
209
|
+
const decls = rule.declarations.filter((d) => d.type !== CssTypes.whitespace);
|
|
210
|
+
return decls.length > 0;
|
|
211
|
+
}
|
|
212
|
+
return true;
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Check whether a node was newly created (not parsed from source).
|
|
217
|
+
* New nodes lack the raw formatting properties set by the parser.
|
|
218
|
+
*/
|
|
219
|
+
isNewNode(node) {
|
|
220
|
+
switch (node.type) {
|
|
221
|
+
case CssTypes.whitespace:
|
|
222
|
+
return false;
|
|
223
|
+
case CssTypes.comment:
|
|
224
|
+
return !node.position;
|
|
225
|
+
case CssTypes.declaration:
|
|
226
|
+
return node.rawBetween == null;
|
|
227
|
+
case CssTypes.rule:
|
|
228
|
+
return node.rawPrelude == null;
|
|
229
|
+
default:
|
|
230
|
+
if ('rawPrelude' in node)
|
|
231
|
+
return !node.rawPrelude;
|
|
232
|
+
if ('rawSource' in node)
|
|
233
|
+
return !node.rawSource;
|
|
234
|
+
return !node.position;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Visit block children in identity mode, formatting newly added nodes
|
|
239
|
+
* with beautified output while preserving original formatting for
|
|
240
|
+
* existing nodes.
|
|
241
|
+
*
|
|
242
|
+
* @param nodes - The child nodes to visit
|
|
243
|
+
* @param context - 'decls' for declaration blocks, 'rules' for nested
|
|
244
|
+
* rule blocks (e.g. @media), 'stylesheet' for top-level
|
|
245
|
+
*/
|
|
246
|
+
identityVisitBlock(nodes, context) {
|
|
247
|
+
const filtered = this.filterEmptyRules(nodes);
|
|
248
|
+
// Fast path: no new nodes – visit normally
|
|
249
|
+
if (!filtered.some((n) => this.isNewNode(n))) {
|
|
250
|
+
return this.mapVisit(filtered);
|
|
251
|
+
}
|
|
252
|
+
let buf = '';
|
|
253
|
+
const needsDoubleNewline = context === 'rules' || context === 'stylesheet';
|
|
254
|
+
for (let i = 0; i < filtered.length; i++) {
|
|
255
|
+
const node = filtered[i];
|
|
256
|
+
if (!this.isNewNode(node)) {
|
|
257
|
+
buf += this.visit(node);
|
|
258
|
+
continue;
|
|
259
|
+
}
|
|
260
|
+
// ── New node: add proper separator before it ──
|
|
261
|
+
// Check whether the buffer already ends with \n (possibly followed
|
|
262
|
+
// by spaces that were originally the closing-brace indent). If so,
|
|
263
|
+
// trim those trailing spaces – the beautified fallback of the new
|
|
264
|
+
// node will supply the correct indentation.
|
|
265
|
+
const lastNl = buf.lastIndexOf('\n');
|
|
266
|
+
const hasTrailingNewline = lastNl >= 0 && buf.slice(lastNl + 1).trim() === '';
|
|
267
|
+
if (hasTrailingNewline) {
|
|
268
|
+
buf = buf.slice(0, lastNl + 1);
|
|
269
|
+
}
|
|
270
|
+
else if (buf.length === 0 && context !== 'stylesheet') {
|
|
271
|
+
// First child in a block – add newline after opening brace
|
|
272
|
+
buf += '\n';
|
|
273
|
+
}
|
|
274
|
+
else if (buf.length > 0) {
|
|
275
|
+
buf += '\n';
|
|
276
|
+
}
|
|
277
|
+
if (needsDoubleNewline && buf.length > 1 && !buf.endsWith('\n\n')) {
|
|
278
|
+
buf += '\n';
|
|
279
|
+
}
|
|
280
|
+
// Visit the node (uses beautified fallback since raw props are absent)
|
|
281
|
+
const str = this.visit(node);
|
|
282
|
+
if (str)
|
|
283
|
+
buf += str;
|
|
284
|
+
}
|
|
285
|
+
// Add trailing newline + closing-brace indent when the last meaningful
|
|
286
|
+
// node is new (blocks only, not the top-level stylesheet)
|
|
287
|
+
if (context !== 'stylesheet') {
|
|
288
|
+
const lastMeaningful = [...filtered]
|
|
289
|
+
.reverse()
|
|
290
|
+
.find((n) => n.type !== CssTypes.whitespace);
|
|
291
|
+
if (lastMeaningful &&
|
|
292
|
+
this.isNewNode(lastMeaningful) &&
|
|
293
|
+
buf.length > 0 &&
|
|
294
|
+
!buf.endsWith('\n')) {
|
|
295
|
+
buf += '\n';
|
|
296
|
+
// Indent for the closing brace (one level less than current)
|
|
297
|
+
this.indent(-1);
|
|
298
|
+
buf += this.indent();
|
|
299
|
+
this.indent(1);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
return buf;
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Visit whitespace node.
|
|
306
|
+
*/
|
|
307
|
+
whitespace(node) {
|
|
308
|
+
if (this.identity) {
|
|
309
|
+
return this.emit(node.value);
|
|
310
|
+
}
|
|
311
|
+
// In beautified/compressed mode, whitespace nodes are stripped before visiting
|
|
312
|
+
return '';
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Visit comment node.
|
|
316
|
+
*/
|
|
317
|
+
comment(node) {
|
|
318
|
+
if (this.compress) {
|
|
319
|
+
return this.emit('', node.position);
|
|
320
|
+
}
|
|
321
|
+
const indent = this.identity && node.position ? '' : this.indent();
|
|
322
|
+
return this.emit(`${indent}/*${node.comment}*/`, node.position);
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Visit container node.
|
|
326
|
+
*/
|
|
327
|
+
container(node) {
|
|
328
|
+
return this.rulesBlock(`@container ${node.container}`, node.rules, node.position, node.rawPrelude);
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* Visit container node.
|
|
332
|
+
*/
|
|
333
|
+
layer(node) {
|
|
334
|
+
if (this.identity && node.rawPrelude && node.rules) {
|
|
335
|
+
this.indent(1);
|
|
336
|
+
const result = this.emit(node.rawPrelude, node.position) +
|
|
337
|
+
this.emit('{') +
|
|
338
|
+
this.identityVisitBlock(this.filterEmptyRules(node.rules), 'rules') +
|
|
339
|
+
this.emit('}');
|
|
340
|
+
this.indent(-1);
|
|
341
|
+
return result;
|
|
342
|
+
}
|
|
343
|
+
if (this.identity && !node.rules && node.rawSource) {
|
|
344
|
+
return this.emit(node.rawSource, node.position);
|
|
345
|
+
}
|
|
346
|
+
const rules = node.rules
|
|
347
|
+
? this.stripWhitespace(node.rules)
|
|
348
|
+
: undefined;
|
|
349
|
+
if (this.compress) {
|
|
350
|
+
return (this.emit(`@layer ${node.layer}`, node.position) +
|
|
351
|
+
(rules ? this.emit('{') + this.mapVisit(rules) + this.emit('}') : ';'));
|
|
352
|
+
}
|
|
353
|
+
return (this.emit(`${this.indent()}@layer ${node.layer}`, node.position) +
|
|
354
|
+
(rules
|
|
355
|
+
? this.emit(` {\n${this.indent(1)}`) +
|
|
356
|
+
this.mapVisit(rules, '\n\n') +
|
|
357
|
+
this.emit(`\n${this.indent(-1)}${this.indent()}}`)
|
|
358
|
+
: ';'));
|
|
359
|
+
}
|
|
360
|
+
/**
|
|
361
|
+
* Visit import node.
|
|
362
|
+
*/
|
|
363
|
+
import(node) {
|
|
364
|
+
if (this.identity && node.rawSource) {
|
|
365
|
+
return this.emit(node.rawSource, node.position);
|
|
366
|
+
}
|
|
367
|
+
return this.emit(`@import ${node.import};`, node.position);
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* Visit media node.
|
|
371
|
+
*/
|
|
372
|
+
media(node) {
|
|
373
|
+
return this.rulesBlock(`@media ${node.media}`, node.rules, node.position, node.rawPrelude);
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Visit document node.
|
|
377
|
+
*/
|
|
378
|
+
document(node) {
|
|
379
|
+
const doc = `@${node.vendor || ''}document ${node.document}`;
|
|
380
|
+
if (this.identity && node.rawPrelude) {
|
|
381
|
+
this.indent(1);
|
|
382
|
+
const result = this.emit(node.rawPrelude, node.position) +
|
|
383
|
+
this.emit('{') +
|
|
384
|
+
this.identityVisitBlock(this.filterEmptyRules(node.rules), 'rules') +
|
|
385
|
+
this.emit('}');
|
|
386
|
+
this.indent(-1);
|
|
387
|
+
return result;
|
|
388
|
+
}
|
|
389
|
+
const rules = this.stripWhitespace(node.rules);
|
|
390
|
+
if (this.compress) {
|
|
391
|
+
return (this.emit(doc, node.position) +
|
|
392
|
+
this.emit('{') +
|
|
393
|
+
this.mapVisit(rules) +
|
|
394
|
+
this.emit('}'));
|
|
395
|
+
}
|
|
396
|
+
return (this.emit(doc, node.position) +
|
|
397
|
+
this.emit(` {\n${this.indent(1)}`) +
|
|
398
|
+
this.mapVisit(rules, '\n\n') +
|
|
399
|
+
this.emit(`${this.indent(-1)}\n}`));
|
|
400
|
+
}
|
|
401
|
+
/**
|
|
402
|
+
* Visit charset node.
|
|
403
|
+
*/
|
|
404
|
+
charset(node) {
|
|
405
|
+
if (this.identity && node.rawSource) {
|
|
406
|
+
return this.emit(node.rawSource, node.position);
|
|
407
|
+
}
|
|
408
|
+
return this.emit(`@charset ${node.charset};`, node.position);
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* Visit namespace node.
|
|
412
|
+
*/
|
|
413
|
+
namespace(node) {
|
|
414
|
+
if (this.identity && node.rawSource) {
|
|
415
|
+
return this.emit(node.rawSource, node.position);
|
|
416
|
+
}
|
|
417
|
+
return this.emit(`@namespace ${node.namespace};`, node.position);
|
|
418
|
+
}
|
|
419
|
+
/**
|
|
420
|
+
* Visit starting-style node.
|
|
421
|
+
*/
|
|
422
|
+
startingStyle(node) {
|
|
423
|
+
return this.rulesBlock('@starting-style', node.rules, node.position, node.rawPrelude);
|
|
424
|
+
}
|
|
425
|
+
/**
|
|
426
|
+
* Visit supports node.
|
|
427
|
+
*/
|
|
428
|
+
supports(node) {
|
|
429
|
+
return this.rulesBlock(`@supports ${node.supports}`, node.rules, node.position, node.rawPrelude);
|
|
430
|
+
}
|
|
431
|
+
/**
|
|
432
|
+
* Visit keyframes node.
|
|
433
|
+
*/
|
|
434
|
+
keyframes(node) {
|
|
435
|
+
if (this.identity && node.rawPrelude) {
|
|
436
|
+
this.indent(1);
|
|
437
|
+
const result = this.emit(node.rawPrelude, node.position) +
|
|
438
|
+
this.emit('{') +
|
|
439
|
+
this.identityVisitBlock(node.keyframes, 'rules') +
|
|
440
|
+
this.emit('}');
|
|
441
|
+
this.indent(-1);
|
|
442
|
+
return result;
|
|
443
|
+
}
|
|
444
|
+
const frames = this.stripWhitespace(node.keyframes);
|
|
445
|
+
if (this.compress) {
|
|
446
|
+
return (this.emit(`@${node.vendor || ''}keyframes ${node.name}`, node.position) +
|
|
447
|
+
this.emit('{') +
|
|
448
|
+
this.mapVisit(frames) +
|
|
449
|
+
this.emit('}'));
|
|
450
|
+
}
|
|
451
|
+
return (this.emit(`@${node.vendor || ''}keyframes ${node.name}`, node.position) +
|
|
452
|
+
this.emit(` {\n${this.indent(1)}`) +
|
|
453
|
+
this.mapVisit(frames, '\n') +
|
|
454
|
+
this.emit(`${this.indent(-1)}}`));
|
|
455
|
+
}
|
|
456
|
+
/**
|
|
457
|
+
* Visit keyframe node.
|
|
458
|
+
*/
|
|
459
|
+
keyframe(node) {
|
|
460
|
+
const decls = node.declarations;
|
|
461
|
+
if (this.identity && node.rawPrelude) {
|
|
462
|
+
this.indent(1);
|
|
463
|
+
const result = this.emit(node.rawPrelude, node.position) +
|
|
464
|
+
this.emit('{') +
|
|
465
|
+
this.identityVisitBlock(decls, 'decls') +
|
|
466
|
+
this.emit('}');
|
|
467
|
+
this.indent(-1);
|
|
468
|
+
return result;
|
|
469
|
+
}
|
|
470
|
+
const stripped = this.stripWhitespace(decls);
|
|
471
|
+
if (this.compress) {
|
|
472
|
+
return (this.emit(node.values.join(','), node.position) +
|
|
473
|
+
this.emit('{') +
|
|
474
|
+
this.mapVisit(stripped) +
|
|
475
|
+
this.emit('}'));
|
|
476
|
+
}
|
|
477
|
+
return (this.emit(this.indent()) +
|
|
478
|
+
this.emit(node.values.join(', '), node.position) +
|
|
479
|
+
this.emit(` {\n${this.indent(1)}`) +
|
|
480
|
+
this.mapVisit(stripped, '\n') +
|
|
481
|
+
this.emit(`${this.indent(-1)}\n${this.indent()}}\n`));
|
|
482
|
+
}
|
|
483
|
+
/**
|
|
484
|
+
* Visit page node.
|
|
485
|
+
*/
|
|
486
|
+
page(node) {
|
|
487
|
+
if (this.identity && node.rawPrelude) {
|
|
488
|
+
this.indent(1);
|
|
489
|
+
const result = this.emit(node.rawPrelude, node.position) +
|
|
490
|
+
this.emit('{') +
|
|
491
|
+
this.identityVisitBlock(node.declarations, 'decls') +
|
|
492
|
+
this.emit('}');
|
|
493
|
+
this.indent(-1);
|
|
494
|
+
return result;
|
|
495
|
+
}
|
|
496
|
+
const decls = this.stripWhitespace(node.declarations);
|
|
497
|
+
if (this.compress) {
|
|
498
|
+
const sel = node.selectors.length ? node.selectors.join(', ') : '';
|
|
499
|
+
return (this.emit(`@page ${sel}`, node.position) +
|
|
500
|
+
this.emit('{') +
|
|
501
|
+
this.mapVisit(decls) +
|
|
502
|
+
this.emit('}'));
|
|
503
|
+
}
|
|
504
|
+
const sel = node.selectors.length ? `${node.selectors.join(', ')} ` : '';
|
|
505
|
+
return (this.emit(`@page ${sel}`, node.position) +
|
|
506
|
+
this.emit('{\n') +
|
|
507
|
+
this.emit(this.indent(1)) +
|
|
508
|
+
this.mapVisit(decls, '\n') +
|
|
509
|
+
this.emit(this.indent(-1)) +
|
|
510
|
+
this.emit('\n}'));
|
|
511
|
+
}
|
|
512
|
+
/**
|
|
513
|
+
* Visit @page margin box node (@top-left, @bottom-right, etc.).
|
|
514
|
+
*/
|
|
515
|
+
pageMarginBox(node) {
|
|
516
|
+
if (this.identity && node.rawPrelude) {
|
|
517
|
+
this.indent(1);
|
|
518
|
+
const result = this.emit(node.rawPrelude, node.position) +
|
|
519
|
+
this.emit('{') +
|
|
520
|
+
this.identityVisitBlock(node.declarations, 'decls') +
|
|
521
|
+
this.emit('}');
|
|
522
|
+
this.indent(-1);
|
|
523
|
+
return result;
|
|
524
|
+
}
|
|
525
|
+
const decls = this.stripWhitespace(node.declarations);
|
|
526
|
+
if (this.compress) {
|
|
527
|
+
return (this.emit(`@${node.name}`, node.position) +
|
|
528
|
+
this.emit('{') +
|
|
529
|
+
this.mapVisit(decls) +
|
|
530
|
+
this.emit('}'));
|
|
531
|
+
}
|
|
532
|
+
return (this.emit(`${this.indent()}@${node.name} `, node.position) +
|
|
533
|
+
this.emit('{\n') +
|
|
534
|
+
this.emit(this.indent(1)) +
|
|
535
|
+
this.mapVisit(decls, '\n') +
|
|
536
|
+
this.emit(this.indent(-1)) +
|
|
537
|
+
this.emit(`\n${this.indent()}}`));
|
|
538
|
+
}
|
|
539
|
+
/**
|
|
540
|
+
* Visit font-face node.
|
|
541
|
+
*/
|
|
542
|
+
fontFace(node) {
|
|
543
|
+
return this.declsBlock('@font-face', node.declarations, node.position, node.rawPrelude);
|
|
544
|
+
}
|
|
545
|
+
/**
|
|
546
|
+
* Visit host node.
|
|
547
|
+
*/
|
|
548
|
+
host(node) {
|
|
549
|
+
if (this.identity && node.rawPrelude) {
|
|
550
|
+
this.indent(1);
|
|
551
|
+
const result = this.emit(node.rawPrelude, node.position) +
|
|
552
|
+
this.emit('{') +
|
|
553
|
+
this.identityVisitBlock(this.filterEmptyRules(node.rules), 'rules') +
|
|
554
|
+
this.emit('}');
|
|
555
|
+
this.indent(-1);
|
|
556
|
+
return result;
|
|
557
|
+
}
|
|
558
|
+
const rules = this.stripWhitespace(node.rules);
|
|
559
|
+
if (this.compress) {
|
|
560
|
+
return (this.emit('@host', node.position) +
|
|
561
|
+
this.emit('{') +
|
|
562
|
+
this.mapVisit(rules) +
|
|
563
|
+
this.emit('}'));
|
|
564
|
+
}
|
|
565
|
+
return (this.emit('@host', node.position) +
|
|
566
|
+
this.emit(` {\n${this.indent(1)}`) +
|
|
567
|
+
this.mapVisit(rules, '\n\n') +
|
|
568
|
+
this.emit(`${this.indent(-1)}\n}`));
|
|
569
|
+
}
|
|
570
|
+
/**
|
|
571
|
+
* Visit custom-media node.
|
|
572
|
+
*/
|
|
573
|
+
customMedia(node) {
|
|
574
|
+
if (this.identity && node.rawSource) {
|
|
575
|
+
return this.emit(node.rawSource, node.position);
|
|
576
|
+
}
|
|
577
|
+
return this.emit(`@custom-media ${node.name} ${node.media};`, node.position);
|
|
578
|
+
}
|
|
579
|
+
/**
|
|
580
|
+
* Visit @property node.
|
|
581
|
+
*/
|
|
582
|
+
property(node) {
|
|
583
|
+
return this.declsBlock(`@property ${node.name}`, node.declarations, node.position, node.rawPrelude);
|
|
584
|
+
}
|
|
585
|
+
/**
|
|
586
|
+
* Visit @counter-style node.
|
|
587
|
+
*/
|
|
588
|
+
counterStyle(node) {
|
|
589
|
+
return this.declsBlock(`@counter-style ${node.name}`, node.declarations, node.position, node.rawPrelude);
|
|
590
|
+
}
|
|
591
|
+
/**
|
|
592
|
+
* Visit @font-feature-values node.
|
|
593
|
+
*/
|
|
594
|
+
fontFeatureValues(node) {
|
|
595
|
+
return this.rulesBlock(`@font-feature-values ${node.fontFamily}`, node.rules, node.position, node.rawPrelude);
|
|
596
|
+
}
|
|
597
|
+
/**
|
|
598
|
+
* Visit @scope node.
|
|
599
|
+
*/
|
|
600
|
+
scope(node) {
|
|
601
|
+
if (this.identity && node.rawPrelude) {
|
|
602
|
+
this.indent(1);
|
|
603
|
+
const result = this.emit(node.rawPrelude, node.position) +
|
|
604
|
+
this.emit('{') +
|
|
605
|
+
this.identityVisitBlock(this.filterEmptyRules(node.rules), 'rules') +
|
|
606
|
+
this.emit('}');
|
|
607
|
+
this.indent(-1);
|
|
608
|
+
return result;
|
|
609
|
+
}
|
|
610
|
+
const prelude = node.scope ? ` ${node.scope}` : '';
|
|
611
|
+
return this.rulesBlock(`@scope${prelude}`, this.stripWhitespace(node.rules), node.position);
|
|
612
|
+
}
|
|
613
|
+
/**
|
|
614
|
+
* Visit @view-transition node.
|
|
615
|
+
*/
|
|
616
|
+
viewTransition(node) {
|
|
617
|
+
return this.declsBlock('@view-transition', node.declarations, node.position, node.rawPrelude);
|
|
618
|
+
}
|
|
619
|
+
/**
|
|
620
|
+
* Visit @position-try node.
|
|
621
|
+
*/
|
|
622
|
+
positionTry(node) {
|
|
623
|
+
return this.declsBlock(`@position-try ${node.name}`, node.declarations, node.position, node.rawPrelude);
|
|
624
|
+
}
|
|
625
|
+
/**
|
|
626
|
+
* Visit generic at-rule node (fallback for any unrecognized at-rule).
|
|
627
|
+
*/
|
|
628
|
+
genericAtRule(node) {
|
|
629
|
+
if (this.identity && node.rawPrelude && node.rules) {
|
|
630
|
+
this.indent(1);
|
|
631
|
+
const result = this.emit(node.rawPrelude, node.position) +
|
|
632
|
+
this.emit('{') +
|
|
633
|
+
this.identityVisitBlock(this.filterEmptyRules(node.rules), 'rules') +
|
|
634
|
+
this.emit('}');
|
|
635
|
+
this.indent(-1);
|
|
636
|
+
return result;
|
|
637
|
+
}
|
|
638
|
+
const prelude = node.prelude ? ` ${node.prelude}` : '';
|
|
639
|
+
const rules = node.rules
|
|
640
|
+
? this.stripWhitespace(node.rules)
|
|
641
|
+
: undefined;
|
|
642
|
+
if (this.compress) {
|
|
643
|
+
return (this.emit(`@${node.name}${prelude}`, node.position) +
|
|
644
|
+
(rules ? this.emit('{') + this.mapVisit(rules) + this.emit('}') : ';'));
|
|
645
|
+
}
|
|
646
|
+
if (!rules) {
|
|
647
|
+
return this.emit(`${this.indent()}@${node.name}${prelude};`, node.position);
|
|
648
|
+
}
|
|
649
|
+
const hasNestedRules = rules.some((r) => r.type !== CssTypes.declaration && r.type !== CssTypes.comment);
|
|
650
|
+
const delim = hasNestedRules ? '\n\n' : '\n';
|
|
651
|
+
return (this.emit(`${this.indent()}@${node.name}${prelude}`, node.position) +
|
|
652
|
+
this.emit(hasNestedRules ? ` {\n${this.indent(1)}` : ' {\n') +
|
|
653
|
+
this.emit(hasNestedRules ? '' : this.indent(1)) +
|
|
654
|
+
this.mapVisit(rules, delim) +
|
|
655
|
+
this.emit(hasNestedRules
|
|
656
|
+
? `\n${this.indent(-1)}${this.indent()}}`
|
|
657
|
+
: `${this.indent(-1)}\n${this.indent()}}`));
|
|
658
|
+
}
|
|
659
|
+
/**
|
|
660
|
+
* Visit rule node.
|
|
661
|
+
*/
|
|
662
|
+
rule(node) {
|
|
663
|
+
const decls = node.declarations;
|
|
664
|
+
if (this.identity && node.rawPrelude) {
|
|
665
|
+
this.indent(1);
|
|
666
|
+
const result = this.emit(node.rawPrelude, node.position) +
|
|
667
|
+
this.emit('{') +
|
|
668
|
+
this.identityVisitBlock(decls, 'decls') +
|
|
669
|
+
this.emit('}');
|
|
670
|
+
this.indent(-1);
|
|
671
|
+
return result;
|
|
672
|
+
}
|
|
673
|
+
const stripped = this.stripWhitespace(decls);
|
|
674
|
+
if (this.compress) {
|
|
675
|
+
if (this.removeEmptyRules && !stripped.length) {
|
|
676
|
+
return '';
|
|
677
|
+
}
|
|
678
|
+
return (this.emit(node.selectors.join(','), node.position) +
|
|
679
|
+
this.emit('{') +
|
|
680
|
+
this.mapVisit(stripped) +
|
|
681
|
+
this.emit('}'));
|
|
682
|
+
}
|
|
683
|
+
const indent = this.indent();
|
|
684
|
+
if (!stripped.length) {
|
|
685
|
+
if (this.removeEmptyRules) {
|
|
686
|
+
return '';
|
|
687
|
+
}
|
|
688
|
+
return (this.emit(node.selectors
|
|
689
|
+
.map((s) => {
|
|
690
|
+
return indent + s;
|
|
691
|
+
})
|
|
692
|
+
.join(',\n'), node.position) + this.emit(' {}'));
|
|
693
|
+
}
|
|
694
|
+
return (this.emit(node.selectors
|
|
695
|
+
.map((s) => {
|
|
696
|
+
return indent + s;
|
|
697
|
+
})
|
|
698
|
+
.join(',\n'), node.position) +
|
|
699
|
+
this.emit(' {\n') +
|
|
700
|
+
this.emit(this.indent(1)) +
|
|
701
|
+
this.mapVisit(stripped, '\n') +
|
|
702
|
+
this.emit(this.indent(-1)) +
|
|
703
|
+
this.emit(`\n${this.indent()}}`));
|
|
704
|
+
}
|
|
705
|
+
/**
|
|
706
|
+
* Visit declaration node.
|
|
707
|
+
*/
|
|
708
|
+
declaration(node) {
|
|
709
|
+
if (this.identity && node.rawBetween != null) {
|
|
710
|
+
return this.emit(`${node.property}${node.rawBetween}${node.rawValue ?? node.value}`, node.position);
|
|
711
|
+
}
|
|
712
|
+
if (this.compress) {
|
|
713
|
+
return (this.emit(`${node.property}:${node.value}`, node.position) +
|
|
714
|
+
this.emit(';'));
|
|
715
|
+
}
|
|
716
|
+
if (node.property === 'grid-template-areas') {
|
|
717
|
+
const indent = this.indent();
|
|
718
|
+
const pad = indent.length + node.property.length + 2; // 2 for ": "
|
|
719
|
+
const parts = node.value.split('\n');
|
|
720
|
+
const aligned = parts
|
|
721
|
+
.map((p, i) => (i === 0 ? p : ' '.repeat(pad) + p.trimStart()))
|
|
722
|
+
.join('\n');
|
|
723
|
+
return (this.emit(indent) +
|
|
724
|
+
this.emit(`${node.property}: ${aligned}`, node.position) +
|
|
725
|
+
this.emit(';'));
|
|
726
|
+
}
|
|
727
|
+
return (this.emit(this.indent()) +
|
|
728
|
+
this.emit(`${node.property}: ${node.value}`, node.position) +
|
|
729
|
+
this.emit(';'));
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
export default Compiler;
|