Files
dpage-editor/scripts/generate-editor-fonts.mjs
T
hamid zarghami b7ffb2b857
deploy to danak / build_and_deploy (push) Has been cancelled
fonts
2026-06-15 09:35:24 +03:30

399 lines
12 KiB
JavaScript

import fs from "fs";
import path from "path";
import { fileURLToPath } from "url";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const ROOT = path.join(__dirname, "../src/assets/fonts/irancell/fonts-editor");
const OUT_JSON = path.join(ROOT, "fonts.json");
const OUT_CSS = path.join(ROOT, "fonts.css");
const WEIGHT_LABELS = {
100: "Thin",
200: "Extra Light",
300: "Light",
400: "Regular",
500: "Medium",
600: "Semi Bold",
700: "Bold",
800: "Extra Bold",
900: "Black",
};
/** @type {Array<{ id: string; label: string; cssFamily: string; category: "persian" | "english"; faces: Array<{ weight: number; src: string; format?: string }> }>} */
const FONT_FAMILIES = [
{
id: "irancell",
label: "ایرانسل",
cssFamily: "editor-irancell",
category: "persian",
defaultWeight: "300",
faces: [
{ weight: 200, src: "../irancell-extralight.ttf" },
{ weight: 300, src: "../irancell-light.ttf" },
{ weight: 600, src: "../irancell-bold.ttf" },
{ weight: 700, src: "../irancell-bold.ttf" },
],
},
{
id: "peyda",
label: "پیدا",
cssFamily: "editor-peyda",
category: "persian",
faces: [
{ weight: 100, src: "Persian Font/peyda/woff2/PeydaWeb-Thin.woff2", format: "woff2" },
{ weight: 200, src: "Persian Font/peyda/woff2/peydaWeb-extralight.woff2", format: "woff2" },
{ weight: 300, src: "Persian Font/peyda/woff2/peydaWeb-light.woff2", format: "woff2" },
{ weight: 400, src: "Persian Font/peyda/woff2/PeydaWeb-Regular.woff2", format: "woff2" },
{ weight: 500, src: "Persian Font/peyda/woff2/PeydaWeb-Medium.woff2", format: "woff2" },
{ weight: 600, src: "Persian Font/peyda/woff2/PeydaWeb-SemiBold.woff2", format: "woff2" },
{ weight: 700, src: "Persian Font/peyda/woff2/PeydaWeb-Bold.woff2", format: "woff2" },
{ weight: 800, src: "Persian Font/peyda/woff2/PeydaWeb-ExtraBold.woff2", format: "woff2" },
{ weight: 900, src: "Persian Font/peyda/woff2/PeydaWeb-Black.woff2", format: "woff2" },
],
},
{
id: "iransans-fanum",
label: "ایران‌سنس (اعداد فارسی)",
cssFamily: "editor-iransans-fanum",
category: "persian",
faces: [
{ weight: 200, src: "Persian Font/IRANSansWeb(FaNum)_UltraLight.ttf" },
{ weight: 300, src: "Persian Font/IRANSansWeb(FaNum)_Light.ttf" },
{ weight: 400, src: "Persian Font/IRANSansWeb(FaNum).ttf" },
{ weight: 500, src: "Persian Font/IRANSansWeb(FaNum)_Medium.ttf" },
{ weight: 700, src: "Persian Font/IRANSansWeb(FaNum)_Bold.ttf" },
],
},
{
id: "sahel",
label: "ساحل",
cssFamily: "editor-sahel",
category: "persian",
faces: [{ weight: 400, src: "Persian Font/Sahel-VF.ttf" }],
},
{
id: "yekan",
label: "یکان",
cssFamily: "editor-yekan",
category: "persian",
faces: [
{ weight: 400, src: "Persian Font/Yekan.ttf" },
{ weight: 700, src: "Persian Font/BYekan.ttf" },
],
},
{
id: "btehran",
label: "تهران",
cssFamily: "editor-btehran",
category: "persian",
faces: [{ weight: 400, src: "Persian Font/BTehran.ttf" }],
},
{
id: "byagut",
label: "یاقوت",
cssFamily: "editor-byagut",
category: "persian",
faces: [{ weight: 400, src: "Persian Font/BYagut.ttf" }],
},
{
id: "byas",
label: "یاس",
cssFamily: "editor-byas",
category: "persian",
faces: [{ weight: 400, src: "Persian Font/BYas.ttf" }],
},
{
id: "bzar",
label: "زر",
cssFamily: "editor-bzar",
category: "persian",
faces: [{ weight: 700, src: "Persian Font/BZarBd.ttf" }],
},
{
id: "bkoodak",
label: "کودک",
cssFamily: "editor-bkoodak",
category: "persian",
faces: [{ weight: 700, src: "Persian Font/BKoodakBold.ttf" }],
},
{
id: "bbaran",
label: "باران",
cssFamily: "editor-bbaran",
category: "persian",
faces: [{ weight: 400, src: "Persian Font/BBaran.ttf" }],
},
{
id: "broya",
label: "رویا",
cssFamily: "editor-broya",
category: "persian",
faces: [{ weight: 400, src: "Persian Font/BRoya.ttf" }],
},
{
id: "bmahsa",
label: "مهسا",
cssFamily: "editor-bmahsa",
category: "persian",
faces: [{ weight: 400, src: "Persian Font/BMahsa.ttf" }],
},
{
id: "bmorvarid",
label: "مروارید",
cssFamily: "editor-bmorvarid",
category: "persian",
faces: [{ weight: 400, src: "Persian Font/BMorvarid.ttf" }],
},
{
id: "bbc-nassim",
label: "نسیم",
cssFamily: "editor-bbc-nassim",
category: "persian",
faces: [{ weight: 400, src: "Persian Font/BBCNassim.ttf" }],
},
{
id: "far-titr",
label: "تیتر",
cssFamily: "editor-far-titr",
category: "persian",
faces: [{ weight: 400, src: "Persian Font/Far_TitrDF.ttf" }],
},
{
id: "roboto",
label: "Roboto",
cssFamily: "editor-roboto",
category: "english",
faces: [
{ weight: 100, src: "English Font/Roboto-Thin-webfont.ttf" },
{ weight: 300, src: "English Font/Roboto-Light-webfont.ttf" },
{ weight: 400, src: "English Font/Roboto-Regular-webfont.ttf" },
{ weight: 500, src: "English Font/Roboto-Medium-webfont.ttf" },
{ weight: 700, src: "English Font/Roboto-Bold-webfont.ttf" },
{ weight: 900, src: "English Font/Roboto-Black-webfont.ttf" },
],
},
{
id: "roboto-condensed",
label: "Roboto Condensed",
cssFamily: "editor-roboto-condensed",
category: "english",
faces: [
{ weight: 400, src: "English Font/Roboto-Condensed-webfont.ttf" },
{ weight: 700, src: "English Font/Roboto-BoldCondensed-webfont.ttf" },
],
},
{
id: "vollkorn",
label: "Vollkorn",
cssFamily: "editor-vollkorn",
category: "english",
faces: [
{ weight: 400, src: "English Font/Vollkorn-Regular.ttf" },
{ weight: 500, src: "English Font/Vollkorn-Medium.ttf" },
{ weight: 600, src: "English Font/Vollkorn-Semibold.ttf" },
{ weight: 700, src: "English Font/Vollkorn-Bold.ttf" },
],
},
{
id: "caviar-dreams",
label: "Caviar Dreams",
cssFamily: "editor-caviar-dreams",
category: "english",
faces: [
{ weight: 400, src: "English Font/CaviarDreams.ttf" },
{ weight: 700, src: "English Font/CaviarDreams_Bold.ttf" },
],
},
{
id: "raleway",
label: "Raleway",
cssFamily: "editor-raleway",
category: "english",
faces: [
{ weight: 200, src: "English Font/raleway-extralight-webfont.ttf" },
{ weight: 400, src: "English Font/raleway-regular-webfont.ttf" },
{ weight: 500, src: "English Font/raleway-medium-webfont.ttf" },
{ weight: 600, src: "English Font/raleway-semibold-webfont.ttf" },
{ weight: 700, src: "English Font/raleway-bold-webfont.ttf" },
{ weight: 800, src: "English Font/raleway-extrabold-webfont.ttf" },
],
},
{
id: "proxima-nova",
label: "Proxima Nova",
cssFamily: "editor-proxima-nova",
category: "english",
faces: [
{ weight: 300, src: "English Font/proximanova-light-webfont.ttf" },
{ weight: 400, src: "English Font/proximanova-reg-webfont.ttf" },
{ weight: 600, src: "English Font/proximanova-semibold-webfont.ttf" },
{ weight: 700, src: "English Font/proximanova-bold-webfont.ttf" },
{ weight: 800, src: "English Font/proximanova-extrabold-webfont.ttf" },
{ weight: 900, src: "English Font/proximanova-black-webfont.ttf" },
],
},
{
id: "proxima-nova-condensed",
label: "Proxima Nova Condensed",
cssFamily: "editor-proxima-nova-condensed",
category: "english",
faces: [
{ weight: 300, src: "English Font/proximanovacond-light-webfont.ttf" },
{ weight: 600, src: "English Font/proximanovacond-semiboldit-webfont.ttf" },
],
},
{
id: "din-pro",
label: "DIN Pro",
cssFamily: "editor-din-pro",
category: "english",
faces: [
{ weight: 400, src: "English Font/dinpro-regular.ttf" },
{ weight: 500, src: "English Font/dinpro-medium.ttf" },
{ weight: 700, src: "English Font/dinpro-bold.ttf" },
{ weight: 900, src: "English Font/dinpro-black.ttf" },
],
},
{
id: "din-alternate",
label: "DIN Alternate",
cssFamily: "editor-din-alternate",
category: "english",
faces: [
{ weight: 300, src: "English Font/din-lightalternate.ttf" },
{ weight: 400, src: "English Font/din-regularalternate.ttf" },
{ weight: 500, src: "English Font/din-mediumalternate.ttf" },
{ weight: 700, src: "English Font/din-boldalternate.ttf" },
{ weight: 900, src: "English Font/din-blackalternate.ttf" },
],
},
{
id: "abril-fatface",
label: "Abril Fatface",
cssFamily: "editor-abril-fatface",
category: "english",
faces: [{ weight: 400, src: "English Font/AbrilFatface-Regular.otf", format: "opentype" }],
},
{
id: "anton",
label: "Anton",
cssFamily: "editor-anton",
category: "english",
faces: [{ weight: 400, src: "English Font/Anton.ttf" }],
},
{
id: "bebas-neue",
label: "Bebas Neue",
cssFamily: "editor-bebas-neue",
category: "english",
faces: [{ weight: 400, src: "English Font/Bebas Neue.ttf" }],
},
{
id: "kepler-std",
label: "Kepler Std",
cssFamily: "editor-kepler-std",
category: "english",
faces: [{ weight: 400, src: "English Font/kepler-std.ttf" }],
},
{
id: "playfair-display",
label: "Playfair Display",
cssFamily: "editor-playfair-display",
category: "english",
faces: [{ weight: 900, src: "English Font/playfairdisplay-black-webfont.ttf" }],
},
];
function encodeUrlSegment(segment) {
return segment
.split("/")
.map((part) => encodeURIComponent(part))
.join("/");
}
function buildCss(families) {
const blocks = families.flatMap((family) =>
family.faces.map((face) => {
const formatSuffix = face.format ? ` format("${face.format}")` : "";
const url = encodeUrlSegment(face.src);
return `@font-face {
font-family: "${family.cssFamily}";
font-style: normal;
font-weight: ${face.weight};
src: url("${url}")${formatSuffix};
}`;
}),
);
return `/* Auto-generated by scripts/generate-editor-fonts.mjs — do not edit manually */\n\n${blocks.join("\n\n")}\n`;
}
function buildJson(families) {
const fonts = families.map((family) => {
const srcToFace = new Map();
for (const face of family.faces) {
const existing = srcToFace.get(face.src);
if (!existing || face.weight > existing.weight) {
srcToFace.set(face.src, face);
}
}
const uniqueWeightFaces = [...srcToFace.values()].sort(
(a, b) => a.weight - b.weight,
);
const uniqueWeights = uniqueWeightFaces.map((f) => f.weight);
return {
id: family.id,
label: family.label,
cssFamily: family.cssFamily,
category: family.category,
defaultWeight: family.defaultWeight
? String(family.defaultWeight)
: uniqueWeights.includes(400)
? "400"
: String(uniqueWeights[0]),
weights: uniqueWeightFaces.map((face) => ({
value: String(face.weight),
label: WEIGHT_LABELS[face.weight] || String(face.weight),
})),
};
});
return {
version: 1,
fonts,
};
}
function verifySources(families) {
const missing = [];
for (const family of families) {
for (const face of family.faces) {
const resolved = face.src.startsWith("../")
? path.join(ROOT, face.src)
: path.join(ROOT, face.src);
if (!fs.existsSync(resolved)) {
missing.push(resolved);
}
}
}
if (missing.length) {
console.error("Missing font files:\n" + missing.map((m) => ` - ${m}`).join("\n"));
process.exit(1);
}
}
verifySources(FONT_FAMILIES);
const json = buildJson(FONT_FAMILIES);
const css = buildCss(FONT_FAMILIES);
fs.writeFileSync(OUT_JSON, JSON.stringify(json, null, 2) + "\n");
fs.writeFileSync(OUT_CSS, css);
console.log(`Wrote ${OUT_JSON}`);
console.log(`Wrote ${OUT_CSS}`);
console.log(`Fonts: ${json.fonts.length}`);