@kensio/pinyinjs 0.1.0-beta.0 → 1.0.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 +87 -0
- package/NOTICE +7 -0
- package/README.md +144 -19
- package/data/full.entries +13400 -13400
- package/data/manifest.json +4 -4
- package/data/standard.entries +2492 -2492
- package/dist/cli/arguments.d.ts +67 -0
- package/dist/cli/arguments.d.ts.map +1 -1
- package/dist/cli/arguments.js +79 -0
- package/dist/cli/arguments.js.map +1 -1
- package/dist/cli/colour.d.ts +77 -0
- package/dist/cli/colour.d.ts.map +1 -0
- package/dist/cli/colour.js +117 -0
- package/dist/cli/colour.js.map +1 -0
- package/dist/cli/commands.d.ts +49 -1
- package/dist/cli/commands.d.ts.map +1 -1
- package/dist/cli/commands.js +404 -42
- package/dist/cli/commands.js.map +1 -1
- package/dist/cli/environment.d.ts.map +1 -1
- package/dist/cli/environment.js +20 -0
- package/dist/cli/environment.js.map +1 -1
- package/dist/cli/help.d.ts.map +1 -1
- package/dist/cli/help.js +43 -16
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/run.d.ts +11 -0
- package/dist/cli/run.d.ts.map +1 -1
- package/dist/cli/run.js +4 -2
- package/dist/cli/run.js.map +1 -1
- package/dist/decode/convert.d.ts +20 -0
- package/dist/decode/convert.d.ts.map +1 -1
- package/dist/decode/convert.js +170 -12
- package/dist/decode/convert.js.map +1 -1
- package/dist/decode/decode.d.ts +3 -2
- package/dist/decode/decode.d.ts.map +1 -1
- package/dist/decode/decode.js +17 -4
- package/dist/decode/decode.js.map +1 -1
- package/dist/decode/reading-rules.d.ts +56 -0
- package/dist/decode/reading-rules.d.ts.map +1 -0
- package/dist/decode/reading-rules.js +107 -0
- package/dist/decode/reading-rules.js.map +1 -0
- package/dist/decode/rules.d.ts +66 -0
- package/dist/decode/rules.d.ts.map +1 -0
- package/dist/decode/rules.js +138 -0
- package/dist/decode/rules.js.map +1 -0
- package/dist/decode/sandhi.d.ts +1 -1
- package/dist/decode/sandhi.d.ts.map +1 -1
- package/dist/decode/sandhi.js +60 -1
- package/dist/decode/sandhi.js.map +1 -1
- package/dist/decode/word.d.ts +18 -0
- package/dist/decode/word.d.ts.map +1 -1
- package/dist/dictionary/artifact.d.ts.map +1 -1
- package/dist/dictionary/artifact.js +28 -1
- package/dist/dictionary/artifact.js.map +1 -1
- package/dist/dictionary/dictionary.d.ts +9 -0
- package/dist/dictionary/dictionary.d.ts.map +1 -1
- package/dist/dictionary/dictionary.js +7 -0
- package/dist/dictionary/dictionary.js.map +1 -1
- package/dist/dictionary/entry.d.ts +12 -0
- package/dist/dictionary/entry.d.ts.map +1 -1
- package/dist/dictionary/entry.js.map +1 -1
- package/dist/dictionary/merge.d.ts +3 -1
- package/dist/dictionary/merge.d.ts.map +1 -1
- package/dist/dictionary/merge.js +19 -1
- package/dist/dictionary/merge.js.map +1 -1
- package/dist/format/transcription.d.ts +52 -0
- package/dist/format/transcription.d.ts.map +1 -0
- package/dist/format/transcription.js +88 -0
- package/dist/format/transcription.js.map +1 -0
- package/dist/index.d.ts +24 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -1
- package/dist/index.js.map +1 -1
- package/dist/numerals/cardinal.d.ts +39 -0
- package/dist/numerals/cardinal.d.ts.map +1 -0
- package/dist/numerals/cardinal.js +111 -0
- package/dist/numerals/cardinal.js.map +1 -0
- package/dist/numerals/characters.d.ts +31 -0
- package/dist/numerals/characters.d.ts.map +1 -0
- package/dist/numerals/characters.js +80 -0
- package/dist/numerals/characters.js.map +1 -0
- package/dist/numerals/numerals.d.ts +76 -0
- package/dist/numerals/numerals.d.ts.map +1 -0
- package/dist/numerals/numerals.js +119 -0
- package/dist/numerals/numerals.js.map +1 -0
- package/dist/numerals/text.d.ts +52 -0
- package/dist/numerals/text.d.ts.map +1 -0
- package/dist/numerals/text.js +248 -0
- package/dist/numerals/text.js.map +1 -0
- package/dist/orthography/grouping.d.ts +56 -11
- package/dist/orthography/grouping.d.ts.map +1 -1
- package/dist/orthography/grouping.js +109 -35
- package/dist/orthography/grouping.js.map +1 -1
- package/dist/orthography/idiom-list.d.ts +56 -0
- package/dist/orthography/idiom-list.d.ts.map +1 -0
- package/dist/orthography/idiom-list.js +296 -0
- package/dist/orthography/idiom-list.js.map +1 -0
- package/dist/orthography/idioms.d.ts +18 -0
- package/dist/orthography/idioms.d.ts.map +1 -0
- package/dist/orthography/idioms.js +22 -0
- package/dist/orthography/idioms.js.map +1 -0
- package/dist/orthography/reduplication.d.ts +52 -0
- package/dist/orthography/reduplication.d.ts.map +1 -0
- package/dist/orthography/reduplication.js +99 -0
- package/dist/orthography/reduplication.js.map +1 -0
- package/dist/orthography/rule.d.ts +50 -0
- package/dist/orthography/rule.d.ts.map +1 -0
- package/dist/orthography/rule.js +101 -0
- package/dist/orthography/rule.js.map +1 -0
- package/dist/sources/cedict.d.ts +23 -0
- package/dist/sources/cedict.d.ts.map +1 -1
- package/dist/sources/cedict.js +28 -0
- package/dist/sources/cedict.js.map +1 -1
- package/dist/syllable/syllable.d.ts +1 -1
- package/dist/syllable/syllable.d.ts.map +1 -1
- package/dist/syllable/syllable.js +2 -37
- package/dist/syllable/syllable.js.map +1 -1
- package/dist/tone/tone-mark.d.ts +23 -0
- package/dist/tone/tone-mark.d.ts.map +1 -1
- package/dist/tone/tone-mark.js +49 -0
- package/dist/tone/tone-mark.js.map +1 -1
- package/dist/transcription/bopomofo.d.ts +46 -0
- package/dist/transcription/bopomofo.d.ts.map +1 -0
- package/dist/transcription/bopomofo.js +371 -0
- package/dist/transcription/bopomofo.js.map +1 -0
- package/dist/transcription/gwoyeu.d.ts +32 -0
- package/dist/transcription/gwoyeu.d.ts.map +1 -0
- package/dist/transcription/gwoyeu.js +491 -0
- package/dist/transcription/gwoyeu.js.map +1 -0
- package/dist/transcription/ipa.d.ts +40 -0
- package/dist/transcription/ipa.d.ts.map +1 -0
- package/dist/transcription/ipa.js +221 -0
- package/dist/transcription/ipa.js.map +1 -0
- package/dist/transcription/spelling-index.d.ts +23 -0
- package/dist/transcription/spelling-index.d.ts.map +1 -0
- package/dist/transcription/spelling-index.js +61 -0
- package/dist/transcription/spelling-index.js.map +1 -0
- package/dist/transcription/wade-giles.d.ts +108 -0
- package/dist/transcription/wade-giles.d.ts.map +1 -0
- package/dist/transcription/wade-giles.js +656 -0
- package/dist/transcription/wade-giles.js.map +1 -0
- package/dist/transcription/yale.d.ts +43 -0
- package/dist/transcription/yale.d.ts.map +1 -0
- package/dist/transcription/yale.js +242 -0
- package/dist/transcription/yale.js.map +1 -0
- package/package.json +9 -5
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The 成语 GB/T 16159 writes with a hyphen down the middle.
|
|
3
|
+
*
|
|
4
|
+
* 6.3.2: a four-syllable 成语 *that can be read as two disyllables* takes a
|
|
5
|
+
* connecting hyphen — `fēngpíng-làngjìng` — and one that cannot is written
|
|
6
|
+
* solid: `bùyìlèhū`, `chūqíbùyì`. The condition is prosodic and structural, and
|
|
7
|
+
* **nothing in the data tracks it.** Conditioning on both halves being
|
|
8
|
+
* dictionary words fires on 10,202 of the 22,192 four-character words jieba tags
|
|
9
|
+
* `i` and is uncorrelated with the standard: it fires on 层出不穷 and not on
|
|
10
|
+
* 风平浪静, which are the standard's own two examples of the same rule, and it
|
|
11
|
+
* fires on 精神文明 and 凯旋归来, which want a space rather than a hyphen. No
|
|
12
|
+
* source carries hyphenated pinyin either, so unlike every other claim this
|
|
13
|
+
* package makes, a 成语 rule could not be scored even if one were written.
|
|
14
|
+
*
|
|
15
|
+
* So: a list, on the same argument as [the spaced word list](./word-list.ts).
|
|
16
|
+
*
|
|
17
|
+
* **What is in it, and what is not.** Only 成语 whose two halves are each a
|
|
18
|
+
* self-contained disyllable — parallel halves (风平|浪静, 千军|万马), a
|
|
19
|
+
* disyllable and its predicate (声势|浩大), or a disyllabic stem with a
|
|
20
|
+
* reduplicated tail (小心|翼翼). Those are the ones where 2+2 is beyond doubt.
|
|
21
|
+
* Anything with a monosyllabic word breaking the rhythm is left out and stays
|
|
22
|
+
* solid, which is what the standard does with it anyway: 目不转睛 is 目 |
|
|
23
|
+
* 不转睛, 迫不及待 is 迫 | 不及待, 情不自禁 and 显而易见 and 名副其实 the same.
|
|
24
|
+
* Left out too is anything this file is not sure of, because a missing entry
|
|
25
|
+
* keeps today's output and a wrong one breaks it.
|
|
26
|
+
*
|
|
27
|
+
* It is not a complete 成语 list and is not meant to become one — 22,192 of them
|
|
28
|
+
* exist. Measured over 88,866 lines of Tatoeba and zh.wikipedia, the 117 here
|
|
29
|
+
* cover 264 of the 1,737 four-character `i`-tagged words that turn up, or
|
|
30
|
+
* 15.2%. Most of what is left is either genuinely not 2+2 (据我所知, 一无所知,
|
|
31
|
+
* 心不在焉, 难以置信) or not a 成语 at all (非常感谢, 重新启动, 可口可乐), which
|
|
32
|
+
* is the shape a curated list should have: the cases it declines are mostly
|
|
33
|
+
* cases it should decline.
|
|
34
|
+
*/
|
|
35
|
+
/**
|
|
36
|
+
* 简体 forms, grouped by why the halves are halves.
|
|
37
|
+
*/
|
|
38
|
+
const HANS = [
|
|
39
|
+
// ── Parallel halves: 联合式, the clearest case ─────────────
|
|
40
|
+
"风平浪静",
|
|
41
|
+
"山清水秀",
|
|
42
|
+
"千军万马",
|
|
43
|
+
"千家万户",
|
|
44
|
+
"千方百计",
|
|
45
|
+
"四面八方",
|
|
46
|
+
"四通八达",
|
|
47
|
+
"七零八落",
|
|
48
|
+
"大街小巷",
|
|
49
|
+
"成千上万",
|
|
50
|
+
"生死存亡",
|
|
51
|
+
"你死我活",
|
|
52
|
+
"翻来覆去",
|
|
53
|
+
"无影无踪",
|
|
54
|
+
"无声无息",
|
|
55
|
+
"自由自在",
|
|
56
|
+
"自言自语",
|
|
57
|
+
"自给自足",
|
|
58
|
+
"全心全意",
|
|
59
|
+
"一心一意",
|
|
60
|
+
"平起平坐",
|
|
61
|
+
"不慌不忙",
|
|
62
|
+
"所作所为",
|
|
63
|
+
"咬牙切齿",
|
|
64
|
+
"手忙脚乱",
|
|
65
|
+
"胡思乱想",
|
|
66
|
+
"横冲直撞",
|
|
67
|
+
"歌功颂德",
|
|
68
|
+
"耀武扬威",
|
|
69
|
+
"拨乱反正",
|
|
70
|
+
"提心吊胆",
|
|
71
|
+
"前仆后继",
|
|
72
|
+
"轻描淡写",
|
|
73
|
+
"斩钉截铁",
|
|
74
|
+
"讨价还价",
|
|
75
|
+
"粉身碎骨",
|
|
76
|
+
"惊天动地",
|
|
77
|
+
"大惊小怪",
|
|
78
|
+
"三心二意",
|
|
79
|
+
"爱憎分明",
|
|
80
|
+
"光明磊落",
|
|
81
|
+
"精疲力尽",
|
|
82
|
+
"新陈代谢",
|
|
83
|
+
"人杰地灵",
|
|
84
|
+
"错综复杂",
|
|
85
|
+
"心甘情愿",
|
|
86
|
+
"触目惊心",
|
|
87
|
+
"遍体鳞伤",
|
|
88
|
+
"气急败坏",
|
|
89
|
+
"大声疾呼",
|
|
90
|
+
"欢声雷动",
|
|
91
|
+
"星罗棋布",
|
|
92
|
+
"卧薪尝胆",
|
|
93
|
+
"目瞪口呆",
|
|
94
|
+
"赤手空拳",
|
|
95
|
+
"破口大骂",
|
|
96
|
+
"束手无策",
|
|
97
|
+
"大惊失色",
|
|
98
|
+
"手足无措",
|
|
99
|
+
"针锋相对",
|
|
100
|
+
"全力以赴",
|
|
101
|
+
"举世闻名",
|
|
102
|
+
"全军覆没",
|
|
103
|
+
"家喻户晓",
|
|
104
|
+
"想方设法",
|
|
105
|
+
"独立自主",
|
|
106
|
+
"不由自主",
|
|
107
|
+
"自力更生",
|
|
108
|
+
"艰苦奋斗",
|
|
109
|
+
"心满意足",
|
|
110
|
+
"不知不觉",
|
|
111
|
+
"心旷神怡",
|
|
112
|
+
"热血沸腾",
|
|
113
|
+
"光彩夺目",
|
|
114
|
+
"丰富多彩",
|
|
115
|
+
"慷慨激昂",
|
|
116
|
+
"声势浩大",
|
|
117
|
+
"兴高采烈",
|
|
118
|
+
"恶有恶报",
|
|
119
|
+
"开门见山",
|
|
120
|
+
"粗心大意",
|
|
121
|
+
"一见钟情",
|
|
122
|
+
"截然不同",
|
|
123
|
+
"独一无二",
|
|
124
|
+
"与众不同",
|
|
125
|
+
"大错特错",
|
|
126
|
+
"有朝一日",
|
|
127
|
+
"吹毛求疵",
|
|
128
|
+
"沉默寡言",
|
|
129
|
+
"鸡毛蒜皮",
|
|
130
|
+
"胡说八道",
|
|
131
|
+
"了如指掌",
|
|
132
|
+
"无家可归",
|
|
133
|
+
"乱七八糟",
|
|
134
|
+
"引人注目",
|
|
135
|
+
"大吃一惊",
|
|
136
|
+
"竭尽全力",
|
|
137
|
+
"五脏六腑",
|
|
138
|
+
"直截了当",
|
|
139
|
+
"出类拔萃",
|
|
140
|
+
"水落石出",
|
|
141
|
+
"倾盆大雨",
|
|
142
|
+
"完美无瑕",
|
|
143
|
+
"层出不穷",
|
|
144
|
+
// ── A disyllable with a reduplicated tail: ABCC ────────────
|
|
145
|
+
"小心翼翼",
|
|
146
|
+
"威风凛凛",
|
|
147
|
+
"忠心耿耿",
|
|
148
|
+
"杀气腾腾",
|
|
149
|
+
"兴致勃勃",
|
|
150
|
+
"气喘吁吁",
|
|
151
|
+
"忧心忡忡",
|
|
152
|
+
// ── A reduplicated head with a disyllable: AABC ────────────
|
|
153
|
+
"咄咄逼人",
|
|
154
|
+
"滔滔不绝",
|
|
155
|
+
"念念不忘",
|
|
156
|
+
"源源不断",
|
|
157
|
+
"息息相关",
|
|
158
|
+
"面面相觑",
|
|
159
|
+
];
|
|
160
|
+
/**
|
|
161
|
+
* 繁體 spellings of the same 成语, where they differ.
|
|
162
|
+
*
|
|
163
|
+
* Listed rather than converted, because 繁體 is a key in its own right
|
|
164
|
+
* everywhere else in this package and routing it through 简体 to look something
|
|
165
|
+
* up is exactly what SCRIPTS-AND-LOCALES.md refuses to do. Every entry is
|
|
166
|
+
* checked against the dictionary by a test, so a spelling that is not a real
|
|
167
|
+
* word cannot sit here unnoticed.
|
|
168
|
+
*/
|
|
169
|
+
const HANT = [
|
|
170
|
+
"風平浪靜",
|
|
171
|
+
"山清水秀",
|
|
172
|
+
"千軍萬馬",
|
|
173
|
+
"千家萬戶",
|
|
174
|
+
"千方百計",
|
|
175
|
+
"四面八方",
|
|
176
|
+
"四通八達",
|
|
177
|
+
"七零八落",
|
|
178
|
+
"大街小巷",
|
|
179
|
+
"成千上萬",
|
|
180
|
+
"生死存亡",
|
|
181
|
+
"你死我活",
|
|
182
|
+
"翻來覆去",
|
|
183
|
+
"無影無蹤",
|
|
184
|
+
"無聲無息",
|
|
185
|
+
"自由自在",
|
|
186
|
+
"自言自語",
|
|
187
|
+
"自給自足",
|
|
188
|
+
"全心全意",
|
|
189
|
+
"一心一意",
|
|
190
|
+
"平起平坐",
|
|
191
|
+
"不慌不忙",
|
|
192
|
+
"所作所為",
|
|
193
|
+
"咬牙切齒",
|
|
194
|
+
"手忙腳亂",
|
|
195
|
+
"胡思亂想",
|
|
196
|
+
"橫衝直撞",
|
|
197
|
+
"歌功頌德",
|
|
198
|
+
"耀武揚威",
|
|
199
|
+
"撥亂反正",
|
|
200
|
+
"提心吊膽",
|
|
201
|
+
"前仆後繼",
|
|
202
|
+
"輕描淡寫",
|
|
203
|
+
"斬釘截鐵",
|
|
204
|
+
"討價還價",
|
|
205
|
+
"粉身碎骨",
|
|
206
|
+
"驚天動地",
|
|
207
|
+
"大驚小怪",
|
|
208
|
+
"三心二意",
|
|
209
|
+
"愛憎分明",
|
|
210
|
+
"光明磊落",
|
|
211
|
+
"精疲力盡",
|
|
212
|
+
"新陳代謝",
|
|
213
|
+
"人傑地靈",
|
|
214
|
+
"錯綜複雜",
|
|
215
|
+
"心甘情願",
|
|
216
|
+
"觸目驚心",
|
|
217
|
+
"遍體鱗傷",
|
|
218
|
+
"氣急敗壞",
|
|
219
|
+
"大聲疾呼",
|
|
220
|
+
"歡聲雷動",
|
|
221
|
+
"星羅棋布",
|
|
222
|
+
"臥薪嘗膽",
|
|
223
|
+
"目瞪口呆",
|
|
224
|
+
"赤手空拳",
|
|
225
|
+
"破口大罵",
|
|
226
|
+
"束手無策",
|
|
227
|
+
"大驚失色",
|
|
228
|
+
"手足無措",
|
|
229
|
+
"針鋒相對",
|
|
230
|
+
"全力以赴",
|
|
231
|
+
"舉世聞名",
|
|
232
|
+
"全軍覆沒",
|
|
233
|
+
"家喻戶曉",
|
|
234
|
+
"想方設法",
|
|
235
|
+
"獨立自主",
|
|
236
|
+
"不由自主",
|
|
237
|
+
"自力更生",
|
|
238
|
+
"艱苦奮鬥",
|
|
239
|
+
"心滿意足",
|
|
240
|
+
"不知不覺",
|
|
241
|
+
"心曠神怡",
|
|
242
|
+
"熱血沸騰",
|
|
243
|
+
"光彩奪目",
|
|
244
|
+
"豐富多彩",
|
|
245
|
+
"慷慨激昂",
|
|
246
|
+
"聲勢浩大",
|
|
247
|
+
"興高采烈",
|
|
248
|
+
"惡有惡報",
|
|
249
|
+
"開門見山",
|
|
250
|
+
"粗心大意",
|
|
251
|
+
"一見鍾情",
|
|
252
|
+
"截然不同",
|
|
253
|
+
"獨一無二",
|
|
254
|
+
"與眾不同",
|
|
255
|
+
"大錯特錯",
|
|
256
|
+
"有朝一日",
|
|
257
|
+
"吹毛求疵",
|
|
258
|
+
"沉默寡言",
|
|
259
|
+
"雞毛蒜皮",
|
|
260
|
+
"胡說八道",
|
|
261
|
+
"瞭如指掌",
|
|
262
|
+
"無家可歸",
|
|
263
|
+
"亂七八糟",
|
|
264
|
+
"引人注目",
|
|
265
|
+
"大吃一驚",
|
|
266
|
+
"竭盡全力",
|
|
267
|
+
"五臟六腑",
|
|
268
|
+
"直截了當",
|
|
269
|
+
"出類拔萃",
|
|
270
|
+
"水落石出",
|
|
271
|
+
"傾盆大雨",
|
|
272
|
+
"完美無瑕",
|
|
273
|
+
"層出不窮",
|
|
274
|
+
"小心翼翼",
|
|
275
|
+
"威風凜凜",
|
|
276
|
+
"忠心耿耿",
|
|
277
|
+
"殺氣騰騰",
|
|
278
|
+
"興致勃勃",
|
|
279
|
+
"氣喘吁吁",
|
|
280
|
+
"憂心忡忡",
|
|
281
|
+
"咄咄逼人",
|
|
282
|
+
"滔滔不絕",
|
|
283
|
+
"念念不忘",
|
|
284
|
+
"源源不斷",
|
|
285
|
+
"息息相關",
|
|
286
|
+
"面面相覷",
|
|
287
|
+
];
|
|
288
|
+
/**
|
|
289
|
+
* Every 成语 written with the 2+2 hyphen, paired across the two scripts.
|
|
290
|
+
*/
|
|
291
|
+
export const HYPHENATED_IDIOMS = HANS.map((hans, at) => ({ hans, hant: HANT[at] ?? "" }));
|
|
292
|
+
/**
|
|
293
|
+
* Every spelling that takes the hyphen, which is how the rule asks.
|
|
294
|
+
*/
|
|
295
|
+
export const HYPHENATED_IDIOM_FORMS = new Set(HYPHENATED_IDIOMS.flatMap((idiom) => [idiom.hans, idiom.hant]));
|
|
296
|
+
//# sourceMappingURL=idiom-list.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"idiom-list.js","sourceRoot":"","sources":["../../src/orthography/idiom-list.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type GroupingRule } from "./rule.js";
|
|
2
|
+
/**
|
|
3
|
+
* The 成语 hyphen, from the list, since no rule reaches it.
|
|
4
|
+
*
|
|
5
|
+
* GB/T 16159 6.3.2 hyphenates a four-syllable 成语 that can be read as two
|
|
6
|
+
* disyllables and writes the rest solid. Which of the two an idiom is cannot be
|
|
7
|
+
* derived from anything this package holds — see
|
|
8
|
+
* [the list](./idiom-list.ts) for the measurement — so the list is the rule's
|
|
9
|
+
* whole evidence, and an idiom that is not on it is written the way it was
|
|
10
|
+
* before: solid, which is what the standard does with the ones that cannot be
|
|
11
|
+
* halved.
|
|
12
|
+
*
|
|
13
|
+
* Every entry decodes as a single four-syllable word, so this only ever cuts
|
|
14
|
+
* something the dictionary already agreed was one word, and cuts it where the
|
|
15
|
+
* list says.
|
|
16
|
+
*/
|
|
17
|
+
export declare const IDIOM_HYPHENS: GroupingRule;
|
|
18
|
+
//# sourceMappingURL=idioms.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"idioms.d.ts","sourceRoot":"","sources":["../../src/orthography/idioms.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,YAAY,EAAa,MAAM,WAAW,CAAC;AAEzD;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,aAAa,EAAE,YAM3B,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { HYPHENATED_IDIOM_FORMS } from "./idiom-list.js";
|
|
2
|
+
import { hyphenate } from "./rule.js";
|
|
3
|
+
/**
|
|
4
|
+
* The 成语 hyphen, from the list, since no rule reaches it.
|
|
5
|
+
*
|
|
6
|
+
* GB/T 16159 6.3.2 hyphenates a four-syllable 成语 that can be read as two
|
|
7
|
+
* disyllables and writes the rest solid. Which of the two an idiom is cannot be
|
|
8
|
+
* derived from anything this package holds — see
|
|
9
|
+
* [the list](./idiom-list.ts) for the measurement — so the list is the rule's
|
|
10
|
+
* whole evidence, and an idiom that is not on it is written the way it was
|
|
11
|
+
* before: solid, which is what the standard does with the ones that cannot be
|
|
12
|
+
* halved.
|
|
13
|
+
*
|
|
14
|
+
* Every entry decodes as a single four-syllable word, so this only ever cuts
|
|
15
|
+
* something the dictionary already agreed was one word, and cuts it where the
|
|
16
|
+
* list says.
|
|
17
|
+
*/
|
|
18
|
+
export const IDIOM_HYPHENS = {
|
|
19
|
+
name: "idiom-hyphens",
|
|
20
|
+
apply: (words) => words.flatMap((word) => HYPHENATED_IDIOM_FORMS.has(word.text) ? hyphenate(word, 2) : [word]),
|
|
21
|
+
};
|
|
22
|
+
//# sourceMappingURL=idioms.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"idioms.js","sourceRoot":"","sources":["../../src/orthography/idioms.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAqB,SAAS,EAAE,MAAM,WAAW,CAAC;AAEzD;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,aAAa,GAAiB;IACzC,IAAI,EAAE,eAAe;IACrB,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CACf,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CACrB,sBAAsB,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CACpE;CACJ,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { type GroupingRule } from "./rule.js";
|
|
2
|
+
/**
|
|
3
|
+
* The 重叠 hyphen inside a four-character AABB word.
|
|
4
|
+
*
|
|
5
|
+
* GB/T 16159 6.1.3 writes 干干净净 as `gāngān-jìngjìng`: one word, with the
|
|
6
|
+
* boundary between its halves marked. The shape *is* the evidence — a
|
|
7
|
+
* four-character word whose first two characters double and whose last two
|
|
8
|
+
* double is a reduplication and essentially nothing else — so this needs no
|
|
9
|
+
* tag, which matters given that two thirds of the dictionary carries none.
|
|
10
|
+
*
|
|
11
|
+
* Two conditions keep it honest, both sized against the whole dictionary. The
|
|
12
|
+
* word must have reached the rule as **one** decoded word: 爸爸妈妈 and 哥哥姐姐
|
|
13
|
+
* decode as two words each and are two words, `bàba māma`, not a reduplication
|
|
14
|
+
* of 爸妈. And a proper noun is left alone, since a name that happens to be
|
|
15
|
+
* shaped this way is not a reduplication of anything.
|
|
16
|
+
*
|
|
17
|
+
* Fires on 1,541 of the dictionary's 1,590 AABB keys; the 49 it holds back are
|
|
18
|
+
* all jieba proper-noun tags that CC-CEDICT did not veto — 斯斯文文, 老老少少,
|
|
19
|
+
* 正正经经 — which are mis-tagged rather than misjudged here, and are already
|
|
20
|
+
* wrong in their capitals for the same reason.
|
|
21
|
+
*
|
|
22
|
+
* Over 711,000 decoded words of Tatoeba and zh.wikipedia it fires 66 times,
|
|
23
|
+
* and all 66 are reduplications: 时时刻刻, 马马虎虎, 形形色色, 轰轰烈烈. What
|
|
24
|
+
* it misses is the same shape arriving as two words — 43 spans, of which about
|
|
25
|
+
* 16 are reduplications the decode happened to split (匆匆忙忙, 来来往往) and
|
|
26
|
+
* the rest are 爸爸妈妈, 爷爷奶奶 and 爸爸刚刚, where joining would be wrong.
|
|
27
|
+
* Nothing separates the two halves of that mixture: 匆匆 and 爸爸 are both
|
|
28
|
+
* words, and so are 匆忙 and 爸妈.
|
|
29
|
+
*/
|
|
30
|
+
export declare const AABB_REDUPLICATION: GroupingRule;
|
|
31
|
+
/**
|
|
32
|
+
* The 重叠 hyphen between a repeated two-character word: 研究研究.
|
|
33
|
+
*
|
|
34
|
+
* GB/T 16159 writes verb reduplication `yánjiū-yánjiū`, and this is the
|
|
35
|
+
* productive half of 重叠: 研究研究 is not a dictionary entry and never will be,
|
|
36
|
+
* so it arrives as two decoded words rather than as one word to be split.
|
|
37
|
+
* Marking the second is all that is needed, and no reading changes.
|
|
38
|
+
*
|
|
39
|
+
* The ABAB words the dictionary *does* hold are deliberately not touched: they
|
|
40
|
+
* decode as one word, and 50 keys are shaped this way with 哔哩哔哩 and
|
|
41
|
+
* 达姆达姆 among them, where a hyphen would be asserting a reduplication that
|
|
42
|
+
* is really a transliteration.
|
|
43
|
+
*
|
|
44
|
+
* Measured over the same 711,000 decoded words, it fires 54 times and is right
|
|
45
|
+
* 46 of them — 休息休息, 一天一天, 考虑考虑, 好久好久. The eight misfires are
|
|
46
|
+
* all one word ending a clause and the same word starting the next
|
|
47
|
+
* (告诉我们|我们在哪里, 不喜欢|喜欢不问问题的), or a noun said twice to
|
|
48
|
+
* address someone (大象大象). Nothing short of syntax separates those from
|
|
49
|
+
* 讨论讨论, and the eight are a spacing error where all 54 were one before.
|
|
50
|
+
*/
|
|
51
|
+
export declare const ABAB_REDUPLICATION: GroupingRule;
|
|
52
|
+
//# sourceMappingURL=reduplication.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reduplication.d.ts","sourceRoot":"","sources":["../../src/orthography/reduplication.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,YAAY,EAAa,MAAM,WAAW,CAAC;AAkBzD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,eAAO,MAAM,kBAAkB,EAAE,YAQhC,CAAC;AAyBF;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,kBAAkB,EAAE,YAShC,CAAC"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { toCharacters } from "../script/characters.js";
|
|
2
|
+
import { hyphenate } from "./rule.js";
|
|
3
|
+
/**
|
|
4
|
+
* Whether four characters repeat as AABB, with A and B different.
|
|
5
|
+
*
|
|
6
|
+
* 干干净净 and 高高兴兴 do; 一一得一 does not, and neither does a 叠字 name
|
|
7
|
+
* like 丁丁 doubled, since A and B have to differ for there to be two halves.
|
|
8
|
+
*/
|
|
9
|
+
function isAabb(characters) {
|
|
10
|
+
const [first, second, third, fourth] = characters;
|
|
11
|
+
return (characters.length === 4 &&
|
|
12
|
+
first === second &&
|
|
13
|
+
third === fourth &&
|
|
14
|
+
first !== third);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* The 重叠 hyphen inside a four-character AABB word.
|
|
18
|
+
*
|
|
19
|
+
* GB/T 16159 6.1.3 writes 干干净净 as `gāngān-jìngjìng`: one word, with the
|
|
20
|
+
* boundary between its halves marked. The shape *is* the evidence — a
|
|
21
|
+
* four-character word whose first two characters double and whose last two
|
|
22
|
+
* double is a reduplication and essentially nothing else — so this needs no
|
|
23
|
+
* tag, which matters given that two thirds of the dictionary carries none.
|
|
24
|
+
*
|
|
25
|
+
* Two conditions keep it honest, both sized against the whole dictionary. The
|
|
26
|
+
* word must have reached the rule as **one** decoded word: 爸爸妈妈 and 哥哥姐姐
|
|
27
|
+
* decode as two words each and are two words, `bàba māma`, not a reduplication
|
|
28
|
+
* of 爸妈. And a proper noun is left alone, since a name that happens to be
|
|
29
|
+
* shaped this way is not a reduplication of anything.
|
|
30
|
+
*
|
|
31
|
+
* Fires on 1,541 of the dictionary's 1,590 AABB keys; the 49 it holds back are
|
|
32
|
+
* all jieba proper-noun tags that CC-CEDICT did not veto — 斯斯文文, 老老少少,
|
|
33
|
+
* 正正经经 — which are mis-tagged rather than misjudged here, and are already
|
|
34
|
+
* wrong in their capitals for the same reason.
|
|
35
|
+
*
|
|
36
|
+
* Over 711,000 decoded words of Tatoeba and zh.wikipedia it fires 66 times,
|
|
37
|
+
* and all 66 are reduplications: 时时刻刻, 马马虎虎, 形形色色, 轰轰烈烈. What
|
|
38
|
+
* it misses is the same shape arriving as two words — 43 spans, of which about
|
|
39
|
+
* 16 are reduplications the decode happened to split (匆匆忙忙, 来来往往) and
|
|
40
|
+
* the rest are 爸爸妈妈, 爷爷奶奶 and 爸爸刚刚, where joining would be wrong.
|
|
41
|
+
* Nothing separates the two halves of that mixture: 匆匆 and 爸爸 are both
|
|
42
|
+
* words, and so are 匆忙 and 爸妈.
|
|
43
|
+
*/
|
|
44
|
+
export const AABB_REDUPLICATION = {
|
|
45
|
+
name: "aabb-reduplication",
|
|
46
|
+
apply: (words) => words.flatMap((word) => word.isProperNoun || !isAabb(toCharacters(word.text))
|
|
47
|
+
? [word]
|
|
48
|
+
: hyphenate(word, 2)),
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Whether two words are the same word repeated: 研究研究.
|
|
52
|
+
*
|
|
53
|
+
* Two characters each, because a one-character repeat is a different rule —
|
|
54
|
+
* 看看 is `kànkan`, written solid with a neutral second syllable — and because
|
|
55
|
+
* a repeated single character is as likely to be two separate words.
|
|
56
|
+
*
|
|
57
|
+
* Nothing is asked of the part of speech, which was measured rather than
|
|
58
|
+
* assumed: excluding noun-tagged repeats removes three misfires — 战争 falling
|
|
59
|
+
* either side of 克里米亚战争|战争中, and 大象大象 addressing an elephant
|
|
60
|
+
* twice — at the cost of four real reduplications, since jieba tags 商量,
|
|
61
|
+
* 多谢 and 拜托 as nouns. Fewer right answers for a better-looking rule.
|
|
62
|
+
*/
|
|
63
|
+
function isRepeat(word, previous) {
|
|
64
|
+
return (word.text === previous.text &&
|
|
65
|
+
word.isKnown &&
|
|
66
|
+
!word.isProperNoun &&
|
|
67
|
+
toCharacters(word.text).length === 2 &&
|
|
68
|
+
word.separator === undefined);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* The 重叠 hyphen between a repeated two-character word: 研究研究.
|
|
72
|
+
*
|
|
73
|
+
* GB/T 16159 writes verb reduplication `yánjiū-yánjiū`, and this is the
|
|
74
|
+
* productive half of 重叠: 研究研究 is not a dictionary entry and never will be,
|
|
75
|
+
* so it arrives as two decoded words rather than as one word to be split.
|
|
76
|
+
* Marking the second is all that is needed, and no reading changes.
|
|
77
|
+
*
|
|
78
|
+
* The ABAB words the dictionary *does* hold are deliberately not touched: they
|
|
79
|
+
* decode as one word, and 50 keys are shaped this way with 哔哩哔哩 and
|
|
80
|
+
* 达姆达姆 among them, where a hyphen would be asserting a reduplication that
|
|
81
|
+
* is really a transliteration.
|
|
82
|
+
*
|
|
83
|
+
* Measured over the same 711,000 decoded words, it fires 54 times and is right
|
|
84
|
+
* 46 of them — 休息休息, 一天一天, 考虑考虑, 好久好久. The eight misfires are
|
|
85
|
+
* all one word ending a clause and the same word starting the next
|
|
86
|
+
* (告诉我们|我们在哪里, 不喜欢|喜欢不问问题的), or a noun said twice to
|
|
87
|
+
* address someone (大象大象). Nothing short of syntax separates those from
|
|
88
|
+
* 讨论讨论, and the eight are a spacing error where all 54 were one before.
|
|
89
|
+
*/
|
|
90
|
+
export const ABAB_REDUPLICATION = {
|
|
91
|
+
name: "abab-reduplication",
|
|
92
|
+
apply: (words) => words.map((word, at) => {
|
|
93
|
+
const previous = words[at - 1];
|
|
94
|
+
return previous !== undefined && isRepeat(word, previous)
|
|
95
|
+
? { ...word, separator: "-" }
|
|
96
|
+
: word;
|
|
97
|
+
}),
|
|
98
|
+
};
|
|
99
|
+
//# sourceMappingURL=reduplication.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reduplication.js","sourceRoot":"","sources":["../../src/orthography/reduplication.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAqB,SAAS,EAAE,MAAM,WAAW,CAAC;AAEzD;;;;;GAKG;AACH,SAAS,MAAM,CAAC,UAA6B;IAC3C,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,UAAU,CAAC;IAClD,OAAO,CACL,UAAU,CAAC,MAAM,KAAK,CAAC;QACvB,KAAK,KAAK,MAAM;QAChB,KAAK,KAAK,MAAM;QAChB,KAAK,KAAK,KAAK,CAChB,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAiB;IAC9C,IAAI,EAAE,oBAAoB;IAC1B,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CACf,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CACrB,IAAI,CAAC,YAAY,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnD,CAAC,CAAC,CAAC,IAAI,CAAC;QACR,CAAC,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,CACvB;CACJ,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,SAAS,QAAQ,CAAC,IAAiB,EAAE,QAAqB;IACxD,OAAO,CACL,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,IAAI;QAC3B,IAAI,CAAC,OAAO;QACZ,CAAC,IAAI,CAAC,YAAY;QAClB,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC;QACpC,IAAI,CAAC,SAAS,KAAK,SAAS,CAC7B,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAiB;IAC9C,IAAI,EAAE,oBAAoB;IAC1B,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CACf,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,EAAE,EAAE;QACrB,MAAM,QAAQ,GAAG,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;QAC/B,OAAO,QAAQ,KAAK,SAAS,IAAI,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;YACvD,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,SAAS,EAAE,GAAY,EAAE;YACtC,CAAC,CAAC,IAAI,CAAC;IACX,CAAC,CAAC;CACL,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { DecodedWord } from "../decode/word.js";
|
|
2
|
+
import type { Dictionary } from "../dictionary/dictionary.js";
|
|
3
|
+
/**
|
|
4
|
+
* One 分词连写 rule, rewriting the words a decode produced.
|
|
5
|
+
*
|
|
6
|
+
* Typed and individually testable, which is the point ALGORITHM.md makes about
|
|
7
|
+
* rules: the old project patched the output string with regexes, so its rules
|
|
8
|
+
* were order-dependent and could not be tested apart from each other.
|
|
9
|
+
*/
|
|
10
|
+
export interface GroupingRule {
|
|
11
|
+
readonly name: string;
|
|
12
|
+
readonly apply: (words: readonly DecodedWord[], dictionary: Dictionary) => readonly DecodedWord[];
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Join two decoded words into one.
|
|
16
|
+
*
|
|
17
|
+
* The first word's flags carry, because it is the head: 看了 is the verb 看
|
|
18
|
+
* with an aspect particle stuck to it, not a new word of its own.
|
|
19
|
+
*/
|
|
20
|
+
export declare function join(head: DecodedWord, tail: DecodedWord): DecodedWord;
|
|
21
|
+
/**
|
|
22
|
+
* Write a word as two halves with a hyphen between them.
|
|
23
|
+
*
|
|
24
|
+
* The 重叠 and 成语 hyphens are the same operation on different evidence: cut
|
|
25
|
+
* the word, mark the second half, and leave the reading exactly as it was. The
|
|
26
|
+
* word is returned untouched where its reading cannot be cut — 儿化 has no
|
|
27
|
+
* halves.
|
|
28
|
+
*/
|
|
29
|
+
export declare function hyphenate(word: DecodedWord, at: number): readonly DecodedWord[];
|
|
30
|
+
/**
|
|
31
|
+
* Divide a decoded word at every one of a list of character offsets.
|
|
32
|
+
*
|
|
33
|
+
* {@link splitAt} generalised, for the proper names whose parts CC-CEDICT marks
|
|
34
|
+
* more than two of: 上海交通大学 divides at 2 and 4, and cutting only at the
|
|
35
|
+
* first would leave `Shànghǎi Jiāotōngdàxué`.
|
|
36
|
+
*
|
|
37
|
+
* The word comes back whole where its reading cannot be cut — the same 儿化
|
|
38
|
+
* condition {@link splitAt} has — or where an offset is out of order or outside
|
|
39
|
+
* the word, since a boundary that does not describe this word cannot be applied
|
|
40
|
+
* to it.
|
|
41
|
+
*/
|
|
42
|
+
export declare function divideAt(word: DecodedWord, offsets: readonly number[]): readonly DecodedWord[];
|
|
43
|
+
/**
|
|
44
|
+
* Split a decoded word into two at a character offset.
|
|
45
|
+
*
|
|
46
|
+
* Only possible where the reading has one syllable per character, which 儿化
|
|
47
|
+
* does not: there is no way to cut `wánr` in half.
|
|
48
|
+
*/
|
|
49
|
+
export declare function splitAt(word: DecodedWord, at: number): readonly [DecodedWord, DecodedWord] | undefined;
|
|
50
|
+
//# sourceMappingURL=rule.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rule.d.ts","sourceRoot":"","sources":["../../src/orthography/rule.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAG9D;;;;;;GAMG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,CACd,KAAK,EAAE,SAAS,WAAW,EAAE,EAC7B,UAAU,EAAE,UAAU,KACnB,SAAS,WAAW,EAAE,CAAC;CAC7B;AAED;;;;;GAKG;AACH,wBAAgB,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,WAAW,GAAG,WAAW,CAStE;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CACvB,IAAI,EAAE,WAAW,EACjB,EAAE,EAAE,MAAM,GACT,SAAS,WAAW,EAAE,CAOxB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,QAAQ,CACtB,IAAI,EAAE,WAAW,EACjB,OAAO,EAAE,SAAS,MAAM,EAAE,GACzB,SAAS,WAAW,EAAE,CA2BxB;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CACrB,IAAI,EAAE,WAAW,EACjB,EAAE,EAAE,MAAM,GACT,SAAS,CAAC,WAAW,EAAE,WAAW,CAAC,GAAG,SAAS,CAsBjD"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { toCharacters } from "../script/characters.js";
|
|
2
|
+
/**
|
|
3
|
+
* Join two decoded words into one.
|
|
4
|
+
*
|
|
5
|
+
* The first word's flags carry, because it is the head: 看了 is the verb 看
|
|
6
|
+
* with an aspect particle stuck to it, not a new word of its own.
|
|
7
|
+
*/
|
|
8
|
+
export function join(head, tail) {
|
|
9
|
+
return {
|
|
10
|
+
text: head.text + tail.text,
|
|
11
|
+
reading: [...head.reading, ...tail.reading],
|
|
12
|
+
isProperNoun: head.isProperNoun,
|
|
13
|
+
partOfSpeech: head.partOfSpeech,
|
|
14
|
+
isKnown: head.isKnown && tail.isKnown,
|
|
15
|
+
...(head.separator !== undefined && { separator: head.separator }),
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Write a word as two halves with a hyphen between them.
|
|
20
|
+
*
|
|
21
|
+
* The 重叠 and 成语 hyphens are the same operation on different evidence: cut
|
|
22
|
+
* the word, mark the second half, and leave the reading exactly as it was. The
|
|
23
|
+
* word is returned untouched where its reading cannot be cut — 儿化 has no
|
|
24
|
+
* halves.
|
|
25
|
+
*/
|
|
26
|
+
export function hyphenate(word, at) {
|
|
27
|
+
const split = splitAt(word, at);
|
|
28
|
+
if (split === undefined) {
|
|
29
|
+
return [word];
|
|
30
|
+
}
|
|
31
|
+
const [head, tail] = split;
|
|
32
|
+
return [head, { ...tail, separator: "-" }];
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Divide a decoded word at every one of a list of character offsets.
|
|
36
|
+
*
|
|
37
|
+
* {@link splitAt} generalised, for the proper names whose parts CC-CEDICT marks
|
|
38
|
+
* more than two of: 上海交通大学 divides at 2 and 4, and cutting only at the
|
|
39
|
+
* first would leave `Shànghǎi Jiāotōngdàxué`.
|
|
40
|
+
*
|
|
41
|
+
* The word comes back whole where its reading cannot be cut — the same 儿化
|
|
42
|
+
* condition {@link splitAt} has — or where an offset is out of order or outside
|
|
43
|
+
* the word, since a boundary that does not describe this word cannot be applied
|
|
44
|
+
* to it.
|
|
45
|
+
*/
|
|
46
|
+
export function divideAt(word, offsets) {
|
|
47
|
+
const characters = toCharacters(word.text);
|
|
48
|
+
if (word.reading.length !== characters.length) {
|
|
49
|
+
return [word];
|
|
50
|
+
}
|
|
51
|
+
const cuts = [0, ...offsets, characters.length];
|
|
52
|
+
const isOrdered = cuts.every((at, index) => index === 0 || at > (cuts[index - 1] ?? 0));
|
|
53
|
+
if (!isOrdered || (offsets.at(-1) ?? 0) >= characters.length) {
|
|
54
|
+
return [word];
|
|
55
|
+
}
|
|
56
|
+
return cuts.slice(0, -1).map((from, index) => {
|
|
57
|
+
const to = cuts[index + 1] ?? characters.length;
|
|
58
|
+
const part = {
|
|
59
|
+
text: characters.slice(from, to).join(""),
|
|
60
|
+
reading: word.reading.slice(from, to),
|
|
61
|
+
isProperNoun: word.isProperNoun,
|
|
62
|
+
partOfSpeech: word.partOfSpeech,
|
|
63
|
+
isKnown: word.isKnown,
|
|
64
|
+
};
|
|
65
|
+
// Only the head keeps what was written in front of the word: every later
|
|
66
|
+
// part is written against the part before it rather than against that.
|
|
67
|
+
return index === 0 && word.separator !== undefined
|
|
68
|
+
? { ...part, separator: word.separator }
|
|
69
|
+
: part;
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Split a decoded word into two at a character offset.
|
|
74
|
+
*
|
|
75
|
+
* Only possible where the reading has one syllable per character, which 儿化
|
|
76
|
+
* does not: there is no way to cut `wánr` in half.
|
|
77
|
+
*/
|
|
78
|
+
export function splitAt(word, at) {
|
|
79
|
+
const characters = toCharacters(word.text);
|
|
80
|
+
if (word.reading.length !== characters.length) {
|
|
81
|
+
return undefined;
|
|
82
|
+
}
|
|
83
|
+
const part = (from, to) => ({
|
|
84
|
+
text: characters.slice(from, to).join(""),
|
|
85
|
+
reading: word.reading.slice(from, to),
|
|
86
|
+
isProperNoun: word.isProperNoun,
|
|
87
|
+
partOfSpeech: word.partOfSpeech,
|
|
88
|
+
isKnown: word.isKnown,
|
|
89
|
+
});
|
|
90
|
+
const head = part(0, at);
|
|
91
|
+
return [
|
|
92
|
+
// Only the head keeps whatever was written in front of the word, since the
|
|
93
|
+
// tail is now written against the head rather than against what came
|
|
94
|
+
// before it.
|
|
95
|
+
word.separator === undefined
|
|
96
|
+
? head
|
|
97
|
+
: { ...head, separator: word.separator },
|
|
98
|
+
part(at, characters.length),
|
|
99
|
+
];
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=rule.js.map
|