Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
286 changes: 240 additions & 46 deletions lib/parsers.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ const SYS_COLORS = new Set([
]);

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

/**
* Parses a <length-percentage> value.
*
* @param {Array<object>} val - The AST value.
* @param {object} [opt={}] - The options for parsing.
* @returns {string|undefined} The parsed length-percentage.
*/
const parseLengthPercentage = (val, opt = {}) => {
const res = parseNumericValue(
val,
opt,
(type, value) =>
type === AST_TYPES.DIMENSION ||
type === AST_TYPES.PERCENTAGE ||
(type === AST_TYPES.NUMBER && value === "0")
);
if (!res) {
return;
}
const { num, unit, type } = res;
if (unit) {
if (/deg|g?rad|turn/i.test(unit)) {
return;
}
return `${num}${unit}`;
} else if (type === AST_TYPES.PERCENTAGE) {
return `${num}%`;
} else if (num === 0) {
return `${num}px`;
}
};

/**
* Parses an <angle> value.
*
Expand Down Expand Up @@ -638,23 +605,250 @@ const parseGradient = (val) => {
}
};

/**
* Resolves a keyword value.
*
* @param {Array<object>} value - The AST node array containing the keyword value.
* @param {object} [opt={}] - The options for parsing.
* @returns {string|undefined} The resolved keyword or undefined.
*/
const resolveKeywordValue = (value, opt = {}) => {
const [{ name, type }] = value;
const { length } = opt;
switch (type) {
case AST_TYPES.GLOBAL_KEYWORD: {
if (length > 1) {
return;
}
return name;
}
case AST_TYPES.IDENTIFIER: {
return name;
}
default:
}
};

/**
* Resolves a function value.
*
* @param {Array<object>} value - The AST node array containing the function value.
* @param {object} [opt={}] - The options for parsing.
* @returns {string|undefined} The resolved function or undefined.
*/
const resolveFunctionValue = (value, opt = {}) => {
const [{ name, type, value: itemValue }] = value;
const { length } = opt;
switch (type) {
case AST_TYPES.FUNCTION: {
return `${name}(${itemValue})`;
}
case AST_TYPES.GLOBAL_KEYWORD: {
if (length > 1) {
return;
}
return name;
}
case AST_TYPES.IDENTIFIER: {
return name;
}
default:
}
};

/**
* Resolves a length or percentage or number value.
*
* @param {Array<object>} value - The AST node array containing the value.
* @param {object} [opt={}] - The options for parsing.
* @returns {string|undefined} The resolved length/percentage/number or undefined.
*/
const resolveNumericValue = (value, opt = {}) => {
const [{ name, type: itemType, value: itemValue }] = value;
const { length, type } = opt;
switch (itemType) {
case AST_TYPES.CALC: {
return `${name}(${itemValue})`;
}
case AST_TYPES.DIMENSION: {
if (type === "angle") {
return parseAngle(value, opt);
}
return parseLength(value, opt);
}
case AST_TYPES.GLOBAL_KEYWORD: {
if (length > 1) {
return;
}
return name;
}
case AST_TYPES.IDENTIFIER: {
return name;
}
case AST_TYPES.NUMBER: {
switch (type) {
case "angle": {
return parseAngle(value, opt);
}
case "length": {
return parseLength(value, opt);
}
case "percentage": {
return parsePercentage(value, opt);
}
default: {
return parseNumber(value, opt);
}
}
}
case AST_TYPES.PERCENTAGE: {
return parsePercentage(value, opt);
}
default:
}
};

/**
* Resolves a color value.
*
* @param {Array<object>} value - The AST node array containing the color value.
* @param {object} [opt={}] - The options for parsing.
* @returns {string|undefined} The resolved color or undefined.
*/
const resolveColorValue = (value, opt = {}) => {
const [{ name, type }] = value;
const { length } = opt;
switch (type) {
case AST_TYPES.GLOBAL_KEYWORD: {
if (length > 1) {
return;
}
return name;
}
default: {
return parseColor(value, opt);
}
}
};

/**
* Resolves a gradient or URL value.
*
* @param {Array<object>} value - The AST node array containing the color value.
* @param {object} [opt={}] - The options for parsing.
* @returns {string|undefined} The resolved gradient/url or undefined.
*/
const resolveGradientUrlValue = (value, opt = {}) => {
const [{ name, type }] = value;
const { length } = opt;
switch (type) {
case AST_TYPES.GLOBAL_KEYWORD: {
if (length > 1) {
return;
}
return name;
}
case AST_TYPES.IDENTIFIER: {
return name;
}
case AST_TYPES.URL: {
return parseUrl(value, opt);
}
default: {
return parseGradient(value, opt);
}
}
};

/**
* Resolves a border shorthand value.
*
* @param {Array<object>} value - The AST node array containing the shorthand value.
* @param {object} subProps - The sub properties object.
* @param {Map} parsedValues - The Map of parsed values.
* @returns {Array|string|undefined} - The resolved [prop, value] pair, keyword or undefined.
*/
const resolveBorderShorthandValue = (value, subProps, parsedValues) => {
const [{ isNumber, name, type, value: itemValue }] = value;
const { color: colorProp, style: styleProp, width: widthProp } = subProps;
switch (type) {
case AST_TYPES.CALC: {
if (isNumber || parsedValues.has(widthProp)) {
return;
}
return [widthProp, `${name}(${itemValue}`];
}
case AST_TYPES.DIMENSION:
case AST_TYPES.NUMBER: {
if (parsedValues.has(widthProp)) {
return;
}
const parsedValue = parseLength(value, { min: 0 });
if (!parsedValue) {
return;
}
return [widthProp, parsedValue];
}
case AST_TYPES.FUNCTION:
case AST_TYPES.HASH: {
if (parsedValues.has(colorProp)) {
return;
}
const parsedValue = parseColor(value);
if (!parsedValue) {
return;
}
return [colorProp, parsedValue];
}
case AST_TYPES.GLOBAL_KEYWORD: {
return name;
}
case AST_TYPES.IDENTIFIER: {
if (isValidPropertyValue(widthProp, name)) {
if (parsedValues.has(widthProp)) {
return;
}
return [widthProp, name];
} else if (isValidPropertyValue(styleProp, name)) {
if (parsedValues.has(styleProp)) {
return;
}
return [styleProp, name];
} else if (isValidPropertyValue(colorProp, name)) {
if (parsedValues.has(colorProp)) {
return;
}
return [colorProp, name];
}
break;
}
default:
}
};

module.exports = {
prepareValue,
isGlobalKeyword,
hasVarFunc,
AST_TYPES,
hasCalcFunc,
splitValue,
parseCSS,
hasVarFunc,
isGlobalKeyword,
isValidPropertyValue,
resolveCalc,
parsePropertyValue,
parseNumber,
parseAngle,
parseCSS,
parseColor,
parseGradient,
parseLength,
parseNumber,
parsePercentage,
parseLengthPercentage,
parseAngle,
parseUrl,
parsePropertyValue,
parseString,
parseColor,
parseGradient
parseUrl,
prepareValue,
resolveBorderShorthandValue,
resolveCalc,
resolveColorValue,
resolveFunctionValue,
resolveGradientUrlValue,
resolveKeywordValue,
resolveNumericValue,
splitValue
};
Loading