@kensio/pinyinjs 1.7.4 → 1.7.6
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/README.md +128 -123
- package/data/full.entries +2595 -2595
- package/data/manifest.json +5 -5
- package/data/script.map +66 -3
- package/dist/accuracy/score-case.d.ts +23 -0
- package/dist/accuracy/score-case.d.ts.map +1 -0
- package/dist/accuracy/score-case.js +63 -0
- package/dist/accuracy/score-case.js.map +1 -0
- package/dist/accuracy/score.d.ts +1 -8
- package/dist/accuracy/score.d.ts.map +1 -1
- package/dist/accuracy/score.js +1 -55
- package/dist/accuracy/score.js.map +1 -1
- package/dist/cli/arguments.d.ts +4 -290
- package/dist/cli/arguments.d.ts.map +1 -1
- package/dist/cli/arguments.js +5 -357
- package/dist/cli/arguments.js.map +1 -1
- package/dist/cli/check-command.d.ts +9 -0
- package/dist/cli/check-command.d.ts.map +1 -0
- package/dist/cli/check-command.js +95 -0
- package/dist/cli/check-command.js.map +1 -0
- package/dist/cli/cli-input.d.ts +49 -0
- package/dist/cli/cli-input.d.ts.map +1 -0
- package/dist/cli/cli-input.js +31 -0
- package/dist/cli/cli-input.js.map +1 -0
- package/dist/cli/command.d.ts +97 -0
- package/dist/cli/command.d.ts.map +1 -0
- package/dist/cli/command.js +40 -0
- package/dist/cli/command.js.map +1 -0
- package/dist/cli/commands.d.ts +7 -110
- package/dist/cli/commands.d.ts.map +1 -1
- package/dist/cli/commands.js +14 -991
- package/dist/cli/commands.js.map +1 -1
- package/dist/cli/convert-command.d.ts +6 -0
- package/dist/cli/convert-command.d.ts.map +1 -0
- package/dist/cli/convert-command.js +52 -0
- package/dist/cli/convert-command.js.map +1 -0
- package/dist/cli/environment.d.ts +1 -1
- package/dist/cli/environment.d.ts.map +1 -1
- package/dist/cli/explain-command.d.ts +6 -0
- package/dist/cli/explain-command.d.ts.map +1 -0
- package/dist/cli/explain-command.js +40 -0
- package/dist/cli/explain-command.js.map +1 -0
- package/dist/cli/explain-syllable.d.ts +10 -0
- package/dist/cli/explain-syllable.d.ts.map +1 -0
- package/dist/cli/explain-syllable.js +70 -0
- package/dist/cli/explain-syllable.js.map +1 -0
- package/dist/cli/flag-help.d.ts +18 -0
- package/dist/cli/flag-help.d.ts.map +1 -0
- package/dist/cli/flag-help.js +78 -0
- package/dist/cli/flag-help.js.map +1 -0
- package/dist/cli/flag-lists.d.ts +49 -0
- package/dist/cli/flag-lists.d.ts.map +1 -0
- package/dist/cli/flag-lists.js +58 -0
- package/dist/cli/flag-lists.js.map +1 -0
- package/dist/cli/flag-values.d.ts +44 -0
- package/dist/cli/flag-values.d.ts.map +1 -0
- package/dist/cli/flag-values.js +56 -0
- package/dist/cli/flag-values.js.map +1 -0
- package/dist/cli/flags.d.ts +193 -0
- package/dist/cli/flags.d.ts.map +1 -0
- package/dist/cli/flags.js +133 -0
- package/dist/cli/flags.js.map +1 -0
- package/dist/cli/format-options.d.ts +29 -0
- package/dist/cli/format-options.d.ts.map +1 -0
- package/dist/cli/format-options.js +72 -0
- package/dist/cli/format-options.js.map +1 -0
- package/dist/cli/global-help.d.ts +23 -0
- package/dist/cli/global-help.d.ts.map +1 -0
- package/dist/cli/global-help.js +40 -0
- package/dist/cli/global-help.js.map +1 -0
- package/dist/cli/help.d.ts +1 -1
- package/dist/cli/help.d.ts.map +1 -1
- package/dist/cli/help.js +5 -99
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/html-commands.d.ts +13 -0
- package/dist/cli/html-commands.d.ts.map +1 -0
- package/dist/cli/html-commands.js +49 -0
- package/dist/cli/html-commands.js.map +1 -0
- package/dist/cli/info-command.d.ts +7 -0
- package/dist/cli/info-command.d.ts.map +1 -0
- package/dist/cli/info-command.js +39 -0
- package/dist/cli/info-command.js.map +1 -0
- package/dist/cli/lookup-commands.d.ts +10 -0
- package/dist/cli/lookup-commands.d.ts.map +1 -0
- package/dist/cli/lookup-commands.js +101 -0
- package/dist/cli/lookup-commands.js.map +1 -0
- package/dist/cli/match-command.d.ts +11 -0
- package/dist/cli/match-command.d.ts.map +1 -0
- package/dist/cli/match-command.js +76 -0
- package/dist/cli/match-command.js.map +1 -0
- package/dist/cli/number-command.d.ts +12 -0
- package/dist/cli/number-command.d.ts.map +1 -0
- package/dist/cli/number-command.js +89 -0
- package/dist/cli/number-command.js.map +1 -0
- package/dist/cli/options.d.ts +30 -0
- package/dist/cli/options.d.ts.map +1 -0
- package/dist/cli/options.js +54 -0
- package/dist/cli/options.js.map +1 -0
- package/dist/cli/run-command.d.ts +24 -0
- package/dist/cli/run-command.d.ts.map +1 -0
- package/dist/cli/run-command.js +40 -0
- package/dist/cli/run-command.js.map +1 -0
- package/dist/cli/run.d.ts +4 -42
- package/dist/cli/run.d.ts.map +1 -1
- package/dist/cli/run.js +6 -61
- package/dist/cli/run.js.map +1 -1
- package/dist/cli/script-command.d.ts +10 -0
- package/dist/cli/script-command.d.ts.map +1 -0
- package/dist/cli/script-command.js +58 -0
- package/dist/cli/script-command.js.map +1 -0
- package/dist/cli/segment-command.d.ts +11 -0
- package/dist/cli/segment-command.d.ts.map +1 -0
- package/dist/cli/segment-command.js +53 -0
- package/dist/cli/segment-command.js.map +1 -0
- package/dist/cli/slug-command.d.ts +10 -0
- package/dist/cli/slug-command.d.ts.map +1 -0
- package/dist/cli/slug-command.js +28 -0
- package/dist/cli/slug-command.js.map +1 -0
- package/dist/cli/syllable-command.d.ts +14 -0
- package/dist/cli/syllable-command.d.ts.map +1 -0
- package/dist/cli/syllable-command.js +82 -0
- package/dist/cli/syllable-command.js.map +1 -0
- package/dist/cli/system-table.d.ts +12 -0
- package/dist/cli/system-table.d.ts.map +1 -0
- package/dist/cli/system-table.js +48 -0
- package/dist/cli/system-table.js.map +1 -0
- package/dist/cli/systems.d.ts +57 -0
- package/dist/cli/systems.d.ts.map +1 -0
- package/dist/cli/systems.js +27 -0
- package/dist/cli/systems.js.map +1 -0
- package/dist/cli/transcribe-command.d.ts +18 -0
- package/dist/cli/transcribe-command.d.ts.map +1 -0
- package/dist/cli/transcribe-command.js +86 -0
- package/dist/cli/transcribe-command.js.map +1 -0
- package/dist/cli/transcribe-reading.d.ts +15 -0
- package/dist/cli/transcribe-reading.d.ts.map +1 -0
- package/dist/cli/transcribe-reading.js +90 -0
- package/dist/cli/transcribe-reading.js.map +1 -0
- package/dist/cli/transcribe-rows.d.ts +26 -0
- package/dist/cli/transcribe-rows.d.ts.map +1 -0
- package/dist/cli/transcribe-rows.js +30 -0
- package/dist/cli/transcribe-rows.js.map +1 -0
- package/dist/cli/usage-error.d.ts +9 -0
- package/dist/cli/usage-error.d.ts.map +1 -0
- package/dist/cli/usage-error.js +9 -0
- package/dist/cli/usage-error.js.map +1 -0
- package/dist/decode/alternatives.d.ts +16 -0
- package/dist/decode/alternatives.d.ts.map +1 -0
- package/dist/decode/alternatives.js +31 -0
- package/dist/decode/alternatives.js.map +1 -0
- package/dist/decode/chang-context.d.ts +27 -0
- package/dist/decode/chang-context.d.ts.map +1 -0
- package/dist/decode/chang-context.js +66 -0
- package/dist/decode/chang-context.js.map +1 -0
- package/dist/decode/chang-rule.d.ts +37 -0
- package/dist/decode/chang-rule.d.ts.map +1 -0
- package/dist/decode/chang-rule.js +169 -0
- package/dist/decode/chang-rule.js.map +1 -0
- package/dist/decode/confidence.d.ts +11 -3
- package/dist/decode/confidence.d.ts.map +1 -1
- package/dist/decode/confidence.js +14 -121
- package/dist/decode/confidence.js.map +1 -1
- package/dist/decode/convert-options.d.ts +116 -0
- package/dist/decode/convert-options.d.ts.map +1 -0
- package/dist/decode/convert-options.js +2 -0
- package/dist/decode/convert-options.js.map +1 -0
- package/dist/decode/convert-pipeline.d.ts +18 -0
- package/dist/decode/convert-pipeline.d.ts.map +1 -0
- package/dist/decode/convert-pipeline.js +67 -0
- package/dist/decode/convert-pipeline.js.map +1 -0
- package/dist/decode/convert.d.ts +9 -118
- package/dist/decode/convert.d.ts.map +1 -1
- package/dist/decode/convert.js +5 -453
- package/dist/decode/convert.js.map +1 -1
- package/dist/decode/de-rule.d.ts +54 -0
- package/dist/decode/de-rule.d.ts.map +1 -0
- package/dist/decode/de-rule.js +113 -0
- package/dist/decode/de-rule.js.map +1 -0
- package/dist/decode/decode.d.ts +2 -15
- package/dist/decode/decode.d.ts.map +1 -1
- package/dist/decode/decode.js +2 -121
- package/dist/decode/decode.js.map +1 -1
- package/dist/decode/decoders.d.ts +32 -0
- package/dist/decode/decoders.d.ts.map +1 -0
- package/dist/decode/decoders.js +29 -0
- package/dist/decode/decoders.js.map +1 -0
- package/dist/decode/edge-context.d.ts +38 -0
- package/dist/decode/edge-context.d.ts.map +1 -0
- package/dist/decode/edge-context.js +57 -0
- package/dist/decode/edge-context.js.map +1 -0
- package/dist/decode/hint-lattice.d.ts +45 -0
- package/dist/decode/hint-lattice.d.ts.map +1 -0
- package/dist/decode/hint-lattice.js +154 -0
- package/dist/decode/hint-lattice.js.map +1 -0
- package/dist/decode/hints.d.ts +2 -45
- package/dist/decode/hints.d.ts.map +1 -1
- package/dist/decode/hints.js +1 -139
- package/dist/decode/hints.js.map +1 -1
- package/dist/decode/jiao-rule.d.ts +64 -0
- package/dist/decode/jiao-rule.d.ts.map +1 -0
- package/dist/decode/jiao-rule.js +115 -0
- package/dist/decode/jiao-rule.js.map +1 -0
- package/dist/decode/lattice-costs.d.ts +55 -0
- package/dist/decode/lattice-costs.d.ts.map +1 -0
- package/dist/decode/lattice-costs.js +90 -0
- package/dist/decode/lattice-costs.js.map +1 -0
- package/dist/decode/lattice-edges.d.ts +29 -0
- package/dist/decode/lattice-edges.d.ts.map +1 -0
- package/dist/decode/lattice-edges.js +78 -0
- package/dist/decode/lattice-edges.js.map +1 -0
- package/dist/decode/lattice-slice.d.ts +37 -0
- package/dist/decode/lattice-slice.d.ts.map +1 -0
- package/dist/decode/lattice-slice.js +43 -0
- package/dist/decode/lattice-slice.js.map +1 -0
- package/dist/decode/lattice-types.d.ts +101 -0
- package/dist/decode/lattice-types.d.ts.map +1 -0
- package/dist/decode/lattice-types.js +63 -0
- package/dist/decode/lattice-types.js.map +1 -0
- package/dist/decode/lattice.d.ts +2 -59
- package/dist/decode/lattice.d.ts.map +1 -1
- package/dist/decode/lattice.js +2 -118
- package/dist/decode/lattice.js.map +1 -1
- package/dist/decode/number-pieces.d.ts +62 -0
- package/dist/decode/number-pieces.d.ts.map +1 -0
- package/dist/decode/number-pieces.js +106 -0
- package/dist/decode/number-pieces.js.map +1 -0
- package/dist/decode/numbers.d.ts +53 -0
- package/dist/decode/numbers.d.ts.map +1 -0
- package/dist/decode/numbers.js +69 -0
- package/dist/decode/numbers.js.map +1 -0
- package/dist/decode/pieces.d.ts +78 -0
- package/dist/decode/pieces.d.ts.map +1 -0
- package/dist/decode/pieces.js +136 -0
- package/dist/decode/pieces.js.map +1 -0
- package/dist/decode/polyphone-rules.d.ts +11 -0
- package/dist/decode/polyphone-rules.d.ts.map +1 -0
- package/dist/decode/polyphone-rules.js +11 -0
- package/dist/decode/polyphone-rules.js.map +1 -0
- package/dist/decode/reading-rules.d.ts +3 -126
- package/dist/decode/reading-rules.d.ts.map +1 -1
- package/dist/decode/reading-rules.js +8 -434
- package/dist/decode/reading-rules.js.map +1 -1
- package/dist/decode/rules.d.ts +1 -17
- package/dist/decode/rules.d.ts.map +1 -1
- package/dist/decode/rules.js +1 -43
- package/dist/decode/rules.js.map +1 -1
- package/dist/decode/run-lattice.d.ts +52 -0
- package/dist/decode/run-lattice.d.ts.map +1 -0
- package/dist/decode/run-lattice.js +91 -0
- package/dist/decode/run-lattice.js.map +1 -0
- package/dist/decode/run-words.d.ts +17 -0
- package/dist/decode/run-words.d.ts.map +1 -0
- package/dist/decode/run-words.js +29 -0
- package/dist/decode/run-words.js.map +1 -0
- package/dist/decode/sandhi-input.d.ts +30 -0
- package/dist/decode/sandhi-input.d.ts.map +1 -0
- package/dist/decode/sandhi-input.js +35 -0
- package/dist/decode/sandhi-input.js.map +1 -0
- package/dist/decode/sandhi-tones.d.ts +97 -0
- package/dist/decode/sandhi-tones.d.ts.map +1 -0
- package/dist/decode/sandhi-tones.js +139 -0
- package/dist/decode/sandhi-tones.js.map +1 -0
- package/dist/decode/sandhi.d.ts +10 -7
- package/dist/decode/sandhi.d.ts.map +1 -1
- package/dist/decode/sandhi.js +11 -88
- package/dist/decode/sandhi.js.map +1 -1
- package/dist/decode/script-types.d.ts +76 -0
- package/dist/decode/script-types.d.ts.map +1 -0
- package/dist/decode/script-types.js +35 -0
- package/dist/decode/script-types.js.map +1 -0
- package/dist/decode/script-words.d.ts +32 -0
- package/dist/decode/script-words.d.ts.map +1 -0
- package/dist/decode/script-words.js +77 -0
- package/dist/decode/script-words.js.map +1 -0
- package/dist/decode/script.d.ts +3 -73
- package/dist/decode/script.d.ts.map +1 -1
- package/dist/decode/script.js +3 -109
- package/dist/decode/script.js.map +1 -1
- package/dist/decode/tan-rule.d.ts +68 -0
- package/dist/decode/tan-rule.d.ts.map +1 -0
- package/dist/decode/tan-rule.js +131 -0
- package/dist/decode/tan-rule.js.map +1 -0
- package/dist/decode/write-run.d.ts +21 -0
- package/dist/decode/write-run.d.ts.map +1 -0
- package/dist/decode/write-run.js +42 -0
- package/dist/decode/write-run.js.map +1 -0
- package/dist/dictionary/artifact-claims.d.ts +25 -0
- package/dist/dictionary/artifact-claims.d.ts.map +1 -0
- package/dist/dictionary/artifact-claims.js +47 -0
- package/dist/dictionary/artifact-claims.js.map +1 -0
- package/dist/dictionary/artifact-format.d.ts +86 -0
- package/dist/dictionary/artifact-format.d.ts.map +1 -0
- package/dist/dictionary/artifact-format.js +91 -0
- package/dist/dictionary/artifact-format.js.map +1 -0
- package/dist/dictionary/artifact-read.d.ts +34 -0
- package/dist/dictionary/artifact-read.d.ts.map +1 -0
- package/dist/dictionary/artifact-read.js +114 -0
- package/dist/dictionary/artifact-read.js.map +1 -0
- package/dist/dictionary/artifact.d.ts +4 -63
- package/dist/dictionary/artifact.d.ts.map +1 -1
- package/dist/dictionary/artifact.js +12 -229
- package/dist/dictionary/artifact.js.map +1 -1
- package/dist/dictionary/assertions.d.ts +5 -57
- package/dist/dictionary/assertions.d.ts.map +1 -1
- package/dist/dictionary/assertions.js +4 -317
- package/dist/dictionary/assertions.js.map +1 -1
- package/dist/dictionary/build-assertions.d.ts +12 -0
- package/dist/dictionary/build-assertions.d.ts.map +1 -0
- package/dist/dictionary/build-assertions.js +13 -0
- package/dist/dictionary/build-assertions.js.map +1 -0
- package/dist/dictionary/built-dictionary.d.ts +46 -0
- package/dist/dictionary/built-dictionary.d.ts.map +1 -0
- package/dist/dictionary/built-dictionary.js +97 -0
- package/dist/dictionary/built-dictionary.js.map +1 -0
- package/dist/dictionary/cedict-senses.d.ts +87 -0
- package/dist/dictionary/cedict-senses.d.ts.map +1 -0
- package/dist/dictionary/cedict-senses.js +126 -0
- package/dist/dictionary/cedict-senses.js.map +1 -0
- package/dist/dictionary/character-defaults.d.ts +26 -0
- package/dist/dictionary/character-defaults.d.ts.map +1 -0
- package/dist/dictionary/character-defaults.js +67 -0
- package/dist/dictionary/character-defaults.js.map +1 -0
- package/dist/dictionary/character-readings.d.ts +10 -0
- package/dist/dictionary/character-readings.d.ts.map +1 -0
- package/dist/dictionary/character-readings.js +25 -0
- package/dist/dictionary/character-readings.js.map +1 -0
- package/dist/dictionary/constituent-repair.d.ts +36 -0
- package/dist/dictionary/constituent-repair.d.ts.map +1 -0
- package/dist/dictionary/constituent-repair.js +117 -0
- package/dist/dictionary/constituent-repair.js.map +1 -0
- package/dist/dictionary/dictionary-entry.d.ts +37 -0
- package/dist/dictionary/dictionary-entry.d.ts.map +1 -0
- package/dist/dictionary/dictionary-entry.js +41 -0
- package/dist/dictionary/dictionary-entry.js.map +1 -0
- package/dist/dictionary/dictionary-readings.d.ts +56 -0
- package/dist/dictionary/dictionary-readings.d.ts.map +1 -0
- package/dist/dictionary/dictionary-readings.js +93 -0
- package/dist/dictionary/dictionary-readings.js.map +1 -0
- package/dist/dictionary/dictionary.d.ts +6 -60
- package/dist/dictionary/dictionary.d.ts.map +1 -1
- package/dist/dictionary/dictionary.js +9 -169
- package/dist/dictionary/dictionary.js.map +1 -1
- package/dist/dictionary/entry-invariants.d.ts +3 -0
- package/dist/dictionary/entry-invariants.d.ts.map +1 -0
- package/dist/dictionary/entry-invariants.js +67 -0
- package/dist/dictionary/entry-invariants.js.map +1 -0
- package/dist/dictionary/entry-lines.d.ts +35 -0
- package/dist/dictionary/entry-lines.d.ts.map +1 -0
- package/dist/dictionary/entry-lines.js +70 -0
- package/dist/dictionary/entry-lines.js.map +1 -0
- package/dist/dictionary/erhua-repair.d.ts +26 -0
- package/dist/dictionary/erhua-repair.d.ts.map +1 -0
- package/dist/dictionary/erhua-repair.js +49 -0
- package/dist/dictionary/erhua-repair.js.map +1 -0
- package/dist/dictionary/frequency-tones.d.ts +74 -0
- package/dist/dictionary/frequency-tones.d.ts.map +1 -0
- package/dist/dictionary/frequency-tones.js +128 -0
- package/dist/dictionary/frequency-tones.js.map +1 -0
- package/dist/dictionary/inventory-invariants.d.ts +3 -0
- package/dist/dictionary/inventory-invariants.d.ts.map +1 -0
- package/dist/dictionary/inventory-invariants.js +54 -0
- package/dist/dictionary/inventory-invariants.js.map +1 -0
- package/dist/dictionary/locale-candidates.d.ts +40 -0
- package/dist/dictionary/locale-candidates.d.ts.map +1 -0
- package/dist/dictionary/locale-candidates.js +77 -0
- package/dist/dictionary/locale-candidates.js.map +1 -0
- package/dist/dictionary/locale-segments.d.ts +47 -0
- package/dist/dictionary/locale-segments.d.ts.map +1 -0
- package/dist/dictionary/locale-segments.js +141 -0
- package/dist/dictionary/locale-segments.js.map +1 -0
- package/dist/dictionary/locale.d.ts +1 -21
- package/dist/dictionary/locale.d.ts.map +1 -1
- package/dist/dictionary/locale.js +9 -198
- package/dist/dictionary/locale.js.map +1 -1
- package/dist/dictionary/merge-types.d.ts +127 -0
- package/dist/dictionary/merge-types.d.ts.map +1 -0
- package/dist/dictionary/merge-types.js +35 -0
- package/dist/dictionary/merge-types.js.map +1 -0
- package/dist/dictionary/merge-walk.d.ts +27 -0
- package/dist/dictionary/merge-walk.d.ts.map +1 -0
- package/dist/dictionary/merge-walk.js +49 -0
- package/dist/dictionary/merge-walk.js.map +1 -0
- package/dist/dictionary/merge-word.d.ts +7 -0
- package/dist/dictionary/merge-word.d.ts.map +1 -0
- package/dist/dictionary/merge-word.js +91 -0
- package/dist/dictionary/merge-word.js.map +1 -0
- package/dist/dictionary/merge.d.ts +5 -62
- package/dist/dictionary/merge.d.ts.map +1 -1
- package/dist/dictionary/merge.js +32 -725
- package/dist/dictionary/merge.js.map +1 -1
- package/dist/dictionary/proper-noun.d.ts +28 -0
- package/dist/dictionary/proper-noun.d.ts.map +1 -0
- package/dist/dictionary/proper-noun.js +43 -0
- package/dist/dictionary/proper-noun.js.map +1 -0
- package/dist/dictionary/reading-agreement.d.ts +71 -0
- package/dist/dictionary/reading-agreement.d.ts.map +1 -0
- package/dist/dictionary/reading-agreement.js +156 -0
- package/dist/dictionary/reading-agreement.js.map +1 -0
- package/dist/dictionary/script-conversion.d.ts +28 -0
- package/dist/dictionary/script-conversion.d.ts.map +1 -0
- package/dist/dictionary/script-conversion.js +58 -0
- package/dist/dictionary/script-conversion.js.map +1 -0
- package/dist/dictionary/script-pairings.d.ts +74 -0
- package/dist/dictionary/script-pairings.d.ts.map +1 -0
- package/dist/dictionary/script-pairings.js +120 -0
- package/dist/dictionary/script-pairings.js.map +1 -0
- package/dist/dictionary/script-tables.d.ts.map +1 -1
- package/dist/dictionary/script-tables.js +2 -165
- package/dist/dictionary/script-tables.js.map +1 -1
- package/dist/dictionary/taiwan-reading.d.ts +8 -0
- package/dist/dictionary/taiwan-reading.d.ts.map +1 -0
- package/dist/dictionary/taiwan-reading.js +38 -0
- package/dist/dictionary/taiwan-reading.js.map +1 -0
- package/dist/dictionary/tone-invariants.d.ts +3 -0
- package/dist/dictionary/tone-invariants.d.ts.map +1 -0
- package/dist/dictionary/tone-invariants.js +64 -0
- package/dist/dictionary/tone-invariants.js.map +1 -0
- package/dist/dictionary/traditional-form.d.ts +21 -0
- package/dist/dictionary/traditional-form.d.ts.map +1 -0
- package/dist/dictionary/traditional-form.js +59 -0
- package/dist/dictionary/traditional-form.js.map +1 -0
- package/dist/dictionary/traditional-ranking.d.ts +22 -0
- package/dist/dictionary/traditional-ranking.d.ts.map +1 -0
- package/dist/dictionary/traditional-ranking.js +74 -0
- package/dist/dictionary/traditional-ranking.js.map +1 -0
- package/dist/dictionary/traditional-table.d.ts +51 -0
- package/dist/dictionary/traditional-table.d.ts.map +1 -0
- package/dist/dictionary/traditional-table.js +98 -0
- package/dist/dictionary/traditional-table.js.map +1 -0
- package/dist/dictionary/traditional.d.ts +3 -56
- package/dist/dictionary/traditional.d.ts.map +1 -1
- package/dist/dictionary/traditional.js +3 -186
- package/dist/dictionary/traditional.js.map +1 -1
- package/dist/dictionary/variant-counts.d.ts +39 -0
- package/dist/dictionary/variant-counts.d.ts.map +1 -0
- package/dist/dictionary/variant-counts.js +38 -0
- package/dist/dictionary/variant-counts.js.map +1 -0
- package/dist/dictionary/word-reading.d.ts +26 -0
- package/dist/dictionary/word-reading.d.ts.map +1 -0
- package/dist/dictionary/word-reading.js +76 -0
- package/dist/dictionary/word-reading.js.map +1 -0
- package/dist/dictionary/word-readings.d.ts +15 -0
- package/dist/dictionary/word-readings.d.ts.map +1 -0
- package/dist/dictionary/word-readings.js +41 -0
- package/dist/dictionary/word-readings.js.map +1 -0
- package/dist/format/annotate.d.ts +90 -0
- package/dist/format/annotate.d.ts.map +1 -0
- package/dist/format/annotate.js +168 -0
- package/dist/format/annotate.js.map +1 -0
- package/dist/format/html.d.ts +15 -46
- package/dist/format/html.d.ts.map +1 -1
- package/dist/format/html.js +3 -162
- package/dist/format/html.js.map +1 -1
- package/dist/format/slug-hash.d.ts +51 -0
- package/dist/format/slug-hash.d.ts.map +1 -0
- package/dist/format/slug-hash.js +74 -0
- package/dist/format/slug-hash.js.map +1 -0
- package/dist/format/slug-options.d.ts +98 -0
- package/dist/format/slug-options.d.ts.map +1 -0
- package/dist/format/slug-options.js +2 -0
- package/dist/format/slug-options.js.map +1 -0
- package/dist/format/slug-words.d.ts +27 -0
- package/dist/format/slug-words.d.ts.map +1 -0
- package/dist/format/slug-words.js +0 -0
- package/dist/format/slug-words.js.map +1 -0
- package/dist/format/slug.d.ts +3 -128
- package/dist/format/slug.d.ts.map +1 -1
- package/dist/format/slug.js +0 -0
- package/dist/format/slug.js.map +1 -1
- package/dist/grade/check-readings.d.ts +41 -0
- package/dist/grade/check-readings.d.ts.map +1 -0
- package/dist/grade/check-readings.js +36 -0
- package/dist/grade/check-readings.js.map +1 -0
- package/dist/grade/check.d.ts +4 -4
- package/dist/grade/check.d.ts.map +1 -1
- package/dist/grade/check.js +5 -270
- package/dist/grade/check.js.map +1 -1
- package/dist/grade/pair-syllables.d.ts +48 -0
- package/dist/grade/pair-syllables.d.ts.map +1 -0
- package/dist/grade/pair-syllables.js +71 -0
- package/dist/grade/pair-syllables.js.map +1 -0
- package/dist/grade/reading-syllables.d.ts +62 -0
- package/dist/grade/reading-syllables.d.ts.map +1 -0
- package/dist/grade/reading-syllables.js +58 -0
- package/dist/grade/reading-syllables.js.map +1 -0
- package/dist/grade/reading-tolerance.d.ts +72 -0
- package/dist/grade/reading-tolerance.d.ts.map +1 -0
- package/dist/grade/reading-tolerance.js +107 -0
- package/dist/grade/reading-tolerance.js.map +1 -0
- package/dist/grade/typed-reading.d.ts +28 -0
- package/dist/grade/typed-reading.d.ts.map +1 -0
- package/dist/grade/typed-reading.js +36 -0
- package/dist/grade/typed-reading.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/numerals/numeral-parse.d.ts +32 -0
- package/dist/numerals/numeral-parse.d.ts.map +1 -0
- package/dist/numerals/numeral-parse.js +44 -0
- package/dist/numerals/numeral-parse.js.map +1 -0
- package/dist/numerals/numeral-shapes.d.ts +89 -0
- package/dist/numerals/numeral-shapes.d.ts.map +1 -0
- package/dist/numerals/numeral-shapes.js +99 -0
- package/dist/numerals/numeral-shapes.js.map +1 -0
- package/dist/numerals/numerals.d.ts.map +1 -1
- package/dist/numerals/numerals.js +2 -36
- package/dist/numerals/numerals.js.map +1 -1
- package/dist/numerals/read-numeral.d.ts +76 -0
- package/dist/numerals/read-numeral.d.ts.map +1 -0
- package/dist/numerals/read-numeral.js +88 -0
- package/dist/numerals/read-numeral.js.map +1 -0
- package/dist/numerals/text.d.ts +3 -37
- package/dist/numerals/text.d.ts.map +1 -1
- package/dist/numerals/text.js +3 -254
- package/dist/numerals/text.js.map +1 -1
- package/dist/numerals/time.d.ts +34 -0
- package/dist/numerals/time.d.ts.map +1 -0
- package/dist/numerals/time.js +93 -0
- package/dist/numerals/time.js.map +1 -0
- package/dist/orthography/address-grouping.d.ts +34 -0
- package/dist/orthography/address-grouping.d.ts.map +1 -0
- package/dist/orthography/address-grouping.js +52 -0
- package/dist/orthography/address-grouping.js.map +1 -0
- package/dist/orthography/grouping.d.ts +3 -87
- package/dist/orthography/grouping.d.ts.map +1 -1
- package/dist/orthography/grouping.js +4 -270
- package/dist/orthography/grouping.js.map +1 -1
- package/dist/orthography/place-grouping.d.ts +39 -0
- package/dist/orthography/place-grouping.d.ts.map +1 -0
- package/dist/orthography/place-grouping.js +83 -0
- package/dist/orthography/place-grouping.js.map +1 -0
- package/dist/orthography/word-grouping.d.ts +48 -0
- package/dist/orthography/word-grouping.d.ts.map +1 -0
- package/dist/orthography/word-grouping.js +147 -0
- package/dist/orthography/word-grouping.js.map +1 -0
- package/dist/script/conversion-format.d.ts +22 -0
- package/dist/script/conversion-format.d.ts.map +1 -0
- package/dist/script/conversion-format.js +22 -0
- package/dist/script/conversion-format.js.map +1 -0
- package/dist/script/conversion-read.d.ts +9 -0
- package/dist/script/conversion-read.d.ts.map +1 -0
- package/dist/script/conversion-read.js +69 -0
- package/dist/script/conversion-read.js.map +1 -0
- package/dist/script/conversion-write.d.ts +14 -0
- package/dist/script/conversion-write.d.ts.map +1 -0
- package/dist/script/conversion-write.js +34 -0
- package/dist/script/conversion-write.js.map +1 -0
- package/dist/script/conversion.d.ts +10 -16
- package/dist/script/conversion.d.ts.map +1 -1
- package/dist/script/conversion.js +2 -115
- package/dist/script/conversion.js.map +1 -1
- package/dist/search/candidate-narrowing.d.ts +56 -0
- package/dist/search/candidate-narrowing.d.ts.map +1 -0
- package/dist/search/candidate-narrowing.js +55 -0
- package/dist/search/candidate-narrowing.js.map +1 -0
- package/dist/search/candidate-query.d.ts +25 -0
- package/dist/search/candidate-query.d.ts.map +1 -0
- package/dist/search/candidate-query.js +28 -0
- package/dist/search/candidate-query.js.map +1 -0
- package/dist/search/candidate-writings.d.ts +24 -0
- package/dist/search/candidate-writings.d.ts.map +1 -0
- package/dist/search/candidate-writings.js +114 -0
- package/dist/search/candidate-writings.js.map +1 -0
- package/dist/search/candidates.d.ts +7 -41
- package/dist/search/candidates.d.ts.map +1 -1
- package/dist/search/candidates.js +10 -164
- package/dist/search/candidates.js.map +1 -1
- package/dist/search/match-chunks.d.ts +19 -0
- package/dist/search/match-chunks.d.ts.map +1 -0
- package/dist/search/match-chunks.js +30 -0
- package/dist/search/match-chunks.js.map +1 -0
- package/dist/search/match-ranking.d.ts +39 -0
- package/dist/search/match-ranking.d.ts.map +1 -0
- package/dist/search/match-ranking.js +51 -0
- package/dist/search/match-ranking.js.map +1 -0
- package/dist/search/match-readings.d.ts +43 -0
- package/dist/search/match-readings.d.ts.map +1 -0
- package/dist/search/match-readings.js +83 -0
- package/dist/search/match-readings.js.map +1 -0
- package/dist/search/match-scoring.d.ts +146 -0
- package/dist/search/match-scoring.d.ts.map +1 -0
- package/dist/search/match-scoring.js +114 -0
- package/dist/search/match-scoring.js.map +1 -0
- package/dist/search/match-search.d.ts +28 -0
- package/dist/search/match-search.d.ts.map +1 -0
- package/dist/search/match-search.js +128 -0
- package/dist/search/match-search.js.map +1 -0
- package/dist/search/match.d.ts +5 -36
- package/dist/search/match.d.ts.map +1 -1
- package/dist/search/match.js +2 -379
- package/dist/search/match.js.map +1 -1
- package/dist/search/reverse-index-build.d.ts +30 -0
- package/dist/search/reverse-index-build.d.ts.map +1 -0
- package/dist/search/reverse-index-build.js +72 -0
- package/dist/search/reverse-index-build.js.map +1 -0
- package/dist/search/reverse-index-format.d.ts +60 -0
- package/dist/search/reverse-index-format.d.ts.map +1 -0
- package/dist/search/reverse-index-format.js +54 -0
- package/dist/search/reverse-index-format.js.map +1 -0
- package/dist/search/reverse-index-groups.d.ts +37 -0
- package/dist/search/reverse-index-groups.d.ts.map +1 -0
- package/dist/search/reverse-index-groups.js +71 -0
- package/dist/search/reverse-index-groups.js.map +1 -0
- package/dist/search/reverse-index-passes.d.ts +78 -0
- package/dist/search/reverse-index-passes.d.ts.map +1 -0
- package/dist/search/reverse-index-passes.js +59 -0
- package/dist/search/reverse-index-passes.js.map +1 -0
- package/dist/search/reverse-index-state.d.ts +36 -0
- package/dist/search/reverse-index-state.d.ts.map +1 -0
- package/dist/search/reverse-index-state.js +95 -0
- package/dist/search/reverse-index-state.js.map +1 -0
- package/dist/search/reverse-index.d.ts +8 -67
- package/dist/search/reverse-index.d.ts.map +1 -1
- package/dist/search/reverse-index.js +4 -255
- package/dist/search/reverse-index.js.map +1 -1
- package/dist/sources/unihan-readings.d.ts +58 -0
- package/dist/sources/unihan-readings.d.ts.map +1 -0
- package/dist/sources/unihan-readings.js +95 -0
- package/dist/sources/unihan-readings.js.map +1 -0
- package/dist/sources/unihan.d.ts +6 -9
- package/dist/sources/unihan.d.ts.map +1 -1
- package/dist/sources/unihan.js +2 -85
- package/dist/sources/unihan.js.map +1 -1
- package/dist/syllable/final-tables.d.ts +23 -0
- package/dist/syllable/final-tables.d.ts.map +1 -0
- package/dist/syllable/final-tables.js +50 -0
- package/dist/syllable/final-tables.js.map +1 -0
- package/dist/syllable/inventory.d.ts +8 -42
- package/dist/syllable/inventory.d.ts.map +1 -1
- package/dist/syllable/inventory.js +9 -918
- package/dist/syllable/inventory.js.map +1 -1
- package/dist/syllable/spellings.d.ts +40 -0
- package/dist/syllable/spellings.d.ts.map +1 -0
- package/dist/syllable/spellings.js +469 -0
- package/dist/syllable/spellings.js.map +1 -0
- package/dist/syllable/syllable-parts.d.ts +31 -0
- package/dist/syllable/syllable-parts.d.ts.map +1 -0
- package/dist/syllable/syllable-parts.js +105 -0
- package/dist/syllable/syllable-parts.js.map +1 -0
- package/dist/syllable/syllable.d.ts +1 -14
- package/dist/syllable/syllable.d.ts.map +1 -1
- package/dist/syllable/syllable.js +3 -144
- package/dist/syllable/syllable.js.map +1 -1
- package/dist/syllable/written-tones.d.ts +6 -0
- package/dist/syllable/written-tones.d.ts.map +1 -0
- package/dist/syllable/written-tones.js +453 -0
- package/dist/syllable/written-tones.js.map +1 -0
- package/dist/transcription/bopomofo-parse.d.ts +42 -0
- package/dist/transcription/bopomofo-parse.d.ts.map +1 -0
- package/dist/transcription/bopomofo-parse.js +92 -0
- package/dist/transcription/bopomofo-parse.js.map +1 -0
- package/dist/transcription/bopomofo-reverse.d.ts +31 -0
- package/dist/transcription/bopomofo-reverse.d.ts.map +1 -0
- package/dist/transcription/bopomofo-reverse.js +48 -0
- package/dist/transcription/bopomofo-reverse.js.map +1 -0
- package/dist/transcription/bopomofo-symbols.d.ts +36 -0
- package/dist/transcription/bopomofo-symbols.d.ts.map +1 -0
- package/dist/transcription/bopomofo-symbols.js +41 -0
- package/dist/transcription/bopomofo-symbols.js.map +1 -0
- package/dist/transcription/bopomofo-tables.d.ts +87 -0
- package/dist/transcription/bopomofo-tables.d.ts.map +1 -0
- package/dist/transcription/bopomofo-tables.js +180 -0
- package/dist/transcription/bopomofo-tables.js.map +1 -0
- package/dist/transcription/bopomofo.d.ts +14 -32
- package/dist/transcription/bopomofo.d.ts.map +1 -1
- package/dist/transcription/bopomofo.js +5 -343
- package/dist/transcription/bopomofo.js.map +1 -1
- package/dist/transcription/gwoyeu-first-second.d.ts +36 -0
- package/dist/transcription/gwoyeu-first-second.d.ts.map +1 -0
- package/dist/transcription/gwoyeu-first-second.js +75 -0
- package/dist/transcription/gwoyeu-first-second.js.map +1 -0
- package/dist/transcription/gwoyeu-spelling.d.ts +38 -0
- package/dist/transcription/gwoyeu-spelling.d.ts.map +1 -0
- package/dist/transcription/gwoyeu-spelling.js +124 -0
- package/dist/transcription/gwoyeu-spelling.js.map +1 -0
- package/dist/transcription/gwoyeu-tables.d.ts +93 -0
- package/dist/transcription/gwoyeu-tables.d.ts.map +1 -0
- package/dist/transcription/gwoyeu-tables.js +205 -0
- package/dist/transcription/gwoyeu-tables.js.map +1 -0
- package/dist/transcription/gwoyeu-tonal-forms.d.ts +49 -0
- package/dist/transcription/gwoyeu-tonal-forms.d.ts.map +1 -0
- package/dist/transcription/gwoyeu-tonal-forms.js +89 -0
- package/dist/transcription/gwoyeu-tonal-forms.js.map +1 -0
- package/dist/transcription/gwoyeu-vowels.d.ts +51 -0
- package/dist/transcription/gwoyeu-vowels.d.ts.map +1 -0
- package/dist/transcription/gwoyeu-vowels.js +58 -0
- package/dist/transcription/gwoyeu-vowels.js.map +1 -0
- package/dist/transcription/gwoyeu.d.ts +1 -26
- package/dist/transcription/gwoyeu.d.ts.map +1 -1
- package/dist/transcription/gwoyeu.js +2 -540
- package/dist/transcription/gwoyeu.js.map +1 -1
- package/dist/transcription/ipa-symbols.d.ts +67 -0
- package/dist/transcription/ipa-symbols.d.ts.map +1 -0
- package/dist/transcription/ipa-symbols.js +135 -0
- package/dist/transcription/ipa-symbols.js.map +1 -0
- package/dist/transcription/ipa.d.ts +2 -10
- package/dist/transcription/ipa.d.ts.map +1 -1
- package/dist/transcription/ipa.js +2 -134
- package/dist/transcription/ipa.js.map +1 -1
- package/dist/transcription/wade-giles-index.d.ts +35 -0
- package/dist/transcription/wade-giles-index.d.ts.map +1 -0
- package/dist/transcription/wade-giles-index.js +110 -0
- package/dist/transcription/wade-giles-index.js.map +1 -0
- package/dist/transcription/wade-giles-parse.d.ts +36 -0
- package/dist/transcription/wade-giles-parse.d.ts.map +1 -0
- package/dist/transcription/wade-giles-parse.js +84 -0
- package/dist/transcription/wade-giles-parse.js.map +1 -0
- package/dist/transcription/wade-giles-spelling.d.ts +61 -0
- package/dist/transcription/wade-giles-spelling.d.ts.map +1 -0
- package/dist/transcription/wade-giles-spelling.js +107 -0
- package/dist/transcription/wade-giles-spelling.js.map +1 -0
- package/dist/transcription/wade-giles-syllable.d.ts +29 -0
- package/dist/transcription/wade-giles-syllable.d.ts.map +1 -0
- package/dist/transcription/wade-giles-syllable.js +90 -0
- package/dist/transcription/wade-giles-syllable.js.map +1 -0
- package/dist/transcription/wade-giles-tables.d.ts +80 -0
- package/dist/transcription/wade-giles-tables.d.ts.map +1 -0
- package/dist/transcription/wade-giles-tables.js +178 -0
- package/dist/transcription/wade-giles-tables.js.map +1 -0
- package/dist/transcription/wade-giles.d.ts +9 -60
- package/dist/transcription/wade-giles.d.ts.map +1 -1
- package/dist/transcription/wade-giles.js +6 -543
- package/dist/transcription/wade-giles.js.map +1 -1
- package/dist/transcription/yale-tables.d.ts +54 -0
- package/dist/transcription/yale-tables.d.ts.map +1 -0
- package/dist/transcription/yale-tables.js +125 -0
- package/dist/transcription/yale-tables.js.map +1 -0
- package/dist/transcription/yale.d.ts.map +1 -1
- package/dist/transcription/yale.js +1 -124
- package/dist/transcription/yale.js.map +1 -1
- package/package.json +2 -2
package/dist/dictionary/merge.js
CHANGED
|
@@ -1,754 +1,61 @@
|
|
|
1
|
-
import { characterCount, isSingleCharacter } from "../script/characters.js";
|
|
2
|
-
import { toCanonicalGlyphs } from "../script/glyphs.js";
|
|
3
|
-
import { nameBoundariesOf } from "../sources/cedict.js";
|
|
4
|
-
import { isProperNounTag } from "../sources/jieba.js";
|
|
5
|
-
import { FREQUENCY_FIELD, } from "../sources/unihan.js";
|
|
6
|
-
import { NEUTRAL_TONE } from "../tone/tone.js";
|
|
7
|
-
import { countCorpusMass, rankByCorpusMass } from "./corpus-mass.js";
|
|
8
|
-
import { isSameReading } from "./entry.js";
|
|
9
|
-
import { attachErhua, isErFinal, NON_ERHUA_ER_WORDS } from "./erhua.js";
|
|
10
|
-
import { composeLocaleDeltas } from "./locale.js";
|
|
11
|
-
import { NEUTRAL_SENSE_LOOKUP } from "./neutral-senses.js";
|
|
12
|
-
import { OVERRIDE_READINGS } from "./overrides.js";
|
|
13
|
-
import { ERHUA_TOKEN, readAlignedReading, readDictionaryReading, } from "./reading.js";
|
|
14
|
-
import { pairScripts, TraditionalTable, } from "./traditional.js";
|
|
15
|
-
/**
|
|
16
|
-
* Order two strings by UTF-16 code unit, matching the key index's ordering.
|
|
17
|
-
*/
|
|
18
|
-
function byCodeUnit(left, right) {
|
|
19
|
-
if (left < right) {
|
|
20
|
-
return -1;
|
|
21
|
-
}
|
|
22
|
-
return left > right ? 1 : 0;
|
|
23
|
-
}
|
|
24
|
-
/**
|
|
25
|
-
* Whether a phrase-corpus headword is really the 繁體 spelling of another word.
|
|
26
|
-
*
|
|
27
|
-
* `large_pinyin.txt` is a 简体 corpus, and where it carries a 繁體 headword
|
|
28
|
-
* anyway it has read it as though the characters were 简体: 特徵 is `tè zhǐ`
|
|
29
|
-
* there because 徵 alone is `zhǐ`, 沈溺 is `shěn nì` because 沈 alone is the
|
|
30
|
-
* surname, 蝨子 is `shī zǐ`, 纔然 is `shān rán`. Every one of those is a word
|
|
31
|
-
* whose 简体 form the corpus also carries, correctly.
|
|
32
|
-
*
|
|
33
|
-
* Left in, each becomes an entry of its own that outranks the 繁體 key the
|
|
34
|
-
* derivation would have hung on the 简体 entry, so the word reads one way in a
|
|
35
|
-
* tier holding the phrase tail and another way in a tier without it.
|
|
36
|
-
*
|
|
37
|
-
* So the corpus is held to its own contract: a headword CC-CEDICT knows only as
|
|
38
|
-
* the 繁體 spelling of a different 简体 word contributes no entry, and the word
|
|
39
|
-
* keeps the reading CC-CEDICT pairs it with. It is 72 headwords, 13 of which
|
|
40
|
-
* the corpus reads wrongly; the other 59 arrive at the same reading either way.
|
|
41
|
-
*
|
|
42
|
-
* Narrow on purpose. 2,854 corpus headwords contain a 繁體-only character and
|
|
43
|
-
* only these 72 are ones CC-CEDICT pairs — the rest are rare or mixed-script
|
|
44
|
-
* words whose characters do read them, and dropping those would lose coverage
|
|
45
|
-
* to fix nothing.
|
|
46
|
-
*/
|
|
47
|
-
function isSpeltTraditionally(word, byWord, byHant) {
|
|
48
|
-
if (byWord.has(word)) {
|
|
49
|
-
return false;
|
|
50
|
-
}
|
|
51
|
-
return (byHant.get(word) ?? []).some((entry) => entry.simplified !== entry.traditional);
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* CC-CEDICT's entries for a word, keyed by one of its two written forms.
|
|
55
|
-
*/
|
|
56
|
-
function indexCedict(cedict, formOf) {
|
|
57
|
-
const byWord = new Map();
|
|
58
|
-
for (const entry of cedict) {
|
|
59
|
-
const form = formOf(entry);
|
|
60
|
-
const existing = byWord.get(form);
|
|
61
|
-
if (existing === undefined) {
|
|
62
|
-
byWord.set(form, [entry]);
|
|
63
|
-
}
|
|
64
|
-
else {
|
|
65
|
-
existing.push(entry);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
return byWord;
|
|
69
|
-
}
|
|
70
|
-
/**
|
|
71
|
-
* How far apart two readings of the same length are.
|
|
72
|
-
*
|
|
73
|
-
* Used to pick which of CC-CEDICT's senses to compare against, since a word
|
|
74
|
-
* with several senses has several readings and only the nearest one is talking
|
|
75
|
-
* about the same pronunciation.
|
|
76
|
-
*
|
|
77
|
-
* A difference in spelling counts for more than a difference in tone, and the
|
|
78
|
-
* distinction decides real cases. 行长 is `xíng zhǎng` in one CC-CEDICT sense
|
|
79
|
-
* and `háng zhang` in another; against the phrase corpus's `háng zhǎng` the two
|
|
80
|
-
* differ in one syllable each, but only the second is the same word — the first
|
|
81
|
-
* has a different initial, so it is a different word that happens to be
|
|
82
|
-
* written the same way.
|
|
83
|
-
*/
|
|
84
|
-
function readingGap(left, right) {
|
|
85
|
-
if (left.length !== right.length) {
|
|
86
|
-
return Infinity;
|
|
87
|
-
}
|
|
88
|
-
let spelling = 0;
|
|
89
|
-
let tones = 0;
|
|
90
|
-
for (const [at, syllable] of left.entries()) {
|
|
91
|
-
/* c8 ignore next -- the lengths match, so the fallback is unreachable */
|
|
92
|
-
const other = right[at] ?? syllable;
|
|
93
|
-
if (syllable.initial !== other.initial || syllable.final !== other.final) {
|
|
94
|
-
spelling++;
|
|
95
|
-
}
|
|
96
|
-
else if (syllable.tone !== other.tone) {
|
|
97
|
-
tones++;
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
// Scaled so that any number of tone differences still beats one spelling
|
|
101
|
-
// difference.
|
|
102
|
-
return spelling * (left.length + 1) + tones;
|
|
103
|
-
}
|
|
104
|
-
/**
|
|
105
|
-
* Take CC-CEDICT's neutral tones where it and the phrase corpus disagree.
|
|
106
|
-
*
|
|
107
|
-
* The disagreements between the two are almost entirely about 轻声, and
|
|
108
|
-
* CC-CEDICT is the more careful source there: it has 头发 as `tou2 fa5` and
|
|
109
|
-
* 还是 as `hai2 shi5` where the phrase corpus writes full tones on both. Only
|
|
110
|
-
* the tone is taken, and only when it is neutral — a disagreement about the
|
|
111
|
-
* syllable itself is left to the phrase corpus, which has three times the
|
|
112
|
-
* coverage and is the primary source.
|
|
113
|
-
*
|
|
114
|
-
* The two readings must be the same length, which the caller establishes by
|
|
115
|
-
* only passing a sense {@link readingGap} scored as finite.
|
|
116
|
-
*/
|
|
117
|
-
function preferNeutralTones(phrase, cedict) {
|
|
118
|
-
return phrase.map((syllable, at) => {
|
|
119
|
-
/* c8 ignore next -- the caller only passes a sense of the same length */
|
|
120
|
-
const other = cedict[at] ?? syllable;
|
|
121
|
-
const isSameSound = syllable.initial === other.initial && syllable.final === other.final;
|
|
122
|
-
return isSameSound &&
|
|
123
|
-
other.tone === NEUTRAL_TONE &&
|
|
124
|
-
syllable.tone !== NEUTRAL_TONE
|
|
125
|
-
? { ...syllable, tone: NEUTRAL_TONE }
|
|
126
|
-
: syllable;
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
/**
|
|
130
|
-
* Whether a word's trailing 儿 is an r suffix rather than a syllable.
|
|
131
|
-
*
|
|
132
|
-
* CC-CEDICT decides wherever it has the word, because its `r5` token is an
|
|
133
|
-
* explicit and reliable marker. Only where it is silent does the checked-in
|
|
134
|
-
* exception list get a say, and there the default is 儿化 — a trailing 儿 is
|
|
135
|
-
* far more often a diminutive suffix than the word 儿 itself.
|
|
136
|
-
*/
|
|
137
|
-
function isErhua(word, cedictReadings) {
|
|
138
|
-
if (!isErFinal(word)) {
|
|
139
|
-
return false;
|
|
140
|
-
}
|
|
141
|
-
if (cedictReadings.length > 0) {
|
|
142
|
-
return cedictReadings.some((reading) => reading.at(-1)?.erhua === true);
|
|
143
|
-
}
|
|
144
|
-
return !NON_ERHUA_ER_WORDS.has(word);
|
|
145
|
-
}
|
|
146
|
-
/**
|
|
147
|
-
* Whether a candidate reads a syllable 轻声 that the chosen reading tones.
|
|
148
|
-
*
|
|
149
|
-
* What separates a sense that is the same word said more carefully from one
|
|
150
|
-
* that is a different word: 东西's `dong1 xi5` reduces the `dōng xī` the corpus
|
|
151
|
-
* wrote, while its `dong1 xi1` is that same reading and 行长's `háng zhang` has
|
|
152
|
-
* a different initial. Length is checked because a reading of another length
|
|
153
|
-
* describes another pronunciation entirely.
|
|
154
|
-
*/
|
|
155
|
-
function reducesToNeutral(reading, candidate) {
|
|
156
|
-
if (reading.length !== candidate.length) {
|
|
157
|
-
return false;
|
|
158
|
-
}
|
|
159
|
-
return reading.some((syllable, at) => {
|
|
160
|
-
const other = candidate[at];
|
|
161
|
-
return (other !== undefined &&
|
|
162
|
-
syllable.initial === other.initial &&
|
|
163
|
-
syllable.final === other.final &&
|
|
164
|
-
syllable.tone !== NEUTRAL_TONE &&
|
|
165
|
-
other.tone === NEUTRAL_TONE);
|
|
166
|
-
});
|
|
167
|
-
}
|
|
168
|
-
/**
|
|
169
|
-
* The candidate reading nearest the chosen one, or undefined if none compares.
|
|
170
|
-
*
|
|
171
|
-
* Undefined covers both having no candidates at all and having only candidates
|
|
172
|
-
* of a different length, which describe a different pronunciation rather than a
|
|
173
|
-
* more careful transcription of this one.
|
|
174
|
-
*/
|
|
175
|
-
function nearestReading(reading, candidates) {
|
|
176
|
-
let nearest;
|
|
177
|
-
let smallest = Infinity;
|
|
178
|
-
for (const candidate of candidates) {
|
|
179
|
-
const gap = readingGap(reading, candidate);
|
|
180
|
-
if (gap < smallest) {
|
|
181
|
-
nearest = candidate;
|
|
182
|
-
smallest = gap;
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
return nearest;
|
|
186
|
-
}
|
|
187
|
-
/**
|
|
188
|
-
* The CC-CEDICT senses describing the pronunciation chosen for a word.
|
|
189
|
-
*
|
|
190
|
-
* A word with several pronunciations has several CC-CEDICT entries, and they
|
|
191
|
-
* can disagree about more than the reading: 万 is written 萬 when read `wàn` and
|
|
192
|
-
* 万 when read `mò`. Everything taken from CC-CEDICT for an entry — its 繁體
|
|
193
|
-
* form, its Taiwan reading — has to come from a sense that matches the reading,
|
|
194
|
-
* or the entry ends up describing two different words at once.
|
|
195
|
-
*
|
|
196
|
-
* Every sense equally near the reading is returned, most useful first, because
|
|
197
|
-
* senses can agree about the pronunciation and still differ about the script:
|
|
198
|
-
* 重复 is `chóng fù` whether it is written 重複 or 重覆, and both spellings are
|
|
199
|
-
* this word. The first is the entry's 繁體 form and the rest are its
|
|
200
|
-
* {@link DictionaryEntry.hantVariants}.
|
|
201
|
-
*
|
|
202
|
-
* Where nothing compares — no sense has a readable reading of the same length —
|
|
203
|
-
* only the first is returned. A tie between senses that could not be measured
|
|
204
|
-
* is not evidence that they are the same word.
|
|
205
|
-
*/
|
|
206
|
-
function sensesForReading(word, entries, reading) {
|
|
207
|
-
const measured = entries.map((entry) => {
|
|
208
|
-
const candidate = readDictionaryReading(word, entry.readings);
|
|
209
|
-
return {
|
|
210
|
-
entry,
|
|
211
|
-
gap: candidate === undefined ? Infinity : readingGap(reading, candidate),
|
|
212
|
-
};
|
|
213
|
-
});
|
|
214
|
-
const nearest = Math.min(...measured.map(({ gap }) => gap));
|
|
215
|
-
if (measured.length === 0 || nearest === Infinity) {
|
|
216
|
-
return entries.slice(0, 1);
|
|
217
|
-
}
|
|
218
|
-
return measured
|
|
219
|
-
.filter(({ gap }) => gap === nearest)
|
|
220
|
-
.map(({ entry }) => entry);
|
|
221
|
-
}
|
|
222
|
-
/**
|
|
223
|
-
* A word's readings as CC-CEDICT gives them, one per sense.
|
|
224
|
-
*/
|
|
225
|
-
function cedictReadingsOf(word, entries) {
|
|
226
|
-
return entries
|
|
227
|
-
.map((entry) => readDictionaryReading(word, entry.readings))
|
|
228
|
-
.filter((reading) => reading !== undefined);
|
|
229
|
-
}
|
|
230
|
-
/**
|
|
231
|
-
* Whether a proposed 國語 reading is really another 普通话 sense of the word.
|
|
232
|
-
*
|
|
233
|
-
* The test that separates a locale shift from a sense selection, which the
|
|
234
|
-
* sources write the same way and mean differently. 地 is offered `dì` against a
|
|
235
|
-
* 普通话 `de` — but CC-CEDICT lists 地[de5] and 地[di4] as two entries, so `dì`
|
|
236
|
-
* is what 地 reads in 普通话 when it means the ground, not what 國語 does to the
|
|
237
|
-
* particle. The adverbial 地 is `de` in Taipei too, and 4,240 entries end in it.
|
|
238
|
-
* 都 is the same shape, and so are 着, 应, 差, 称, 斗, 舍, 薄 and 万.
|
|
239
|
-
*
|
|
240
|
-
* A genuine delta leaves no such trace: nothing in 普通话 reads 和 as `hàn`, 期
|
|
241
|
-
* as `qí` or 垃 as `lè`, which is why those survive this and 71 characters and
|
|
242
|
-
* 3 words do not.
|
|
243
|
-
*
|
|
244
|
-
* Only CC-CEDICT is consulted. Unihan's reading fields carry rare and historical
|
|
245
|
-
* pronunciations alongside current ones — 驯 is listed `xún` somewhere in them —
|
|
246
|
-
* and a reading no one uses today is not evidence that a source meant a sense
|
|
247
|
-
* rather than a locale.
|
|
248
|
-
*/
|
|
249
|
-
function isOwnSense(taiwan, senseReadings) {
|
|
250
|
-
return senseReadings.some((sense) => isSameReading(sense, taiwan));
|
|
251
|
-
}
|
|
252
|
-
/**
|
|
253
|
-
* Whether a character's `Taiwan pr.` note describes one sense rather than the
|
|
254
|
-
* character.
|
|
255
|
-
*
|
|
256
|
-
* The other half of the sense test, and the one {@link isOwnSense} cannot do.
|
|
257
|
-
* That test asks whether the offered reading is a 普通话 sense of the word; this
|
|
258
|
-
* asks whether the note was ever about the whole word to begin with. 從's
|
|
259
|
-
* `Taiwan pr. [zong4]` sits on three of its eight senses — 侍從, 從兄弟, 從犯 —
|
|
260
|
-
* and 教育部's dictionary agrees with CC-CEDICT about which: 跟隨, 依順, 參與 and
|
|
261
|
-
* the preposition are `cóng` in Taipei exactly as they are in Beijing. Applying
|
|
262
|
-
* it to the headword made 我从北京来 read `wǒ zòng Běijīng lái`. 會 (`huǐ`, only
|
|
263
|
-
* 一會兒), 勞 (`lào`, only 慰勞) and 燥 (`sào`, only 肉燥) are the same shape.
|
|
264
|
-
*
|
|
265
|
-
* A note the entry leads with is kept, because the leading sense is what the
|
|
266
|
-
* character means with nothing to narrow it: 和's `hàn` is on the conjunction,
|
|
267
|
-
* which is what a bare 和 almost always is.
|
|
268
|
-
*
|
|
269
|
-
* **Only a character is tested this way.** Its entry is what every occurrence
|
|
270
|
-
* no longer word covers falls back to, so it has to carry the reading that
|
|
271
|
-
* survives out of context; a multi-character headword is reached only where
|
|
272
|
-
* that exact word is written. Four of them carry an inline note — 相親, 載具,
|
|
273
|
-
* 高挑 and 樂色 — and only 相親 has senses that differ, its dominant one being
|
|
274
|
-
* the matchmaking sense that really is `xiàngqīn`.
|
|
275
|
-
*/
|
|
276
|
-
function isSenseScopedNote(word, sense) {
|
|
277
|
-
return sense?.taiwanScope === "sense" && isSingleCharacter(word);
|
|
278
|
-
}
|
|
279
|
-
/**
|
|
280
|
-
* Strip the tone marks from a reading, for comparing two spellings.
|
|
281
|
-
*/
|
|
282
|
-
function tonelessReading(reading) {
|
|
283
|
-
return reading
|
|
284
|
-
.normalize("NFD")
|
|
285
|
-
.replaceAll(/[̀́̄̌]/gu, "")
|
|
286
|
-
.normalize("NFC");
|
|
287
|
-
}
|
|
288
1
|
/**
|
|
289
|
-
*
|
|
290
|
-
*/
|
|
291
|
-
function isToneMarked(reading) {
|
|
292
|
-
return tonelessReading(reading) !== reading;
|
|
293
|
-
}
|
|
294
|
-
/**
|
|
295
|
-
* Put back a tone that `kHanyuPinlu` left off.
|
|
2
|
+
* The order the merge does its work in.
|
|
296
3
|
*
|
|
297
|
-
*
|
|
298
|
-
*
|
|
299
|
-
*
|
|
300
|
-
* `Li Huá`, and it is the only Unihan field this happens in.
|
|
301
|
-
*
|
|
302
|
-
* The other fields settle which it is. If they also write the spelling bare,
|
|
303
|
-
* the neutral tone is real and 么, 们, 吧, 裳 keep it. If every one of them
|
|
304
|
-
* writes it with a tone, the frequency field simply omitted the mark, and the
|
|
305
|
-
* tone is taken back. Measured over the real file, 3,799 characters have a
|
|
306
|
-
* `kHanyuPinlu` entry, 60 of those have only unmarked readings, and the split
|
|
307
|
-
* is 45 that should carry a tone against 15 genuine 轻声.
|
|
4
|
+
* Which spellings get an entry and how each one is settled is `merge-walk.ts`.
|
|
5
|
+
* What is here is the sequence: the indexes and character defaults everything
|
|
6
|
+
* else reads, the walk, and the two passes that run over the finished entries.
|
|
308
7
|
*/
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
frequencyReadings.some((reading) => isToneMarked(reading))) {
|
|
315
|
-
return unihan.readings;
|
|
316
|
-
}
|
|
317
|
-
const elsewhere = [...unihan.fields]
|
|
318
|
-
.filter(([field]) => field !== FREQUENCY_FIELD)
|
|
319
|
-
.flatMap(([, readings]) => readings);
|
|
320
|
-
return unihan.readings.map((reading) => {
|
|
321
|
-
if (isToneMarked(reading)) {
|
|
322
|
-
return reading;
|
|
323
|
-
}
|
|
324
|
-
const sameSpelling = elsewhere.filter((other) => tonelessReading(other) === reading);
|
|
325
|
-
if (sameSpelling.length === 0 || sameSpelling.includes(reading)) {
|
|
326
|
-
return reading;
|
|
327
|
-
}
|
|
328
|
-
return sameSpelling.find((other) => isToneMarked(other)) ?? reading;
|
|
329
|
-
});
|
|
330
|
-
}
|
|
331
|
-
/**
|
|
332
|
-
* A CC-CEDICT sense that describes a suffix rather than a word.
|
|
333
|
-
*
|
|
334
|
-
* Matches its own wording: 子 is `/noun suffix, as in 椅子[yi3 zi5] "chair"/`,
|
|
335
|
-
* and the other suffix senses are written the same way.
|
|
336
|
-
*/
|
|
337
|
-
const SUFFIX_SENSE = /\bsuffix\b/iu;
|
|
338
|
-
/**
|
|
339
|
-
* Whether CC-CEDICT reads the bare character 轻声 in its own right.
|
|
340
|
-
*
|
|
341
|
-
* The exception to {@link demoteReducedNeutrals}, and the thing that separates
|
|
342
|
-
* a 语气词 from a syllable that is only ever unstressed inside a word. A
|
|
343
|
-
* single-character CC-CEDICT headword with a neutral reading is a claim about
|
|
344
|
-
* the character standing alone, which is exactly what the frequency field's
|
|
345
|
-
* counting cannot distinguish: 吗 is `(question particle for "yes-no"
|
|
346
|
-
* questions)`, 啊 is `modal particle ending sentence`, 得 is `structural
|
|
347
|
-
* particle: used after a verb`. Nine characters carry one — 得, 啊, 吗, 呀, 啦,
|
|
348
|
-
* 哇, 嘛, 罢 and 子 — and their 繁體 spellings with them.
|
|
349
|
-
*
|
|
350
|
-
* **A suffix sense is not such a claim.** 子's neutral headword is `noun
|
|
351
|
-
* suffix, as in 椅子`, which says the character is unstressed *in words*, and
|
|
352
|
-
* words are what the corpus can already see. 子 is `zǐ` on its own — 子曰, 母子
|
|
353
|
-
* — and CPP's human labelling has it `zi3` in 30 of its 38 cases.
|
|
354
|
-
*
|
|
355
|
-
* 罢 is the known loss. CC-CEDICT calls its `ba5` a final particle, so it is
|
|
356
|
-
* held here, and CPP labels the character `ba4` in all 40 of its cases: the
|
|
357
|
-
* particle is the literary 也罢 and 罢了, while a modern bare 罢 is 罢工. Left
|
|
358
|
-
* protected because the rule is about what a source claims of the character,
|
|
359
|
-
* and singling one out because a dataset disagrees is fitting to the dataset.
|
|
360
|
-
*/
|
|
361
|
-
function isNeutralAlone(character, entries) {
|
|
362
|
-
return entries.some((entry) => {
|
|
363
|
-
const reading = readDictionaryReading(character, entry.readings);
|
|
364
|
-
return (reading?.length === 1 &&
|
|
365
|
-
reading[0]?.tone === NEUTRAL_TONE &&
|
|
366
|
-
!entry.definitions.some((definition) => SUFFIX_SENSE.test(definition)));
|
|
367
|
-
});
|
|
368
|
-
}
|
|
369
|
-
/**
|
|
370
|
-
* Demote a 轻声 the frequency field counted only inside words.
|
|
371
|
-
*
|
|
372
|
-
* `kHanyuPinlu` counts occurrences in running text, and a character's neutral
|
|
373
|
-
* count there mixes two unrelated things: a character that stands alone
|
|
374
|
-
* unstressed, and one reduced *inside a word*. Where the field writes the same
|
|
375
|
-
* spelling both bare and toned it is reporting that split with no way to say
|
|
376
|
-
* which is which — 西 is `xi(902) xī(738)`, and the 902 are 东西 — and since the
|
|
377
|
-
* field leads {@link import("../sources/unihan.js").READING_FIELDS}, the
|
|
378
|
-
* reduction became the character's reading. 西 read `xi`, so 往西 was `wǎng xi`;
|
|
379
|
-
* 夫 read `fu`, 识 `shi`, 拾 `shi`, 候 `hou`, 姐 `jie`, 友 `you`.
|
|
380
|
-
*
|
|
381
|
-
* So a bare spelling the field also writes with a tone ranks below that twin —
|
|
382
|
-
* demoted rather than dropped, keeping it as a candidate without letting it set
|
|
383
|
-
* the default, exactly as a lone `kHanyuPinlu` reading is. It reaches 50
|
|
384
|
-
* characters, and {@link isNeutralAlone} holds back the ones a source says are
|
|
385
|
-
* neutral on their own.
|
|
386
|
-
*
|
|
387
|
-
* The other half of the same blind spot is already handled: where the field
|
|
388
|
-
* marks *no* tone at all it omitted the mark rather than meaning 轻声, which is
|
|
389
|
-
* {@link resolveFrequencyTones}.
|
|
390
|
-
*/
|
|
391
|
-
function demoteReducedNeutrals(unihan, readings) {
|
|
392
|
-
const frequency = unihan.fields.get(FREQUENCY_FIELD) ?? [];
|
|
393
|
-
const reduced = new Set(frequency.filter((reading) => !isToneMarked(reading) &&
|
|
394
|
-
frequency.some((other) => isToneMarked(other) && tonelessReading(other) === reading)));
|
|
395
|
-
if (reduced.size === 0) {
|
|
396
|
-
return readings;
|
|
397
|
-
}
|
|
398
|
-
return [
|
|
399
|
-
...readings.filter((reading) => !reduced.has(reading)),
|
|
400
|
-
...readings.filter((reading) => reduced.has(reading)),
|
|
401
|
-
];
|
|
402
|
-
}
|
|
403
|
-
/**
|
|
404
|
-
* Parse a Unihan reading string for one character.
|
|
405
|
-
*
|
|
406
|
-
* Goes through the dictionary reader so that a Unihan reading gets the same
|
|
407
|
-
* treatment as any other source's: an unmarked tone means neutral, and 一 and
|
|
408
|
-
* 不 are restored to their underlying tones.
|
|
409
|
-
*/
|
|
410
|
-
function characterSyllable(character, reading) {
|
|
411
|
-
return readDictionaryReading(character, [reading])?.[0];
|
|
412
|
-
}
|
|
8
|
+
import { composeLocaleDeltas } from "./locale.js";
|
|
9
|
+
import { indexCedict, senseLookup } from "./cedict-senses.js";
|
|
10
|
+
import { buildCharacterDefaults } from "./character-defaults.js";
|
|
11
|
+
import { repairConstituentReadings } from "./constituent-repair.js";
|
|
12
|
+
import { mergeWords, wordList } from "./merge-walk.js";
|
|
413
13
|
/**
|
|
414
14
|
* Build the merged dictionary from the four parsed sources.
|
|
415
15
|
*
|
|
416
16
|
* The order of operations is the one MERGE.md sets out, and it is not
|
|
417
17
|
* arbitrary — each step depends on the one before. Spelling, tones, sandhi and
|
|
418
|
-
* validation happen in {@link readAlignedReading} as each source is read;
|
|
419
|
-
*
|
|
420
|
-
*
|
|
18
|
+
* validation happen in {@link import("./reading.js").readAlignedReading} as each source is read;
|
|
19
|
+
* {@link mergeWords} then settles one word at a time, and the passes after it
|
|
20
|
+
* see every entry at once.
|
|
421
21
|
*/
|
|
422
22
|
export function mergeSources(sources) {
|
|
423
|
-
const {
|
|
23
|
+
const { phrase, cedict } = sources;
|
|
424
24
|
const cedictByWord = indexCedict(cedict, (entry) => entry.simplified);
|
|
425
25
|
// Only ever read for {@link isOwnSense}. A 繁體-only headword keeps its senses
|
|
426
26
|
// under whichever 简体 form each one simplifies to — 沈 is `chén` under 沉 and
|
|
427
27
|
// 誰 is `shéi` under 谁 — so the 简体 index alone cannot say what a character
|
|
428
28
|
// like that already reads in 普通话.
|
|
429
29
|
const cedictByHant = indexCedict(cedict, (entry) => entry.traditional);
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
//
|
|
442
|
-
//
|
|
443
|
-
//
|
|
444
|
-
|
|
445
|
-
const
|
|
446
|
-
let reducedNeutrals = 0;
|
|
447
|
-
for (const [character, readings] of unihanReadings) {
|
|
448
|
-
const resolved = resolveFrequencyTones(readings);
|
|
449
|
-
// A 轻声 the frequency field only ever counted inside words is not the
|
|
450
|
-
// character's reading — unless a source says the bare character is neutral.
|
|
451
|
-
const ranked = isNeutralAlone(character, [
|
|
452
|
-
...(cedictByWord.get(character) ?? []),
|
|
453
|
-
...(cedictByHant.get(character) ?? []),
|
|
454
|
-
])
|
|
455
|
-
? resolved
|
|
456
|
-
: demoteReducedNeutrals(readings, resolved);
|
|
457
|
-
if (ranked !== resolved && ranked[0] !== resolved[0]) {
|
|
458
|
-
reducedNeutrals++;
|
|
459
|
-
}
|
|
460
|
-
const parsed = ranked
|
|
461
|
-
.map((reading) => characterSyllable(character, reading))
|
|
462
|
-
.filter((syllable) => syllable !== undefined);
|
|
463
|
-
if (parsed.length > 0) {
|
|
464
|
-
defaults.set(character, rankByCorpusMass(character, parsed, readings.fields, mass));
|
|
465
|
-
}
|
|
466
|
-
}
|
|
467
|
-
const words = new Set([
|
|
468
|
-
...defaults.keys(),
|
|
469
|
-
...[...phrase.keys()].filter((word) => !isSpeltTraditionally(word, cedictByWord, cedictByHant)),
|
|
470
|
-
...cedictByWord.keys(),
|
|
471
|
-
]);
|
|
472
|
-
const entries = [];
|
|
473
|
-
const rejected = new Map();
|
|
474
|
-
let neutralToneCorrections = 0;
|
|
475
|
-
let erhuaRepairs = 0;
|
|
476
|
-
let derivedTraditional = 0;
|
|
477
|
-
let scriptPairs = 0;
|
|
478
|
-
let variantSpellings = 0;
|
|
479
|
-
let taiwanReadings = 0;
|
|
480
|
-
let properNounVetoes = 0;
|
|
481
|
-
let nameBoundaries = 0;
|
|
482
|
-
let phraseWords = 0;
|
|
483
|
-
let cedictWords = 0;
|
|
484
|
-
let characters = 0;
|
|
485
|
-
for (const word of [...words].toSorted(byCodeUnit)) {
|
|
486
|
-
const cedictEntries = cedictByWord.get(word) ?? [];
|
|
487
|
-
const cedictReadings = cedictReadingsOf(word, cedictEntries);
|
|
488
|
-
// Every reading CC-CEDICT gives this spelling, under either script.
|
|
489
|
-
const senseReadings = [
|
|
490
|
-
...cedictReadings,
|
|
491
|
-
...cedictReadingsOf(word, cedictByHant.get(word) ?? []),
|
|
492
|
-
];
|
|
493
|
-
const phraseReading = phrase.get(word);
|
|
494
|
-
const phraseAligned = phraseReading === undefined
|
|
495
|
-
? undefined
|
|
496
|
-
: readAlignedReading(word, phraseReading);
|
|
497
|
-
// ── The reading: phrase corpus leads, CC-CEDICT corrects ──
|
|
498
|
-
let aligned = phraseAligned;
|
|
499
|
-
let reading = aligned
|
|
500
|
-
?.map((read) => read.syllable)
|
|
501
|
-
.filter((syllable) => syllable !== undefined);
|
|
502
|
-
if (reading === undefined) {
|
|
503
|
-
// No phrase entry. Single characters fall back to Unihan, which is the
|
|
504
|
-
// better source for them anyway; everything else falls back to
|
|
505
|
-
// CC-CEDICT.
|
|
506
|
-
const characterDefault = defaults.get(word);
|
|
507
|
-
if (isSingleCharacter(word) && characterDefault !== undefined) {
|
|
508
|
-
reading = characterDefault.slice(0, 1);
|
|
509
|
-
aligned = [{ characters: word, syllable: reading[0] }];
|
|
510
|
-
}
|
|
511
|
-
else if (cedictReadings[0] !== undefined) {
|
|
512
|
-
reading = cedictReadings[0];
|
|
513
|
-
aligned = readAlignedReading(word, cedictEntries[0]?.readings ?? []);
|
|
514
|
-
}
|
|
515
|
-
}
|
|
516
|
-
if (reading === undefined || reading.length === 0) {
|
|
517
|
-
rejected.set(word, phraseReading ?? cedictEntries[0]?.readings ?? []);
|
|
518
|
-
continue;
|
|
519
|
-
}
|
|
520
|
-
// ── 儿化, before anything compares two readings ────────────
|
|
521
|
-
if (isErhua(word, cedictReadings)) {
|
|
522
|
-
const attached = attachErhua(reading);
|
|
523
|
-
if (attached !== reading) {
|
|
524
|
-
erhuaRepairs++;
|
|
525
|
-
reading = attached;
|
|
526
|
-
// Fold the alignment the same way, so the 繁體 derivation still knows
|
|
527
|
-
// which character each syllable reads.
|
|
528
|
-
const last = aligned?.at(-1);
|
|
529
|
-
const previous = aligned?.at(-2);
|
|
530
|
-
if (aligned !== undefined &&
|
|
531
|
-
last !== undefined &&
|
|
532
|
-
previous !== undefined) {
|
|
533
|
-
aligned = [
|
|
534
|
-
...aligned.slice(0, -2),
|
|
535
|
-
{
|
|
536
|
-
characters: previous.characters + last.characters,
|
|
537
|
-
syllable: attached.at(-1),
|
|
538
|
-
},
|
|
539
|
-
];
|
|
540
|
-
}
|
|
541
|
-
}
|
|
542
|
-
}
|
|
543
|
-
else if (reading.every((syllable) => syllable.erhua !== true)) {
|
|
544
|
-
// 儿化 in the middle of a word, which the trailing repair above cannot
|
|
545
|
-
// reach: 一点儿事 is `yìdiǎnr shì`, three syllables over four characters,
|
|
546
|
-
// and the phrase corpus writes four. Only CC-CEDICT's `r5` marks it, and
|
|
547
|
-
// only it knows where, so where it does the whole reading is taken from
|
|
548
|
-
// it — 53 of its 683 `r5` entries carry the marker mid-word.
|
|
549
|
-
const marked = cedictEntries.find((entry) => entry.readings.includes(ERHUA_TOKEN));
|
|
550
|
-
const markedAligned = marked === undefined
|
|
551
|
-
? undefined
|
|
552
|
-
: readAlignedReading(word, marked.readings);
|
|
553
|
-
if (markedAligned !== undefined) {
|
|
554
|
-
erhuaRepairs++;
|
|
555
|
-
aligned = markedAligned;
|
|
556
|
-
reading = markedAligned
|
|
557
|
-
.map((read) => read.syllable)
|
|
558
|
-
.filter((syllable) => syllable !== undefined);
|
|
559
|
-
}
|
|
560
|
-
}
|
|
561
|
-
// ── Disagreements: CC-CEDICT wins on neutral tones ────────
|
|
562
|
-
// Which sense to correct against is normally the nearest one. For a word on
|
|
563
|
-
// the 轻声 list it is the nearest sense that *reduces* a syllable, because
|
|
564
|
-
// there the nearest sense is the full-tone homograph the corpus happens to
|
|
565
|
-
// have written and the everyday word is the other one — see
|
|
566
|
-
// {@link NEUTRAL_SENSE_WORDS}.
|
|
567
|
-
const chosen = reading;
|
|
568
|
-
const nearest = phraseAligned === undefined
|
|
569
|
-
? undefined
|
|
570
|
-
: ((NEUTRAL_SENSE_LOOKUP.has(word)
|
|
571
|
-
? nearestReading(chosen, cedictReadings.filter((candidate) => reducesToNeutral(chosen, candidate)))
|
|
572
|
-
: undefined) ?? nearestReading(chosen, cedictReadings));
|
|
573
|
-
// A sense of a different length describes a different pronunciation, so
|
|
574
|
-
// there is no syllable-for-syllable correction to make against it.
|
|
575
|
-
if (nearest !== undefined) {
|
|
576
|
-
const corrected = preferNeutralTones(reading, nearest);
|
|
577
|
-
if (!isSameReading(corrected, reading)) {
|
|
578
|
-
neutralToneCorrections++;
|
|
579
|
-
reading = corrected;
|
|
580
|
-
}
|
|
581
|
-
}
|
|
582
|
-
// ── The override table has the last word ──────────────────
|
|
583
|
-
const override = OVERRIDE_READINGS.get(word);
|
|
584
|
-
if (override !== undefined) {
|
|
585
|
-
reading = override;
|
|
586
|
-
}
|
|
587
|
-
// ── 繁體: taken from CC-CEDICT, derived where it is silent ─
|
|
588
|
-
// Which sense matters: 万 is 萬 when read wàn but stays 万 when read mò, and
|
|
589
|
-
// CC-CEDICT carries both as separate entries. Taking whichever came first
|
|
590
|
-
// in the file would pair the chosen reading with another sense's script.
|
|
591
|
-
const senses = sensesForReading(word, cedictEntries, reading);
|
|
592
|
-
const sense = senses[0];
|
|
593
|
-
let hant;
|
|
594
|
-
if (sense === undefined) {
|
|
595
|
-
// Canonicalised because the derivation settles each word against Unihan's
|
|
596
|
-
// variant lists with no single standard behind it, so 里 derives as 裏
|
|
597
|
-
// where the corpus overwhelmingly writes 裡. Both are the same character
|
|
598
|
-
// with the same reading, and a key written in the form the lookup path
|
|
599
|
-
// normalises *away from* can never be found — see the note below.
|
|
600
|
-
hant = toCanonicalGlyphs(traditional.convert(aligned ?? []));
|
|
601
|
-
if (hant !== word) {
|
|
602
|
-
derivedTraditional++;
|
|
603
|
-
}
|
|
604
|
-
}
|
|
605
|
-
else {
|
|
606
|
-
hant = toCanonicalGlyphs(sense.traditional);
|
|
607
|
-
}
|
|
608
|
-
if (hant !== word) {
|
|
609
|
-
scriptPairs++;
|
|
610
|
-
}
|
|
611
|
-
// Other spellings of the same word, so that a 繁體 reader of either finds
|
|
612
|
-
// it. Only what a source writes out: composing spellings from per-character
|
|
613
|
-
// variants instead would add 229,482 keys to the full tier, almost all of
|
|
614
|
-
// them forms nobody writes — 方麵 for 方面, 公裡 for 公里 — because the
|
|
615
|
-
// reading that picks the right variant for one word does not generalise to
|
|
616
|
-
// every word the character appears in.
|
|
617
|
-
//
|
|
618
|
-
// Canonicalised for the same reason `hant` is, and deduplicated after:
|
|
619
|
-
// 裏面 and 裡面 are one spelling once the glyph forms are folded, and
|
|
620
|
-
// keying both would claim a variant that does not exist.
|
|
621
|
-
//
|
|
622
|
-
// The 简体 headword's own canonical spelling joins them where it differs,
|
|
623
|
-
// and that is not a nicety: the lookup path normalises 繁體 glyph forms
|
|
624
|
-
// before it searches, so a key written in a form it normalises *away from*
|
|
625
|
-
// can never be found. The phrase corpus carries a few hundred headwords
|
|
626
|
-
// spelled with 峯, 藴 or 枱 — 鹫峯寺, 义藴, 写字枱 — and without this they
|
|
627
|
-
// are entries nothing can reach.
|
|
628
|
-
const hantVariants = [
|
|
629
|
-
...new Set([
|
|
630
|
-
...senses.map((other) => toCanonicalGlyphs(other.traditional)),
|
|
631
|
-
toCanonicalGlyphs(word),
|
|
632
|
-
]),
|
|
633
|
-
].filter((form) => form !== hant && form !== word);
|
|
634
|
-
if (hantVariants.length > 0) {
|
|
635
|
-
variantSpellings++;
|
|
636
|
-
}
|
|
637
|
-
// ── zh-TW delta ───────────────────────────────────────────
|
|
638
|
-
// Only from a sense that reads the way this entry reads. CC-CEDICT hangs
|
|
639
|
-
// `Taiwan pr.` on one sense of a headword and the others know nothing about
|
|
640
|
-
// it: 著 is marked `zhuó` on the chess-move sense that reads `zhāo`, and
|
|
641
|
-
// reaching across for it gave the aspect particle 着 a 國語 reading of
|
|
642
|
-
// `zhuó`.
|
|
643
|
-
//
|
|
644
|
-
// A note can also sit on a sense of the *right* reading and still not be
|
|
645
|
-
// about the character — see `isSenseScopedNote`.
|
|
646
|
-
const taiwanSense = senses.find((entry) => entry.taiwanReadings !== undefined);
|
|
647
|
-
const taiwanTokens = isSenseScopedNote(word, taiwanSense)
|
|
648
|
-
? undefined
|
|
649
|
-
: taiwanSense?.taiwanReadings;
|
|
650
|
-
const unihanTaiwan = unihanReadings.get(word)?.taiwanReading;
|
|
651
|
-
let taiwan;
|
|
652
|
-
if (taiwanTokens !== undefined) {
|
|
653
|
-
taiwan = readDictionaryReading(word, taiwanTokens);
|
|
654
|
-
}
|
|
655
|
-
else if (isSingleCharacter(word) && unihanTaiwan !== undefined) {
|
|
656
|
-
const syllable = characterSyllable(word, unihanTaiwan);
|
|
657
|
-
taiwan = syllable === undefined ? undefined : [syllable];
|
|
658
|
-
}
|
|
659
|
-
if (taiwan !== undefined &&
|
|
660
|
-
(isSameReading(taiwan, reading) || isOwnSense(taiwan, senseReadings))) {
|
|
661
|
-
taiwan = undefined;
|
|
662
|
-
}
|
|
663
|
-
if (taiwan !== undefined) {
|
|
664
|
-
taiwanReadings++;
|
|
665
|
-
}
|
|
666
|
-
// ── Frequency, part of speech and the proper noun bit ─────
|
|
667
|
-
const jiebaEntry = jieba.get(word);
|
|
668
|
-
const partOfSpeech = jiebaEntry?.partOfSpeech ?? "";
|
|
669
|
-
// jieba's tags propose a proper noun and CC-CEDICT's capitalisation can
|
|
670
|
-
// veto it. The tags on their own are noisy enough to be worth correcting:
|
|
671
|
-
// 沙发, 城市, 阿姨, 智能卡 and 花生仁 are all tagged nr or nz, and the
|
|
672
|
-
// decoder capitalises straight off this bit, so 我买了一个沙发 came out as
|
|
673
|
-
// `Wǒ mǎile yīge Shāfā`.
|
|
674
|
-
//
|
|
675
|
-
// The veto only ever demotes, never promotes. CC-CEDICT capitalises the
|
|
676
|
-
// pinyin of a proper noun, which is a claim about the word rather than a
|
|
677
|
-
// category it was sorted into — but it also capitalises any headword
|
|
678
|
-
// written with Latin letters, so a capital there is not proof on its own.
|
|
679
|
-
// A lowercase one is much better evidence, since nothing else would write
|
|
680
|
-
// it that way.
|
|
681
|
-
const isProperNoun = jiebaEntry === undefined
|
|
682
|
-
? cedictEntries.some((entry) => entry.isProperNoun)
|
|
683
|
-
: isProperNounTag(partOfSpeech) &&
|
|
684
|
-
(senses.length === 0 || senses.some((entry) => entry.isProperNoun));
|
|
685
|
-
if (isProperNounTag(partOfSpeech) && !isProperNoun) {
|
|
686
|
-
properNounVetoes++;
|
|
687
|
-
}
|
|
688
|
-
// ── Where the 姓 ends, where CC-CEDICT says so ────────────
|
|
689
|
-
// Only for a word that survived the veto above: an entry no one takes for a
|
|
690
|
-
// proper noun has no 姓 to end. The boundary counts characters, so it is
|
|
691
|
-
// only meaningful where this word reads one syllable per character — 儿化
|
|
692
|
-
// reads two characters as one syllable and could not be cut by it.
|
|
693
|
-
const isAligned = characterCount(word) === reading.length;
|
|
694
|
-
const boundaries = isProperNoun && isAligned
|
|
695
|
-
? (cedictEntries
|
|
696
|
-
.map((entry) => nameBoundariesOf(entry.readings))
|
|
697
|
-
.find((found) => found.length > 0) ?? [])
|
|
698
|
-
: [];
|
|
699
|
-
if (boundaries.length > 0) {
|
|
700
|
-
nameBoundaries++;
|
|
701
|
-
}
|
|
702
|
-
// ── Polyphone priors, for single characters only ──────────
|
|
703
|
-
const characterReadings = defaults.get(word) ?? [];
|
|
704
|
-
const alternates = isSingleCharacter(word)
|
|
705
|
-
? characterReadings
|
|
706
|
-
.filter((syllable) => !isSameReading([syllable], reading))
|
|
707
|
-
.map((syllable) => [syllable])
|
|
708
|
-
: [];
|
|
709
|
-
entries.push({
|
|
710
|
-
hans: word,
|
|
711
|
-
hant,
|
|
712
|
-
...(hantVariants.length > 0 && { hantVariants }),
|
|
713
|
-
readings: { cn: reading, ...(taiwan !== undefined && { tw: taiwan }) },
|
|
714
|
-
frequency: jiebaEntry?.frequency ?? 0,
|
|
715
|
-
partOfSpeech,
|
|
716
|
-
isProperNoun,
|
|
717
|
-
...(boundaries.length > 0 && { nameBoundaries: boundaries }),
|
|
718
|
-
...(alternates.length > 0 && { alternates }),
|
|
719
|
-
});
|
|
720
|
-
if (isSingleCharacter(word)) {
|
|
721
|
-
characters++;
|
|
722
|
-
}
|
|
723
|
-
if (phraseReading !== undefined) {
|
|
724
|
-
phraseWords++;
|
|
725
|
-
}
|
|
726
|
-
if (cedictEntries.length > 0) {
|
|
727
|
-
cedictWords++;
|
|
728
|
-
}
|
|
729
|
-
}
|
|
30
|
+
const { traditional, defaults, reducedNeutrals } = buildCharacterDefaults(sources, cedictByWord, cedictByHant);
|
|
31
|
+
const wordSources = {
|
|
32
|
+
cedictByWord,
|
|
33
|
+
cedictByHant,
|
|
34
|
+
phrase,
|
|
35
|
+
jieba: sources.jieba,
|
|
36
|
+
unihanReadings: sources.unihanReadings,
|
|
37
|
+
traditional,
|
|
38
|
+
defaults,
|
|
39
|
+
};
|
|
40
|
+
const { entries, rejected, counts } = mergeWords(wordList(phrase, defaults, cedictByWord, cedictByHant), wordSources);
|
|
41
|
+
// ── Phrase entries held to the words inside them ───────────
|
|
42
|
+
// Before the locale pass, which asks whether a compound reads a constituent
|
|
43
|
+
// the way that constituent's own entry reads it. A phrase entry repaired here
|
|
44
|
+
// answers yes where it used to answer no.
|
|
45
|
+
const held = repairConstituentReadings(entries, senseLookup(cedictByWord, cedictByHant));
|
|
730
46
|
// ── zh-TW deltas the sources marked only on a constituent ──
|
|
731
47
|
// Last, because it segments each compound against the finished entries: the
|
|
732
48
|
// readings, both scripts' keys and the frequencies all have to be settled
|
|
733
49
|
// before a compound can be asked what it is made of.
|
|
734
|
-
const localised = composeLocaleDeltas(entries);
|
|
50
|
+
const localised = composeLocaleDeltas(held.entries);
|
|
735
51
|
return {
|
|
736
52
|
entries: localised.entries,
|
|
737
53
|
rejected,
|
|
738
54
|
stats: {
|
|
739
|
-
|
|
740
|
-
phraseWords,
|
|
741
|
-
cedictWords,
|
|
742
|
-
neutralToneCorrections,
|
|
55
|
+
...counts,
|
|
743
56
|
reducedNeutrals,
|
|
744
|
-
|
|
745
|
-
derivedTraditional,
|
|
746
|
-
scriptPairs,
|
|
747
|
-
variantSpellings,
|
|
748
|
-
taiwanReadings,
|
|
57
|
+
repairedConstituents: held.repaired,
|
|
749
58
|
composedTaiwanReadings: localised.composed,
|
|
750
|
-
properNounVetoes,
|
|
751
|
-
nameBoundaries,
|
|
752
59
|
rejected: rejected.size,
|
|
753
60
|
},
|
|
754
61
|
};
|