@cf-wasm/og
Version:
Generate Open Graph Images dynamically from HTML/CSS without a browser.
88 lines (87 loc) • 2.85 kB
JavaScript
const require_font = require("./font.cjs");
//#region src/core/language.ts
/** Language font map */
const LANGUAGE_FONT_MAP = {
"ja-JP": "Noto+Sans+JP",
"ko-KR": "Noto+Sans+KR",
"zh-CN": "Noto+Sans+SC",
"zh-TW": "Noto+Sans+TC",
"zh-HK": "Noto+Sans+HK",
"th-TH": "Noto+Sans+Thai",
"bn-IN": "Noto+Sans+Bengali",
"ar-AR": "Noto+Sans+Arabic",
"ta-IN": "Noto+Sans+Tamil",
"ml-IN": "Noto+Sans+Malayalam",
"he-IL": "Noto+Sans+Hebrew",
"te-IN": "Noto+Sans+Telugu",
devanagari: "Noto+Sans+Devanagari",
kannada: "Noto+Sans+Kannada",
symbol: ["Noto+Sans+Symbols", "Noto+Sans+Symbols+2"],
math: "Noto+Sans+Math",
unknown: "Noto+Sans"
};
function convert(input) {
return input.split(", ").map((r) => {
const [start, end] = r.replaceAll("U+", "").split("-").map((hex) => Number.parseInt(hex, 16));
if (typeof end !== "number" || Number.isNaN(end)) return start;
return [start, end];
});
}
function checkSegmentInRange(segment, range) {
const codePoint = segment.codePointAt(0);
if (!codePoint) return false;
return range.some((value) => {
if (typeof value === "number") return codePoint === value;
const [start, end] = value;
return start <= codePoint && codePoint <= end;
});
}
var FontDetector = class {
constructor() {
this.rangesByLang = {};
}
addDetectors(input) {
const matches = input.matchAll(/font-family:\s*'(.+?)';.+?unicode-range:\s*(.+?);/gms);
for (const [, _lang, range] of matches) {
const lang = _lang.replaceAll(" ", "+");
this.rangesByLang[lang] ??= [];
this.rangesByLang[lang].push(...convert(range));
}
}
detectSegment(segment, fonts) {
for (const font of fonts) {
const range = this.rangesByLang[font];
if (range && checkSegmentInRange(segment, range)) return font;
}
return null;
}
async load(fonts) {
let params = "";
const existingLang = Object.keys(this.rangesByLang);
const langNeedsToLoad = fonts.filter((font) => !existingLang.includes(font));
if (langNeedsToLoad.length === 0) return;
for (const font of langNeedsToLoad) params += `family=${font}&`;
params += "display=swap";
const cssUrl = `https://fonts.googleapis.com/css2?${params}`;
const fontFace = await require_font.googleFonts.loadCss(cssUrl, "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36");
this.addDetectors(fontFace);
}
async detect(text, fonts) {
await this.load(fonts);
const result = {};
for (const segment of text) {
const lang = this.detectSegment(segment, fonts);
if (lang) {
result[lang] = result[lang] || "";
result[lang] += segment;
}
}
return result;
}
};
//#endregion
exports.FontDetector = FontDetector;
exports.LANGUAGE_FONT_MAP = LANGUAGE_FONT_MAP;
exports.checkSegmentInRange = checkSegmentInRange;
exports.convert = convert;
//# sourceMappingURL=language.cjs.map