399 lines
12 KiB
JavaScript
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}`);
|