86 lines
3.7 KiB
JavaScript
86 lines
3.7 KiB
JavaScript
|
|
// Vendor the editor's bundled webfonts.
|
||
|
|
//
|
||
|
|
// npm run fonts (from addon-build/docx-editor/)
|
||
|
|
//
|
||
|
|
// The editor offers fonts in its ribbon, and a font the machine doesn't have
|
||
|
|
// is a font the user picks and then cannot see. Ubuntu and Fraunces are not
|
||
|
|
// on Windows, so they ship with the add-on.
|
||
|
|
//
|
||
|
|
// Fetched from Google Fonts once, here, and committed — never at runtime. An
|
||
|
|
// extension in a browser built around not phoning home should not ask
|
||
|
|
// fonts.gstatic.com what a document looks like every time one is opened.
|
||
|
|
//
|
||
|
|
// Subsets: Latin plus Cyrillic and Greek where the family has them, because
|
||
|
|
// the documents this editor is actually used on are not all English.
|
||
|
|
import fs from "node:fs";
|
||
|
|
import path from "node:path";
|
||
|
|
import { fileURLToPath } from "node:url";
|
||
|
|
|
||
|
|
const here = path.dirname(fileURLToPath(import.meta.url));
|
||
|
|
const OUT = path.resolve(here, "../../bundled-addons/docx-editor/fonts");
|
||
|
|
|
||
|
|
// A browser UA, or Google serves ttf instead of woff2.
|
||
|
|
const UA = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 " +
|
||
|
|
"(KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36";
|
||
|
|
|
||
|
|
const FAMILIES = [
|
||
|
|
{
|
||
|
|
name: "Ubuntu",
|
||
|
|
css: "https://fonts.googleapis.com/css2?family=Ubuntu:ital,wght@0,400;0,700;1,400;1,700&display=block",
|
||
|
|
// No cyrillic-ext or greek-ext: 148 KB for historic and liturgical
|
||
|
|
// ranges that a word processor's font menu will not miss.
|
||
|
|
keep: ["latin", "latin-ext", "cyrillic", "greek"],
|
||
|
|
},
|
||
|
|
{
|
||
|
|
// The variable file, which is smaller than the four static instances it
|
||
|
|
// replaces (280 KB against 305 KB) and carries every weight between them.
|
||
|
|
name: "Fraunces",
|
||
|
|
css: "https://fonts.googleapis.com/css2?family=Fraunces:ital,opsz,wght@0,9..144,100..900;1,9..144,100..900&display=block",
|
||
|
|
keep: ["latin", "latin-ext"],
|
||
|
|
},
|
||
|
|
];
|
||
|
|
|
||
|
|
async function text(url) {
|
||
|
|
const r = await fetch(url, { headers: { "User-Agent": UA } });
|
||
|
|
if (!r.ok) throw new Error(`${r.status} for ${url}`);
|
||
|
|
return r.text();
|
||
|
|
}
|
||
|
|
|
||
|
|
fs.mkdirSync(OUT, { recursive: true });
|
||
|
|
let css = `/* Bundled with the Word editor — see addon-build/docx-editor/fetch-fonts.mjs.
|
||
|
|
Regenerate with \`npm run fonts\`; do not edit by hand. */\n`;
|
||
|
|
let total = 0;
|
||
|
|
|
||
|
|
for (const fam of FAMILIES) {
|
||
|
|
const sheet = await text(fam.css);
|
||
|
|
// Google's stylesheet is a run of /* subset */ + @font-face blocks.
|
||
|
|
const blocks = sheet.split("/*").slice(1);
|
||
|
|
let n = 0;
|
||
|
|
for (const raw of blocks) {
|
||
|
|
const subset = raw.slice(0, raw.indexOf("*/")).trim();
|
||
|
|
if (!fam.keep.includes(subset)) continue;
|
||
|
|
const block = raw.slice(raw.indexOf("*/") + 2);
|
||
|
|
const url = /src:\s*url\(([^)]+)\)/.exec(block)?.[1];
|
||
|
|
if (!url) continue;
|
||
|
|
const style = /font-style:\s*(\w+)/.exec(block)?.[1] || "normal";
|
||
|
|
const weight = /font-weight:\s*([\d\s]+)/.exec(block)?.[1].trim() || "400";
|
||
|
|
const range = /unicode-range:\s*([^;]+);/.exec(block)?.[1].trim();
|
||
|
|
|
||
|
|
const file = `${fam.name.toLowerCase()}-${subset}-${style}-${weight.replace(/\s+/g, "_")}.woff2`;
|
||
|
|
const bytes = Buffer.from(await (await fetch(url, { headers: { "User-Agent": UA } })).arrayBuffer());
|
||
|
|
fs.writeFileSync(path.join(OUT, file), bytes);
|
||
|
|
total += bytes.length;
|
||
|
|
n++;
|
||
|
|
|
||
|
|
css += `@font-face {\n font-family: '${fam.name}';\n font-style: ${style};\n` +
|
||
|
|
` font-weight: ${weight};\n font-display: block;\n` +
|
||
|
|
` src: url('fonts/${file}') format('woff2');\n` +
|
||
|
|
(range ? ` unicode-range: ${range};\n` : "") + `}\n`;
|
||
|
|
}
|
||
|
|
console.log(`${fam.name}: ${n} file(s)`);
|
||
|
|
}
|
||
|
|
|
||
|
|
fs.writeFileSync(path.resolve(OUT, "../fonts.css"), css);
|
||
|
|
console.log(`\n${(total / 1024).toFixed(0)} KB of woff2 in ${path.relative(path.resolve(here, "../.."), OUT)}`);
|
||
|
|
console.log(`stylesheet: bundled-addons/docx-editor/fonts.css`);
|