Public commit
This commit is contained in:
80
scripts/plugins/babel-inline-css-vars.ts
Normal file
80
scripts/plugins/babel-inline-css-vars.ts
Normal file
@ -0,0 +1,80 @@
|
||||
import hash from "@emotion/hash"
|
||||
import type { types } from "@babel/core"
|
||||
import { kebabCase } from "lodash"
|
||||
import type { BabelPlugin } from "./esbuild-babel"
|
||||
|
||||
export const inlineCSSVariables =
|
||||
(): BabelPlugin<{ styles: { id: string; light: string; dark: string }[] }> =>
|
||||
({ types: t }) => ({
|
||||
name: "inline CSS variables",
|
||||
visitor: {
|
||||
Program: {
|
||||
enter(_, state) {
|
||||
state.styles = []
|
||||
},
|
||||
exit(path, { styles }) {
|
||||
if (!styles.length) return
|
||||
|
||||
const css =
|
||||
`body.light {${styles.map(s => `--${s.id}:${s.light}`).join(";")}}\n` +
|
||||
`body.dark {${styles.map(s => `--${s.id}:${s.dark}`).join(";")}}`
|
||||
|
||||
path.node.body.unshift(
|
||||
t.importDeclaration([], t.stringLiteral(`data:text/css,${encodeURI(css)}`)),
|
||||
)
|
||||
},
|
||||
},
|
||||
|
||||
TaggedTemplateExpression(path, state) {
|
||||
function join(exp: types.Node): string[] | undefined {
|
||||
if (t.isIdentifier(exp)) return [exp.name]
|
||||
if (!t.isMemberExpression(exp) || !t.isIdentifier(exp.property)) return
|
||||
const prev = t.isIdentifier(exp.object) ? [exp.object.name] : join(exp.object)
|
||||
return prev ? [...prev, exp.property.name] : undefined
|
||||
}
|
||||
|
||||
const { expressions: exps } = path.node.quasi
|
||||
for (const [i, exp] of exps.entries()) {
|
||||
if (t.isIdentifier(exp)) {
|
||||
if (exp.name === "DARK_MODE") {
|
||||
exps[i] = t.stringLiteral("body.dark &")
|
||||
} else if (exp.name === "LIGHT_MODE") {
|
||||
exps[i] = t.stringLiteral("body.light &")
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if (
|
||||
t.isCallExpression(exp) &&
|
||||
t.isIdentifier(exp.callee, { name: "color" }) &&
|
||||
exp.arguments.length === 2 &&
|
||||
t.isStringLiteral(exp.arguments[0]) &&
|
||||
t.isStringLiteral(exp.arguments[1])
|
||||
) {
|
||||
const [light, dark] = (exp.arguments as babel.types.StringLiteral[]).map(
|
||||
arg => arg.value,
|
||||
)
|
||||
const id = hash(`${light}-${dark}`)
|
||||
state.styles.push({ id, light, dark })
|
||||
exps[i] = t.stringLiteral(`var(--${id})`)
|
||||
continue
|
||||
}
|
||||
|
||||
let ids: string[] | undefined
|
||||
if (
|
||||
t.isMemberExpression(exp) &&
|
||||
t.isIdentifier(exp.property) &&
|
||||
(ids = join(exp))
|
||||
) {
|
||||
const rest = ids.slice(1).join(".")
|
||||
if (ids[0] === "vars") {
|
||||
exps[i] = t.stringLiteral(`var(--${kebabCase(rest)})`)
|
||||
}
|
||||
if (ids[0] === "token") {
|
||||
exps[i] = t.stringLiteral(`var(--color-${kebabCase(rest)})`)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
})
|
Reference in New Issue
Block a user