267 lines
5.9 KiB
JavaScript
267 lines
5.9 KiB
JavaScript
import fs from "fs";
|
|
import path from "path";
|
|
import url from "url";
|
|
|
|
import { ArrayUtil } from "../../font-src/support/utils.mjs";
|
|
|
|
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
|
|
|
|
setImmediate(() => {
|
|
main().catch(e => {
|
|
console.error(e);
|
|
process.exit(1);
|
|
});
|
|
});
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
async function main() {
|
|
for (const target of Targets) {
|
|
await target.filter.load();
|
|
}
|
|
|
|
const results = new Map();
|
|
|
|
nextChar: for (let lch = 0; lch < 0x20000; lch++) {
|
|
for (const target of Targets) {
|
|
if (target.filter.has(lch)) {
|
|
const resultKey = `${target.scriptTag}-${target.featureTag}`;
|
|
let result = results.get(resultKey);
|
|
if (!result) {
|
|
result = [];
|
|
results.set(resultKey, result);
|
|
}
|
|
result.push(lch);
|
|
|
|
continue nextChar;
|
|
}
|
|
}
|
|
}
|
|
|
|
let out = [];
|
|
|
|
for (const [key, value] of results) {
|
|
out.push({
|
|
scriptTag: key.split("-")[0],
|
|
featureTag: key.split("-")[1],
|
|
ranges: ArrayUtil.toRanges(value)
|
|
});
|
|
}
|
|
|
|
await fs.promises.writeFile(
|
|
path.resolve(__dirname, "../../font-src/generated/ttfa-ranges.mjs"),
|
|
`/* eslint-disable */\n` +
|
|
`// Machine generated. Do not modify。\n` +
|
|
`export default ` +
|
|
JSON.stringify(out, null, "\t") +
|
|
";\n"
|
|
);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
class InUnicodeDataSet {
|
|
constructor(subpath) {
|
|
this.subpath = subpath;
|
|
this.dataset = null;
|
|
}
|
|
|
|
async load() {
|
|
if (this.dataset) return;
|
|
const d = (await import(`@unicode/unicode-15.0.0/${this.subpath}/code-points.js`)).default;
|
|
this.dataset = new Set(d);
|
|
}
|
|
|
|
has(lch) {
|
|
return this.dataset.has(lch);
|
|
}
|
|
}
|
|
|
|
class InScriptDataSet extends InUnicodeDataSet {
|
|
constructor(script) {
|
|
super(`Script/${script}`);
|
|
}
|
|
}
|
|
|
|
class InBlockDataSet extends InUnicodeDataSet {
|
|
constructor(block) {
|
|
super(`Block/${block}`);
|
|
}
|
|
}
|
|
|
|
class InGeneralCategoryDataSet extends InUnicodeDataSet {
|
|
constructor(general_category) {
|
|
super(`General_Category/${general_category}`);
|
|
}
|
|
}
|
|
|
|
class InString {
|
|
constructor(s) {
|
|
this.s = s;
|
|
this.dataset = null;
|
|
}
|
|
|
|
async load() {
|
|
if (this.dataset) return;
|
|
this.dataset = new Set(this.s);
|
|
}
|
|
|
|
has(lch) {
|
|
return this.dataset.has(String.fromCodePoint(lch));
|
|
}
|
|
}
|
|
|
|
class Negation {
|
|
constructor(operand) {
|
|
this.operand = operand;
|
|
}
|
|
async load() {
|
|
await this.operand.load();
|
|
}
|
|
has(lch) {
|
|
return !this.operand.has(lch);
|
|
}
|
|
}
|
|
|
|
class Conjunct {
|
|
constructor(operands) {
|
|
this.operands = operands;
|
|
}
|
|
async load() {
|
|
for (const operand of this.operands) await operand.load();
|
|
}
|
|
has(lch) {
|
|
for (const operand of this.operands) if (!operand.has(lch)) return false;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
class Disjunct {
|
|
constructor(operands) {
|
|
this.operands = operands;
|
|
}
|
|
async load() {
|
|
for (const operand of this.operands) await operand.load();
|
|
}
|
|
has(lch) {
|
|
for (const operand of this.operands) if (operand.has(lch)) return true;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
const Script = s => new InScriptDataSet(s);
|
|
const Block = b => new InBlockDataSet(b);
|
|
const GeneralCategory = gc => new InGeneralCategoryDataSet(gc);
|
|
const In = s => new InString(s);
|
|
|
|
const All = (...operands) => new Conjunct(operands);
|
|
const Either = (...operands) => new Disjunct(operands);
|
|
const Not = operand => new Negation(operand);
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
const LatinBase = {
|
|
scriptTag: "latn",
|
|
featureTag: "dflt",
|
|
filter: Either(
|
|
All(
|
|
Script("Latin"),
|
|
Either(GeneralCategory("Uppercase_Letter"), GeneralCategory("Lowercase_Letter")),
|
|
Not(Block("Halfwidth_And_Fullwidth_Forms"))
|
|
),
|
|
Block("Currency_Symbols"),
|
|
All(Block("Letterlike_Symbols"), Not(In("℀℁⅍℠℡™℻")))
|
|
)
|
|
};
|
|
const CyrillicBase = {
|
|
scriptTag: "cyrl",
|
|
featureTag: "dflt",
|
|
filter: All(
|
|
Script("Cyrillic"),
|
|
Either(GeneralCategory("Uppercase_Letter"), GeneralCategory("Lowercase_Letter"))
|
|
)
|
|
};
|
|
const GreekBase = {
|
|
scriptTag: "grek",
|
|
featureTag: "dflt",
|
|
filter: All(
|
|
Script("Greek"),
|
|
Either(GeneralCategory("Uppercase_Letter"), GeneralCategory("Lowercase_Letter"))
|
|
)
|
|
};
|
|
const DigitBase = {
|
|
scriptTag: "latn",
|
|
featureTag: "dflt",
|
|
filter: Either(In("0123456789"))
|
|
};
|
|
|
|
const LatinSubscript = {
|
|
scriptTag: "latb",
|
|
featureTag: "dflt",
|
|
filter: Either(In("ₐₑₔₕᵢⱼₖₗₘₙₒₚᵣₛₜᵤᵥₓ"))
|
|
};
|
|
const GreekSubscript = {
|
|
scriptTag: "latb",
|
|
featureTag: "dflt",
|
|
filter: Either(In("ᵦᵧᵨᵩᵪ"))
|
|
};
|
|
const CyrillicSubscript = {
|
|
scriptTag: "latb",
|
|
featureTag: "dflt",
|
|
filter: Either(In("𞁑𞁒𞁓𞁔𞁧𞁕𞁖𞁗𞁘𞁩𞁙𞁨𞁚𞁛𞁜𞁝𞁞𞁟𞁠𞁡𞁢𞁣𞁪𞁤𞁥𞁦"))
|
|
};
|
|
const DigitSubscript = {
|
|
scriptTag: "latb",
|
|
featureTag: "dflt",
|
|
filter: Either(In("₀₁₂₃₄₅₆₇₈₉₊₋₌₍₎"))
|
|
};
|
|
|
|
const LatinSuperscript = {
|
|
scriptTag: "latp",
|
|
featureTag: "dflt",
|
|
filter: Either(In("ªº"), All(Script("Latin"), Either(GeneralCategory("Modifier_Letter"))))
|
|
};
|
|
const GreekSuperscript = {
|
|
scriptTag: "latp",
|
|
featureTag: "dflt",
|
|
filter: All(Script("Greek"), Either(GeneralCategory("Modifier_Letter")))
|
|
};
|
|
const CyrillicSuperscript = {
|
|
scriptTag: "latp",
|
|
featureTag: "dflt",
|
|
filter: All(Script("Cyrillic"), Either(GeneralCategory("Modifier_Letter")))
|
|
};
|
|
const DigitSuperscript = {
|
|
scriptTag: "latp",
|
|
featureTag: "dflt",
|
|
filter: Either(In("⁰¹²³⁴⁵⁶⁷⁸⁹⁺⁻⁼⁽⁾"))
|
|
};
|
|
|
|
const LatinPunctuation = {
|
|
scriptTag: "latn",
|
|
featureTag: "dflt",
|
|
filter: Either(
|
|
Block("Basic_Latin"),
|
|
Block("Latin_1_Supplement"),
|
|
Block("General_Punctuation"),
|
|
Block("Supplemental_Punctuation")
|
|
)
|
|
};
|
|
|
|
const Targets = [
|
|
LatinBase,
|
|
LatinSubscript,
|
|
LatinSuperscript,
|
|
GreekBase,
|
|
GreekSubscript,
|
|
GreekSuperscript,
|
|
CyrillicBase,
|
|
CyrillicSubscript,
|
|
CyrillicSuperscript,
|
|
DigitBase,
|
|
DigitSubscript,
|
|
DigitSuperscript,
|
|
LatinPunctuation
|
|
];
|