#!/usr/bin/env -S node -r esbin import { promises as fs } from "fs" import { resolve } from "path" import sass from "sass" import { kebabCase } from "lodash" import { tokenSource } from "~/shared/theme/tokens" const trim = (s: string) => s.trim() const [, outdir] = process.argv.slice(2) // This file is used to `make theme`. namespace primer { // https://github.com/primer/github-vscode-theme/commit/5f08d0cc4de8abc33e13c3f63fe92288824a11cf // prettier-ignore const classic = { black: "#1b1f23", white: "#fff", gray: ["#fafbfc", "#f6f8fa", "#e1e4e8", "#d1d5da", "#959da5", "#6a737d", "#586069", "#444d56", "#2f363d", "#24292e"], blue: ["#f1f8ff", "#dbedff", "#c8e1ff", "#79b8ff", "#2188ff", "#0366d6", "#005cc5", "#044289", "#032f62", "#05264c"], green: ["#f0fff4", "#dcffe4", "#bef5cb", "#85e89d", "#34d058", "#28a745", "#22863a", "#176f2c", "#165c26", "#144620"], yellow: ["#fffdef", "#fffbdd", "#fff5b1", "#ffea7f", "#ffdf5d", "#ffd33d", "#f9c513", "#dbab09", "#b08800", "#735c0f"], orange: ["#fff8f2", "#ffebda", "#ffd1ac", "#ffab70", "#fb8532", "#f66a0a", "#e36209", "#d15704", "#c24e00", "#a04100"], red: ["#ffeef0", "#ffdce0", "#fdaeb7", "#f97583", "#ea4a5a", "#d73a49", "#cb2431", "#b31d28", "#9e1c23", "#86181d"], purple: ["#f5f0ff", "#e6dcfd", "#d1bcf9", "#b392f0", "#8a63d2", "#6f42c1", "#5a32a3", "#4c2889", "#3a1d6e", "#29134e"], pink: ["#ffeef8", "#fedbf0", "#f9b3dd", "#f692ce", "#ec6cb9", "#ea4aaa", "#d03592", "#b93a86", "#99306f", "#6d224f"] }; function addClassic(css: string, dark: boolean) { const r = (name: string, value?: string) => (css = css.replace( RegExp(/(--color-NAME: )([^;]+);/.source.replace("NAME", name)), (_, name, originalValue) => `${name}${value ?? originalValue};`, )) r("canvas-default", dark ? "#1f2428" : undefined) return css } function sassCompile(code: string) { return sass.compileString(code, { loadPaths: [resolve(__dirname, "../node_modules")], style: "compressed", }).css } export async function main() { const outputDir = resolve(__dirname, "../dist/vendor/primer") await fs.mkdir(outputDir, { recursive: true }) const themes = { dark: "dark-default", dark_colorblind: undefined, dark_dimmed: undefined, dark_high_contrast: undefined, dark_tritanopia: undefined, light: "light-default", light_colorblind: undefined, light_high_contrast: undefined, light_tritanopia: undefined, } const toRoot = (name: string, themeName = name) => sassCompile(/* scss */ ` @use "@primer/primitives/dist/scss/colors/_${name}.scss" as *; :root[data-theme="github-${themeName}"] { @include primer-colors-${name}; } `) await Promise.all([ ...Object.entries(themes).map(([source, name = source]) => fs.writeFile(resolve(outputDir, `github-${name}.css`), toRoot(source, name)), ), fs.writeFile( resolve(outputDir, "github-dark.css"), addClassic(toRoot("dark"), true), ), fs.writeFile( resolve(outputDir, "github-light.css"), addClassic(toRoot("light"), false), ), ]) } } async function tokens() { const declarations = Object.entries(tokenSource).map(([name, value]) => { const [light, dark] = value.trim().split(",").map(trim) return { name, light, dark } }) await fs.writeFile( resolve(outdir, "tokens.generated.css"), [ "body{", ...declarations.map(({ name, light }) => `--${kebabCase(name)}:${light};`), "}", "body.dark{", ...declarations.map(({ name, dark }) => `--${kebabCase(name)}:${dark};`), "}", ].join(""), ) } async function main() { await tokens() await primer.main() } main()