@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.
Files changed (145) hide show
  1. package/CHANGELOG.md +87 -0
  2. package/NOTICE +7 -0
  3. package/README.md +144 -19
  4. package/data/full.entries +13400 -13400
  5. package/data/manifest.json +4 -4
  6. package/data/standard.entries +2492 -2492
  7. package/dist/cli/arguments.d.ts +67 -0
  8. package/dist/cli/arguments.d.ts.map +1 -1
  9. package/dist/cli/arguments.js +79 -0
  10. package/dist/cli/arguments.js.map +1 -1
  11. package/dist/cli/colour.d.ts +77 -0
  12. package/dist/cli/colour.d.ts.map +1 -0
  13. package/dist/cli/colour.js +117 -0
  14. package/dist/cli/colour.js.map +1 -0
  15. package/dist/cli/commands.d.ts +49 -1
  16. package/dist/cli/commands.d.ts.map +1 -1
  17. package/dist/cli/commands.js +404 -42
  18. package/dist/cli/commands.js.map +1 -1
  19. package/dist/cli/environment.d.ts.map +1 -1
  20. package/dist/cli/environment.js +20 -0
  21. package/dist/cli/environment.js.map +1 -1
  22. package/dist/cli/help.d.ts.map +1 -1
  23. package/dist/cli/help.js +43 -16
  24. package/dist/cli/help.js.map +1 -1
  25. package/dist/cli/run.d.ts +11 -0
  26. package/dist/cli/run.d.ts.map +1 -1
  27. package/dist/cli/run.js +4 -2
  28. package/dist/cli/run.js.map +1 -1
  29. package/dist/decode/convert.d.ts +20 -0
  30. package/dist/decode/convert.d.ts.map +1 -1
  31. package/dist/decode/convert.js +170 -12
  32. package/dist/decode/convert.js.map +1 -1
  33. package/dist/decode/decode.d.ts +3 -2
  34. package/dist/decode/decode.d.ts.map +1 -1
  35. package/dist/decode/decode.js +17 -4
  36. package/dist/decode/decode.js.map +1 -1
  37. package/dist/decode/reading-rules.d.ts +56 -0
  38. package/dist/decode/reading-rules.d.ts.map +1 -0
  39. package/dist/decode/reading-rules.js +107 -0
  40. package/dist/decode/reading-rules.js.map +1 -0
  41. package/dist/decode/rules.d.ts +66 -0
  42. package/dist/decode/rules.d.ts.map +1 -0
  43. package/dist/decode/rules.js +138 -0
  44. package/dist/decode/rules.js.map +1 -0
  45. package/dist/decode/sandhi.d.ts +1 -1
  46. package/dist/decode/sandhi.d.ts.map +1 -1
  47. package/dist/decode/sandhi.js +60 -1
  48. package/dist/decode/sandhi.js.map +1 -1
  49. package/dist/decode/word.d.ts +18 -0
  50. package/dist/decode/word.d.ts.map +1 -1
  51. package/dist/dictionary/artifact.d.ts.map +1 -1
  52. package/dist/dictionary/artifact.js +28 -1
  53. package/dist/dictionary/artifact.js.map +1 -1
  54. package/dist/dictionary/dictionary.d.ts +9 -0
  55. package/dist/dictionary/dictionary.d.ts.map +1 -1
  56. package/dist/dictionary/dictionary.js +7 -0
  57. package/dist/dictionary/dictionary.js.map +1 -1
  58. package/dist/dictionary/entry.d.ts +12 -0
  59. package/dist/dictionary/entry.d.ts.map +1 -1
  60. package/dist/dictionary/entry.js.map +1 -1
  61. package/dist/dictionary/merge.d.ts +3 -1
  62. package/dist/dictionary/merge.d.ts.map +1 -1
  63. package/dist/dictionary/merge.js +19 -1
  64. package/dist/dictionary/merge.js.map +1 -1
  65. package/dist/format/transcription.d.ts +52 -0
  66. package/dist/format/transcription.d.ts.map +1 -0
  67. package/dist/format/transcription.js +88 -0
  68. package/dist/format/transcription.js.map +1 -0
  69. package/dist/index.d.ts +24 -3
  70. package/dist/index.d.ts.map +1 -1
  71. package/dist/index.js +15 -1
  72. package/dist/index.js.map +1 -1
  73. package/dist/numerals/cardinal.d.ts +39 -0
  74. package/dist/numerals/cardinal.d.ts.map +1 -0
  75. package/dist/numerals/cardinal.js +111 -0
  76. package/dist/numerals/cardinal.js.map +1 -0
  77. package/dist/numerals/characters.d.ts +31 -0
  78. package/dist/numerals/characters.d.ts.map +1 -0
  79. package/dist/numerals/characters.js +80 -0
  80. package/dist/numerals/characters.js.map +1 -0
  81. package/dist/numerals/numerals.d.ts +76 -0
  82. package/dist/numerals/numerals.d.ts.map +1 -0
  83. package/dist/numerals/numerals.js +119 -0
  84. package/dist/numerals/numerals.js.map +1 -0
  85. package/dist/numerals/text.d.ts +52 -0
  86. package/dist/numerals/text.d.ts.map +1 -0
  87. package/dist/numerals/text.js +248 -0
  88. package/dist/numerals/text.js.map +1 -0
  89. package/dist/orthography/grouping.d.ts +56 -11
  90. package/dist/orthography/grouping.d.ts.map +1 -1
  91. package/dist/orthography/grouping.js +109 -35
  92. package/dist/orthography/grouping.js.map +1 -1
  93. package/dist/orthography/idiom-list.d.ts +56 -0
  94. package/dist/orthography/idiom-list.d.ts.map +1 -0
  95. package/dist/orthography/idiom-list.js +296 -0
  96. package/dist/orthography/idiom-list.js.map +1 -0
  97. package/dist/orthography/idioms.d.ts +18 -0
  98. package/dist/orthography/idioms.d.ts.map +1 -0
  99. package/dist/orthography/idioms.js +22 -0
  100. package/dist/orthography/idioms.js.map +1 -0
  101. package/dist/orthography/reduplication.d.ts +52 -0
  102. package/dist/orthography/reduplication.d.ts.map +1 -0
  103. package/dist/orthography/reduplication.js +99 -0
  104. package/dist/orthography/reduplication.js.map +1 -0
  105. package/dist/orthography/rule.d.ts +50 -0
  106. package/dist/orthography/rule.d.ts.map +1 -0
  107. package/dist/orthography/rule.js +101 -0
  108. package/dist/orthography/rule.js.map +1 -0
  109. package/dist/sources/cedict.d.ts +23 -0
  110. package/dist/sources/cedict.d.ts.map +1 -1
  111. package/dist/sources/cedict.js +28 -0
  112. package/dist/sources/cedict.js.map +1 -1
  113. package/dist/syllable/syllable.d.ts +1 -1
  114. package/dist/syllable/syllable.d.ts.map +1 -1
  115. package/dist/syllable/syllable.js +2 -37
  116. package/dist/syllable/syllable.js.map +1 -1
  117. package/dist/tone/tone-mark.d.ts +23 -0
  118. package/dist/tone/tone-mark.d.ts.map +1 -1
  119. package/dist/tone/tone-mark.js +49 -0
  120. package/dist/tone/tone-mark.js.map +1 -1
  121. package/dist/transcription/bopomofo.d.ts +46 -0
  122. package/dist/transcription/bopomofo.d.ts.map +1 -0
  123. package/dist/transcription/bopomofo.js +371 -0
  124. package/dist/transcription/bopomofo.js.map +1 -0
  125. package/dist/transcription/gwoyeu.d.ts +32 -0
  126. package/dist/transcription/gwoyeu.d.ts.map +1 -0
  127. package/dist/transcription/gwoyeu.js +491 -0
  128. package/dist/transcription/gwoyeu.js.map +1 -0
  129. package/dist/transcription/ipa.d.ts +40 -0
  130. package/dist/transcription/ipa.d.ts.map +1 -0
  131. package/dist/transcription/ipa.js +221 -0
  132. package/dist/transcription/ipa.js.map +1 -0
  133. package/dist/transcription/spelling-index.d.ts +23 -0
  134. package/dist/transcription/spelling-index.d.ts.map +1 -0
  135. package/dist/transcription/spelling-index.js +61 -0
  136. package/dist/transcription/spelling-index.js.map +1 -0
  137. package/dist/transcription/wade-giles.d.ts +108 -0
  138. package/dist/transcription/wade-giles.d.ts.map +1 -0
  139. package/dist/transcription/wade-giles.js +656 -0
  140. package/dist/transcription/wade-giles.js.map +1 -0
  141. package/dist/transcription/yale.d.ts +43 -0
  142. package/dist/transcription/yale.d.ts.map +1 -0
  143. package/dist/transcription/yale.js +242 -0
  144. package/dist/transcription/yale.js.map +1 -0
  145. package/package.json +9 -5
@@ -3,6 +3,7 @@ import process from "node:process";
3
3
  import { fileURLToPath } from "node:url";
4
4
  import { fileSource } from "../dictionary/node-source.js";
5
5
  import { loadDictionary } from "../dictionary/source.js";
6
+ import { depthFrom } from "./colour.js";
6
7
  /**
7
8
  * Where the artifacts that shipped with the package are.
8
9
  *
@@ -61,12 +62,31 @@ export function versionFrom(manifest) {
61
62
  async function version() {
62
63
  return versionFrom(await readFile(new URL("../../package.json", import.meta.url), "utf8"));
63
64
  }
65
+ /**
66
+ * What this process's terminal says about itself.
67
+ *
68
+ * The reading half only: {@link depthFrom} decides what it means, so that the
69
+ * decision is a pure function with a test rather than a sniff at the point of
70
+ * use. Standard output is the stream asked about, since that is where a
71
+ * command's answer goes.
72
+ */
73
+ /* c8 ignore start -- the real process; depthFrom does the deciding */
74
+ function terminalColours() {
75
+ return depthFrom({
76
+ isTerminal: process.stdout.isTTY,
77
+ noColour: process.env["NO_COLOR"],
78
+ term: process.env["TERM"],
79
+ colorterm: process.env["COLORTERM"],
80
+ });
81
+ }
82
+ /* c8 ignore stop */
64
83
  /**
65
84
  * Wire the CLI up to Node.
66
85
  */
67
86
  export async function nodeEnvironment() {
68
87
  return {
69
88
  version: await version(),
89
+ colours: terminalColours(),
70
90
  readInput,
71
91
  loadDictionary: async (choice) => loadDictionary(fileSource(choice.directory ?? shippedData()), choice.tier),
72
92
  };
@@ -1 +1 @@
1
- {"version":3,"file":"environment.js","sourceRoot":"","sources":["../../src/cli/environment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,OAAO,MAAM,cAAc,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAGzD;;;;;;;GAOG;AACH,SAAS,WAAW;IAClB,OAAO,aAAa,CAAC,IAAI,GAAG,CAAC,YAAY,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC/D,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,KAA4B;IACxD,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,KAAK,EAAE,CAAC;QAChC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrB,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACzB,CAAC;AAED;;;;;GAKG;AACH,uEAAuE;AACvE,KAAK,UAAU,SAAS;IACtB,IAAI,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACxB,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IAClC,4EAA4E;IAC5E,6DAA6D;IAC7D,MAAM,KAAK,GAA0B,OAAO,CAAC,KAAK,CAAC;IACnD,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC;AACxB,CAAC;AACD,oBAAoB;AAEpB;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAC,QAAgB;IAC1C,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC7C,MAAM,KAAK,GACT,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,SAAS,IAAI,MAAM;QAClE,CAAC,CAAC,MAAM,CAAC,OAAO;QAChB,CAAC,CAAC,SAAS,CAAC;IAChB,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AACvD,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,OAAO;IACpB,OAAO,WAAW,CAChB,MAAM,QAAQ,CAAC,IAAI,GAAG,CAAC,oBAAoB,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CACvE,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,OAAO;QACL,OAAO,EAAE,MAAM,OAAO,EAAE;QACxB,SAAS;QACT,cAAc,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,CAC/B,cAAc,CACZ,UAAU,CAAC,MAAM,CAAC,SAAS,IAAI,WAAW,EAAE,CAAC,EAC7C,MAAM,CAAC,IAAI,CACZ;KACJ,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"environment.js","sourceRoot":"","sources":["../../src/cli/environment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,OAAO,MAAM,cAAc,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,EAAoB,SAAS,EAAE,MAAM,aAAa,CAAC;AAG1D;;;;;;;GAOG;AACH,SAAS,WAAW;IAClB,OAAO,aAAa,CAAC,IAAI,GAAG,CAAC,YAAY,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC/D,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,KAA4B;IACxD,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,KAAK,EAAE,CAAC;QAChC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrB,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACzB,CAAC;AAED;;;;;GAKG;AACH,uEAAuE;AACvE,KAAK,UAAU,SAAS;IACtB,IAAI,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACxB,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IAClC,4EAA4E;IAC5E,6DAA6D;IAC7D,MAAM,KAAK,GAA0B,OAAO,CAAC,KAAK,CAAC;IACnD,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC;AACxB,CAAC;AACD,oBAAoB;AAEpB;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAC,QAAgB;IAC1C,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC7C,MAAM,KAAK,GACT,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,SAAS,IAAI,MAAM;QAClE,CAAC,CAAC,MAAM,CAAC,OAAO;QAChB,CAAC,CAAC,SAAS,CAAC;IAChB,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AACvD,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,OAAO;IACpB,OAAO,WAAW,CAChB,MAAM,QAAQ,CAAC,IAAI,GAAG,CAAC,oBAAoB,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CACvE,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,sEAAsE;AACtE,SAAS,eAAe;IACtB,OAAO,SAAS,CAAC;QACf,UAAU,EAAE,OAAO,CAAC,MAAM,CAAC,KAAK;QAChC,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC;QACjC,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC;QACzB,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC;KACpC,CAAC,CAAC;AACL,CAAC;AACD,oBAAoB;AAEpB;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,OAAO;QACL,OAAO,EAAE,MAAM,OAAO,EAAE;QACxB,OAAO,EAAE,eAAe,EAAE;QAC1B,SAAS;QACT,cAAc,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,CAC/B,cAAc,CACZ,UAAU,CAAC,MAAM,CAAC,SAAS,IAAI,WAAW,EAAE,CAAC,EAC7C,MAAM,CAAC,IAAI,CACZ;KACJ,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../../src/cli/help.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAY,MAAM,eAAe,CAAC;AA8DvD;;GAEG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,SAAS,MAAM,EAAE,CAe/D;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,SAAS,MAAM,EAAE,CAwB/C"}
1
+ {"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../../src/cli/help.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAY,MAAM,eAAe,CAAC;AAgGvD;;GAEG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,SAAS,MAAM,EAAE,CAe/D;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,SAAS,MAAM,EAAE,CAyB/C"}
package/dist/cli/help.js CHANGED
@@ -15,42 +15,68 @@ const FLAG_HELP = new Map([
15
15
  ["third-tone", "write third-tone sandhi: nǐ hǎo becomes ní hǎo"],
16
16
  ["no-sandhi", "do not write 一 and 不 sandhi"],
17
17
  ["greedy", "decode with the old longest-match baseline"],
18
+ ["system", "write it in bopomofo, wade-giles, yale, gwoyeu or ipa"],
18
19
  ["no-tone-classes", "leave the tone classes off"],
19
20
  ["no-uncertain", "do not mark uncertain readings"],
21
+ ["from", "pinyin, wade-giles or bopomofo (auto by default)"],
20
22
  ["data", "read the dictionary from this directory"],
21
23
  ["tier", "core, standard or full (default)"],
22
24
  ]);
23
25
  /**
24
- * How wide the flag column is, which is the longest flag plus a gap.
25
- */
26
- const FLAG_WIDTH = 23;
27
- /**
28
- * The global flags, listed under every command's help.
26
+ * How wide the command column is in the listing.
27
+ *
28
+ * Derived from the longest name rather than fixed, because a fixed 10 was
29
+ * exactly the width of `transcribe` and ran the summary straight into it. A
30
+ * number that has to be revisited whenever a command is added is a number that
31
+ * will not be.
29
32
  */
30
- const GLOBAL_HELP = [
31
- ["--data <dir>", "read the dictionary from this directory"],
32
- ["--tier <tier>", "core, standard or full (default)"],
33
- ["--json", "write one JSON document per answer"],
34
- ["-h, --help", "show this help"],
35
- ["-v, --version", "show the version"],
36
- ].map(([flag, help]) => ` ${flag.padEnd(FLAG_WIDTH)}${help}`);
33
+ const COMMAND_WIDTH = Math.max(...COMMANDS.map((command) => command.name.length)) + 2;
37
34
  /**
38
35
  * The flags that take a value after them, as opposed to standing alone.
39
36
  */
40
37
  const VALUE_FLAGS = new Set([
38
+ "from",
39
+ "system",
41
40
  "notation",
42
41
  "locale",
43
42
  "apostrophe",
44
43
  "capitals",
45
44
  "punctuation",
46
45
  ]);
46
+ /**
47
+ * A flag as the help writes it, before its description.
48
+ */
49
+ function flagWritten(name) {
50
+ return `--${name}${VALUE_FLAGS.has(name) ? " <value>" : ""}`;
51
+ }
52
+ /**
53
+ * The global flags, listed under every command's help.
54
+ *
55
+ * Both spellings of the colour flags are listed rather than one being a quiet
56
+ * alias: nobody should have to discover which of the two this command chose.
57
+ */
58
+ const GLOBAL_FLAG_HELP = [
59
+ ["--data <dir>", "read the dictionary from this directory"],
60
+ ["--tier <tier>", "core, standard or full (default)"],
61
+ ["--colour, --color", "colour the tones, terminal or not"],
62
+ ["--no-colour, --no-color", "leave the tones uncoloured"],
63
+ ["--json", "write one JSON document per answer"],
64
+ ["-h, --help", "show this help"],
65
+ ["-v, --version", "show the version"],
66
+ ];
67
+ /**
68
+ * How wide the flag column is, which is the longest flag written plus a gap.
69
+ *
70
+ * Derived for the same reason {@link COMMAND_WIDTH} is: it was a fixed 23, and
71
+ * `--no-colour, --no-color` is exactly 23 characters long.
72
+ */
73
+ const FLAG_WIDTH = Math.max(...GLOBAL_FLAG_HELP.map(([flag]) => flag.length), ...[...FLAG_HELP.keys()].map((name) => flagWritten(name).length)) + 2;
74
+ const GLOBAL_HELP = GLOBAL_FLAG_HELP.map(([flag, help]) => ` ${flag.padEnd(FLAG_WIDTH)}${help}`);
47
75
  /**
48
76
  * A flag as the help lists it.
49
77
  */
50
78
  function flagLine(name) {
51
- const hasValue = VALUE_FLAGS.has(name);
52
- const written = `--${name}${hasValue ? " <value>" : ""}`;
53
- return ` ${written.padEnd(FLAG_WIDTH)}${FLAG_HELP.get(name) ?? ""}`;
79
+ return ` ${flagWritten(name).padEnd(FLAG_WIDTH)}${FLAG_HELP.get(name) ?? ""}`;
54
80
  }
55
81
  /**
56
82
  * The help for one command.
@@ -81,7 +107,7 @@ export function generalHelp() {
81
107
  "Usage: pinyinjs <command> [arguments] [options]",
82
108
  "",
83
109
  "Commands:",
84
- ...COMMANDS.map((command) => ` ${command.name.padEnd(10)}${command.summary}`),
110
+ ...COMMANDS.map((command) => ` ${command.name.padEnd(COMMAND_WIDTH)}${command.summary}`),
85
111
  "",
86
112
  "Options for every command:",
87
113
  ...GLOBAL_HELP,
@@ -94,6 +120,7 @@ export function generalHelp() {
94
120
  " pinyinjs explain 长江大桥",
95
121
  " pinyinjs lookup 头发",
96
122
  " pinyinjs syllable nǐhǎo",
123
+ " pinyinjs transcribe běijīng",
97
124
  " cat article.txt | pinyinjs convert",
98
125
  ];
99
126
  }
@@ -1 +1 @@
1
- {"version":3,"file":"help.js","sourceRoot":"","sources":["../../src/cli/help.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"help.js","sourceRoot":"","sources":["../../src/cli/help.ts"],"names":[],"mappings":"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"}
package/dist/cli/run.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import type { Dictionary } from "../dictionary/dictionary.js";
2
2
  import { type DictionaryChoice } from "./arguments.js";
3
+ import { type ColourDepth } from "./colour.js";
3
4
  /**
4
5
  * What the CLI needs from the world outside it.
5
6
  *
@@ -11,6 +12,16 @@ export interface CliEnvironment {
11
12
  /** Standard input, or the empty string where there is none to read. */
12
13
  readonly readInput: () => Promise<string>;
13
14
  readonly loadDictionary: (choice: DictionaryChoice) => Promise<Dictionary>;
15
+ /**
16
+ * How much colour the output can carry, before any flag has its say.
17
+ *
18
+ * Here rather than sniffed inside a command, because a command reaching for
19
+ * `process.stdout.isTTY` would put a decision in the one place the coverage
20
+ * gate cannot see. An environment states the answer and a test can ask for
21
+ * either one. `depthFrom` in `colour.ts` is how the Node adapter arrives at
22
+ * it, and is a pure function for the same reason.
23
+ */
24
+ readonly colours: ColourDepth;
14
25
  }
15
26
  /**
16
27
  * What a run produced.
@@ -1 +1 @@
1
- {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/cli/run.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAEL,KAAK,gBAAgB,EAKtB,MAAM,gBAAgB,CAAC;AAIxB;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,uEAAuE;IACvE,QAAQ,CAAC,SAAS,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1C,QAAQ,CAAC,cAAc,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;CAC5E;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,+DAA+D;IAC/D,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAuED;;;;;GAKG;AACH,wBAAsB,MAAM,CAC1B,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,WAAW,EAAE,cAAc,GAC1B,OAAO,CAAC,SAAS,CAAC,CAoCpB"}
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/cli/run.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAGL,KAAK,gBAAgB,EAKtB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,KAAK,WAAW,EAAc,MAAM,aAAa,CAAC;AAI3D;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,uEAAuE;IACvE,QAAQ,CAAC,SAAS,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1C,QAAQ,CAAC,cAAc,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;IAC3E;;;;;;;;OAQG;IACH,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;CAC/B;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,+DAA+D;IAC/D,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAwED;;;;;GAKG;AACH,wBAAsB,MAAM,CAC1B,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,WAAW,EAAE,cAAc,GAC1B,OAAO,CAAC,SAAS,CAAC,CAoCpB"}
package/dist/cli/run.js CHANGED
@@ -1,4 +1,5 @@
1
- import { checkFlags, dictionaryChoice, GLOBAL_FLAGS, parseArguments, UsageError, } from "./arguments.js";
1
+ import { checkFlags, colourDepth, dictionaryChoice, GLOBAL_FLAGS, parseArguments, UsageError, } from "./arguments.js";
2
+ import { painterFor } from "./colour.js";
2
3
  import { commandNamed } from "./commands.js";
3
4
  import { commandHelp, generalHelp } from "./help.js";
4
5
  /**
@@ -38,7 +39,8 @@ async function runCommand(command, texts, flags, environment) {
38
39
  const dictionary = command.needsDictionary
39
40
  ? await environment.loadDictionary(choice)
40
41
  : undefined;
41
- const reported = command.run({ texts, flags, dictionary, choice });
42
+ const paint = painterFor(colourDepth(flags, environment.colours));
43
+ const reported = command.run({ texts, flags, dictionary, choice, paint });
42
44
  return {
43
45
  // One JSON document per answer rather than one array for the run, so that
44
46
  // `jq` sees the same shape whether one text was converted or a file was.
@@ -1 +1 @@
1
- {"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/cli/run.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/cli/run.ts"],"names":[],"mappings":"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"}
@@ -24,7 +24,19 @@ export interface ConvertOptions {
24
24
  readonly punctuation?: PunctuationStyle;
25
25
  /** Whether GB/T 16159 word grouping is applied. Defaults to true. */
26
26
  readonly grouping?: boolean;
27
+ /**
28
+ * What to do with the digits in a text. Defaults to `read`.
29
+ *
30
+ * `read` says them: 我有3个 is `wǒ yǒu sān gè` and 1997年 is
31
+ * `yī jiǔ jiǔ qī nián`. `keep` leaves every digit exactly as it was written,
32
+ * which is what this did before there was anything to read them with.
33
+ */
34
+ readonly numbers?: NumberStyle;
27
35
  }
36
+ /**
37
+ * What a conversion does with the digits it meets.
38
+ */
39
+ export type NumberStyle = "read" | "keep";
28
40
  /**
29
41
  * One piece of a conversion: a syllable, or the text between two of them.
30
42
  *
@@ -82,4 +94,12 @@ export declare function joinPieces(pieces: readonly ConvertedPiece[]): string;
82
94
  * Use {@link convert} instead.
83
95
  */
84
96
  export declare function convertGreedily(dictionary: Dictionary, text: string, options?: ConvertOptions): string;
97
+ /**
98
+ * The same, kept in pieces.
99
+ *
100
+ * {@link convertPieces} for the baseline, so that a caller rendering each
101
+ * syllable — colouring its tone — can still ask for the comparison. The pieces
102
+ * carry no confidence, because the greedy decode cannot say what it rejected.
103
+ */
104
+ export declare function convertPiecesGreedily(dictionary: Dictionary, text: string, options?: ConvertOptions): readonly ConvertedPiece[];
85
105
  //# sourceMappingURL=convert.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"convert.d.ts","sourceRoot":"","sources":["../../src/decode/convert.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,KAAK,eAAe,EAAY,MAAM,8BAA8B,CAAC;AAC9E,OAAO,EAGL,KAAK,YAAY,EAElB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EACL,KAAK,gBAAgB,EAEtB,MAAM,+BAA+B,CAAC;AACvC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,YAAY,EAElB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAIzD,OAAO,EAAe,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAG9D;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,0DAA0D;IAC1D,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,qDAAqD;IACrD,QAAQ,CAAC,QAAQ,CAAC,EAAE,YAAY,CAAC;IACjC,kCAAkC;IAClC,QAAQ,CAAC,MAAM,CAAC,EAAE,aAAa,CAAC;IAChC,sDAAsD;IACtD,QAAQ,CAAC,UAAU,CAAC,EAAE,eAAe,CAAC;IACtC,sDAAsD;IACtD,QAAQ,CAAC,QAAQ,CAAC,EAAE,YAAY,CAAC;IACjC,qEAAqE;IACrE,QAAQ,CAAC,WAAW,CAAC,EAAE,gBAAgB,CAAC;IACxC,qEAAqE;IACrE,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,yEAAyE;IACzE,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,SAAS,CAAC;IACxC;;;;;;;OAOG;IACH,QAAQ,CAAC,UAAU,EAAE,iBAAiB,GAAG,SAAS,CAAC;CACpD;AA8ND;;;;;;;;GAQG;AACH,wBAAgB,OAAO,CACrB,UAAU,EAAE,UAAU,EACtB,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,cAAmB,GAC3B,MAAM,CAER;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAC3B,UAAU,EAAE,UAAU,EACtB,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,cAAmB,GAC3B,SAAS,cAAc,EAAE,CAE3B;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,SAAS,cAAc,EAAE,GAAG,MAAM,CAEpE;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,UAAU,EAAE,UAAU,EACtB,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,cAAmB,GAC3B,MAAM,CAER"}
1
+ {"version":3,"file":"convert.d.ts","sourceRoot":"","sources":["../../src/decode/convert.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,KAAK,eAAe,EAAY,MAAM,8BAA8B,CAAC;AAC9E,OAAO,EAGL,KAAK,YAAY,EAElB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EACL,KAAK,gBAAgB,EAEtB,MAAM,+BAA+B,CAAC;AAOvC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,YAAY,EAElB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAIzD,OAAO,EAAe,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAG9D;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,0DAA0D;IAC1D,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,qDAAqD;IACrD,QAAQ,CAAC,QAAQ,CAAC,EAAE,YAAY,CAAC;IACjC,kCAAkC;IAClC,QAAQ,CAAC,MAAM,CAAC,EAAE,aAAa,CAAC;IAChC,sDAAsD;IACtD,QAAQ,CAAC,UAAU,CAAC,EAAE,eAAe,CAAC;IACtC,sDAAsD;IACtD,QAAQ,CAAC,QAAQ,CAAC,EAAE,YAAY,CAAC;IACjC,qEAAqE;IACrE,QAAQ,CAAC,WAAW,CAAC,EAAE,gBAAgB,CAAC;IACxC,qEAAqE;IACrE,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B;;;;;;OAMG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,WAAW,CAAC;CAChC;AAED;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,CAAC;AAE1C;;;;;;;GAOG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,yEAAyE;IACzE,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,SAAS,CAAC;IACxC;;;;;;;OAOG;IACH,QAAQ,CAAC,UAAU,EAAE,iBAAiB,GAAG,SAAS,CAAC;CACpD;AAibD;;;;;;;;GAQG;AACH,wBAAgB,OAAO,CACrB,UAAU,EAAE,UAAU,EACtB,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,cAAmB,GAC3B,MAAM,CAER;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAC3B,UAAU,EAAE,UAAU,EACtB,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,cAAmB,GAC3B,SAAS,cAAc,EAAE,CAE3B;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,SAAS,cAAc,EAAE,GAAG,MAAM,CAEpE;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,UAAU,EAAE,UAAU,EACtB,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,cAAmB,GAC3B,MAAM,CAER;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,UAAU,EAAE,UAAU,EACtB,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,cAAmB,GAC3B,SAAS,cAAc,EAAE,CAE3B"}
@@ -2,6 +2,8 @@ import { markWord } from "../orthography/apostrophe.js";
2
2
  import { capitaliseSentenceParts, capitaliseWord, isSentence, } from "../orthography/capitals.js";
3
3
  import { applyGrouping } from "../orthography/grouping.js";
4
4
  import { toLatinPunctuationParts, } from "../orthography/punctuation.js";
5
+ import { readNumbersIn, saidNumeral, } from "../numerals/text.js";
6
+ import { toCharacters } from "../script/characters.js";
5
7
  import { writeSyllable, } from "../syllable/syllable.js";
6
8
  import { decodeRun, decodeRunScored } from "./decode.js";
7
9
  import { decodeGreedily } from "./greedy.js";
@@ -75,7 +77,9 @@ function writeRun(dictionary, words, locale, written, sandhi) {
75
77
  /* c8 ignore next -- readings is built by mapping over these same words */
76
78
  const length = readings[index]?.length ?? 0;
77
79
  if (index > 0) {
78
- pieces.push(plainPiece(" "));
80
+ // A space, unless 分词连写 wrote a hyphen: 干干净净 is one orthographic
81
+ // word, `gāngān-jìngjìng`, cut into two decoded ones.
82
+ pieces.push(plainPiece(scored.word.separator ?? " "));
79
83
  }
80
84
  pieces.push(...writeWord(flattened.slice(at, at + length),
81
85
  // A locale reading of a different length cannot be lined up with the
@@ -96,25 +100,169 @@ function rewrite(pieces, pass) {
96
100
  return text === piece.text ? piece : { ...piece, text };
97
101
  });
98
102
  }
103
+ /**
104
+ * The words a Han run decodes to, with 分词连写 applied.
105
+ *
106
+ * Grouping rewrites word boundaries and never the readings behind them, so the
107
+ * syllables — and the confidence beside them — survive it in order.
108
+ */
109
+ function wordsOf(decoded, dictionary, isGrouped) {
110
+ return isGrouped
111
+ ? regroup(decoded, applyGrouping(decoded.map((scored) => scored.word), dictionary))
112
+ : decoded;
113
+ }
114
+ /**
115
+ * What comes after a run: the first character of the next Han, and its first
116
+ * syllable.
117
+ *
118
+ * A number's only context. The character decides how it is read — 年 makes
119
+ * 1997 a year, 个 makes 3 a count — and the syllable is what a 一 ending the
120
+ * number assimilates to.
121
+ */
122
+ function following(runs, decoded, at) {
123
+ const next = runs[at + 1];
124
+ const isAfterHan = runs[at - 1]?.isHan === true;
125
+ if (next?.isHan !== true) {
126
+ return { after: { character: "", syllable: undefined }, isAfterHan };
127
+ }
128
+ return {
129
+ after: {
130
+ character: toCharacters(next.text)[0] ?? "",
131
+ syllable: decoded[at + 1]?.[0]?.word.reading[0],
132
+ },
133
+ isAfterHan,
134
+ };
135
+ }
136
+ /**
137
+ * Whether a character wants a space between it and a number read out.
138
+ *
139
+ * A letter or a digit does; punctuation does not, so 20%。 keeps its full stop
140
+ * against the number.
141
+ */
142
+ const WORDLIKE = /[\p{L}\p{N}]/u;
143
+ /**
144
+ * Whether two stretches take a space between them once one has been read.
145
+ */
146
+ function isSpaced(before, after) {
147
+ return WORDLIKE.test(before.at(-1) ?? "") && WORDLIKE.test(after[0] ?? "");
148
+ }
149
+ /**
150
+ * Write a run whose words are already known, a word at a time.
151
+ *
152
+ * Each group is one orthographic word and takes the 隔音符号 within itself, so
153
+ * a time's minutes are `sānshí` rather than `sān shí` — the same grouping the
154
+ * number would get if the text had written 6点30分 out in 汉字.
155
+ */
156
+ function groupedPieces(spelled, said, words, written) {
157
+ const pieces = [];
158
+ let at = 0;
159
+ for (const length of words) {
160
+ if (at > 0) {
161
+ pieces.push(plainPiece(" "));
162
+ }
163
+ const group = spelled.slice(at, at + length);
164
+ for (const [index, text] of markWord(group, written.apostrophe).entries()) {
165
+ pieces.push({
166
+ text,
167
+ syllable: said[at + index],
168
+ confidence: undefined,
169
+ });
170
+ }
171
+ at += length;
172
+ }
173
+ return pieces;
174
+ }
175
+ /**
176
+ * Write a number's syllables as the pieces they are written with.
177
+ *
178
+ * A counted number is *one word*, which is what 正词法 6.1.5 asks for: 123 is
179
+ * `yībǎi'èrshísān` and not three words, so the syllables run together and take
180
+ * the 隔音符号 where one is needed. A number read out digit by digit is not a
181
+ * word at all — it is digits — so those are written apart: 1997年 is
182
+ * `yī jiǔ jiǔ qī nián`.
183
+ */
184
+ function numberPieces(said, segment, written) {
185
+ const spelled = said.map((syllable) => writeSyllable(syllable, written.notation));
186
+ // A run that says where its words break gets them: a time is `liù diǎn
187
+ // sānshí fēn`, with the hour and the minutes each a word of their own.
188
+ if (segment.words !== undefined) {
189
+ return groupedPieces(spelled, said, segment.words, written);
190
+ }
191
+ // A decimal is not one word either: everything after the 点 is read digit by
192
+ // digit, so 3.14 is `sān diǎn yī sì`.
193
+ if (segment.style === "digits" || (segment.hanzi ?? "").includes("点")) {
194
+ return spelled.flatMap((text, at) => [
195
+ ...(at === 0 ? [] : [plainPiece(" ")]),
196
+ { text, syllable: said[at], confidence: undefined },
197
+ ]);
198
+ }
199
+ const isNumbered = written.notation === "numbers" || written.notation === "superscript";
200
+ return markWord(spelled, isNumbered ? "never" : written.apostrophe).map((text, at) => ({ text, syllable: said[at], confidence: undefined }));
201
+ }
202
+ /**
203
+ * A stand-in for the pinyin either side of a run, which ends in a letter.
204
+ */
205
+ function runEdge(isHan) {
206
+ return isHan ? "a" : "";
207
+ }
208
+ /**
209
+ * Write a stretch that was never Han, reading the numbers in it.
210
+ *
211
+ * Everything that is not a number goes through exactly as written, which is
212
+ * what this always did: digits are the only part of a non-Han run this package
213
+ * has anything to say about. Once a number *has* been read, though, the whole
214
+ * stretch is being said rather than shown, so its parts take the spacing of
215
+ * words — 3D打印 is `sān D dǎyìn` — and punctuation still takes none.
216
+ */
217
+ function writeNumbers(text, context, written, options) {
218
+ const segments = options.numbers === "keep"
219
+ ? []
220
+ : readNumbersIn(text, context.after.character);
221
+ if (segments.every((segment) => segment.reading === undefined)) {
222
+ return [plainPiece(text)];
223
+ }
224
+ const pieces = [];
225
+ let before = runEdge(context.isAfterHan);
226
+ for (const segment of segments) {
227
+ if (isSpaced(before, segment.text)) {
228
+ pieces.push(plainPiece(" "));
229
+ }
230
+ pieces.push(...(segment.reading === undefined
231
+ ? [plainPiece(segment.text)]
232
+ : numberPieces(saidNumeral(segment, context.after.syllable, options.sandhi), segment, written)));
233
+ // What decides the next space is what was *written*, not what was read:
234
+ // 95% ends in a sign and `bǎifēnzhījiǔshíwǔ` ends in a letter.
235
+ before = pieces.at(-1)?.text ?? before;
236
+ }
237
+ if (isSpaced(before, runEdge(context.after.character !== ""))) {
238
+ pieces.push(plainPiece(" "));
239
+ }
240
+ return pieces;
241
+ }
99
242
  /**
100
243
  * Run the pipeline over a text with a given decoder.
101
244
  */
102
245
  function convertWith(decode, dictionary, text, options) {
103
- const { locale = "zh-CN", notation = "marks", apostrophe = "always", capitals = "auto", punctuation = "latin", grouping = true, sandhi, } = options;
246
+ const { locale = "zh-CN", notation = "marks", apostrophe = "always", capitals = "auto", punctuation = "latin", grouping = true, numbers = "read", sandhi, } = options;
104
247
  const written = { notation, apostrophe, capitals };
105
248
  const converted = [];
106
- for (const run of splitRuns(text)) {
107
- if (!run.isHan) {
108
- converted.push(plainPiece(run.text));
249
+ // Decoded before anything is written, because a number needs to know what
250
+ // follows it — 1997年 is a year and 3个 is a count — and what follows it is
251
+ // in the next run.
252
+ const runs = [...splitRuns(text)];
253
+ const decoded = runs.map((run) => run.isHan
254
+ ? wordsOf(decode(dictionary, run.text), dictionary, grouping)
255
+ : []);
256
+ for (const [at, run] of runs.entries()) {
257
+ const words = decoded[at] ?? [];
258
+ if (run.isHan) {
259
+ converted.push(...writeRun(dictionary, words, locale, written, sandhi));
109
260
  continue;
110
261
  }
111
- const decoded = decode(dictionary, run.text);
112
- // Grouping rewrites word boundaries and never the readings behind them, so
113
- // the syllables — and the confidence beside them — survive it in order.
114
- const words = grouping
115
- ? regroup(decoded, applyGrouping(decoded.map((scored) => scored.word), dictionary))
116
- : decoded;
117
- converted.push(...writeRun(dictionary, words, locale, written, sandhi));
262
+ converted.push(...writeNumbers(run.text, following(runs, decoded, at), written, {
263
+ numbers,
264
+ sandhi,
265
+ }));
118
266
  }
119
267
  let pieces = converted;
120
268
  // Both of these read the whole conversion rather than one run: a sentence
@@ -186,4 +334,14 @@ export function joinPieces(pieces) {
186
334
  export function convertGreedily(dictionary, text, options = {}) {
187
335
  return joinPieces(convertWith(GREEDY, dictionary, text, options));
188
336
  }
337
+ /**
338
+ * The same, kept in pieces.
339
+ *
340
+ * {@link convertPieces} for the baseline, so that a caller rendering each
341
+ * syllable — colouring its tone — can still ask for the comparison. The pieces
342
+ * carry no confidence, because the greedy decode cannot say what it rejected.
343
+ */
344
+ export function convertPiecesGreedily(dictionary, text, options = {}) {
345
+ return convertWith(GREEDY, dictionary, text, options);
346
+ }
189
347
  //# sourceMappingURL=convert.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"convert.js","sourceRoot":"","sources":["../../src/decode/convert.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"convert.js","sourceRoot":"","sources":["../../src/decode/convert.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  import type { Dictionary } from "../dictionary/dictionary.js";
2
2
  import { type Lattice } from "./lattice.js";
3
3
  import { type ReadingProjection, type ReadingUnit } from "./locking.js";
4
+ import { type EdgeRule } from "./rules.js";
4
5
  import type { DecodedWord, ScoredWord } from "./word.js";
5
6
  /**
6
7
  * Decode the run's readings, scoring only where the readings are still open.
@@ -27,7 +28,7 @@ export declare function decodeSpacing(lattice: Lattice): readonly number[];
27
28
  * lock the positions that cannot vary, score the rest — where the greedy
28
29
  * baseline commits to the longest match at each position and never revisits it.
29
30
  */
30
- export declare function decodeRun(dictionary: Dictionary, run: string): readonly DecodedWord[];
31
+ export declare function decodeRun(dictionary: Dictionary, run: string, rules?: readonly EdgeRule[]): readonly DecodedWord[];
31
32
  /**
32
33
  * Decode a Han run, keeping what each reading was chosen over.
33
34
  *
@@ -36,5 +37,5 @@ export declare function decodeRun(dictionary: Dictionary, run: string): readonly
36
37
  * only worth running for a caller that will use the answer — rendering
37
38
  * uncertain readings differently, or reporting them.
38
39
  */
39
- export declare function decodeRunScored(dictionary: Dictionary, run: string): readonly ScoredWord[];
40
+ export declare function decodeRunScored(dictionary: Dictionary, run: string, rules?: readonly EdgeRule[]): readonly ScoredWord[];
40
41
  //# sourceMappingURL=decode.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"decode.d.ts","sourceRoot":"","sources":["../../src/decode/decode.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAE9D,OAAO,EAA2B,KAAK,OAAO,EAAE,MAAM,cAAc,CAAC;AACrE,OAAO,EAGL,KAAK,iBAAiB,EACtB,KAAK,WAAW,EAGjB,MAAM,cAAc,CAAC;AAEtB,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEzD;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,iBAAiB,GAC5B,SAAS,WAAW,EAAE,CAmBxB;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,SAAS,MAAM,EAAE,CAIjE;AA2DD;;;;;;GAMG;AACH,wBAAgB,SAAS,CACvB,UAAU,EAAE,UAAU,EACtB,GAAG,EAAE,MAAM,GACV,SAAS,WAAW,EAAE,CAMxB;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,UAAU,EAAE,UAAU,EACtB,GAAG,EAAE,MAAM,GACV,SAAS,UAAU,EAAE,CAavB"}
1
+ {"version":3,"file":"decode.d.ts","sourceRoot":"","sources":["../../src/decode/decode.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAE9D,OAAO,EAA2B,KAAK,OAAO,EAAE,MAAM,cAAc,CAAC;AACrE,OAAO,EAGL,KAAK,iBAAiB,EACtB,KAAK,WAAW,EAGjB,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3D,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEzD;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,iBAAiB,GAC5B,SAAS,WAAW,EAAE,CAmBxB;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,SAAS,MAAM,EAAE,CAIjE;AA2ED;;;;;;GAMG;AACH,wBAAgB,SAAS,CACvB,UAAU,EAAE,UAAU,EACtB,GAAG,EAAE,MAAM,EACX,KAAK,GAAE,SAAS,QAAQ,EAAkB,GACzC,SAAS,WAAW,EAAE,CAMxB;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,UAAU,EAAE,UAAU,EACtB,GAAG,EAAE,MAAM,EACX,KAAK,GAAE,SAAS,QAAQ,EAAkB,GACzC,SAAS,UAAU,EAAE,CAavB"}
@@ -1,6 +1,8 @@
1
1
  import { scoreReadings } from "./confidence.js";
2
2
  import { buildLattice, cutPoints } from "./lattice.js";
3
3
  import { isSettled, projectReadings, settledUnits, unitsOf, } from "./locking.js";
4
+ import { READING_RULES } from "./reading-rules.js";
5
+ import { applyEdgeRules } from "./rules.js";
4
6
  import { readingCost, shortestPath, spacingCost } from "./viterbi.js";
5
7
  /**
6
8
  * Decode the run's readings, scoring only where the readings are still open.
@@ -84,6 +86,17 @@ function wordFrom(dictionary, lattice, group) {
84
86
  isKnown: entry !== undefined,
85
87
  };
86
88
  }
89
+ /**
90
+ * The lattice a run decodes over: stage 1 built, then stage 4 applied.
91
+ *
92
+ * The rules run between building and decoding rather than over the output,
93
+ * which is the whole point of them — they change what the decode gets to choose
94
+ * between, so everything downstream sees one lattice rather than a decode and
95
+ * a list of corrections to it.
96
+ */
97
+ function ruledLattice(dictionary, run, rules) {
98
+ return applyEdgeRules(buildLattice(dictionary, run), dictionary, rules);
99
+ }
87
100
  /**
88
101
  * Decode a Han run with the lattice: the recommended path.
89
102
  *
@@ -91,8 +104,8 @@ function wordFrom(dictionary, lattice, group) {
91
104
  * lock the positions that cannot vary, score the rest — where the greedy
92
105
  * baseline commits to the longest match at each position and never revisits it.
93
106
  */
94
- export function decodeRun(dictionary, run) {
95
- const lattice = buildLattice(dictionary, run);
107
+ export function decodeRun(dictionary, run, rules = READING_RULES) {
108
+ const lattice = ruledLattice(dictionary, run, rules);
96
109
  const units = decodeReadings(lattice, projectReadings(lattice));
97
110
  return groupUnits(units, decodeSpacing(lattice)).map((group) => wordFrom(dictionary, lattice, group));
98
111
  }
@@ -104,8 +117,8 @@ export function decodeRun(dictionary, run) {
104
117
  * only worth running for a caller that will use the answer — rendering
105
118
  * uncertain readings differently, or reporting them.
106
119
  */
107
- export function decodeRunScored(dictionary, run) {
108
- const lattice = buildLattice(dictionary, run);
120
+ export function decodeRunScored(dictionary, run, rules = READING_RULES) {
121
+ const lattice = ruledLattice(dictionary, run, rules);
109
122
  const units = scoreReadings(lattice, projectReadings(lattice));
110
123
  return groupUnits(units, decodeSpacing(lattice)).map((group) => ({
111
124
  word: wordFrom(dictionary, lattice, group),