yomitan-core 1.0.2 → 1.2.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 (198) hide show
  1. package/README.md +8 -1
  2. package/dist/anki-connect-B2UXtiUS.js +6 -0
  3. package/dist/anki-connect-BXvjYYm0.cjs +6 -0
  4. package/dist/{anki-connect-B_YpChhu.cjs → anki-connect-DGx7Gr0H.cjs} +3 -3
  5. package/dist/{anki-connect-B_YpChhu.cjs.map → anki-connect-DGx7Gr0H.cjs.map} +1 -1
  6. package/dist/{anki-connect-697E04LF.js → anki-connect-Dau8nAXZ.js} +3 -3
  7. package/dist/{anki-connect-697E04LF.js.map → anki-connect-Dau8nAXZ.js.map} +1 -1
  8. package/dist/anki.cjs +6 -6
  9. package/dist/anki.d.cts.map +1 -1
  10. package/dist/anki.d.ts +2 -2
  11. package/dist/anki.d.ts.map +1 -1
  12. package/dist/anki.js +6 -6
  13. package/dist/{audio-ZuaDkaUZ.d.ts → audio-DN-FhZ5k.d.ts} +1 -1
  14. package/dist/{audio-ZuaDkaUZ.d.ts.map → audio-DN-FhZ5k.d.ts.map} +1 -1
  15. package/dist/{audio-url-generator-CgTMaTM2.js → audio-url-generator-C7mkxYeq.js} +2 -2
  16. package/dist/{audio-url-generator-CfXaxZ47.cjs → audio-url-generator-CZECihX-.cjs} +2 -2
  17. package/dist/{audio-url-generator-C23AXVj1.cjs → audio-url-generator-CorFRyBU.cjs} +2 -2
  18. package/dist/{audio-url-generator-C23AXVj1.cjs.map → audio-url-generator-CorFRyBU.cjs.map} +1 -1
  19. package/dist/{audio-url-generator-DykdzZJu.js → audio-url-generator-_6Qk0i3T.js} +2 -2
  20. package/dist/{audio-url-generator-DykdzZJu.js.map → audio-url-generator-_6Qk0i3T.js.map} +1 -1
  21. package/dist/audio.cjs +2 -2
  22. package/dist/audio.d.ts +2 -2
  23. package/dist/audio.js +2 -2
  24. package/dist/{batch-processor-CXZZhx5t.js → batch-processor-BR-gB3H3.js} +1 -1
  25. package/dist/{batch-processor-CXZZhx5t.js.map → batch-processor-BR-gB3H3.js.map} +1 -1
  26. package/dist/batch-processor-CSF1acTw.cjs +3 -0
  27. package/dist/{batch-processor-C8pSzqRE.cjs → batch-processor-DFqM_L-_.cjs} +1 -1
  28. package/dist/{batch-processor-C8pSzqRE.cjs.map → batch-processor-DFqM_L-_.cjs.map} +1 -1
  29. package/dist/batch-processor-Quo9jUyf.js +3 -0
  30. package/dist/{core-C_0QjRBI.d.ts → core-CRjMTF7c.d.ts} +1 -1
  31. package/dist/{core-C_0QjRBI.d.ts.map → core-CRjMTF7c.d.ts.map} +1 -1
  32. package/dist/database.d.ts +3 -3
  33. package/dist/debug-I2dyAd2e.cjs +51 -0
  34. package/dist/debug-I2dyAd2e.cjs.map +1 -0
  35. package/dist/debug-hF63AFkq.js +38 -0
  36. package/dist/debug-hF63AFkq.js.map +1 -0
  37. package/dist/{dictionary-CfzEFbXZ.d.ts → dictionary-DdxghSJP.d.ts} +1 -1
  38. package/dist/{dictionary-CfzEFbXZ.d.ts.map → dictionary-DdxghSJP.d.ts.map} +1 -1
  39. package/dist/{dictionary-data-util-BY_72f3u.cjs → dictionary-data-util-DmLJMtGc.cjs} +1 -1
  40. package/dist/{dictionary-data-util-BY_72f3u.cjs.map → dictionary-data-util-DmLJMtGc.cjs.map} +1 -1
  41. package/dist/{dictionary-data-util-CKDT7n2t.js → dictionary-data-util-gUUD9ElK.js} +1 -1
  42. package/dist/{dictionary-data-util-CKDT7n2t.js.map → dictionary-data-util-gUUD9ElK.js.map} +1 -1
  43. package/dist/{dictionary-database-BRAqOF_M.d.ts → dictionary-database-D0lvK2n3.d.ts} +2 -2
  44. package/dist/{dictionary-database-BRAqOF_M.d.ts.map → dictionary-database-D0lvK2n3.d.ts.map} +1 -1
  45. package/dist/{dictionary-importer-C7mNL5CJ.js → dictionary-importer-BPlLeF5R.js} +5 -5
  46. package/dist/{dictionary-importer-C7mNL5CJ.js.map → dictionary-importer-BPlLeF5R.js.map} +1 -1
  47. package/dist/{dictionary-importer-CbMwsqEX.cjs → dictionary-importer-BvgP1Fs9.cjs} +5 -5
  48. package/dist/{dictionary-importer-CbMwsqEX.cjs.map → dictionary-importer-BvgP1Fs9.cjs.map} +1 -1
  49. package/dist/{dictionary-importer-C-AlWsIN.d.ts → dictionary-importer-CDbCAbwG.d.ts} +2 -2
  50. package/dist/{dictionary-importer-C-AlWsIN.d.ts.map → dictionary-importer-CDbCAbwG.d.ts.map} +1 -1
  51. package/dist/dictionary-importer-DEMVqTjR.js +8 -0
  52. package/dist/dictionary-importer-Luz6usUQ.cjs +8 -0
  53. package/dist/{dictionary-update-checker-DE2ymYcs.js → dictionary-update-checker-CLbtQ48X.js} +2 -2
  54. package/dist/{dictionary-update-checker-DE2ymYcs.js.map → dictionary-update-checker-CLbtQ48X.js.map} +1 -1
  55. package/dist/dictionary-update-checker-CsS7MxK_.js +4 -0
  56. package/dist/{dictionary-update-checker-CU3q0aoP.cjs → dictionary-update-checker-DgjPsURI.cjs} +2 -2
  57. package/dist/{dictionary-update-checker-xIwF77-R.cjs → dictionary-update-checker-DmiIUoKw.cjs} +2 -2
  58. package/dist/{dictionary-update-checker-xIwF77-R.cjs.map → dictionary-update-checker-DmiIUoKw.cjs.map} +1 -1
  59. package/dist/{display-generator-vjbG05fn.js → display-generator-BAEJDrHT.js} +9 -7
  60. package/dist/display-generator-BAEJDrHT.js.map +1 -0
  61. package/dist/display-generator-D5fkD0JI.cjs +10 -0
  62. package/dist/display-generator-DZLMaVuP.js +10 -0
  63. package/dist/{display-generator-BhV_MOD1.cjs → display-generator-D_0chBzj.cjs} +9 -7
  64. package/dist/display-generator-D_0chBzj.cjs.map +1 -0
  65. package/dist/{errors-ZI2FcGUl.cjs → errors-0pIJI6N2.cjs} +1 -1
  66. package/dist/{errors-ZI2FcGUl.cjs.map → errors-0pIJI6N2.cjs.map} +1 -1
  67. package/dist/{errors-D2JfYV-C.js → errors-DvKlMRXC.js} +1 -1
  68. package/dist/{errors-D2JfYV-C.js.map → errors-DvKlMRXC.js.map} +1 -1
  69. package/dist/frequency-ranking-BXjfhhUQ.js +3 -0
  70. package/dist/{frequency-ranking-DmNIoxut.cjs → frequency-ranking-Cx1kkIrw.cjs} +1 -1
  71. package/dist/{frequency-ranking-DzbdZghE.js → frequency-ranking-DEJMTMdg.js} +1 -1
  72. package/dist/{frequency-ranking-DzbdZghE.js.map → frequency-ranking-DEJMTMdg.js.map} +1 -1
  73. package/dist/{frequency-ranking-Dm6xCMkY.cjs → frequency-ranking-DVYxTXN-.cjs} +1 -1
  74. package/dist/{frequency-ranking-Dm6xCMkY.cjs.map → frequency-ranking-DVYxTXN-.cjs.map} +1 -1
  75. package/dist/furigana-MU_j_m5i.cjs +5 -0
  76. package/dist/{furigana-BnY7-dJ-.cjs → furigana-SZuBaUyl.cjs} +2 -2
  77. package/dist/{furigana-BnY7-dJ-.cjs.map → furigana-SZuBaUyl.cjs.map} +1 -1
  78. package/dist/furigana-ZCs0Xs0b.js +5 -0
  79. package/dist/{furigana-CI6LUA-6.js → furigana-h18vaQ7a.js} +2 -2
  80. package/dist/{furigana-CI6LUA-6.js.map → furigana-h18vaQ7a.js.map} +1 -1
  81. package/dist/import.cjs +6 -6
  82. package/dist/import.d.ts +3 -3
  83. package/dist/import.js +6 -6
  84. package/dist/index.cjs +44 -18
  85. package/dist/index.cjs.map +1 -1
  86. package/dist/index.d.cts +3 -3
  87. package/dist/index.d.cts.map +1 -1
  88. package/dist/index.d.ts +10 -10
  89. package/dist/index.d.ts.map +1 -1
  90. package/dist/index.js +44 -18
  91. package/dist/index.js.map +1 -1
  92. package/dist/{japanese-BVV1Ctk-.cjs → japanese-C83fmEfb.cjs} +1 -1
  93. package/dist/{japanese-BVV1Ctk-.cjs.map → japanese-C83fmEfb.cjs.map} +1 -1
  94. package/dist/{japanese-DhmmW35J.js → japanese-OKEGf_i4.js} +2 -2
  95. package/dist/{japanese-DhmmW35J.js.map → japanese-OKEGf_i4.js.map} +1 -1
  96. package/dist/{json-CyQBn52D.cjs → json-Cdj6aIOQ.cjs} +1 -1
  97. package/dist/{json-CyQBn52D.cjs.map → json-Cdj6aIOQ.cjs.map} +1 -1
  98. package/dist/{json-DTq_IXXF.js → json-rIgOFqVY.js} +1 -1
  99. package/dist/{json-DTq_IXXF.js.map → json-rIgOFqVY.js.map} +1 -1
  100. package/dist/{language-DFFp_7nc.d.ts → language-DMwuc2-C.d.ts} +1 -1
  101. package/dist/{language-DFFp_7nc.d.ts.map → language-DMwuc2-C.d.ts.map} +1 -1
  102. package/dist/language.cjs +12 -12
  103. package/dist/language.d.cts +41 -3
  104. package/dist/language.d.cts.map +1 -1
  105. package/dist/language.d.ts +44 -6
  106. package/dist/language.d.ts.map +1 -1
  107. package/dist/language.js +5 -5
  108. package/dist/lookup.cjs +7 -6
  109. package/dist/lookup.d.cts +5 -78
  110. package/dist/lookup.d.cts.map +1 -1
  111. package/dist/lookup.d.ts +8 -81
  112. package/dist/lookup.d.ts.map +1 -1
  113. package/dist/lookup.js +7 -6
  114. package/dist/{media-loader-CMEuD0fn.js → media-loader-C1WZVVaA.js} +1 -1
  115. package/dist/{media-loader-CMEuD0fn.js.map → media-loader-C1WZVVaA.js.map} +1 -1
  116. package/dist/media-loader-CWNb22gc.cjs +3 -0
  117. package/dist/media-loader-CrQnDnSp.js +3 -0
  118. package/dist/{media-loader-DS2ZXpSI.cjs → media-loader-RE32nGs3.cjs} +1 -1
  119. package/dist/{media-loader-DS2ZXpSI.cjs.map → media-loader-RE32nGs3.cjs.map} +1 -1
  120. package/dist/{multi-language-transformer-CjLO0S8V.d.ts → multi-language-transformer-CFu0CVWY.d.ts} +3 -3
  121. package/dist/{multi-language-transformer-CjLO0S8V.d.ts.map → multi-language-transformer-CFu0CVWY.d.ts.map} +1 -1
  122. package/dist/multi-language-transformer-Dk8S4W6j.js +12503 -0
  123. package/dist/multi-language-transformer-Dk8S4W6j.js.map +1 -0
  124. package/dist/{multi-language-transformer-B2133Zg_.cjs → multi-language-transformer-N66Mmb2E.cjs} +9614 -5
  125. package/dist/multi-language-transformer-N66Mmb2E.cjs.map +1 -0
  126. package/dist/{pronunciation-generator-cNtAQi5s.js → pronunciation-generator-BXcwS3By.js} +2 -2
  127. package/dist/{pronunciation-generator-cNtAQi5s.js.map → pronunciation-generator-BXcwS3By.js.map} +1 -1
  128. package/dist/{pronunciation-generator-CPwnr43z.cjs → pronunciation-generator-CP1kjYje.cjs} +1 -1
  129. package/dist/{pronunciation-generator-B8y__W7I.cjs → pronunciation-generator-CeC3LFPU.cjs} +1 -1
  130. package/dist/{pronunciation-generator-B8y__W7I.cjs.map → pronunciation-generator-CeC3LFPU.cjs.map} +1 -1
  131. package/dist/{pronunciation-generator-BvTbUlOy.js → pronunciation-generator-I1xpdJu0.js} +1 -1
  132. package/dist/render.cjs +96 -8
  133. package/dist/render.cjs.map +1 -1
  134. package/dist/render.d.cts +33 -3
  135. package/dist/render.d.cts.map +1 -1
  136. package/dist/render.d.ts +35 -5
  137. package/dist/render.d.ts.map +1 -1
  138. package/dist/render.js +95 -9
  139. package/dist/render.js.map +1 -1
  140. package/dist/{sentence-parser-DUQJ3cTT.cjs → sentence-parser-8i1Y_OGS.cjs} +74 -46
  141. package/dist/sentence-parser-8i1Y_OGS.cjs.map +1 -0
  142. package/dist/{translator-TiTDVbmS.d.cts → sentence-parser-BQpu2oSA.d.cts} +80 -4
  143. package/dist/sentence-parser-BQpu2oSA.d.cts.map +1 -0
  144. package/dist/{sentence-parser-sx7y6Oyh.js → sentence-parser-CXDs4R_c.js} +74 -46
  145. package/dist/sentence-parser-CXDs4R_c.js.map +1 -0
  146. package/dist/{translator-CYvGmODX.d.ts → sentence-parser-CmsHUc_p.d.ts} +81 -5
  147. package/dist/sentence-parser-CmsHUc_p.d.ts.map +1 -0
  148. package/dist/sentence-parser-DQccqSpq.cjs +6 -0
  149. package/dist/sentence-parser-DsleseSI.js +6 -0
  150. package/dist/structured-content-generator-BhEkwa0T.js +4 -0
  151. package/dist/{structured-content-generator-C5Hhaurz.cjs → structured-content-generator-CokLKgrb.cjs} +2 -2
  152. package/dist/{structured-content-generator-C5Hhaurz.cjs.map → structured-content-generator-CokLKgrb.cjs.map} +1 -1
  153. package/dist/{structured-content-generator-D48bLhPA.cjs → structured-content-generator-_z5dJECG.cjs} +2 -2
  154. package/dist/{structured-content-generator-aJieXElq.js → structured-content-generator-gnjtdBcC.js} +2 -2
  155. package/dist/{structured-content-generator-aJieXElq.js.map → structured-content-generator-gnjtdBcC.js.map} +1 -1
  156. package/dist/{text-utilities-CFDC9Bkr.cjs → text-utilities-CTsN1Bq8.cjs} +1 -1
  157. package/dist/{text-utilities-CFDC9Bkr.cjs.map → text-utilities-CTsN1Bq8.cjs.map} +1 -1
  158. package/dist/{text-utilities-D5eno9GK.js → text-utilities-DjLdStjv.js} +1 -1
  159. package/dist/{text-utilities-D5eno9GK.js.map → text-utilities-DjLdStjv.js.map} +1 -1
  160. package/dist/translator-BGI37WRC.js +7 -0
  161. package/dist/translator-Cd1ECBM1.cjs +7 -0
  162. package/dist/{translator-B1uTusjx.cjs → translator-ClzybVmi.cjs} +2 -2
  163. package/dist/{translator-B1uTusjx.cjs.map → translator-ClzybVmi.cjs.map} +1 -1
  164. package/dist/{translator-CrDE1UJW.js → translator-jFVzLjEs.js} +2 -2
  165. package/dist/{translator-CrDE1UJW.js.map → translator-jFVzLjEs.js.map} +1 -1
  166. package/package.json +1 -1
  167. package/dist/anki-connect-D-02BbHi.cjs +0 -6
  168. package/dist/anki-connect-Vn-cnxs8.js +0 -6
  169. package/dist/batch-processor-DItpL6Pp.js +0 -3
  170. package/dist/batch-processor-fiLvFS2_.cjs +0 -3
  171. package/dist/dictionary-importer-B9M3SD2y.js +0 -8
  172. package/dist/dictionary-importer-DnR8Bsai.cjs +0 -8
  173. package/dist/dictionary-update-checker-Cnjz4tQD.js +0 -4
  174. package/dist/display-generator-BhV_MOD1.cjs.map +0 -1
  175. package/dist/display-generator-Cn4vCiSI.js +0 -10
  176. package/dist/display-generator-G2e03o0R.cjs +0 -10
  177. package/dist/display-generator-vjbG05fn.js.map +0 -1
  178. package/dist/frequency-ranking-B-kvnxro.js +0 -3
  179. package/dist/furigana-cpPhFnBv.cjs +0 -5
  180. package/dist/furigana-kZjqnnFC.js +0 -5
  181. package/dist/japanese-DdsS8rT1.d.ts +0 -41
  182. package/dist/japanese-DdsS8rT1.d.ts.map +0 -1
  183. package/dist/japanese-DgmP3i76.d.cts +0 -41
  184. package/dist/japanese-DgmP3i76.d.cts.map +0 -1
  185. package/dist/media-loader-BBTESZXn.cjs +0 -3
  186. package/dist/media-loader-CNKoAjQs.js +0 -3
  187. package/dist/multi-language-transformer-B2133Zg_.cjs.map +0 -1
  188. package/dist/multi-language-transformer-BkwMTV2g.js +0 -2893
  189. package/dist/multi-language-transformer-BkwMTV2g.js.map +0 -1
  190. package/dist/sentence-parser-B-gM8mKk.js +0 -5
  191. package/dist/sentence-parser-Cp3cm_QU.cjs +0 -5
  192. package/dist/sentence-parser-DUQJ3cTT.cjs.map +0 -1
  193. package/dist/sentence-parser-sx7y6Oyh.js.map +0 -1
  194. package/dist/structured-content-generator-Dww8IT7Y.js +0 -4
  195. package/dist/translator-BiTHo9Nm.js +0 -7
  196. package/dist/translator-CYvGmODX.d.ts.map +0 -1
  197. package/dist/translator-TiTDVbmS.d.cts.map +0 -1
  198. package/dist/translator-Y7Haj_qJ.cjs +0 -7
@@ -393,5 +393,5 @@ var PronunciationGenerator = class {
393
393
  };
394
394
 
395
395
  //#endregion
396
- export { PronunciationGenerator, getDownstepPositions, getKanaDiacriticInfo, getKanaMoraCount, getKanaMorae, getPitchCategory, isCodePointKanji, isMoraPitchHigh };
397
- //# sourceMappingURL=pronunciation-generator-cNtAQi5s.js.map
396
+ export { PronunciationGenerator, getDownstepPositions as getDownstepPositions$1, getKanaDiacriticInfo as getKanaDiacriticInfo$1, getKanaMoraCount as getKanaMoraCount$1, getKanaMorae as getKanaMorae$1, getPitchCategory as getPitchCategory$1, isCodePointKanji as isCodePointKanji$1, isMoraPitchHigh as isMoraPitchHigh$1 };
397
+ //# sourceMappingURL=pronunciation-generator-BXcwS3By.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"pronunciation-generator-cNtAQi5s.js","names":["codePoint: number","moraIndex: number","pitchAccentValue: number | string","text: string","isVerbOrAdjective: boolean","pitchString: string","downsteps: number[]","morae: string[]","i: number","character: string","doc: Document","morae: string[]","pitchPositions: number | string","nasalPositions: number[]","devoicePositions: number[]","characterNodes: HTMLSpanElement[]","pathPoints: string[]","downstepPositions: number | string","mora: string[]","circles: Element[]","paths: Element[]","container: Element","svgns: string","x: number","y: number","className: string","radius: string","numberOfMora: number","pitchValue: number | string","o: boolean","node","mora: string","svg: SVGSVGElement","type: string","stepWidth: number"],"sources":["../src/render/japanese-util.ts","../src/render/pronunciation-generator.ts"],"sourcesContent":["/*\n * Copyright (C) 2024-2025 Yomitan Authors\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program. If not, see <https://www.gnu.org/licenses/>.\n */\n\n/**\n * Japanese language utility functions used by the display rendering layer.\n * These are ported from the Yomitan extension's japanese.js module.\n */\n\nimport { CJK_IDEOGRAPH_RANGES, isCodePointInRanges } from '../language/cjk-util.js';\n\nexport type PitchCategory = 'heiban' | 'atamadaka' | 'nakadaka' | 'odaka' | 'kifuku';\n\nexport type DiacriticType = 'dakuten' | 'handakuten';\n\nconst SMALL_KANA_SET = new Set('ぁぃぅぇぉゃゅょゎァィゥェォャュョヮ');\n\nconst kana =\n 'うゔ-かが-きぎ-くぐ-けげ-こご-さざ-しじ-すず-せぜ-そぞ-ただ-ちぢ-つづ-てで-とど-はばぱひびぴふぶぷへべぺほぼぽワヷ-ヰヸ-ウヴ-ヱヹ-ヲヺ-カガ-キギ-クグ-ケゲ-コゴ-サザ-シジ-スズ-セゼ-ソゾ-タダ-チヂ-ツヅ-テデ-トド-ハバパヒビピフブプヘベペホボポ';\nconst DIACRITIC_MAPPING = new Map<string, { character: string; type: DiacriticType }>();\nfor (let i = 0, ii = kana.length; i < ii; i += 3) {\n const character = kana[i];\n const dakuten = kana[i + 1];\n const handakuten = kana[i + 2];\n DIACRITIC_MAPPING.set(dakuten, { character, type: 'dakuten' });\n if (handakuten !== '-') {\n DIACRITIC_MAPPING.set(handakuten, { character, type: 'handakuten' });\n }\n}\n\n/**\n * Checks if a code point represents a CJK kanji character.\n */\nexport function isCodePointKanji(codePoint: number): boolean {\n return isCodePointInRanges(codePoint, CJK_IDEOGRAPH_RANGES);\n}\n\n/**\n * Determines whether a mora at a given index has high pitch.\n * @param moraIndex - The 0-based mora index to check.\n * @param pitchAccentValue - The pitch accent pattern (number = downstep position, string = HL pattern).\n * @returns True if the mora at the given index has high pitch.\n */\nexport function isMoraPitchHigh(moraIndex: number, pitchAccentValue: number | string): boolean {\n if (typeof pitchAccentValue === 'string') {\n return pitchAccentValue[moraIndex] === 'H';\n }\n switch (pitchAccentValue) {\n case 0:\n return moraIndex > 0;\n case 1:\n return moraIndex < 1;\n default:\n return moraIndex > 0 && moraIndex < pitchAccentValue;\n }\n}\n\n/**\n * Determines the pitch accent category for a word.\n * @param text - The reading text.\n * @param pitchAccentValue - The pitch accent pattern.\n * @param isVerbOrAdjective - Whether the word is a verb or adjective (not a noun).\n * @returns The pitch category, or null if it cannot be determined.\n */\nexport function getPitchCategory(\n text: string,\n pitchAccentValue: number | string,\n isVerbOrAdjective: boolean,\n): PitchCategory | null {\n const pitchAccentDownstepPosition =\n typeof pitchAccentValue === 'string' ? getDownstepPositions(pitchAccentValue)[0] : pitchAccentValue;\n if (pitchAccentDownstepPosition === 0) {\n return 'heiban';\n }\n if (isVerbOrAdjective) {\n return pitchAccentDownstepPosition > 0 ? 'kifuku' : null;\n }\n if (pitchAccentDownstepPosition === 1) {\n return 'atamadaka';\n }\n if (pitchAccentDownstepPosition > 1) {\n return pitchAccentDownstepPosition >= getKanaMoraCount(text) ? 'odaka' : 'nakadaka';\n }\n return null;\n}\n\n/**\n * Extracts downstep positions from an HL pitch string pattern.\n * @param pitchString - A string of 'H' and 'L' characters representing pitch.\n * @returns Array of downstep positions (1-indexed mora positions where pitch drops).\n */\nexport function getDownstepPositions(pitchString: string): number[] {\n const downsteps: number[] = [];\n const moraCount = pitchString.length;\n for (let i = 0; i < moraCount; i++) {\n if (i > 0 && pitchString[i - 1] === 'H' && pitchString[i] === 'L') {\n downsteps.push(i);\n }\n }\n if (downsteps.length === 0) {\n downsteps.push(pitchString.startsWith('L') ? 0 : -1);\n }\n return downsteps;\n}\n\n/**\n * Splits a kana text into an array of morae, combining small kana with their preceding character.\n * @param text - The kana text to split.\n * @returns Array of mora strings.\n */\nexport function getKanaMorae(text: string): string[] {\n const morae: string[] = [];\n let i: number;\n for (const c of text) {\n if (SMALL_KANA_SET.has(c) && (i = morae.length) > 0) {\n morae[i - 1] += c;\n } else {\n morae.push(c);\n }\n }\n return morae;\n}\n\n/**\n * Counts the number of morae in a kana text.\n * @param text - The kana text to count morae in.\n * @returns The number of morae.\n */\nexport function getKanaMoraCount(text: string): number {\n let moraCount = 0;\n for (const c of text) {\n if (!(SMALL_KANA_SET.has(c) && moraCount > 0)) {\n ++moraCount;\n }\n }\n return moraCount;\n}\n\n/**\n * Gets diacritic information for a kana character.\n * If the character is a dakuten or handakuten variant, returns the base character and type.\n * @param character - The kana character to check.\n * @returns An object with the base character and diacritic type, or null if not a diacritic variant.\n */\nexport function getKanaDiacriticInfo(character: string): { character: string; type: DiacriticType } | null {\n const info = DIACRITIC_MAPPING.get(character);\n return typeof info !== 'undefined' ? { character: info.character, type: info.type } : null;\n}\n","/*\n * Copyright (C) 2023-2025 Yomitan Authors\n * Copyright (C) 2021-2022 Yomichan Authors\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program. If not, see <https://www.gnu.org/licenses/>.\n */\n\nimport { getDownstepPositions, getKanaDiacriticInfo, isMoraPitchHigh } from './japanese-util.js';\n\n/**\n * Generates DOM elements for pronunciation visualizations including\n * pitch accent text, graphs, and downstep position notation.\n */\nexport class PronunciationGenerator {\n private _document: Document;\n\n /**\n * Creates a new PronunciationGenerator.\n * @param doc - The Document object to use for creating DOM elements.\n */\n constructor(doc: Document) {\n this._document = doc;\n }\n\n /**\n * Creates a span element containing styled mora elements for pronunciation text.\n * @param morae - Array of mora strings.\n * @param pitchPositions - The pitch accent downstep position (number or HL string pattern).\n * @param nasalPositions - Array of 1-indexed mora positions that are nasalized.\n * @param devoicePositions - Array of 1-indexed mora positions that are devoiced.\n * @returns A span element with class `pronunciation-text`.\n */\n createPronunciationText(\n morae: string[],\n pitchPositions: number | string,\n nasalPositions: number[],\n devoicePositions: number[],\n ): HTMLSpanElement {\n const nasalPositionsSet = nasalPositions.length > 0 ? new Set(nasalPositions) : null;\n const devoicePositionsSet = devoicePositions.length > 0 ? new Set(devoicePositions) : null;\n const container = this._document.createElement('span');\n container.className = 'pronunciation-text';\n for (let i = 0, ii = morae.length; i < ii; ++i) {\n const i1 = i + 1;\n const mora = morae[i];\n const highPitch = isMoraPitchHigh(i, pitchPositions);\n const highPitchNext = isMoraPitchHigh(i1, pitchPositions);\n const nasal = nasalPositionsSet?.has(i1);\n const devoice = devoicePositionsSet?.has(i1);\n\n const n1 = this._document.createElement('span');\n n1.className = 'pronunciation-mora';\n n1.dataset.position = `${i}`;\n n1.dataset.pitch = highPitch ? 'high' : 'low';\n n1.dataset.pitchNext = highPitchNext ? 'high' : 'low';\n\n const characterNodes: HTMLSpanElement[] = [];\n for (const character of mora) {\n const n2 = this._document.createElement('span');\n n2.className = 'pronunciation-character';\n n2.textContent = character;\n n1.appendChild(n2);\n characterNodes.push(n2);\n }\n\n if (devoice) {\n n1.dataset.devoice = 'true';\n const n3 = this._document.createElement('span');\n n3.className = 'pronunciation-devoice-indicator';\n n1.appendChild(n3);\n }\n if (nasal && characterNodes.length > 0) {\n n1.dataset.nasal = 'true';\n\n const group = this._document.createElement('span');\n group.className = 'pronunciation-character-group';\n\n const n2 = characterNodes[0];\n const character = n2.textContent as string;\n\n const characterInfo = getKanaDiacriticInfo(character);\n if (characterInfo !== null) {\n n1.dataset.originalText = mora;\n n2.dataset.originalText = character;\n n2.textContent = characterInfo.character;\n }\n\n let n3 = this._document.createElement('span');\n n3.className = 'pronunciation-nasal-diacritic';\n n3.textContent = '\\u309a'; // Combining handakuten\n group.appendChild(n3);\n\n n3 = this._document.createElement('span');\n n3.className = 'pronunciation-nasal-indicator';\n group.appendChild(n3);\n\n (n2.parentNode as ParentNode).replaceChild(group, n2);\n group.insertBefore(n2, group.firstChild);\n }\n\n const line = this._document.createElement('span');\n line.className = 'pronunciation-mora-line';\n n1.appendChild(line);\n\n container.appendChild(n1);\n }\n return container;\n }\n\n /**\n * Creates an SVG element representing the pitch accent graph.\n * @param morae - Array of mora strings.\n * @param pitchPositions - The pitch accent downstep position (number or HL string pattern).\n * @returns An SVG element with class `pronunciation-graph`.\n */\n createPronunciationGraph(morae: string[], pitchPositions: number | string): SVGSVGElement {\n const ii = morae.length;\n\n const svgns = 'http://www.w3.org/2000/svg';\n const svg = this._document.createElementNS(svgns, 'svg') as SVGSVGElement;\n svg.setAttribute('xmlns', svgns);\n svg.setAttribute('class', 'pronunciation-graph');\n svg.setAttribute('focusable', 'false');\n svg.setAttribute('viewBox', `0 0 ${50 * (ii + 1)} 100`);\n\n if (ii <= 0) {\n return svg;\n }\n\n const path1 = this._document.createElementNS(svgns, 'path');\n svg.appendChild(path1);\n\n const path2 = this._document.createElementNS(svgns, 'path');\n svg.appendChild(path2);\n\n const pathPoints: string[] = [];\n for (let i = 0; i < ii; ++i) {\n const highPitch = isMoraPitchHigh(i, pitchPositions);\n const highPitchNext = isMoraPitchHigh(i + 1, pitchPositions);\n const x = i * 50 + 25;\n const y = highPitch ? 25 : 75;\n if (highPitch && !highPitchNext) {\n this._addGraphDotDownstep(svg, svgns, x, y);\n } else {\n this._addGraphDot(svg, svgns, x, y);\n }\n pathPoints.push(`${x} ${y}`);\n }\n\n path1.setAttribute('class', 'pronunciation-graph-line');\n path1.setAttribute('d', `M${pathPoints.join(' L')}`);\n\n pathPoints.splice(0, ii - 1);\n {\n const highPitch = isMoraPitchHigh(ii, pitchPositions);\n const x = ii * 50 + 25;\n const y = highPitch ? 25 : 75;\n this._addGraphTriangle(svg, svgns, x, y);\n pathPoints.push(`${x} ${y}`);\n }\n\n path2.setAttribute('class', 'pronunciation-graph-line-tail');\n path2.setAttribute('d', `M${pathPoints.join(' L')}`);\n\n return svg;\n }\n\n /**\n * Creates a span element showing the downstep position in bracket notation.\n * @param downstepPositions - The downstep position (number or HL string pattern).\n * @returns A span element with class `pronunciation-downstep-notation`.\n */\n createPronunciationDownstepPosition(downstepPositions: number | string): HTMLSpanElement {\n const downsteps =\n typeof downstepPositions === 'string' ? getDownstepPositions(downstepPositions) : downstepPositions;\n const downstepPositionString = `${downsteps}`;\n\n const n1 = this._document.createElement('span');\n n1.className = 'pronunciation-downstep-notation';\n n1.dataset.downstepPosition = downstepPositionString;\n\n let n2 = this._document.createElement('span');\n n2.className = 'pronunciation-downstep-notation-prefix';\n n2.textContent = '[';\n n1.appendChild(n2);\n\n n2 = this._document.createElement('span');\n n2.className = 'pronunciation-downstep-notation-number';\n n2.textContent = downstepPositionString;\n n1.appendChild(n2);\n\n n2 = this._document.createElement('span');\n n2.className = 'pronunciation-downstep-notation-suffix';\n n2.textContent = ']';\n n1.appendChild(n2);\n\n return n1;\n }\n\n /**\n * Creates a Jidoujisho-style pronunciation graph SVG.\n * @param mora - Array of mora strings.\n * @param pitchPositions - The pitch accent downstep position (number or HL string pattern).\n * @returns An SVG element.\n */\n createPronunciationGraphJJ(mora: string[], pitchPositions: number | string): SVGSVGElement {\n const patt = this._pitchValueToPattJJ(mora.length, pitchPositions);\n\n const positions = Math.max(mora.length, patt.length);\n const stepWidth = 35;\n const marginLr = 16;\n const svgWidth = Math.max(0, (positions - 1) * stepWidth + marginLr * 2);\n\n const svgns = 'http://www.w3.org/2000/svg';\n const svg = this._document.createElementNS(svgns, 'svg') as SVGSVGElement;\n svg.setAttribute('xmlns', svgns);\n svg.setAttribute('width', `${svgWidth * (3 / 5)}px`);\n svg.setAttribute('height', '45px');\n svg.setAttribute('viewBox', `0 0 ${svgWidth} 75`);\n\n if (mora.length <= 0) {\n return svg;\n }\n\n for (let i = 0; i < mora.length; i++) {\n const xCenter = marginLr + i * stepWidth;\n this._textJJ(xCenter - 11, mora[i], svgns, svg);\n }\n\n let pathType = '';\n\n const circles: Element[] = [];\n const paths: Element[] = [];\n\n let prevCenter = [-1, -1];\n for (let i = 0; i < patt.length; i++) {\n const xCenter = marginLr + i * stepWidth;\n const accent = patt[i];\n let yCenter = 0;\n if (accent === 'H') {\n yCenter = 5;\n } else if (accent === 'L') {\n yCenter = 30;\n }\n circles.push(this._circleJJ(xCenter, yCenter, i >= mora.length, svgns));\n\n if (i > 0) {\n if (prevCenter[1] === yCenter) {\n pathType = 's';\n } else if (prevCenter[1] < yCenter) {\n pathType = 'd';\n } else if (prevCenter[1] > yCenter) {\n pathType = 'u';\n }\n paths.push(this._pathJJ(prevCenter[0], prevCenter[1], pathType, stepWidth, svgns));\n }\n prevCenter = [xCenter, yCenter];\n }\n\n for (const path of paths) {\n svg.appendChild(path);\n }\n\n for (const circle of circles) {\n svg.appendChild(circle);\n }\n\n return svg;\n }\n\n // Private\n\n private _addGraphDot(container: Element, svgns: string, x: number, y: number): void {\n container.appendChild(this._createGraphCircle(svgns, 'pronunciation-graph-dot', x, y, '15'));\n }\n\n private _addGraphDotDownstep(container: Element, svgns: string, x: number, y: number): void {\n container.appendChild(this._createGraphCircle(svgns, 'pronunciation-graph-dot-downstep1', x, y, '15'));\n container.appendChild(this._createGraphCircle(svgns, 'pronunciation-graph-dot-downstep2', x, y, '5'));\n }\n\n private _addGraphTriangle(container: Element, svgns: string, x: number, y: number): void {\n const node = this._document.createElementNS(svgns, 'path');\n node.setAttribute('class', 'pronunciation-graph-triangle');\n node.setAttribute('d', 'M0 13 L15 -13 L-15 -13 Z');\n node.setAttribute('transform', `translate(${x},${y})`);\n container.appendChild(node);\n }\n\n private _createGraphCircle(svgns: string, className: string, x: number, y: number, radius: string): Element {\n const node = this._document.createElementNS(svgns, 'circle');\n node.setAttribute('class', className);\n node.setAttribute('cx', `${x}`);\n node.setAttribute('cy', `${y}`);\n node.setAttribute('r', radius);\n return node;\n }\n\n private _pitchValueToPattJJ(numberOfMora: number, pitchValue: number | string): string {\n if (typeof pitchValue === 'string') {\n return pitchValue + pitchValue[pitchValue.length - 1];\n }\n if (numberOfMora >= 1) {\n if (pitchValue === 0) {\n return `L${'H'.repeat(numberOfMora)}`;\n }\n if (pitchValue === 1) {\n return `H${'L'.repeat(numberOfMora)}`;\n }\n if (pitchValue >= 2) {\n const stepdown = pitchValue - 2;\n return `LH${'H'.repeat(stepdown)}${'L'.repeat(numberOfMora - pitchValue + 1)}`;\n }\n }\n return '';\n }\n\n private _circleJJ(x: number, y: number, o: boolean, svgns: string): Element {\n if (o) {\n const node = this._document.createElementNS(svgns, 'circle');\n node.setAttribute('r', '4');\n node.setAttribute('cx', `${x + 4}`);\n node.setAttribute('cy', `${y}`);\n node.setAttribute('stroke', 'currentColor');\n node.setAttribute('stroke-width', '2');\n node.setAttribute('fill', 'none');\n return node;\n }\n const node = this._document.createElementNS(svgns, 'circle');\n node.setAttribute('r', '5');\n node.setAttribute('cx', `${x}`);\n node.setAttribute('cy', `${y}`);\n node.setAttribute('style', 'opacity:1;fill:currentColor;');\n return node;\n }\n\n private _textJJ(x: number, mora: string, svgns: string, svg: SVGSVGElement): void {\n if (mora.length === 1) {\n const path = this._document.createElementNS(svgns, 'text');\n path.setAttribute('x', `${x}`);\n path.setAttribute('y', '67.5');\n path.setAttribute('style', 'font-size:20px;font-family:sans-serif;fill:currentColor;');\n path.textContent = mora;\n svg.appendChild(path);\n } else {\n const path1 = this._document.createElementNS(svgns, 'text');\n path1.setAttribute('x', `${x - 5}`);\n path1.setAttribute('y', '67.5');\n path1.setAttribute('style', 'font-size:20px;font-family:sans-serif;fill:currentColor;');\n path1.textContent = mora[0];\n svg.appendChild(path1);\n\n const path2 = this._document.createElementNS(svgns, 'text');\n path2.setAttribute('x', `${x + 12}`);\n path2.setAttribute('y', '67.5');\n path2.setAttribute('style', 'font-size:14px;font-family:sans-serif;fill:currentColor;');\n path2.textContent = mora[1];\n svg.appendChild(path2);\n }\n }\n\n private _pathJJ(x: number, y: number, type: string, stepWidth: number, svgns: string): Element {\n let delta = '';\n switch (type) {\n case 's':\n delta = `${stepWidth},0`;\n break;\n case 'u':\n delta = `${stepWidth},-25`;\n break;\n case 'd':\n delta = `${stepWidth},25`;\n break;\n }\n\n const path = this._document.createElementNS(svgns, 'path');\n path.setAttribute('d', `m ${x},${y} ${delta}`);\n path.setAttribute('style', 'fill:none;stroke:currentColor;stroke-width:1.5;');\n\n return path;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"pronunciation-generator-BXcwS3By.js","names":["codePoint: number","moraIndex: number","pitchAccentValue: number | string","text: string","isVerbOrAdjective: boolean","pitchString: string","downsteps: number[]","morae: string[]","i: number","character: string","doc: Document","morae: string[]","pitchPositions: number | string","nasalPositions: number[]","devoicePositions: number[]","characterNodes: HTMLSpanElement[]","pathPoints: string[]","downstepPositions: number | string","mora: string[]","circles: Element[]","paths: Element[]","container: Element","svgns: string","x: number","y: number","className: string","radius: string","numberOfMora: number","pitchValue: number | string","o: boolean","node","mora: string","svg: SVGSVGElement","type: string","stepWidth: number"],"sources":["../src/render/japanese-util.ts","../src/render/pronunciation-generator.ts"],"sourcesContent":["/*\n * Copyright (C) 2024-2025 Yomitan Authors\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program. If not, see <https://www.gnu.org/licenses/>.\n */\n\n/**\n * Japanese language utility functions used by the display rendering layer.\n * These are ported from the Yomitan extension's japanese.js module.\n */\n\nimport { CJK_IDEOGRAPH_RANGES, isCodePointInRanges } from '../language/cjk-util.js';\n\nexport type PitchCategory = 'heiban' | 'atamadaka' | 'nakadaka' | 'odaka' | 'kifuku';\n\nexport type DiacriticType = 'dakuten' | 'handakuten';\n\nconst SMALL_KANA_SET = new Set('ぁぃぅぇぉゃゅょゎァィゥェォャュョヮ');\n\nconst kana =\n 'うゔ-かが-きぎ-くぐ-けげ-こご-さざ-しじ-すず-せぜ-そぞ-ただ-ちぢ-つづ-てで-とど-はばぱひびぴふぶぷへべぺほぼぽワヷ-ヰヸ-ウヴ-ヱヹ-ヲヺ-カガ-キギ-クグ-ケゲ-コゴ-サザ-シジ-スズ-セゼ-ソゾ-タダ-チヂ-ツヅ-テデ-トド-ハバパヒビピフブプヘベペホボポ';\nconst DIACRITIC_MAPPING = new Map<string, { character: string; type: DiacriticType }>();\nfor (let i = 0, ii = kana.length; i < ii; i += 3) {\n const character = kana[i];\n const dakuten = kana[i + 1];\n const handakuten = kana[i + 2];\n DIACRITIC_MAPPING.set(dakuten, { character, type: 'dakuten' });\n if (handakuten !== '-') {\n DIACRITIC_MAPPING.set(handakuten, { character, type: 'handakuten' });\n }\n}\n\n/**\n * Checks if a code point represents a CJK kanji character.\n */\nexport function isCodePointKanji(codePoint: number): boolean {\n return isCodePointInRanges(codePoint, CJK_IDEOGRAPH_RANGES);\n}\n\n/**\n * Determines whether a mora at a given index has high pitch.\n * @param moraIndex - The 0-based mora index to check.\n * @param pitchAccentValue - The pitch accent pattern (number = downstep position, string = HL pattern).\n * @returns True if the mora at the given index has high pitch.\n */\nexport function isMoraPitchHigh(moraIndex: number, pitchAccentValue: number | string): boolean {\n if (typeof pitchAccentValue === 'string') {\n return pitchAccentValue[moraIndex] === 'H';\n }\n switch (pitchAccentValue) {\n case 0:\n return moraIndex > 0;\n case 1:\n return moraIndex < 1;\n default:\n return moraIndex > 0 && moraIndex < pitchAccentValue;\n }\n}\n\n/**\n * Determines the pitch accent category for a word.\n * @param text - The reading text.\n * @param pitchAccentValue - The pitch accent pattern.\n * @param isVerbOrAdjective - Whether the word is a verb or adjective (not a noun).\n * @returns The pitch category, or null if it cannot be determined.\n */\nexport function getPitchCategory(\n text: string,\n pitchAccentValue: number | string,\n isVerbOrAdjective: boolean,\n): PitchCategory | null {\n const pitchAccentDownstepPosition =\n typeof pitchAccentValue === 'string' ? getDownstepPositions(pitchAccentValue)[0] : pitchAccentValue;\n if (pitchAccentDownstepPosition === 0) {\n return 'heiban';\n }\n if (isVerbOrAdjective) {\n return pitchAccentDownstepPosition > 0 ? 'kifuku' : null;\n }\n if (pitchAccentDownstepPosition === 1) {\n return 'atamadaka';\n }\n if (pitchAccentDownstepPosition > 1) {\n return pitchAccentDownstepPosition >= getKanaMoraCount(text) ? 'odaka' : 'nakadaka';\n }\n return null;\n}\n\n/**\n * Extracts downstep positions from an HL pitch string pattern.\n * @param pitchString - A string of 'H' and 'L' characters representing pitch.\n * @returns Array of downstep positions (1-indexed mora positions where pitch drops).\n */\nexport function getDownstepPositions(pitchString: string): number[] {\n const downsteps: number[] = [];\n const moraCount = pitchString.length;\n for (let i = 0; i < moraCount; i++) {\n if (i > 0 && pitchString[i - 1] === 'H' && pitchString[i] === 'L') {\n downsteps.push(i);\n }\n }\n if (downsteps.length === 0) {\n downsteps.push(pitchString.startsWith('L') ? 0 : -1);\n }\n return downsteps;\n}\n\n/**\n * Splits a kana text into an array of morae, combining small kana with their preceding character.\n * @param text - The kana text to split.\n * @returns Array of mora strings.\n */\nexport function getKanaMorae(text: string): string[] {\n const morae: string[] = [];\n let i: number;\n for (const c of text) {\n if (SMALL_KANA_SET.has(c) && (i = morae.length) > 0) {\n morae[i - 1] += c;\n } else {\n morae.push(c);\n }\n }\n return morae;\n}\n\n/**\n * Counts the number of morae in a kana text.\n * @param text - The kana text to count morae in.\n * @returns The number of morae.\n */\nexport function getKanaMoraCount(text: string): number {\n let moraCount = 0;\n for (const c of text) {\n if (!(SMALL_KANA_SET.has(c) && moraCount > 0)) {\n ++moraCount;\n }\n }\n return moraCount;\n}\n\n/**\n * Gets diacritic information for a kana character.\n * If the character is a dakuten or handakuten variant, returns the base character and type.\n * @param character - The kana character to check.\n * @returns An object with the base character and diacritic type, or null if not a diacritic variant.\n */\nexport function getKanaDiacriticInfo(character: string): { character: string; type: DiacriticType } | null {\n const info = DIACRITIC_MAPPING.get(character);\n return typeof info !== 'undefined' ? { character: info.character, type: info.type } : null;\n}\n","/*\n * Copyright (C) 2023-2025 Yomitan Authors\n * Copyright (C) 2021-2022 Yomichan Authors\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program. If not, see <https://www.gnu.org/licenses/>.\n */\n\nimport { getDownstepPositions, getKanaDiacriticInfo, isMoraPitchHigh } from './japanese-util.js';\n\n/**\n * Generates DOM elements for pronunciation visualizations including\n * pitch accent text, graphs, and downstep position notation.\n */\nexport class PronunciationGenerator {\n private _document: Document;\n\n /**\n * Creates a new PronunciationGenerator.\n * @param doc - The Document object to use for creating DOM elements.\n */\n constructor(doc: Document) {\n this._document = doc;\n }\n\n /**\n * Creates a span element containing styled mora elements for pronunciation text.\n * @param morae - Array of mora strings.\n * @param pitchPositions - The pitch accent downstep position (number or HL string pattern).\n * @param nasalPositions - Array of 1-indexed mora positions that are nasalized.\n * @param devoicePositions - Array of 1-indexed mora positions that are devoiced.\n * @returns A span element with class `pronunciation-text`.\n */\n createPronunciationText(\n morae: string[],\n pitchPositions: number | string,\n nasalPositions: number[],\n devoicePositions: number[],\n ): HTMLSpanElement {\n const nasalPositionsSet = nasalPositions.length > 0 ? new Set(nasalPositions) : null;\n const devoicePositionsSet = devoicePositions.length > 0 ? new Set(devoicePositions) : null;\n const container = this._document.createElement('span');\n container.className = 'pronunciation-text';\n for (let i = 0, ii = morae.length; i < ii; ++i) {\n const i1 = i + 1;\n const mora = morae[i];\n const highPitch = isMoraPitchHigh(i, pitchPositions);\n const highPitchNext = isMoraPitchHigh(i1, pitchPositions);\n const nasal = nasalPositionsSet?.has(i1);\n const devoice = devoicePositionsSet?.has(i1);\n\n const n1 = this._document.createElement('span');\n n1.className = 'pronunciation-mora';\n n1.dataset.position = `${i}`;\n n1.dataset.pitch = highPitch ? 'high' : 'low';\n n1.dataset.pitchNext = highPitchNext ? 'high' : 'low';\n\n const characterNodes: HTMLSpanElement[] = [];\n for (const character of mora) {\n const n2 = this._document.createElement('span');\n n2.className = 'pronunciation-character';\n n2.textContent = character;\n n1.appendChild(n2);\n characterNodes.push(n2);\n }\n\n if (devoice) {\n n1.dataset.devoice = 'true';\n const n3 = this._document.createElement('span');\n n3.className = 'pronunciation-devoice-indicator';\n n1.appendChild(n3);\n }\n if (nasal && characterNodes.length > 0) {\n n1.dataset.nasal = 'true';\n\n const group = this._document.createElement('span');\n group.className = 'pronunciation-character-group';\n\n const n2 = characterNodes[0];\n const character = n2.textContent as string;\n\n const characterInfo = getKanaDiacriticInfo(character);\n if (characterInfo !== null) {\n n1.dataset.originalText = mora;\n n2.dataset.originalText = character;\n n2.textContent = characterInfo.character;\n }\n\n let n3 = this._document.createElement('span');\n n3.className = 'pronunciation-nasal-diacritic';\n n3.textContent = '\\u309a'; // Combining handakuten\n group.appendChild(n3);\n\n n3 = this._document.createElement('span');\n n3.className = 'pronunciation-nasal-indicator';\n group.appendChild(n3);\n\n (n2.parentNode as ParentNode).replaceChild(group, n2);\n group.insertBefore(n2, group.firstChild);\n }\n\n const line = this._document.createElement('span');\n line.className = 'pronunciation-mora-line';\n n1.appendChild(line);\n\n container.appendChild(n1);\n }\n return container;\n }\n\n /**\n * Creates an SVG element representing the pitch accent graph.\n * @param morae - Array of mora strings.\n * @param pitchPositions - The pitch accent downstep position (number or HL string pattern).\n * @returns An SVG element with class `pronunciation-graph`.\n */\n createPronunciationGraph(morae: string[], pitchPositions: number | string): SVGSVGElement {\n const ii = morae.length;\n\n const svgns = 'http://www.w3.org/2000/svg';\n const svg = this._document.createElementNS(svgns, 'svg') as SVGSVGElement;\n svg.setAttribute('xmlns', svgns);\n svg.setAttribute('class', 'pronunciation-graph');\n svg.setAttribute('focusable', 'false');\n svg.setAttribute('viewBox', `0 0 ${50 * (ii + 1)} 100`);\n\n if (ii <= 0) {\n return svg;\n }\n\n const path1 = this._document.createElementNS(svgns, 'path');\n svg.appendChild(path1);\n\n const path2 = this._document.createElementNS(svgns, 'path');\n svg.appendChild(path2);\n\n const pathPoints: string[] = [];\n for (let i = 0; i < ii; ++i) {\n const highPitch = isMoraPitchHigh(i, pitchPositions);\n const highPitchNext = isMoraPitchHigh(i + 1, pitchPositions);\n const x = i * 50 + 25;\n const y = highPitch ? 25 : 75;\n if (highPitch && !highPitchNext) {\n this._addGraphDotDownstep(svg, svgns, x, y);\n } else {\n this._addGraphDot(svg, svgns, x, y);\n }\n pathPoints.push(`${x} ${y}`);\n }\n\n path1.setAttribute('class', 'pronunciation-graph-line');\n path1.setAttribute('d', `M${pathPoints.join(' L')}`);\n\n pathPoints.splice(0, ii - 1);\n {\n const highPitch = isMoraPitchHigh(ii, pitchPositions);\n const x = ii * 50 + 25;\n const y = highPitch ? 25 : 75;\n this._addGraphTriangle(svg, svgns, x, y);\n pathPoints.push(`${x} ${y}`);\n }\n\n path2.setAttribute('class', 'pronunciation-graph-line-tail');\n path2.setAttribute('d', `M${pathPoints.join(' L')}`);\n\n return svg;\n }\n\n /**\n * Creates a span element showing the downstep position in bracket notation.\n * @param downstepPositions - The downstep position (number or HL string pattern).\n * @returns A span element with class `pronunciation-downstep-notation`.\n */\n createPronunciationDownstepPosition(downstepPositions: number | string): HTMLSpanElement {\n const downsteps =\n typeof downstepPositions === 'string' ? getDownstepPositions(downstepPositions) : downstepPositions;\n const downstepPositionString = `${downsteps}`;\n\n const n1 = this._document.createElement('span');\n n1.className = 'pronunciation-downstep-notation';\n n1.dataset.downstepPosition = downstepPositionString;\n\n let n2 = this._document.createElement('span');\n n2.className = 'pronunciation-downstep-notation-prefix';\n n2.textContent = '[';\n n1.appendChild(n2);\n\n n2 = this._document.createElement('span');\n n2.className = 'pronunciation-downstep-notation-number';\n n2.textContent = downstepPositionString;\n n1.appendChild(n2);\n\n n2 = this._document.createElement('span');\n n2.className = 'pronunciation-downstep-notation-suffix';\n n2.textContent = ']';\n n1.appendChild(n2);\n\n return n1;\n }\n\n /**\n * Creates a Jidoujisho-style pronunciation graph SVG.\n * @param mora - Array of mora strings.\n * @param pitchPositions - The pitch accent downstep position (number or HL string pattern).\n * @returns An SVG element.\n */\n createPronunciationGraphJJ(mora: string[], pitchPositions: number | string): SVGSVGElement {\n const patt = this._pitchValueToPattJJ(mora.length, pitchPositions);\n\n const positions = Math.max(mora.length, patt.length);\n const stepWidth = 35;\n const marginLr = 16;\n const svgWidth = Math.max(0, (positions - 1) * stepWidth + marginLr * 2);\n\n const svgns = 'http://www.w3.org/2000/svg';\n const svg = this._document.createElementNS(svgns, 'svg') as SVGSVGElement;\n svg.setAttribute('xmlns', svgns);\n svg.setAttribute('width', `${svgWidth * (3 / 5)}px`);\n svg.setAttribute('height', '45px');\n svg.setAttribute('viewBox', `0 0 ${svgWidth} 75`);\n\n if (mora.length <= 0) {\n return svg;\n }\n\n for (let i = 0; i < mora.length; i++) {\n const xCenter = marginLr + i * stepWidth;\n this._textJJ(xCenter - 11, mora[i], svgns, svg);\n }\n\n let pathType = '';\n\n const circles: Element[] = [];\n const paths: Element[] = [];\n\n let prevCenter = [-1, -1];\n for (let i = 0; i < patt.length; i++) {\n const xCenter = marginLr + i * stepWidth;\n const accent = patt[i];\n let yCenter = 0;\n if (accent === 'H') {\n yCenter = 5;\n } else if (accent === 'L') {\n yCenter = 30;\n }\n circles.push(this._circleJJ(xCenter, yCenter, i >= mora.length, svgns));\n\n if (i > 0) {\n if (prevCenter[1] === yCenter) {\n pathType = 's';\n } else if (prevCenter[1] < yCenter) {\n pathType = 'd';\n } else if (prevCenter[1] > yCenter) {\n pathType = 'u';\n }\n paths.push(this._pathJJ(prevCenter[0], prevCenter[1], pathType, stepWidth, svgns));\n }\n prevCenter = [xCenter, yCenter];\n }\n\n for (const path of paths) {\n svg.appendChild(path);\n }\n\n for (const circle of circles) {\n svg.appendChild(circle);\n }\n\n return svg;\n }\n\n // Private\n\n private _addGraphDot(container: Element, svgns: string, x: number, y: number): void {\n container.appendChild(this._createGraphCircle(svgns, 'pronunciation-graph-dot', x, y, '15'));\n }\n\n private _addGraphDotDownstep(container: Element, svgns: string, x: number, y: number): void {\n container.appendChild(this._createGraphCircle(svgns, 'pronunciation-graph-dot-downstep1', x, y, '15'));\n container.appendChild(this._createGraphCircle(svgns, 'pronunciation-graph-dot-downstep2', x, y, '5'));\n }\n\n private _addGraphTriangle(container: Element, svgns: string, x: number, y: number): void {\n const node = this._document.createElementNS(svgns, 'path');\n node.setAttribute('class', 'pronunciation-graph-triangle');\n node.setAttribute('d', 'M0 13 L15 -13 L-15 -13 Z');\n node.setAttribute('transform', `translate(${x},${y})`);\n container.appendChild(node);\n }\n\n private _createGraphCircle(svgns: string, className: string, x: number, y: number, radius: string): Element {\n const node = this._document.createElementNS(svgns, 'circle');\n node.setAttribute('class', className);\n node.setAttribute('cx', `${x}`);\n node.setAttribute('cy', `${y}`);\n node.setAttribute('r', radius);\n return node;\n }\n\n private _pitchValueToPattJJ(numberOfMora: number, pitchValue: number | string): string {\n if (typeof pitchValue === 'string') {\n return pitchValue + pitchValue[pitchValue.length - 1];\n }\n if (numberOfMora >= 1) {\n if (pitchValue === 0) {\n return `L${'H'.repeat(numberOfMora)}`;\n }\n if (pitchValue === 1) {\n return `H${'L'.repeat(numberOfMora)}`;\n }\n if (pitchValue >= 2) {\n const stepdown = pitchValue - 2;\n return `LH${'H'.repeat(stepdown)}${'L'.repeat(numberOfMora - pitchValue + 1)}`;\n }\n }\n return '';\n }\n\n private _circleJJ(x: number, y: number, o: boolean, svgns: string): Element {\n if (o) {\n const node = this._document.createElementNS(svgns, 'circle');\n node.setAttribute('r', '4');\n node.setAttribute('cx', `${x + 4}`);\n node.setAttribute('cy', `${y}`);\n node.setAttribute('stroke', 'currentColor');\n node.setAttribute('stroke-width', '2');\n node.setAttribute('fill', 'none');\n return node;\n }\n const node = this._document.createElementNS(svgns, 'circle');\n node.setAttribute('r', '5');\n node.setAttribute('cx', `${x}`);\n node.setAttribute('cy', `${y}`);\n node.setAttribute('style', 'opacity:1;fill:currentColor;');\n return node;\n }\n\n private _textJJ(x: number, mora: string, svgns: string, svg: SVGSVGElement): void {\n if (mora.length === 1) {\n const path = this._document.createElementNS(svgns, 'text');\n path.setAttribute('x', `${x}`);\n path.setAttribute('y', '67.5');\n path.setAttribute('style', 'font-size:20px;font-family:sans-serif;fill:currentColor;');\n path.textContent = mora;\n svg.appendChild(path);\n } else {\n const path1 = this._document.createElementNS(svgns, 'text');\n path1.setAttribute('x', `${x - 5}`);\n path1.setAttribute('y', '67.5');\n path1.setAttribute('style', 'font-size:20px;font-family:sans-serif;fill:currentColor;');\n path1.textContent = mora[0];\n svg.appendChild(path1);\n\n const path2 = this._document.createElementNS(svgns, 'text');\n path2.setAttribute('x', `${x + 12}`);\n path2.setAttribute('y', '67.5');\n path2.setAttribute('style', 'font-size:14px;font-family:sans-serif;fill:currentColor;');\n path2.textContent = mora[1];\n svg.appendChild(path2);\n }\n }\n\n private _pathJJ(x: number, y: number, type: string, stepWidth: number, svgns: string): Element {\n let delta = '';\n switch (type) {\n case 's':\n delta = `${stepWidth},0`;\n break;\n case 'u':\n delta = `${stepWidth},-25`;\n break;\n case 'd':\n delta = `${stepWidth},25`;\n break;\n }\n\n const path = this._document.createElementNS(svgns, 'path');\n path.setAttribute('d', `m ${x},${y} ${delta}`);\n path.setAttribute('style', 'fill:none;stroke:currentColor;stroke-width:1.5;');\n\n return path;\n }\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
1
  require('./cjk-util-Dp0ZU0sh.cjs');
2
- const require_pronunciation_generator = require('./pronunciation-generator-B8y__W7I.cjs');
2
+ const require_pronunciation_generator = require('./pronunciation-generator-CeC3LFPU.cjs');
3
3
 
4
4
  exports.PronunciationGenerator = require_pronunciation_generator.PronunciationGenerator
@@ -442,4 +442,4 @@ Object.defineProperty(exports, 'isMoraPitchHigh', {
442
442
  return isMoraPitchHigh;
443
443
  }
444
444
  });
445
- //# sourceMappingURL=pronunciation-generator-B8y__W7I.cjs.map
445
+ //# sourceMappingURL=pronunciation-generator-CeC3LFPU.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"pronunciation-generator-B8y__W7I.cjs","names":["codePoint: number","CJK_IDEOGRAPH_RANGES","moraIndex: number","pitchAccentValue: number | string","text: string","isVerbOrAdjective: boolean","pitchString: string","downsteps: number[]","morae: string[]","i: number","character: string","doc: Document","morae: string[]","pitchPositions: number | string","nasalPositions: number[]","devoicePositions: number[]","characterNodes: HTMLSpanElement[]","pathPoints: string[]","downstepPositions: number | string","mora: string[]","circles: Element[]","paths: Element[]","container: Element","svgns: string","x: number","y: number","className: string","radius: string","numberOfMora: number","pitchValue: number | string","o: boolean","node","mora: string","svg: SVGSVGElement","type: string","stepWidth: number"],"sources":["../src/render/japanese-util.ts","../src/render/pronunciation-generator.ts"],"sourcesContent":["/*\n * Copyright (C) 2024-2025 Yomitan Authors\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program. If not, see <https://www.gnu.org/licenses/>.\n */\n\n/**\n * Japanese language utility functions used by the display rendering layer.\n * These are ported from the Yomitan extension's japanese.js module.\n */\n\nimport { CJK_IDEOGRAPH_RANGES, isCodePointInRanges } from '../language/cjk-util.js';\n\nexport type PitchCategory = 'heiban' | 'atamadaka' | 'nakadaka' | 'odaka' | 'kifuku';\n\nexport type DiacriticType = 'dakuten' | 'handakuten';\n\nconst SMALL_KANA_SET = new Set('ぁぃぅぇぉゃゅょゎァィゥェォャュョヮ');\n\nconst kana =\n 'うゔ-かが-きぎ-くぐ-けげ-こご-さざ-しじ-すず-せぜ-そぞ-ただ-ちぢ-つづ-てで-とど-はばぱひびぴふぶぷへべぺほぼぽワヷ-ヰヸ-ウヴ-ヱヹ-ヲヺ-カガ-キギ-クグ-ケゲ-コゴ-サザ-シジ-スズ-セゼ-ソゾ-タダ-チヂ-ツヅ-テデ-トド-ハバパヒビピフブプヘベペホボポ';\nconst DIACRITIC_MAPPING = new Map<string, { character: string; type: DiacriticType }>();\nfor (let i = 0, ii = kana.length; i < ii; i += 3) {\n const character = kana[i];\n const dakuten = kana[i + 1];\n const handakuten = kana[i + 2];\n DIACRITIC_MAPPING.set(dakuten, { character, type: 'dakuten' });\n if (handakuten !== '-') {\n DIACRITIC_MAPPING.set(handakuten, { character, type: 'handakuten' });\n }\n}\n\n/**\n * Checks if a code point represents a CJK kanji character.\n */\nexport function isCodePointKanji(codePoint: number): boolean {\n return isCodePointInRanges(codePoint, CJK_IDEOGRAPH_RANGES);\n}\n\n/**\n * Determines whether a mora at a given index has high pitch.\n * @param moraIndex - The 0-based mora index to check.\n * @param pitchAccentValue - The pitch accent pattern (number = downstep position, string = HL pattern).\n * @returns True if the mora at the given index has high pitch.\n */\nexport function isMoraPitchHigh(moraIndex: number, pitchAccentValue: number | string): boolean {\n if (typeof pitchAccentValue === 'string') {\n return pitchAccentValue[moraIndex] === 'H';\n }\n switch (pitchAccentValue) {\n case 0:\n return moraIndex > 0;\n case 1:\n return moraIndex < 1;\n default:\n return moraIndex > 0 && moraIndex < pitchAccentValue;\n }\n}\n\n/**\n * Determines the pitch accent category for a word.\n * @param text - The reading text.\n * @param pitchAccentValue - The pitch accent pattern.\n * @param isVerbOrAdjective - Whether the word is a verb or adjective (not a noun).\n * @returns The pitch category, or null if it cannot be determined.\n */\nexport function getPitchCategory(\n text: string,\n pitchAccentValue: number | string,\n isVerbOrAdjective: boolean,\n): PitchCategory | null {\n const pitchAccentDownstepPosition =\n typeof pitchAccentValue === 'string' ? getDownstepPositions(pitchAccentValue)[0] : pitchAccentValue;\n if (pitchAccentDownstepPosition === 0) {\n return 'heiban';\n }\n if (isVerbOrAdjective) {\n return pitchAccentDownstepPosition > 0 ? 'kifuku' : null;\n }\n if (pitchAccentDownstepPosition === 1) {\n return 'atamadaka';\n }\n if (pitchAccentDownstepPosition > 1) {\n return pitchAccentDownstepPosition >= getKanaMoraCount(text) ? 'odaka' : 'nakadaka';\n }\n return null;\n}\n\n/**\n * Extracts downstep positions from an HL pitch string pattern.\n * @param pitchString - A string of 'H' and 'L' characters representing pitch.\n * @returns Array of downstep positions (1-indexed mora positions where pitch drops).\n */\nexport function getDownstepPositions(pitchString: string): number[] {\n const downsteps: number[] = [];\n const moraCount = pitchString.length;\n for (let i = 0; i < moraCount; i++) {\n if (i > 0 && pitchString[i - 1] === 'H' && pitchString[i] === 'L') {\n downsteps.push(i);\n }\n }\n if (downsteps.length === 0) {\n downsteps.push(pitchString.startsWith('L') ? 0 : -1);\n }\n return downsteps;\n}\n\n/**\n * Splits a kana text into an array of morae, combining small kana with their preceding character.\n * @param text - The kana text to split.\n * @returns Array of mora strings.\n */\nexport function getKanaMorae(text: string): string[] {\n const morae: string[] = [];\n let i: number;\n for (const c of text) {\n if (SMALL_KANA_SET.has(c) && (i = morae.length) > 0) {\n morae[i - 1] += c;\n } else {\n morae.push(c);\n }\n }\n return morae;\n}\n\n/**\n * Counts the number of morae in a kana text.\n * @param text - The kana text to count morae in.\n * @returns The number of morae.\n */\nexport function getKanaMoraCount(text: string): number {\n let moraCount = 0;\n for (const c of text) {\n if (!(SMALL_KANA_SET.has(c) && moraCount > 0)) {\n ++moraCount;\n }\n }\n return moraCount;\n}\n\n/**\n * Gets diacritic information for a kana character.\n * If the character is a dakuten or handakuten variant, returns the base character and type.\n * @param character - The kana character to check.\n * @returns An object with the base character and diacritic type, or null if not a diacritic variant.\n */\nexport function getKanaDiacriticInfo(character: string): { character: string; type: DiacriticType } | null {\n const info = DIACRITIC_MAPPING.get(character);\n return typeof info !== 'undefined' ? { character: info.character, type: info.type } : null;\n}\n","/*\n * Copyright (C) 2023-2025 Yomitan Authors\n * Copyright (C) 2021-2022 Yomichan Authors\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program. If not, see <https://www.gnu.org/licenses/>.\n */\n\nimport { getDownstepPositions, getKanaDiacriticInfo, isMoraPitchHigh } from './japanese-util.js';\n\n/**\n * Generates DOM elements for pronunciation visualizations including\n * pitch accent text, graphs, and downstep position notation.\n */\nexport class PronunciationGenerator {\n private _document: Document;\n\n /**\n * Creates a new PronunciationGenerator.\n * @param doc - The Document object to use for creating DOM elements.\n */\n constructor(doc: Document) {\n this._document = doc;\n }\n\n /**\n * Creates a span element containing styled mora elements for pronunciation text.\n * @param morae - Array of mora strings.\n * @param pitchPositions - The pitch accent downstep position (number or HL string pattern).\n * @param nasalPositions - Array of 1-indexed mora positions that are nasalized.\n * @param devoicePositions - Array of 1-indexed mora positions that are devoiced.\n * @returns A span element with class `pronunciation-text`.\n */\n createPronunciationText(\n morae: string[],\n pitchPositions: number | string,\n nasalPositions: number[],\n devoicePositions: number[],\n ): HTMLSpanElement {\n const nasalPositionsSet = nasalPositions.length > 0 ? new Set(nasalPositions) : null;\n const devoicePositionsSet = devoicePositions.length > 0 ? new Set(devoicePositions) : null;\n const container = this._document.createElement('span');\n container.className = 'pronunciation-text';\n for (let i = 0, ii = morae.length; i < ii; ++i) {\n const i1 = i + 1;\n const mora = morae[i];\n const highPitch = isMoraPitchHigh(i, pitchPositions);\n const highPitchNext = isMoraPitchHigh(i1, pitchPositions);\n const nasal = nasalPositionsSet?.has(i1);\n const devoice = devoicePositionsSet?.has(i1);\n\n const n1 = this._document.createElement('span');\n n1.className = 'pronunciation-mora';\n n1.dataset.position = `${i}`;\n n1.dataset.pitch = highPitch ? 'high' : 'low';\n n1.dataset.pitchNext = highPitchNext ? 'high' : 'low';\n\n const characterNodes: HTMLSpanElement[] = [];\n for (const character of mora) {\n const n2 = this._document.createElement('span');\n n2.className = 'pronunciation-character';\n n2.textContent = character;\n n1.appendChild(n2);\n characterNodes.push(n2);\n }\n\n if (devoice) {\n n1.dataset.devoice = 'true';\n const n3 = this._document.createElement('span');\n n3.className = 'pronunciation-devoice-indicator';\n n1.appendChild(n3);\n }\n if (nasal && characterNodes.length > 0) {\n n1.dataset.nasal = 'true';\n\n const group = this._document.createElement('span');\n group.className = 'pronunciation-character-group';\n\n const n2 = characterNodes[0];\n const character = n2.textContent as string;\n\n const characterInfo = getKanaDiacriticInfo(character);\n if (characterInfo !== null) {\n n1.dataset.originalText = mora;\n n2.dataset.originalText = character;\n n2.textContent = characterInfo.character;\n }\n\n let n3 = this._document.createElement('span');\n n3.className = 'pronunciation-nasal-diacritic';\n n3.textContent = '\\u309a'; // Combining handakuten\n group.appendChild(n3);\n\n n3 = this._document.createElement('span');\n n3.className = 'pronunciation-nasal-indicator';\n group.appendChild(n3);\n\n (n2.parentNode as ParentNode).replaceChild(group, n2);\n group.insertBefore(n2, group.firstChild);\n }\n\n const line = this._document.createElement('span');\n line.className = 'pronunciation-mora-line';\n n1.appendChild(line);\n\n container.appendChild(n1);\n }\n return container;\n }\n\n /**\n * Creates an SVG element representing the pitch accent graph.\n * @param morae - Array of mora strings.\n * @param pitchPositions - The pitch accent downstep position (number or HL string pattern).\n * @returns An SVG element with class `pronunciation-graph`.\n */\n createPronunciationGraph(morae: string[], pitchPositions: number | string): SVGSVGElement {\n const ii = morae.length;\n\n const svgns = 'http://www.w3.org/2000/svg';\n const svg = this._document.createElementNS(svgns, 'svg') as SVGSVGElement;\n svg.setAttribute('xmlns', svgns);\n svg.setAttribute('class', 'pronunciation-graph');\n svg.setAttribute('focusable', 'false');\n svg.setAttribute('viewBox', `0 0 ${50 * (ii + 1)} 100`);\n\n if (ii <= 0) {\n return svg;\n }\n\n const path1 = this._document.createElementNS(svgns, 'path');\n svg.appendChild(path1);\n\n const path2 = this._document.createElementNS(svgns, 'path');\n svg.appendChild(path2);\n\n const pathPoints: string[] = [];\n for (let i = 0; i < ii; ++i) {\n const highPitch = isMoraPitchHigh(i, pitchPositions);\n const highPitchNext = isMoraPitchHigh(i + 1, pitchPositions);\n const x = i * 50 + 25;\n const y = highPitch ? 25 : 75;\n if (highPitch && !highPitchNext) {\n this._addGraphDotDownstep(svg, svgns, x, y);\n } else {\n this._addGraphDot(svg, svgns, x, y);\n }\n pathPoints.push(`${x} ${y}`);\n }\n\n path1.setAttribute('class', 'pronunciation-graph-line');\n path1.setAttribute('d', `M${pathPoints.join(' L')}`);\n\n pathPoints.splice(0, ii - 1);\n {\n const highPitch = isMoraPitchHigh(ii, pitchPositions);\n const x = ii * 50 + 25;\n const y = highPitch ? 25 : 75;\n this._addGraphTriangle(svg, svgns, x, y);\n pathPoints.push(`${x} ${y}`);\n }\n\n path2.setAttribute('class', 'pronunciation-graph-line-tail');\n path2.setAttribute('d', `M${pathPoints.join(' L')}`);\n\n return svg;\n }\n\n /**\n * Creates a span element showing the downstep position in bracket notation.\n * @param downstepPositions - The downstep position (number or HL string pattern).\n * @returns A span element with class `pronunciation-downstep-notation`.\n */\n createPronunciationDownstepPosition(downstepPositions: number | string): HTMLSpanElement {\n const downsteps =\n typeof downstepPositions === 'string' ? getDownstepPositions(downstepPositions) : downstepPositions;\n const downstepPositionString = `${downsteps}`;\n\n const n1 = this._document.createElement('span');\n n1.className = 'pronunciation-downstep-notation';\n n1.dataset.downstepPosition = downstepPositionString;\n\n let n2 = this._document.createElement('span');\n n2.className = 'pronunciation-downstep-notation-prefix';\n n2.textContent = '[';\n n1.appendChild(n2);\n\n n2 = this._document.createElement('span');\n n2.className = 'pronunciation-downstep-notation-number';\n n2.textContent = downstepPositionString;\n n1.appendChild(n2);\n\n n2 = this._document.createElement('span');\n n2.className = 'pronunciation-downstep-notation-suffix';\n n2.textContent = ']';\n n1.appendChild(n2);\n\n return n1;\n }\n\n /**\n * Creates a Jidoujisho-style pronunciation graph SVG.\n * @param mora - Array of mora strings.\n * @param pitchPositions - The pitch accent downstep position (number or HL string pattern).\n * @returns An SVG element.\n */\n createPronunciationGraphJJ(mora: string[], pitchPositions: number | string): SVGSVGElement {\n const patt = this._pitchValueToPattJJ(mora.length, pitchPositions);\n\n const positions = Math.max(mora.length, patt.length);\n const stepWidth = 35;\n const marginLr = 16;\n const svgWidth = Math.max(0, (positions - 1) * stepWidth + marginLr * 2);\n\n const svgns = 'http://www.w3.org/2000/svg';\n const svg = this._document.createElementNS(svgns, 'svg') as SVGSVGElement;\n svg.setAttribute('xmlns', svgns);\n svg.setAttribute('width', `${svgWidth * (3 / 5)}px`);\n svg.setAttribute('height', '45px');\n svg.setAttribute('viewBox', `0 0 ${svgWidth} 75`);\n\n if (mora.length <= 0) {\n return svg;\n }\n\n for (let i = 0; i < mora.length; i++) {\n const xCenter = marginLr + i * stepWidth;\n this._textJJ(xCenter - 11, mora[i], svgns, svg);\n }\n\n let pathType = '';\n\n const circles: Element[] = [];\n const paths: Element[] = [];\n\n let prevCenter = [-1, -1];\n for (let i = 0; i < patt.length; i++) {\n const xCenter = marginLr + i * stepWidth;\n const accent = patt[i];\n let yCenter = 0;\n if (accent === 'H') {\n yCenter = 5;\n } else if (accent === 'L') {\n yCenter = 30;\n }\n circles.push(this._circleJJ(xCenter, yCenter, i >= mora.length, svgns));\n\n if (i > 0) {\n if (prevCenter[1] === yCenter) {\n pathType = 's';\n } else if (prevCenter[1] < yCenter) {\n pathType = 'd';\n } else if (prevCenter[1] > yCenter) {\n pathType = 'u';\n }\n paths.push(this._pathJJ(prevCenter[0], prevCenter[1], pathType, stepWidth, svgns));\n }\n prevCenter = [xCenter, yCenter];\n }\n\n for (const path of paths) {\n svg.appendChild(path);\n }\n\n for (const circle of circles) {\n svg.appendChild(circle);\n }\n\n return svg;\n }\n\n // Private\n\n private _addGraphDot(container: Element, svgns: string, x: number, y: number): void {\n container.appendChild(this._createGraphCircle(svgns, 'pronunciation-graph-dot', x, y, '15'));\n }\n\n private _addGraphDotDownstep(container: Element, svgns: string, x: number, y: number): void {\n container.appendChild(this._createGraphCircle(svgns, 'pronunciation-graph-dot-downstep1', x, y, '15'));\n container.appendChild(this._createGraphCircle(svgns, 'pronunciation-graph-dot-downstep2', x, y, '5'));\n }\n\n private _addGraphTriangle(container: Element, svgns: string, x: number, y: number): void {\n const node = this._document.createElementNS(svgns, 'path');\n node.setAttribute('class', 'pronunciation-graph-triangle');\n node.setAttribute('d', 'M0 13 L15 -13 L-15 -13 Z');\n node.setAttribute('transform', `translate(${x},${y})`);\n container.appendChild(node);\n }\n\n private _createGraphCircle(svgns: string, className: string, x: number, y: number, radius: string): Element {\n const node = this._document.createElementNS(svgns, 'circle');\n node.setAttribute('class', className);\n node.setAttribute('cx', `${x}`);\n node.setAttribute('cy', `${y}`);\n node.setAttribute('r', radius);\n return node;\n }\n\n private _pitchValueToPattJJ(numberOfMora: number, pitchValue: number | string): string {\n if (typeof pitchValue === 'string') {\n return pitchValue + pitchValue[pitchValue.length - 1];\n }\n if (numberOfMora >= 1) {\n if (pitchValue === 0) {\n return `L${'H'.repeat(numberOfMora)}`;\n }\n if (pitchValue === 1) {\n return `H${'L'.repeat(numberOfMora)}`;\n }\n if (pitchValue >= 2) {\n const stepdown = pitchValue - 2;\n return `LH${'H'.repeat(stepdown)}${'L'.repeat(numberOfMora - pitchValue + 1)}`;\n }\n }\n return '';\n }\n\n private _circleJJ(x: number, y: number, o: boolean, svgns: string): Element {\n if (o) {\n const node = this._document.createElementNS(svgns, 'circle');\n node.setAttribute('r', '4');\n node.setAttribute('cx', `${x + 4}`);\n node.setAttribute('cy', `${y}`);\n node.setAttribute('stroke', 'currentColor');\n node.setAttribute('stroke-width', '2');\n node.setAttribute('fill', 'none');\n return node;\n }\n const node = this._document.createElementNS(svgns, 'circle');\n node.setAttribute('r', '5');\n node.setAttribute('cx', `${x}`);\n node.setAttribute('cy', `${y}`);\n node.setAttribute('style', 'opacity:1;fill:currentColor;');\n return node;\n }\n\n private _textJJ(x: number, mora: string, svgns: string, svg: SVGSVGElement): void {\n if (mora.length === 1) {\n const path = this._document.createElementNS(svgns, 'text');\n path.setAttribute('x', `${x}`);\n path.setAttribute('y', '67.5');\n path.setAttribute('style', 'font-size:20px;font-family:sans-serif;fill:currentColor;');\n path.textContent = mora;\n svg.appendChild(path);\n } else {\n const path1 = this._document.createElementNS(svgns, 'text');\n path1.setAttribute('x', `${x - 5}`);\n path1.setAttribute('y', '67.5');\n path1.setAttribute('style', 'font-size:20px;font-family:sans-serif;fill:currentColor;');\n path1.textContent = mora[0];\n svg.appendChild(path1);\n\n const path2 = this._document.createElementNS(svgns, 'text');\n path2.setAttribute('x', `${x + 12}`);\n path2.setAttribute('y', '67.5');\n path2.setAttribute('style', 'font-size:14px;font-family:sans-serif;fill:currentColor;');\n path2.textContent = mora[1];\n svg.appendChild(path2);\n }\n }\n\n private _pathJJ(x: number, y: number, type: string, stepWidth: number, svgns: string): Element {\n let delta = '';\n switch (type) {\n case 's':\n delta = `${stepWidth},0`;\n break;\n case 'u':\n delta = `${stepWidth},-25`;\n break;\n case 'd':\n delta = `${stepWidth},25`;\n break;\n }\n\n const path = this._document.createElementNS(svgns, 'path');\n path.setAttribute('d', `m ${x},${y} ${delta}`);\n path.setAttribute('style', 'fill:none;stroke:currentColor;stroke-width:1.5;');\n\n return path;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"pronunciation-generator-CeC3LFPU.cjs","names":["codePoint: number","CJK_IDEOGRAPH_RANGES","moraIndex: number","pitchAccentValue: number | string","text: string","isVerbOrAdjective: boolean","pitchString: string","downsteps: number[]","morae: string[]","i: number","character: string","doc: Document","morae: string[]","pitchPositions: number | string","nasalPositions: number[]","devoicePositions: number[]","characterNodes: HTMLSpanElement[]","pathPoints: string[]","downstepPositions: number | string","mora: string[]","circles: Element[]","paths: Element[]","container: Element","svgns: string","x: number","y: number","className: string","radius: string","numberOfMora: number","pitchValue: number | string","o: boolean","node","mora: string","svg: SVGSVGElement","type: string","stepWidth: number"],"sources":["../src/render/japanese-util.ts","../src/render/pronunciation-generator.ts"],"sourcesContent":["/*\n * Copyright (C) 2024-2025 Yomitan Authors\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program. If not, see <https://www.gnu.org/licenses/>.\n */\n\n/**\n * Japanese language utility functions used by the display rendering layer.\n * These are ported from the Yomitan extension's japanese.js module.\n */\n\nimport { CJK_IDEOGRAPH_RANGES, isCodePointInRanges } from '../language/cjk-util.js';\n\nexport type PitchCategory = 'heiban' | 'atamadaka' | 'nakadaka' | 'odaka' | 'kifuku';\n\nexport type DiacriticType = 'dakuten' | 'handakuten';\n\nconst SMALL_KANA_SET = new Set('ぁぃぅぇぉゃゅょゎァィゥェォャュョヮ');\n\nconst kana =\n 'うゔ-かが-きぎ-くぐ-けげ-こご-さざ-しじ-すず-せぜ-そぞ-ただ-ちぢ-つづ-てで-とど-はばぱひびぴふぶぷへべぺほぼぽワヷ-ヰヸ-ウヴ-ヱヹ-ヲヺ-カガ-キギ-クグ-ケゲ-コゴ-サザ-シジ-スズ-セゼ-ソゾ-タダ-チヂ-ツヅ-テデ-トド-ハバパヒビピフブプヘベペホボポ';\nconst DIACRITIC_MAPPING = new Map<string, { character: string; type: DiacriticType }>();\nfor (let i = 0, ii = kana.length; i < ii; i += 3) {\n const character = kana[i];\n const dakuten = kana[i + 1];\n const handakuten = kana[i + 2];\n DIACRITIC_MAPPING.set(dakuten, { character, type: 'dakuten' });\n if (handakuten !== '-') {\n DIACRITIC_MAPPING.set(handakuten, { character, type: 'handakuten' });\n }\n}\n\n/**\n * Checks if a code point represents a CJK kanji character.\n */\nexport function isCodePointKanji(codePoint: number): boolean {\n return isCodePointInRanges(codePoint, CJK_IDEOGRAPH_RANGES);\n}\n\n/**\n * Determines whether a mora at a given index has high pitch.\n * @param moraIndex - The 0-based mora index to check.\n * @param pitchAccentValue - The pitch accent pattern (number = downstep position, string = HL pattern).\n * @returns True if the mora at the given index has high pitch.\n */\nexport function isMoraPitchHigh(moraIndex: number, pitchAccentValue: number | string): boolean {\n if (typeof pitchAccentValue === 'string') {\n return pitchAccentValue[moraIndex] === 'H';\n }\n switch (pitchAccentValue) {\n case 0:\n return moraIndex > 0;\n case 1:\n return moraIndex < 1;\n default:\n return moraIndex > 0 && moraIndex < pitchAccentValue;\n }\n}\n\n/**\n * Determines the pitch accent category for a word.\n * @param text - The reading text.\n * @param pitchAccentValue - The pitch accent pattern.\n * @param isVerbOrAdjective - Whether the word is a verb or adjective (not a noun).\n * @returns The pitch category, or null if it cannot be determined.\n */\nexport function getPitchCategory(\n text: string,\n pitchAccentValue: number | string,\n isVerbOrAdjective: boolean,\n): PitchCategory | null {\n const pitchAccentDownstepPosition =\n typeof pitchAccentValue === 'string' ? getDownstepPositions(pitchAccentValue)[0] : pitchAccentValue;\n if (pitchAccentDownstepPosition === 0) {\n return 'heiban';\n }\n if (isVerbOrAdjective) {\n return pitchAccentDownstepPosition > 0 ? 'kifuku' : null;\n }\n if (pitchAccentDownstepPosition === 1) {\n return 'atamadaka';\n }\n if (pitchAccentDownstepPosition > 1) {\n return pitchAccentDownstepPosition >= getKanaMoraCount(text) ? 'odaka' : 'nakadaka';\n }\n return null;\n}\n\n/**\n * Extracts downstep positions from an HL pitch string pattern.\n * @param pitchString - A string of 'H' and 'L' characters representing pitch.\n * @returns Array of downstep positions (1-indexed mora positions where pitch drops).\n */\nexport function getDownstepPositions(pitchString: string): number[] {\n const downsteps: number[] = [];\n const moraCount = pitchString.length;\n for (let i = 0; i < moraCount; i++) {\n if (i > 0 && pitchString[i - 1] === 'H' && pitchString[i] === 'L') {\n downsteps.push(i);\n }\n }\n if (downsteps.length === 0) {\n downsteps.push(pitchString.startsWith('L') ? 0 : -1);\n }\n return downsteps;\n}\n\n/**\n * Splits a kana text into an array of morae, combining small kana with their preceding character.\n * @param text - The kana text to split.\n * @returns Array of mora strings.\n */\nexport function getKanaMorae(text: string): string[] {\n const morae: string[] = [];\n let i: number;\n for (const c of text) {\n if (SMALL_KANA_SET.has(c) && (i = morae.length) > 0) {\n morae[i - 1] += c;\n } else {\n morae.push(c);\n }\n }\n return morae;\n}\n\n/**\n * Counts the number of morae in a kana text.\n * @param text - The kana text to count morae in.\n * @returns The number of morae.\n */\nexport function getKanaMoraCount(text: string): number {\n let moraCount = 0;\n for (const c of text) {\n if (!(SMALL_KANA_SET.has(c) && moraCount > 0)) {\n ++moraCount;\n }\n }\n return moraCount;\n}\n\n/**\n * Gets diacritic information for a kana character.\n * If the character is a dakuten or handakuten variant, returns the base character and type.\n * @param character - The kana character to check.\n * @returns An object with the base character and diacritic type, or null if not a diacritic variant.\n */\nexport function getKanaDiacriticInfo(character: string): { character: string; type: DiacriticType } | null {\n const info = DIACRITIC_MAPPING.get(character);\n return typeof info !== 'undefined' ? { character: info.character, type: info.type } : null;\n}\n","/*\n * Copyright (C) 2023-2025 Yomitan Authors\n * Copyright (C) 2021-2022 Yomichan Authors\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program. If not, see <https://www.gnu.org/licenses/>.\n */\n\nimport { getDownstepPositions, getKanaDiacriticInfo, isMoraPitchHigh } from './japanese-util.js';\n\n/**\n * Generates DOM elements for pronunciation visualizations including\n * pitch accent text, graphs, and downstep position notation.\n */\nexport class PronunciationGenerator {\n private _document: Document;\n\n /**\n * Creates a new PronunciationGenerator.\n * @param doc - The Document object to use for creating DOM elements.\n */\n constructor(doc: Document) {\n this._document = doc;\n }\n\n /**\n * Creates a span element containing styled mora elements for pronunciation text.\n * @param morae - Array of mora strings.\n * @param pitchPositions - The pitch accent downstep position (number or HL string pattern).\n * @param nasalPositions - Array of 1-indexed mora positions that are nasalized.\n * @param devoicePositions - Array of 1-indexed mora positions that are devoiced.\n * @returns A span element with class `pronunciation-text`.\n */\n createPronunciationText(\n morae: string[],\n pitchPositions: number | string,\n nasalPositions: number[],\n devoicePositions: number[],\n ): HTMLSpanElement {\n const nasalPositionsSet = nasalPositions.length > 0 ? new Set(nasalPositions) : null;\n const devoicePositionsSet = devoicePositions.length > 0 ? new Set(devoicePositions) : null;\n const container = this._document.createElement('span');\n container.className = 'pronunciation-text';\n for (let i = 0, ii = morae.length; i < ii; ++i) {\n const i1 = i + 1;\n const mora = morae[i];\n const highPitch = isMoraPitchHigh(i, pitchPositions);\n const highPitchNext = isMoraPitchHigh(i1, pitchPositions);\n const nasal = nasalPositionsSet?.has(i1);\n const devoice = devoicePositionsSet?.has(i1);\n\n const n1 = this._document.createElement('span');\n n1.className = 'pronunciation-mora';\n n1.dataset.position = `${i}`;\n n1.dataset.pitch = highPitch ? 'high' : 'low';\n n1.dataset.pitchNext = highPitchNext ? 'high' : 'low';\n\n const characterNodes: HTMLSpanElement[] = [];\n for (const character of mora) {\n const n2 = this._document.createElement('span');\n n2.className = 'pronunciation-character';\n n2.textContent = character;\n n1.appendChild(n2);\n characterNodes.push(n2);\n }\n\n if (devoice) {\n n1.dataset.devoice = 'true';\n const n3 = this._document.createElement('span');\n n3.className = 'pronunciation-devoice-indicator';\n n1.appendChild(n3);\n }\n if (nasal && characterNodes.length > 0) {\n n1.dataset.nasal = 'true';\n\n const group = this._document.createElement('span');\n group.className = 'pronunciation-character-group';\n\n const n2 = characterNodes[0];\n const character = n2.textContent as string;\n\n const characterInfo = getKanaDiacriticInfo(character);\n if (characterInfo !== null) {\n n1.dataset.originalText = mora;\n n2.dataset.originalText = character;\n n2.textContent = characterInfo.character;\n }\n\n let n3 = this._document.createElement('span');\n n3.className = 'pronunciation-nasal-diacritic';\n n3.textContent = '\\u309a'; // Combining handakuten\n group.appendChild(n3);\n\n n3 = this._document.createElement('span');\n n3.className = 'pronunciation-nasal-indicator';\n group.appendChild(n3);\n\n (n2.parentNode as ParentNode).replaceChild(group, n2);\n group.insertBefore(n2, group.firstChild);\n }\n\n const line = this._document.createElement('span');\n line.className = 'pronunciation-mora-line';\n n1.appendChild(line);\n\n container.appendChild(n1);\n }\n return container;\n }\n\n /**\n * Creates an SVG element representing the pitch accent graph.\n * @param morae - Array of mora strings.\n * @param pitchPositions - The pitch accent downstep position (number or HL string pattern).\n * @returns An SVG element with class `pronunciation-graph`.\n */\n createPronunciationGraph(morae: string[], pitchPositions: number | string): SVGSVGElement {\n const ii = morae.length;\n\n const svgns = 'http://www.w3.org/2000/svg';\n const svg = this._document.createElementNS(svgns, 'svg') as SVGSVGElement;\n svg.setAttribute('xmlns', svgns);\n svg.setAttribute('class', 'pronunciation-graph');\n svg.setAttribute('focusable', 'false');\n svg.setAttribute('viewBox', `0 0 ${50 * (ii + 1)} 100`);\n\n if (ii <= 0) {\n return svg;\n }\n\n const path1 = this._document.createElementNS(svgns, 'path');\n svg.appendChild(path1);\n\n const path2 = this._document.createElementNS(svgns, 'path');\n svg.appendChild(path2);\n\n const pathPoints: string[] = [];\n for (let i = 0; i < ii; ++i) {\n const highPitch = isMoraPitchHigh(i, pitchPositions);\n const highPitchNext = isMoraPitchHigh(i + 1, pitchPositions);\n const x = i * 50 + 25;\n const y = highPitch ? 25 : 75;\n if (highPitch && !highPitchNext) {\n this._addGraphDotDownstep(svg, svgns, x, y);\n } else {\n this._addGraphDot(svg, svgns, x, y);\n }\n pathPoints.push(`${x} ${y}`);\n }\n\n path1.setAttribute('class', 'pronunciation-graph-line');\n path1.setAttribute('d', `M${pathPoints.join(' L')}`);\n\n pathPoints.splice(0, ii - 1);\n {\n const highPitch = isMoraPitchHigh(ii, pitchPositions);\n const x = ii * 50 + 25;\n const y = highPitch ? 25 : 75;\n this._addGraphTriangle(svg, svgns, x, y);\n pathPoints.push(`${x} ${y}`);\n }\n\n path2.setAttribute('class', 'pronunciation-graph-line-tail');\n path2.setAttribute('d', `M${pathPoints.join(' L')}`);\n\n return svg;\n }\n\n /**\n * Creates a span element showing the downstep position in bracket notation.\n * @param downstepPositions - The downstep position (number or HL string pattern).\n * @returns A span element with class `pronunciation-downstep-notation`.\n */\n createPronunciationDownstepPosition(downstepPositions: number | string): HTMLSpanElement {\n const downsteps =\n typeof downstepPositions === 'string' ? getDownstepPositions(downstepPositions) : downstepPositions;\n const downstepPositionString = `${downsteps}`;\n\n const n1 = this._document.createElement('span');\n n1.className = 'pronunciation-downstep-notation';\n n1.dataset.downstepPosition = downstepPositionString;\n\n let n2 = this._document.createElement('span');\n n2.className = 'pronunciation-downstep-notation-prefix';\n n2.textContent = '[';\n n1.appendChild(n2);\n\n n2 = this._document.createElement('span');\n n2.className = 'pronunciation-downstep-notation-number';\n n2.textContent = downstepPositionString;\n n1.appendChild(n2);\n\n n2 = this._document.createElement('span');\n n2.className = 'pronunciation-downstep-notation-suffix';\n n2.textContent = ']';\n n1.appendChild(n2);\n\n return n1;\n }\n\n /**\n * Creates a Jidoujisho-style pronunciation graph SVG.\n * @param mora - Array of mora strings.\n * @param pitchPositions - The pitch accent downstep position (number or HL string pattern).\n * @returns An SVG element.\n */\n createPronunciationGraphJJ(mora: string[], pitchPositions: number | string): SVGSVGElement {\n const patt = this._pitchValueToPattJJ(mora.length, pitchPositions);\n\n const positions = Math.max(mora.length, patt.length);\n const stepWidth = 35;\n const marginLr = 16;\n const svgWidth = Math.max(0, (positions - 1) * stepWidth + marginLr * 2);\n\n const svgns = 'http://www.w3.org/2000/svg';\n const svg = this._document.createElementNS(svgns, 'svg') as SVGSVGElement;\n svg.setAttribute('xmlns', svgns);\n svg.setAttribute('width', `${svgWidth * (3 / 5)}px`);\n svg.setAttribute('height', '45px');\n svg.setAttribute('viewBox', `0 0 ${svgWidth} 75`);\n\n if (mora.length <= 0) {\n return svg;\n }\n\n for (let i = 0; i < mora.length; i++) {\n const xCenter = marginLr + i * stepWidth;\n this._textJJ(xCenter - 11, mora[i], svgns, svg);\n }\n\n let pathType = '';\n\n const circles: Element[] = [];\n const paths: Element[] = [];\n\n let prevCenter = [-1, -1];\n for (let i = 0; i < patt.length; i++) {\n const xCenter = marginLr + i * stepWidth;\n const accent = patt[i];\n let yCenter = 0;\n if (accent === 'H') {\n yCenter = 5;\n } else if (accent === 'L') {\n yCenter = 30;\n }\n circles.push(this._circleJJ(xCenter, yCenter, i >= mora.length, svgns));\n\n if (i > 0) {\n if (prevCenter[1] === yCenter) {\n pathType = 's';\n } else if (prevCenter[1] < yCenter) {\n pathType = 'd';\n } else if (prevCenter[1] > yCenter) {\n pathType = 'u';\n }\n paths.push(this._pathJJ(prevCenter[0], prevCenter[1], pathType, stepWidth, svgns));\n }\n prevCenter = [xCenter, yCenter];\n }\n\n for (const path of paths) {\n svg.appendChild(path);\n }\n\n for (const circle of circles) {\n svg.appendChild(circle);\n }\n\n return svg;\n }\n\n // Private\n\n private _addGraphDot(container: Element, svgns: string, x: number, y: number): void {\n container.appendChild(this._createGraphCircle(svgns, 'pronunciation-graph-dot', x, y, '15'));\n }\n\n private _addGraphDotDownstep(container: Element, svgns: string, x: number, y: number): void {\n container.appendChild(this._createGraphCircle(svgns, 'pronunciation-graph-dot-downstep1', x, y, '15'));\n container.appendChild(this._createGraphCircle(svgns, 'pronunciation-graph-dot-downstep2', x, y, '5'));\n }\n\n private _addGraphTriangle(container: Element, svgns: string, x: number, y: number): void {\n const node = this._document.createElementNS(svgns, 'path');\n node.setAttribute('class', 'pronunciation-graph-triangle');\n node.setAttribute('d', 'M0 13 L15 -13 L-15 -13 Z');\n node.setAttribute('transform', `translate(${x},${y})`);\n container.appendChild(node);\n }\n\n private _createGraphCircle(svgns: string, className: string, x: number, y: number, radius: string): Element {\n const node = this._document.createElementNS(svgns, 'circle');\n node.setAttribute('class', className);\n node.setAttribute('cx', `${x}`);\n node.setAttribute('cy', `${y}`);\n node.setAttribute('r', radius);\n return node;\n }\n\n private _pitchValueToPattJJ(numberOfMora: number, pitchValue: number | string): string {\n if (typeof pitchValue === 'string') {\n return pitchValue + pitchValue[pitchValue.length - 1];\n }\n if (numberOfMora >= 1) {\n if (pitchValue === 0) {\n return `L${'H'.repeat(numberOfMora)}`;\n }\n if (pitchValue === 1) {\n return `H${'L'.repeat(numberOfMora)}`;\n }\n if (pitchValue >= 2) {\n const stepdown = pitchValue - 2;\n return `LH${'H'.repeat(stepdown)}${'L'.repeat(numberOfMora - pitchValue + 1)}`;\n }\n }\n return '';\n }\n\n private _circleJJ(x: number, y: number, o: boolean, svgns: string): Element {\n if (o) {\n const node = this._document.createElementNS(svgns, 'circle');\n node.setAttribute('r', '4');\n node.setAttribute('cx', `${x + 4}`);\n node.setAttribute('cy', `${y}`);\n node.setAttribute('stroke', 'currentColor');\n node.setAttribute('stroke-width', '2');\n node.setAttribute('fill', 'none');\n return node;\n }\n const node = this._document.createElementNS(svgns, 'circle');\n node.setAttribute('r', '5');\n node.setAttribute('cx', `${x}`);\n node.setAttribute('cy', `${y}`);\n node.setAttribute('style', 'opacity:1;fill:currentColor;');\n return node;\n }\n\n private _textJJ(x: number, mora: string, svgns: string, svg: SVGSVGElement): void {\n if (mora.length === 1) {\n const path = this._document.createElementNS(svgns, 'text');\n path.setAttribute('x', `${x}`);\n path.setAttribute('y', '67.5');\n path.setAttribute('style', 'font-size:20px;font-family:sans-serif;fill:currentColor;');\n path.textContent = mora;\n svg.appendChild(path);\n } else {\n const path1 = this._document.createElementNS(svgns, 'text');\n path1.setAttribute('x', `${x - 5}`);\n path1.setAttribute('y', '67.5');\n path1.setAttribute('style', 'font-size:20px;font-family:sans-serif;fill:currentColor;');\n path1.textContent = mora[0];\n svg.appendChild(path1);\n\n const path2 = this._document.createElementNS(svgns, 'text');\n path2.setAttribute('x', `${x + 12}`);\n path2.setAttribute('y', '67.5');\n path2.setAttribute('style', 'font-size:14px;font-family:sans-serif;fill:currentColor;');\n path2.textContent = mora[1];\n svg.appendChild(path2);\n }\n }\n\n private _pathJJ(x: number, y: number, type: string, stepWidth: number, svgns: string): Element {\n let delta = '';\n switch (type) {\n case 's':\n delta = `${stepWidth},0`;\n break;\n case 'u':\n delta = `${stepWidth},-25`;\n break;\n case 'd':\n delta = `${stepWidth},25`;\n break;\n }\n\n const path = this._document.createElementNS(svgns, 'path');\n path.setAttribute('d', `m ${x},${y} ${delta}`);\n path.setAttribute('style', 'fill:none;stroke:currentColor;stroke-width:1.5;');\n\n return path;\n }\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
1
  import "./cjk-util-DubXBGDG.js";
2
- import { PronunciationGenerator } from "./pronunciation-generator-cNtAQi5s.js";
2
+ import { PronunciationGenerator } from "./pronunciation-generator-BXcwS3By.js";
3
3
 
4
4
  export { PronunciationGenerator };
package/dist/render.cjs CHANGED
@@ -1,12 +1,12 @@
1
1
  "use strict";
2
2
  require('./cjk-util-Dp0ZU0sh.cjs');
3
- require('./japanese-BVV1Ctk-.cjs');
4
- require('./dictionary-data-util-BY_72f3u.cjs');
5
- require('./furigana-BnY7-dJ-.cjs');
6
- require('./text-utilities-CFDC9Bkr.cjs');
7
- const require_display_generator = require('./display-generator-BhV_MOD1.cjs');
8
- const require_pronunciation_generator = require('./pronunciation-generator-B8y__W7I.cjs');
9
- const require_structured_content_generator = require('./structured-content-generator-C5Hhaurz.cjs');
3
+ require('./japanese-C83fmEfb.cjs');
4
+ require('./dictionary-data-util-DmLJMtGc.cjs');
5
+ require('./furigana-SZuBaUyl.cjs');
6
+ require('./text-utilities-CTsN1Bq8.cjs');
7
+ const require_display_generator = require('./display-generator-D_0chBzj.cjs');
8
+ const require_pronunciation_generator = require('./pronunciation-generator-CeC3LFPU.cjs');
9
+ const require_structured_content_generator = require('./structured-content-generator-CokLKgrb.cjs');
10
10
 
11
11
  //#region src/render/content-manager.ts
12
12
  /**
@@ -2779,6 +2779,91 @@ button.footer-notification-close-button {
2779
2779
  */
2780
2780
  const DISPLAY_CSS = `${DISPLAY_BASE_CSS}\n${STRUCTURED_CONTENT_CSS}\n${PRONUNCIATION_CSS}`;
2781
2781
 
2782
+ //#endregion
2783
+ //#region src/render/popup-theme.ts
2784
+ /**
2785
+ * Resolves popup theme modes into a concrete light/dark theme value.
2786
+ * Mirrors the extension behavior used by ThemeController for popup content.
2787
+ */
2788
+ function resolvePopupTheme(options = {}) {
2789
+ const themeRaw = options.theme ?? "site";
2790
+ const siteOverride = options.siteOverride ?? false;
2791
+ const view = _getView(options.document);
2792
+ const browserTheme = options.browserTheme ?? _computeBrowserTheme(view);
2793
+ const siteTheme = options.siteTheme ?? _computeSiteTheme(options.document, view);
2794
+ const theme = _resolveThemeValue(themeRaw, siteTheme, browserTheme, siteOverride);
2795
+ return {
2796
+ theme,
2797
+ siteTheme,
2798
+ browserTheme,
2799
+ themeRaw
2800
+ };
2801
+ }
2802
+ /**
2803
+ * Applies resolved popup theme attributes to a document element.
2804
+ */
2805
+ function applyPopupTheme(documentElement, options = {}) {
2806
+ const resolved = resolvePopupTheme({
2807
+ ...options,
2808
+ document: options.document ?? documentElement.ownerDocument
2809
+ });
2810
+ const data = documentElement.dataset;
2811
+ data.theme = resolved.theme;
2812
+ data.siteTheme = resolved.siteTheme;
2813
+ data.browserTheme = resolved.browserTheme;
2814
+ data.themeRaw = resolved.themeRaw;
2815
+ return resolved;
2816
+ }
2817
+ function _resolveThemeValue(theme, computedSiteTheme, browserTheme, siteOverride) {
2818
+ switch (theme) {
2819
+ case "site": return siteOverride ? browserTheme : computedSiteTheme;
2820
+ case "browser": return browserTheme;
2821
+ default: return theme;
2822
+ }
2823
+ }
2824
+ function _computeBrowserTheme(view) {
2825
+ if (view === null || typeof view.matchMedia !== "function") return "light";
2826
+ return view.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
2827
+ }
2828
+ function _computeSiteTheme(doc, view) {
2829
+ if (view === null || typeof view.getComputedStyle !== "function" || typeof doc === "undefined") return "light";
2830
+ const color = [
2831
+ 255,
2832
+ 255,
2833
+ 255
2834
+ ];
2835
+ const { documentElement, body } = doc;
2836
+ if (documentElement !== null) _addColor(color, view.getComputedStyle(documentElement).backgroundColor);
2837
+ if (body !== null) _addColor(color, view.getComputedStyle(body).backgroundColor);
2838
+ return color[0] < 128 && color[1] < 128 && color[2] < 128 ? "dark" : "light";
2839
+ }
2840
+ function _getView(doc) {
2841
+ if (typeof doc?.defaultView !== "undefined" && doc.defaultView !== null) return doc.defaultView;
2842
+ if (typeof window !== "undefined") return window;
2843
+ return null;
2844
+ }
2845
+ function _addColor(target, cssColor) {
2846
+ if (typeof cssColor !== "string") return;
2847
+ const color = _getColorInfo(cssColor);
2848
+ if (color === null) return;
2849
+ const a = color[3];
2850
+ if (a <= 0) return;
2851
+ const aInv = 1 - a;
2852
+ for (let i = 0; i < 3; ++i) target[i] = target[i] * aInv + color[i] * a;
2853
+ }
2854
+ function _getColorInfo(cssColor) {
2855
+ const m = /^\s*rgba?\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*([\d.]+)\s*)?\)\s*$/.exec(cssColor);
2856
+ if (m === null) return null;
2857
+ const alphaRaw = m[4];
2858
+ const alpha = alphaRaw ? Math.max(0, Math.min(1, Number.parseFloat(alphaRaw))) : 1;
2859
+ return [
2860
+ Number.parseInt(m[1], 10),
2861
+ Number.parseInt(m[2], 10),
2862
+ Number.parseInt(m[3], 10),
2863
+ alpha
2864
+ ];
2865
+ }
2866
+
2782
2867
  //#endregion
2783
2868
  //#region src/render/display-render-preset.ts
2784
2869
  /**
@@ -2808,8 +2893,9 @@ const EXTENSION_DISPLAY_DATASET_DEFAULTS = {
2808
2893
  * Applies extension-equivalent rendering defaults to an HTML element dataset.
2809
2894
  * Typically this should be called with `document.documentElement`.
2810
2895
  */
2811
- function applyExtensionDisplayDefaults(documentElement) {
2896
+ function applyExtensionDisplayDefaults(documentElement, options) {
2812
2897
  for (const [key, value] of Object.entries(EXTENSION_DISPLAY_DATASET_DEFAULTS)) documentElement.dataset[key] = value;
2898
+ if (typeof options?.popupTheme !== "undefined") applyPopupTheme(documentElement, options.popupTheme);
2813
2899
  }
2814
2900
 
2815
2901
  //#endregion
@@ -2826,6 +2912,7 @@ exports.StructuredContentGenerator = require_structured_content_generator.Struct
2826
2912
  exports.addScopeToCss = addScopeToCss
2827
2913
  exports.addScopeToCssLegacy = addScopeToCssLegacy
2828
2914
  exports.applyExtensionDisplayDefaults = applyExtensionDisplayDefaults
2915
+ exports.applyPopupTheme = applyPopupTheme
2829
2916
  exports.getDownstepPositions = require_pronunciation_generator.getDownstepPositions
2830
2917
  exports.getKanaDiacriticInfo = require_pronunciation_generator.getKanaDiacriticInfo
2831
2918
  exports.getKanaMoraCount = require_pronunciation_generator.getKanaMoraCount
@@ -2833,5 +2920,6 @@ exports.getKanaMorae = require_pronunciation_generator.getKanaMorae
2833
2920
  exports.getPitchCategory = require_pronunciation_generator.getPitchCategory
2834
2921
  exports.isCodePointKanji = require_pronunciation_generator.isCodePointKanji
2835
2922
  exports.isMoraPitchHigh = require_pronunciation_generator.isMoraPitchHigh
2923
+ exports.resolvePopupTheme = resolvePopupTheme
2836
2924
  exports.sanitizeCSS = sanitizeCSS
2837
2925
  //# sourceMappingURL=render.cjs.map