UNPKG

@wix/css-property-parser

Version:

A comprehensive TypeScript library for parsing and serializing CSS property values with full MDN specification compliance

88 lines (87 loc) 3.01 kB
// CSS Variable (Custom Property) data type parser // Handles parsing of CSS custom properties according to MDN specification // https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties // CSS variable pattern - var(--property-name) or var(--property-name, fallback) const CSS_VARIABLE_REGEX = /^var\(\s*(--[a-zA-Z0-9_-]+)\s*(?:,\s*(.+?))?\s*\)$/i; /** * Normalizes a CSS variable fallback value by recursively parsing CSS variables * @param fallback - The fallback value to normalize * @returns Normalized fallback value */ function normalizeFallback(fallback) { const trimmed = fallback.trim(); // If it looks like a CSS variable, parse and re-serialize it to normalize whitespace if (trimmed.startsWith('var(')) { const parsed = parse(trimmed); if (parsed) { const normalized = toCSSValue(parsed); if (normalized) { return normalized; } } } return trimmed; } /** * Parses a CSS variable (custom property) value into structured components * @param input - The CSS variable string * @returns Parsed CSS variable object or null if invalid */ export function parse(input) { if (!input || typeof input !== 'string') { return null; } const trimmed = input.trim(); // Match CSS variable pattern const match = trimmed.match(CSS_VARIABLE_REGEX); if (!match) { return null; } const [, propertyName, fallback] = match; // Validate property name const trimmedPropertyName = propertyName.trim(); if (!trimmedPropertyName.startsWith('--') || trimmedPropertyName.length <= 2) { return null; } // If there's a fallback but it's empty or only whitespace, reject it if (fallback !== undefined) { const trimmedFallback = fallback.trim(); if (trimmedFallback === '') { return null; } // Check if the fallback contains unbalanced parentheses that suggest // it's part of multiple CSS variables (e.g., "10px) var(--other") if (trimmedFallback.includes(') var(')) { return null; } return { type: 'variable', CSSvariable: trimmedPropertyName, defaultValue: normalizeFallback(trimmedFallback) }; } return { type: 'variable', CSSvariable: trimmedPropertyName }; } /** * Converts a parsed CSS variable back to a CSS value string * @param parsed - The parsed CSS variable object * @returns CSS value string or null if invalid */ export function toCSSValue(parsed) { if (!parsed) { return null; } // Validate the parsed CSS variable if (typeof parsed.CSSvariable !== 'string' || !parsed.CSSvariable.startsWith('--') || parsed.CSSvariable.length <= 2) { return null; } if (parsed.defaultValue) { return `var(${parsed.CSSvariable}, ${parsed.defaultValue})`; } return `var(${parsed.CSSvariable})`; }