import File from "vinyl"; import tmp from "tmp"; import { execFile } from "node:child_process"; import { readFileSync, unlinkSync } from "node:fs"; import hashPaths from "../hash.ts"; import { dest, fromGlob } from "../rx-utils.ts"; import { mergeMap } from "rxjs"; const FONT_PRESETS: { [variant: string]: { ranges: string[] } } = { mono: { ranges: ["20-7F", "2205", "2E22-2E25", "2713", "2717"] }, text: { ranges: ["20-7F", "A0-FF", "2000-206F", "20AC"] }, }; function compileFont(font: File): Promise { const [, variant, weight] = /([A-Z][a-z]+)-(\w+)\.ttf$/.exec(font.basename) as string[]; const tmpOutput = tmp.fileSync({ discardDescriptor: true }); const unicodes = FONT_PRESETS[variant.toLowerCase()].ranges; return new Promise((resolve) => { execFile("pyftsubset", [ font.path, `--unicodes=${unicodes.join(",")}`, `--output-file=${tmpOutput.name}`, "--flavor=woff2", ]).once("exit", () => { font.path = `iosevka-adaedra-${variant.toLowerCase()}-${weight.toLowerCase()}.woff2`; font.contents = readFileSync(tmpOutput.name); (font as any).base = null; unlinkSync(tmpOutput.name); resolve(font); }); }); } export const fonts = () => fromGlob("vendor/*.ttf") .pipe(mergeMap(compileFont), hashPaths("fonts.manifest")) .forEach(dest("dist/_assets"));