Files
discourse/frontend/asset-processor/postcss-variable-renamer.js
T
David Taylor 439efc7419 DEV: Introduce system for renaming CSS variables (#42733)
From time-to-time, variables may need to be renamed in core. To avoid
breaking existing themes and plugins, this commit introduces a system to
automatically rewrite old variable names to new ones. A list of renames
is maintained in `stylesheets/variable-renames.json`, and is applied
when CSS is compiled. This list also powers a stylelint rule which will
automatically rewrite old names to new names in source code.

Transformations apply to all core/theme/plugin code. For now, the
stylelint rule/autofix applies to core only, but this will be extracted
to `@discourse/lint-configs` in the near future.

When a transformation is applied, it adds a trailing `/* automatically
renamed --old to --new */` comment so that the behavior is
understandable from the browser developer tools.
2026-09-01 11:34:46 +01:00

57 lines
1.6 KiB
JavaScript

import valueParser from "postcss-value-parser";
import renames from "../../app/assets/stylesheets/variable-renames.json";
/**
* Rewrites renamed CSS custom properties to their current names, so
* stylesheets which set or read an old name keep working. Each rewritten
* declaration gets a trailing `automatically renamed` comment as a clue in
* dev-tools.
*/
export default function postcssVariableRenamer(renameMap = renames) {
const oldNames = Object.keys(renameMap);
return {
postcssPlugin: "postcss-variable-renamer",
Declaration(declaration, { Comment }) {
const applied = new Map();
const newProp = renameMap[declaration.prop];
if (newProp) {
applied.set(declaration.prop, newProp);
declaration.prop = newProp;
}
if (oldNames.some((oldName) => declaration.value.includes(oldName))) {
let valueChanged = false;
const parsed = valueParser(declaration.value);
parsed.walk((node) => {
const newName = node.type === "word" && renameMap[node.value];
if (newName) {
applied.set(node.value, newName);
node.value = newName;
valueChanged = true;
}
});
if (valueChanged) {
declaration.value = parsed.toString();
}
}
if (applied.size > 0) {
const details = [...applied]
.map(([oldName, newName]) => `${oldName} to ${newName}`)
.join(", ");
declaration.after(
new Comment({ text: `automatically renamed ${details}` })
);
}
},
};
}
postcssVariableRenamer.postcss = true;