const VALUES_REG = /,(?![^\(]*\))/ const PARTS_REG = /\s(?![^(]*\))/ const LENGTH_REG = /^[0-9]+[a-zA-Z%]+?$/ const parseValue = str => { const parts = str.split(PARTS_REG) const inset = parts.includes('inset') const last = parts.slice(-1)[0] const color = !isLength(last) ? last : undefined const nums = parts .filter(n => n !== 'inset') .filter(n => n !== color) .map(toNum) const [ offsetX, offsetY, blurRadius, spreadRadius ] = nums return { inset, offsetX, offsetY, blurRadius, spreadRadius, color } } const stringifyValue = obj => { const { inset, offsetX = 0, offsetY = 0, blurRadius = 0, spreadRadius, color } = obj || {} return [ (inset ? 'inset' : null), offsetX, offsetY, blurRadius , spreadRadius, color ].filter(v => v !== null && v !== undefined) .map(toPx) .map(s => ('' + s).trim()) .join(' ') } const isLength = v => v === '0' || LENGTH_REG.test(v) const toNum = v => { if (!/px$/.test(v) && v !== '0') return v const n = parseFloat(v) return !isNaN(n) ? n : v } const toPx = n => typeof n === 'number' && n !== 0 ? (n + 'px') : n const parse = str => str.split(VALUES_REG).map(s => s.trim()).map(parseValue) const stringify = arr => arr.map(stringifyValue).join(', ') module.exports = { parse, stringify }