function appendOrSet(a, b) { if (typeof b === 'string' && /^\s*\|/.test(b)) { return typeof a === 'string' ? a + b : b.replace(/^\s*\|\s*/, ''); } return b || null; } function sliceProps(obj, props) { const result = Object.create(null); for (const [key, value] of Object.entries(obj)) { if (value) { result[key] = {}; for (const prop of Object.keys(value)) { if (props.includes(prop)) { result[key][prop] = value[prop]; } } } } return result; } export default function mix(dest, src) { const result = { ...dest }; for (const [prop, value] of Object.entries(src)) { switch (prop) { case 'generic': result[prop] = Boolean(value); break; case 'units': result[prop] = { ...dest[prop] }; for (const [name, patch] of Object.entries(value)) { result[prop][name] = Array.isArray(patch) ? patch : []; } break; case 'atrules': result[prop] = { ...dest[prop] }; for (const [name, atrule] of Object.entries(value)) { const exists = result[prop][name] || {}; const current = result[prop][name] = { prelude: exists.prelude || null, descriptors: { ...exists.descriptors } }; if (!atrule) { continue; } current.prelude = atrule.prelude ? appendOrSet(current.prelude, atrule.prelude) : current.prelude || null; for (const [descriptorName, descriptorValue] of Object.entries(atrule.descriptors || {})) { current.descriptors[descriptorName] = descriptorValue ? appendOrSet(current.descriptors[descriptorName], descriptorValue) : null; } if (!Object.keys(current.descriptors).length) { current.descriptors = null; } } break; case 'types': case 'properties': result[prop] = { ...dest[prop] }; for (const [name, syntax] of Object.entries(value)) { result[prop][name] = appendOrSet(result[prop][name], syntax); } break; case 'scope': result[prop] = { ...dest[prop] }; for (const [name, props] of Object.entries(value)) { result[prop][name] = { ...result[prop][name], ...props }; } break; case 'parseContext': result[prop] = { ...dest[prop], ...value }; break; case 'atrule': case 'pseudo': result[prop] = { ...dest[prop], ...sliceProps(value, ['parse']) }; break; case 'node': result[prop] = { ...dest[prop], ...sliceProps(value, ['name', 'structure', 'parse', 'generate', 'walkContext']) }; break; } } return result; }