UNPKG

@wix/css-property-parser

Version:

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

115 lines (114 loc) 3.81 kB
"use strict"; // Length data type parser // Handles parsing of CSS length values according to MDN specification // https://developer.mozilla.org/en-US/docs/Web/CSS/length // with units (px, em, rem, %, etc.) and reconstruction back to CSS string Object.defineProperty(exports, "__esModule", { value: true }); exports.parse = parse; exports.toCSSValue = toCSSValue; const number_1 = require('./number.cjs'); const css_variable_1 = require('./css-variable.cjs'); const shared_utils_1 = require('../utils/shared-utils.cjs'); const css_function_parser_1 = require('../utils/css-function-parser.cjs'); // CSS length units categorized by type const LengthUnits = { // Absolute length units absolute: ['px', 'spx', 'cm', 'mm', 'q', 'in', 'pc', 'pt'], // Relative length units relative: ['em', 'rem', 'ex', 'ch', 'lh', 'rlh', 'cap', 'rcap', 'ic', 'ric'], // Viewport percentage units viewport: [ 'vh', 'vw', 'vmin', 'vmax', 'vi', 'vb', 'dvh', 'dvw', 'dvi', 'dvb', 'dvmin', 'dvmax', 'lvh', 'lvw', 'lvi', 'lvb', 'lvmin', 'lvmax', 'svh', 'svw', 'svi', 'svb', 'svmin', 'svmax' ], // Container query length units container: ['cqw', 'cqh', 'cqi', 'cqb', 'cqmin', 'cqmax'] }; // All valid length units flattened const ALL_LENGTH_UNITS = [ ...LengthUnits.absolute, ...LengthUnits.relative, ...LengthUnits.viewport, ...LengthUnits.container, '%' // percentage ]; /** * Parses a CSS length value into structured components * @param value - The CSS length value string * @returns Parsed length object or null if invalid */ function parse(value) { if (!value || typeof value !== 'string') return null; const trimmed = value.trim(); if (trimmed === '') return null; // CSS variables - ALWAYS CHECK FIRST if ((0, shared_utils_1.isCssVariable)(trimmed)) { return (0, css_variable_1.parse)(trimmed); } // Handle special case: zero can be unitless if (trimmed === '0') { return { type: 'length', value: 0, unit: '' }; } // Handle CSS math functions: calc(), clamp(), min(), max() const functionResult = (0, css_function_parser_1.parseCSSFunction)(trimmed); if (functionResult) { return functionResult; } // Regular length with unit const match = trimmed.match(/^([+-]?(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?)([a-zA-Z%]+)$/); if (!match) return null; const [, numberPart, unit] = match; const parsedNumber = (0, number_1.parse)(numberPart); if (!parsedNumber) return null; // Check if it's a simple number value (not calc expression or keyword) if (!('value' in parsedNumber)) { return null; } const lowerUnit = unit.toLowerCase(); // Validate the unit if (!ALL_LENGTH_UNITS.includes(lowerUnit)) { return null; } return { type: 'length', value: parsedNumber.value, unit: lowerUnit }; } /** * Converts a parsed length back to a CSS value string * @param parsed - The parsed length object * @returns CSS value string or null if invalid */ function toCSSValue(parsed) { if (!parsed) { return null; } // Handle CSS variables if ('CSSvariable' in parsed) { return (0, css_variable_1.toCSSValue)(parsed); } // Handle CSS math function expressions if ('expression' in parsed) { return (0, css_function_parser_1.cssFunctionToCSSValue)(parsed); } // Handle regular length values if ('value' in parsed && 'unit' in parsed) { // Special case: zero can be unitless if (parsed.value === 0 && parsed.unit === '') { return '0'; } return `${parsed.value}${parsed.unit}`; } return null; }