Skip to content

Instantly share code, notes, and snippets.

@pengx17
Created January 27, 2024 15:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pengx17/49e24ae8a5a609bdaff122ee8c679d1c to your computer and use it in GitHub Desktop.
Save pengx17/49e24ae8a5a609bdaff122ee8c679d1c to your computer and use it in GitHub Desktop.
transform to cssVar
import * as babel from "@babel/core";
import * as fs from "fs";
import plugin from "./plugin";
const code = fs.readFileSync('./input.ts', 'utf8');
const out = babel.transformSync(code, {
plugins: [plugin],
filename: './input.ts',
presets: [require.resolve("@babel/preset-typescript")],
});
console.log(out.code);
import { NodePath, PluginItem } from "@babel/core";
function cssVarToVar(val: string) {
// var(--affine-black-10) -> --affine-black-10
val = val.replaceAll(/^var\(|\)/g, "");
// remove --affine- prefix
val = val.replace(/^--affine-/, "");
// to snake case, e.g. black-10 -> black10
// black-aaa-bbb -> blackAaaBbb
val = val.replace(/-([a-z-0-9])/g, (match, p1) => {
return p1.toUpperCase();
});
return `cssVar('${val}')`;
}
export default function (babel): PluginItem {
const { types: t, template } = babel;
function ensureCssVarImport(path: NodePath) {
const programPath = path.findParent((p) => p.isProgram());
let alreadyImported = false;
if (!programPath) {
return;
}
programPath.traverse({
ImportDeclaration(p) {
if (p.node.source.value === "@toeverything/theme") {
p.node.specifiers.forEach((spec) => {
if (spec.imported && spec.imported.name === "cssVar") {
alreadyImported = true;
}
});
}
},
});
if (!alreadyImported) {
const importAst = template.ast(
`import { cssVar } from '@toeverything/theme';`
);
programPath.node.body.unshift(importAst);
}
}
return {
visitor: {
StringLiteral(path) {
// full match, replace node with cssVar(xxx)
if (path.node.value.match(/^var\(--affine-([0-9a-zA-Z-]+)\)$/)) {
const newValue = cssVarToVar(path.node.value);
path.replaceWith(t.identifier(newValue));
ensureCssVarImport(path);
return;
}
if (path.node.value.includes("var(--affine")) {
const first = [];
const second = [];
let start = 0;
for (let { 0: found, index, input } of path.node.value.matchAll(
/(var\([0-9a-zA-Z-]+\))/g
)) {
first.push(t.templateElement({ raw: input.slice(start, index) }));
second.push(t.identifier(cssVarToVar(found)));
start = index + found.length;
}
if (start < path.node.value.length) {
first.push(t.templateElement({ raw: path.node.value.slice(start) }));
} else {
first.push(t.templateElement({ raw: "" }, true));
}
path.replaceWith(t.templateLiteral(first, second));
ensureCssVarImport(path);
return;
}
},
},
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment