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
141 changes: 81 additions & 60 deletions lib/parsers.js
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@ function parsePropertyValue(prop, val, opt = {}) {

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

/**
* Parses a <number> value.
* Serializes a <number> value.
*
* @param {Array<object>} val - The AST value.
* @param {object} [opt={}] - The options for parsing.
* @returns {string|undefined} The parsed number.
*/
function parseNumber(val, opt = {}) {
function serializeNumber(val, opt = {}) {
const res = parseNumericValue(val, opt, (type) => type === AST_TYPES.NUMBER);
if (!res) {
return;
Expand All @@ -423,13 +423,13 @@ function parseNumber(val, opt = {}) {
}

/**
* Parses a <length> value.
* Serializes an <angle> value.
*
* @param {Array<object>} val - The AST value.
* @param {object} [opt={}] - The options for parsing.
* @returns {string|undefined} The parsed length.
* @returns {string|undefined} The serialized angle.
*/
function parseLength(val, opt = {}) {
function serializeAngle(val, opt = {}) {
const res = parseNumericValue(
val,
opt,
Expand All @@ -439,67 +439,85 @@ function parseLength(val, opt = {}) {
return;
}
const { num, unit } = res;
if (num === 0 && !unit) {
return `${num}px`;
} else if (unit) {
if (unit) {
if (!/^(?:deg|g?rad|turn)$/i.test(unit)) {
return;
}
return `${num}${unit}`;
} else if (num === 0) {
return `${num}deg`;
}
}

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

/**
* Parses an <angle> value.
* Serializes a <dimension> value, e.g. <frequency>, <time> and <resolution>.
*
* @param {Array<object>} val - The AST value.
* @param {object} [opt={}] - The options for parsing.
* @returns {string|undefined} The parsed angle.
* @returns {string|undefined} The serialized dimension.
*/
function parseAngle(val, opt = {}) {
const res = parseNumericValue(
val,
opt,
(type, value) => type === AST_TYPES.DIMENSION || (type === AST_TYPES.NUMBER && value === "0")
);
function serializeDimension(val, opt = {}) {
const res = parseNumericValue(val, opt, (type) => type === AST_TYPES.DIMENSION);
if (!res) {
return;
}
const { num, unit } = res;
if (unit) {
if (!/^(?:deg|g?rad|turn)$/i.test(unit)) {
return;
}
return `${num}${unit}`;
} else if (num === 0) {
return `${num}deg`;
}
}

/**
* Parses a <url> value.
* Serializes a <percentage> value.
*
* @param {Array<object>} val - The AST value.
* @param {object} [opt={}] - The options for parsing.
* @returns {string|undefined} The serialized percentage.
*/
function serializePercentage(val, opt = {}) {
const res = parseNumericValue(
val,
opt,
(type, value) => type === AST_TYPES.PERCENTAGE || (type === AST_TYPES.NUMBER && value === "0")
);
if (!res) {
return;
}
const { num } = res;
return `${num}%`;
}

/**
* Serializes a <url> value.
*
* @param {Array<object>} val - The AST value.
* @returns {string|undefined} The parsed url.
* @returns {string|undefined} The serialized url.
*/
function parseUrl(val) {
function serializeURL(val) {
const [item] = val;
const { type, value } = item ?? {};
if (type !== AST_TYPES.URL) {
Expand All @@ -510,12 +528,12 @@ function parseUrl(val) {
}

/**
* Parses a <string> value.
* Serializes a <string> value.
*
* @param {Array<object>} val - The AST value.
* @returns {string|undefined} The parsed string.
* @returns {string|undefined} The serialized string.
*/
function parseString(val) {
function serializeString(val) {
const [item] = val;
const { type, value } = item ?? {};
if (type !== AST_TYPES.STRING) {
Expand All @@ -526,12 +544,12 @@ function parseString(val) {
}

/**
* Parses a <color> value.
* Serializes a <color> value.
*
* @param {Array<object>} val - The AST value.
* @returns {string|undefined} The parsed color.
* @returns {string|undefined} The serialized color.
*/
function parseColor(val) {
function serializeColor(val) {
const [item] = val;
const { name, type, value } = item ?? {};
switch (type) {
Expand Down Expand Up @@ -570,12 +588,12 @@ function parseColor(val) {
}

/**
* Parses a <gradient> value.
* Serializes a <gradient> value.
*
* @param {Array<object>} val - The AST value.
* @returns {string|undefined} The parsed gradient.
* @returns {string|undefined} The serialized gradient.
*/
function parseGradient(val) {
function serializeGradient(val) {
const [item] = val;
const { name, type, value } = item ?? {};
if (type !== AST_TYPES.FUNCTION) {
Expand Down Expand Up @@ -656,9 +674,11 @@ function resolveNumericValue(value, opt = {}) {
}
case AST_TYPES.DIMENSION: {
if (type === "angle") {
return parseAngle(value, opt);
return serializeAngle(value, opt);
} else if (type === "length") {
return serializeLength(value, opt);
}
return parseLength(value, opt);
return serializeDimension(value, opt);
}
case AST_TYPES.GLOBAL_KEYWORD: {
if (length > 1) {
Expand All @@ -672,21 +692,21 @@ function resolveNumericValue(value, opt = {}) {
case AST_TYPES.NUMBER: {
switch (type) {
case "angle": {
return parseAngle(value, opt);
return serializeAngle(value, opt);
}
case "length": {
return parseLength(value, opt);
return serializeLength(value, opt);
}
case "percentage": {
return parsePercentage(value, opt);
return serializePercentage(value, opt);
}
default: {
return parseNumber(value, opt);
return serializeNumber(value, opt);
}
}
}
case AST_TYPES.PERCENTAGE: {
return parsePercentage(value, opt);
return serializePercentage(value, opt);
}
default:
}
Expand All @@ -710,7 +730,7 @@ function resolveColorValue(value, opt = {}) {
return name;
}
default: {
return parseColor(value, opt);
return serializeColor(value, opt);
}
}
}
Expand All @@ -736,10 +756,10 @@ function resolveImageValue(value, opt = {}) {
return name;
}
case AST_TYPES.URL: {
return parseUrl(value, opt);
return serializeURL(value, opt);
}
default: {
return parseGradient(value, opt);
return serializeGradient(value, opt);
}
}
}
Expand Down Expand Up @@ -767,7 +787,7 @@ function resolveBorderShorthandValue(value, subProps, parsedValues) {
if (parsedValues.has(widthProp)) {
return;
}
const parsedValue = parseLength(value, { min: 0 });
const parsedValue = serializeLength(value, { min: 0 });
if (!parsedValue) {
return;
}
Expand All @@ -778,7 +798,7 @@ function resolveBorderShorthandValue(value, subProps, parsedValues) {
if (parsedValues.has(colorProp)) {
return;
}
const parsedValue = parseColor(value);
const parsedValue = serializeColor(value);
if (!parsedValue) {
return;
}
Expand Down Expand Up @@ -816,16 +836,8 @@ module.exports = {
hasVarFunc,
isGlobalKeyword,
isValidPropertyValue,
parseAngle,
parseCSS,
parseColor,
parseGradient,
parseLength,
parseNumber,
parsePercentage,
parsePropertyValue,
parseString,
parseUrl,
prepareValue,
resolveBorderShorthandValue,
resolveCalc,
Expand All @@ -834,5 +846,14 @@ module.exports = {
resolveImageValue,
resolveKeywordValue,
resolveNumericValue,
serializeAngle,
serializeColor,
serializeDimension,
serializeGradient,
serializeLength,
serializeNumber,
serializePercentage,
serializeString,
serializeURL,
splitValue
};
24 changes: 15 additions & 9 deletions lib/properties/backgroundPosition.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,21 @@ function parse(v) {
let parsedValue = "";
switch (value.length) {
case 1: {
const val1 =
part1.type === AST_TYPES.IDENTIFIER ? part1.name : parsers.resolveNumericValue([part1], { type: "length" });
if (val1) {
if (val1 === "center") {
parsedValue = `${val1} ${val1}`;
} else if (val1 === "top" || val1 === "bottom") {
parsedValue = `center ${val1}`;
} else {
parsedValue = `${val1} center`;
if (part1.type === AST_TYPES.GLOBAL_KEYWORD) {
parsedValue = part1.name;
} else {
const val1 =
part1.type === AST_TYPES.IDENTIFIER
? part1.name
: parsers.resolveNumericValue([part1], { type: "length" });
if (val1) {
if (val1 === "center") {
parsedValue = `${val1} ${val1}`;
} else if (val1 === "top" || val1 === "bottom") {
parsedValue = `center ${val1}`;
} else {
parsedValue = `${val1} center`;
}
}
}
break;
Expand Down
5 changes: 2 additions & 3 deletions lib/properties/backgroundRepeat.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,8 @@ function parse(v) {
switch (value.length) {
case 1: {
const [part1] = value;
const val1 = part1.type === AST_TYPES.IDENTIFIER && part1.name;
if (val1) {
parsedValue = val1;
if (part1.type === AST_TYPES.GLOBAL_KEYWORD || part1.type === AST_TYPES.IDENTIFIER) {
parsedValue = part1.name;
}
break;
}
Expand Down
Loading