Skip to content

Commit bde86d8

Browse files
authored
Extend generic property descriptor handling
* Integrate scripts/generate*.mjs scripts into scripts/prepare.mjs. * Add serializeDimension function in lib/parsers.js, and rename various parseX → serializeX. * Add handlers for various AST_TYPES in the generic property descriptors. * Fix bugs in properties/backgroundPosition.js and properties/backgroundRepeat.js handlers.
1 parent 256e277 commit bde86d8

10 files changed

Lines changed: 856 additions & 2547 deletions

lib/parsers.js

Lines changed: 81 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,7 @@ function parsePropertyValue(prop, val, opt = {}) {
374374

375375
/**
376376
* Parses a numeric value (number, dimension, percentage).
377-
* Helper function for parseNumber, parseLength, etc.
377+
* Helper function for serializeNumber, serializeLength, etc.
378378
*
379379
* @param {Array<object>} val - The AST value.
380380
* @param {object} [opt={}] - The options for parsing.
@@ -408,13 +408,13 @@ function parseNumericValue(val, opt, validateType) {
408408
}
409409

410410
/**
411-
* Parses a <number> value.
411+
* Serializes a <number> value.
412412
*
413413
* @param {Array<object>} val - The AST value.
414414
* @param {object} [opt={}] - The options for parsing.
415415
* @returns {string|undefined} The parsed number.
416416
*/
417-
function parseNumber(val, opt = {}) {
417+
function serializeNumber(val, opt = {}) {
418418
const res = parseNumericValue(val, opt, (type) => type === AST_TYPES.NUMBER);
419419
if (!res) {
420420
return;
@@ -423,13 +423,13 @@ function parseNumber(val, opt = {}) {
423423
}
424424

425425
/**
426-
* Parses a <length> value.
426+
* Serializes an <angle> value.
427427
*
428428
* @param {Array<object>} val - The AST value.
429429
* @param {object} [opt={}] - The options for parsing.
430-
* @returns {string|undefined} The parsed length.
430+
* @returns {string|undefined} The serialized angle.
431431
*/
432-
function parseLength(val, opt = {}) {
432+
function serializeAngle(val, opt = {}) {
433433
const res = parseNumericValue(
434434
val,
435435
opt,
@@ -439,67 +439,85 @@ function parseLength(val, opt = {}) {
439439
return;
440440
}
441441
const { num, unit } = res;
442-
if (num === 0 && !unit) {
443-
return `${num}px`;
444-
} else if (unit) {
442+
if (unit) {
443+
if (!/^(?:deg|g?rad|turn)$/i.test(unit)) {
444+
return;
445+
}
445446
return `${num}${unit}`;
447+
} else if (num === 0) {
448+
return `${num}deg`;
446449
}
447450
}
448451

449452
/**
450-
* Parses a <percentage> value.
453+
* Serializes a <length> value.
451454
*
452455
* @param {Array<object>} val - The AST value.
453456
* @param {object} [opt={}] - The options for parsing.
454-
* @returns {string|undefined} The parsed percentage.
457+
* @returns {string|undefined} The serialized length.
455458
*/
456-
function parsePercentage(val, opt = {}) {
459+
function serializeLength(val, opt = {}) {
457460
const res = parseNumericValue(
458461
val,
459462
opt,
460-
(type, value) => type === AST_TYPES.PERCENTAGE || (type === AST_TYPES.NUMBER && value === "0")
463+
(type, value) => type === AST_TYPES.DIMENSION || (type === AST_TYPES.NUMBER && value === "0")
461464
);
462465
if (!res) {
463466
return;
464467
}
465-
const { num } = res;
466-
return `${num}%`;
468+
const { num, unit } = res;
469+
if (num === 0 && !unit) {
470+
return `${num}px`;
471+
} else if (unit) {
472+
return `${num}${unit}`;
473+
}
467474
}
468475

469476
/**
470-
* Parses an <angle> value.
477+
* Serializes a <dimension> value, e.g. <frequency>, <time> and <resolution>.
471478
*
472479
* @param {Array<object>} val - The AST value.
473480
* @param {object} [opt={}] - The options for parsing.
474-
* @returns {string|undefined} The parsed angle.
481+
* @returns {string|undefined} The serialized dimension.
475482
*/
476-
function parseAngle(val, opt = {}) {
477-
const res = parseNumericValue(
478-
val,
479-
opt,
480-
(type, value) => type === AST_TYPES.DIMENSION || (type === AST_TYPES.NUMBER && value === "0")
481-
);
483+
function serializeDimension(val, opt = {}) {
484+
const res = parseNumericValue(val, opt, (type) => type === AST_TYPES.DIMENSION);
482485
if (!res) {
483486
return;
484487
}
485488
const { num, unit } = res;
486489
if (unit) {
487-
if (!/^(?:deg|g?rad|turn)$/i.test(unit)) {
488-
return;
489-
}
490490
return `${num}${unit}`;
491-
} else if (num === 0) {
492-
return `${num}deg`;
493491
}
494492
}
495493

496494
/**
497-
* Parses a <url> value.
495+
* Serializes a <percentage> value.
496+
*
497+
* @param {Array<object>} val - The AST value.
498+
* @param {object} [opt={}] - The options for parsing.
499+
* @returns {string|undefined} The serialized percentage.
500+
*/
501+
function serializePercentage(val, opt = {}) {
502+
const res = parseNumericValue(
503+
val,
504+
opt,
505+
(type, value) => type === AST_TYPES.PERCENTAGE || (type === AST_TYPES.NUMBER && value === "0")
506+
);
507+
if (!res) {
508+
return;
509+
}
510+
const { num } = res;
511+
return `${num}%`;
512+
}
513+
514+
/**
515+
* Serializes a <url> value.
498516
*
499517
* @param {Array<object>} val - The AST value.
500-
* @returns {string|undefined} The parsed url.
518+
* @returns {string|undefined} The serialized url.
501519
*/
502-
function parseUrl(val) {
520+
function serializeURL(val) {
503521
const [item] = val;
504522
const { type, value } = item ?? {};
505523
if (type !== AST_TYPES.URL) {
@@ -510,12 +528,12 @@ function parseUrl(val) {
510528
}
511529

512530
/**
513-
* Parses a <string> value.
531+
* Serializes a <string> value.
514532
*
515533
* @param {Array<object>} val - The AST value.
516-
* @returns {string|undefined} The parsed string.
534+
* @returns {string|undefined} The serialized string.
517535
*/
518-
function parseString(val) {
536+
function serializeString(val) {
519537
const [item] = val;
520538
const { type, value } = item ?? {};
521539
if (type !== AST_TYPES.STRING) {
@@ -526,12 +544,12 @@ function parseString(val) {
526544
}
527545

528546
/**
529-
* Parses a <color> value.
547+
* Serializes a <color> value.
530548
*
531549
* @param {Array<object>} val - The AST value.
532-
* @returns {string|undefined} The parsed color.
550+
* @returns {string|undefined} The serialized color.
533551
*/
534-
function parseColor(val) {
552+
function serializeColor(val) {
535553
const [item] = val;
536554
const { name, type, value } = item ?? {};
537555
switch (type) {
@@ -570,12 +588,12 @@ function parseColor(val) {
570588
}
571589

572590
/**
573-
* Parses a <gradient> value.
591+
* Serializes a <gradient> value.
574592
*
575593
* @param {Array<object>} val - The AST value.
576-
* @returns {string|undefined} The parsed gradient.
594+
* @returns {string|undefined} The serialized gradient.
577595
*/
578-
function parseGradient(val) {
596+
function serializeGradient(val) {
579597
const [item] = val;
580598
const { name, type, value } = item ?? {};
581599
if (type !== AST_TYPES.FUNCTION) {
@@ -656,9 +674,11 @@ function resolveNumericValue(value, opt = {}) {
656674
}
657675
case AST_TYPES.DIMENSION: {
658676
if (type === "angle") {
659-
return parseAngle(value, opt);
677+
return serializeAngle(value, opt);
678+
} else if (type === "length") {
679+
return serializeLength(value, opt);
660680
}
661-
return parseLength(value, opt);
681+
return serializeDimension(value, opt);
662682
}
663683
case AST_TYPES.GLOBAL_KEYWORD: {
664684
if (length > 1) {
@@ -672,21 +692,21 @@ function resolveNumericValue(value, opt = {}) {
672692
case AST_TYPES.NUMBER: {
673693
switch (type) {
674694
case "angle": {
675-
return parseAngle(value, opt);
695+
return serializeAngle(value, opt);
676696
}
677697
case "length": {
678-
return parseLength(value, opt);
698+
return serializeLength(value, opt);
679699
}
680700
case "percentage": {
681-
return parsePercentage(value, opt);
701+
return serializePercentage(value, opt);
682702
}
683703
default: {
684-
return parseNumber(value, opt);
704+
return serializeNumber(value, opt);
685705
}
686706
}
687707
}
688708
case AST_TYPES.PERCENTAGE: {
689-
return parsePercentage(value, opt);
709+
return serializePercentage(value, opt);
690710
}
691711
default:
692712
}
@@ -710,7 +730,7 @@ function resolveColorValue(value, opt = {}) {
710730
return name;
711731
}
712732
default: {
713-
return parseColor(value, opt);
733+
return serializeColor(value, opt);
714734
}
715735
}
716736
}
@@ -736,10 +756,10 @@ function resolveImageValue(value, opt = {}) {
736756
return name;
737757
}
738758
case AST_TYPES.URL: {
739-
return parseUrl(value, opt);
759+
return serializeURL(value, opt);
740760
}
741761
default: {
742-
return parseGradient(value, opt);
762+
return serializeGradient(value, opt);
743763
}
744764
}
745765
}
@@ -767,7 +787,7 @@ function resolveBorderShorthandValue(value, subProps, parsedValues) {
767787
if (parsedValues.has(widthProp)) {
768788
return;
769789
}
770-
const parsedValue = parseLength(value, { min: 0 });
790+
const parsedValue = serializeLength(value, { min: 0 });
771791
if (!parsedValue) {
772792
return;
773793
}
@@ -778,7 +798,7 @@ function resolveBorderShorthandValue(value, subProps, parsedValues) {
778798
if (parsedValues.has(colorProp)) {
779799
return;
780800
}
781-
const parsedValue = parseColor(value);
801+
const parsedValue = serializeColor(value);
782802
if (!parsedValue) {
783803
return;
784804
}
@@ -816,16 +836,8 @@ module.exports = {
816836
hasVarFunc,
817837
isGlobalKeyword,
818838
isValidPropertyValue,
819-
parseAngle,
820839
parseCSS,
821-
parseColor,
822-
parseGradient,
823-
parseLength,
824-
parseNumber,
825-
parsePercentage,
826840
parsePropertyValue,
827-
parseString,
828-
parseUrl,
829841
prepareValue,
830842
resolveBorderShorthandValue,
831843
resolveCalc,
@@ -834,5 +846,14 @@ module.exports = {
834846
resolveImageValue,
835847
resolveKeywordValue,
836848
resolveNumericValue,
849+
serializeAngle,
850+
serializeColor,
851+
serializeDimension,
852+
serializeGradient,
853+
serializeLength,
854+
serializeNumber,
855+
serializePercentage,
856+
serializeString,
857+
serializeURL,
837858
splitValue
838859
};

lib/properties/backgroundPosition.js

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -56,15 +56,21 @@ function parse(v) {
5656
let parsedValue = "";
5757
switch (value.length) {
5858
case 1: {
59-
const val1 =
60-
part1.type === AST_TYPES.IDENTIFIER ? part1.name : parsers.resolveNumericValue([part1], { type: "length" });
61-
if (val1) {
62-
if (val1 === "center") {
63-
parsedValue = `${val1} ${val1}`;
64-
} else if (val1 === "top" || val1 === "bottom") {
65-
parsedValue = `center ${val1}`;
66-
} else {
67-
parsedValue = `${val1} center`;
59+
if (part1.type === AST_TYPES.GLOBAL_KEYWORD) {
60+
parsedValue = part1.name;
61+
} else {
62+
const val1 =
63+
part1.type === AST_TYPES.IDENTIFIER
64+
? part1.name
65+
: parsers.resolveNumericValue([part1], { type: "length" });
66+
if (val1) {
67+
if (val1 === "center") {
68+
parsedValue = `${val1} ${val1}`;
69+
} else if (val1 === "top" || val1 === "bottom") {
70+
parsedValue = `center ${val1}`;
71+
} else {
72+
parsedValue = `${val1} center`;
73+
}
6874
}
6975
}
7076
break;

lib/properties/backgroundRepeat.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,8 @@ function parse(v) {
5151
switch (value.length) {
5252
case 1: {
5353
const [part1] = value;
54-
const val1 = part1.type === AST_TYPES.IDENTIFIER && part1.name;
55-
if (val1) {
56-
parsedValue = val1;
54+
if (part1.type === AST_TYPES.GLOBAL_KEYWORD || part1.type === AST_TYPES.IDENTIFIER) {
55+
parsedValue = part1.name;
5756
}
5857
break;
5958
}

0 commit comments

Comments
 (0)