cssstyle 5.3.7 → 6.0.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 (93) hide show
  1. package/lib/CSSStyleDeclaration.js +359 -395
  2. package/lib/generated/.gitkeep +0 -0
  3. package/lib/generated/propertyDefinitions.js +3718 -1474
  4. package/lib/generated/propertyDescriptors.js +1711 -0
  5. package/lib/index.js +9 -0
  6. package/lib/normalize.js +127 -253
  7. package/lib/parsers.js +160 -180
  8. package/lib/properties/background.js +201 -202
  9. package/lib/properties/backgroundAttachment.js +35 -33
  10. package/lib/properties/backgroundClip.js +35 -33
  11. package/lib/properties/backgroundColor.js +26 -24
  12. package/lib/properties/backgroundImage.js +36 -34
  13. package/lib/properties/backgroundOrigin.js +35 -33
  14. package/lib/properties/backgroundPosition.js +57 -57
  15. package/lib/properties/backgroundRepeat.js +40 -37
  16. package/lib/properties/backgroundSize.js +38 -34
  17. package/lib/properties/border.js +41 -34
  18. package/lib/properties/{webkitBorderEndColor.js → borderBlockEndColor.js} +26 -22
  19. package/lib/properties/{webkitBorderAfterColor.js → borderBlockStartColor.js} +26 -22
  20. package/lib/properties/borderBottom.js +40 -36
  21. package/lib/properties/borderBottomColor.js +25 -21
  22. package/lib/properties/borderBottomStyle.js +25 -21
  23. package/lib/properties/borderBottomWidth.js +28 -24
  24. package/lib/properties/borderCollapse.js +25 -21
  25. package/lib/properties/borderColor.js +36 -33
  26. package/lib/properties/{webkitBorderStartColor.js → borderInlineEndColor.js} +26 -22
  27. package/lib/properties/borderInlineStartColor.js +49 -0
  28. package/lib/properties/borderLeft.js +40 -36
  29. package/lib/properties/borderLeftColor.js +25 -21
  30. package/lib/properties/borderLeftStyle.js +25 -21
  31. package/lib/properties/borderLeftWidth.js +28 -24
  32. package/lib/properties/borderRight.js +40 -36
  33. package/lib/properties/borderRightColor.js +25 -21
  34. package/lib/properties/borderRightStyle.js +25 -21
  35. package/lib/properties/borderRightWidth.js +28 -24
  36. package/lib/properties/borderSpacing.js +33 -29
  37. package/lib/properties/borderStyle.js +36 -33
  38. package/lib/properties/borderTop.js +40 -36
  39. package/lib/properties/borderTopColor.js +25 -21
  40. package/lib/properties/borderTopStyle.js +25 -21
  41. package/lib/properties/borderTopWidth.js +28 -24
  42. package/lib/properties/borderWidth.js +36 -33
  43. package/lib/properties/bottom.js +27 -23
  44. package/lib/properties/clear.js +25 -21
  45. package/lib/properties/clip.js +37 -31
  46. package/lib/properties/color.js +25 -21
  47. package/lib/properties/display.js +36 -30
  48. package/lib/properties/flex.js +53 -45
  49. package/lib/properties/flexBasis.js +28 -26
  50. package/lib/properties/flexGrow.js +28 -26
  51. package/lib/properties/flexShrink.js +28 -26
  52. package/lib/properties/float.js +25 -21
  53. package/lib/properties/floodColor.js +25 -21
  54. package/lib/properties/font.js +89 -118
  55. package/lib/properties/fontFamily.js +38 -33
  56. package/lib/properties/fontSize.js +29 -27
  57. package/lib/properties/fontStyle.js +38 -34
  58. package/lib/properties/fontVariant.js +35 -33
  59. package/lib/properties/fontWeight.js +33 -31
  60. package/lib/properties/height.js +28 -24
  61. package/lib/properties/left.js +27 -23
  62. package/lib/properties/lightingColor.js +25 -21
  63. package/lib/properties/lineHeight.js +28 -26
  64. package/lib/properties/margin.js +40 -34
  65. package/lib/properties/marginBottom.js +30 -27
  66. package/lib/properties/marginLeft.js +30 -27
  67. package/lib/properties/marginRight.js +30 -27
  68. package/lib/properties/marginTop.js +30 -27
  69. package/lib/properties/opacity.js +27 -23
  70. package/lib/properties/outlineColor.js +25 -21
  71. package/lib/properties/padding.js +40 -34
  72. package/lib/properties/paddingBottom.js +31 -28
  73. package/lib/properties/paddingLeft.js +31 -28
  74. package/lib/properties/paddingRight.js +31 -28
  75. package/lib/properties/paddingTop.js +31 -28
  76. package/lib/properties/right.js +27 -23
  77. package/lib/properties/stopColor.js +25 -21
  78. package/lib/properties/{webkitBorderBeforeColor.js → textEmphasisColor.js} +26 -22
  79. package/lib/properties/top.js +27 -23
  80. package/lib/properties/webkitTextFillColor.js +25 -21
  81. package/lib/properties/webkitTextStrokeColor.js +25 -21
  82. package/lib/properties/width.js +28 -24
  83. package/lib/utils/propertyDescriptors.js +129 -42
  84. package/lib/utils/strings.js +11 -156
  85. package/package.json +12 -22
  86. package/lib/generated/allProperties.js +0 -653
  87. package/lib/generated/implementedProperties.js +0 -1466
  88. package/lib/generated/properties.js +0 -6637
  89. package/lib/properties/webkitColumnRuleColor.js +0 -45
  90. package/lib/properties/webkitTapHighlightColor.js +0 -45
  91. package/lib/properties/webkitTextEmphasisColor.js +0 -45
  92. package/lib/utils/allExtraProperties.js +0 -155
  93. package/lib/utils/camelize.js +0 -37
package/lib/parsers.js CHANGED
@@ -7,8 +7,12 @@ const {
7
7
  const { next: syntaxes } = require("@csstools/css-syntax-patches-for-csstree");
8
8
  const csstree = require("css-tree");
9
9
  const { LRUCache } = require("lru-cache");
10
+ const propertyDefinitions = require("./generated/propertyDefinitions");
10
11
  const { asciiLowercase } = require("./utils/strings");
11
12
 
13
+ // Constants
14
+ const CALC_FUNC_NAMES = "(?:a?(?:cos|sin|tan)|abs|atan2|calc|clamp|exp|hypot|log|max|min|mod|pow|rem|round|sign|sqrt)";
15
+
12
16
  // CSS global keywords
13
17
  // @see https://drafts.csswg.org/css-cascade-5/#defaulting-keywords
14
18
  const GLOBAL_KEYS = new Set(["initial", "inherit", "unset", "revert", "revert-layer"]);
@@ -76,8 +80,6 @@ const AST_TYPES = Object.freeze({
76
80
  });
77
81
 
78
82
  // Regular expressions
79
- const CALC_FUNC_NAMES =
80
- "(?:a?(?:cos|sin|tan)|abs|atan2|calc|clamp|exp|hypot|log|max|min|mod|pow|rem|round|sign|sqrt)";
81
83
  const calcRegEx = new RegExp(`^${CALC_FUNC_NAMES}\\(`);
82
84
  const calcContainedRegEx = new RegExp(`(?<=[*/\\s(])${CALC_FUNC_NAMES}\\(`);
83
85
  const calcNameRegEx = new RegExp(`^${CALC_FUNC_NAMES}$`);
@@ -98,14 +100,14 @@ const lruCache = new LRUCache({
98
100
  * @param {string|number|null|undefined} value - The value to prepare.
99
101
  * @returns {string} The prepared value.
100
102
  */
101
- const prepareValue = (value) => {
103
+ function prepareValue(value) {
102
104
  // `null` is converted to an empty string.
103
105
  // @see https://webidl.spec.whatwg.org/#LegacyNullToEmptyString
104
106
  if (value === null) {
105
107
  return "";
106
108
  }
107
109
  return `${value}`.trim();
108
- };
110
+ }
109
111
 
110
112
  /**
111
113
  * Checks if the value is a global keyword.
@@ -113,9 +115,9 @@ const prepareValue = (value) => {
113
115
  * @param {string} val - The value to check.
114
116
  * @returns {boolean} True if the value is a global keyword, false otherwise.
115
117
  */
116
- const isGlobalKeyword = (val) => {
118
+ function isGlobalKeyword(val) {
117
119
  return GLOBAL_KEYS.has(asciiLowercase(val));
118
- };
120
+ }
119
121
 
120
122
  /**
121
123
  * Checks if the value starts with or contains a CSS var() function.
@@ -123,9 +125,9 @@ const isGlobalKeyword = (val) => {
123
125
  * @param {string} val - The value to check.
124
126
  * @returns {boolean} True if the value contains a var() function, false otherwise.
125
127
  */
126
- const hasVarFunc = (val) => {
128
+ function hasVarFunc(val) {
127
129
  return varRegEx.test(val) || varContainedRegEx.test(val);
128
- };
130
+ }
129
131
 
130
132
  /**
131
133
  * Checks if the value starts with or contains CSS calc() or math functions.
@@ -133,26 +135,20 @@ const hasVarFunc = (val) => {
133
135
  * @param {string} val - The value to check.
134
136
  * @returns {boolean} True if the value contains calc() or math functions, false otherwise.
135
137
  */
136
- const hasCalcFunc = (val) => {
138
+ function hasCalcFunc(val) {
137
139
  return calcRegEx.test(val) || calcContainedRegEx.test(val);
138
- };
140
+ }
139
141
 
140
142
  /**
141
143
  * Parses a CSS string into an AST.
142
144
  *
143
145
  * @param {string} val - The CSS string to parse.
144
146
  * @param {object} opt - The options for parsing.
145
- * @param {boolean} [toObject=false] - Whether to return a plain object.
146
- * @returns {object} The AST or a plain object.
147
+ * @returns {object} The AST.
147
148
  */
148
- const parseCSS = (val, opt, toObject = false) => {
149
- val = prepareValue(val);
150
- const ast = cssTree.parse(val, opt);
151
- if (toObject) {
152
- return cssTree.toPlainObject(ast);
153
- }
154
- return ast;
155
- };
149
+ function parseCSS(val, opt) {
150
+ return cssTree.parse(prepareValue(val), opt);
151
+ }
156
152
 
157
153
  /**
158
154
  * Checks if the value is a valid property value.
@@ -162,20 +158,14 @@ const parseCSS = (val, opt, toObject = false) => {
162
158
  * @param {string} val - The property value.
163
159
  * @returns {boolean} True if the value is valid, false otherwise.
164
160
  */
165
- const isValidPropertyValue = (prop, val) => {
161
+ function isValidPropertyValue(prop, val) {
162
+ if (!propertyDefinitions.has(prop)) {
163
+ return false;
164
+ }
166
165
  val = prepareValue(val);
167
166
  if (val === "") {
168
167
  return true;
169
168
  }
170
- // cssTree.lexer does not support deprecated system colors
171
- // @see https://github.com/w3c/webref/issues/1519#issuecomment-3120290261
172
- // @see https://github.com/w3c/webref/issues/1647
173
- if (SYS_COLORS.has(asciiLowercase(val))) {
174
- if (/^(?:-webkit-)?(?:[a-z][a-z\d]*-)*color$/i.test(prop)) {
175
- return true;
176
- }
177
- return false;
178
- }
179
169
  const cacheKey = `isValidPropertyValue_${prop}_${val}`;
180
170
  const cachedValue = lruCache.get(cacheKey);
181
171
  if (typeof cachedValue === "boolean") {
@@ -193,7 +183,7 @@ const isValidPropertyValue = (prop, val) => {
193
183
  }
194
184
  lruCache.set(cacheKey, result);
195
185
  return result;
196
- };
186
+ }
197
187
 
198
188
  /**
199
189
  * Resolves CSS math functions.
@@ -202,7 +192,7 @@ const isValidPropertyValue = (prop, val) => {
202
192
  * @param {object} [opt={ format: "specifiedValue" }] - The options for resolving.
203
193
  * @returns {string|undefined} The resolved value.
204
194
  */
205
- const resolveCalc = (val, opt = { format: "specifiedValue" }) => {
195
+ function resolveCalc(val, opt = { format: "specifiedValue" }) {
206
196
  val = prepareValue(val);
207
197
  if (val === "" || hasVarFunc(val) || !hasCalcFunc(val)) {
208
198
  return val;
@@ -212,13 +202,12 @@ const resolveCalc = (val, opt = { format: "specifiedValue" }) => {
212
202
  if (typeof cachedValue === "string") {
213
203
  return cachedValue;
214
204
  }
215
- const obj = parseCSS(val, { context: "value" }, true);
216
- if (!obj?.children) {
205
+ const ast = parseCSS(val, { context: "value" });
206
+ if (!ast?.children) {
217
207
  return;
218
208
  }
219
- const { children: items } = obj;
220
209
  const values = [];
221
- for (const item of items) {
210
+ for (const item of ast.children) {
222
211
  const { type: itemType, name: itemName, value: itemValue } = item;
223
212
  if (itemType === AST_TYPES.FUNCTION) {
224
213
  const value = cssTree
@@ -240,7 +229,7 @@ const resolveCalc = (val, opt = { format: "specifiedValue" }) => {
240
229
  const resolvedValue = values.join(" ");
241
230
  lruCache.set(cacheKey, resolvedValue);
242
231
  return resolvedValue;
243
- };
232
+ }
244
233
 
245
234
  /**
246
235
  * Parses a property value.
@@ -251,8 +240,11 @@ const resolveCalc = (val, opt = { format: "specifiedValue" }) => {
251
240
  * @param {object} [opt={}] - The options for parsing.
252
241
  * @returns {string|Array<object>|undefined} The parsed value.
253
242
  */
254
- const parsePropertyValue = (prop, val, opt = {}) => {
255
- const { caseSensitive, inArray } = opt;
243
+ function parsePropertyValue(prop, val, opt = {}) {
244
+ if (!propertyDefinitions.has(prop)) {
245
+ return;
246
+ }
247
+ const { caseSensitive } = opt;
256
248
  val = prepareValue(val);
257
249
  if (val === "" || hasVarFunc(val)) {
258
250
  return val;
@@ -269,41 +261,18 @@ const parsePropertyValue = (prop, val, opt = {}) => {
269
261
  const cachedValue = lruCache.get(cacheKey);
270
262
  if (cachedValue === false) {
271
263
  return;
272
- } else if (inArray) {
273
- if (Array.isArray(cachedValue)) {
274
- return cachedValue;
275
- }
276
- } else if (typeof cachedValue === "string") {
264
+ } else if (cachedValue !== undefined) {
277
265
  return cachedValue;
278
266
  }
279
267
  let parsedValue;
280
268
  const lowerCasedValue = asciiLowercase(val);
281
269
  if (GLOBAL_KEYS.has(lowerCasedValue)) {
282
- if (inArray) {
283
- parsedValue = [
284
- {
285
- type: AST_TYPES.GLOBAL_KEYWORD,
286
- name: lowerCasedValue
287
- }
288
- ];
289
- } else {
290
- parsedValue = lowerCasedValue;
291
- }
292
- } else if (SYS_COLORS.has(lowerCasedValue)) {
293
- if (/^(?:(?:-webkit-)?(?:[a-z][a-z\d]*-)*color|border)$/i.test(prop)) {
294
- if (inArray) {
295
- parsedValue = [
296
- {
297
- type: AST_TYPES.IDENTIFIER,
298
- name: lowerCasedValue
299
- }
300
- ];
301
- } else {
302
- parsedValue = lowerCasedValue;
270
+ parsedValue = [
271
+ {
272
+ type: AST_TYPES.GLOBAL_KEYWORD,
273
+ name: lowerCasedValue
303
274
  }
304
- } else {
305
- parsedValue = false;
306
- }
275
+ ];
307
276
  } else {
308
277
  try {
309
278
  const ast = parseCSS(val, {
@@ -312,9 +281,9 @@ const parsePropertyValue = (prop, val, opt = {}) => {
312
281
  const { error, matched } = cssTree.lexer.matchProperty(prop, ast);
313
282
  if (error || !matched) {
314
283
  parsedValue = false;
315
- } else if (inArray) {
316
- const obj = cssTree.toPlainObject(ast);
317
- const items = obj.children;
284
+ } else {
285
+ const items = ast.children;
286
+ const itemCount = items.size;
318
287
  const values = [];
319
288
  for (const item of items) {
320
289
  const { children, name, type, value, unit } = item;
@@ -328,48 +297,40 @@ const parsePropertyValue = (prop, val, opt = {}) => {
328
297
  break;
329
298
  }
330
299
  case AST_TYPES.FUNCTION: {
331
- const css = cssTree
332
- .generate(item)
333
- .replace(/\)(?!\)|\s|,)/g, ") ")
334
- .trim();
335
- const raw = items.length === 1 ? val : css;
300
+ const raw = itemCount === 1 ? val : cssTree.generate(item).replace(/\)(?!\)|\s|,)/g, ") ");
336
301
  // Remove "${name}(" from the start and ")" from the end
337
- const itemValue = raw.slice(name.length + 1, -1).trim();
302
+ const itemValue = raw.trim().slice(name.length + 1, -1);
338
303
  if (name === "calc") {
339
- if (children.length === 1) {
340
- const [child] = children;
304
+ if (children.size === 1) {
305
+ const child = children.first;
341
306
  if (child.type === AST_TYPES.NUMBER) {
342
307
  values.push({
343
308
  type: AST_TYPES.CALC,
344
- isNumber: true,
345
- value: `${parseFloat(child.value)}`,
346
309
  name,
347
- raw
310
+ isNumber: true,
311
+ value: `${parseFloat(child.value)}`
348
312
  });
349
313
  } else {
350
314
  values.push({
351
315
  type: AST_TYPES.CALC,
352
- isNumber: false,
353
- value: `${asciiLowercase(itemValue)}`,
354
316
  name,
355
- raw
317
+ isNumber: false,
318
+ value: asciiLowercase(itemValue)
356
319
  });
357
320
  }
358
321
  } else {
359
322
  values.push({
360
323
  type: AST_TYPES.CALC,
361
- isNumber: false,
362
- value: asciiLowercase(itemValue),
363
324
  name,
364
- raw
325
+ isNumber: false,
326
+ value: asciiLowercase(itemValue)
365
327
  });
366
328
  }
367
329
  } else {
368
330
  values.push({
369
331
  type,
370
332
  name,
371
- value: asciiLowercase(itemValue),
372
- raw
333
+ value: caseSensitive ? itemValue : asciiLowercase(itemValue)
373
334
  });
374
335
  }
375
336
  break;
@@ -391,8 +352,6 @@ const parsePropertyValue = (prop, val, opt = {}) => {
391
352
  }
392
353
  }
393
354
  parsedValue = values;
394
- } else {
395
- parsedValue = val;
396
355
  }
397
356
  } catch {
398
357
  parsedValue = false;
@@ -403,18 +362,18 @@ const parsePropertyValue = (prop, val, opt = {}) => {
403
362
  return;
404
363
  }
405
364
  return parsedValue;
406
- };
365
+ }
407
366
 
408
367
  /**
409
368
  * Parses a numeric value (number, dimension, percentage).
410
- * Helper function for parseNumber, parseLength, etc.
369
+ * Helper function for serializeNumber, serializeLength, etc.
411
370
  *
412
371
  * @param {Array<object>} val - The AST value.
413
372
  * @param {object} [opt={}] - The options for parsing.
414
373
  * @param {Function} validateType - Function to validate the node type.
415
374
  * @returns {object|undefined} The parsed result containing num and unit, or undefined.
416
375
  */
417
- const parseNumericValue = (val, opt, validateType) => {
376
+ function parseNumericValue(val, opt, validateType) {
418
377
  const [item] = val;
419
378
  const { type, value, unit } = item ?? {};
420
379
  if (!validateType(type, value, unit)) {
@@ -438,31 +397,31 @@ const parseNumericValue = (val, opt, validateType) => {
438
397
  unit: unit ? asciiLowercase(unit) : null,
439
398
  type
440
399
  };
441
- };
400
+ }
442
401
 
443
402
  /**
444
- * Parses a <number> value.
403
+ * Serializes a <number> value.
445
404
  *
446
405
  * @param {Array<object>} val - The AST value.
447
406
  * @param {object} [opt={}] - The options for parsing.
448
407
  * @returns {string|undefined} The parsed number.
449
408
  */
450
- const parseNumber = (val, opt = {}) => {
409
+ function serializeNumber(val, opt = {}) {
451
410
  const res = parseNumericValue(val, opt, (type) => type === AST_TYPES.NUMBER);
452
411
  if (!res) {
453
412
  return;
454
413
  }
455
414
  return `${res.num}`;
456
- };
415
+ }
457
416
 
458
417
  /**
459
- * Parses a <length> value.
418
+ * Serializes an <angle> value.
460
419
  *
461
420
  * @param {Array<object>} val - The AST value.
462
421
  * @param {object} [opt={}] - The options for parsing.
463
- * @returns {string|undefined} The parsed length.
422
+ * @returns {string|undefined} The serialized angle.
464
423
  */
465
- const parseLength = (val, opt = {}) => {
424
+ function serializeAngle(val, opt = {}) {
466
425
  const res = parseNumericValue(
467
426
  val,
468
427
  opt,
@@ -472,67 +431,85 @@ const parseLength = (val, opt = {}) => {
472
431
  return;
473
432
  }
474
433
  const { num, unit } = res;
475
- if (num === 0 && !unit) {
476
- return `${num}px`;
477
- } else if (unit) {
434
+ if (unit) {
435
+ if (!/^(?:deg|g?rad|turn)$/i.test(unit)) {
436
+ return;
437
+ }
478
438
  return `${num}${unit}`;
439
+ } else if (num === 0) {
440
+ return `${num}deg`;
479
441
  }
480
- };
442
+ }
481
443
 
482
444
  /**
483
- * Parses a <percentage> value.
445
+ * Serializes a <length> value.
484
446
  *
485
447
  * @param {Array<object>} val - The AST value.
486
448
  * @param {object} [opt={}] - The options for parsing.
487
- * @returns {string|undefined} The parsed percentage.
449
+ * @returns {string|undefined} The serialized length.
488
450
  */
489
- const parsePercentage = (val, opt = {}) => {
451
+ function serializeLength(val, opt = {}) {
490
452
  const res = parseNumericValue(
491
453
  val,
492
454
  opt,
493
- (type, value) => type === AST_TYPES.PERCENTAGE || (type === AST_TYPES.NUMBER && value === "0")
455
+ (type, value) => type === AST_TYPES.DIMENSION || (type === AST_TYPES.NUMBER && value === "0")
494
456
  );
495
457
  if (!res) {
496
458
  return;
497
459
  }
498
- const { num } = res;
499
- return `${num}%`;
500
- };
460
+ const { num, unit } = res;
461
+ if (num === 0 && !unit) {
462
+ return `${num}px`;
463
+ } else if (unit) {
464
+ return `${num}${unit}`;
465
+ }
466
+ }
501
467
 
502
468
  /**
503
- * Parses an <angle> value.
469
+ * Serializes a <dimension> value, e.g. <frequency>, <time> and <resolution>.
504
470
  *
505
471
  * @param {Array<object>} val - The AST value.
506
472
  * @param {object} [opt={}] - The options for parsing.
507
- * @returns {string|undefined} The parsed angle.
473
+ * @returns {string|undefined} The serialized dimension.
508
474
  */
509
- const parseAngle = (val, opt = {}) => {
510
- const res = parseNumericValue(
511
- val,
512
- opt,
513
- (type, value) => type === AST_TYPES.DIMENSION || (type === AST_TYPES.NUMBER && value === "0")
514
- );
475
+ function serializeDimension(val, opt = {}) {
476
+ const res = parseNumericValue(val, opt, (type) => type === AST_TYPES.DIMENSION);
515
477
  if (!res) {
516
478
  return;
517
479
  }
518
480
  const { num, unit } = res;
519
481
  if (unit) {
520
- if (!/^(?:deg|g?rad|turn)$/i.test(unit)) {
521
- return;
522
- }
523
482
  return `${num}${unit}`;
524
- } else if (num === 0) {
525
- return `${num}deg`;
526
483
  }
527
- };
484
+ }
485
+
486
+ /**
487
+ * Serializes a <percentage> value.
488
+ *
489
+ * @param {Array<object>} val - The AST value.
490
+ * @param {object} [opt={}] - The options for parsing.
491
+ * @returns {string|undefined} The serialized percentage.
492
+ */
493
+ function serializePercentage(val, opt = {}) {
494
+ const res = parseNumericValue(
495
+ val,
496
+ opt,
497
+ (type, value) => type === AST_TYPES.PERCENTAGE || (type === AST_TYPES.NUMBER && value === "0")
498
+ );
499
+ if (!res) {
500
+ return;
501
+ }
502
+ const { num } = res;
503
+ return `${num}%`;
504
+ }
528
505
 
529
506
  /**
530
- * Parses a <url> value.
507
+ * Serializes a <url> value.
531
508
  *
532
509
  * @param {Array<object>} val - The AST value.
533
- * @returns {string|undefined} The parsed url.
510
+ * @returns {string|undefined} The serialized url.
534
511
  */
535
- const parseUrl = (val) => {
512
+ function serializeURL(val) {
536
513
  const [item] = val;
537
514
  const { type, value } = item ?? {};
538
515
  if (type !== AST_TYPES.URL) {
@@ -540,15 +517,15 @@ const parseUrl = (val) => {
540
517
  }
541
518
  const str = value.replace(/\\\\/g, "\\").replaceAll('"', '\\"');
542
519
  return `url("${str}")`;
543
- };
520
+ }
544
521
 
545
522
  /**
546
- * Parses a <string> value.
523
+ * Serializes a <string> value.
547
524
  *
548
525
  * @param {Array<object>} val - The AST value.
549
- * @returns {string|undefined} The parsed string.
526
+ * @returns {string|undefined} The serialized string.
550
527
  */
551
- const parseString = (val) => {
528
+ function serializeString(val) {
552
529
  const [item] = val;
553
530
  const { type, value } = item ?? {};
554
531
  if (type !== AST_TYPES.STRING) {
@@ -556,15 +533,15 @@ const parseString = (val) => {
556
533
  }
557
534
  const str = value.replace(/\\\\/g, "\\").replaceAll('"', '\\"');
558
535
  return `"${str}"`;
559
- };
536
+ }
560
537
 
561
538
  /**
562
- * Parses a <color> value.
539
+ * Serializes a <color> value.
563
540
  *
564
541
  * @param {Array<object>} val - The AST value.
565
- * @returns {string|undefined} The parsed color.
542
+ * @returns {string|undefined} The serialized color.
566
543
  */
567
- const parseColor = (val) => {
544
+ function serializeColor(val) {
568
545
  const [item] = val;
569
546
  const { name, type, value } = item ?? {};
570
547
  switch (type) {
@@ -600,15 +577,15 @@ const parseColor = (val) => {
600
577
  }
601
578
  default:
602
579
  }
603
- };
580
+ }
604
581
 
605
582
  /**
606
- * Parses a <gradient> value.
583
+ * Serializes a <gradient> value.
607
584
  *
608
585
  * @param {Array<object>} val - The AST value.
609
- * @returns {string|undefined} The parsed gradient.
586
+ * @returns {string|undefined} The serialized gradient.
610
587
  */
611
- const parseGradient = (val) => {
588
+ function serializeGradient(val) {
612
589
  const [item] = val;
613
590
  const { name, type, value } = item ?? {};
614
591
  if (type !== AST_TYPES.FUNCTION) {
@@ -620,7 +597,7 @@ const parseGradient = (val) => {
620
597
  if (res) {
621
598
  return res;
622
599
  }
623
- };
600
+ }
624
601
 
625
602
  /**
626
603
  * Resolves a keyword value.
@@ -629,7 +606,7 @@ const parseGradient = (val) => {
629
606
  * @param {object} [opt={}] - The options for parsing.
630
607
  * @returns {string|undefined} The resolved keyword or undefined.
631
608
  */
632
- const resolveKeywordValue = (value, opt = {}) => {
609
+ function resolveKeywordValue(value, opt = {}) {
633
610
  const [{ name, type }] = value;
634
611
  const { length } = opt;
635
612
  switch (type) {
@@ -644,7 +621,7 @@ const resolveKeywordValue = (value, opt = {}) => {
644
621
  }
645
622
  default:
646
623
  }
647
- };
624
+ }
648
625
 
649
626
  /**
650
627
  * Resolves a function value.
@@ -653,7 +630,7 @@ const resolveKeywordValue = (value, opt = {}) => {
653
630
  * @param {object} [opt={}] - The options for parsing.
654
631
  * @returns {string|undefined} The resolved function or undefined.
655
632
  */
656
- const resolveFunctionValue = (value, opt = {}) => {
633
+ function resolveFunctionValue(value, opt = {}) {
657
634
  const [{ name, type, value: itemValue }] = value;
658
635
  const { length } = opt;
659
636
  switch (type) {
@@ -671,16 +648,16 @@ const resolveFunctionValue = (value, opt = {}) => {
671
648
  }
672
649
  default:
673
650
  }
674
- };
651
+ }
675
652
 
676
653
  /**
677
- * Resolves a length or percentage or number value.
654
+ * Resolves a numeric value.
678
655
  *
679
- * @param {Array<object>} value - The AST node array containing the value.
656
+ * @param {Array<object>} value - The AST node array containing the numeric value.
680
657
  * @param {object} [opt={}] - The options for parsing.
681
658
  * @returns {string|undefined} The resolved length/percentage/number or undefined.
682
659
  */
683
- const resolveNumericValue = (value, opt = {}) => {
660
+ function resolveNumericValue(value, opt = {}) {
684
661
  const [{ name, type: itemType, value: itemValue }] = value;
685
662
  const { length, type } = opt;
686
663
  switch (itemType) {
@@ -689,9 +666,11 @@ const resolveNumericValue = (value, opt = {}) => {
689
666
  }
690
667
  case AST_TYPES.DIMENSION: {
691
668
  if (type === "angle") {
692
- return parseAngle(value, opt);
669
+ return serializeAngle(value, opt);
670
+ } else if (type === "length") {
671
+ return serializeLength(value, opt);
693
672
  }
694
- return parseLength(value, opt);
673
+ return serializeDimension(value, opt);
695
674
  }
696
675
  case AST_TYPES.GLOBAL_KEYWORD: {
697
676
  if (length > 1) {
@@ -705,25 +684,25 @@ const resolveNumericValue = (value, opt = {}) => {
705
684
  case AST_TYPES.NUMBER: {
706
685
  switch (type) {
707
686
  case "angle": {
708
- return parseAngle(value, opt);
687
+ return serializeAngle(value, opt);
709
688
  }
710
689
  case "length": {
711
- return parseLength(value, opt);
690
+ return serializeLength(value, opt);
712
691
  }
713
692
  case "percentage": {
714
- return parsePercentage(value, opt);
693
+ return serializePercentage(value, opt);
715
694
  }
716
695
  default: {
717
- return parseNumber(value, opt);
696
+ return serializeNumber(value, opt);
718
697
  }
719
698
  }
720
699
  }
721
700
  case AST_TYPES.PERCENTAGE: {
722
- return parsePercentage(value, opt);
701
+ return serializePercentage(value, opt);
723
702
  }
724
703
  default:
725
704
  }
726
- };
705
+ }
727
706
 
728
707
  /**
729
708
  * Resolves a color value.
@@ -732,7 +711,7 @@ const resolveNumericValue = (value, opt = {}) => {
732
711
  * @param {object} [opt={}] - The options for parsing.
733
712
  * @returns {string|undefined} The resolved color or undefined.
734
713
  */
735
- const resolveColorValue = (value, opt = {}) => {
714
+ function resolveColorValue(value, opt = {}) {
736
715
  const [{ name, type }] = value;
737
716
  const { length } = opt;
738
717
  switch (type) {
@@ -743,19 +722,19 @@ const resolveColorValue = (value, opt = {}) => {
743
722
  return name;
744
723
  }
745
724
  default: {
746
- return parseColor(value, opt);
725
+ return serializeColor(value, opt);
747
726
  }
748
727
  }
749
- };
728
+ }
750
729
 
751
730
  /**
752
- * Resolves a gradient or URL value.
731
+ * Resolves an image value.
753
732
  *
754
- * @param {Array<object>} value - The AST node array containing the color value.
733
+ * @param {Array<object>} value - The AST node array containing the image value.
755
734
  * @param {object} [opt={}] - The options for parsing.
756
735
  * @returns {string|undefined} The resolved gradient/url or undefined.
757
736
  */
758
- const resolveGradientUrlValue = (value, opt = {}) => {
737
+ function resolveImageValue(value, opt = {}) {
759
738
  const [{ name, type }] = value;
760
739
  const { length } = opt;
761
740
  switch (type) {
@@ -769,13 +748,13 @@ const resolveGradientUrlValue = (value, opt = {}) => {
769
748
  return name;
770
749
  }
771
750
  case AST_TYPES.URL: {
772
- return parseUrl(value, opt);
751
+ return serializeURL(value, opt);
773
752
  }
774
753
  default: {
775
- return parseGradient(value, opt);
754
+ return serializeGradient(value, opt);
776
755
  }
777
756
  }
778
- };
757
+ }
779
758
 
780
759
  /**
781
760
  * Resolves a border shorthand value.
@@ -785,7 +764,7 @@ const resolveGradientUrlValue = (value, opt = {}) => {
785
764
  * @param {Map} parsedValues - The Map of parsed values.
786
765
  * @returns {Array|string|undefined} - The resolved [prop, value] pair, keyword or undefined.
787
766
  */
788
- const resolveBorderShorthandValue = (value, subProps, parsedValues) => {
767
+ function resolveBorderShorthandValue(value, subProps, parsedValues) {
789
768
  const [{ isNumber, name, type, value: itemValue }] = value;
790
769
  const { color: colorProp, style: styleProp, width: widthProp } = subProps;
791
770
  switch (type) {
@@ -800,7 +779,7 @@ const resolveBorderShorthandValue = (value, subProps, parsedValues) => {
800
779
  if (parsedValues.has(widthProp)) {
801
780
  return;
802
781
  }
803
- const parsedValue = parseLength(value, { min: 0 });
782
+ const parsedValue = serializeLength(value, { min: 0 });
804
783
  if (!parsedValue) {
805
784
  return;
806
785
  }
@@ -811,7 +790,7 @@ const resolveBorderShorthandValue = (value, subProps, parsedValues) => {
811
790
  if (parsedValues.has(colorProp)) {
812
791
  return;
813
792
  }
814
- const parsedValue = parseColor(value);
793
+ const parsedValue = serializeColor(value);
815
794
  if (!parsedValue) {
816
795
  return;
817
796
  }
@@ -841,7 +820,7 @@ const resolveBorderShorthandValue = (value, subProps, parsedValues) => {
841
820
  }
842
821
  default:
843
822
  }
844
- };
823
+ }
845
824
 
846
825
  module.exports = {
847
826
  AST_TYPES,
@@ -849,23 +828,24 @@ module.exports = {
849
828
  hasVarFunc,
850
829
  isGlobalKeyword,
851
830
  isValidPropertyValue,
852
- parseAngle,
853
831
  parseCSS,
854
- parseColor,
855
- parseGradient,
856
- parseLength,
857
- parseNumber,
858
- parsePercentage,
859
832
  parsePropertyValue,
860
- parseString,
861
- parseUrl,
862
833
  prepareValue,
863
834
  resolveBorderShorthandValue,
864
835
  resolveCalc,
865
836
  resolveColorValue,
866
837
  resolveFunctionValue,
867
- resolveGradientUrlValue,
838
+ resolveImageValue,
868
839
  resolveKeywordValue,
869
840
  resolveNumericValue,
841
+ serializeAngle,
842
+ serializeColor,
843
+ serializeDimension,
844
+ serializeGradient,
845
+ serializeLength,
846
+ serializeNumber,
847
+ serializePercentage,
848
+ serializeString,
849
+ serializeURL,
870
850
  splitValue
871
851
  };