108 lines
3.3 KiB
JavaScript
108 lines
3.3 KiB
JavaScript
import fs from "fs";
|
|
import zlib from "zlib";
|
|
|
|
import { decode } from "@msgpack/msgpack";
|
|
import cldr from "cldr";
|
|
|
|
import { gatherCoverageData } from "./coverage-export/gather-coverage-data.mjs";
|
|
|
|
// List all the languages that Iosevka supports, but cannot inferred from CLDR data.
|
|
const overrideSupportedLanguages = [];
|
|
const excludedSupportedLanguages = new Set(["Hinglish"]);
|
|
|
|
async function readMpCharMap(p) {
|
|
return decode(zlib.gunzipSync(await fs.promises.readFile(p)));
|
|
}
|
|
|
|
function getSupportedLanguageSet(rawCoverage) {
|
|
const supportLocaleSet = getSupportLocaleSet(rawCoverage);
|
|
addSimilarLocales(supportLocaleSet);
|
|
return getSupportedLangs(supportLocaleSet);
|
|
}
|
|
|
|
function getSupportLocaleSet(rawCoverage) {
|
|
const supportLocaleSet = new Set();
|
|
for (const locale of cldr.localeIds) {
|
|
const exemplar = cldr.extractCharacters(locale).exemplar;
|
|
if (!exemplar) continue;
|
|
const basicChars = [...(exemplar.default || [])];
|
|
const fullChars = [
|
|
...basicChars,
|
|
...(exemplar.auxiliary || []),
|
|
...(exemplar.index || []),
|
|
...(exemplar.numbers || []),
|
|
...(exemplar.punctuation || [])
|
|
].join("");
|
|
let fullSupport = true;
|
|
let basicSupport = true;
|
|
for (const ch of basicChars) {
|
|
if (!rawCoverage.has(ch.codePointAt(0))) basicSupport = false;
|
|
}
|
|
for (const ch of fullChars) {
|
|
if (!rawCoverage.has(ch.codePointAt(0))) fullSupport = false;
|
|
}
|
|
if (basicSupport) {
|
|
supportLocaleSet.add(locale);
|
|
}
|
|
}
|
|
return supportLocaleSet;
|
|
}
|
|
|
|
function addSimilarLocales(supportLocaleSet) {
|
|
for (const loc of supportLocaleSet) {
|
|
const seg = loc.split("_");
|
|
if (seg.length < 2) continue;
|
|
for (let m = 1; m < seg.length; m++) {
|
|
const upperLoc = seg.slice(0, m).join("_");
|
|
if (upperLoc && supportLocaleSet.has(upperLoc)) {
|
|
supportLocaleSet.delete(loc);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function getSupportedLangs(supportLocaleSet) {
|
|
const supportLangSet = new Set(overrideSupportedLanguages);
|
|
for (const loc of supportLocaleSet) {
|
|
const seg = loc.split("_");
|
|
let displayName = null;
|
|
for (let m = 1; m <= seg.length; m++) {
|
|
const upperLoc = seg.slice(0, m).join("_");
|
|
const subDisplayName = cldr.extractLanguageDisplayNames("en")[upperLoc];
|
|
if (subDisplayName)
|
|
displayName = subDisplayName + (upperLoc === loc ? "" : "\u00A0(" + loc + ")");
|
|
}
|
|
if (displayName && !excludedSupportedLanguages.has(displayName)) {
|
|
supportLangSet.add(displayName);
|
|
}
|
|
}
|
|
return supportLangSet;
|
|
}
|
|
|
|
function getRawCoverage(charMap) {
|
|
const rawCoverage = new Map();
|
|
for (const [gn, codes, tv, cv] of charMap)
|
|
for (const u of codes) rawCoverage.set(u, [gn, tv, cv]);
|
|
return rawCoverage;
|
|
}
|
|
|
|
export async function getCharMapAndSupportedLanguageList(cmpUpright, cmpItalic, cmpOblique) {
|
|
const charMap = await readMpCharMap(cmpUpright);
|
|
const charMapItalic = await readMpCharMap(cmpItalic);
|
|
const charMapOblique = await readMpCharMap(cmpOblique);
|
|
const rawCoverage = getRawCoverage(charMap);
|
|
const rawCoverageItalic = getRawCoverage(charMapItalic);
|
|
const rawCoverageOblique = getRawCoverage(charMapOblique);
|
|
|
|
const covData = await gatherCoverageData(rawCoverage, rawCoverageItalic, rawCoverageOblique);
|
|
|
|
return {
|
|
stats: {
|
|
glyphCount: charMap.length,
|
|
codePointCount: rawCoverage.size
|
|
},
|
|
featureSeries: covData.featureSeries,
|
|
unicodeCoverage: covData.unicodeCoverage,
|
|
languages: Array.from(getSupportedLanguageSet(rawCoverage)).sort()
|
|
};
|
|
}
|