@cf-wasm/og
Version:
Generate Open Graph Images dynamically from HTML/CSS without a browser.
103 lines (102 loc) • 2.95 kB
JavaScript
// src/core/language.ts
import { googleFonts } from "./font.js";
var 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"
};
var convert = (input) => input.split(", ").map((r) => {
const range = r.replaceAll("U+", "");
const [start, end] = range.split("-").map((hex) => Number.parseInt(hex, 16));
if (typeof end !== "number" || Number.isNaN(end)) {
return start;
}
return [start, end];
});
var 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) {
var _a;
const regex = /font-family:\s*'(.+?)';.+?unicode-range:\s*(.+?);/gms;
const matches = input.matchAll(regex);
for (const [, _lang, range] of matches) {
const lang = _lang.replaceAll(" ", "+");
(_a = this.rangesByLang)[lang] ?? (_a[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 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;
}
};
export {
FontDetector,
LANGUAGE_FONT_MAP,
checkSegmentInRange,
convert
};