@kensio/pinyinjs 1.2.2 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +116 -3
- package/NOTICE +9 -0
- package/README.md +58 -9
- package/data/core.entries +1 -13
- package/data/core.freq +0 -0
- package/data/core.keys +1 -13
- package/data/full.entries +141 -131
- package/data/full.freq +0 -0
- package/data/full.keys +167 -157
- package/data/manifest.json +24 -9
- package/data/script.map +26543 -0
- package/data/standard.entries +1 -22
- package/data/standard.freq +0 -0
- package/data/standard.keys +2 -23
- package/dist/cli/arguments.d.ts +72 -0
- package/dist/cli/arguments.d.ts.map +1 -1
- package/dist/cli/arguments.js +110 -0
- package/dist/cli/arguments.js.map +1 -1
- package/dist/cli/commands.d.ts +11 -0
- package/dist/cli/commands.d.ts.map +1 -1
- package/dist/cli/commands.js +77 -1
- package/dist/cli/commands.js.map +1 -1
- package/dist/cli/environment.d.ts.map +1 -1
- package/dist/cli/environment.js +2 -1
- package/dist/cli/environment.js.map +1 -1
- package/dist/cli/help.d.ts.map +1 -1
- package/dist/cli/help.js +21 -0
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/run.d.ts +8 -0
- package/dist/cli/run.d.ts.map +1 -1
- package/dist/cli/run.js +11 -1
- package/dist/cli/run.js.map +1 -1
- package/dist/decode/convert.d.ts +10 -0
- package/dist/decode/convert.d.ts.map +1 -1
- package/dist/decode/convert.js +12 -0
- package/dist/decode/convert.js.map +1 -1
- package/dist/decode/script.d.ts +108 -0
- package/dist/decode/script.d.ts.map +1 -0
- package/dist/decode/script.js +195 -0
- package/dist/decode/script.js.map +1 -0
- package/dist/dictionary/dictionary.d.ts +13 -1
- package/dist/dictionary/dictionary.d.ts.map +1 -1
- package/dist/dictionary/dictionary.js +18 -4
- package/dist/dictionary/dictionary.js.map +1 -1
- package/dist/dictionary/merge.d.ts.map +1 -1
- package/dist/dictionary/merge.js +23 -3
- package/dist/dictionary/merge.js.map +1 -1
- package/dist/dictionary/script-tables.d.ts +17 -0
- package/dist/dictionary/script-tables.d.ts.map +1 -0
- package/dist/dictionary/script-tables.js +275 -0
- package/dist/dictionary/script-tables.js.map +1 -0
- package/dist/dictionary/source.d.ts +18 -0
- package/dist/dictionary/source.d.ts.map +1 -1
- package/dist/dictionary/source.js +20 -0
- package/dist/dictionary/source.js.map +1 -1
- package/dist/format/slug.d.ts +156 -0
- package/dist/format/slug.d.ts.map +1 -0
- package/dist/format/slug.js +0 -0
- package/dist/format/slug.js.map +1 -0
- package/dist/index.d.ts +10 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/script/conversion.d.ts +102 -0
- package/dist/script/conversion.d.ts.map +1 -0
- package/dist/script/conversion.js +194 -0
- package/dist/script/conversion.js.map +1 -0
- package/dist/script/glyphs.d.ts +95 -0
- package/dist/script/glyphs.d.ts.map +1 -0
- package/dist/script/glyphs.js +236 -0
- package/dist/script/glyphs.js.map +1 -0
- package/dist/sources/opencc.d.ts +32 -0
- package/dist/sources/opencc.d.ts.map +1 -0
- package/dist/sources/opencc.js +50 -0
- package/dist/sources/opencc.js.map +1 -0
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import type { Syllable } from "../syllable/syllable.js";
|
|
2
|
+
/**
|
|
3
|
+
* How one character converts into the other script.
|
|
4
|
+
*
|
|
5
|
+
* A default, plus the readings that take a different form. The readings are
|
|
6
|
+
* what make this more than a lookup table: 发 is 發 by default and 髮 when read
|
|
7
|
+
* `fà`, and no table without the reading can tell 头发 from 出发.
|
|
8
|
+
*/
|
|
9
|
+
export interface CharacterConversion {
|
|
10
|
+
/** The form taken when no reading is known, or none of them applies. */
|
|
11
|
+
readonly to: string;
|
|
12
|
+
/** Forms taken at particular readings, keyed by numbered pinyin. */
|
|
13
|
+
readonly byReading?: ReadonlyMap<string, string>;
|
|
14
|
+
/**
|
|
15
|
+
* Other forms this character is commonly written as, with no reading to tell
|
|
16
|
+
* them apart.
|
|
17
|
+
*
|
|
18
|
+
* These never change what a conversion *does* — the default or a reading
|
|
19
|
+
* decides that — but they are what makes it honest. 面 and 麵 read alike, so
|
|
20
|
+
* only a word settles which is meant; without these the conversion would
|
|
21
|
+
* report 面粉 as locked while 下面 came out differently, claiming certainty it
|
|
22
|
+
* does not have. Rare variants are excluded, or every 和 would be doubtful on
|
|
23
|
+
* account of 咊.
|
|
24
|
+
*/
|
|
25
|
+
readonly also?: readonly string[];
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Everything needed to convert between the scripts, in either direction.
|
|
29
|
+
*
|
|
30
|
+
* Words come before characters. A word the table names is converted as a whole,
|
|
31
|
+
* because the evidence for a whole word is direct — some source wrote it that
|
|
32
|
+
* way — whereas a character conversion is an inference from how that character
|
|
33
|
+
* behaved elsewhere. Only words the character tables get *wrong* are stored, so
|
|
34
|
+
* the word tables are exception lists rather than dictionaries.
|
|
35
|
+
*/
|
|
36
|
+
export interface ScriptTables {
|
|
37
|
+
readonly toTraditional: ReadonlyMap<string, CharacterConversion>;
|
|
38
|
+
readonly toSimplified: ReadonlyMap<string, CharacterConversion>;
|
|
39
|
+
/** 简体 words whose 繁體 form the characters would get wrong. */
|
|
40
|
+
readonly traditionalWords: ReadonlyMap<string, string>;
|
|
41
|
+
/** 繁體 words whose 简体 form the characters would get wrong. */
|
|
42
|
+
readonly simplifiedWords: ReadonlyMap<string, string>;
|
|
43
|
+
/** Characters written only in 简体, for `detectScript`. */
|
|
44
|
+
readonly hansOnly: ReadonlySet<string>;
|
|
45
|
+
/** Characters written only in 繁體, for `detectScript`. */
|
|
46
|
+
readonly hantOnly: ReadonlySet<string>;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* The key a reading is stored under: numbered pinyin, or the empty string.
|
|
50
|
+
*
|
|
51
|
+
* 儿化 is dropped because the r suffix never bears on which variant is meant,
|
|
52
|
+
* and a toneless syllable keys separately from a toned one rather than matching
|
|
53
|
+
* it, since a source that wrote no tone is not evidence about a particular one.
|
|
54
|
+
*/
|
|
55
|
+
export declare function conversionKey(syllable: Syllable | undefined): string;
|
|
56
|
+
/**
|
|
57
|
+
* The form a character takes, given the syllable it is read as.
|
|
58
|
+
*/
|
|
59
|
+
export declare function convertCharacter(table: ReadonlyMap<string, CharacterConversion>, character: string, syllable: Syllable | undefined): string;
|
|
60
|
+
/**
|
|
61
|
+
* Whether a character's conversion depends on how it is read.
|
|
62
|
+
*
|
|
63
|
+
* True where the table holds a reading that disagrees with the default, which
|
|
64
|
+
* is exactly where a conversion made without a reading is a guess.
|
|
65
|
+
*/
|
|
66
|
+
export declare function isAmbiguousCharacter(table: ReadonlyMap<string, CharacterConversion>, character: string): boolean;
|
|
67
|
+
/**
|
|
68
|
+
* Every form a character is known to take, likeliest first.
|
|
69
|
+
*/
|
|
70
|
+
export declare function formsOf(conversion: CharacterConversion | undefined): readonly string[];
|
|
71
|
+
/**
|
|
72
|
+
* Convert a word character by character, using the readings where it has them.
|
|
73
|
+
*
|
|
74
|
+
* Readings line up with characters by position. A position with no reading
|
|
75
|
+
* behind it takes the default, which is the right answer for the overwhelming
|
|
76
|
+
* majority and a flagged guess for the rest.
|
|
77
|
+
*/
|
|
78
|
+
export declare function convertCharacters(table: ReadonlyMap<string, CharacterConversion>, word: string, readings?: readonly (Syllable | undefined)[]): string;
|
|
79
|
+
/**
|
|
80
|
+
* Write the tables as the artifact text.
|
|
81
|
+
*
|
|
82
|
+
* One line per mapping, tagged by which table it belongs to, so the whole of
|
|
83
|
+
* script conversion is a single file to fetch and a single scan to read. The
|
|
84
|
+
* format is the same shape as the dictionary's: separators rather than syntax,
|
|
85
|
+
* so that reading it back is a split rather than a parse.
|
|
86
|
+
*/
|
|
87
|
+
export declare function writeScriptTables(tables: ScriptTables): string;
|
|
88
|
+
/**
|
|
89
|
+
* Read the tables back from the artifact text.
|
|
90
|
+
*
|
|
91
|
+
* Unknown tags are skipped rather than rejected, so that a future table can be
|
|
92
|
+
* added without an older reader refusing the file outright.
|
|
93
|
+
*/
|
|
94
|
+
export declare function readScriptTables(text: string): ScriptTables;
|
|
95
|
+
/**
|
|
96
|
+
* Parse a stored reading key back into a syllable.
|
|
97
|
+
*
|
|
98
|
+
* Used by the round-trip check rather than by conversion, which keys on the
|
|
99
|
+
* written form directly and never needs the syllable back.
|
|
100
|
+
*/
|
|
101
|
+
export declare function readConversionKey(key: string): Syllable | undefined;
|
|
102
|
+
//# sourceMappingURL=conversion.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conversion.d.ts","sourceRoot":"","sources":["../../src/script/conversion.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAIxD;;;;;;GAMG;AACH,MAAM,WAAW,mBAAmB;IAClC,wEAAwE;IACxE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,oEAAoE;IACpE,QAAQ,CAAC,SAAS,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjD;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACnC;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,aAAa,EAAE,WAAW,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;IACjE,QAAQ,CAAC,YAAY,EAAE,WAAW,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;IAChE,6DAA6D;IAC7D,QAAQ,CAAC,gBAAgB,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvD,6DAA6D;IAC7D,QAAQ,CAAC,eAAe,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtD,yDAAyD;IACzD,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACvC,yDAAyD;IACzD,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CACxC;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,QAAQ,GAAG,SAAS,GAAG,MAAM,CAMpE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,mBAAmB,CAAC,EAC/C,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,QAAQ,GAAG,SAAS,GAC7B,MAAM,CAOR;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,mBAAmB,CAAC,EAC/C,SAAS,EAAE,MAAM,GAChB,OAAO,CAQT;AAED;;GAEG;AACH,wBAAgB,OAAO,CACrB,UAAU,EAAE,mBAAmB,GAAG,SAAS,GAC1C,SAAS,MAAM,EAAE,CAWnB;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,mBAAmB,CAAC,EAC/C,IAAI,EAAE,MAAM,EACZ,QAAQ,GAAE,SAAS,CAAC,QAAQ,GAAG,SAAS,CAAC,EAAO,GAC/C,MAAM,CAMR;AA4CD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAkB9D;AAyBD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,CA0C3D;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,CAEnE"}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { readSyllable, writeSyllable } from "../syllable/syllable.js";
|
|
2
|
+
import { toCharacters } from "./characters.js";
|
|
3
|
+
/**
|
|
4
|
+
* The key a reading is stored under: numbered pinyin, or the empty string.
|
|
5
|
+
*
|
|
6
|
+
* 儿化 is dropped because the r suffix never bears on which variant is meant,
|
|
7
|
+
* and a toneless syllable keys separately from a toned one rather than matching
|
|
8
|
+
* it, since a source that wrote no tone is not evidence about a particular one.
|
|
9
|
+
*/
|
|
10
|
+
export function conversionKey(syllable) {
|
|
11
|
+
if (syllable === undefined) {
|
|
12
|
+
return "";
|
|
13
|
+
}
|
|
14
|
+
// 儿化 is dropped by writing the syllable without it.
|
|
15
|
+
return writeSyllable({ ...syllable, erhua: false }, "numbers");
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* The form a character takes, given the syllable it is read as.
|
|
19
|
+
*/
|
|
20
|
+
export function convertCharacter(table, character, syllable) {
|
|
21
|
+
const conversion = table.get(character);
|
|
22
|
+
if (conversion === undefined) {
|
|
23
|
+
return character;
|
|
24
|
+
}
|
|
25
|
+
const key = conversionKey(syllable);
|
|
26
|
+
return conversion.byReading?.get(key) ?? conversion.to;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Whether a character's conversion depends on how it is read.
|
|
30
|
+
*
|
|
31
|
+
* True where the table holds a reading that disagrees with the default, which
|
|
32
|
+
* is exactly where a conversion made without a reading is a guess.
|
|
33
|
+
*/
|
|
34
|
+
export function isAmbiguousCharacter(table, character) {
|
|
35
|
+
const conversion = table.get(character);
|
|
36
|
+
if (conversion === undefined) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
return ((conversion.byReading?.size ?? 0) > 0 || (conversion.also?.length ?? 0) > 0);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Every form a character is known to take, likeliest first.
|
|
43
|
+
*/
|
|
44
|
+
export function formsOf(conversion) {
|
|
45
|
+
if (conversion === undefined) {
|
|
46
|
+
return [];
|
|
47
|
+
}
|
|
48
|
+
return [
|
|
49
|
+
...new Set([
|
|
50
|
+
conversion.to,
|
|
51
|
+
...(conversion.byReading?.values() ?? []),
|
|
52
|
+
...(conversion.also ?? []),
|
|
53
|
+
]),
|
|
54
|
+
];
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Convert a word character by character, using the readings where it has them.
|
|
58
|
+
*
|
|
59
|
+
* Readings line up with characters by position. A position with no reading
|
|
60
|
+
* behind it takes the default, which is the right answer for the overwhelming
|
|
61
|
+
* majority and a flagged guess for the rest.
|
|
62
|
+
*/
|
|
63
|
+
export function convertCharacters(table, word, readings = []) {
|
|
64
|
+
let converted = "";
|
|
65
|
+
for (const [at, character] of toCharacters(word).entries()) {
|
|
66
|
+
converted += convertCharacter(table, character, readings[at]);
|
|
67
|
+
}
|
|
68
|
+
return converted;
|
|
69
|
+
}
|
|
70
|
+
const COLUMN = "\t";
|
|
71
|
+
const LINE = "\n";
|
|
72
|
+
const READING = ",";
|
|
73
|
+
const READING_FORM = "=";
|
|
74
|
+
/**
|
|
75
|
+
* Line tags, one per table, so that all six ship as one fetchable file.
|
|
76
|
+
*/
|
|
77
|
+
const TAGS = {
|
|
78
|
+
toTraditional: "t",
|
|
79
|
+
toSimplified: "s",
|
|
80
|
+
traditionalWord: "w",
|
|
81
|
+
simplifiedWord: "x",
|
|
82
|
+
hansOnly: "h",
|
|
83
|
+
hantOnly: "H",
|
|
84
|
+
};
|
|
85
|
+
/**
|
|
86
|
+
* Write one character table's lines.
|
|
87
|
+
*/
|
|
88
|
+
function writeCharacterTable(tag, table) {
|
|
89
|
+
return [...table].map(([character, conversion]) => {
|
|
90
|
+
const readings = [...(conversion.byReading ?? [])]
|
|
91
|
+
.map(([key, form]) => `${key}${READING_FORM}${form}`)
|
|
92
|
+
.join(READING);
|
|
93
|
+
const also = (conversion.also ?? []).join("");
|
|
94
|
+
const columns = [tag, character, conversion.to, readings, also];
|
|
95
|
+
// Trailing empty columns say nothing and are dropped, which is most lines:
|
|
96
|
+
// the common case is a character with one form and no reading to condition.
|
|
97
|
+
while (columns.at(-1) === "") {
|
|
98
|
+
columns.pop();
|
|
99
|
+
}
|
|
100
|
+
return columns.join(COLUMN);
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Write the tables as the artifact text.
|
|
105
|
+
*
|
|
106
|
+
* One line per mapping, tagged by which table it belongs to, so the whole of
|
|
107
|
+
* script conversion is a single file to fetch and a single scan to read. The
|
|
108
|
+
* format is the same shape as the dictionary's: separators rather than syntax,
|
|
109
|
+
* so that reading it back is a split rather than a parse.
|
|
110
|
+
*/
|
|
111
|
+
export function writeScriptTables(tables) {
|
|
112
|
+
return [
|
|
113
|
+
...writeCharacterTable(TAGS.toTraditional, tables.toTraditional),
|
|
114
|
+
...writeCharacterTable(TAGS.toSimplified, tables.toSimplified),
|
|
115
|
+
...[...tables.traditionalWords].map(([hans, hant]) => [TAGS.traditionalWord, hans, hant].join(COLUMN)),
|
|
116
|
+
...[...tables.simplifiedWords].map(([hant, hans]) => [TAGS.simplifiedWord, hant, hans].join(COLUMN)),
|
|
117
|
+
...[...tables.hansOnly].map((character) => [TAGS.hansOnly, character].join(COLUMN)),
|
|
118
|
+
...[...tables.hantOnly].map((character) => [TAGS.hantOnly, character].join(COLUMN)),
|
|
119
|
+
"",
|
|
120
|
+
].join(LINE);
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Read one character table line into its conversion.
|
|
124
|
+
*/
|
|
125
|
+
function readConversion(to, readings, also) {
|
|
126
|
+
const pairs = readings === "" ? [] : readings.split(READING);
|
|
127
|
+
const byReading = new Map();
|
|
128
|
+
for (const pair of pairs) {
|
|
129
|
+
const [key = "", form = ""] = pair.split(READING_FORM);
|
|
130
|
+
if (form !== "") {
|
|
131
|
+
byReading.set(key, form);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return {
|
|
135
|
+
to,
|
|
136
|
+
...(byReading.size > 0 && { byReading }),
|
|
137
|
+
...(also !== "" && { also: toCharacters(also) }),
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Read the tables back from the artifact text.
|
|
142
|
+
*
|
|
143
|
+
* Unknown tags are skipped rather than rejected, so that a future table can be
|
|
144
|
+
* added without an older reader refusing the file outright.
|
|
145
|
+
*/
|
|
146
|
+
export function readScriptTables(text) {
|
|
147
|
+
const toTraditional = new Map();
|
|
148
|
+
const toSimplified = new Map();
|
|
149
|
+
const traditionalWords = new Map();
|
|
150
|
+
const simplifiedWords = new Map();
|
|
151
|
+
const hansOnly = new Set();
|
|
152
|
+
const hantOnly = new Set();
|
|
153
|
+
const characterTables = new Map([
|
|
154
|
+
[TAGS.toTraditional, toTraditional],
|
|
155
|
+
[TAGS.toSimplified, toSimplified],
|
|
156
|
+
]);
|
|
157
|
+
const wordTables = new Map([
|
|
158
|
+
[TAGS.traditionalWord, traditionalWords],
|
|
159
|
+
[TAGS.simplifiedWord, simplifiedWords],
|
|
160
|
+
]);
|
|
161
|
+
const characterSets = new Map([
|
|
162
|
+
[TAGS.hansOnly, hansOnly],
|
|
163
|
+
[TAGS.hantOnly, hantOnly],
|
|
164
|
+
]);
|
|
165
|
+
for (const line of text.split(LINE)) {
|
|
166
|
+
const [tag = "", from = "", to = "", readings = "", also = ""] = line.split(COLUMN);
|
|
167
|
+
if (from === "") {
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
// Dispatching on a map rather than a switch keeps an unknown tag a no-op,
|
|
171
|
+
// so a file written by a later version reads as much as this one knows.
|
|
172
|
+
characterTables.get(tag)?.set(from, readConversion(to, readings, also));
|
|
173
|
+
wordTables.get(tag)?.set(from, to);
|
|
174
|
+
characterSets.get(tag)?.add(from);
|
|
175
|
+
}
|
|
176
|
+
return {
|
|
177
|
+
toTraditional,
|
|
178
|
+
toSimplified,
|
|
179
|
+
traditionalWords,
|
|
180
|
+
simplifiedWords,
|
|
181
|
+
hansOnly,
|
|
182
|
+
hantOnly,
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Parse a stored reading key back into a syllable.
|
|
187
|
+
*
|
|
188
|
+
* Used by the round-trip check rather than by conversion, which keys on the
|
|
189
|
+
* written form directly and never needs the syllable back.
|
|
190
|
+
*/
|
|
191
|
+
export function readConversionKey(key) {
|
|
192
|
+
return key === "" ? undefined : readSyllable(key);
|
|
193
|
+
}
|
|
194
|
+
//# sourceMappingURL=conversion.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conversion.js","sourceRoot":"","sources":["../../src/script/conversion.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import type { Syllable } from "../syllable/syllable.js";
|
|
2
|
+
/**
|
|
3
|
+
* The regional 繁體 orthographies this package writes.
|
|
4
|
+
*
|
|
5
|
+
* A third axis, independent of the script and locale axes in `script.ts`:
|
|
6
|
+
* Taiwan and Hong Kong write the same characters with the same readings, and
|
|
7
|
+
* disagree about the standard form of 58 of them. See SCRIPTS-AND-LOCALES.md.
|
|
8
|
+
*/
|
|
9
|
+
export declare const REGIONS: readonly ["TW", "HK"];
|
|
10
|
+
/**
|
|
11
|
+
* A regional 繁體 orthography: `TW` for 教育部標準字體 or `HK` for 常用字字形表.
|
|
12
|
+
*
|
|
13
|
+
* Only meaningful under `Hant`. Singapore and Malaysia differ from the PRC
|
|
14
|
+
* lexically rather than orthographically, so there is no second 简体 standard.
|
|
15
|
+
*/
|
|
16
|
+
export type Region = (typeof REGIONS)[number];
|
|
17
|
+
/**
|
|
18
|
+
* The 繁體 orthography written when the caller does not name one.
|
|
19
|
+
*
|
|
20
|
+
* There is no region-free 繁體 to fall back on: converting character by
|
|
21
|
+
* character from OpenCC's baseline yields 爲, 衆, 峯, 羣, 裏, 麪, which are the
|
|
22
|
+
* Hong Kong forms. Declining to choose would mean choosing Hong Kong silently,
|
|
23
|
+
* so a region is always applied and always named.
|
|
24
|
+
*
|
|
25
|
+
* Taiwan wins it on population, and more to the point because it is the one
|
|
26
|
+
* polity where 繁體 orthography and Mandarin as the spoken standard coincide —
|
|
27
|
+
* which is the intersection a pinyin package serves.
|
|
28
|
+
*/
|
|
29
|
+
export declare const DEFAULT_REGION = "TW";
|
|
30
|
+
/**
|
|
31
|
+
* Variant 繁體 forms mapped to the canonical form, as a table.
|
|
32
|
+
*
|
|
33
|
+
* Exported so the data pipeline can recompute it from OpenCC and fail the build
|
|
34
|
+
* if the two have drifted — these tables are code rather than an artifact, so
|
|
35
|
+
* nothing else would notice an upstream release that moved a character.
|
|
36
|
+
*/
|
|
37
|
+
export declare const CANONICAL_FORMS: ReadonlyMap<string, string>;
|
|
38
|
+
/**
|
|
39
|
+
* Canonical 繁體 forms mapped to Hong Kong's, as a table. Verified like
|
|
40
|
+
* {@link CANONICAL_FORMS}.
|
|
41
|
+
*/
|
|
42
|
+
export declare const HONG_KONG_FORMS: ReadonlyMap<string, string>;
|
|
43
|
+
/**
|
|
44
|
+
* Whether a character's regional form depends on how it is read.
|
|
45
|
+
*
|
|
46
|
+
* Exposed so that a conversion can report the choice as uncertain when it had
|
|
47
|
+
* no reading to go on, rather than presenting a default as though it were
|
|
48
|
+
* settled.
|
|
49
|
+
*/
|
|
50
|
+
export declare function isReadingSensitive(character: string): boolean;
|
|
51
|
+
/**
|
|
52
|
+
* Normalise one 繁體 character to the canonical form the dictionary stores.
|
|
53
|
+
*
|
|
54
|
+
* Characters no table knows are returned unchanged, which is the right answer
|
|
55
|
+
* for nearly all of them: the two standards agree about everything except the
|
|
56
|
+
* 58 characters {@link HONG_KONG_FORMS} lists.
|
|
57
|
+
*/
|
|
58
|
+
export declare function toCanonicalGlyph(character: string): string;
|
|
59
|
+
/**
|
|
60
|
+
* Normalise a whole 繁體 text to the canonical forms the dictionary stores.
|
|
61
|
+
*
|
|
62
|
+
* Safe to run over 简体 or mixed text, but only because the table is built to
|
|
63
|
+
* make it so: every variant that is also a current 简体 character is excluded,
|
|
64
|
+
* since many Hong Kong forms and mainland simplified forms are the same
|
|
65
|
+
* character. See {@link CANONICAL_FORMS}.
|
|
66
|
+
*
|
|
67
|
+
* Returns the original string when nothing needs normalising, which is nearly
|
|
68
|
+
* always. This sits on the dictionary lookup path, where it is called once per
|
|
69
|
+
* candidate word at every position of a run, so the common case has to cost a
|
|
70
|
+
* scan rather than an allocation.
|
|
71
|
+
*
|
|
72
|
+
* The mapping is one character to one character, which is what makes it safe
|
|
73
|
+
* here: normalising a prefix gives the same answer as taking the prefix of the
|
|
74
|
+
* normalised text, so a lattice scan that prunes on prefixes cannot disagree
|
|
75
|
+
* with the lookup that follows it.
|
|
76
|
+
*/
|
|
77
|
+
export declare function toCanonicalGlyphs(text: string): string;
|
|
78
|
+
/**
|
|
79
|
+
* Write one canonical character in a region's orthography.
|
|
80
|
+
*
|
|
81
|
+
* The syllable is used only where the character is one the two standards split
|
|
82
|
+
* on a reading; everywhere else it is ignored, because a glyph choice never
|
|
83
|
+
* changes how a character is read.
|
|
84
|
+
*/
|
|
85
|
+
export declare function toRegionalGlyph(character: string, region: Region, syllable?: Syllable): string;
|
|
86
|
+
/**
|
|
87
|
+
* Write a whole canonical text in a region's orthography.
|
|
88
|
+
*
|
|
89
|
+
* Readings are matched to characters by position, so a caller with a decoded
|
|
90
|
+
* reading can pass it and a caller without one can leave it out. A position
|
|
91
|
+
* with no syllable behind it falls back to the region's default form, which is
|
|
92
|
+
* what {@link isReadingSensitive} lets the caller flag.
|
|
93
|
+
*/
|
|
94
|
+
export declare function toRegionalGlyphs(text: string, region: Region, readings?: readonly (Syllable | undefined)[]): string;
|
|
95
|
+
//# sourceMappingURL=glyphs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"glyphs.d.ts","sourceRoot":"","sources":["../../src/script/glyphs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAGxD;;;;;;GAMG;AACH,eAAO,MAAM,OAAO,YAAI,IAAI,EAAE,IAAI,CAAU,CAAC;AAE7C;;;;;GAKG;AACH,MAAM,MAAM,MAAM,GAAG,CAAC,OAAO,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC;AAE9C;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,cAAc,OAAwB,CAAC;AAiFpD;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,6BAA6B,CAAC;AAE1D;;;GAGG;AACH,eAAO,MAAM,eAAe,6BAA6B,CAAC;AAsC1D;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAE7D;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAE1D;AAcD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAStD;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,QAAQ,CAAC,EAAE,QAAQ,GAClB,MAAM,CAUR;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,QAAQ,GAAE,SAAS,CAAC,QAAQ,GAAG,SAAS,CAAC,EAAO,GAC/C,MAAM,CASR"}
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
import { toCharacters } from "./characters.js";
|
|
2
|
+
/**
|
|
3
|
+
* The regional 繁體 orthographies this package writes.
|
|
4
|
+
*
|
|
5
|
+
* A third axis, independent of the script and locale axes in `script.ts`:
|
|
6
|
+
* Taiwan and Hong Kong write the same characters with the same readings, and
|
|
7
|
+
* disagree about the standard form of 58 of them. See SCRIPTS-AND-LOCALES.md.
|
|
8
|
+
*/
|
|
9
|
+
export const REGIONS = ["TW", "HK"];
|
|
10
|
+
/**
|
|
11
|
+
* The 繁體 orthography written when the caller does not name one.
|
|
12
|
+
*
|
|
13
|
+
* There is no region-free 繁體 to fall back on: converting character by
|
|
14
|
+
* character from OpenCC's baseline yields 爲, 衆, 峯, 羣, 裏, 麪, which are the
|
|
15
|
+
* Hong Kong forms. Declining to choose would mean choosing Hong Kong silently,
|
|
16
|
+
* so a region is always applied and always named.
|
|
17
|
+
*
|
|
18
|
+
* Taiwan wins it on population, and more to the point because it is the one
|
|
19
|
+
* polity where 繁體 orthography and Mandarin as the spoken standard coincide —
|
|
20
|
+
* which is the intersection a pinyin package serves.
|
|
21
|
+
*/
|
|
22
|
+
export const DEFAULT_REGION = "TW";
|
|
23
|
+
/**
|
|
24
|
+
* Read a table written as a flat run of `from`/`to` character pairs.
|
|
25
|
+
*
|
|
26
|
+
* Pairs rather than a `Record` so that the tables stay legible as data and cost
|
|
27
|
+
* one string each: these are code rather than an artifact to fetch, for the
|
|
28
|
+
* same reason the transcription tables are — 133 mappings do not justify a
|
|
29
|
+
* download, and they must be available before any dictionary has loaded.
|
|
30
|
+
*/
|
|
31
|
+
function readPairs(pairs) {
|
|
32
|
+
const characters = toCharacters(pairs);
|
|
33
|
+
const table = new Map();
|
|
34
|
+
for (let at = 0; at + 1 < characters.length; at += 2) {
|
|
35
|
+
/* c8 ignore next 2 -- both indices are in range while at + 1 < length */
|
|
36
|
+
table.set(characters[at] ?? "", characters[at + 1] ?? "");
|
|
37
|
+
}
|
|
38
|
+
return table;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Variant 繁體 forms, mapped to the canonical form this package stores.
|
|
42
|
+
*
|
|
43
|
+
* The canonical form is Taiwan's, because that is what the dictionary's 繁體
|
|
44
|
+
* keys already are: measured on CC-CEDICT's traditional column, 裡 outnumbers
|
|
45
|
+
* 裏 116 to 8, 群 outnumbers 羣 175 to 1 and 麵 outnumbers 麪 138 to 1. So
|
|
46
|
+
* normalisation means mapping toward `TW`, and only Hong Kong output needs a
|
|
47
|
+
* pass away from what is stored.
|
|
48
|
+
*
|
|
49
|
+
* This is what lets Hong Kong text find dictionary keys. 羣眾 and 麪包 are not
|
|
50
|
+
* keys and never will be, so they would otherwise fall back to converting
|
|
51
|
+
* character by character — the same loss 臺灣 had before `hantVariants`.
|
|
52
|
+
* Measured: of the 9,833 dictionary keys with a distinct Hong Kong spelling,
|
|
53
|
+
* 2,358 are already keys and normalisation reaches a further 5,439. The 2,036
|
|
54
|
+
* still out of reach are mostly 臺 written as 台, which the exclusions below
|
|
55
|
+
* deliberately decline to reverse.
|
|
56
|
+
*
|
|
57
|
+
* Nineteen mappings OpenCC makes are deliberately **excluded**, because the
|
|
58
|
+
* variant is itself current in the corpus the dictionary is built from and
|
|
59
|
+
* rewriting it would corrupt legitimate text. Two different reasons, and the
|
|
60
|
+
* second is the one that is easy to miss:
|
|
61
|
+
*
|
|
62
|
+
* 1. The variant is a live 繁體 spelling. 台 is the clearest — OpenCC maps it to
|
|
63
|
+
* 臺, but CC-CEDICT writes 台 164 times against 臺's 208, so it is a spelling
|
|
64
|
+
* someone chose rather than a Hong Kong-ism. Also 污, 濕, 睾, 祕, 泄.
|
|
65
|
+
* 2. **The variant is a current 简体 character.** Many Hong Kong standard forms
|
|
66
|
+
* are exactly the mainland simplified form, because the PRC simplification
|
|
67
|
+
* adopted the same 新字形 conventions Hong Kong did: 着, 温, 脱, 户, 税, 卧,
|
|
68
|
+
* 悦, 兑, 葱, 幺, 棱, 檐, 痹. Normalising those would rewrite 简体 text, and
|
|
69
|
+
* 走着 `zǒuzhe` is the case that caught it.
|
|
70
|
+
*
|
|
71
|
+
* Excluding them costs almost nothing, because a variant current in either
|
|
72
|
+
* script is a key in its own right and resolves without any help from here.
|
|
73
|
+
* Reversing a merge is ambiguous in exactly the way 简→繁 is, and where the
|
|
74
|
+
* evidence says the variant is current, the safe answer is to leave it alone.
|
|
75
|
+
*/
|
|
76
|
+
const CANONICAL_PAIRS = "僞偽衹只啓啟喫吃粧妝嫺嫻嬀媯峯峰捝挩敍敘枴柺棁梲" +
|
|
77
|
+
"樑梁枱檯涚涗潙溈潨潀爲為牀床癡痴皁皂竈灶糉粽糭粽" +
|
|
78
|
+
"綫線緼縕繮韁纔才羣群脣唇蒀蒕蔘參蔿蒍藴蘊衆眾衞衛" +
|
|
79
|
+
"裏裡覈核説說輼轀醖醞鉢缽鈎鉤鋭銳鍼針閲閱鮎鯰鰛鰮" +
|
|
80
|
+
"麪麵齶顎";
|
|
81
|
+
/**
|
|
82
|
+
* Canonical 繁體 forms, mapped to the form Hong Kong writes.
|
|
83
|
+
*
|
|
84
|
+
* The 58 characters the two standards genuinely disagree about, measured over
|
|
85
|
+
* the 86 that appear in either of OpenCC's variant tables. The other 28 are
|
|
86
|
+
* agreements rather than differences — 爲 → 為 and 衆 → 眾 are both moves *both*
|
|
87
|
+
* standards make, which is easy to get backwards by reading either table alone.
|
|
88
|
+
*
|
|
89
|
+
* Taiwan needs no table of its own: the canonical form is already Taiwan's, so
|
|
90
|
+
* `zh-Hant-TW` output is what the dictionary stores, unaltered.
|
|
91
|
+
*/
|
|
92
|
+
const HONG_KONG_PAIRS = "兌兑叄叁啟啓囪囱媼媪嫻嫺峰峯么幺悅悦慍愠戶户挩捝" +
|
|
93
|
+
"搵揾敓敚敘敍柺枴梲棁榲榅梁樑簷檐檯枱氳氲汙污洩泄" +
|
|
94
|
+
"涗涚溫温溼濕熅煴床牀痺痹著着睪睾稅税縕緼韁繮群羣" +
|
|
95
|
+
"脫脱膃腽臥卧臺台菸煙蒕蒀參蔘蔥葱蘊藴蛻蜕衛衞裡裏" +
|
|
96
|
+
"說説轀輼醞醖鉤鈎銳鋭閱閲鯰鮎鰮鰛麵麪顎齶";
|
|
97
|
+
/**
|
|
98
|
+
* Variant 繁體 forms mapped to the canonical form, as a table.
|
|
99
|
+
*
|
|
100
|
+
* Exported so the data pipeline can recompute it from OpenCC and fail the build
|
|
101
|
+
* if the two have drifted — these tables are code rather than an artifact, so
|
|
102
|
+
* nothing else would notice an upstream release that moved a character.
|
|
103
|
+
*/
|
|
104
|
+
export const CANONICAL_FORMS = readPairs(CANONICAL_PAIRS);
|
|
105
|
+
/**
|
|
106
|
+
* Canonical 繁體 forms mapped to Hong Kong's, as a table. Verified like
|
|
107
|
+
* {@link CANONICAL_FORMS}.
|
|
108
|
+
*/
|
|
109
|
+
export const HONG_KONG_FORMS = readPairs(HONG_KONG_PAIRS);
|
|
110
|
+
/**
|
|
111
|
+
* The one glyph mapping whose answer depends on how the character is read.
|
|
112
|
+
*
|
|
113
|
+
* Taiwan writes 著 for every sense; Hong Kong splits it, writing 着 for the
|
|
114
|
+
* aspect particle and its relatives and keeping 著 for `zhù`. CC-CEDICT records
|
|
115
|
+
* the same split in its 简体 column — `著 着 [zhe5]` against `著 著 [zhu4]` —
|
|
116
|
+
* which is independent confirmation that the divide is real and where it falls.
|
|
117
|
+
*
|
|
118
|
+
* OpenCC resolves this with a phrase table. We resolve it with the reading,
|
|
119
|
+
* which is the point of difference this feature exists for, and which
|
|
120
|
+
* generalises to words no phrase table lists.
|
|
121
|
+
*
|
|
122
|
+
* `zhuó` is deliberately absent, and that is not an oversight: CC-CEDICT writes
|
|
123
|
+
* it both ways — `著 着 [zhuo2]` for wearing or applying, `著 著 [zhuo2]` for
|
|
124
|
+
* 執著 — so the reading genuinely does not settle it. It falls through to the
|
|
125
|
+
* default below and is reported as uncertain rather than guessed at silently.
|
|
126
|
+
*/
|
|
127
|
+
const READING_SPLITS = new Map([["著", new Map([["zhu", "著"]])]]);
|
|
128
|
+
/**
|
|
129
|
+
* A reading key ignoring tone and 儿化, which never bear on a glyph choice.
|
|
130
|
+
*
|
|
131
|
+
* Tone is dropped because the split that needs it — 著 — divides `zhù` from
|
|
132
|
+
* `zhe` and `zháo`, and those differ in their vowels as well, so the initial
|
|
133
|
+
* and final are enough and are what sources agree on most.
|
|
134
|
+
*/
|
|
135
|
+
function readingKey(syllable) {
|
|
136
|
+
if (syllable === undefined) {
|
|
137
|
+
return undefined;
|
|
138
|
+
}
|
|
139
|
+
return `${syllable.initial}${syllable.final}`;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Whether a character's regional form depends on how it is read.
|
|
143
|
+
*
|
|
144
|
+
* Exposed so that a conversion can report the choice as uncertain when it had
|
|
145
|
+
* no reading to go on, rather than presenting a default as though it were
|
|
146
|
+
* settled.
|
|
147
|
+
*/
|
|
148
|
+
export function isReadingSensitive(character) {
|
|
149
|
+
return READING_SPLITS.has(character);
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Normalise one 繁體 character to the canonical form the dictionary stores.
|
|
153
|
+
*
|
|
154
|
+
* Characters no table knows are returned unchanged, which is the right answer
|
|
155
|
+
* for nearly all of them: the two standards agree about everything except the
|
|
156
|
+
* 58 characters {@link HONG_KONG_FORMS} lists.
|
|
157
|
+
*/
|
|
158
|
+
export function toCanonicalGlyph(character) {
|
|
159
|
+
return CANONICAL_FORMS.get(character) ?? character;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Whether any character of a text has a canonical form other than itself.
|
|
163
|
+
*/
|
|
164
|
+
function hasVariantGlyph(text) {
|
|
165
|
+
for (const character of text) {
|
|
166
|
+
if (CANONICAL_FORMS.has(character)) {
|
|
167
|
+
return true;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Normalise a whole 繁體 text to the canonical forms the dictionary stores.
|
|
174
|
+
*
|
|
175
|
+
* Safe to run over 简体 or mixed text, but only because the table is built to
|
|
176
|
+
* make it so: every variant that is also a current 简体 character is excluded,
|
|
177
|
+
* since many Hong Kong forms and mainland simplified forms are the same
|
|
178
|
+
* character. See {@link CANONICAL_FORMS}.
|
|
179
|
+
*
|
|
180
|
+
* Returns the original string when nothing needs normalising, which is nearly
|
|
181
|
+
* always. This sits on the dictionary lookup path, where it is called once per
|
|
182
|
+
* candidate word at every position of a run, so the common case has to cost a
|
|
183
|
+
* scan rather than an allocation.
|
|
184
|
+
*
|
|
185
|
+
* The mapping is one character to one character, which is what makes it safe
|
|
186
|
+
* here: normalising a prefix gives the same answer as taking the prefix of the
|
|
187
|
+
* normalised text, so a lattice scan that prunes on prefixes cannot disagree
|
|
188
|
+
* with the lookup that follows it.
|
|
189
|
+
*/
|
|
190
|
+
export function toCanonicalGlyphs(text) {
|
|
191
|
+
if (!hasVariantGlyph(text)) {
|
|
192
|
+
return text;
|
|
193
|
+
}
|
|
194
|
+
let normalised = "";
|
|
195
|
+
for (const character of toCharacters(text)) {
|
|
196
|
+
normalised += toCanonicalGlyph(character);
|
|
197
|
+
}
|
|
198
|
+
return normalised;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Write one canonical character in a region's orthography.
|
|
202
|
+
*
|
|
203
|
+
* The syllable is used only where the character is one the two standards split
|
|
204
|
+
* on a reading; everywhere else it is ignored, because a glyph choice never
|
|
205
|
+
* changes how a character is read.
|
|
206
|
+
*/
|
|
207
|
+
export function toRegionalGlyph(character, region, syllable) {
|
|
208
|
+
if (region === DEFAULT_REGION) {
|
|
209
|
+
return character;
|
|
210
|
+
}
|
|
211
|
+
const split = READING_SPLITS.get(character);
|
|
212
|
+
const kept = split?.get(readingKey(syllable) ?? "");
|
|
213
|
+
if (kept !== undefined) {
|
|
214
|
+
return kept;
|
|
215
|
+
}
|
|
216
|
+
return HONG_KONG_FORMS.get(character) ?? character;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Write a whole canonical text in a region's orthography.
|
|
220
|
+
*
|
|
221
|
+
* Readings are matched to characters by position, so a caller with a decoded
|
|
222
|
+
* reading can pass it and a caller without one can leave it out. A position
|
|
223
|
+
* with no syllable behind it falls back to the region's default form, which is
|
|
224
|
+
* what {@link isReadingSensitive} lets the caller flag.
|
|
225
|
+
*/
|
|
226
|
+
export function toRegionalGlyphs(text, region, readings = []) {
|
|
227
|
+
if (region === DEFAULT_REGION) {
|
|
228
|
+
return text;
|
|
229
|
+
}
|
|
230
|
+
let written = "";
|
|
231
|
+
for (const [at, character] of toCharacters(text).entries()) {
|
|
232
|
+
written += toRegionalGlyph(character, region, readings[at]);
|
|
233
|
+
}
|
|
234
|
+
return written;
|
|
235
|
+
}
|
|
236
|
+
//# sourceMappingURL=glyphs.js.map
|