152 lines
5.0 KiB
JavaScript
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();
|