Files
rhinelab-ui/scripts/vendor-fonts.mjs
T

41 lines
2.8 KiB
JavaScript

// npm pack [email protected] --ignore-scripts --pack-destination .tools/font-comparison
// Pass its extracted package directory as the first argument. Font bytes are
// copied unchanged; only CSS family/weight names and relative URLs are adapted.
import { readFile, writeFile, mkdir, copyFile } from 'node:fs/promises';
import { resolve, dirname, basename } from 'node:path';
import { createHash } from 'node:crypto';
const source = resolve(process.argv[2] || '.tools/font-comparison/mobeicanyue/package');
const version = 'misans-webfont-4.3.1';
const destination = resolve('public/fonts', version);
const archive = resolve(source, '../../misans-webfont-4.3.1.tgz');
const expected = 'lVU2j0sS0Ah/DjcqPk7X/2Vo7P2498bWQnpt9ruxHnxqzeaC2caQ+CmHjxNCujiDhHHX0q0w9cfabh9Yj5gG9g==';
if (createHash('sha512').update(await readFile(archive)).digest('base64') !== expected) throw Error('Unexpected npm archive integrity');
let css = '/* Generated by scripts/vendor-fonts.mjs from [email protected]. */\n';
const files = [];
for (const [weight,label] of [[300,'light'],[400,'regular'],[600,'demibold'],[700,'bold']]) {
const sheet = resolve(source, `misans/misans-${label}/result.css`);
const upstream = await readFile(sheet,'utf8');
await mkdir(resolve(destination,label),{recursive:true});
for (const [,body] of upstream.matchAll(/@font-face\s*\{([^}]+)\}/g)) {
const url = body.match(/url\(['"]?([^'"\)]+)['"]?\)/)[1];
const range = body.match(/unicode-range:([^;}]*)/i)[1];
const file = basename(url);
if (!/^\d+\.woff2$/.test(file)) throw Error(`Unexpected font file: ${file}`);
const bytes = await readFile(resolve(dirname(sheet),file));
await writeFile(resolve(destination,label,file),bytes);
files.push({path:`${label}/${file}`,bytes:bytes.length,sha256:createHash('sha256').update(bytes).digest('hex')});
css += `@font-face{font-family:"MiSans";font-style:normal;font-weight:${weight};font-display:swap;src:url("/fonts/${version}/${label}/${file}") format("woff2");unicode-range:${range}}\n`;
}
await copyFile(sheet, resolve(destination,label,'upstream.css.txt'));
}
await copyFile(resolve(source,'README.md'),resolve(destination,'UPSTREAM-README.md'));
await writeFile('src/fonts.css',css);
await writeFile(resolve(destination,'source.json'),JSON.stringify({
package:'misans-webfont',version:'4.3.1',fontVersion:'4.003',
repository:'https://github.com/mobeicanyue/misans-webfont',
archive:'https://registry.npmjs.org/misans-webfont/-/misans-webfont-4.3.1.tgz',
integrity:`sha512-${expected}`,fontFilesModified:false,
cssChanges:'One MiSans family with 300/400/600/700 weights; remove local() so installed fonts cannot replace pinned files; use versioned same-origin URLs.',files,
},null,2)+'\n');
console.log(`Vendored ${files.length} unchanged font shards, ${(files.reduce((n,f)=>n+f.bytes,0)/1048576).toFixed(2)} MiB.`);