mirror of
https://github.com/webstudio-is/webstudio.git
synced 2026-10-26 21:17:40 +09:00
Shorthand properties like background: var(--color) were silently dropped when pasting into the CSS editor because the shorthand expander can't handle unresolved var() references. Fix: CSS vars from the current element's computed styles are now resolved before expanding shorthands. Inline and nested fallbacks (var(--a, var(--b))) are supported. If a var still can't be resolved, a toast error is shown instead of silently dropping the property.
69 lines
1.8 KiB
TypeScript
69 lines
1.8 KiB
TypeScript
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
import htmlTags from "html-tags";
|
|
import { parseCss } from "@webstudio-is/css-data";
|
|
|
|
const mapGroupBy = <Item, Key>(
|
|
array: Item[] | Iterable<Item>,
|
|
getKey: (item: Item) => Key
|
|
) => {
|
|
const groups = new Map<Key, Item[]>();
|
|
for (const item of array) {
|
|
const key = getKey(item);
|
|
let group = groups.get(key);
|
|
if (group === undefined) {
|
|
group = [];
|
|
groups.set(key, group);
|
|
}
|
|
group.push(item);
|
|
}
|
|
return groups;
|
|
};
|
|
|
|
const css = await readFile("./src/normalize.css", "utf8");
|
|
const { styles: parsed } = parseCss(css, new Map());
|
|
const groups = mapGroupBy(parsed, (styleDecl) => styleDecl.selector);
|
|
|
|
const validTags = [
|
|
...htmlTags,
|
|
// exceptions to access preset styles in Checkbox and Radio components
|
|
"checkbox",
|
|
"radio",
|
|
];
|
|
|
|
const cache = new Map<string, string>();
|
|
|
|
let code = "";
|
|
code += `import type { CssProperty, StyleValue } from "@webstudio-is/css-engine";\n`;
|
|
code += `
|
|
type StyleDecl = {
|
|
state?: string;
|
|
property: CssProperty;
|
|
value: StyleValue;
|
|
}
|
|
|
|
`;
|
|
for (const [tag, styles] of groups) {
|
|
if (validTags.includes(tag) === false) {
|
|
throw Error(`Unexpected tag "${tag}"`);
|
|
}
|
|
const newStyles = styles.map(({ state, property, value }) => ({
|
|
state,
|
|
property,
|
|
value,
|
|
}));
|
|
let serializedStyles = JSON.stringify(newStyles);
|
|
const cachedTag = cache.get(serializedStyles);
|
|
// to prevent duplicating same styles
|
|
// assign already rendered tag to the tag with same styles
|
|
if (cachedTag) {
|
|
serializedStyles = cachedTag;
|
|
code += `export const ${tag} = ${cachedTag};\n\n`;
|
|
} else {
|
|
cache.set(serializedStyles, tag);
|
|
code += `export const ${tag}: StyleDecl[] = ${serializedStyles};\n\n`;
|
|
}
|
|
}
|
|
|
|
await mkdir("./src/__generated__", { recursive: true });
|
|
await writeFile("./src/__generated__/normalize.css.ts", code);
|