@tbela99/css-parser 0.0.1-alpha5 → 0.0.1-rc2
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/.gitattributes +1 -0
- package/README.md +20 -8
- package/dist/config.json.js +95 -4
- package/dist/index-umd-web.js +1639 -1400
- package/dist/index.cjs +1639 -1400
- package/dist/index.d.ts +327 -10
- package/dist/index.js +6 -2
- package/dist/lib/{parser/deduplicate.js → ast/minify.js} +413 -418
- package/dist/lib/parser/declaration/list.js +38 -9
- package/dist/lib/parser/declaration/map.js +203 -145
- package/dist/lib/parser/declaration/set.js +26 -34
- package/dist/lib/parser/parse.js +242 -685
- package/dist/lib/parser/tokenize.js +454 -0
- package/dist/lib/parser/utils/eq.js +29 -5
- package/dist/lib/parser/utils/syntax.js +25 -11
- package/dist/lib/renderer/render.js +19 -11
- package/dist/lib/transform.js +12 -14
- package/dist/node/index.js +1 -0
- package/dist/web/index.js +6 -2
- package/package.json +12 -5
- /package/dist/lib/{walker → ast}/walk.js +0 -0
|
@@ -0,0 +1,454 @@
|
|
|
1
|
+
import { isWhiteSpace, isDigit, isNewLine } from './utils/syntax.js';
|
|
2
|
+
|
|
3
|
+
function* tokenize(iterator) {
|
|
4
|
+
let ind = -1;
|
|
5
|
+
let lin = 1;
|
|
6
|
+
let col = 0;
|
|
7
|
+
const position = {
|
|
8
|
+
ind: Math.max(ind, 0),
|
|
9
|
+
lin: lin,
|
|
10
|
+
col: Math.max(col, 1)
|
|
11
|
+
};
|
|
12
|
+
let value;
|
|
13
|
+
let buffer = '';
|
|
14
|
+
function consumeWhiteSpace() {
|
|
15
|
+
let count = 0;
|
|
16
|
+
while (isWhiteSpace(iterator.charAt(count + ind + 1).charCodeAt(0))) {
|
|
17
|
+
count++;
|
|
18
|
+
}
|
|
19
|
+
next(count);
|
|
20
|
+
return count;
|
|
21
|
+
}
|
|
22
|
+
function pushToken(token, hint) {
|
|
23
|
+
const result = { token, hint, position: { ...position }, bytesIn: ind };
|
|
24
|
+
position.ind = ind;
|
|
25
|
+
position.lin = lin;
|
|
26
|
+
position.col = col == 0 ? 1 : col;
|
|
27
|
+
return result;
|
|
28
|
+
}
|
|
29
|
+
function* consumeString(quoteStr) {
|
|
30
|
+
const quote = quoteStr;
|
|
31
|
+
let value;
|
|
32
|
+
let hasNewLine = false;
|
|
33
|
+
if (buffer.length > 0) {
|
|
34
|
+
yield pushToken(buffer);
|
|
35
|
+
buffer = '';
|
|
36
|
+
}
|
|
37
|
+
buffer += quoteStr;
|
|
38
|
+
while (value = peek()) {
|
|
39
|
+
// if (ind >= iterator.length) {
|
|
40
|
+
//
|
|
41
|
+
// yield pushToken(buffer, hasNewLine ? 'Bad-string' : 'Unclosed-string');
|
|
42
|
+
// break;
|
|
43
|
+
// }
|
|
44
|
+
if (value == '\\') {
|
|
45
|
+
const sequence = peek(6);
|
|
46
|
+
let escapeSequence = '';
|
|
47
|
+
let codepoint;
|
|
48
|
+
let i;
|
|
49
|
+
for (i = 1; i < sequence.length; i++) {
|
|
50
|
+
codepoint = sequence.charCodeAt(i);
|
|
51
|
+
if (codepoint == 0x20 ||
|
|
52
|
+
(codepoint >= 0x61 && codepoint <= 0x66) ||
|
|
53
|
+
(codepoint >= 0x41 && codepoint <= 0x46) ||
|
|
54
|
+
(codepoint >= 0x30 && codepoint <= 0x39)) {
|
|
55
|
+
escapeSequence += sequence[i];
|
|
56
|
+
if (codepoint == 0x20) {
|
|
57
|
+
break;
|
|
58
|
+
}
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
// not hex or new line
|
|
64
|
+
// @ts-ignore
|
|
65
|
+
if (i == 1 && !isNewLine(codepoint)) {
|
|
66
|
+
buffer += value + sequence[i];
|
|
67
|
+
next(2);
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
if (escapeSequence.trimEnd().length > 0) {
|
|
71
|
+
const codepoint = Number(`0x${escapeSequence.trimEnd()}`);
|
|
72
|
+
if (codepoint == 0 ||
|
|
73
|
+
// leading surrogate
|
|
74
|
+
(0xD800 <= codepoint && codepoint <= 0xDBFF) ||
|
|
75
|
+
// trailing surrogate
|
|
76
|
+
(0xDC00 <= codepoint && codepoint <= 0xDFFF)) {
|
|
77
|
+
buffer += String.fromCodePoint(0xFFFD);
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
buffer += String.fromCodePoint(codepoint);
|
|
81
|
+
}
|
|
82
|
+
next(escapeSequence.length + 1);
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
// buffer += value;
|
|
86
|
+
// if (ind >= iterator.length) {
|
|
87
|
+
//
|
|
88
|
+
// // drop '\\' at the end
|
|
89
|
+
// yield pushToken(buffer);
|
|
90
|
+
// break;
|
|
91
|
+
// }
|
|
92
|
+
buffer += next(2);
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
if (value == quote) {
|
|
96
|
+
buffer += value;
|
|
97
|
+
yield pushToken(buffer, hasNewLine ? 'Bad-string' : 'String');
|
|
98
|
+
next();
|
|
99
|
+
// i += value.length;
|
|
100
|
+
buffer = '';
|
|
101
|
+
break;
|
|
102
|
+
}
|
|
103
|
+
if (isNewLine(value.charCodeAt(0))) {
|
|
104
|
+
hasNewLine = true;
|
|
105
|
+
}
|
|
106
|
+
if (hasNewLine && value == ';') {
|
|
107
|
+
yield pushToken(buffer, 'Bad-string');
|
|
108
|
+
buffer = '';
|
|
109
|
+
break;
|
|
110
|
+
}
|
|
111
|
+
buffer += value;
|
|
112
|
+
// i += value.length;
|
|
113
|
+
next();
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
function peek(count = 1) {
|
|
117
|
+
if (count == 1) {
|
|
118
|
+
return iterator.charAt(ind + 1);
|
|
119
|
+
}
|
|
120
|
+
return iterator.slice(ind + 1, ind + count + 1);
|
|
121
|
+
}
|
|
122
|
+
function prev(count = 1) {
|
|
123
|
+
if (count == 1) {
|
|
124
|
+
return ind == 0 ? '' : iterator.charAt(ind - 1);
|
|
125
|
+
}
|
|
126
|
+
return iterator.slice(ind - 1 - count, ind - 1);
|
|
127
|
+
}
|
|
128
|
+
function next(count = 1) {
|
|
129
|
+
let char = '';
|
|
130
|
+
while (count-- > 0 && ind < iterator.length) {
|
|
131
|
+
const codepoint = iterator.charCodeAt(++ind);
|
|
132
|
+
if (isNaN(codepoint)) {
|
|
133
|
+
return char;
|
|
134
|
+
}
|
|
135
|
+
char += iterator.charAt(ind);
|
|
136
|
+
if (isNewLine(codepoint)) {
|
|
137
|
+
lin++;
|
|
138
|
+
col = 0;
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
col++;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return char;
|
|
145
|
+
}
|
|
146
|
+
while (value = next()) {
|
|
147
|
+
if (ind >= iterator.length) {
|
|
148
|
+
if (buffer.length > 0) {
|
|
149
|
+
yield pushToken(buffer);
|
|
150
|
+
buffer = '';
|
|
151
|
+
}
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
154
|
+
if (isWhiteSpace(value.charCodeAt(0))) {
|
|
155
|
+
if (buffer.length > 0) {
|
|
156
|
+
yield pushToken(buffer);
|
|
157
|
+
buffer = '';
|
|
158
|
+
}
|
|
159
|
+
while (value = next()) {
|
|
160
|
+
if (ind >= iterator.length) {
|
|
161
|
+
break;
|
|
162
|
+
}
|
|
163
|
+
if (!isWhiteSpace(value.charCodeAt(0))) {
|
|
164
|
+
break;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
yield pushToken('', 'Whitespace');
|
|
168
|
+
buffer = '';
|
|
169
|
+
if (ind >= iterator.length) {
|
|
170
|
+
break;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
switch (value) {
|
|
174
|
+
case '/':
|
|
175
|
+
if (buffer.length > 0) {
|
|
176
|
+
yield pushToken(buffer);
|
|
177
|
+
buffer = '';
|
|
178
|
+
if (peek() != '*') {
|
|
179
|
+
yield pushToken(value);
|
|
180
|
+
break;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
buffer += value;
|
|
184
|
+
if (peek() == '*') {
|
|
185
|
+
buffer += '*';
|
|
186
|
+
// i++;
|
|
187
|
+
next();
|
|
188
|
+
while (value = next()) {
|
|
189
|
+
if (ind >= iterator.length) {
|
|
190
|
+
yield pushToken(buffer, 'Bad-comment');
|
|
191
|
+
break;
|
|
192
|
+
}
|
|
193
|
+
if (value == '\\') {
|
|
194
|
+
buffer += value;
|
|
195
|
+
value = next();
|
|
196
|
+
if (ind >= iterator.length) {
|
|
197
|
+
yield pushToken(buffer, 'Bad-comment');
|
|
198
|
+
break;
|
|
199
|
+
}
|
|
200
|
+
buffer += value;
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
203
|
+
if (value == '*') {
|
|
204
|
+
buffer += value;
|
|
205
|
+
value = next();
|
|
206
|
+
if (ind >= iterator.length) {
|
|
207
|
+
yield pushToken(buffer, 'Bad-comment');
|
|
208
|
+
break;
|
|
209
|
+
}
|
|
210
|
+
buffer += value;
|
|
211
|
+
if (value == '/') {
|
|
212
|
+
yield pushToken(buffer, 'Comment');
|
|
213
|
+
buffer = '';
|
|
214
|
+
break;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
buffer += value;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
break;
|
|
223
|
+
case '<':
|
|
224
|
+
if (buffer.length > 0) {
|
|
225
|
+
yield pushToken(buffer);
|
|
226
|
+
buffer = '';
|
|
227
|
+
}
|
|
228
|
+
buffer += value;
|
|
229
|
+
value = next();
|
|
230
|
+
if (ind >= iterator.length) {
|
|
231
|
+
break;
|
|
232
|
+
}
|
|
233
|
+
if (peek(3) == '!--') {
|
|
234
|
+
while (value = next()) {
|
|
235
|
+
if (ind >= iterator.length) {
|
|
236
|
+
break;
|
|
237
|
+
}
|
|
238
|
+
buffer += value;
|
|
239
|
+
if (value == '>' && prev(2) == '--') {
|
|
240
|
+
yield pushToken(buffer, 'CDOCOMM');
|
|
241
|
+
buffer = '';
|
|
242
|
+
break;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
if (ind >= iterator.length) {
|
|
247
|
+
yield pushToken(buffer, 'BADCDO');
|
|
248
|
+
buffer = '';
|
|
249
|
+
}
|
|
250
|
+
break;
|
|
251
|
+
case '\\':
|
|
252
|
+
value = next();
|
|
253
|
+
// EOF
|
|
254
|
+
if (ind + 1 >= iterator.length) {
|
|
255
|
+
// end of stream ignore \\
|
|
256
|
+
yield pushToken(buffer);
|
|
257
|
+
buffer = '';
|
|
258
|
+
break;
|
|
259
|
+
}
|
|
260
|
+
buffer += prev() + value;
|
|
261
|
+
break;
|
|
262
|
+
case '"':
|
|
263
|
+
case "'":
|
|
264
|
+
yield* consumeString(value);
|
|
265
|
+
break;
|
|
266
|
+
case '~':
|
|
267
|
+
case '|':
|
|
268
|
+
if (buffer.length > 0) {
|
|
269
|
+
yield pushToken(buffer);
|
|
270
|
+
buffer = '';
|
|
271
|
+
}
|
|
272
|
+
buffer += value;
|
|
273
|
+
value = next();
|
|
274
|
+
if (ind >= iterator.length) {
|
|
275
|
+
yield pushToken(buffer);
|
|
276
|
+
buffer = '';
|
|
277
|
+
break;
|
|
278
|
+
}
|
|
279
|
+
if (value == '=') {
|
|
280
|
+
buffer += value;
|
|
281
|
+
yield pushToken(buffer, buffer[0] == '~' ? 'Includes' : 'Dash-matches');
|
|
282
|
+
buffer = '';
|
|
283
|
+
break;
|
|
284
|
+
}
|
|
285
|
+
yield pushToken(buffer);
|
|
286
|
+
while (isWhiteSpace(value.charCodeAt(0))) {
|
|
287
|
+
value = next();
|
|
288
|
+
}
|
|
289
|
+
buffer = value;
|
|
290
|
+
break;
|
|
291
|
+
case '>':
|
|
292
|
+
if (buffer !== '') {
|
|
293
|
+
yield pushToken(buffer);
|
|
294
|
+
buffer = '';
|
|
295
|
+
}
|
|
296
|
+
yield pushToken('', 'Gt');
|
|
297
|
+
consumeWhiteSpace();
|
|
298
|
+
break;
|
|
299
|
+
case '.':
|
|
300
|
+
const codepoint = peek().charCodeAt(0);
|
|
301
|
+
if (!isDigit(codepoint) && buffer !== '') {
|
|
302
|
+
yield pushToken(buffer);
|
|
303
|
+
buffer = value;
|
|
304
|
+
break;
|
|
305
|
+
}
|
|
306
|
+
buffer += value;
|
|
307
|
+
break;
|
|
308
|
+
case '+':
|
|
309
|
+
case ':':
|
|
310
|
+
case ',':
|
|
311
|
+
case '=':
|
|
312
|
+
if (buffer.length > 0) {
|
|
313
|
+
yield pushToken(buffer);
|
|
314
|
+
buffer = '';
|
|
315
|
+
}
|
|
316
|
+
if (value == ':' && ':' == peek()) {
|
|
317
|
+
buffer += value + next();
|
|
318
|
+
break;
|
|
319
|
+
}
|
|
320
|
+
yield pushToken(value);
|
|
321
|
+
buffer = '';
|
|
322
|
+
if (value == '+' && isWhiteSpace(peek().charCodeAt(0))) {
|
|
323
|
+
yield pushToken(next());
|
|
324
|
+
}
|
|
325
|
+
while (isWhiteSpace(peek().charCodeAt(0))) {
|
|
326
|
+
next();
|
|
327
|
+
}
|
|
328
|
+
break;
|
|
329
|
+
case ')':
|
|
330
|
+
if (buffer.length > 0) {
|
|
331
|
+
yield pushToken(buffer);
|
|
332
|
+
buffer = '';
|
|
333
|
+
}
|
|
334
|
+
yield pushToken('', 'End-parens');
|
|
335
|
+
break;
|
|
336
|
+
case '(':
|
|
337
|
+
if (buffer.length == 0) {
|
|
338
|
+
yield pushToken('', 'Start-parens');
|
|
339
|
+
break;
|
|
340
|
+
}
|
|
341
|
+
buffer += value;
|
|
342
|
+
// @ts-ignore
|
|
343
|
+
if (buffer == 'url(') {
|
|
344
|
+
yield pushToken(buffer);
|
|
345
|
+
buffer = '';
|
|
346
|
+
// consume either string or url token
|
|
347
|
+
let whitespace = '';
|
|
348
|
+
value = peek();
|
|
349
|
+
while (isWhiteSpace(value.charCodeAt(0))) {
|
|
350
|
+
whitespace += value;
|
|
351
|
+
}
|
|
352
|
+
if (whitespace.length > 0) {
|
|
353
|
+
next(whitespace.length);
|
|
354
|
+
}
|
|
355
|
+
value = peek();
|
|
356
|
+
if (value == '"' || value == "'") {
|
|
357
|
+
yield* consumeString(next());
|
|
358
|
+
break;
|
|
359
|
+
}
|
|
360
|
+
else {
|
|
361
|
+
buffer = '';
|
|
362
|
+
do {
|
|
363
|
+
let cp = value.charCodeAt(0);
|
|
364
|
+
// EOF -
|
|
365
|
+
if (cp == null) {
|
|
366
|
+
yield pushToken('', 'Bad-url-token');
|
|
367
|
+
break;
|
|
368
|
+
}
|
|
369
|
+
// ')'
|
|
370
|
+
if (cp == 0x29 || cp == null) {
|
|
371
|
+
if (buffer.length == 0) {
|
|
372
|
+
yield pushToken(buffer, 'Bad-url-token');
|
|
373
|
+
}
|
|
374
|
+
else {
|
|
375
|
+
yield pushToken(buffer, 'Url-token');
|
|
376
|
+
}
|
|
377
|
+
if (cp != null) {
|
|
378
|
+
yield pushToken(next());
|
|
379
|
+
}
|
|
380
|
+
break;
|
|
381
|
+
}
|
|
382
|
+
if (isWhiteSpace(cp)) {
|
|
383
|
+
whitespace = next();
|
|
384
|
+
while (true) {
|
|
385
|
+
value = peek();
|
|
386
|
+
cp = value.charCodeAt(0);
|
|
387
|
+
if (isWhiteSpace(cp)) {
|
|
388
|
+
whitespace += value;
|
|
389
|
+
continue;
|
|
390
|
+
}
|
|
391
|
+
break;
|
|
392
|
+
}
|
|
393
|
+
if (cp == null || cp == 0x29) {
|
|
394
|
+
continue;
|
|
395
|
+
}
|
|
396
|
+
// bad url token
|
|
397
|
+
buffer += next(whitespace.length);
|
|
398
|
+
do {
|
|
399
|
+
value = peek();
|
|
400
|
+
cp = value.charCodeAt(0);
|
|
401
|
+
if (cp == null || cp == 0x29) {
|
|
402
|
+
break;
|
|
403
|
+
}
|
|
404
|
+
buffer += next();
|
|
405
|
+
} while (true);
|
|
406
|
+
yield pushToken(buffer, 'Bad-url-token');
|
|
407
|
+
continue;
|
|
408
|
+
}
|
|
409
|
+
buffer += next();
|
|
410
|
+
value = peek();
|
|
411
|
+
} while (true);
|
|
412
|
+
buffer = '';
|
|
413
|
+
}
|
|
414
|
+
break;
|
|
415
|
+
}
|
|
416
|
+
yield pushToken(buffer);
|
|
417
|
+
buffer = '';
|
|
418
|
+
break;
|
|
419
|
+
case '[':
|
|
420
|
+
case ']':
|
|
421
|
+
case '{':
|
|
422
|
+
case '}':
|
|
423
|
+
case ';':
|
|
424
|
+
if (buffer.length > 0) {
|
|
425
|
+
yield pushToken(buffer);
|
|
426
|
+
buffer = '';
|
|
427
|
+
}
|
|
428
|
+
yield pushToken(value);
|
|
429
|
+
break;
|
|
430
|
+
case '!':
|
|
431
|
+
if (buffer.length > 0) {
|
|
432
|
+
yield pushToken(buffer);
|
|
433
|
+
buffer = '';
|
|
434
|
+
}
|
|
435
|
+
const important = peek(9);
|
|
436
|
+
if (important == 'important') {
|
|
437
|
+
yield pushToken('', 'Important');
|
|
438
|
+
next(9);
|
|
439
|
+
buffer = '';
|
|
440
|
+
break;
|
|
441
|
+
}
|
|
442
|
+
buffer = '!';
|
|
443
|
+
break;
|
|
444
|
+
default:
|
|
445
|
+
buffer += value;
|
|
446
|
+
break;
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
if (buffer.length > 0) {
|
|
450
|
+
yield pushToken(buffer);
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
export { tokenize };
|
|
@@ -1,13 +1,37 @@
|
|
|
1
1
|
function eq(a, b) {
|
|
2
|
-
if (
|
|
2
|
+
if (a == null || b == null) {
|
|
3
|
+
return a == b;
|
|
4
|
+
}
|
|
5
|
+
if (typeof a != 'object' || typeof b != 'object') {
|
|
3
6
|
return a === b;
|
|
4
7
|
}
|
|
8
|
+
if (Object.getPrototypeOf(a) !== Object.getPrototypeOf(b)) {
|
|
9
|
+
return false;
|
|
10
|
+
}
|
|
11
|
+
if (Array.isArray(a)) {
|
|
12
|
+
if (a.length != b.length) {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
let i = 0;
|
|
16
|
+
for (; i < a.length; i++) {
|
|
17
|
+
if (!eq(a[i], b[i])) {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
5
23
|
const k1 = Object.keys(a);
|
|
6
24
|
const k2 = Object.keys(b);
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
25
|
+
if (k1.length != k2.length) {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
let key;
|
|
29
|
+
for (key of k1) {
|
|
30
|
+
if (!eq(a[key], b[key])) {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return true;
|
|
11
35
|
}
|
|
12
36
|
|
|
13
37
|
export { eq };
|
|
@@ -2,13 +2,14 @@
|
|
|
2
2
|
// https://www.w3.org/TR/2021/CRD-css-syntax-3-20211224/#typedef-ident-token
|
|
3
3
|
// '\\'
|
|
4
4
|
const REVERSE_SOLIDUS = 0x5c;
|
|
5
|
+
const dimensionUnits = [
|
|
6
|
+
'q', 'cap', 'ch', 'cm', 'cqb', 'cqh', 'cqi', 'cqmax', 'cqmin', 'cqw', 'dvb',
|
|
7
|
+
'dvh', 'dvi', 'dvmax', 'dvmin', 'dvw', 'em', 'ex', 'ic', 'in', 'lh', 'lvb',
|
|
8
|
+
'lvh', 'lvi', 'lvmax', 'lvw', 'mm', 'pc', 'pt', 'px', 'rem', 'rlh', 'svb',
|
|
9
|
+
'svh', 'svi', 'svmin', 'svw', 'vb', 'vh', 'vi', 'vmax', 'vmin', 'vw'
|
|
10
|
+
];
|
|
5
11
|
function isLength(dimension) {
|
|
6
|
-
return 'unit' in dimension &&
|
|
7
|
-
'q', 'cap', 'ch', 'cm', 'cqb', 'cqh', 'cqi', 'cqmax', 'cqmin', 'cqw', 'dvb',
|
|
8
|
-
'dvh', 'dvi', 'dvmax', 'dvmin', 'dvw', 'em', 'ex', 'ic', 'in', 'lh', 'lvb',
|
|
9
|
-
'lvh', 'lvi', 'lvmax', 'lvw', 'mm', 'pc', 'pt', 'px', 'rem', 'rlh', 'svb',
|
|
10
|
-
'svh', 'svi', 'svmin', 'svw', 'vb', 'vh', 'vi', 'vmax', 'vmin', 'vw'
|
|
11
|
-
].includes(dimension.unit.toLowerCase());
|
|
12
|
+
return 'unit' in dimension && dimensionUnits.includes(dimension.unit.toLowerCase());
|
|
12
13
|
}
|
|
13
14
|
function isResolution(dimension) {
|
|
14
15
|
return 'unit' in dimension && ['dpi', 'dpcm', 'dppx', 'x'].includes(dimension.unit.toLowerCase());
|
|
@@ -86,10 +87,7 @@ function isHash(name) {
|
|
|
86
87
|
if (name.charAt(0) != '#') {
|
|
87
88
|
return false;
|
|
88
89
|
}
|
|
89
|
-
|
|
90
|
-
return true;
|
|
91
|
-
}
|
|
92
|
-
return true;
|
|
90
|
+
return isIdent(name.charAt(1));
|
|
93
91
|
}
|
|
94
92
|
function isNumber(name) {
|
|
95
93
|
if (name.length == 0) {
|
|
@@ -233,6 +231,22 @@ function isHexColor(name) {
|
|
|
233
231
|
}
|
|
234
232
|
return true;
|
|
235
233
|
}
|
|
234
|
+
function isHexDigit(name) {
|
|
235
|
+
if (name.length || name.length > 6) {
|
|
236
|
+
return false;
|
|
237
|
+
}
|
|
238
|
+
for (let chr of name) {
|
|
239
|
+
let codepoint = chr.charCodeAt(0);
|
|
240
|
+
if (!isDigit(codepoint) &&
|
|
241
|
+
// A F
|
|
242
|
+
!(codepoint >= 0x41 && codepoint <= 0x46) &&
|
|
243
|
+
// a f
|
|
244
|
+
!(codepoint >= 0x61 && codepoint <= 0x66)) {
|
|
245
|
+
return false;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
return true;
|
|
249
|
+
}
|
|
236
250
|
function isFunction(name) {
|
|
237
251
|
return name.endsWith('(') && isIdent(name.slice(0, -1));
|
|
238
252
|
}
|
|
@@ -249,4 +263,4 @@ function isWhiteSpace(codepoint) {
|
|
|
249
263
|
codepoint == 0xa || codepoint == 0xc || codepoint == 0xd;
|
|
250
264
|
}
|
|
251
265
|
|
|
252
|
-
export { isAngle, isAtKeyword, isDigit, isDimension, isFrequency, isFunction, isHash, isHexColor, isIdent, isIdentCodepoint, isIdentStart, isLength, isNewLine, isNumber, isPercentage, isPseudo, isResolution, isTime, isWhiteSpace, parseDimension };
|
|
266
|
+
export { isAngle, isAtKeyword, isDigit, isDimension, isFrequency, isFunction, isHash, isHexColor, isHexDigit, isIdent, isIdentCodepoint, isIdentStart, isLength, isNewLine, isNumber, isPercentage, isPseudo, isResolution, isTime, isWhiteSpace, parseDimension };
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { rgb2Hex, hsl2Hex, hwb2hex, cmyk2hex, NAMES_COLORS } from './utils/color.js';
|
|
1
|
+
import { COLORS_NAMES, rgb2Hex, hsl2Hex, hwb2hex, cmyk2hex, NAMES_COLORS } from './utils/color.js';
|
|
2
2
|
|
|
3
3
|
function render(data, opt = {}) {
|
|
4
|
-
const
|
|
4
|
+
const startTime = performance.now();
|
|
5
|
+
const options = Object.assign(opt.minify ?? true ? {
|
|
5
6
|
indent: '',
|
|
6
7
|
newLine: '',
|
|
7
8
|
removeComments: true
|
|
@@ -19,7 +20,9 @@ function render(data, opt = {}) {
|
|
|
19
20
|
}
|
|
20
21
|
return acc + renderToken(curr, options);
|
|
21
22
|
}
|
|
22
|
-
return { code: doRender(data, options, reducer, 0)
|
|
23
|
+
return { code: doRender(data, options, reducer, 0), stats: {
|
|
24
|
+
total: `${(performance.now() - startTime).toFixed(2)}ms`
|
|
25
|
+
} };
|
|
23
26
|
}
|
|
24
27
|
// @ts-ignore
|
|
25
28
|
function doRender(data, options, reducer, level = 0, indents = []) {
|
|
@@ -48,7 +51,7 @@ function doRender(data, options, reducer, level = 0, indents = []) {
|
|
|
48
51
|
case 'AtRule':
|
|
49
52
|
case 'Rule':
|
|
50
53
|
if (data.typ == 'AtRule' && !('chi' in data)) {
|
|
51
|
-
return `${indent}@${data.nam} ${data.val};`;
|
|
54
|
+
return `${indent}@${data.nam}${data.val === '' ? '' : options.indent || ' '}${data.val};`;
|
|
52
55
|
}
|
|
53
56
|
// @ts-ignore
|
|
54
57
|
let children = data.chi.reduce((css, node) => {
|
|
@@ -60,7 +63,7 @@ function doRender(data, options, reducer, level = 0, indents = []) {
|
|
|
60
63
|
str = `${node.nam}:${options.indent}${node.val.reduce(reducer, '').trimEnd()};`;
|
|
61
64
|
}
|
|
62
65
|
else if (node.typ == 'AtRule' && !('chi' in node)) {
|
|
63
|
-
str =
|
|
66
|
+
str = `${data.val === '' ? '' : options.indent || ' '}${data.val};`;
|
|
64
67
|
}
|
|
65
68
|
else {
|
|
66
69
|
str = doRender(node, options, reducer, level + 1, indents);
|
|
@@ -77,7 +80,7 @@ function doRender(data, options, reducer, level = 0, indents = []) {
|
|
|
77
80
|
children = children.slice(0, -1);
|
|
78
81
|
}
|
|
79
82
|
if (data.typ == 'AtRule') {
|
|
80
|
-
return `@${data.nam}${data.val
|
|
83
|
+
return `@${data.nam}${data.val === '' ? '' : options.indent || ' '}${data.val}${options.indent}{${options.newLine}` + (children === '' ? '' : indentSub + children + options.newLine) + indent + `}`;
|
|
81
84
|
}
|
|
82
85
|
return data.sel + `${options.indent}{${options.newLine}` + (children === '' ? '' : indentSub + children + options.newLine) + indent + `}`;
|
|
83
86
|
}
|
|
@@ -86,8 +89,11 @@ function doRender(data, options, reducer, level = 0, indents = []) {
|
|
|
86
89
|
function renderToken(token, options = {}) {
|
|
87
90
|
switch (token.typ) {
|
|
88
91
|
case 'Color':
|
|
89
|
-
if (options.
|
|
90
|
-
|
|
92
|
+
if (options.minify || options.colorConvert) {
|
|
93
|
+
if (token.kin == 'lit' && token.val.toLowerCase() == 'currentcolor') {
|
|
94
|
+
return 'currentcolor';
|
|
95
|
+
}
|
|
96
|
+
let value = token.kin == 'hex' ? token.val.toLowerCase() : (token.kin == 'lit' ? COLORS_NAMES[token.val.toLowerCase()] : '');
|
|
91
97
|
if (token.val == 'rgb' || token.val == 'rgba') {
|
|
92
98
|
value = rgb2Hex(token);
|
|
93
99
|
}
|
|
@@ -131,7 +137,7 @@ function renderToken(token, options = {}) {
|
|
|
131
137
|
case 'UrlFunc':
|
|
132
138
|
case 'Pseudo-class-func':
|
|
133
139
|
// @ts-ignore
|
|
134
|
-
return ( /* options.
|
|
140
|
+
return ( /* options.minify && 'Pseudo-class-func' == token.typ && token.val.slice(0, 2) == '::' ? token.val.slice(1) :*/token.val ?? '') + '(' + token.chi.reduce((acc, curr) => {
|
|
135
141
|
if (options.removeComments && curr.typ == 'Comment') {
|
|
136
142
|
if (!options.preserveLicense || !curr.val.startsWith('/*!')) {
|
|
137
143
|
return acc;
|
|
@@ -222,9 +228,11 @@ function renderToken(token, options = {}) {
|
|
|
222
228
|
case 'String':
|
|
223
229
|
case 'Iden':
|
|
224
230
|
case 'Delim':
|
|
225
|
-
return /* options.
|
|
231
|
+
return /* options.minify && 'Pseudo-class' == token.typ && '::' == token.val.slice(0, 2) ? token.val.slice(1) : */ token.val;
|
|
226
232
|
}
|
|
227
|
-
|
|
233
|
+
console.error(`unexpected token ${JSON.stringify(token, null, 1)}`);
|
|
234
|
+
// throw new Error(`unexpected token ${JSON.stringify(token, null, 1)}`);
|
|
235
|
+
return '';
|
|
228
236
|
}
|
|
229
237
|
|
|
230
238
|
export { render, renderToken };
|
package/dist/lib/transform.js
CHANGED
|
@@ -2,21 +2,19 @@ import { parse } from './parser/parse.js';
|
|
|
2
2
|
import { render } from './renderer/render.js';
|
|
3
3
|
|
|
4
4
|
async function transform(css, options = {}) {
|
|
5
|
-
options = {
|
|
5
|
+
options = { minify: true, removeEmpty: true, ...options };
|
|
6
6
|
const startTime = performance.now();
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
19
|
-
};
|
|
7
|
+
return parse(css, options).then((parseResult) => {
|
|
8
|
+
const rendered = render(parseResult.ast, options);
|
|
9
|
+
return {
|
|
10
|
+
...parseResult, ...rendered, stats: {
|
|
11
|
+
bytesOut: rendered.code.length,
|
|
12
|
+
...parseResult.stats,
|
|
13
|
+
render: rendered.stats.total,
|
|
14
|
+
total: `${(performance.now() - startTime).toFixed(2)}ms`
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
});
|
|
20
18
|
}
|
|
21
19
|
|
|
22
20
|
export { transform };
|
package/dist/node/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { parse as parse$1 } from '../lib/parser/parse.js';
|
|
2
|
+
export { parseString, urlTokenMatcher } from '../lib/parser/parse.js';
|
|
2
3
|
import '../lib/renderer/utils/color.js';
|
|
3
4
|
import { transform as transform$1 } from '../lib/transform.js';
|
|
4
5
|
import { load } from './load.js';
|