@tbela99/css-parser 0.2.0 → 0.4.0

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 (57) hide show
  1. package/{LICENSE → LICENSE.md} +1 -1
  2. package/README.md +250 -77
  3. package/dist/config.json.js +245 -1
  4. package/dist/index-umd-web.js +4241 -1583
  5. package/dist/index.cjs +4242 -1584
  6. package/dist/index.d.ts +71 -23
  7. package/dist/lib/ast/expand.js +1 -1
  8. package/dist/lib/ast/features/calc.js +31 -192
  9. package/dist/lib/ast/features/index.js +3 -3
  10. package/dist/lib/ast/features/inlinecssvariables.js +6 -6
  11. package/dist/lib/ast/features/shorthand.js +5 -6
  12. package/dist/lib/ast/math/expression.js +220 -0
  13. package/dist/lib/ast/{features/utils → math}/math.js +4 -4
  14. package/dist/lib/ast/minify.js +0 -1
  15. package/dist/lib/ast/types.js +31 -13
  16. package/dist/lib/ast/utils/minifyfeature.js +4 -3
  17. package/dist/lib/ast/walk.js +24 -4
  18. package/dist/lib/fs/resolve.js +4 -3
  19. package/dist/lib/parser/declaration/list.js +6 -2
  20. package/dist/lib/parser/declaration/map.js +158 -24
  21. package/dist/lib/parser/declaration/set.js +42 -22
  22. package/dist/lib/parser/parse.js +345 -349
  23. package/dist/lib/parser/tokenize.js +220 -223
  24. package/dist/lib/parser/utils/declaration.js +67 -0
  25. package/dist/lib/parser/utils/syntax.js +172 -6
  26. package/dist/lib/parser/utils/type.js +2 -2
  27. package/dist/lib/renderer/color/a98rgb.js +64 -0
  28. package/dist/lib/renderer/color/color.js +521 -0
  29. package/dist/lib/renderer/color/colormix.js +337 -0
  30. package/dist/lib/renderer/color/hex.js +92 -0
  31. package/dist/lib/renderer/color/hsl.js +118 -0
  32. package/dist/lib/renderer/color/hsv.js +20 -0
  33. package/dist/lib/renderer/color/hwb.js +101 -0
  34. package/dist/lib/renderer/color/lab.js +136 -0
  35. package/dist/lib/renderer/color/lch.js +79 -0
  36. package/dist/lib/renderer/color/oklab.js +121 -0
  37. package/dist/lib/renderer/color/oklch.js +65 -0
  38. package/dist/lib/renderer/color/p3.js +57 -0
  39. package/dist/lib/renderer/color/prophotorgb.js +56 -0
  40. package/dist/lib/renderer/color/rec2020.js +70 -0
  41. package/dist/lib/renderer/color/relativecolor.js +152 -0
  42. package/dist/lib/renderer/color/rgb.js +44 -0
  43. package/dist/lib/renderer/color/srgb.js +261 -0
  44. package/dist/lib/renderer/color/utils/components.js +20 -0
  45. package/dist/lib/renderer/color/utils/constants.js +191 -0
  46. package/dist/lib/renderer/color/utils/matrix.js +35 -0
  47. package/dist/lib/renderer/color/xyz.js +64 -0
  48. package/dist/lib/renderer/color/xyzd50.js +33 -0
  49. package/dist/lib/renderer/render.js +128 -30
  50. package/dist/node/index.js +1 -1
  51. package/dist/node/load.js +1 -1
  52. package/dist/web/index.js +1 -1
  53. package/package.json +19 -18
  54. package/quickjs.sh +1 -0
  55. package/dist/lib/iterable/weakmap.js +0 -53
  56. package/dist/lib/renderer/utils/color.js +0 -499
  57. /package/dist/lib/iterable/{set.js → weakset.js} +0 -0
@@ -1,15 +1,13 @@
1
1
  import { eq } from '../utils/eq.js';
2
2
  import { renderToken } from '../../renderer/render.js';
3
- import '../../renderer/utils/color.js';
4
3
  import { EnumToken } from '../../ast/types.js';
5
4
  import '../../ast/minify.js';
6
5
  import { parseString } from '../parse.js';
6
+ import '../../renderer/color/utils/constants.js';
7
7
  import { getConfig } from '../utils/config.js';
8
8
  import { matchType } from '../utils/type.js';
9
9
  import { PropertySet } from './set.js';
10
- import { IterableWeakMap } from '../../iterable/weakmap.js';
11
10
 
12
- const cache = new IterableWeakMap();
13
11
  const propertiesConfig = getConfig();
14
12
  class PropertyMap {
15
13
  config;
@@ -24,12 +22,10 @@ class PropertyMap {
24
22
  this.pattern = config.pattern.split(/\s/);
25
23
  }
26
24
  add(declaration) {
27
- for (const val of declaration.val) {
28
- Object.defineProperty(val, 'propertyName', { enumerable: false, writable: true, value: declaration.nam });
29
- }
30
25
  if (declaration.nam == this.config.shorthand) {
31
26
  this.declarations = new Map;
32
27
  this.declarations.set(declaration.nam, declaration);
28
+ this.matchTypes(declaration);
33
29
  }
34
30
  else {
35
31
  const separator = this.config.separator != null ? {
@@ -167,6 +163,55 @@ class PropertyMap {
167
163
  }
168
164
  return this;
169
165
  }
166
+ matchTypes(declaration) {
167
+ const patterns = this.pattern.slice();
168
+ const values = [...declaration.val];
169
+ let i;
170
+ let j;
171
+ const map = new Map;
172
+ for (i = 0; i < patterns.length; i++) {
173
+ for (j = 0; j < values.length; j++) {
174
+ if (!map.has(patterns[i])) {
175
+ // @ts-ignore
176
+ map.set(patterns[i], this.config.properties?.[patterns[i]]?.constraints?.mapping?.max ?? 1);
177
+ }
178
+ let count = map.get(patterns[i]);
179
+ if (count > 0 && matchType(values[j], this.config.properties[patterns[i]])) {
180
+ Object.defineProperty(values[j], 'propertyName', {
181
+ enumerable: false,
182
+ writable: true,
183
+ value: patterns[i]
184
+ });
185
+ map.set(patterns[i], --count);
186
+ values.splice(j--, 1);
187
+ }
188
+ }
189
+ }
190
+ if (this.config.set != null) {
191
+ for (const [key, val] of Object.entries(this.config.set)) {
192
+ if (map.has(key)) {
193
+ for (const v of val) {
194
+ // missing
195
+ if (map.get(v) == 1) {
196
+ let i = declaration.val.length;
197
+ while (i--) {
198
+ // @ts-ignore
199
+ if (declaration.val[i].propertyName == key) {
200
+ const val = { ...declaration.val[i] };
201
+ Object.defineProperty(val, 'propertyName', {
202
+ enumerable: false,
203
+ writable: true,
204
+ value: v
205
+ });
206
+ declaration.val.splice(i, 0, val, { typ: EnumToken.WhitespaceTokenType });
207
+ }
208
+ }
209
+ }
210
+ }
211
+ }
212
+ }
213
+ }
214
+ }
170
215
  [Symbol.iterator]() {
171
216
  let iterable;
172
217
  let requiredCount = 0;
@@ -195,22 +240,62 @@ class PropertyMap {
195
240
  }
196
241
  if (!isShorthand || requiredCount < this.requiredCount) {
197
242
  if (isShorthand && this.declarations.has(this.config.shorthand)) {
198
- // console.debug(...this.declarations.values());
243
+ const cache = new Map();
199
244
  const removeDefaults = (declaration) => {
200
- // const dec: AstDeclaration = {...declaration};
201
- const config = this.config.shorthand == declaration.nam ? this.config : this.config.properties[declaration.nam];
202
- declaration.val = declaration.val.filter((val) => {
203
- if (!cache.has(val)) {
204
- cache.set(val, renderToken(val, { minify: true }));
245
+ let i;
246
+ let t;
247
+ let map = new Map();
248
+ let value = [];
249
+ let values = [];
250
+ // @ts-ignore
251
+ let typ = (EnumToken[this.config.separator?.typ] ?? EnumToken.CommaTokenType);
252
+ let separator = this.config.separator ? renderToken(this.config.separator) : ',';
253
+ this.matchTypes(declaration);
254
+ values.push(value);
255
+ for (i = 0; i < declaration.val.length; i++) {
256
+ t = declaration.val[i];
257
+ if (!cache.has(t)) {
258
+ cache.set(t, renderToken(t, { minify: true }));
259
+ }
260
+ if (t.typ == typ && separator == cache.get(t)) {
261
+ this.removeDefaults(map, value);
262
+ value = [];
263
+ values.push(value);
264
+ map.clear();
265
+ continue;
266
+ }
267
+ value.push(t);
268
+ // @ts-ignore
269
+ if ('propertyName' in t) {
270
+ // @ts-ignore
271
+ if (!map.has(t.propertyName)) {
272
+ // @ts-ignore
273
+ map.set(t.propertyName, { t: [t], value: [cache.get(t)] });
274
+ }
275
+ else {
276
+ // @ts-ignore
277
+ const v = map.get(t.propertyName);
278
+ v.t.push(t);
279
+ v.value.push(cache.get(t));
280
+ }
205
281
  }
206
- return !config.default.includes(cache.get(val));
207
- })
208
- .filter((val, index, array) => !(index > 0 &&
209
- val.typ == EnumToken.WhitespaceTokenType &&
210
- array[index - 1].typ == EnumToken.WhitespaceTokenType));
211
- if (declaration.val.at(-1)?.typ == EnumToken.WhitespaceTokenType) {
282
+ }
283
+ this.removeDefaults(map, value);
284
+ declaration.val = values.reduce((acc, curr) => {
285
+ for (const cr of curr) {
286
+ if (cr.typ == EnumToken.WhitespaceTokenType && acc.at(-1)?.typ == cr.typ) {
287
+ continue;
288
+ }
289
+ acc.push(cr);
290
+ }
291
+ return acc;
292
+ }, []);
293
+ while (declaration.val.at(-1)?.typ == EnumToken.WhitespaceTokenType) {
212
294
  declaration.val.pop();
213
295
  }
296
+ while (declaration.val.at(0)?.typ == EnumToken.WhitespaceTokenType) {
297
+ declaration.val.shift();
298
+ }
214
299
  return declaration;
215
300
  };
216
301
  const values = [...this.declarations.values()].reduce((acc, curr) => {
@@ -222,13 +307,24 @@ class PropertyMap {
222
307
  }
223
308
  return acc;
224
309
  }, []);
225
- const filtered = values.map(removeDefaults).filter((x) => x.val.length > 0);
310
+ let isImportant = false;
311
+ const filtered = values.map(removeDefaults).filter((x) => x.val.filter((t) => {
312
+ if (t.typ == EnumToken.ImportantTokenType) {
313
+ isImportant = true;
314
+ }
315
+ return ![EnumToken.WhitespaceTokenType, EnumToken.ImportantTokenType].includes(t.typ);
316
+ }).length > 0);
226
317
  if (filtered.length == 0 && this.config.default.length > 0) {
227
318
  filtered.push({
228
319
  typ: EnumToken.DeclarationNodeType,
229
320
  nam: this.config.shorthand,
230
321
  val: parseString(this.config.default[0])
231
322
  });
323
+ if (isImportant) {
324
+ filtered[0].val.push({
325
+ typ: EnumToken.ImportantTokenType
326
+ });
327
+ }
232
328
  }
233
329
  return (filtered.length > 0 ? filtered : values)[Symbol.iterator]();
234
330
  }
@@ -299,12 +395,12 @@ class PropertyMap {
299
395
  return acc;
300
396
  }, []);
301
397
  count++;
302
- if (!isShorthand || Object.entries(this.config.properties).some(entry => {
398
+ if (!isShorthand || Object.entries(this.config.properties).some((entry) => {
303
399
  // missing required property
304
400
  return entry[1].required && !(entry[0] in tokens);
305
401
  }) ||
306
402
  // @ts-ignore
307
- !Object.values(tokens).every(v => v.filter(t => t.typ != EnumToken.CommentTokenType).length == count)) {
403
+ !Object.values(tokens).every((v) => v.filter((t) => t.typ != EnumToken.CommentTokenType).length == count)) {
308
404
  // @ts-ignore
309
405
  iterable = this.declarations.values();
310
406
  }
@@ -324,7 +420,9 @@ class PropertyMap {
324
420
  }, []);
325
421
  // @todo remove renderToken call
326
422
  if (props.default.includes(curr[1][i].reduce((acc, curr) => acc + renderToken(curr) + ' ', '').trimEnd())) {
327
- continue;
423
+ if (!this.config.properties[curr[0]].required) {
424
+ continue;
425
+ }
328
426
  }
329
427
  // remove default values
330
428
  let doFilterDefault = true;
@@ -338,12 +436,15 @@ class PropertyMap {
338
436
  }
339
437
  }
340
438
  // remove default values
341
- values = values.filter((val) => {
439
+ const filtered = values.filter((val) => {
342
440
  if (val.typ == EnumToken.WhitespaceTokenType || val.typ == EnumToken.CommentTokenType) {
343
441
  return false;
344
442
  }
345
443
  return !doFilterDefault || !(val.typ == EnumToken.IdenTokenType && props.default.includes(val.val));
346
444
  });
445
+ if (filtered.length > 0 || !(this.requiredCount == requiredCount && this.config.properties[curr[0]].required)) {
446
+ values = filtered;
447
+ }
347
448
  if (values.length > 0) {
348
449
  if ('mapping' in props) {
349
450
  // @ts-ignore
@@ -399,7 +500,10 @@ class PropertyMap {
399
500
  return acc;
400
501
  }, []);
401
502
  if (this.config.mapping != null) {
402
- const val = values.reduce((acc, curr) => acc + renderToken(curr, { removeComments: true, minify: true }), '');
503
+ const val = values.reduce((acc, curr) => acc + renderToken(curr, {
504
+ removeComments: true,
505
+ minify: true
506
+ }), '');
403
507
  if (val in this.config.mapping) {
404
508
  values.length = 0;
405
509
  values.push({
@@ -451,6 +555,36 @@ class PropertyMap {
451
555
  }
452
556
  };
453
557
  }
558
+ removeDefaults(map, value) {
559
+ for (const [key, val] of map) {
560
+ const config = this.config.properties[key];
561
+ if (config == null) {
562
+ continue;
563
+ }
564
+ const v = val.value.join(' ');
565
+ if (config.default.includes(v) || (value.length == 1 && this.config.default.includes(v))) {
566
+ for (const token of value) {
567
+ if (val.t.includes(token)) {
568
+ let index = value.indexOf(token);
569
+ value.splice(index, 1);
570
+ if (config.prefix != null) {
571
+ while (index-- > 0) {
572
+ if (value[index].typ == EnumToken.WhitespaceTokenType) {
573
+ continue;
574
+ }
575
+ if (value[index].typ == EnumToken[config.prefix.typ] &&
576
+ // @ts-ignore
577
+ value[index].val == config.prefix.val) {
578
+ value.splice(index, 1);
579
+ break;
580
+ }
581
+ }
582
+ }
583
+ }
584
+ }
585
+ }
586
+ }
587
+ }
454
588
  }
455
589
 
456
590
  export { PropertyMap };
@@ -3,9 +3,32 @@ import { isLength } from '../utils/syntax.js';
3
3
  import { EnumToken } from '../../ast/types.js';
4
4
  import '../../ast/minify.js';
5
5
  import '../parse.js';
6
- import '../../renderer/utils/color.js';
6
+ import '../../renderer/color/utils/constants.js';
7
7
  import '../../renderer/sourcemap/lib/encode.js';
8
8
 
9
+ function dedup(values) {
10
+ for (const value of values) {
11
+ let i = value.length;
12
+ while (i-- > 1) {
13
+ const t = value[i];
14
+ const k = value[i == 1 ? 0 : i % 2];
15
+ if (t.val == k.val && t.val == '0') {
16
+ if ((t.typ == EnumToken.NumberTokenType && isLength(k)) ||
17
+ (k.typ == EnumToken.NumberTokenType && isLength(t)) ||
18
+ (isLength(k) || isLength(t))) {
19
+ value.splice(i, 1);
20
+ continue;
21
+ }
22
+ }
23
+ if (eq(t, k)) {
24
+ value.splice(i, 1);
25
+ continue;
26
+ }
27
+ break;
28
+ }
29
+ }
30
+ return values;
31
+ }
9
32
  class PropertySet {
10
33
  config;
11
34
  declarations;
@@ -100,7 +123,23 @@ class PropertySet {
100
123
  let iterator;
101
124
  const declarations = this.declarations;
102
125
  if (declarations.size < this.config.properties.length) {
103
- iterator = declarations.values();
126
+ const values = [...declarations.values()];
127
+ if (this.isShortHand()) {
128
+ const val = values[0].val.reduce((acc, curr) => {
129
+ if (![EnumToken.WhitespaceTokenType, EnumToken.CommentTokenType].includes(curr.typ)) {
130
+ acc.push(curr);
131
+ }
132
+ return acc;
133
+ }, []);
134
+ values[0].val = val.reduce((acc, curr) => {
135
+ if (acc.length > 0) {
136
+ acc.push({ typ: EnumToken.WhitespaceTokenType });
137
+ }
138
+ acc.push(curr);
139
+ return acc;
140
+ }, []);
141
+ }
142
+ return values[Symbol.iterator]();
104
143
  }
105
144
  else {
106
145
  const values = [];
@@ -118,26 +157,7 @@ class PropertySet {
118
157
  index++;
119
158
  }
120
159
  });
121
- for (const value of values) {
122
- let i = value.length;
123
- while (i-- > 1) {
124
- const t = value[i];
125
- const k = value[i == 1 ? 0 : i % 2];
126
- if (t.val == k.val && t.val == '0') {
127
- if ((t.typ == EnumToken.NumberTokenType && isLength(k)) ||
128
- (k.typ == EnumToken.NumberTokenType && isLength(t)) ||
129
- (isLength(k) || isLength(t))) {
130
- value.splice(i, 1);
131
- continue;
132
- }
133
- }
134
- if (eq(t, k)) {
135
- value.splice(i, 1);
136
- continue;
137
- }
138
- break;
139
- }
140
- }
160
+ dedup(values);
141
161
  iterator = [{
142
162
  typ: EnumToken.DeclarationNodeType,
143
163
  nam: this.config.shorthand,