feat(fonts): preset Sans uses Medeo Sans (replaces Geologica + PT Sans)

This commit is contained in:
Nikolay Mamadaev committed 2026-10-29 18:20:45 +02:00
1 parent cd5aefbb14
commit e5bead9104
106 files changed
+603 -589

No files matched your search

+19 -19
View File
@@ -16,7 +16,7 @@ const fontsFilesOut = path.join(fontsOut, "files");
const PLYR_VERSION = "3.8.4";
/** @type {{ id: string, sources: { pkg: string, css: string, familyReplace?: [string, string] }[] }[]} */
/** @type {{ id: string, sources: { pkg: string, css: string, familyReplace?: [string, string], urlBase?: string, filesDir?: string }[] }[]} */
const FONT_BUNDLES = [
{
id: "merriweather",
@@ -27,15 +27,9 @@ const FONT_BUNDLES = [
],
},
{
id: "geologica",
id: "medeo",
sources: [
{
pkg: "@fontsource-variable/geologica",
css: "wght.css",
familyReplace: ["Geologica Variable", "Geologica"],
},
{ pkg: "@fontsource/pt-sans", css: "400.css" },
{ pkg: "@fontsource/pt-sans", css: "700.css" },
{ pkg: "medeo-font", css: "dist/sans.css", urlBase: "fonts", filesDir: "dist/fonts" },
],
},
{
@@ -76,25 +70,29 @@ function copyPlyr() {
console.log(`Plyr ${PLYR_VERSION} -> public/vendor/plyr/`);
}
const woff2Re = /url\(\.\/files\/([^)]+\.woff2)\)/g;
function fontUrlRe(base) {
return new RegExp(`url\\(["']?\\.\\/${base}\\/([^)"']+\\.woff2)["']?\\)`, "g");
}
function transformFontCss(raw, familyReplace) {
function transformFontCss(raw, familyReplace, urlBase = "files") {
let out = raw;
if (familyReplace) {
const [from, to] = familyReplace;
out = out.split(`'${from}'`).join(`'${to}'`);
out = out.split(`"${from}"`).join(`"${to}"`);
}
out = out.replace(/,\s*url\(\.\/files\/[^)]+\.woff\)/g, "");
out = out.replace(new RegExp(`,?\\s*url\\(\\.\\/${urlBase}\\/[^)]+\\.woff\\)`, "g"), "");
out = out.replace(/\s+format\(['"]woff['"]\)/g, "");
// Плоская раскладка: url(./fonts/medeo-sans/X.woff2) -> url(./files/X.woff2)
out = out.replace(fontUrlRe(urlBase), (_m, rel) => `url(./files/${path.posix.basename(rel)})`);
return out;
}
function collectWoff2Files(cssText) {
function collectWoff2Files(cssText, urlBase = "files") {
const names = new Set();
const re = fontUrlRe(urlBase);
let m;
woff2Re.lastIndex = 0;
while ((m = woff2Re.exec(cssText)) !== null) {
while ((m = re.exec(cssText)) !== null) {
names.add(m[1]);
}
return names;
@@ -116,12 +114,14 @@ function buildFontBundles() {
throw new Error(`Font CSS not found: ${cssPath}`);
}
const raw = fs.readFileSync(cssPath, "utf8");
const transformed = transformFontCss(raw, source.familyReplace);
const urlBase = source.urlBase || "files";
const transformed = transformFontCss(raw, source.familyReplace, urlBase);
blocks.push(transformed.trim());
const filesDir = path.join(pkgDir, "files");
for (const fileName of collectWoff2Files(transformed)) {
const srcFile = path.join(filesDir, fileName);
const filesDir = path.join(pkgDir, source.filesDir || urlBase);
for (const relPath of collectWoff2Files(raw, urlBase)) {
const fileName = path.posix.basename(relPath);
const srcFile = path.join(filesDir, relPath);
const dstFile = path.join(fontsFilesOut, fileName);
if (!fs.existsSync(srcFile)) {
throw new Error(`Font file not found: ${srcFile}`);
+1 -1
View File
@@ -5,7 +5,7 @@ import { dirname, resolve } from 'path';
const __dirname = dirname(fileURLToPath(import.meta.url));
const OUT = resolve(__dirname, '../public/assets/resume/Mamadaev_Nik__CV__Product_Designer_UX-UI.pdf');
const PAGE = process.argv[2] || 'http://localhost:4175/resume/';
const FONT = process.argv[3] || 'geologica';
const FONT = process.argv[3] || 'medeo';
const browser = await puppeteer.launch({
headless: true,