@kensio/pinyinjs 1.7.13 → 1.8.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/dist/decode/sandhi-grouping.d.ts +55 -0
- package/dist/decode/sandhi-grouping.d.ts.map +1 -0
- package/dist/decode/sandhi-grouping.js +81 -0
- package/dist/decode/sandhi-grouping.js.map +1 -0
- package/dist/decode/sandhi-input.d.ts +14 -9
- package/dist/decode/sandhi-input.d.ts.map +1 -1
- package/dist/decode/sandhi-input.js +11 -6
- package/dist/decode/sandhi-input.js.map +1 -1
- package/dist/decode/sandhi-tones.d.ts +19 -3
- package/dist/decode/sandhi-tones.d.ts.map +1 -1
- package/dist/decode/sandhi-tones.js +25 -5
- package/dist/decode/sandhi-tones.js.map +1 -1
- package/dist/decode/sandhi.d.ts +20 -19
- package/dist/decode/sandhi.d.ts.map +1 -1
- package/dist/decode/sandhi.js +31 -52
- package/dist/decode/sandhi.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How the syllables group, and the two things sandhi reads out of a grouping.
|
|
3
|
+
*
|
|
4
|
+
* Third-tone sandhi wants the junctions, since its domain is the prosodic foot
|
|
5
|
+
* and a foot is built from structure. 一 wants the word ends, since a 一 that
|
|
6
|
+
* closes a longer word counts nothing after it. Both are answered here so that
|
|
7
|
+
* `sandhi.ts` holds the rules rather than the bookkeeping.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* How the syllables group, for sandhi to read.
|
|
11
|
+
*
|
|
12
|
+
* One entry per word: its syllable count, or the counts of the constituents it
|
|
13
|
+
* divides into. 老板 很 好 is `[2, 1, 1]` and 纸老虎 is `[[1, 2]]`.
|
|
14
|
+
*
|
|
15
|
+
* Third-tone sandhi's domain is the prosodic foot rather than the word, and the
|
|
16
|
+
* foot is built from structure — which is why this is worth carrying. See
|
|
17
|
+
* {@link import("./sandhi.js").applySandhi}.
|
|
18
|
+
*/
|
|
19
|
+
export type SandhiGrouping = readonly (number | readonly number[])[];
|
|
20
|
+
/**
|
|
21
|
+
* Where sandhi may apply, as the index of the syllable that would lower.
|
|
22
|
+
*
|
|
23
|
+
* Every junction is between adjacent syllables — words and their constituents
|
|
24
|
+
* cover the reading end to end — so one index says all of it, and the three
|
|
25
|
+
* lists are the three passes third-tone sandhi makes.
|
|
26
|
+
*/
|
|
27
|
+
export interface SandhiJunctions {
|
|
28
|
+
/** Inside a constituent. */
|
|
29
|
+
readonly inner: readonly number[];
|
|
30
|
+
/** Between the constituents of a word. */
|
|
31
|
+
readonly parts: readonly number[];
|
|
32
|
+
/** Between a single-syllable word and the word after it. */
|
|
33
|
+
readonly words: readonly number[];
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Read a grouping as the junctions it puts in the syllable array.
|
|
37
|
+
*
|
|
38
|
+
* The whole array is treated as one undivided word where no grouping is given,
|
|
39
|
+
* or where the one given does not account for exactly the syllables there are —
|
|
40
|
+
* a grouping that does not fit is describing some other text, and guessing
|
|
41
|
+
* which syllables it meant would be worse than ignoring it.
|
|
42
|
+
*/
|
|
43
|
+
export declare function junctionsOf(length: number, grouping?: SandhiGrouping): SandhiJunctions;
|
|
44
|
+
/**
|
|
45
|
+
* Where a word of more than one syllable ends, as indices into the array.
|
|
46
|
+
*
|
|
47
|
+
* Empty without a grouping, and empty for a grouping that does not fit, which
|
|
48
|
+
* is the judgement {@link junctionsOf} makes and for the same reason.
|
|
49
|
+
*
|
|
50
|
+
* A one-syllable word is deliberately not an ending here. 一 on its own is a
|
|
51
|
+
* word and it counts the word after it: see
|
|
52
|
+
* {@link import("./sandhi.js").applySandhi}.
|
|
53
|
+
*/
|
|
54
|
+
export declare function endingsOf(length: number, grouping?: SandhiGrouping): ReadonlySet<number>;
|
|
55
|
+
//# sourceMappingURL=sandhi-grouping.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sandhi-grouping.d.ts","sourceRoot":"","sources":["../../src/decode/sandhi-grouping.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;;;;;;;;GASG;AACH,MAAM,MAAM,cAAc,GAAG,SAAS,CAAC,MAAM,GAAG,SAAS,MAAM,EAAE,CAAC,EAAE,CAAC;AAErE;;;;;;GAMG;AACH,MAAM,WAAW,eAAe;IAC9B,4BAA4B;IAC5B,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,0CAA0C;IAC1C,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,4DAA4D;IAC5D,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;CACnC;AASD;;;;;;;GAOG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,MAAM,EACd,QAAQ,CAAC,EAAE,cAAc,GACxB,eAAe,CAiCjB;AAED;;;;;;;;;GASG;AACH,wBAAgB,SAAS,CACvB,MAAM,EAAE,MAAM,EACd,QAAQ,CAAC,EAAE,cAAc,GACxB,WAAW,CAAC,MAAM,CAAC,CAerB"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How the syllables group, and the two things sandhi reads out of a grouping.
|
|
3
|
+
*
|
|
4
|
+
* Third-tone sandhi wants the junctions, since its domain is the prosodic foot
|
|
5
|
+
* and a foot is built from structure. 一 wants the word ends, since a 一 that
|
|
6
|
+
* closes a longer word counts nothing after it. Both are answered here so that
|
|
7
|
+
* `sandhi.ts` holds the rules rather than the bookkeeping.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* The syllable counts one grouping entry holds, as a flat list of its parts.
|
|
11
|
+
*/
|
|
12
|
+
function partsOf(word) {
|
|
13
|
+
return typeof word === "number" ? [word] : word;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Read a grouping as the junctions it puts in the syllable array.
|
|
17
|
+
*
|
|
18
|
+
* The whole array is treated as one undivided word where no grouping is given,
|
|
19
|
+
* or where the one given does not account for exactly the syllables there are —
|
|
20
|
+
* a grouping that does not fit is describing some other text, and guessing
|
|
21
|
+
* which syllables it meant would be worse than ignoring it.
|
|
22
|
+
*/
|
|
23
|
+
export function junctionsOf(length, grouping) {
|
|
24
|
+
const undivided = {
|
|
25
|
+
inner: Array.from({ length: Math.max(length - 1, 0) }, (_, at) => at),
|
|
26
|
+
parts: [],
|
|
27
|
+
words: [],
|
|
28
|
+
};
|
|
29
|
+
if (grouping === undefined) {
|
|
30
|
+
return undivided;
|
|
31
|
+
}
|
|
32
|
+
const inner = [];
|
|
33
|
+
const parts = [];
|
|
34
|
+
const words = [];
|
|
35
|
+
let at = 0;
|
|
36
|
+
for (const [index, word] of grouping.entries()) {
|
|
37
|
+
const divisions = partsOf(word);
|
|
38
|
+
const from = at;
|
|
39
|
+
for (const [division, size] of divisions.entries()) {
|
|
40
|
+
for (let step = 1; step < size; step++) {
|
|
41
|
+
inner.push(at + step - 1);
|
|
42
|
+
}
|
|
43
|
+
at += size;
|
|
44
|
+
// The junction closing a word's last constituent is the one *around* the
|
|
45
|
+
// word rather than one inside it.
|
|
46
|
+
if (division < divisions.length - 1) {
|
|
47
|
+
parts.push(at - 1);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
if (at - from === 1 && index < grouping.length - 1) {
|
|
51
|
+
words.push(at - 1);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return at === length ? { inner, parts, words } : undivided;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Where a word of more than one syllable ends, as indices into the array.
|
|
58
|
+
*
|
|
59
|
+
* Empty without a grouping, and empty for a grouping that does not fit, which
|
|
60
|
+
* is the judgement {@link junctionsOf} makes and for the same reason.
|
|
61
|
+
*
|
|
62
|
+
* A one-syllable word is deliberately not an ending here. 一 on its own is a
|
|
63
|
+
* word and it counts the word after it: see
|
|
64
|
+
* {@link import("./sandhi.js").applySandhi}.
|
|
65
|
+
*/
|
|
66
|
+
export function endingsOf(length, grouping) {
|
|
67
|
+
const endings = new Set();
|
|
68
|
+
if (grouping === undefined) {
|
|
69
|
+
return endings;
|
|
70
|
+
}
|
|
71
|
+
let at = 0;
|
|
72
|
+
for (const word of grouping) {
|
|
73
|
+
const size = partsOf(word).reduce((total, part) => total + part, 0);
|
|
74
|
+
at += size;
|
|
75
|
+
if (size > 1) {
|
|
76
|
+
endings.add(at - 1);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return at === length ? endings : new Set();
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=sandhi-grouping.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sandhi-grouping.js","sourceRoot":"","sources":["../../src/decode/sandhi-grouping.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,29 +1,34 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* What the sandhi pass needs from a decoded run, beyond the syllables.
|
|
3
3
|
*
|
|
4
|
-
* Two questions sandhi cannot answer from a reading alone.
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* is a
|
|
8
|
-
* the syllable array does not.
|
|
4
|
+
* Two questions sandhi cannot answer from a reading alone. Where the words and
|
|
5
|
+
* their parts are, which third-tone sandhi needs for the prosodic foot it
|
|
6
|
+
* applies inside and 一 needs for the word ends. And which 汉字 each syllable
|
|
7
|
+
* reads, which is what says a `yī` is 一 rather than 医 and what stands in front
|
|
8
|
+
* of it. Both are things the decode knows and the syllable array does not.
|
|
9
9
|
*/
|
|
10
10
|
import type { Dictionary } from "../dictionary/dictionary.js";
|
|
11
11
|
import type { Syllable } from "../syllable/syllable.js";
|
|
12
12
|
import type { SandhiGrouping } from "./sandhi.js";
|
|
13
13
|
import type { ScoredWord } from "./word.js";
|
|
14
14
|
/**
|
|
15
|
-
* Where the words and their constituents fall
|
|
15
|
+
* Where the words and their constituents fall.
|
|
16
16
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
17
|
+
* One entry per word always, because 一 sandhi reads the word ends: a 一 that
|
|
18
|
+
* closes a longer word is not counting the word after it, so 唯一 stays `wéiyī`
|
|
19
|
+
* in front of anything.
|
|
20
|
+
*
|
|
21
|
+
* Where a word *divides* is only worked out for third-tone sandhi, which is the
|
|
22
|
+
* only pass that reads it and costs a dictionary lookup per word to answer.
|
|
19
23
|
*/
|
|
20
|
-
export declare function groupingOf(dictionary: Dictionary, words: readonly ScoredWord[], readings: readonly (readonly Syllable[])[], isThirdTone: boolean): SandhiGrouping
|
|
24
|
+
export declare function groupingOf(dictionary: Dictionary, words: readonly ScoredWord[], readings: readonly (readonly Syllable[])[], isThirdTone: boolean): SandhiGrouping;
|
|
21
25
|
/**
|
|
22
26
|
* One 汉字 per syllable, where a word offers one.
|
|
23
27
|
*
|
|
24
28
|
* A word whose reading is a different length from its text — 玩儿 as `wánr` —
|
|
25
29
|
* has no character to give any one of its syllables, so its syllables get none
|
|
26
30
|
* and the pass falls back to their spellings. See
|
|
31
|
+
* {@link import("./sandhi-tones.js").isYi} and
|
|
27
32
|
* {@link import("./sandhi-tones.js").isCounting}.
|
|
28
33
|
*/
|
|
29
34
|
export declare function charactersPerSyllable(words: readonly ScoredWord[], readings: readonly (readonly Syllable[])[]): readonly (string | undefined)[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sandhi-input.d.ts","sourceRoot":"","sources":["../../src/decode/sandhi-input.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAE9D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAExD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAE5C
|
|
1
|
+
{"version":3,"file":"sandhi-input.d.ts","sourceRoot":"","sources":["../../src/decode/sandhi-input.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAE9D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAExD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAE5C;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CACxB,UAAU,EAAE,UAAU,EACtB,KAAK,EAAE,SAAS,UAAU,EAAE,EAC5B,QAAQ,EAAE,SAAS,CAAC,SAAS,QAAQ,EAAE,CAAC,EAAE,EAC1C,WAAW,EAAE,OAAO,GACnB,cAAc,CAQhB;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,SAAS,UAAU,EAAE,EAC5B,QAAQ,EAAE,SAAS,CAAC,SAAS,QAAQ,EAAE,CAAC,EAAE,GACzC,SAAS,CAAC,MAAM,GAAG,SAAS,CAAC,EAAE,CAQjC"}
|
|
@@ -1,17 +1,21 @@
|
|
|
1
1
|
import { toCharacters } from "../script/characters.js";
|
|
2
2
|
import { divisionOf } from "./constituents.js";
|
|
3
3
|
/**
|
|
4
|
-
* Where the words and their constituents fall
|
|
4
|
+
* Where the words and their constituents fall.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
6
|
+
* One entry per word always, because 一 sandhi reads the word ends: a 一 that
|
|
7
|
+
* closes a longer word is not counting the word after it, so 唯一 stays `wéiyī`
|
|
8
|
+
* in front of anything.
|
|
9
|
+
*
|
|
10
|
+
* Where a word *divides* is only worked out for third-tone sandhi, which is the
|
|
11
|
+
* only pass that reads it and costs a dictionary lookup per word to answer.
|
|
8
12
|
*/
|
|
9
13
|
export function groupingOf(dictionary, words, readings, isThirdTone) {
|
|
10
|
-
if (!isThirdTone) {
|
|
11
|
-
return undefined;
|
|
12
|
-
}
|
|
13
14
|
return words.map((scored, index) => {
|
|
14
15
|
const reading = readings[index] ?? [];
|
|
16
|
+
if (!isThirdTone) {
|
|
17
|
+
return reading.length;
|
|
18
|
+
}
|
|
15
19
|
return divisionOf(dictionary, scored.word.text, reading) ?? reading.length;
|
|
16
20
|
});
|
|
17
21
|
}
|
|
@@ -21,6 +25,7 @@ export function groupingOf(dictionary, words, readings, isThirdTone) {
|
|
|
21
25
|
* A word whose reading is a different length from its text — 玩儿 as `wánr` —
|
|
22
26
|
* has no character to give any one of its syllables, so its syllables get none
|
|
23
27
|
* and the pass falls back to their spellings. See
|
|
28
|
+
* {@link import("./sandhi-tones.js").isYi} and
|
|
24
29
|
* {@link import("./sandhi-tones.js").isCounting}.
|
|
25
30
|
*/
|
|
26
31
|
export function charactersPerSyllable(words, readings) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sandhi-input.js","sourceRoot":"","sources":["../../src/decode/sandhi-input.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAEvD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAI/C
|
|
1
|
+
{"version":3,"file":"sandhi-input.js","sourceRoot":"","sources":["../../src/decode/sandhi-input.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAEvD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAI/C;;;;;;;;;GASG;AACH,MAAM,UAAU,UAAU,CACxB,UAAsB,EACtB,KAA4B,EAC5B,QAA0C,EAC1C,WAAoB;IAEpB,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE;QACjC,MAAM,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QACtC,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,OAAO,OAAO,CAAC,MAAM,CAAC;QACxB,CAAC;QACD,OAAO,UAAU,CAAC,UAAU,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,OAAO,CAAC,MAAM,CAAC;IAC7E,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,qBAAqB,CACnC,KAA4B,EAC5B,QAA0C;IAE1C,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,KAAK,EAAmC,EAAE;QACtE,MAAM,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QACtC,MAAM,IAAI,GAAG,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5C,OAAO,IAAI,CAAC,MAAM,KAAK,OAAO,CAAC,MAAM;YACnC,CAAC,CAAC,IAAI;YACN,CAAC,CAAC,KAAK,CAAC,IAAI,CAAqB,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACjE,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -7,13 +7,29 @@
|
|
|
7
7
|
import { type Syllable } from "../syllable/syllable.js";
|
|
8
8
|
import { type Tone } from "../tone/tone.js";
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
10
|
+
* The 汉字 一.
|
|
11
11
|
*/
|
|
12
|
-
export declare
|
|
12
|
+
export declare const YI_CHARACTER = "\u4E00";
|
|
13
|
+
/**
|
|
14
|
+
* The 汉字 不.
|
|
15
|
+
*/
|
|
16
|
+
export declare const BU_CHARACTER = "\u4E0D";
|
|
17
|
+
/**
|
|
18
|
+
* Whether a syllable is 一.
|
|
19
|
+
*
|
|
20
|
+
* **Answered from the 汉字 where the caller has one**, and from the spelling
|
|
21
|
+
* where it does not, the way {@link isCounting} is. The spelling is not the
|
|
22
|
+
* morpheme and never was: 医, 依, 衣 and 伊 are all `yī` and none of them
|
|
23
|
+
* changes tone for what follows it. This rule is a fact about one character.
|
|
24
|
+
*/
|
|
25
|
+
export declare function isYi(syllable: Syllable, character?: string): boolean;
|
|
13
26
|
/**
|
|
14
27
|
* Whether a syllable is 不.
|
|
28
|
+
*
|
|
29
|
+
* Read from the 汉字 or the spelling on the same terms as {@link isYi}, and for
|
|
30
|
+
* the same reason: 部, 布, 步 and 埠 are all `bù` and none of them flattens.
|
|
15
31
|
*/
|
|
16
|
-
export declare function isBu(syllable: Syllable): boolean;
|
|
32
|
+
export declare function isBu(syllable: Syllable, character?: string): boolean;
|
|
17
33
|
/**
|
|
18
34
|
* The tone 一 takes before a given following tone.
|
|
19
35
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sandhi-tones.d.ts","sourceRoot":"","sources":["../../src/decode/sandhi-tones.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,KAAK,QAAQ,EAAyB,MAAM,yBAAyB,CAAC;AAC/E,OAAO,EAAgB,KAAK,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAE1D;;GAEG;AACH,wBAAgB,IAAI,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,
|
|
1
|
+
{"version":3,"file":"sandhi-tones.d.ts","sourceRoot":"","sources":["../../src/decode/sandhi-tones.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,KAAK,QAAQ,EAAyB,MAAM,yBAAyB,CAAC;AAC/E,OAAO,EAAgB,KAAK,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAE1D;;GAEG;AACH,eAAO,MAAM,YAAY,WAAM,CAAC;AAEhC;;GAEG;AACH,eAAO,MAAM,YAAY,WAAM,CAAC;AAEhC;;;;;;;GAOG;AACH,wBAAgB,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAIpE;AAED;;;;;GAKG;AACH,wBAAgB,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAIpE;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,IAAI,GAAG,SAAS,GAAG,IAAI,CAK9D;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,aAAa,aAAyC,CAAC;AAEpE;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,aAAsC,CAAC;AAEpE;;GAEG;AACH,eAAO,MAAM,cAAc,OAAO,CAAC;AAEnC;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,kBAAkB,aAS7B,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,2BAA2B,aAItC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,iBAAiB,WAAM,CAAC;AAErC;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,UAAU,CACxB,SAAS,EAAE,SAAS,QAAQ,EAAE,EAC9B,EAAE,EAAE,MAAM,EACV,UAAU,GAAE,SAAS,CAAC,MAAM,GAAG,SAAS,CAAC,EAAO,GAC/C,OAAO,CAwBT"}
|
|
@@ -7,16 +7,36 @@
|
|
|
7
7
|
import { writeSyllableSpelling } from "../syllable/syllable.js";
|
|
8
8
|
import { NEUTRAL_TONE } from "../tone/tone.js";
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
10
|
+
* The 汉字 一.
|
|
11
11
|
*/
|
|
12
|
-
export
|
|
13
|
-
|
|
12
|
+
export const YI_CHARACTER = "一";
|
|
13
|
+
/**
|
|
14
|
+
* The 汉字 不.
|
|
15
|
+
*/
|
|
16
|
+
export const BU_CHARACTER = "不";
|
|
17
|
+
/**
|
|
18
|
+
* Whether a syllable is 一.
|
|
19
|
+
*
|
|
20
|
+
* **Answered from the 汉字 where the caller has one**, and from the spelling
|
|
21
|
+
* where it does not, the way {@link isCounting} is. The spelling is not the
|
|
22
|
+
* morpheme and never was: 医, 依, 衣 and 伊 are all `yī` and none of them
|
|
23
|
+
* changes tone for what follows it. This rule is a fact about one character.
|
|
24
|
+
*/
|
|
25
|
+
export function isYi(syllable, character) {
|
|
26
|
+
return character === undefined
|
|
27
|
+
? syllable.initial === "" && syllable.final === "i"
|
|
28
|
+
: character === YI_CHARACTER;
|
|
14
29
|
}
|
|
15
30
|
/**
|
|
16
31
|
* Whether a syllable is 不.
|
|
32
|
+
*
|
|
33
|
+
* Read from the 汉字 or the spelling on the same terms as {@link isYi}, and for
|
|
34
|
+
* the same reason: 部, 布, 步 and 埠 are all `bù` and none of them flattens.
|
|
17
35
|
*/
|
|
18
|
-
export function isBu(syllable) {
|
|
19
|
-
return
|
|
36
|
+
export function isBu(syllable, character) {
|
|
37
|
+
return character === undefined
|
|
38
|
+
? syllable.initial === "b" && syllable.final === "u"
|
|
39
|
+
: character === BU_CHARACTER;
|
|
20
40
|
}
|
|
21
41
|
/**
|
|
22
42
|
* The tone 一 takes before a given following tone.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sandhi-tones.js","sourceRoot":"","sources":["../../src/decode/sandhi-tones.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAiB,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAC/E,OAAO,EAAE,YAAY,EAAa,MAAM,iBAAiB,CAAC;AAE1D;;GAEG;AACH,MAAM,UAAU,IAAI,CAAC,QAAkB;
|
|
1
|
+
{"version":3,"file":"sandhi-tones.js","sourceRoot":"","sources":["../../src/decode/sandhi-tones.ts"],"names":[],"mappings":"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"}
|
package/dist/decode/sandhi.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { Syllable } from "../syllable/syllable.js";
|
|
2
|
+
import { type SandhiGrouping } from "./sandhi-grouping.js";
|
|
3
|
+
export type { SandhiGrouping } from "./sandhi-grouping.js";
|
|
2
4
|
/**
|
|
3
5
|
* How much of the sandhi to apply.
|
|
4
6
|
*/
|
|
@@ -19,17 +21,6 @@ export interface SandhiOptions {
|
|
|
19
21
|
*/
|
|
20
22
|
readonly thirdTone?: boolean;
|
|
21
23
|
}
|
|
22
|
-
/**
|
|
23
|
-
* How the syllables group, for third-tone sandhi to read.
|
|
24
|
-
*
|
|
25
|
-
* One entry per word: its syllable count, or the counts of the constituents it
|
|
26
|
-
* divides into. 老板 很 好 is `[2, 1, 1]` and 纸老虎 is `[[1, 2]]`.
|
|
27
|
-
*
|
|
28
|
-
* Sandhi's domain is the prosodic foot rather than the word, and the foot is
|
|
29
|
-
* built from structure — which is why this is worth carrying. See
|
|
30
|
-
* {@link applyThirdTone} for what is done with it.
|
|
31
|
-
*/
|
|
32
|
-
export type SandhiGrouping = readonly (number | readonly number[])[];
|
|
33
24
|
/**
|
|
34
25
|
* Apply the tone sandhi that standard orthography writes.
|
|
35
26
|
*
|
|
@@ -39,14 +30,24 @@ export type SandhiGrouping = readonly (number | readonly number[])[];
|
|
|
39
30
|
* contextual tone is put back, over the whole syllable array rather than within
|
|
40
31
|
* a word, which is what lets 不 in one word assimilate to a tone in the next.
|
|
41
32
|
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
* them
|
|
33
|
+
* A caller holding nothing but a reading can still use this, and several do:
|
|
34
|
+
* `pinyinjs sandhi bùshì` and the numeral reader both hand over syllables and
|
|
35
|
+
* nothing else. `grouping` and `characters` are what a caller that knows more
|
|
36
|
+
* says so with, and each one is read on its own, since a caller can have one
|
|
37
|
+
* and not the other.
|
|
38
|
+
*
|
|
39
|
+
* `characters` holds one 汉字 per syllable, and is what tells 一 and 不 apart
|
|
40
|
+
* from the syllables that merely sound like them — 医生 is `yīshēng` and 部队
|
|
41
|
+
* is `bùduì`. Without it the pass falls back to the spellings, which is all
|
|
42
|
+
* bare pinyin offers. See {@link isYi} and {@link isCounting}.
|
|
43
|
+
*
|
|
44
|
+
* `grouping` says where the words and their parts are. Third-tone sandhi needs
|
|
45
|
+
* it because its domain is the prosodic foot rather than the syllable string,
|
|
46
|
+
* and 一 needs the word ends out of it: a 一 that closes a longer word is not
|
|
47
|
+
* counting the word after it. Without a grouping the whole array is taken for
|
|
48
|
+
* a single word, which is all a bare reading says.
|
|
49
|
+
*
|
|
50
|
+
* 不 is the one rule that needs neither: it assimilates to whatever follows.
|
|
50
51
|
*
|
|
51
52
|
* Never operates on a string. The old project patched output text with regexes,
|
|
52
53
|
* which is what made its rules order-dependent and untestable.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sandhi.d.ts","sourceRoot":"","sources":["../../src/decode/sandhi.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"sandhi.d.ts","sourceRoot":"","sources":["../../src/decode/sandhi.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,sBAAsB,CAAC;AAG9B,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B;;;;;OAKG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IACxB;;;;;;OAMG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;CAC9B;AA+DD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,WAAW,CACzB,SAAS,EAAE,SAAS,QAAQ,EAAE,EAC9B,OAAO,GAAE,aAAkB,EAC3B,QAAQ,CAAC,EAAE,cAAc,EACzB,UAAU,CAAC,EAAE,SAAS,CAAC,MAAM,GAAG,SAAS,CAAC,EAAE,GAC3C,SAAS,QAAQ,EAAE,CAsCrB"}
|
package/dist/decode/sandhi.js
CHANGED
|
@@ -1,45 +1,5 @@
|
|
|
1
|
+
import { endingsOf, junctionsOf, } from "./sandhi-grouping.js";
|
|
1
2
|
import { isBu, isCounting, isYi, yiToneBefore } from "./sandhi-tones.js";
|
|
2
|
-
/**
|
|
3
|
-
* Read a grouping as the junctions it puts in the syllable array.
|
|
4
|
-
*
|
|
5
|
-
* The whole array is treated as one undivided word where no grouping is given,
|
|
6
|
-
* or where the one given does not account for exactly the syllables there are —
|
|
7
|
-
* a grouping that does not fit is describing some other text, and guessing
|
|
8
|
-
* which syllables it meant would be worse than ignoring it.
|
|
9
|
-
*/
|
|
10
|
-
function junctionsOf(length, grouping) {
|
|
11
|
-
const undivided = {
|
|
12
|
-
inner: Array.from({ length: Math.max(length - 1, 0) }, (_, at) => at),
|
|
13
|
-
parts: [],
|
|
14
|
-
words: [],
|
|
15
|
-
};
|
|
16
|
-
if (grouping === undefined) {
|
|
17
|
-
return undivided;
|
|
18
|
-
}
|
|
19
|
-
const inner = [];
|
|
20
|
-
const parts = [];
|
|
21
|
-
const words = [];
|
|
22
|
-
let at = 0;
|
|
23
|
-
for (const [index, word] of grouping.entries()) {
|
|
24
|
-
const divisions = typeof word === "number" ? [word] : word;
|
|
25
|
-
const from = at;
|
|
26
|
-
for (const [division, size] of divisions.entries()) {
|
|
27
|
-
for (let step = 1; step < size; step++) {
|
|
28
|
-
inner.push(at + step - 1);
|
|
29
|
-
}
|
|
30
|
-
at += size;
|
|
31
|
-
// The junction closing a word's last constituent is the one *around* the
|
|
32
|
-
// word rather than one inside it.
|
|
33
|
-
if (division < divisions.length - 1) {
|
|
34
|
-
parts.push(at - 1);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
if (at - from === 1 && index < grouping.length - 1) {
|
|
38
|
-
words.push(at - 1);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
return at === length ? { inner, parts, words } : undivided;
|
|
42
|
-
}
|
|
43
3
|
/**
|
|
44
4
|
* Lower a third tone to a second where the syllable after it is a third too.
|
|
45
5
|
*
|
|
@@ -103,14 +63,24 @@ function applyThirdTone(syllables, grouping) {
|
|
|
103
63
|
* contextual tone is put back, over the whole syllable array rather than within
|
|
104
64
|
* a word, which is what lets 不 in one word assimilate to a tone in the next.
|
|
105
65
|
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
* them
|
|
66
|
+
* A caller holding nothing but a reading can still use this, and several do:
|
|
67
|
+
* `pinyinjs sandhi bùshì` and the numeral reader both hand over syllables and
|
|
68
|
+
* nothing else. `grouping` and `characters` are what a caller that knows more
|
|
69
|
+
* says so with, and each one is read on its own, since a caller can have one
|
|
70
|
+
* and not the other.
|
|
71
|
+
*
|
|
72
|
+
* `characters` holds one 汉字 per syllable, and is what tells 一 and 不 apart
|
|
73
|
+
* from the syllables that merely sound like them — 医生 is `yīshēng` and 部队
|
|
74
|
+
* is `bùduì`. Without it the pass falls back to the spellings, which is all
|
|
75
|
+
* bare pinyin offers. See {@link isYi} and {@link isCounting}.
|
|
76
|
+
*
|
|
77
|
+
* `grouping` says where the words and their parts are. Third-tone sandhi needs
|
|
78
|
+
* it because its domain is the prosodic foot rather than the syllable string,
|
|
79
|
+
* and 一 needs the word ends out of it: a 一 that closes a longer word is not
|
|
80
|
+
* counting the word after it. Without a grouping the whole array is taken for
|
|
81
|
+
* a single word, which is all a bare reading says.
|
|
82
|
+
*
|
|
83
|
+
* 不 is the one rule that needs neither: it assimilates to whatever follows.
|
|
114
84
|
*
|
|
115
85
|
* Never operates on a string. The old project patched output text with regexes,
|
|
116
86
|
* which is what made its rules order-dependent and untestable.
|
|
@@ -120,19 +90,28 @@ export function applySandhi(syllables, options = {}, grouping, characters) {
|
|
|
120
90
|
const applied = thirdTone
|
|
121
91
|
? applyThirdTone(syllables, grouping)
|
|
122
92
|
: [...syllables];
|
|
93
|
+
const endings = endingsOf(syllables.length, grouping);
|
|
123
94
|
for (const [at, syllable] of applied.entries()) {
|
|
95
|
+
const character = characters?.[at];
|
|
124
96
|
const following = applied[at + 1];
|
|
125
|
-
if (yiBu && isYi(syllable) && syllable.tone === 1) {
|
|
97
|
+
if (yiBu && isYi(syllable, character) && syllable.tone === 1) {
|
|
126
98
|
// A 一 that is not counting keeps its citation tone, so it is left
|
|
127
99
|
// exactly as the dictionary stored it.
|
|
128
100
|
if (isCounting(applied, at, characters)) {
|
|
129
|
-
|
|
101
|
+
// A 一 closing a longer word counts nothing, because what follows it
|
|
102
|
+
// is outside the word: 唯一 is `wéiyī` whatever comes next, and so are
|
|
103
|
+
// 之一, 统一 and 星期一. The 一 of 一个 is a word of its own, which is
|
|
104
|
+
// why it still assimilates across the boundary.
|
|
105
|
+
const counted = endings.has(at) ? undefined : following;
|
|
106
|
+
applied[at] = { ...syllable, tone: yiToneBefore(counted?.tone) };
|
|
130
107
|
}
|
|
131
108
|
continue;
|
|
132
109
|
}
|
|
133
110
|
// 不 flattens to second tone before a fourth, and is otherwise unchanged.
|
|
111
|
+
// Unlike 一 it keeps assimilating at the end of a word, since what it
|
|
112
|
+
// negates is regularly in the next one: 决不会 is `juébú huì`.
|
|
134
113
|
if (yiBu &&
|
|
135
|
-
isBu(syllable) &&
|
|
114
|
+
isBu(syllable, character) &&
|
|
136
115
|
syllable.tone === 4 &&
|
|
137
116
|
following?.tone === 4) {
|
|
138
117
|
applied[at] = { ...syllable, tone: 2 };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sandhi.js","sourceRoot":"","sources":["../../src/decode/sandhi.ts"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"sandhi.js","sourceRoot":"","sources":["../../src/decode/sandhi.ts"],"names":[],"mappings":"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"}
|