Files

152 lines
5.0 KiB
JavaScript

/**
* Копирует Plyr и шрифты из node_modules в public/ (автономный деплой без CDN).
* Plyr: 3.8.4 (package.json)
*/
import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const root = path.resolve(__dirname, "..");
const nodeModules = path.join(root, "node_modules");
const publicDir = path.join(root, "public");
const plyrOut = path.join(publicDir, "vendor", "plyr");
const fontsOut = path.join(publicDir, "assets", "fonts");
const fontsFilesOut = path.join(fontsOut, "files");
const PLYR_VERSION = "3.8.4";
/** @type {{ id: string, sources: { pkg: string, css: string, familyReplace?: [string, string], urlBase?: string, filesDir?: string }[] }[]} */
const FONT_BUNDLES = [
{
id: "merriweather",
sources: [
{ pkg: "@fontsource/alice", css: "400.css" },
{ pkg: "@fontsource/merriweather", css: "400.css" },
{ pkg: "@fontsource/merriweather", css: "700.css" },
],
},
{
id: "medeo",
sources: [
{ pkg: "medeo-font", css: "dist/sans.css", urlBase: "fonts", filesDir: "dist/fonts" },
],
},
{
id: "mono",
sources: [
{ pkg: "@fontsource/pt-mono", css: "400.css" },
{ pkg: "@fontsource/source-code-pro", css: "400.css" },
{ pkg: "@fontsource/source-code-pro", css: "500.css" },
{ pkg: "@fontsource/source-code-pro", css: "600.css" },
{ pkg: "@fontsource/source-code-pro", css: "700.css" },
],
},
];
function ensureDir(dir) {
fs.mkdirSync(dir, { recursive: true });
}
function emptyDir(dir) {
if (!fs.existsSync(dir)) return;
for (const name of fs.readdirSync(dir)) {
fs.rmSync(path.join(dir, name), { recursive: true, force: true });
}
}
function copyPlyr() {
const dist = path.join(nodeModules, "plyr", "dist");
for (const name of ["plyr.css", "plyr.min.mjs"]) {
const src = path.join(dist, name);
if (!fs.existsSync(src)) {
throw new Error(`Plyr file not found: ${src}. Run npm install.`);
}
}
emptyDir(plyrOut);
ensureDir(plyrOut);
fs.copyFileSync(path.join(dist, "plyr.css"), path.join(plyrOut, "plyr.css"));
fs.copyFileSync(path.join(dist, "plyr.min.mjs"), path.join(plyrOut, "plyr.min.mjs"));
console.log(`Plyr ${PLYR_VERSION} -> public/vendor/plyr/`);
}
function fontUrlRe(base) {
return new RegExp(`url\\(["']?\\.\\/${base}\\/([^)"']+\\.woff2)["']?\\)`, "g");
}
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(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, urlBase = "files") {
const names = new Set();
const re = fontUrlRe(urlBase);
let m;
while ((m = re.exec(cssText)) !== null) {
names.add(m[1]);
}
return names;
}
function buildFontBundles() {
emptyDir(fontsFilesOut);
ensureDir(fontsFilesOut);
const copied = new Set();
for (const bundle of FONT_BUNDLES) {
const blocks = [];
for (const source of bundle.sources) {
const pkgDir = path.join(nodeModules, source.pkg);
const cssPath = path.join(pkgDir, source.css);
if (!fs.existsSync(cssPath)) {
throw new Error(`Font CSS not found: ${cssPath}`);
}
const raw = fs.readFileSync(cssPath, "utf8");
const urlBase = source.urlBase || "files";
const transformed = transformFontCss(raw, source.familyReplace, urlBase);
blocks.push(transformed.trim());
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}`);
}
if (!copied.has(fileName)) {
fs.copyFileSync(srcFile, dstFile);
copied.add(fileName);
}
}
}
const outCss = `${blocks.join("\n\n")}\n`;
const outPath = path.join(fontsOut, `${bundle.id}.css`);
fs.writeFileSync(outPath, outCss, "utf8");
console.log(`${bundle.id}.css (${copied.size} woff2 total so far) -> public/assets/fonts/`);
}
console.log(`Font files: ${copied.size} woff2 in public/assets/fonts/files/`);
}
function main() {
copyPlyr();
buildFontBundles();
console.log("vendor:copy done.");
}
main();