UNPKG

@cf-wasm/og

Version:

Generate Open Graph Images dynamically from HTML/CSS without a browser.

1 lines 5.14 kB
{"version":3,"file":"language.cjs","names":["googleFonts"],"sources":["../../src/core/language.ts"],"sourcesContent":["import { googleFonts } from './font';\n\n/** Language font map */\nexport const LANGUAGE_FONT_MAP = {\n\t'ja-JP': 'Noto+Sans+JP',\n\t'ko-KR': 'Noto+Sans+KR',\n\t'zh-CN': 'Noto+Sans+SC',\n\t'zh-TW': 'Noto+Sans+TC',\n\t'zh-HK': 'Noto+Sans+HK',\n\t'th-TH': 'Noto+Sans+Thai',\n\t'bn-IN': 'Noto+Sans+Bengali',\n\t'ar-AR': 'Noto+Sans+Arabic',\n\t'ta-IN': 'Noto+Sans+Tamil',\n\t'ml-IN': 'Noto+Sans+Malayalam',\n\t'he-IL': 'Noto+Sans+Hebrew',\n\t'te-IN': 'Noto+Sans+Telugu',\n\tdevanagari: 'Noto+Sans+Devanagari',\n\tkannada: 'Noto+Sans+Kannada',\n\tsymbol: ['Noto+Sans+Symbols', 'Noto+Sans+Symbols+2'],\n\tmath: 'Noto+Sans+Math',\n\tunknown: 'Noto+Sans',\n};\n\nexport function convert(input: string): (number | [number, number])[] {\n\treturn input.split(', ').map((r) => {\n\t\tconst range = r.replaceAll('U+', '');\n\t\tconst [start, end] = range\n\t\t\t.split('-')\n\t\t\t.map((hex) => Number.parseInt(hex, 16));\n\n\t\tif (typeof end !== 'number' || Number.isNaN(end)) {\n\t\t\treturn start;\n\t\t}\n\t\treturn [start, end];\n\t});\n}\n\nexport function checkSegmentInRange(\n\tsegment: string,\n\trange: (number | number[])[],\n): boolean {\n\tconst codePoint = segment.codePointAt(0);\n\tif (!codePoint) {\n\t\treturn false;\n\t}\n\treturn range.some((value) => {\n\t\tif (typeof value === 'number') {\n\t\t\treturn codePoint === value;\n\t\t}\n\t\tconst [start, end] = value;\n\t\treturn start <= codePoint && codePoint <= end;\n\t});\n}\n\nexport class FontDetector {\n\tprivate rangesByLang: Record<string, (number | number[])[]>;\n\n\tconstructor() {\n\t\tthis.rangesByLang = {};\n\t}\n\n\tprivate addDetectors(input: string) {\n\t\tconst regex = /font-family:\\s*'(.+?)';.+?unicode-range:\\s*(.+?);/gms;\n\t\tconst matches = input.matchAll(regex);\n\t\tfor (const [, _lang, range] of matches) {\n\t\t\tconst lang = _lang.replaceAll(' ', '+');\n\t\t\tthis.rangesByLang[lang] ??= [];\n\t\t\tthis.rangesByLang[lang].push(...convert(range));\n\t\t}\n\t}\n\n\tprivate detectSegment(segment: string, fonts: string[]): string | null {\n\t\tfor (const font of fonts) {\n\t\t\tconst range = this.rangesByLang[font];\n\t\t\tif (range && checkSegmentInRange(segment, range)) {\n\t\t\t\treturn font;\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\tprivate async load(fonts: string[]) {\n\t\tlet params = '';\n\n\t\tconst existingLang = Object.keys(this.rangesByLang);\n\t\tconst langNeedsToLoad = fonts.filter(\n\t\t\t(font) => !existingLang.includes(font),\n\t\t);\n\n\t\tif (langNeedsToLoad.length === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tfor (const font of langNeedsToLoad) {\n\t\t\tparams += `family=${font}&`;\n\t\t}\n\t\tparams += 'display=swap';\n\n\t\tconst cssUrl = `https://fonts.googleapis.com/css2?${params}`;\n\n\t\tconst fontFace = await googleFonts.loadCss(\n\t\t\tcssUrl,\n\t\t\t'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',\n\t\t);\n\n\t\tthis.addDetectors(fontFace);\n\t}\n\n\tpublic async detect(\n\t\ttext: string,\n\t\tfonts: string[],\n\t): Promise<Record<string, string>> {\n\t\tawait this.load(fonts);\n\t\tconst result: Record<string, string> = {};\n\t\tfor (const segment of text) {\n\t\t\tconst lang = this.detectSegment(segment, fonts);\n\t\t\tif (lang) {\n\t\t\t\tresult[lang] = result[lang] || '';\n\t\t\t\tresult[lang] += segment;\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n}\n"],"mappings":";;;AAGA,MAAa,oBAAoB;CAChC,SAAS;CACT,SAAS;CACT,SAAS;CACT,SAAS;CACT,SAAS;CACT,SAAS;CACT,SAAS;CACT,SAAS;CACT,SAAS;CACT,SAAS;CACT,SAAS;CACT,SAAS;CACT,YAAY;CACZ,SAAS;CACT,QAAQ,CAAC,qBAAqB,qBAAqB;CACnD,MAAM;CACN,SAAS;AACV;AAEA,SAAgB,QAAQ,OAA8C;CACrE,OAAO,MAAM,MAAM,IAAI,CAAC,CAAC,KAAK,MAAM;EAEnC,MAAM,CAAC,OAAO,OADA,EAAE,WAAW,MAAM,EACR,CAAC,CACxB,MAAM,GAAG,CAAC,CACV,KAAK,QAAQ,OAAO,SAAS,KAAK,EAAE,CAAC;EAEvC,IAAI,OAAO,QAAQ,YAAY,OAAO,MAAM,GAAG,GAC9C,OAAO;EAER,OAAO,CAAC,OAAO,GAAG;CACnB,CAAC;AACF;AAEA,SAAgB,oBACf,SACA,OACU;CACV,MAAM,YAAY,QAAQ,YAAY,CAAC;CACvC,IAAI,CAAC,WACJ,OAAO;CAER,OAAO,MAAM,MAAM,UAAU;EAC5B,IAAI,OAAO,UAAU,UACpB,OAAO,cAAc;EAEtB,MAAM,CAAC,OAAO,OAAO;EACrB,OAAO,SAAS,aAAa,aAAa;CAC3C,CAAC;AACF;AAEA,IAAa,eAAb,MAA0B;CAGzB,cAAc;EACb,KAAK,eAAe,CAAC;CACtB;CAEA,aAAqB,OAAe;EAEnC,MAAM,UAAU,MAAM,SAAS,sDAAK;EACpC,KAAK,MAAM,GAAG,OAAO,UAAU,SAAS;GACvC,MAAM,OAAO,MAAM,WAAW,KAAK,GAAG;GACtC,KAAK,aAAa,UAAU,CAAC;GAC7B,KAAK,aAAa,KAAK,CAAC,KAAK,GAAG,QAAQ,KAAK,CAAC;EAC/C;CACD;CAEA,cAAsB,SAAiB,OAAgC;EACtE,KAAK,MAAM,QAAQ,OAAO;GACzB,MAAM,QAAQ,KAAK,aAAa;GAChC,IAAI,SAAS,oBAAoB,SAAS,KAAK,GAC9C,OAAO;EAET;EACA,OAAO;CACR;CAEA,MAAc,KAAK,OAAiB;EACnC,IAAI,SAAS;EAEb,MAAM,eAAe,OAAO,KAAK,KAAK,YAAY;EAClD,MAAM,kBAAkB,MAAM,QAC5B,SAAS,CAAC,aAAa,SAAS,IAAI,CACtC;EAEA,IAAI,gBAAgB,WAAW,GAC9B;EAGD,KAAK,MAAM,QAAQ,iBAClB,UAAU,UAAU,KAAK;EAE1B,UAAU;EAEV,MAAM,SAAS,qCAAqC;EAEpD,MAAM,WAAW,MAAMA,aAAAA,YAAY,QAClC,QACA,uHACD;EAEA,KAAK,aAAa,QAAQ;CAC3B;CAEA,MAAa,OACZ,MACA,OACkC;EAClC,MAAM,KAAK,KAAK,KAAK;EACrB,MAAM,SAAiC,CAAC;EACxC,KAAK,MAAM,WAAW,MAAM;GAC3B,MAAM,OAAO,KAAK,cAAc,SAAS,KAAK;GAC9C,IAAI,MAAM;IACT,OAAO,QAAQ,OAAO,SAAS;IAC/B,OAAO,SAAS;GACjB;EACD;EACA,OAAO;CACR;AACD"}