@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,111 @@
|
|
|
1
|
+
import { DIGIT_CHARACTERS } from "./characters.js";
|
|
2
|
+
/**
|
|
3
|
+
* The places inside one group of four digits, largest first.
|
|
4
|
+
*/
|
|
5
|
+
const PLACES = ["千", "百", "十", ""];
|
|
6
|
+
/**
|
|
7
|
+
* The group separators, in the order the groups come off the number.
|
|
8
|
+
*/
|
|
9
|
+
const GROUPS = ["", "万", "亿", "万亿"];
|
|
10
|
+
/**
|
|
11
|
+
* How many digits one group holds.
|
|
12
|
+
*
|
|
13
|
+
* Chinese numbers are grouped by 万 rather than by thousands, which is why a
|
|
14
|
+
* group is four digits wide and why 12,345 is *one* 万 and 2,345.
|
|
15
|
+
*/
|
|
16
|
+
const GROUP_DIGITS = 4;
|
|
17
|
+
/**
|
|
18
|
+
* The largest number this can write, being four groups of four digits.
|
|
19
|
+
*/
|
|
20
|
+
export const LARGEST_CARDINAL = 10 ** 16 - 1;
|
|
21
|
+
/**
|
|
22
|
+
* Whether a lone 2 opening this group takes 两.
|
|
23
|
+
*/
|
|
24
|
+
function isLiang(liang, isLeading) {
|
|
25
|
+
return liang === "always" || (liang === "leading" && isLeading);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* The character a digit takes in a place: 两 before a 千, 二 otherwise.
|
|
29
|
+
*/
|
|
30
|
+
function digitAt(value, place, isFirst, options) {
|
|
31
|
+
return value === 2 &&
|
|
32
|
+
place === "千" &&
|
|
33
|
+
isLiang(options.liang, options.isLeading && isFirst)
|
|
34
|
+
? "两"
|
|
35
|
+
: (DIGIT_CHARACTERS[value] ?? "");
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Write one group of at most four digits: 2345 as 二千三百四十五.
|
|
39
|
+
*
|
|
40
|
+
* Empty for a group that is all zeros. A run of zeros inside the group becomes
|
|
41
|
+
* one 零, and only where a non-zero digit follows it: 1,005 is 一千零五 while
|
|
42
|
+
* 1,500 is 一千五百.
|
|
43
|
+
*/
|
|
44
|
+
function writeGroup(group, options) {
|
|
45
|
+
const digits = String(group).padStart(GROUP_DIGITS, "0").split("");
|
|
46
|
+
let written = "";
|
|
47
|
+
let isPending = false;
|
|
48
|
+
for (const [at, digit] of digits.entries()) {
|
|
49
|
+
const value = Number(digit);
|
|
50
|
+
if (value === 0) {
|
|
51
|
+
isPending = written !== "";
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
const place = PLACES[at] ?? "";
|
|
55
|
+
if (isPending) {
|
|
56
|
+
written += "零";
|
|
57
|
+
isPending = false;
|
|
58
|
+
}
|
|
59
|
+
// 十五 rather than 一十五: the 一 drops only from a bare leading 十, so
|
|
60
|
+
// 一百一十五 keeps it and so does the 一十五 inside 一万零一十五.
|
|
61
|
+
const isBareTen = value === 1 && place === "十" && written === "" && options.isLeading;
|
|
62
|
+
written += isBareTen
|
|
63
|
+
? place
|
|
64
|
+
: digitAt(value, place, written === "", options) + place;
|
|
65
|
+
}
|
|
66
|
+
return written;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Write a non-negative integer as a cardinal: 12345 → 一万二千三百四十五.
|
|
70
|
+
*
|
|
71
|
+
* The awkward parts are 零 and the bare 十, and both are about saying the
|
|
72
|
+
* number aloud rather than about arithmetic. A 零 goes where a place is skipped
|
|
73
|
+
* inside* the spoken number (一千零五) and not where the number simply ends
|
|
74
|
+
* (一千五百), which is the same question one level up between groups: 25,000 is
|
|
75
|
+
* 两万五千 because the lower group fills its 千, and 20,050 is 两万零五十
|
|
76
|
+
* because it does not.
|
|
77
|
+
* @throws {RangeError} for a negative, a fraction, or anything above 10^16.
|
|
78
|
+
*/
|
|
79
|
+
export function cardinalHanzi(value, options = {}) {
|
|
80
|
+
if (!Number.isSafeInteger(value) || value < 0 || value > LARGEST_CARDINAL) {
|
|
81
|
+
throw new RangeError(`not a writable whole number: ${String(value)}`);
|
|
82
|
+
}
|
|
83
|
+
if (value === 0) {
|
|
84
|
+
return "零";
|
|
85
|
+
}
|
|
86
|
+
const { liang = "always" } = options;
|
|
87
|
+
const groups = [];
|
|
88
|
+
for (let rest = value; rest > 0; rest = Math.floor(rest / 10_000)) {
|
|
89
|
+
groups.push(rest % 10_000);
|
|
90
|
+
}
|
|
91
|
+
let written = "";
|
|
92
|
+
for (const [at, group] of groups.entries()) {
|
|
93
|
+
if (group === 0) {
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
const unit = GROUPS[at] ?? "";
|
|
97
|
+
const body = writeGroup(group, {
|
|
98
|
+
isLeading: at === groups.length - 1,
|
|
99
|
+
liang,
|
|
100
|
+
});
|
|
101
|
+
// The group immediately below decides whether a 零 is spoken between them:
|
|
102
|
+
// it is needed unless that group fills its own 千 place.
|
|
103
|
+
const below = groups[at - 1] ?? 0;
|
|
104
|
+
const gap = written !== "" && below < 1000 ? "零" : "";
|
|
105
|
+
const isLeading = at === groups.length - 1;
|
|
106
|
+
const lone = body === "二" && unit !== "" && isLiang(liang, isLeading) ? "两" : body;
|
|
107
|
+
written = lone + unit + gap + written;
|
|
108
|
+
}
|
|
109
|
+
return written;
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=cardinal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cardinal.js","sourceRoot":"","sources":["../../src/numerals/cardinal.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { type Syllable } from "../syllable/syllable.js";
|
|
2
|
+
/**
|
|
3
|
+
* The 汉字 a digit is written with, indexed by its value.
|
|
4
|
+
*/
|
|
5
|
+
export declare const DIGIT_CHARACTERS = "\u96F6\u4E00\u4E8C\u4E09\u56DB\u4E94\u516D\u4E03\u516B\u4E5D";
|
|
6
|
+
/**
|
|
7
|
+
* The other 汉字 a written number is made of, and what each is worth.
|
|
8
|
+
*
|
|
9
|
+
* 十, 百 and 千 are the places inside a group of four; 万 and 亿 are the group
|
|
10
|
+
* separators, which is what makes Chinese numbers myriad-grouped rather than
|
|
11
|
+
* thousand-grouped: 12,345 is 一万二千三百四十五, one 万 and 2,345.
|
|
12
|
+
*/
|
|
13
|
+
export declare const UNIT_VALUES: ReadonlyMap<string, number>;
|
|
14
|
+
/**
|
|
15
|
+
* Read one numeral character.
|
|
16
|
+
*
|
|
17
|
+
* Undefined for anything that is not one, which is how a caller tells a
|
|
18
|
+
* numeral apart from the text around it.
|
|
19
|
+
*/
|
|
20
|
+
export declare function numeralSyllable(character: string): Syllable | undefined;
|
|
21
|
+
/**
|
|
22
|
+
* `yāo`, which is how 一 is said when digits are read out one at a time.
|
|
23
|
+
*
|
|
24
|
+
* 110 is `yāo yāo líng` and 120 is `yāo èr líng`, because `yī` and `qī` are
|
|
25
|
+
* hard to tell apart over a bad line. It is a reading of the digit rather than
|
|
26
|
+
* a different digit — 一 is still written — and it belongs to phone numbers,
|
|
27
|
+
* room numbers and the like rather than to counting, which is why it is a
|
|
28
|
+
* separate reading here and an option rather than a rule.
|
|
29
|
+
*/
|
|
30
|
+
export declare function yaoSyllable(): Syllable | undefined;
|
|
31
|
+
//# sourceMappingURL=characters.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"characters.d.ts","sourceRoot":"","sources":["../../src/numerals/characters.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAEtE;;GAEG;AACH,eAAO,MAAM,gBAAgB,iEAAe,CAAC;AAE7C;;;;;;GAMG;AACH,eAAO,MAAM,WAAW,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAMlD,CAAC;AAyCH;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,CAGvE;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,IAAI,QAAQ,GAAG,SAAS,CAElD"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { readSyllable } from "../syllable/syllable.js";
|
|
2
|
+
/**
|
|
3
|
+
* The 汉字 a digit is written with, indexed by its value.
|
|
4
|
+
*/
|
|
5
|
+
export const DIGIT_CHARACTERS = "零一二三四五六七八九";
|
|
6
|
+
/**
|
|
7
|
+
* The other 汉字 a written number is made of, and what each is worth.
|
|
8
|
+
*
|
|
9
|
+
* 十, 百 and 千 are the places inside a group of four; 万 and 亿 are the group
|
|
10
|
+
* separators, which is what makes Chinese numbers myriad-grouped rather than
|
|
11
|
+
* thousand-grouped: 12,345 is 一万二千三百四十五, one 万 and 2,345.
|
|
12
|
+
*/
|
|
13
|
+
export const UNIT_VALUES = new Map([
|
|
14
|
+
["十", 10],
|
|
15
|
+
["百", 100],
|
|
16
|
+
["千", 1000],
|
|
17
|
+
["万", 10_000],
|
|
18
|
+
["亿", 100_000_000],
|
|
19
|
+
]);
|
|
20
|
+
/**
|
|
21
|
+
* Every character a number can be written with, and how it is read.
|
|
22
|
+
*
|
|
23
|
+
* This is the whole of the numerals' data — twenty-odd readings, carried here
|
|
24
|
+
* rather than looked up, because reading a number needs no dictionary and a
|
|
25
|
+
* package that needed one for it would be the wrong shape. Readings are
|
|
26
|
+
* underlying*: 一 is `yī` and 不 would be `bù`, with the contextual tone left
|
|
27
|
+
* to the sandhi pass, exactly as the dictionary stores them.
|
|
28
|
+
*/
|
|
29
|
+
const READINGS = new Map([
|
|
30
|
+
["零", "líng"],
|
|
31
|
+
["〇", "líng"],
|
|
32
|
+
["一", "yī"],
|
|
33
|
+
["二", "èr"],
|
|
34
|
+
["两", "liǎng"],
|
|
35
|
+
["兩", "liǎng"],
|
|
36
|
+
["三", "sān"],
|
|
37
|
+
["四", "sì"],
|
|
38
|
+
["五", "wǔ"],
|
|
39
|
+
["六", "liù"],
|
|
40
|
+
["七", "qī"],
|
|
41
|
+
["八", "bā"],
|
|
42
|
+
["九", "jiǔ"],
|
|
43
|
+
["十", "shí"],
|
|
44
|
+
["百", "bǎi"],
|
|
45
|
+
["千", "qiān"],
|
|
46
|
+
["万", "wàn"],
|
|
47
|
+
["萬", "wàn"],
|
|
48
|
+
["亿", "yì"],
|
|
49
|
+
["億", "yì"],
|
|
50
|
+
["点", "diǎn"],
|
|
51
|
+
["點", "diǎn"],
|
|
52
|
+
["负", "fù"],
|
|
53
|
+
["負", "fù"],
|
|
54
|
+
["分", "fēn"],
|
|
55
|
+
["之", "zhī"],
|
|
56
|
+
["百分之", "bǎi fēn zhī"],
|
|
57
|
+
]);
|
|
58
|
+
/**
|
|
59
|
+
* Read one numeral character.
|
|
60
|
+
*
|
|
61
|
+
* Undefined for anything that is not one, which is how a caller tells a
|
|
62
|
+
* numeral apart from the text around it.
|
|
63
|
+
*/
|
|
64
|
+
export function numeralSyllable(character) {
|
|
65
|
+
const spelling = READINGS.get(character);
|
|
66
|
+
return spelling === undefined ? undefined : readSyllable(spelling);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* `yāo`, which is how 一 is said when digits are read out one at a time.
|
|
70
|
+
*
|
|
71
|
+
* 110 is `yāo yāo líng` and 120 is `yāo èr líng`, because `yī` and `qī` are
|
|
72
|
+
* hard to tell apart over a bad line. It is a reading of the digit rather than
|
|
73
|
+
* a different digit — 一 is still written — and it belongs to phone numbers,
|
|
74
|
+
* room numbers and the like rather than to counting, which is why it is a
|
|
75
|
+
* separate reading here and an option rather than a rule.
|
|
76
|
+
*/
|
|
77
|
+
export function yaoSyllable() {
|
|
78
|
+
return readSyllable("yāo");
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=characters.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"characters.js","sourceRoot":"","sources":["../../src/numerals/characters.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAiB,MAAM,yBAAyB,CAAC;AAEtE;;GAEG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,YAAY,CAAC;AAE7C;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,WAAW,GAAgC,IAAI,GAAG,CAAC;IAC9D,CAAC,GAAG,EAAE,EAAE,CAAC;IACT,CAAC,GAAG,EAAE,GAAG,CAAC;IACV,CAAC,GAAG,EAAE,IAAI,CAAC;IACX,CAAC,GAAG,EAAE,MAAM,CAAC;IACb,CAAC,GAAG,EAAE,WAAW,CAAC;CACnB,CAAC,CAAC;AAEH;;;;;;;;GAQG;AACH,MAAM,QAAQ,GAAgC,IAAI,GAAG,CAAC;IACpD,CAAC,GAAG,EAAE,MAAM,CAAC;IACb,CAAC,GAAG,EAAE,MAAM,CAAC;IACb,CAAC,GAAG,EAAE,IAAI,CAAC;IACX,CAAC,GAAG,EAAE,IAAI,CAAC;IACX,CAAC,GAAG,EAAE,OAAO,CAAC;IACd,CAAC,GAAG,EAAE,OAAO,CAAC;IACd,CAAC,GAAG,EAAE,KAAK,CAAC;IACZ,CAAC,GAAG,EAAE,IAAI,CAAC;IACX,CAAC,GAAG,EAAE,IAAI,CAAC;IACX,CAAC,GAAG,EAAE,KAAK,CAAC;IACZ,CAAC,GAAG,EAAE,IAAI,CAAC;IACX,CAAC,GAAG,EAAE,IAAI,CAAC;IACX,CAAC,GAAG,EAAE,KAAK,CAAC;IACZ,CAAC,GAAG,EAAE,KAAK,CAAC;IACZ,CAAC,GAAG,EAAE,KAAK,CAAC;IACZ,CAAC,GAAG,EAAE,MAAM,CAAC;IACb,CAAC,GAAG,EAAE,KAAK,CAAC;IACZ,CAAC,GAAG,EAAE,KAAK,CAAC;IACZ,CAAC,GAAG,EAAE,IAAI,CAAC;IACX,CAAC,GAAG,EAAE,IAAI,CAAC;IACX,CAAC,GAAG,EAAE,MAAM,CAAC;IACb,CAAC,GAAG,EAAE,MAAM,CAAC;IACb,CAAC,GAAG,EAAE,IAAI,CAAC;IACX,CAAC,GAAG,EAAE,IAAI,CAAC;IACX,CAAC,GAAG,EAAE,KAAK,CAAC;IACZ,CAAC,GAAG,EAAE,KAAK,CAAC;IACZ,CAAC,KAAK,EAAE,aAAa,CAAC;CACvB,CAAC,CAAC;AAEH;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,SAAiB;IAC/C,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACzC,OAAO,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;AACrE,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,WAAW;IACzB,OAAO,YAAY,CAAC,KAAK,CAAC,CAAC;AAC7B,CAAC"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import type { Syllable } from "../syllable/syllable.js";
|
|
2
|
+
import { type CardinalOptions } from "./cardinal.js";
|
|
3
|
+
/**
|
|
4
|
+
* How a number is said: as a quantity, or digit by digit.
|
|
5
|
+
*
|
|
6
|
+
* The distinction is the whole of this module's difficulty, because the *same*
|
|
7
|
+
* digits go both ways depending on what they are counting. 2026年 is
|
|
8
|
+
* `èr líng èr liù nián`, read out one digit at a time, and 2026个 is
|
|
9
|
+
* `liǎng qiān líng èr shí liù gè`, counted. Nothing about the number says
|
|
10
|
+
* which; only what follows it does, so the choice belongs to the caller and
|
|
11
|
+
* this module will do either.
|
|
12
|
+
*/
|
|
13
|
+
export type NumeralStyle = "cardinal" | "digits";
|
|
14
|
+
/**
|
|
15
|
+
* How a number should be written and read.
|
|
16
|
+
*/
|
|
17
|
+
export interface NumeralOptions extends CardinalOptions {
|
|
18
|
+
/** Defaults to `cardinal`. */
|
|
19
|
+
readonly style?: NumeralStyle;
|
|
20
|
+
/**
|
|
21
|
+
* Whether 1 is read `yāo` when the digits are read out one at a time.
|
|
22
|
+
*
|
|
23
|
+
* Off by default and meaningless outside `digits`. 110 is `yāo yāo líng` and
|
|
24
|
+
* a room number is said the same way, because `yī` and `qī` are hard to tell
|
|
25
|
+
* apart down a bad line — but 2019 is `èr líng yī jiǔ` with an ordinary `yī`,
|
|
26
|
+
* so this is a property of what is being said rather than of the digits.
|
|
27
|
+
*/
|
|
28
|
+
readonly yao?: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Which zero the digit style writes. Defaults to 〇, as dates and years do.
|
|
31
|
+
*/
|
|
32
|
+
readonly zero?: "零" | "〇";
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Write a number in 汉字: 12345 → 一万二千三百四十五, or 一二三四五.
|
|
36
|
+
*
|
|
37
|
+
* Undefined for anything that is not a number, and for a `cardinal` whose whole
|
|
38
|
+
* part is too large to write — a digit string is not limited that way, since
|
|
39
|
+
* reading digits out needs no arithmetic at all.
|
|
40
|
+
*
|
|
41
|
+
* The fractional part is always read digit by digit whatever the style, because
|
|
42
|
+
* that is how it is said: 3.14 is 三点一四 and never 三点十四.
|
|
43
|
+
*/
|
|
44
|
+
export declare function numeralHanzi(value: string | number, options?: NumeralOptions): string | undefined;
|
|
45
|
+
/**
|
|
46
|
+
* Read written numeral 汉字 as syllables.
|
|
47
|
+
*
|
|
48
|
+
* Undefined where the text holds anything that is not a numeral character, so a
|
|
49
|
+
* caller can tell "not a number" from a number that reads oddly.
|
|
50
|
+
*/
|
|
51
|
+
export declare function readNumeralHanzi(hanzi: string, options?: NumeralOptions): readonly Syllable[] | undefined;
|
|
52
|
+
/**
|
|
53
|
+
* Read a number as syllables: 2019 as `èr líng yī jiǔ`, or as a quantity.
|
|
54
|
+
*
|
|
55
|
+
* The readings are *underlying*, as the dictionary's are — 一 is `yī` however
|
|
56
|
+
* it will be said in context — so a caller assembling a longer utterance runs
|
|
57
|
+
* the sandhi pass over the result and gets `yìbǎi` and `yí gè` from it. That is
|
|
58
|
+
* the same contract `decodeRun` has, and it is what keeps a number from having
|
|
59
|
+
* to know what follows it.
|
|
60
|
+
*/
|
|
61
|
+
export declare function readNumeral(value: string | number, options?: NumeralOptions): readonly Syllable[] | undefined;
|
|
62
|
+
/**
|
|
63
|
+
* Write a percentage the way it is said: 95% → 百分之九十五.
|
|
64
|
+
*
|
|
65
|
+
* The order reverses — "of a hundred parts, ninety-five" — which is why this
|
|
66
|
+
* cannot be left to whoever writes the number and the sign separately.
|
|
67
|
+
*/
|
|
68
|
+
export declare function percentHanzi(value: string | number, options?: NumeralOptions): string | undefined;
|
|
69
|
+
/**
|
|
70
|
+
* Write a fraction the way it is said: 3/4 → 四分之三.
|
|
71
|
+
*
|
|
72
|
+
* Same reversal as a percentage, of which this is the general case: the
|
|
73
|
+
* denominator is named first and the numerator second.
|
|
74
|
+
*/
|
|
75
|
+
export declare function fractionHanzi(numerator: string | number, denominator: string | number, options?: NumeralOptions): string | undefined;
|
|
76
|
+
//# sourceMappingURL=numerals.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"numerals.d.ts","sourceRoot":"","sources":["../../src/numerals/numerals.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAEL,KAAK,eAAe,EAErB,MAAM,eAAe,CAAC;AAOvB;;;;;;;;;GASG;AACH,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG,QAAQ,CAAC;AAEjD;;GAEG;AACH,MAAM,WAAW,cAAe,SAAQ,eAAe;IACrD,8BAA8B;IAC9B,QAAQ,CAAC,KAAK,CAAC,EAAE,YAAY,CAAC;IAC9B;;;;;;;OAOG;IACH,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC;IACvB;;OAEG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,GAAG,GAAG,GAAG,CAAC;CAC3B;AAiDD;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,MAAM,GAAG,MAAM,EACtB,OAAO,GAAE,cAAmB,GAC3B,MAAM,GAAG,SAAS,CAqBpB;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,cAAmB,GAC3B,SAAS,QAAQ,EAAE,GAAG,SAAS,CAajC;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,MAAM,GAAG,MAAM,EACtB,OAAO,GAAE,cAAmB,GAC3B,SAAS,QAAQ,EAAE,GAAG,SAAS,CAGjC;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,MAAM,GAAG,MAAM,EACtB,OAAO,GAAE,cAAmB,GAC3B,MAAM,GAAG,SAAS,CAGpB;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,SAAS,EAAE,MAAM,GAAG,MAAM,EAC1B,WAAW,EAAE,MAAM,GAAG,MAAM,EAC5B,OAAO,GAAE,cAAmB,GAC3B,MAAM,GAAG,SAAS,CAMpB"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { toCharacters } from "../script/characters.js";
|
|
2
|
+
import { cardinalHanzi, LARGEST_CARDINAL, } from "./cardinal.js";
|
|
3
|
+
import { DIGIT_CHARACTERS, numeralSyllable, yaoSyllable, } from "./characters.js";
|
|
4
|
+
/**
|
|
5
|
+
* Anything this module will read: digits, optionally signed and pointed.
|
|
6
|
+
*/
|
|
7
|
+
const NUMBER = /^(?<sign>-?)(?<whole>\d+)(?:\.(?<fraction>\d+))?$/u;
|
|
8
|
+
/**
|
|
9
|
+
* Take a number apart, keeping the digits exactly as they were written.
|
|
10
|
+
*
|
|
11
|
+
* A string rather than a number is the input that carries the most: `007` and
|
|
12
|
+
* `7` are the same quantity and different digits, and a room number keeps its
|
|
13
|
+
* zeros. A `number` is stringified first, which is why a caller who cares about
|
|
14
|
+
* leading zeros should pass the string.
|
|
15
|
+
*/
|
|
16
|
+
function parse(value) {
|
|
17
|
+
const found = NUMBER.exec(String(value))?.groups;
|
|
18
|
+
if (found === undefined) {
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
return {
|
|
22
|
+
isNegative: found["sign"] === "-",
|
|
23
|
+
whole: found["whole"] ?? "",
|
|
24
|
+
fraction: found["fraction"] ?? "",
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Write digits one at a time: 2019 → 二〇一九.
|
|
29
|
+
*/
|
|
30
|
+
function digitsHanzi(digits, zero) {
|
|
31
|
+
return toCharacters(digits)
|
|
32
|
+
.map((digit) => digit === "0" ? zero : (DIGIT_CHARACTERS[Number(digit)] ?? digit))
|
|
33
|
+
.join("");
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Write a number in 汉字: 12345 → 一万二千三百四十五, or 一二三四五.
|
|
37
|
+
*
|
|
38
|
+
* Undefined for anything that is not a number, and for a `cardinal` whose whole
|
|
39
|
+
* part is too large to write — a digit string is not limited that way, since
|
|
40
|
+
* reading digits out needs no arithmetic at all.
|
|
41
|
+
*
|
|
42
|
+
* The fractional part is always read digit by digit whatever the style, because
|
|
43
|
+
* that is how it is said: 3.14 is 三点一四 and never 三点十四.
|
|
44
|
+
*/
|
|
45
|
+
export function numeralHanzi(value, options = {}) {
|
|
46
|
+
const parsed = parse(value);
|
|
47
|
+
if (parsed === undefined) {
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
const { style = "cardinal", zero = "〇" } = options;
|
|
51
|
+
let whole;
|
|
52
|
+
if (style === "digits") {
|
|
53
|
+
whole = digitsHanzi(parsed.whole, zero);
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
const quantity = Number(parsed.whole);
|
|
57
|
+
if (!Number.isSafeInteger(quantity) || quantity > LARGEST_CARDINAL) {
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
whole = cardinalHanzi(quantity, options);
|
|
61
|
+
}
|
|
62
|
+
const point = parsed.fraction === "" ? "" : `点${digitsHanzi(parsed.fraction, "零")}`;
|
|
63
|
+
return `${parsed.isNegative ? "负" : ""}${whole}${point}`;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Read written numeral 汉字 as syllables.
|
|
67
|
+
*
|
|
68
|
+
* Undefined where the text holds anything that is not a numeral character, so a
|
|
69
|
+
* caller can tell "not a number" from a number that reads oddly.
|
|
70
|
+
*/
|
|
71
|
+
export function readNumeralHanzi(hanzi, options = {}) {
|
|
72
|
+
const isYao = options.yao ?? false;
|
|
73
|
+
const syllables = [];
|
|
74
|
+
for (const character of toCharacters(hanzi)) {
|
|
75
|
+
const syllable = isYao && character === "一" ? yaoSyllable() : numeralSyllable(character);
|
|
76
|
+
if (syllable === undefined) {
|
|
77
|
+
return undefined;
|
|
78
|
+
}
|
|
79
|
+
syllables.push(syllable);
|
|
80
|
+
}
|
|
81
|
+
return syllables;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Read a number as syllables: 2019 as `èr líng yī jiǔ`, or as a quantity.
|
|
85
|
+
*
|
|
86
|
+
* The readings are *underlying*, as the dictionary's are — 一 is `yī` however
|
|
87
|
+
* it will be said in context — so a caller assembling a longer utterance runs
|
|
88
|
+
* the sandhi pass over the result and gets `yìbǎi` and `yí gè` from it. That is
|
|
89
|
+
* the same contract `decodeRun` has, and it is what keeps a number from having
|
|
90
|
+
* to know what follows it.
|
|
91
|
+
*/
|
|
92
|
+
export function readNumeral(value, options = {}) {
|
|
93
|
+
const hanzi = numeralHanzi(value, options);
|
|
94
|
+
return hanzi === undefined ? undefined : readNumeralHanzi(hanzi, options);
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Write a percentage the way it is said: 95% → 百分之九十五.
|
|
98
|
+
*
|
|
99
|
+
* The order reverses — "of a hundred parts, ninety-five" — which is why this
|
|
100
|
+
* cannot be left to whoever writes the number and the sign separately.
|
|
101
|
+
*/
|
|
102
|
+
export function percentHanzi(value, options = {}) {
|
|
103
|
+
const written = numeralHanzi(value, options);
|
|
104
|
+
return written === undefined ? undefined : `百分之${written}`;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Write a fraction the way it is said: 3/4 → 四分之三.
|
|
108
|
+
*
|
|
109
|
+
* Same reversal as a percentage, of which this is the general case: the
|
|
110
|
+
* denominator is named first and the numerator second.
|
|
111
|
+
*/
|
|
112
|
+
export function fractionHanzi(numerator, denominator, options = {}) {
|
|
113
|
+
const top = numeralHanzi(numerator, options);
|
|
114
|
+
const bottom = numeralHanzi(denominator, options);
|
|
115
|
+
return top === undefined || bottom === undefined
|
|
116
|
+
? undefined
|
|
117
|
+
: `${bottom}分之${top}`;
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=numerals.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"numerals.js","sourceRoot":"","sources":["../../src/numerals/numerals.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { type SandhiOptions } from "../decode/sandhi.js";
|
|
2
|
+
import type { Syllable } from "../syllable/syllable.js";
|
|
3
|
+
import { type NumeralOptions, type NumeralStyle } from "./numerals.js";
|
|
4
|
+
/**
|
|
5
|
+
* One stretch of text that was never Han, read or left as it was.
|
|
6
|
+
*/
|
|
7
|
+
export interface NumeralSegment {
|
|
8
|
+
/** The characters this covers, exactly as they were written. */
|
|
9
|
+
readonly text: string;
|
|
10
|
+
/** How it is said, where it was read as a number. */
|
|
11
|
+
readonly reading: readonly Syllable[] | undefined;
|
|
12
|
+
/** The 汉字 the number would be written with, where it was read. */
|
|
13
|
+
readonly hanzi: string | undefined;
|
|
14
|
+
/** How it was read, which decides whether sandhi applies to it. */
|
|
15
|
+
readonly style: NumeralStyle | undefined;
|
|
16
|
+
/**
|
|
17
|
+
* Where the words break, as a syllable count each.
|
|
18
|
+
*
|
|
19
|
+
* A counted number is one word and needs none of this. A time is three or
|
|
20
|
+
* four — 6:30 is `liù diǎn sānshí fēn`, where the hour and the minutes are
|
|
21
|
+
* numbers and 点 and 分 are not — and nothing in the syllables themselves
|
|
22
|
+
* says where those breaks are.
|
|
23
|
+
*/
|
|
24
|
+
readonly words?: readonly number[];
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Split a stretch of non-Han text into what is read and what is not.
|
|
28
|
+
*
|
|
29
|
+
* `following` is the first character of the Han that comes after this stretch,
|
|
30
|
+
* which is the only context a number has: 年 makes 1997 a year and 个 makes 3 a
|
|
31
|
+
* count. Where there is nothing after it, or nothing that decides, the number
|
|
32
|
+
* is counted.
|
|
33
|
+
*
|
|
34
|
+
* Text that is not a number is returned unread rather than dropped, so the
|
|
35
|
+
* segments always concatenate back to the input.
|
|
36
|
+
*/
|
|
37
|
+
export declare function readNumbersIn(text: string, following: string, options?: NumeralOptions): readonly NumeralSegment[];
|
|
38
|
+
/**
|
|
39
|
+
* A number as it is said, with the sandhi a counted quantity takes.
|
|
40
|
+
*
|
|
41
|
+
* Two things decide how much of it assimilates. A number read out digit by
|
|
42
|
+
* digit does not at all — 110 is `yāo yāo líng` and never `yì yì líng` —
|
|
43
|
+
* and in a counted one the sandhi stops at the 点, since everything after the
|
|
44
|
+
* decimal point is read digit by digit whatever the style: 3.14 is
|
|
45
|
+
* `sān diǎn yī sì`.
|
|
46
|
+
*
|
|
47
|
+
* `following` is the syllable after the number, which is what a 一 at the end
|
|
48
|
+
* of it assimilates to: the 一 of 一个 is `yí` because 个 is a fourth tone, and
|
|
49
|
+
* that tone is in the next run rather than in the number.
|
|
50
|
+
*/
|
|
51
|
+
export declare function saidNumeral(segment: NumeralSegment, following: Syllable | undefined, sandhi: SandhiOptions | undefined): readonly Syllable[];
|
|
52
|
+
//# sourceMappingURL=text.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../src/numerals/text.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEtE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,YAAY,EAGlB,MAAM,eAAe,CAAC;AAEvB;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,gEAAgE;IAChE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,qDAAqD;IACrD,QAAQ,CAAC,OAAO,EAAE,SAAS,QAAQ,EAAE,GAAG,SAAS,CAAC;IAClD,kEAAkE;IAClE,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,mEAAmE;IACnE,QAAQ,CAAC,KAAK,EAAE,YAAY,GAAG,SAAS,CAAC;IACzC;;;;;;;OAOG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC;AAsMD;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,cAAmB,GAC3B,SAAS,cAAc,EAAE,CA2C3B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,CACzB,OAAO,EAAE,cAAc,EACvB,SAAS,EAAE,QAAQ,GAAG,SAAS,EAC/B,MAAM,EAAE,aAAa,GAAG,SAAS,GAChC,SAAS,QAAQ,EAAE,CAUrB"}
|