Skip to content

Commit c06fbab

Browse files
asamuzaKdomenic
authored andcommitted
Add resolvers and apply to properties/*.js
1 parent 3705035 commit c06fbab

79 files changed

Lines changed: 661 additions & 1549 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

lib/parsers.js

Lines changed: 240 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@ const SYS_COLORS = new Set([
6161
]);
6262

6363
// AST node types
64-
// TODO: Export and use in properties/*.js in the future
6564
const AST_TYPES = Object.freeze({
6665
CALC: "Calc",
6766
DIMENSION: "Dimension",
@@ -483,38 +482,6 @@ const parsePercentage = (val, opt = {}) => {
483482
return `${num}%`;
484483
};
485484

486-
/**
487-
* Parses a <length-percentage> value.
488-
*
489-
* @param {Array<object>} val - The AST value.
490-
* @param {object} [opt={}] - The options for parsing.
491-
* @returns {string|undefined} The parsed length-percentage.
492-
*/
493-
const parseLengthPercentage = (val, opt = {}) => {
494-
const res = parseNumericValue(
495-
val,
496-
opt,
497-
(type, value) =>
498-
type === AST_TYPES.DIMENSION ||
499-
type === AST_TYPES.PERCENTAGE ||
500-
(type === AST_TYPES.NUMBER && value === "0")
501-
);
502-
if (!res) {
503-
return;
504-
}
505-
const { num, unit, type } = res;
506-
if (unit) {
507-
if (/deg|g?rad|turn/i.test(unit)) {
508-
return;
509-
}
510-
return `${num}${unit}`;
511-
} else if (type === AST_TYPES.PERCENTAGE) {
512-
return `${num}%`;
513-
} else if (num === 0) {
514-
return `${num}px`;
515-
}
516-
};
517-
518485
/**
519486
* Parses an <angle> value.
520487
*
@@ -638,23 +605,250 @@ const parseGradient = (val) => {
638605
}
639606
};
640607

608+
/**
609+
* Resolves a keyword value.
610+
*
611+
* @param {Array<object>} value - The AST node array containing the keyword value.
612+
* @param {object} [opt={}] - The options for parsing.
613+
* @returns {string|undefined} The resolved keyword or undefined.
614+
*/
615+
const resolveKeywordValue = (value, opt = {}) => {
616+
const [{ name, type }] = value;
617+
const { length } = opt;
618+
switch (type) {
619+
case AST_TYPES.GLOBAL_KEYWORD: {
620+
if (length > 1) {
621+
return;
622+
}
623+
return name;
624+
}
625+
case AST_TYPES.IDENTIFIER: {
626+
return name;
627+
}
628+
default:
629+
}
630+
};
631+
632+
/**
633+
* Resolves a function value.
634+
*
635+
* @param {Array<object>} value - The AST node array containing the function value.
636+
* @param {object} [opt={}] - The options for parsing.
637+
* @returns {string|undefined} The resolved function or undefined.
638+
*/
639+
const resolveFunctionValue = (value, opt = {}) => {
640+
const [{ name, type, value: itemValue }] = value;
641+
const { length } = opt;
642+
switch (type) {
643+
case AST_TYPES.FUNCTION: {
644+
return `${name}(${itemValue})`;
645+
}
646+
case AST_TYPES.GLOBAL_KEYWORD: {
647+
if (length > 1) {
648+
return;
649+
}
650+
return name;
651+
}
652+
case AST_TYPES.IDENTIFIER: {
653+
return name;
654+
}
655+
default:
656+
}
657+
};
658+
659+
/**
660+
* Resolves a length or percentage or number value.
661+
*
662+
* @param {Array<object>} value - The AST node array containing the value.
663+
* @param {object} [opt={}] - The options for parsing.
664+
* @returns {string|undefined} The resolved length/percentage/number or undefined.
665+
*/
666+
const resolveNumericValue = (value, opt = {}) => {
667+
const [{ name, type: itemType, value: itemValue }] = value;
668+
const { length, type } = opt;
669+
switch (itemType) {
670+
case AST_TYPES.CALC: {
671+
return `${name}(${itemValue})`;
672+
}
673+
case AST_TYPES.DIMENSION: {
674+
if (type === "angle") {
675+
return parseAngle(value, opt);
676+
}
677+
return parseLength(value, opt);
678+
}
679+
case AST_TYPES.GLOBAL_KEYWORD: {
680+
if (length > 1) {
681+
return;
682+
}
683+
return name;
684+
}
685+
case AST_TYPES.IDENTIFIER: {
686+
return name;
687+
}
688+
case AST_TYPES.NUMBER: {
689+
switch (type) {
690+
case "angle": {
691+
return parseAngle(value, opt);
692+
}
693+
case "length": {
694+
return parseLength(value, opt);
695+
}
696+
case "percentage": {
697+
return parsePercentage(value, opt);
698+
}
699+
default: {
700+
return parseNumber(value, opt);
701+
}
702+
}
703+
}
704+
case AST_TYPES.PERCENTAGE: {
705+
return parsePercentage(value, opt);
706+
}
707+
default:
708+
}
709+
};
710+
711+
/**
712+
* Resolves a color value.
713+
*
714+
* @param {Array<object>} value - The AST node array containing the color value.
715+
* @param {object} [opt={}] - The options for parsing.
716+
* @returns {string|undefined} The resolved color or undefined.
717+
*/
718+
const resolveColorValue = (value, opt = {}) => {
719+
const [{ name, type }] = value;
720+
const { length } = opt;
721+
switch (type) {
722+
case AST_TYPES.GLOBAL_KEYWORD: {
723+
if (length > 1) {
724+
return;
725+
}
726+
return name;
727+
}
728+
default: {
729+
return parseColor(value, opt);
730+
}
731+
}
732+
};
733+
734+
/**
735+
* Resolves a gradient or URL value.
736+
*
737+
* @param {Array<object>} value - The AST node array containing the color value.
738+
* @param {object} [opt={}] - The options for parsing.
739+
* @returns {string|undefined} The resolved gradient/url or undefined.
740+
*/
741+
const resolveGradientUrlValue = (value, opt = {}) => {
742+
const [{ name, type }] = value;
743+
const { length } = opt;
744+
switch (type) {
745+
case AST_TYPES.GLOBAL_KEYWORD: {
746+
if (length > 1) {
747+
return;
748+
}
749+
return name;
750+
}
751+
case AST_TYPES.IDENTIFIER: {
752+
return name;
753+
}
754+
case AST_TYPES.URL: {
755+
return parseUrl(value, opt);
756+
}
757+
default: {
758+
return parseGradient(value, opt);
759+
}
760+
}
761+
};
762+
763+
/**
764+
* Resolves a border shorthand value.
765+
*
766+
* @param {Array<object>} value - The AST node array containing the shorthand value.
767+
* @param {object} subProps - The sub properties object.
768+
* @param {Map} parsedValues - The Map of parsed values.
769+
* @returns {Array|string|undefined} - The resolved [prop, value] pair, keyword or undefined.
770+
*/
771+
const resolveBorderShorthandValue = (value, subProps, parsedValues) => {
772+
const [{ isNumber, name, type, value: itemValue }] = value;
773+
const { color: colorProp, style: styleProp, width: widthProp } = subProps;
774+
switch (type) {
775+
case AST_TYPES.CALC: {
776+
if (isNumber || parsedValues.has(widthProp)) {
777+
return;
778+
}
779+
return [widthProp, `${name}(${itemValue}`];
780+
}
781+
case AST_TYPES.DIMENSION:
782+
case AST_TYPES.NUMBER: {
783+
if (parsedValues.has(widthProp)) {
784+
return;
785+
}
786+
const parsedValue = parseLength(value, { min: 0 });
787+
if (!parsedValue) {
788+
return;
789+
}
790+
return [widthProp, parsedValue];
791+
}
792+
case AST_TYPES.FUNCTION:
793+
case AST_TYPES.HASH: {
794+
if (parsedValues.has(colorProp)) {
795+
return;
796+
}
797+
const parsedValue = parseColor(value);
798+
if (!parsedValue) {
799+
return;
800+
}
801+
return [colorProp, parsedValue];
802+
}
803+
case AST_TYPES.GLOBAL_KEYWORD: {
804+
return name;
805+
}
806+
case AST_TYPES.IDENTIFIER: {
807+
if (isValidPropertyValue(widthProp, name)) {
808+
if (parsedValues.has(widthProp)) {
809+
return;
810+
}
811+
return [widthProp, name];
812+
} else if (isValidPropertyValue(styleProp, name)) {
813+
if (parsedValues.has(styleProp)) {
814+
return;
815+
}
816+
return [styleProp, name];
817+
} else if (isValidPropertyValue(colorProp, name)) {
818+
if (parsedValues.has(colorProp)) {
819+
return;
820+
}
821+
return [colorProp, name];
822+
}
823+
break;
824+
}
825+
default:
826+
}
827+
};
828+
641829
module.exports = {
642-
prepareValue,
643-
isGlobalKeyword,
644-
hasVarFunc,
830+
AST_TYPES,
645831
hasCalcFunc,
646-
splitValue,
647-
parseCSS,
832+
hasVarFunc,
833+
isGlobalKeyword,
648834
isValidPropertyValue,
649-
resolveCalc,
650-
parsePropertyValue,
651-
parseNumber,
835+
parseAngle,
836+
parseCSS,
837+
parseColor,
838+
parseGradient,
652839
parseLength,
840+
parseNumber,
653841
parsePercentage,
654-
parseLengthPercentage,
655-
parseAngle,
656-
parseUrl,
842+
parsePropertyValue,
657843
parseString,
658-
parseColor,
659-
parseGradient
844+
parseUrl,
845+
prepareValue,
846+
resolveBorderShorthandValue,
847+
resolveCalc,
848+
resolveColorValue,
849+
resolveFunctionValue,
850+
resolveGradientUrlValue,
851+
resolveKeywordValue,
852+
resolveNumericValue,
853+
splitValue
660854
};

lib/properties/background.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ module.exports.shorthandFor = new Map([
3434
[backgroundColor.property, backgroundColor]
3535
]);
3636

37-
module.exports.parse = function parse(v, opt = {}) {
37+
module.exports.parse = (v, opt = {}) => {
3838
const { globalObject } = opt;
3939
if (v === "") {
4040
return v;

lib/properties/backgroundAttachment.js

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ const parsers = require("../parsers");
55
const property = "background-attachment";
66
const shorthand = "background";
77

8-
module.exports.parse = function parse(v, opt = {}) {
8+
module.exports.parse = (v, opt = {}) => {
99
const { globalObject } = opt;
1010
if (v === "") {
1111
return v;
@@ -18,17 +18,11 @@ module.exports.parse = function parse(v, opt = {}) {
1818
inArray: true
1919
});
2020
if (Array.isArray(value) && value.length === 1) {
21-
const [{ name, type }] = value;
22-
switch (type) {
23-
case "GlobalKeyword":
24-
case "Identifier": {
25-
parsedValues.push(name);
26-
break;
27-
}
28-
default: {
29-
return;
30-
}
21+
const parsedValue = parsers.resolveKeywordValue(value);
22+
if (!parsedValue) {
23+
return;
3124
}
25+
parsedValues.push(parsedValue);
3226
} else if (typeof value === "string") {
3327
parsedValues.push(value);
3428
}

lib/properties/backgroundClip.js

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ const parsers = require("../parsers");
55
const property = "background-clip";
66
const shorthand = "background";
77

8-
module.exports.parse = function parse(v, opt = {}) {
8+
module.exports.parse = (v, opt = {}) => {
99
const { globalObject } = opt;
1010
if (v === "") {
1111
return v;
@@ -18,17 +18,11 @@ module.exports.parse = function parse(v, opt = {}) {
1818
inArray: true
1919
});
2020
if (Array.isArray(value) && value.length === 1) {
21-
const [{ name, type }] = value;
22-
switch (type) {
23-
case "GlobalKeyword":
24-
case "Identifier": {
25-
parsedValues.push(name);
26-
break;
27-
}
28-
default: {
29-
return;
30-
}
21+
const parsedValue = parsers.resolveKeywordValue(value);
22+
if (!parsedValue) {
23+
return;
3124
}
25+
parsedValues.push(parsedValue);
3226
} else if (typeof value === "string") {
3327
parsedValues.push(value);
3428
}

0 commit comments

Comments
 (0)