/** * Checks that the packaged Google Sans Flex subset still carries the variable axes the CSS uses. * * Run from the repository root with `npm run check:font` (or `node bin/check-font.mjs [woff2]`). * tests/Feature/FontTest.php runs it through the configured `node` binary as well, because PHP * cannot open a woff2 without the Brotli extension. * * wght 400–700 — every typescale weight (font.css `font-weight: 400 700`, type.css's regular, * medium and bold reference tokens). * ROND 0–100 — the roundness axis every `type-emphasized-*` utility sets to 100. Re-subset * the font without it and the emphasized styles quietly stop being round. * * Output is one JSON object on stdout — {file, postscriptName, numGlyphs, axes: {tag: {name, min, * default, max}}} — and the exit status is 1, with the reason on stderr, when an axis is missing * or narrower than the range above. */ import { openSync } from 'fontkit' import { fileURLToPath } from 'node:url' /** The axes the stylesheets depend on, and the range each one has to cover. */ const REQUIRED = { wght: { min: 400, max: 700 }, ROND: { min: 0, max: 100 }, } const file = process.argv[2] ?? fileURLToPath(new URL('../resources/fonts/google-sans-flex/GoogleSansFlex-Latin.woff2', import.meta.url)) let font try { font = openSync(file) } catch (error) { process.stderr.write(`${file}: ${error.message}\n`) process.exit(1) } const axes = font.variationAxes ?? {} const problems = Object.entries(REQUIRED).flatMap(([tag, range]) => { const axis = axes[tag] if (!axis) { return [`${tag} is missing; the subset has ${Object.keys(axes).join(', ') || 'no variable axes'}.`] } return axis.min > range.min || axis.max < range.max ? [`${tag} covers ${axis.min}–${axis.max}, not the ${range.min}–${range.max} the stylesheets ask for.`] : [] }) process.stdout.write(`${JSON.stringify({ file, postscriptName: font.postscriptName, numGlyphs: font.numGlyphs, axes, })}\n`) if (problems.length > 0) { process.stderr.write(`${file}\n${problems.map((problem) => ` ${problem}`).join('\n')}\n`) process.exit(1) }