yomitan-core 0.1.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 (207) hide show
  1. package/README.md +485 -0
  2. package/dist/anki-connect-BQyCGW3O.cjs +513 -0
  3. package/dist/anki-connect-BQyCGW3O.cjs.map +1 -0
  4. package/dist/anki-connect-CPPuhyiQ.js +6 -0
  5. package/dist/anki-connect-DbrQHphS.js +495 -0
  6. package/dist/anki-connect-DbrQHphS.js.map +1 -0
  7. package/dist/anki-connect-DcheJrp-.cjs +6 -0
  8. package/dist/anki.cjs +1758 -0
  9. package/dist/anki.cjs.map +1 -0
  10. package/dist/anki.d.cts +751 -0
  11. package/dist/anki.d.cts.map +1 -0
  12. package/dist/anki.d.ts +751 -0
  13. package/dist/anki.d.ts.map +1 -0
  14. package/dist/anki.js +1751 -0
  15. package/dist/anki.js.map +1 -0
  16. package/dist/audio-D9DvYyB7.d.cts +48 -0
  17. package/dist/audio-D9DvYyB7.d.cts.map +1 -0
  18. package/dist/audio-DQulUkDM.d.ts +48 -0
  19. package/dist/audio-DQulUkDM.d.ts.map +1 -0
  20. package/dist/audio-url-generator-BXvQaqUi.cjs +4 -0
  21. package/dist/audio-url-generator-Dy2hb2Mm.cjs +414 -0
  22. package/dist/audio-url-generator-Dy2hb2Mm.cjs.map +1 -0
  23. package/dist/audio-url-generator-Qi0rfzHz.js +4 -0
  24. package/dist/audio-url-generator-pFQAB5Nb.js +390 -0
  25. package/dist/audio-url-generator-pFQAB5Nb.js.map +1 -0
  26. package/dist/audio.cjs +7 -0
  27. package/dist/audio.d.cts +86 -0
  28. package/dist/audio.d.cts.map +1 -0
  29. package/dist/audio.d.ts +86 -0
  30. package/dist/audio.d.ts.map +1 -0
  31. package/dist/audio.js +4 -0
  32. package/dist/batch-processor-BR-gB3H3.js +84 -0
  33. package/dist/batch-processor-BR-gB3H3.js.map +1 -0
  34. package/dist/batch-processor-CSF1acTw.cjs +3 -0
  35. package/dist/batch-processor-DFqM_L-_.cjs +91 -0
  36. package/dist/batch-processor-DFqM_L-_.cjs.map +1 -0
  37. package/dist/batch-processor-Quo9jUyf.js +3 -0
  38. package/dist/chunk-BCwAaXi7.cjs +31 -0
  39. package/dist/cjk-util-Dp0ZU0sh.cjs +167 -0
  40. package/dist/cjk-util-Dp0ZU0sh.cjs.map +1 -0
  41. package/dist/cjk-util-DubXBGDG.js +94 -0
  42. package/dist/cjk-util-DubXBGDG.js.map +1 -0
  43. package/dist/core-BUpclilG.d.cts +102 -0
  44. package/dist/core-BUpclilG.d.cts.map +1 -0
  45. package/dist/core-DFUj5GtA.d.ts +102 -0
  46. package/dist/core-DFUj5GtA.d.ts.map +1 -0
  47. package/dist/database.cjs +7 -0
  48. package/dist/database.d.cts +4 -0
  49. package/dist/database.d.ts +4 -0
  50. package/dist/database.js +5 -0
  51. package/dist/dictionary-D7l-qFt1.d.cts +316 -0
  52. package/dist/dictionary-D7l-qFt1.d.cts.map +1 -0
  53. package/dist/dictionary-_vzfBLWi.d.ts +316 -0
  54. package/dist/dictionary-_vzfBLWi.d.ts.map +1 -0
  55. package/dist/dictionary-data-util-CHnRdYZ9.cjs +378 -0
  56. package/dist/dictionary-data-util-CHnRdYZ9.cjs.map +1 -0
  57. package/dist/dictionary-data-util-CfOLfEDE.js +323 -0
  58. package/dist/dictionary-data-util-CfOLfEDE.js.map +1 -0
  59. package/dist/dictionary-database-BDC2f9zc.d.ts +58 -0
  60. package/dist/dictionary-database-BDC2f9zc.d.ts.map +1 -0
  61. package/dist/dictionary-database-CU4TsvCC.js +393 -0
  62. package/dist/dictionary-database-CU4TsvCC.js.map +1 -0
  63. package/dist/dictionary-database-DsOi04Sg.d.cts +58 -0
  64. package/dist/dictionary-database-DsOi04Sg.d.cts.map +1 -0
  65. package/dist/dictionary-database-lvFvftnO.cjs +412 -0
  66. package/dist/dictionary-database-lvFvftnO.cjs.map +1 -0
  67. package/dist/dictionary-importer-BkQQSBhm.d.ts +237 -0
  68. package/dist/dictionary-importer-BkQQSBhm.d.ts.map +1 -0
  69. package/dist/dictionary-importer-Cen1z6co.js +1821 -0
  70. package/dist/dictionary-importer-Cen1z6co.js.map +1 -0
  71. package/dist/dictionary-importer-DYmmWmcX.cjs +8 -0
  72. package/dist/dictionary-importer-Da3AuTZw.d.cts +237 -0
  73. package/dist/dictionary-importer-Da3AuTZw.d.cts.map +1 -0
  74. package/dist/dictionary-importer-Dhn75iZ4.cjs +1834 -0
  75. package/dist/dictionary-importer-Dhn75iZ4.cjs.map +1 -0
  76. package/dist/dictionary-importer-xWkel0h-.js +8 -0
  77. package/dist/dictionary-update-checker-BNE4pGTx.js +4 -0
  78. package/dist/dictionary-update-checker-Byjvifd2.cjs +75 -0
  79. package/dist/dictionary-update-checker-Byjvifd2.cjs.map +1 -0
  80. package/dist/dictionary-update-checker-YdpalZ41.cjs +4 -0
  81. package/dist/dictionary-update-checker-kKukiovj.js +69 -0
  82. package/dist/dictionary-update-checker-kKukiovj.js.map +1 -0
  83. package/dist/display-generator-BGVWiI0t.js +746 -0
  84. package/dist/display-generator-BGVWiI0t.js.map +1 -0
  85. package/dist/display-generator-BMQmG5Ov.cjs +9 -0
  86. package/dist/display-generator-BxZ7mBjP.js +9 -0
  87. package/dist/display-generator-DyP-HNzP.cjs +758 -0
  88. package/dist/display-generator-DyP-HNzP.cjs.map +1 -0
  89. package/dist/errors-BSezaJwm.cjs +35 -0
  90. package/dist/errors-BSezaJwm.cjs.map +1 -0
  91. package/dist/errors-DuuDSO5N.js +22 -0
  92. package/dist/errors-DuuDSO5N.js.map +1 -0
  93. package/dist/frequency-ranking-BXjfhhUQ.js +3 -0
  94. package/dist/frequency-ranking-Cx1kkIrw.cjs +3 -0
  95. package/dist/frequency-ranking-DEJMTMdg.js +159 -0
  96. package/dist/frequency-ranking-DEJMTMdg.js.map +1 -0
  97. package/dist/frequency-ranking-DVYxTXN-.cjs +166 -0
  98. package/dist/frequency-ranking-DVYxTXN-.cjs.map +1 -0
  99. package/dist/furigana-5HK97CY8.js +4 -0
  100. package/dist/furigana-9bBI9-qe.d.ts +47 -0
  101. package/dist/furigana-9bBI9-qe.d.ts.map +1 -0
  102. package/dist/furigana-B3-0y231.js +471 -0
  103. package/dist/furigana-B3-0y231.js.map +1 -0
  104. package/dist/furigana-CjOhzvZt.d.cts +47 -0
  105. package/dist/furigana-CjOhzvZt.d.cts.map +1 -0
  106. package/dist/furigana-DpZLcues.cjs +609 -0
  107. package/dist/furigana-DpZLcues.cjs.map +1 -0
  108. package/dist/furigana-h3v2ub4-.cjs +4 -0
  109. package/dist/import.cjs +12 -0
  110. package/dist/import.d.cts +107 -0
  111. package/dist/import.d.cts.map +1 -0
  112. package/dist/import.d.ts +107 -0
  113. package/dist/import.d.ts.map +1 -0
  114. package/dist/import.js +9 -0
  115. package/dist/index.cjs +275 -0
  116. package/dist/index.cjs.map +1 -0
  117. package/dist/index.d.cts +211 -0
  118. package/dist/index.d.cts.map +1 -0
  119. package/dist/index.d.ts +211 -0
  120. package/dist/index.d.ts.map +1 -0
  121. package/dist/index.js +238 -0
  122. package/dist/index.js.map +1 -0
  123. package/dist/json-DGd-cunA.js +17 -0
  124. package/dist/json-DGd-cunA.js.map +1 -0
  125. package/dist/json-DKWp-B7Y.cjs +30 -0
  126. package/dist/json-DKWp-B7Y.cjs.map +1 -0
  127. package/dist/language-KN_u-nTR.d.ts +104 -0
  128. package/dist/language-KN_u-nTR.d.ts.map +1 -0
  129. package/dist/language-xAbQxgXc.d.cts +104 -0
  130. package/dist/language-xAbQxgXc.d.cts.map +1 -0
  131. package/dist/language.cjs +15626 -0
  132. package/dist/language.cjs.map +1 -0
  133. package/dist/language.d.cts +959 -0
  134. package/dist/language.d.cts.map +1 -0
  135. package/dist/language.d.ts +959 -0
  136. package/dist/language.d.ts.map +1 -0
  137. package/dist/language.js +15522 -0
  138. package/dist/language.js.map +1 -0
  139. package/dist/log-D8KtR3aP.cjs +67 -0
  140. package/dist/log-D8KtR3aP.cjs.map +1 -0
  141. package/dist/log-hgSll-dS.js +60 -0
  142. package/dist/log-hgSll-dS.js.map +1 -0
  143. package/dist/lookup.cjs +13 -0
  144. package/dist/lookup.d.cts +161 -0
  145. package/dist/lookup.d.cts.map +1 -0
  146. package/dist/lookup.d.ts +161 -0
  147. package/dist/lookup.d.ts.map +1 -0
  148. package/dist/lookup.js +10 -0
  149. package/dist/media-loader-BABA_E4W.js +3 -0
  150. package/dist/media-loader-Ce9cuANS.cjs +21 -0
  151. package/dist/media-loader-Ce9cuANS.cjs.map +1 -0
  152. package/dist/media-loader-qRti-Q6h.js +14 -0
  153. package/dist/media-loader-qRti-Q6h.js.map +1 -0
  154. package/dist/media-loader-xlUGaJrx.cjs +3 -0
  155. package/dist/multi-language-transformer-AlxOM6b3.js +637 -0
  156. package/dist/multi-language-transformer-AlxOM6b3.js.map +1 -0
  157. package/dist/multi-language-transformer-MdbQBBOt.cjs +685 -0
  158. package/dist/multi-language-transformer-MdbQBBOt.cjs.map +1 -0
  159. package/dist/multi-language-transformer-SEhcJXEB.d.ts +63 -0
  160. package/dist/multi-language-transformer-SEhcJXEB.d.ts.map +1 -0
  161. package/dist/multi-language-transformer-Ul9mbRce.d.cts +63 -0
  162. package/dist/multi-language-transformer-Ul9mbRce.d.cts.map +1 -0
  163. package/dist/pronunciation-generator-BtBc4q_V.js +397 -0
  164. package/dist/pronunciation-generator-BtBc4q_V.js.map +1 -0
  165. package/dist/pronunciation-generator-CBYdXYou.js +4 -0
  166. package/dist/pronunciation-generator-CFbZlf5J.cjs +445 -0
  167. package/dist/pronunciation-generator-CFbZlf5J.cjs.map +1 -0
  168. package/dist/pronunciation-generator-DOz9hEuk.cjs +4 -0
  169. package/dist/render.cjs +2796 -0
  170. package/dist/render.cjs.map +1 -0
  171. package/dist/render.d.cts +424 -0
  172. package/dist/render.d.cts.map +1 -0
  173. package/dist/render.d.ts +424 -0
  174. package/dist/render.d.ts.map +1 -0
  175. package/dist/render.js +2777 -0
  176. package/dist/render.js.map +1 -0
  177. package/dist/sentence-parser-BPAJNzqW.js +126 -0
  178. package/dist/sentence-parser-BPAJNzqW.js.map +1 -0
  179. package/dist/sentence-parser-BVIOI64h.cjs +132 -0
  180. package/dist/sentence-parser-BVIOI64h.cjs.map +1 -0
  181. package/dist/sentence-parser-BoHO3cHn.js +5 -0
  182. package/dist/sentence-parser-DQVLSW0z.cjs +5 -0
  183. package/dist/structured-content-generator-BtOApkTW.cjs +4 -0
  184. package/dist/structured-content-generator-Bx62RYa8.js +4 -0
  185. package/dist/structured-content-generator-CLnybumI.js +276 -0
  186. package/dist/structured-content-generator-CLnybumI.js.map +1 -0
  187. package/dist/structured-content-generator-DrwkB0-k.cjs +282 -0
  188. package/dist/structured-content-generator-DrwkB0-k.cjs.map +1 -0
  189. package/dist/text-utilities-B7PIythe.js +8 -0
  190. package/dist/text-utilities-B7PIythe.js.map +1 -0
  191. package/dist/text-utilities-Del2Ivkg.cjs +15 -0
  192. package/dist/text-utilities-Del2Ivkg.cjs.map +1 -0
  193. package/dist/translator-CRPlPzqi.cjs +1545 -0
  194. package/dist/translator-CRPlPzqi.cjs.map +1 -0
  195. package/dist/translator-CWgG5drA.js +1539 -0
  196. package/dist/translator-CWgG5drA.js.map +1 -0
  197. package/dist/translator-CaGtJvnQ.cjs +6 -0
  198. package/dist/translator-Cc6OGxrW.d.ts +180 -0
  199. package/dist/translator-Cc6OGxrW.d.ts.map +1 -0
  200. package/dist/translator-CcA-s-W4.d.cts +180 -0
  201. package/dist/translator-CcA-s-W4.d.cts.map +1 -0
  202. package/dist/translator-CuJOTK6l.js +6 -0
  203. package/dist/utilities-C-lbZaJE.cjs +52 -0
  204. package/dist/utilities-C-lbZaJE.cjs.map +1 -0
  205. package/dist/utilities-bi3EF-q5.js +33 -0
  206. package/dist/utilities-bi3EF-q5.js.map +1 -0
  207. package/package.json +102 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.js","names":["_path: string","_dictionary: string","_mediaType: string","element: HTMLAnchorElement","href: string","_internal: boolean","css: string","scopeSelector: string","newCSSRules: string[]","newSelectors: string[]"],"sources":["../src/render/content-manager.ts","../src/render/css-util.ts","../src/render/templates/display-templates.ts","../src/render/styles/display-styles.ts","../src/render/styles/structured-content-styles.ts","../src/render/styles/pronunciation-styles.ts"],"sourcesContent":["/*\n * Copyright (C) 2023-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 * Interface for managing media content loading within dictionary entries.\n * Implementations handle loading images and other media from dictionary archives.\n */\nexport interface ContentManager {\n /**\n * Loads a media resource from a dictionary.\n * @param path - The path to the media file within the dictionary archive.\n * @param dictionary - The name of the dictionary containing the media.\n * @param mediaType - The MIME type or category of the media (e.g., 'image').\n * @returns A URL string that can be used to display the media, or empty string if unavailable.\n */\n loadMedia(path: string, dictionary: string, mediaType: string): string;\n\n /**\n * Prepares a link element for navigation.\n * @param element - The anchor element to prepare.\n * @param href - The URL to link to.\n * @param internal - Whether the link is internal to the application.\n */\n prepareLink(element: HTMLAnchorElement, href: string, internal: boolean): void;\n\n /**\n * Unloads all previously loaded media resources.\n */\n unloadAll(): void;\n}\n\n/**\n * A no-op implementation of ContentManager that returns empty values.\n * Useful for rendering dictionary entries without media support.\n */\nexport class NoOpContentManager implements ContentManager {\n loadMedia(_path: string, _dictionary: string, _mediaType: string): string {\n return '';\n }\n\n prepareLink(element: HTMLAnchorElement, href: string, _internal: boolean): void {\n element.href = href;\n }\n\n unloadAll(): void {}\n}\n","/*\n * Copyright (C) 2023-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 * DOM-dependent CSS utility functions for sanitizing and scoping CSS.\n * These require a DOM environment (browser or JSDOM/linkedom).\n */\n\n/**\n * Sanitizes a CSS string by parsing it through a CSSStyleSheet and\n * re-serializing it. This removes any invalid or potentially dangerous rules.\n * @param css - The raw CSS string to sanitize.\n * @returns The sanitized CSS string.\n */\nexport function sanitizeCSS(css: string): string {\n const sanitizer = new CSSStyleSheet();\n sanitizer.replaceSync(css);\n return Array.from(sanitizer.cssRules)\n .map((rule) => rule.cssText || '')\n .join('\\n');\n}\n\n/**\n * Wraps a CSS string inside a scope selector using CSS nesting.\n * The resulting CSS will only apply within the scope of the given selector.\n * @param css - The CSS string to scope.\n * @param scopeSelector - The CSS selector to use as the scope.\n * @returns The scoped CSS string.\n */\nexport function addScopeToCss(css: string, scopeSelector: string): string {\n return `${scopeSelector} {${css}\\n}`;\n}\n\n/**\n * Wraps a CSS string inside a scope selector using legacy (non-nesting) approach.\n * Each CSS rule's selector is prefixed with the scope selector.\n * This is compatible with older browsers that do not support CSS nesting.\n * @param css - The CSS string to scope.\n * @param scopeSelector - The CSS selector to use as the scope prefix.\n * @returns The scoped CSS string.\n */\nexport function addScopeToCssLegacy(css: string, scopeSelector: string): string {\n try {\n const stylesheet = new CSSStyleSheet();\n stylesheet.replaceSync(css);\n const newCSSRules: string[] = [];\n for (const cssRule of Array.from(stylesheet.cssRules)) {\n if (!('selectorText' in cssRule)) {\n continue;\n }\n\n const styleRule = cssRule as CSSStyleRule;\n const newSelectors: string[] = [];\n for (const selector of styleRule.selectorText.split(',')) {\n newSelectors.push(`${scopeSelector} ${selector}`);\n }\n const newRule = styleRule.cssText.replace(styleRule.selectorText, newSelectors.join(', '));\n newCSSRules.push(newRule);\n }\n stylesheet.replaceSync(newCSSRules.join('\\n'));\n return Array.from(stylesheet.cssRules)\n .map((rule) => rule.cssText || '')\n .join('\\n');\n } catch (_e) {\n return addScopeToCss(css, scopeSelector);\n }\n}\n","/*\n * Copyright (C) 2023-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 * The full HTML template string for display rendering.\n * Contains all template elements used by DisplayGenerator and HtmlTemplateCollection.\n * Sourced from Yomitan's templates-display.html.\n */\nexport const DISPLAY_TEMPLATES = `<!DOCTYPE html><html><head><title>Templates</title></head><body>\n\n<!-- Term entry -->\n<template id=\"term-entry-template\" data-remove-whitespace-text=\"true\"><div class=\"entry\" data-type=\"term\">\n <div class=\"entry-current-indicator\" title=\"Current entry\"><span class=\"entry-current-indicator-inner\"></span></div>\n <div class=\"entry-header\">\n <div class=\"actions\">\n <div class=\"note-actions-container\"></div>\n <div class=\"action-button-container\">\n <button type=\"button\" class=\"action-button\" data-action=\"play-audio\" title=\"Play audio\" data-title-default=\"Play audio\" data-menu-position=\"left below h-cover v-cover\">\n <span class=\"action-icon icon color-icon\" data-icon=\"play-audio\"></span>\n <span class=\"action-button-badge icon\" hidden></span>\n </button>\n <button type=\"button\" class=\"action-button action-button-collapsible\" data-action=\"menu\" data-menu-position=\"left below h-cover v-cover\">\n <span class=\"action-icon icon\" data-icon=\"kebab-menu\"></span>\n </button>\n </div>\n <span class=\"entry-current-indicator-icon\" title=\"Current entry\">\n <span class=\"icon color-icon\" data-icon=\"entry-current\"></span>\n </span>\n </div>\n <div class=\"headword-list\"></div>\n <div class=\"headword-list-details\">\n <div class=\"headword-list-tag-list tag-list\"></div>\n <ul class=\"inflection-rule-chains\"></ul>\n </div>\n </div>\n <div class=\"entry-body\">\n <div class=\"entry-body-section\" data-section-type=\"frequencies\">\n <div class=\"entry-body-section-content frequency-group-list\"></div>\n </div>\n <div class=\"entry-body-section\" data-section-type=\"pronunciations\">\n <ol class=\"entry-body-section-content pronunciation-group-list\"></ol>\n </div>\n <div class=\"entry-body-section\" data-section-type=\"definitions\">\n <ol class=\"entry-body-section-content definition-list\"></ol>\n </div>\n </div>\n</div></template>\n<template id=\"headword-template\" data-remove-whitespace-text=\"true\"><div class=\"headword\">\n <div class=\"headword-text-container\">\n <span class=\"headword-term-outer source-text\">\n <span class=\"headword-current-indicator\"></span>\n <span class=\"headword-term\"></span>\n </span>\n <span class=\"headword-reading-outer\">\n <span class=\"headword-reading\"></span>\n </span>\n </div>\n <div class=\"headword-details\">\n <button type=\"button\" class=\"action-button\" data-action=\"play-audio\" title=\"Play audio\" data-title-default=\"Play audio\" data-menu-position=\"right below h-cover v-cover\">\n <span class=\"action-icon icon color-icon\" data-icon=\"play-audio\"></span>\n <span class=\"action-button-badge icon\" hidden></span>\n </button>\n </div>\n</div></template>\n<template id=\"definition-item-template\" data-remove-whitespace-text=\"true\"><li class=\"definition-item\">\n <div class=\"definition-item-inner\">\n <button type=\"button\" class=\"expansion-button\"><div class=\"expansion-button-icon icon\" data-icon=\"double-down-chevron\"></div></button>\n <div class=\"definition-item-content\">\n <div class=\"definition-tag-list tag-list\"></div>\n <div class=\"definition-disambiguation-list\"></div>\n <ul class=\"gloss-list\"></ul>\n </div>\n </div>\n</li></template>\n<template id=\"definition-disambiguation-template\"><span class=\"definition-disambiguation\"></span></template>\n<template id=\"gloss-item-template\"><li class=\"gloss-item click-scannable\"><span class=\"gloss-separator\"> </span><span class=\"gloss-content\"></span></li></template>\n<template id=\"gloss-item-image-description-template\"> <span class=\"gloss-image-description\"></span></template>\n<template id=\"inflection-rule-chain-template\"><li class=\"inflection-rule-chain\"></li></template>\n<template id=\"inflection-template\"><span class=\"inflection\"></span><span class=\"inflection-separator\"> </span></template>\n\n<!-- Frequency -->\n<template id=\"frequency-group-item-template\"><span class=\"frequency-group-item\"><span class=\"tag tag-has-body frequency-group-tag\" data-category=\"frequency\"><span class=\"tag-label\"><span class=\"tag-label-content\"></span></span><span class=\"tag-body\"><span class=\"tag-body-content frequency-list\"></span></span></span></span></template>\n<template id=\"term-frequency-item-template\" data-remove-whitespace-text=\"true\"><span class=\"frequency-item\"><span class=\"tag tag-has-body frequency-tag\" data-category=\"frequency\" data-frequency-type=\"term\">\n <span class=\"tag-label\"><span class=\"tag-label-content\"></span></span>\n <span class=\"tag-body\"><span class=\"tag-body-content frequency-body\">\n <span class=\"frequency-disambiguation\"><ruby>\n <span class=\"frequency-disambiguation-term\"></span>\n <span class=\"frequency-disambiguation-separator\"></span>\n <rt class=\"frequency-disambiguation-reading\"></rt>\n </ruby></span>\n <span class=\"frequency-separator\"></span>\n <span class=\"frequency-value-list\"></span>\n </span></span>\n</span></span></template>\n<template id=\"kanji-frequency-item-template\" data-remove-whitespace-text=\"true\"><span class=\"frequency-item\"><span class=\"tag tag-has-body frequency-tag\" data-category=\"frequency\" data-frequency-type=\"kanji\">\n <span class=\"tag-label\"><span class=\"tag-label-content\"></span></span>\n <span class=\"tag-body\"><span class=\"tag-body-content frequency-body\">\n <span class=\"frequency-value-list\"></span>\n </span></span>\n</span></span></template>\n\n<!-- Pitch accent -->\n<template id=\"pronunciation-group-template\"><li class=\"pronunciation-group\"><span class=\"pronunciation-group-tag-list tag-list\"></span><ul class=\"pronunciation-list\"></ul></li></template>\n<template id=\"pronunciation-disambiguation-template\"><span class=\"pronunciation-disambiguation\"></span></template>\n<template id=\"pronunciation-template\"><li class=\"pronunciation\"><span class=\"pronunciation-tag-list tag-list\"></span><span class=\"pronunciation-disambiguation-list\"></span><span class=\"pronunciation-representation-list\"><span class=\"pronunciation-text-container\"></span><span class=\"pronunciation-downstep-notation-container\"></span><span class=\"pronunciation-graph-container\"></span></span></li></template>\n\n<!-- Kanji entry -->\n<template id=\"kanji-entry-template\" data-remove-whitespace-text=\"true\"><div class=\"entry kanji-entry\" data-type=\"kanji\">\n <div class=\"entry-current-indicator\" title=\"Current entry\"><span class=\"entry-current-indicator-inner\"></span></div>\n <div class=\"entry-header\">\n <div class=\"actions\">\n <div class=\"note-actions-container\"></div>\n <span class=\"entry-current-indicator-icon\" title=\"Current entry\">\n <span class=\"icon color-icon\" data-icon=\"entry-current\"></span>\n </span>\n <button type=\"button\" class=\"action-button action-button-collapsible\" data-action=\"menu\" data-menu-position=\"left below h-cover v-cover\">\n <span class=\"action-icon icon\" data-icon=\"kebab-menu\"></span>\n </button>\n </div>\n <div class=\"kanji-glyph-container\">\n <span class=\"headword-current-indicator\"></span>\n <div class=\"kanji-glyph source-text\"></div>\n </div>\n <div class=\"kanji-tag-list tag-list\"></div>\n </div>\n <div class=\"entry-body\">\n <div class=\"entry-body-section\" data-section-type=\"frequencies\">\n <div class=\"entry-body-section-content frequency-group-list\"></div>\n </div>\n </div>\n <div class=\"kanji-glyph-data\">\n <button type=\"button\" class=\"expansion-button\"><div class=\"expansion-button-icon icon\" data-icon=\"double-down-chevron\"></div></button>\n <table class=\"kanji-glyph-table\">\n <tbody>\n <tr>\n <th scope=\"col\">Meaning</th>\n <th scope=\"col\">Readings</th>\n <th scope=\"col\">Statistics</th>\n </tr>\n <tr>\n <td class=\"kanji-gloss-container\"><ol class=\"kanji-gloss-list\"></ol></td>\n <td class=\"kanji-readings\"><dl class=\"kanji-readings-chinese\"></dl><dl class=\"kanji-readings-japanese\"></dl></td>\n <td class=\"kanji-statistics\"></td>\n </tr>\n <tr><th scope=\"col\" colspan=\"3\">Classifications</th></tr>\n <tr><td colspan=\"3\" class=\"kanji-classifications\"></td></tr>\n <tr><th scope=\"col\" colspan=\"3\">Codepoints</th></tr>\n <tr><td colspan=\"3\" class=\"kanji-codepoints\"></td></tr>\n <tr><th scope=\"col\" colspan=\"3\">Dictionary Indices</th></tr>\n <tr><td colspan=\"3\" class=\"kanji-dictionary-indices\"></td></tr>\n </tbody>\n </table>\n </div>\n</div></template>\n<template id=\"kanji-info-table-template\"><table class=\"kanji-info-table\"><tbody class=\"kanji-info-table-body\"></tbody></table></template>\n<template id=\"kanji-info-table-item-template\"><tr class=\"kanji-info-table-item\"><th scope=\"col\" class=\"kanji-info-table-item-header\"></th><td class=\"kanji-info-table-item-value\"></td></tr></template>\n<template id=\"kanji-info-table-empty-template\"><tr class=\"kanji-info-table-item kanji-info-table-item-empty\"><td class=\"kanji-info-table-item-value-empty\">No data found</td></tr></template>\n<template id=\"kanji-gloss-item-template\"><li class=\"kanji-gloss-item\"><span class=\"kanji-gloss-content\"></span></li></template>\n<template id=\"kanji-reading-template\"><dd class=\"kanji-reading\"></dd></template>\n\n<!-- Tag -->\n<template id=\"tag-template\"><span class=\"tag\"><span class=\"tag-label\"><span class=\"tag-label-content\"></span></span></span></template>\n<template id=\"tag-with-body-template\"><span class=\"tag tag-has-body\"><span class=\"tag-label\"><span class=\"tag-label-content\"></span></span><span class=\"tag-body\"><span class=\"tag-body-content\"></span></span></span></template>\n\n<!-- Extra -->\n<template id=\"footer-notification-template\"><div class=\"footer-notification scrollbar\">\n <div class=\"footer-notification-body\"></div>\n <div class=\"footer-notification-close-button-container\">\n <button type=\"button\" class=\"footer-notification-close-button\"><span class=\"footer-notification-close-button-icon icon\" data-icon=\"cross\"></span></button>\n </div>\n</div></template>\n<template id=\"footer-notification-tag-details-template\" data-remove-whitespace-text=\"true\">\n <div class=\"tag-details\"></div>\n <div class=\"tag-details-disambiguation-list\"></div>\n</template>\n<template id=\"profile-list-item-template\"><label class=\"profile-list-item\">\n <div class=\"profile-list-item-selection\"><label class=\"radio\"><input type=\"radio\" class=\"profile-entry-is-default-radio\" name=\"profile-entry-default-radio\"><span class=\"radio-body\"><span class=\"radio-border\"></span><span class=\"radio-dot\"></span></span></label></div>\n <div class=\"profile-list-item-name\"></div>\n</label></template>\n\n</body></html>`;\n","/*\n * Copyright (C) 2023-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 * The display CSS styles from the Yomitan extension.\n * Sourced from Yomitan's ext/css/display.css.\n */\nexport const DISPLAY_CSS = `/*\n * Copyright (C) 2023-2025 Yomitan Authors\n * Copyright (C) 2016-2022 Yomichan Authors\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the entrys 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/* Variables */\n:root {\n /* Strings */\n --compact-list-separator: ' | ';\n\n --disambiguation-separator: ', ';\n --disambiguation-reading-separator: ':';\n\n --headword-separator: '\\\\3001';\n\n --inflection-separator: '\\\\00AB';\n\n /* Layout */\n --font-size-no-units: 14;\n --font-size: calc(1px * var(--font-size-no-units));\n --query-parser-font-size-no-units: 2;\n --query-parser-font-size: calc(1em * var(--query-parser-font-size-no-units));\n --h2-font-size-no-units: 1.25;\n --h2-font-size: calc(1em * var(--h2-font-size-no-units));\n\n --headword-font-size-no-units: 2;\n --headword-font-size: calc(1em * var(--headword-font-size-no-units));\n --headword-reading-font-size-no-units: 0.75;\n --headword-reading-font-size: calc(var(--headword-reading-font-size-no-units) * var(--headword-font-size));\n --headword-reading-space: 0.5em;\n --headword-list-end-space: 0.5em;\n --headword-thin-border-size: calc(1em / (var(--headword-font-size-no-units) * var(--font-size-no-units)));\n\n --line-height-no-units: 20;\n --line-height: calc(var(--line-height-no-units) / var(--font-size-no-units));\n\n --thin-border-size: calc(1em / var(--font-size-no-units));\n\n --action-button-size-no-units: 16;\n --action-button-size: calc(1em * (var(--action-button-size-no-units) / var(--font-size-no-units)));\n --action-button-padding: 0.3em;\n\n --list-margin: 0.72em;\n --content-width: 100%;\n --main-content-vertical-padding: 0em;\n --main-content-horizontal-padding: 0em;\n --entry-horizontal-padding: 0.72em;\n --entry-vertical-padding: 0.72em;\n --query-horizontal-padding: 0.72em;\n\n --sidebar-width-no-units: 40;\n --sidebar-width: calc(1em * (var(--sidebar-width-no-units) / var(--font-size-no-units)));\n --sidebar-button-height-no-units: 30;\n --sidebar-button-height: calc(1em * (var(--sidebar-button-height-no-units) / var(--font-size-no-units)));\n --sidebar-button-icon-size-no-units: 16;\n --sidebar-button-icon-size: calc(1em * (var(--sidebar-button-icon-size-no-units) / var(--font-size-no-units)));\n\n --progress-bar-height-no-units: 4;\n --progress-bar-height: calc(1em * (var(--progress-bar-height-no-units) / var(--font-size-no-units)));\n --progress-bar-active-transition-duration: 0.125s;\n --progress-bar-active-transition-start-delay: 0.0625s;\n --progress-bar-animation-duration: 2s;\n\n --entry-current-indicator-width-no-units: 4;\n --entry-current-indicator-width: calc(1em * var(--entry-current-indicator-width-no-units) / var(--font-size-no-units));\n --entry-current-indicator-transition-duration: 0.125s;\n\n --tag-height-no-units: 20;\n --tag-height: calc(1em * var(--tag-height-no-units) / var(--font-size-no-units));\n --tag-font-size-no-units: 11;\n --tag-font-size: calc(1em * var(--tag-font-size-no-units) / var(--font-size-no-units));\n --tag-border-size-no-units: 1;\n --tag-border-size: calc(1em * (var(--tag-border-size-no-units) / var(--font-size-no-units)));\n --tag-border-style: solid;\n --tag-font-weight: bold;\n --tag-border-radius: 0.25em;\n\n --list-padding1: 1.4em;\n --list-padding2: var(--list-padding1);\n\n --entry-current-indicator-triangle-size-no-units: 6;\n --entry-current-indicator-triangle-size: calc(1em * (var(--entry-current-indicator-triangle-size-no-units) / var(--font-size-no-units)));\n\n --overlay-panel-translate-distance: 4em;\n\n --disambiguation-space: 0.25em;\n\n --animation-duration: 0.125s;\n --animation-duration2: calc(2 * var(--animation-duration));\n\n --collapsible-definition-line-count: 3;\n --collapsible-kanji-glyph-data-line-count: 3;\n --kanji-glyph-table-header-height: calc((20em / var(--font-size-no-units)) + var(--kanji-glyph-table-cell-padding) * 3);\n --collapsible-definition-test-offset: 0.2em;\n --collpasible-kanji-glyph-data-test-offset: 0.2em;\n\n /* Colors */\n --background-color: #ffffff;\n --gloss-image-background-color: #eeeeee;\n --link-color: var(--accent-color);\n\n --text-color: #000000;\n --reason-text-color: var(--text-color-light3);\n\n --headword-text-color: var(--text-color);\n --headword-text-color-popular: var(--accent-color);\n --headword-text-color-rare: var(--text-color-light4);\n --headword-furigana-text-color: var(--headword-text-color);\n --headword-furigana-text-color-popular: var(--headword-text-color-popular);\n --headword-furigana-text-color-rare: var(--headword-text-color-rare);\n --headword-reading-text-color: var(--headword-furigana-text-color);\n --headword-reading-text-color-popular: var(--headword-furigana-text-color-popular);\n --headword-reading-text-color-rare: var(--headword-furigana-text-color-rare);\n --headword-kanji-text-color: var(--headword-text-color);\n --headword-kanji-text-color-popular: var(--headword-text-color-popular);\n --headword-kanji-text-color-rare: var(--headword-text-color-rare);\n --headword-kanji-border-color: var(--dark-border-color);\n --headword-kanji-border-color-popular: var(--headword-kanji-border-color);\n --headword-kanji-border-color-rare: var(--headword-kanji-border-color);\n\n --kanji-glyph-table-cell-padding: 0.36em;\n\n --light-border-color: #eeeeee;\n --medium-border-color: #dddddd;\n --dark-border-color: #777777;\n\n --tag-text-color: #ffffff;\n --tag-border-color: transparent;\n --tag-default-background-color: #8a8a91;\n --tag-name-background-color: #b6327a;\n --tag-expression-background-color: #f0ad4e;\n --tag-popular-background-color: #0275d8;\n --tag-frequent-background-color: #5bc0de;\n --tag-archaism-background-color: #d9534f;\n --tag-dictionary-background-color: #aa66cc;\n --tag-frequency-background-color: #5cb85c;\n --tag-part-of-speech-background-color: #565656;\n --tag-search-background-color: #8a8a91;\n --tag-pronunciation-dictionary-background-color: #6640be;\n\n --sidebar-background-color: #f8f9fa;\n\n --sidebar-button-background-color: transparent;\n --sidebar-button-background-color-hover: #cccccc;\n --sidebar-button-background-color-active: #aaaaaa;\n --sidebar-button-danger-background-color: transparent;\n --sidebar-button-danger-background-color-hover: #dd2222;\n --sidebar-button-danger-background-color-active: #bb2222;\n --sidebar-button-icon-color: #333333;\n --sidebar-button-disabled-icon-color: #888888;\n --sidebar-button-danger-icon-color: #ffffff;\n\n --scrollbar-thumb-color: #c1c1c1;\n --scrollbar-track-color: #f1f1f1;\n --scrollbar-inverse-thumb-color: #444444;\n --scrollbar-inverse-track-color: #2f2f2f;\n\n --progress-bar-track-color: #cccccc;\n --progress-bar-indicator-color: var(--accent-color);\n --entry-current-indicator-color: var(--accent-color);\n\n --notification-text-color: #2f2f2f;\n --notification-background-color: #f1f1f1;\n --notification-background-color-light: #e1e1e1;\n --notification-background-color-lighter: #bbbbbb;\n --notification-shadow-color: rgba(255, 255, 255, 0.25);\n\n --action-button-hover-color: #dddddd;\n --action-button-active-color: #c1c1c1;\n}\n:root[data-theme=dark] {\n /* Colors */\n --background-color: #1e1e1e;\n --gloss-image-background-color: #2f2f2f;\n --link-color: var(--accent-color);\n\n --text-color: #d4d4d4;\n --reason-text-color: var(--text-color-light3);\n\n --headword-text-color: var(--text-color);\n --headword-text-color-popular: var(--accent-color);\n --headword-text-color-rare: var(--text-color-light4);\n --headword-furigana-text-color: var(--headword-text-color);\n --headword-furigana-text-color-popular: var(--headword-text-color-popular);\n --headword-furigana-text-color-rare: var(--headword-text-color-rare);\n --headword-reading-text-color: var(--headword-furigana-text-color);\n --headword-reading-text-color-popular: var(--headword-furigana-text-color-popular);\n --headword-reading-text-color-rare: var(--headword-furigana-text-color-rare);\n --headword-kanji-border-color: var(--dark-border-color);\n\n --light-border-color: #2f2f2f;\n --medium-border-color: #3f3f3f;\n --dark-border-color: #888888;\n\n --tag-text-color: #f1f1f1;\n --tag-border-color: transparent;\n --tag-default-background-color: #69696e;\n --tag-name-background-color: #992a67;\n --tag-expression-background-color: #b07f39;\n --tag-popular-background-color: #025caa;\n --tag-frequent-background-color: #4490a7;\n --tag-archaism-background-color: #b04340;\n --tag-dictionary-background-color: #9057ad;\n --tag-frequency-background-color: #489148;\n --tag-part-of-speech-background-color: #565656;\n --tag-search-background-color: #69696e;\n --tag-pronunciation-dictionary-background-color: #6640be;\n\n --sidebar-background-color: #282828;\n\n --sidebar-button-background-color: transparent;\n --sidebar-button-background-color-hover: #3a3a3a;\n --sidebar-button-background-color-active: #5a5a5a;\n --sidebar-button-danger-background-color: transparent;\n --sidebar-button-danger-background-color-hover: #dd2222;\n --sidebar-button-danger-background-color-active: #bb2222;\n --sidebar-button-icon-color: #cccccc;\n --sidebar-button-disabled-icon-color: #777777;\n --sidebar-button-danger-icon-color: #ffffff;\n\n --scrollbar-thumb-color: #444444;\n --scrollbar-track-color: #2f2f2f;\n --scrollbar-inverse-thumb-color: #c1c1c1;\n --scrollbar-inverse-track-color: #f1f1f1;\n\n --progress-bar-track-color: #3a3a3a;\n --progress-bar-indicator-color: var(--accent-color);\n --entry-current-indicator-color: var(--accent-color);\n\n --notification-text-color: #ffffff;\n --notification-background-color: #333333;\n --notification-background-color-light: #555555;\n --notification-background-color-lighter: #666666;\n --notification-shadow-color: rgba(0, 0, 0, 0.5);\n\n --action-button-hover-color: #282828;\n --action-button-active-color: #444444;\n}\n\n\n/* Fonts */\n@font-face {\n font-family: kanji-stroke-orders;\n src: url('/data/fonts/kanji-stroke-orders.ttf');\n}\n\n\n/* General */\n:root[data-page-type=popup]:not([data-theme]),\n:root[data-page-type=popup]:not([data-theme]) body {\n background-color: transparent;\n}\nbody {\n overflow: hidden;\n}\nol, ul {\n margin-top: 0;\n margin-bottom: var(--list-padding);\n}\nh2 {\n font-size: var(--h2-font-size);\n font-weight: normal;\n margin: 0.25em 0 0;\n border-bottom: calc(1em / (var(--font-size-no-units) * var(--h2-font-size-no-units))) solid var(--light-border-color);\n}\nh3 {\n font-size: 1em;\n font-weight: bold;\n margin: 0.25em 0 0.375em;\n padding: 0;\n}\nh5 {\n font-size: calc(12em / var(--font-size-no-units));\n margin: 0;\n padding: 0;\n font-weight: normal;\n}\na {\n color: var(--link-color);\n text-decoration: underline;\n cursor: pointer;\n text-underline-offset: calc(4em / var(--font-size-no-units));\n text-decoration-thickness: calc(1em / var(--font-size-no-units));\n}\na:has(rt) {\n text-decoration: none;\n border-bottom: solid calc(1em / var(--font-size-no-units)) var(--link-color);\n}\n\n\n/* Selection */\n#content-scroll-focus {\n opacity: 0;\n margin: 0;\n padding: 0;\n outline: none;\n background-color: transparent;\n display: inline;\n width: 0;\n height: 0;\n line-height: 0;\n user-select: none;\n}\n#content-scroll-focus::-moz-focus-inner {\n border: 0;\n}\n\n\n/* Scrollbars */\n:root:not([data-theme=light]) .scrollbar {\n scrollbar-color: var(--scrollbar-thumb-color) var(--scrollbar-track-color);\n}\n:root:not([data-theme=light]) .scrollbar::-webkit-scrollbar {\n width: auto;\n}\n:root:not([data-theme=light]) .scrollbar::-webkit-scrollbar-button {\n height: 0;\n}\n:root:not([data-theme=light]) .scrollbar::-webkit-scrollbar-thumb {\n background-color: var(--scrollbar-thumb-color);\n}\n:root:not([data-theme=light]) .scrollbar::-webkit-scrollbar-track {\n background-color: var(--scrollbar-thumb-color);\n}\n:root:not([data-theme=light]) .scrollbar::-webkit-scrollbar-track-piece {\n background-color: var(--scrollbar-track-color);\n}\n:root:not([data-theme=light]) .scrollbar::-webkit-scrollbar-corner {\n background-color: var(--scrollbar-track-color);\n}\n:root .scrollbar-inverse {\n scrollbar-color: var(--scrollbar-inverse-humb-color) var(--scrollbar-inverse-track-color);\n}\n:root .scrollbar-inverse::-webkit-scrollbar {\n width: auto;\n}\n:root .scrollbar-inverse::-webkit-scrollbar-button {\n height: 0;\n}\n:root .scrollbar-inverse::-webkit-scrollbar-thumb {\n background-color: var(--scrollbar-inverse-thumb-color);\n}\n:root .scrollbar-inverse::-webkit-scrollbar-track {\n background-color: var(--scrollbar-inverse-thumb-color);\n}\n:root .scrollbar-inverse::-webkit-scrollbar-track-piece {\n background-color: var(--scrollbar-inverse-track-color);\n}\n:root .scrollbar-inverse::-webkit-scrollbar-corner {\n background-color: var(--scrollbar-inverse-track-color);\n}\n.scrollbar-spacer {\n display: inline-block;\n overflow-x: hidden;\n overflow-y: scroll;\n visibility: hidden;\n flex: 0 1 auto;\n}\n\n\n/* Main layout */\n.content {\n flex: 1 1 auto;\n position: relative;\n}\n.content-scroll {\n position: absolute;\n left: 0;\n top: 0;\n right: 0;\n bottom: 0;\n display: flex;\n flex-flow: column nowrap;\n overflow-x: hidden;\n overflow-y: scroll;\n align-items: stretch;\n justify-content: flex-start;\n}\n.content-body {\n flex: 1 1 auto;\n position: relative;\n}\n.content-body-inner {\n width: var(--content-width);\n max-width: 100%;\n box-sizing: border-box;\n margin: 0 auto;\n padding: var(--main-content-vertical-padding) var(--main-content-horizontal-padding);\n}\n.content-footer-container1 {\n display: flex;\n flex-flow: row nowrap;\n position: absolute;\n left: 0;\n right: 0;\n bottom: 0;\n max-height: 100%;\n pointer-events: none;\n z-index: 5;\n}\n.content-footer-container2 {\n display: flex;\n flex-flow: row nowrap;\n justify-content: center;\n flex: 1 1 auto;\n max-width: 100%;\n}\n.content-footer {\n width: var(--content-width);\n max-width: 100%;\n}\n.contain-overscroll {\n overscroll-behavior: contain;\n}\n\n\n/* Sidebar layout */\n.content-outer {\n width: 100%;\n height: 100%;\n display: flex;\n flex-flow: row nowrap;\n overflow: hidden;\n align-items: stretch;\n align-content: stretch;\n justify-content: center;\n}\n.content-sidebar {\n flex: 0 0 auto;\n height: 100%;\n overflow-x: hidden;\n overflow-y: auto;\n background-color: var(--sidebar-background-color);\n z-index: 10;\n position: relative;\n display: none;\n}\n:root[data-has-navigation-previous=true] .content-sidebar,\n:root[data-has-navigation-next=true] .content-sidebar,\n:root[data-popup-action-bar-visibility=always] .content-sidebar,\n:root[data-profile-panel-visible=true] .content-sidebar {\n display: block;\n}\n.content-sidebar-inner {\n display: flex;\n flex-flow: column nowrap;\n width: var(--sidebar-width);\n height: 100%;\n}\n.content-sidebar-top-pre {\n flex: 0 0 auto;\n display: flex;\n flex-flow: column nowrap;\n}\n.content-sidebar-top {\n flex: 1 1 auto;\n display: flex;\n flex-flow: column nowrap;\n}\n.content-sidebar-bottom {\n position: sticky;\n bottom: 0;\n background-color: var(--sidebar-background-color);\n display: flex;\n flex-flow: column nowrap;\n align-items: center;\n}\n:root[data-popup-action-bar-location=top] .content-outer,\n:root[data-popup-action-bar-location=bottom] .content-outer {\n flex-flow: column nowrap;\n}\n:root[data-popup-action-bar-location=top] .content-sidebar,\n:root[data-popup-action-bar-location=bottom] .content-sidebar {\n height: auto;\n width: 100%;\n}\n:root[data-popup-action-bar-location=left] .content-sidebar,\n:root[data-popup-action-bar-location=top] .content-sidebar {\n order: -1;\n}\n:root[data-popup-action-bar-location=top] .content-sidebar-inner,\n:root[data-popup-action-bar-location=bottom] .content-sidebar-inner {\n flex-flow: row nowrap;\n width: auto;\n height: var(--sidebar-button-height);\n}\n:root[data-popup-action-bar-location=top] .content-sidebar-top-pre,\n:root[data-popup-action-bar-location=bottom] .content-sidebar-top-pre {\n flex-flow: row nowrap;\n order: 1;\n}\n:root[data-popup-action-bar-location=top] .content-sidebar-top,\n:root[data-popup-action-bar-location=bottom] .content-sidebar-top {\n flex-flow: row nowrap;\n}\n:root[data-popup-action-bar-location=top] .content-sidebar-bottom,\n:root[data-popup-action-bar-location=bottom] .content-sidebar-bottom {\n flex-flow: row nowrap;\n}\n\n:root[data-popup-action-bar-location=right] #profile-name,\n:root[data-popup-action-bar-location=left] #profile-name {\n writing-mode: vertical-rl;\n text-orientation: vertical;\n letter-spacing: 2px;\n}\n\n\n/* Sidebar buttons */\nbutton.sidebar-button {\n --button-content-color: var(--sidebar-button-icon-color);\n --button-border-color: transparent;\n --button-background-color: var(--sidebar-button-background-color);\n --button-shadow: none;\n\n --button-hover-border-color: transparent;\n --button-hover-background-color: var(--sidebar-button-background-color-hover);\n --button-hover-shadow: none;\n\n --button-active-border-color: transparent;\n --button-active-background-color: var(--sidebar-button-background-color-active);\n --button-active-shadow: none;\n\n --button-disabled-content-color: var(--sidebar-button-disabled-icon-color);\n --button-disabled-border-color: transparent;\n --button-disabled-background-color: var(--sidebar-button-background-color);\n --button-disabled-shadow: none;\n\n width: 100%;\n height: var(--sidebar-button-height);\n margin: 0;\n padding: 0;\n border-style: none;\n border-width: 0;\n cursor: pointer;\n display: block;\n transition: background-color 0.125s ease-in-out;\n outline: none;\n font-size: inherit;\n border-radius: 0;\n}\n:root[data-popup-action-bar-location=top] button.sidebar-button,\n:root[data-popup-action-bar-location=bottom] button.sidebar-button {\n width: var(--sidebar-width);\n height: 100%;\n}\nbutton.sidebar-button.danger {\n --button-content-color: var(--sidebar-button-icon-color);\n --button-border-color: transparent;\n --button-background-color: var(--sidebar-button-danger-background-color);\n --button-shadow: none;\n\n --button-hover-content-color: var(--sidebar-button-danger-icon-color);\n --button-hover-border-color: transparent;\n --button-hover-background-color: var(--sidebar-button-danger-background-color-hover);\n --button-hover-shadow: none;\n\n --button-active-content-color: var(--sidebar-button-danger-icon-color);\n --button-active-border-color: transparent;\n --button-active-background-color: var(--sidebar-button-danger-background-color-active);\n --button-active-shadow: none;\n}\n.sidebar-button-icon {\n --icon-size: var(--sidebar-button-icon-size) var(--sidebar-button-icon-size);\n\n display: block;\n width: 100%;\n height: 100%;\n background-color: var(--button-current-content-color);\n transition: background-color 0.125s ease-in-out;\n}\nbutton.sidebar-button.sidebar-button-highlight {\n --button-content-color: var(--accent-color);\n --button-hover-content-color: var(--accent-color);\n --button-active-content-color: var(--accent-color);\n}\n\n\n/* Search page */\n.search-header-wrapper {\n background-color: var(--background-color);\n width: 100%;\n display: flex;\n justify-content: center;\n}\n.sticky-header {\n position: sticky;\n top: 0px;\n z-index: 1000;\n}\n#sticky-search-header {\n padding-top: 10px;\n}\n.sticky-header #query-parser-content {\n max-height: calc(var(--query-parser-font-size) * 2);\n}\n.search-header {\n width: var(--content-width);\n display: flex;\n flex-flow: column nowrap;\n max-height: 100vh;\n padding: var(--main-content-vertical-padding) var(--main-content-horizontal-padding);\n}\n#query-parser-container {\n overflow-y: auto;\n padding-left: var(--query-horizontal-padding);\n padding-right: var(--query-horizontal-padding);\n padding-bottom: 0.25em;\n border-bottom: var(--headword-thin-border-size) solid var(--light-border-color);\n}\n#query-parser-content {\n margin-top: 0.5em;\n font-size: var(--query-parser-font-size);\n white-space: pre-wrap;\n}\n#query-parser-content[data-term-spacing=true] .query-parser-term {\n margin-right: 0.2em;\n}\n\n\n/* Action buttons */\n.actions {\n display: flex;\n flex-flow: row nowrap;\n float: right;\n margin: -0.25em;\n position: relative;\n z-index: 1;\n}\n.actions::after {\n clear: both;\n content: '';\n display: block;\n}\n.note-actions-container {\n display: flex;\n flex-flow: row nowrap;\n align-items: start;\n}\n.action-button-container {\n display: flex;\n flex-direction: column;\n position: relative;\n}\n\n.note-actions-container .action-button-container::after {\n content: '';\n position: absolute;\n left: calc(50% - 0.5px);\n top: calc((var(--action-button-size) + var(--action-button-padding) * 2) * 0.5);\n bottom: calc((var(--action-button-size) + var(--action-button-padding) * 2) * 0.5);\n width: 1px;\n background: var(--accent-color);\n pointer-events: none;\n opacity: 0.25;\n z-index: -1;\n}\n\n.note-actions-container .action-button-container:first-child {\n flex-direction: row-reverse;\n}\n.note-actions-container .action-button-container:first-child::after {\n top: calc(50% - 0.5px);\n left: calc((var(--action-button-size) + var(--action-button-padding) * 2) * 0.5);\n right: calc((var(--action-button-size) + var(--action-button-padding) * 2) * 0.5);\n bottom: auto;\n height: 1px;\n width: auto;\n}\n\n.note-actions-container .action-button-container:only-child::after {\n display: none;\n}\n\nbutton.action-button {\n cursor: pointer;\n display: block;\n opacity: 1;\n border: 0;\n margin: 0;\n padding: var(--action-button-padding);\n background: transparent;\n font-size: inherit;\n box-shadow: none;\n position: relative;\n z-index: 1;\n transition:\n opacity var(--animation-duration) linear,\n visibility 0s linear 0s,\n filter var(--animation-duration) linear,\n -webkit-filter var(--animation-duration) linear,\n background-color var(--animation-duration) linear;\n}\nbutton.action-button[hidden] {\n display: block;\n visibility: hidden;\n opacity: 0;\n transition:\n opacity var(--animation-duration) linear,\n visibility 0s linear var(--animation-duration),\n filter var(--animation-duration) linear,\n -webkit-filter var(--animation-duration) linear,\n background-color var(--animation-duration) linear;\n}\nbutton.action-button-collapsible[hidden] {\n display: none;\n}\nbutton.action-button:disabled {\n pointer-events: auto;\n cursor: default;\n -webkit-filter: grayscale(100%);\n filter: grayscale(100%);\n background-color: transparent;\n}\nbutton.action-button:disabled:not([hidden]) {\n opacity: 0.25;\n}\nbutton.action-button:hover,\nbutton.action-button:focus {\n background-color: transparent;\n box-shadow: none;\n}\nbutton.action-button:focus-visible {\n background-color: var(--action-button-hover-color);\n box-shadow: none;\n}\nbutton.action-button:active:not(:disabled) {\n background-color: var(--action-button-active-color);\n box-shadow: none;\n}\n\n.icon[data-icon=view-note] { background-image: url('/images/view-note.svg'); }\n.icon[data-icon=view-note-learning] { background-image: url('/images/view-note-learning.svg'); }\n.icon[data-icon=view-note-review] { background-image: url('/images/view-note-review.svg'); }\n.icon[data-icon=view-note-suspended] { background-image: url('/images/view-note-suspended.svg'); }\n.icon[data-icon=view-note-buried] { background-image: url('/images/view-note-buried.svg'); }\n.icon[data-icon=big-circle] { background-image: url('/images/big-circle.svg'); }\n.icon[data-icon=small-circle] { background-image: url('/images/small-circle.svg'); }\n.icon[data-icon=big-square] { background-image: url('/images/big-square.svg'); }\n.icon[data-icon=big-diamond] { background-image: url('/images/big-diamond.svg'); }\n.icon[data-icon=overwrite-big-circle] { background-image: url('/images/overwrite-big-circle.svg'); }\n.icon[data-icon=overwrite-small-circle] { background-image: url('/images/overwrite-small-circle.svg'); }\n.icon[data-icon=overwrite-big-square] { background-image: url('/images/overwrite-big-square.svg'); }\n.icon[data-icon=overwrite-big-diamond] { background-image: url('/images/overwrite-big-diamond.svg'); }\n.icon[data-icon=add-duplicate-big-circle] { background-image: url('/images/add-duplicate-big-circle.svg'); }\n.icon[data-icon=add-duplicate-small-circle] { background-image: url('/images/add-duplicate-small-circle.svg'); }\n.icon[data-icon=add-duplicate-big-square] { background-image: url('/images/add-duplicate-big-square.svg'); }\n.icon[data-icon=add-duplicate-big-diamond] { background-image: url('/images/add-duplicate-big-diamond.svg'); }\n.icon[data-icon=play-audio] { background-image: url('/images/play-audio.svg'); }\n.icon[data-icon=source-term] { background-image: url('/images/source-term.svg'); }\n.icon[data-icon=entry-current] { background-image: url('/images/entry-current.svg'); }\n.action-icon {\n display: block;\n width: var(--action-button-size);\n height: var(--action-button-size);\n}\n.action-icon:not(.color-icon) {\n background-color: var(--text-color);\n}\n:root[data-result-output-mode=merge] .entry[data-type=term] .actions>button.action-button[data-action=play-audio] {\n display: none;\n}\n.action-button-badge {\n pointer-events: none;\n position: absolute;\n display: block;\n right: 0;\n top: 0;\n width: calc(8em / var(--font-size-no-units));\n height: calc(8em / var(--font-size-no-units));\n}\n.action-button-badge[data-icon=cross] {\n background-color: var(--danger-color);\n}\n.action-button-badge[data-icon=plus-thick] {\n background-color: var(--success-color);\n}\n\n\n/* Tags */\n.tag {\n --tag-color: var(--tag-default-background-color);\n\n display: inline-flex;\n flex-flow: row nowrap;\n align-items: stretch;\n border: none;\n border-right: none;\n font-size: 1em;\n min-height: var(--tag-height);\n margin: calc(1em / var(--font-size-no-units)) 0.375em calc(1em / var(--font-size-no-units)) 0;\n}\n.tag-label {\n display: flex;\n flex-flow: row nowrap;\n align-items: center;\n background-color: var(--tag-color);\n border-radius: var(--tag-border-radius);\n padding: calc(2.5em / var(--font-size-no-units)) 0.375em calc(2.5em / var(--font-size-no-units)) 0.375em;\n color: var(--tag-text-color);\n cursor: pointer;\n}\n.tag-label-content {\n display: block;\n font-size: var(--tag-font-size);\n font-weight: var(--tag-font-weight);\n}\n.tag-body {\n display: flex;\n flex-flow: row nowrap;\n align-items: center;\n position: relative;\n padding: 0 0.375em 0 0.375em;\n border-radius: var(--tag-border-radius);\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n}\n.tag-body::before {\n content: '';\n display: block;\n position: absolute;\n left: 0;\n top: 0;\n bottom: 0;\n right: 0;\n border-radius: var(--tag-border-radius);\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n border: var(--tag-border-size) var(--tag-border-style) var(--tag-color);\n border-left: none;\n pointer-events: none;\n}\n.tag-body-content {\n display: block;\n position: relative;\n}\n.tag:not(.tag-has-body)>.tag-body {\n display: none;\n}\n.tag.tag-has-body>.tag-label {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n}\n.tag[data-category=name] {\n --tag-color: var(--tag-name-background-color);\n}\n.tag[data-category=expression] {\n --tag-color: var(--tag-expression-background-color);\n}\n.tag[data-category=popular] {\n --tag-color: var(--tag-popular-background-color);\n}\n.tag[data-category=frequent] {\n --tag-color: var(--tag-frequent-background-color);\n}\n.tag[data-category=archaism] {\n --tag-color: var(--tag-archaism-background-color);\n}\n.tag[data-category=dictionary] {\n --tag-color: var(--tag-dictionary-background-color);\n}\n.tag[data-category=frequency] {\n --tag-color: var(--tag-frequency-background-color);\n}\n.tag[data-category=partOfSpeech] {\n --tag-color: var(--tag-part-of-speech-background-color);\n}\n.tag[data-category=search] {\n --tag-color: var(--tag-search-background-color);\n}\n.tag[data-category=pronunciation-dictionary] {\n --tag-color: var(--tag-pronunciation-dictionary-background-color);\n}\n\n\n/* Entries */\n.entry {\n padding: var(--entry-vertical-padding) var(--entry-horizontal-padding);\n position: relative;\n content-visibility: auto;\n contain-intrinsic-height: auto 500px;\n}\n.entry+.entry {\n border-top: var(--thin-border-size) solid var(--light-border-color);\n}\n.entry-body {\n clear: both;\n}\n.entry[data-definition-count='0'] .entry-body-section[data-section-type=definitions],\n.entry[data-frequency-count='0'] .entry-body-section[data-section-type=frequencies],\n.entry[data-pronunciation-count='0'] .entry-body-section[data-section-type=pronunciations] {\n display: none;\n}\n\n\n/* Inflections */\n.inflection-rule-chains {\n padding-inline-start: 0;\n list-style-type: none;\n}\n.inflection-rule-chain {\n color: var(--reason-text-color);\n}\n.inflection-rule-chain:empty {\n display: none;\n}\n.inflection-rule-chain>.inflection+.inflection-separator+.inflection::before {\n content: var(--inflection-separator);\n padding: 0 0.25em;\n}\n.inflection-source-icon {\n display: inline-block;\n white-space: nowrap;\n text-align: center;\n width: 1.4em;\n margin-right: 0.2em;\n}\n.inflection-source-icon[data-inflection-source='dictionary']::after {\n content: '📖';\n}\n.inflection-source-icon[data-inflection-source='algorithm']::after {\n content: '🧩';\n}\n.inflection-source-icon[data-inflection-source='both'] {\n width: 2.8em;\n}\n.inflection-source-icon[data-inflection-source='both']::after {\n content: '🧩📖';\n}\n.inflection[title] {\n cursor: pointer;\n}\n\n\n/* Headwords */\n.headword-list {\n display: inline;\n margin-right: var(--headword-list-end-space);\n}\n.headword {\n --headword-current-text-color: var(--headword-text-color);\n --headword-current-reading-text-color: var(--headword-reading-text-color);\n --headword-current-furigana-text-color: var(--headword-furigana-text-color);\n --headword-current-kanji-text-color: var(--headword-kanji-text-color);\n --headword-current-kanji-border-color: var(--headword-kanji-border-color);\n\n display: inline-block;\n}\n:root[data-result-output-mode=merge] .headword[data-frequency=popular] {\n --headword-current-text-color: var(--headword-text-color-popular);\n --headword-current-reading-text-color: var(--headword-reading-text-color-popular);\n --headword-current-furigana-text-color: var(--headword-furigana-text-color-popular);\n --headword-current-kanji-text-color: var(--headword-kanji-text-color-popular);\n --headword-current-kanji-border-color: var(--headword-kanji-border-color-popular);\n}\n:root[data-result-output-mode=merge] .headword[data-frequency=rare] {\n --headword-current-text-color: var(--headword-text-color-rare);\n --headword-current-reading-text-color: var(--headword-reading-text-color-rare);\n --headword-current-furigana-text-color: var(--headword-furigana-text-color-rare);\n --headword-current-kanji-text-color: var(--headword-kanji-text-color-rare);\n --headword-current-kanji-border-color: var(--headword-kanji-border-color-rare);\n}\n.headword-details {\n display: inline;\n}\n.headword-list-details {\n display: inline;\n}\n.headword-list-tag-list {\n display: inline;\n}\n.headword-text-container {\n display: inline-block;\n margin-left: calc(-1 * var(--headword-reading-space));\n}\n.headword-term-outer {\n display: inline-block;\n position: relative;\n margin-left: var(--headword-reading-space);\n}\n.headword-reading-outer {\n display: none;\n position: relative;\n margin-left: var(--headword-reading-space);\n}\n.headword-term {\n color: var(--headword-current-text-color);\n font-size: var(--headword-font-size);\n}\n.headword-reading {\n color: var(--headword-current-reading-text-color);\n font-size: var(--headword-reading-font-size);\n}\n.headword-list>.headword:not(:last-of-type)>.headword-text-container>.headword-term-outer::after {\n content: var(--headword-separator);\n font-size: var(--headword-font-size);\n}\n.headword-list>.headword:not(:last-of-type)>.headword-text-container>.headword-reading-outer::after {\n content: var(--headword-separator);\n font-size: var(--headword-reading-font-size);\n}\n.headword-term>ruby>rt {\n color: var(--headword-current-furigana-text-color);\n}\n.headword-kanji-link {\n text-decoration: underline dashed var(--headword-current-kanji-border-color) var(--headword-thin-border-size);\n text-underline-offset: calc(var(--headword-font-size) / 15);\n color: var(--headword-current-kanji-text-color);\n cursor: pointer;\n}\n:root[data-result-output-mode=merge] .headword-list-details {\n display: block;\n}\n:root[data-term-display-mode=ruby-and-reading] .headword-term-outer::after,\n:root[data-term-display-mode=term-and-reading] .headword-term-outer::after {\n display: none;\n}\n:root:not([data-language=ja]) {\n --headword-separator: ', ';\n}\n:root[data-term-display-mode=ruby-and-reading] .headword-reading-outer,\n:root[data-term-display-mode=term-and-reading] .headword-reading-outer {\n display: inline-block;\n}\n:root[data-term-display-mode=ruby-and-reading] .headword[data-reading-is-same=true] .headword-term-outer::after,\n:root[data-term-display-mode=term-and-reading] .headword[data-reading-is-same=true] .headword-term-outer::after {\n display: inline-block;\n}\n:root[data-term-display-mode=ruby-and-reading] .headword[data-reading-is-same=true] .headword-reading-outer,\n:root[data-term-display-mode=term-and-reading] .headword[data-reading-is-same=true] .headword-reading-outer {\n display: none;\n}\n:root[data-term-display-mode=term-and-reading] .headword-term>ruby>rt,\n:root[data-term-display-mode=term-only] .headword-term>ruby>rt {\n display: none;\n}\n\n\n/* Entry indicator */\n.entry-current-indicator {\n display: block;\n position: absolute;\n left: calc(-1 * var(--main-content-horizontal-padding));\n top: 0;\n bottom: 0;\n width: 0;\n background-color: var(--entry-current-indicator-color);\n visibility: hidden;\n transition:\n width var(--entry-current-indicator-transition-duration) linear,\n visibility 0s linear var(--entry-current-indicator-transition-duration);\n}\n.entry.entry-current .entry-current-indicator {\n width: var(--entry-current-indicator-width);\n visibility: visible;\n transition:\n width var(--entry-current-indicator-transition-duration) linear,\n visibility 0s linear 0s;\n}\n:root[data-popup-current-indicator-mode=bar-right] .entry-current-indicator,\n:root[data-popup-current-indicator-mode=dot-right] .entry-current-indicator {\n left: auto;\n right: 0;\n}\n.entry-current-indicator-inner {\n display: none;\n pointer-events: auto;\n width: 100%;\n height: 0;\n top: 0;\n background-color: var(--entry-current-indicator-color);\n transition: none;\n}\n.entry.entry-current .entry-current-indicator-inner {\n height: var(--entry-current-indicator-width);\n transition: height var(--entry-current-indicator-transition-duration) linear;\n}\n:root[data-popup-current-indicator-mode=dot-left] .entry-current-indicator,\n:root[data-popup-current-indicator-mode=dot-right] .entry-current-indicator {\n background-color: transparent;\n}\n:root[data-popup-current-indicator-mode=dot-left] .entry-current-indicator-inner,\n:root[data-popup-current-indicator-mode=dot-right] .entry-current-indicator-inner {\n display: block;\n position: sticky;\n transition: height var(--entry-current-indicator-transition-duration) linear;\n}\n:root[data-popup-current-indicator-mode=none] .entry-current-indicator,\n:root[data-popup-current-indicator-mode=asterisk] .entry-current-indicator,\n:root[data-popup-current-indicator-mode=triangle] .entry-current-indicator {\n display: none;\n transition: none;\n}\n\n\n/* Triangle entry indicator */\n.headword-current-indicator {\n pointer-events: none;\n position: absolute;\n left: calc(-1 * var(--main-content-horizontal-padding));\n top: 0;\n bottom: 0;\n opacity: 0;\n visibility: hidden;\n transition:\n opacity var(--entry-current-indicator-transition-duration) linear,\n visibility 0s linear var(--entry-current-indicator-transition-duration);\n}\n.headword-term .headword-current-indicator {\n font-size: calc(1em / var(--headword-font-size-no-units));\n}\n.entry.entry-current .headword-current-indicator {\n opacity: 1;\n visibility: visible;\n transition:\n opacity var(--entry-current-indicator-transition-duration) linear,\n visibility 0s linear 0s;\n}\n.headword-current-indicator::after {\n content: '';\n display: block;\n position: absolute;\n width: var(--entry-current-indicator-triangle-size);\n height: calc(2 * var(--entry-current-indicator-triangle-size));\n left: calc(-1 * var(--entry-horizontal-padding));\n top: calc(50% - var(--entry-current-indicator-triangle-size));\n background-color: var(--entry-current-indicator-color);\n mask-repeat: no-repeat;\n mask-position: center center;\n mask-mode: alpha;\n mask-size: contain;\n mask-image: url(/images/material-right-arrow.svg);\n -webkit-mask-repeat: no-repeat;\n -webkit-mask-position: center center;\n -webkit-mask-mode: alpha;\n -webkit-mask-size: contain;\n -webkit-mask-image: url(/images/material-right-arrow.svg);\n}\n.headword-list>.headword:not(:first-of-type) .headword-current-indicator,\n:root:not([data-popup-current-indicator-mode=triangle]) .headword-current-indicator {\n display: none;\n transition: none;\n}\n\n\n/* Old entry indicator */\n.entry-current-indicator-icon {\n display: block;\n padding: var(--action-button-padding);\n}\n.entry-current-indicator-icon[hidden],\n.entry:not(.entry-current) .entry-current-indicator-icon,\n:root:not([data-popup-current-indicator-mode=asterisk]) .entry-current-indicator-icon {\n display: none;\n}\n.entry-current-indicator-icon>.icon {\n width: var(--action-button-size);\n height: var(--action-button-size);\n display: block;\n background-image: url('/images/entry-current.svg');\n}\n\n\n/* Merged term styles */\n:root[data-result-output-mode=merge] .headword-list .headword-details {\n display: inline-block;\n position: relative;\n width: 0;\n height: 0;\n visibility: hidden;\n z-index: 1;\n}\n:root[data-result-output-mode=merge] .headword-list>.headword:not(:last-of-type) .headword-details {\n left: calc(-1 * var(--headword-font-size));\n}\n:root[data-result-output-mode=merge] .headword:hover .headword-details {\n visibility: visible;\n}\n:root[data-result-output-mode=merge] .headword-list .headword-details>.action-button[data-action=play-audio] {\n position: absolute;\n left: 0;\n bottom: 0.5em;\n}\n:root:not([data-result-output-mode=merge]) .headword-list .headword-details>.action-button[data-action=play-audio] {\n display: none;\n}\n\n\n/* Definitions */\n.definition-list {\n margin: 0;\n padding: 0 0 0 var(--list-padding1);\n list-style-type: decimal;\n}\n.definition-list[data-count='0'],\n.definition-list[data-count='1'] {\n padding-left: 0;\n list-style-type: none;\n}\n.gloss-list {\n margin: 0;\n padding: 0 0 0 var(--list-padding2);\n list-style-type: circle;\n}\n.gloss-list[data-count='0'],\n.gloss-list[data-count='1'] {\n padding-left: 0;\n list-style-type: none;\n}\n.definition-item::marker,\n.gloss-item::marker {\n color: var(--text-color-light3);\n}\n.gloss-content {\n display: block;\n white-space: pre-line;\n}\n.definition-disambiguation-list {\n color: var(--text-color-light3);\n padding-right: var(--disambiguation-space);\n}\n.definition-disambiguation-list[data-count='0'] {\n display: none;\n}\n.definition-disambiguation+.definition-disambiguation::before {\n content: var(--disambiguation-separator);\n}\n.gloss-separator,\n.inflection-separator {\n display: inline;\n font-size: 0;\n opacity: 0;\n white-space: pre-wrap;\n}\n.gloss-separator {\n display: none;\n}\n.definition-item {\n display: list-item;\n position: relative;\n}\n.definition-item-inner {\n display: flex;\n flex-flow: row nowrap;\n}\n.definition-item-content {\n width: 100%;\n flex: 1 1 auto;\n background-color: transparent;\n transition: background-color var(--animation-duration) ease-in-out;\n}\n\n/* Collapse & Expand */\nbutton.expansion-button {\n --button-content-color: var(--text-color-light4);\n --button-border-color: transparent;\n --button-background-color: transparent;\n\n --button-hover-content-color: var(--text-color-light1);\n --button-hover-border-color: var(--accent-color-lighter);\n --button-hover-background-color: var(--accent-color-lighter);\n\n --button-active-content-color: var(--text-color);\n --button-active-border-color: var(--accent-color-light);\n --button-active-background-color: var(--accent-color-light);\n\n --button-padding-vertical: 0;\n --button-padding-horizontal: 0.125em;\n\n flex: 0 0 auto;\n order: 1;\n border-radius: 0;\n border: 0;\n}\n\nbutton.expansion-button:hover+.definition-item-content,\nbutton.expansion-button:active+.definition-item-content,\nbutton.expansion-button:focus+.definition-item-content,\nbutton.expansion-button:hover+.kanji-glyph-table,\nbutton.expansion-button:active+.kanji-glyph-table,\nbutton.expansion-button:focus+.kanji-glyph-table {\n background-color: var(--accent-color-transparent25);\n}\nbutton.expansion-button:focus:not(:focus-visible)+.definition-item-content,\nbutton.expansion-button:focus:not(:focus-visible)+.kanji-glyph-table {\n background-color: transparent;\n}\nbutton.expansion-button:focus:hover+.definition-item-content,\nbutton.expansion-button:focus:active+.definition-item-content,\nbutton.expansion-button:focus:focus-visible+.definition-item-content,\nbutton.expansion-button:focus:hover+.kanji-glyph-table,\nbutton.expansion-button:focus:active+.kanji-glyph-table,\nbutton.expansion-button:focus:focus-visible+.kanji-glyph-table {\n background-color: var(--accent-color-transparent25);\n}\n.definition-item-inner.collapsible.collapsed {\n max-height: calc(1em * var(--collapsible-definition-line-count) * var(--line-height));\n overflow: hidden;\n}\n.definition-item-inner.collapse-test {\n max-height: calc(1em * var(--collapsible-definition-line-count) * var(--line-height) + var(--collapsible-definition-test-offset));\n overflow: hidden;\n}\n.kanji-glyph-data.collapsible.collapsed {\n max-height: calc(1em * var(--collapsible-kanji-glyph-data-line-count) * var(--line-height) + var(--kanji-glyph-table-header-height));\n overflow: hidden;\n}\n.kanji-glyph-data.collapse-test {\n max-height: calc(1em * var(--collapsible-kanji-glyph-data-line-count) * var(--line-height) + var(--kanji-glyph-table-header-height) + var(--collpasible-kanji-glyph-data-test-offset));\n overflow: hidden;\n}\n:not(.collapsible)>button.expansion-button {\n display: none;\n}\n.expansion-button-icon {\n transform: rotate(0deg);\n width: calc(16em / var(--font-size-no-units));\n height: calc(16em / var(--font-size-no-units));\n background-color: var(--button-current-content-color);\n transition: background-color var(--animation-duration) ease-in-out;\n}\n.collapsible:not(.collapsed)>button.expansion-button>.expansion-button-icon {\n transform: rotate(180deg);\n}\n\n/* Frequencies */\n.frequency-group-item {\n display: inline;\n}\n.frequency-item {\n display: inline;\n}\n.frequency-disambiguation {\n color: var(--text-color-light3);\n padding-right: var(--disambiguation-space);\n}\n.frequency-disambiguation-separator::before {\n content: var(--disambiguation-reading-separator);\n}\n.frequency-disambiguation-reading {\n display: inline;\n font-size: 1em;\n}\n.frequency-body::after {\n white-space: pre-wrap;\n display: inline;\n color: var(--text-color-light3);\n}\n.entry[data-unique-term-count='1'] .frequency-item[data-has-reading=false] .frequency-disambiguation,\n.entry[data-unique-reading-count='1'][data-unique-term-count='1'] .frequency-disambiguation,\n.frequency-item[data-reading-is-same=true] .frequency-disambiguation-separator,\n.frequency-item[data-reading-is-same=true] .frequency-disambiguation-reading,\n.frequency-item[data-has-reading=false] .frequency-disambiguation-separator,\n.frequency-item[data-has-reading=false] .frequency-disambiguation-reading,\n.entry[data-unique-term-count='1'] .frequency-disambiguation-separator,\n.entry[data-unique-term-count='1'] .frequency-disambiguation-term,\n.entry[data-unique-reading-count='1'] .frequency-disambiguation-separator,\n.entry[data-unique-reading-count='1'] .frequency-disambiguation-reading {\n display: none;\n}\n:root[data-frequency-display-mode=tags] .frequency-group-tag,\n:root[data-frequency-display-mode=split-tags] .frequency-group-tag {\n margin: 0;\n display: inline;\n min-height: auto;\n}\n:root[data-frequency-display-mode=tags] .frequency-group-tag>.tag-label,\n:root[data-frequency-display-mode=split-tags] .frequency-group-tag>.tag-label {\n display: none;\n}\n:root[data-frequency-display-mode=tags] .frequency-group-tag>.tag-body,\n:root[data-frequency-display-mode=split-tags] .frequency-group-tag>.tag-body {\n display: inline;\n padding: 0;\n}\n:root[data-frequency-display-mode=tags] .frequency-group-tag>.tag-body::before,\n:root[data-frequency-display-mode=split-tags] .frequency-group-tag>.tag-body::before {\n display: none;\n}\n:root[data-frequency-display-mode=tags] .frequency-list,\n:root[data-frequency-display-mode=split-tags] .frequency-list {\n display: inline;\n}\n:root[data-frequency-display-mode=list] .frequency-tag,\n:root[data-frequency-display-mode=inline-list] .frequency-tag,\n:root[data-frequency-display-mode=tags-grouped] .frequency-tag,\n:root[data-frequency-display-mode=split-tags-grouped] .frequency-tag {\n margin: 0;\n display: inline;\n min-height: auto;\n}\n:root[data-frequency-display-mode=list] .frequency-tag>.tag-label,\n:root[data-frequency-display-mode=inline-list] .frequency-tag>.tag-label,\n:root[data-frequency-display-mode=tags-grouped] .frequency-tag>.tag-label,\n:root[data-frequency-display-mode=split-tags-grouped] .frequency-tag>.tag-label {\n display: none;\n}\n:root[data-frequency-display-mode=list] .frequency-tag>.tag-body,\n:root[data-frequency-display-mode=inline-list] .frequency-tag>.tag-body,\n:root[data-frequency-display-mode=tags-grouped] .frequency-tag>.tag-body,\n:root[data-frequency-display-mode=split-tags-grouped] .frequency-tag>.tag-body {\n display: inline;\n padding: 0;\n}\n:root[data-frequency-display-mode=list] .frequency-tag>.tag-body::before,\n:root[data-frequency-display-mode=inline-list] .frequency-tag>.tag-body::before,\n:root[data-frequency-display-mode=tags-grouped] .frequency-tag>.tag-body::before,\n:root[data-frequency-display-mode=split-tags-grouped] .frequency-tag>.tag-body::before {\n display: none;\n}\n:root[data-frequency-display-mode=list] .frequency-body,\n:root[data-frequency-display-mode=inline-list] .frequency-body,\n:root[data-frequency-display-mode=tags-grouped] .frequency-body,\n:root[data-frequency-display-mode=split-tags-grouped] .frequency-body {\n display: inline-block;\n}\n:root[data-frequency-display-mode=inline-list] .frequency-item:not(:last-child)>.frequency-tag>.tag-body>.frequency-body::after,\n:root[data-frequency-display-mode=tags-grouped] .frequency-item:not(:last-child)>.frequency-tag>.tag-body>.frequency-body::after,\n:root[data-frequency-display-mode=split-tags-grouped] .frequency-item:not(:last-child)>.frequency-tag>.tag-body>.frequency-body::after {\n content: var(--compact-list-separator);\n}\n:root[data-frequency-display-mode=list] .frequency-group-tag>.tag-body::before,\n:root[data-frequency-display-mode=inline-list] .frequency-group-tag>.tag-body::before {\n display: none;\n}\n:root[data-frequency-display-mode=list] .frequency-group-tag.tag.tag-has-body>.tag-label,\n:root[data-frequency-display-mode=inline-list] .frequency-group-tag.tag.tag-has-body>.tag-label {\n border-radius: var(--tag-border-radius);\n}\n:root[data-frequency-display-mode=tags] .frequency-tag>.tag-body::before {\n display: none;\n}\n:root[data-frequency-display-mode=tags] .frequency-tag>.tag-body {\n background-color: var(--tag-color);\n padding-left: 0;\n}\n:root[data-frequency-display-mode=tags] .frequency-body {\n font-size: var(--tag-font-size);\n font-weight: var(--tag-font-weight);\n color: var(--tag-text-color);\n}\n:root[data-frequency-display-mode=tags] .frequency-tag>.tag-label>.tag-label-content::after {\n content: ':';\n}\n:root[data-frequency-display-mode=tags-grouped] .frequency-group-tag>.tag-body::before {\n display: none;\n}\n:root[data-frequency-display-mode=tags-grouped] .frequency-group-tag>.tag-body {\n background-color: var(--tag-color);\n padding-left: 0;\n}\n:root[data-frequency-display-mode=tags-grouped] .frequency-list {\n font-size: var(--tag-font-size);\n font-weight: var(--tag-font-weight);\n color: var(--tag-text-color);\n}\n:root[data-frequency-display-mode=tags-grouped] .frequency-group-tag>.tag-label>.tag-label-content::after {\n content: ':';\n}\n:root[data-frequency-display-mode=tags] .frequency-disambiguation,\n:root[data-frequency-display-mode=tags-grouped] .frequency-disambiguation,\n:root[data-frequency-display-mode=tags] .frequency-body::after,\n:root[data-frequency-display-mode=tags-grouped] .frequency-body::after {\n color: inherit;\n font-weight: normal;\n opacity: 0.75;\n}\n:root[data-frequency-display-mode=list] .frequency-group-list {\n list-style-type: decimal;\n padding: 0 0 0 var(--list-padding1);\n}\n:root[data-frequency-display-mode=list] .frequency-group-item {\n display: list-item;\n}\n:root[data-frequency-display-mode=list] .frequency-group-item::marker {\n color: var(--text-color-light3);\n}\n:root[data-frequency-display-mode=list] .frequency-group-tag {\n display: block;\n min-height: auto;\n}\n:root[data-frequency-display-mode=list] .frequency-group-tag>.tag-label {\n display: inline-flex;\n}\n:root[data-frequency-display-mode=list] .frequency-list {\n list-style-type: circle;\n padding: 0 0 0 var(--list-padding2);\n}\n:root[data-frequency-display-mode=list] .frequency-item {\n display: list-item;\n}\n:root[data-frequency-display-mode=list] .frequency-item::marker {\n color: var(--text-color-light3);\n}\n:root[data-frequency-display-mode=list] .frequency-group-list[data-count='1'] {\n list-style-type: none;\n padding-left: 0;\n}\n:root[data-frequency-display-mode=list] .frequency-group-list[data-count='1']>.frequency-group-item {\n display: inline;\n}\n:root[data-frequency-display-mode=list] .frequency-group-item[data-count='1']>.frequency-group-tag>.tag-body {\n display: inline-flex;\n}\n:root[data-frequency-display-mode=list] .frequency-group-item[data-count='1']>.frequency-group-tag>.tag-body>.frequency-body {\n display: inline;\n}\n:root[data-frequency-display-mode=list] .frequency-group-item[data-count='1'] .frequency-list {\n list-style-type: none;\n padding-left: 0;\n}\n:root[data-frequency-display-mode=list] .frequency-group-item[data-count='1'] .frequency-item {\n display: inline;\n}\n\n\n/* Pitch accent styles */\n.pronunciation-group-list {\n margin: 0;\n padding: 0 0 0 var(--list-padding1);\n list-style-type: decimal;\n}\n.pronunciation-group-list[data-count='0'],\n.pronunciation-group-list[data-count='1'] {\n padding-left: 0;\n list-style-type: none;\n}\n.pronunciation-list {\n margin: 0;\n padding: 0 0 0 var(--list-padding2);\n list-style-type: circle;\n display: block;\n}\n.pronunciation-list[data-count='0'],\n.pronunciation-list[data-count='1'] {\n padding-left: 0;\n list-style-type: none;\n display: inline;\n}\n.pronunciation-group::marker,\n.pronunciation::marker {\n color: var(--text-color-light3);\n}\n.pronunciation {\n display: list-item;\n line-height: 1.5;\n}\n.pronunciation-list[data-count='0'] .pronunciation,\n.pronunciation-list[data-count='1'] .pronunciation {\n display: inline;\n}\n.pronunciation-group-tag-list {\n margin-right: 0.375em;\n}\n.pronunciation-disambiguation-list {\n color: var(--text-color-light3);\n padding-right: var(--disambiguation-space);\n}\n.pronunciation-disambiguation+.pronunciation-disambiguation::before {\n content: var(--disambiguation-separator);\n}\n.pronunciation-disambiguation-list[data-count='0'] {\n display: none;\n}\n.pronunciation-tag-list:not([data-count='0']) {\n margin-right: 0.375em;\n}\n.pronunciation-downstep-notation-container {\n margin-left: 0.25em;\n}\n.pronunciation-graph-container {\n margin-left: 0.25em;\n}\n\n\n/* Kanji */\n.kanji-glyph-container {\n display: block;\n position: relative;\n}\n.kanji-glyph {\n font-family: sans-serif;\n font-size: 8.5em;\n line-height: 1;\n padding: 0.01em;\n vertical-align: top;\n}\n.kanji-glyph-data {\n margin-top: 0.75em;\n display: flex;\n flex-flow: row nowrap;\n}\n.kanji-glyph-table {\n border-spacing: 0;\n border-collapse: collapse;\n}\n.kanji-glyph-table>tbody>tr>* {\n border-top: var(--thin-border-size) solid var(--medium-border-color);\n text-align: left;\n vertical-align: top;\n padding: var(--kanji-glyph-table-cell-padding);\n margin: 0;\n}\n.kanji-info-table {\n width: 100%;\n}\n.kanji-info-table>tbody>tr>th,\n.kanji-info-table>tbody>tr>td {\n text-align: left;\n vertical-align: top;\n padding: 0;\n margin: 0;\n}\n.kanji-info-table>tbody>tr>td {\n text-align: right;\n}\n.kanji-glyph-table dl {\n margin-top: 0;\n margin-bottom: 1.4em;\n}\n.kanji-glyph-table dd {\n margin-left: 0;\n}\n.kanji-gloss-list {\n margin: 0;\n padding: 0 0 0 var(--list-padding1);\n list-style-type: decimal;\n}\n.kanji-gloss-list[data-count='0'],\n.kanji-gloss-list[data-count='1'] {\n padding-left: 0;\n list-style-type: none;\n}\n.kanji-gloss-item::marker {\n color: var(--text-color-light3);\n}\n.kanji-gloss-content {\n white-space: pre-line;\n}\n.kanji-tag-list {\n position: relative;\n}\n.entry[data-type=kanji] .entry-body-section[data-section-type=frequencies] {\n position: relative;\n}\n\n\n/* Progress bar */\n@keyframes progress-bar-indeterminant1a {\n 0% { left: 0; }\n 25% { left: 0; }\n 75% { left: 100%; }\n 100% { left: 100%; }\n}\n@keyframes progress-bar-indeterminant1b {\n 0% { right: 100%; }\n 50% { right: 0; }\n 100% { right: 0; }\n}\n@keyframes progress-bar-indeterminant2a {\n 0% { left: 0; }\n 25% { left: 0; }\n 100% { left: 100%; }\n}\n@keyframes progress-bar-indeterminant2b {\n 0% { right: 100%; }\n 75% { right: 0; }\n 100% { right: 0; }\n}\n.progress-bar-indeterminant {\n display: block;\n width: 100%;\n height: 0;\n background-color: var(--progress-bar-indicator-color);\n position: relative;\n transition:\n height var(--progress-bar-active-transition-duration) linear var(--progress-bar-active-transition-duration),\n background-color var(--progress-bar-active-transition-duration) linear;\n}\n.progress-bar-indeterminant[data-active=true] {\n height: var(--progress-bar-height);\n background-color: var(--progress-bar-track-color);\n transition:\n height var(--progress-bar-active-transition-duration) linear var(--progress-bar-active-transition-start-delay),\n background-color 0s linear;\n}\n.progress-bar-indeterminant[hidden]:not([data-active=true]) {\n display: none;\n}\n.progress-bar-indeterminant::before,\n.progress-bar-indeterminant::after {\n content: '';\n display: block;\n position: absolute;\n left: 0;\n top: 0;\n bottom: 0;\n right: 100%;\n background-color: var(--progress-bar-indicator-color);\n animation: none;\n}\n.progress-bar-indeterminant:not([hidden])::before {\n animation:\n progress-bar-indeterminant1a var(--progress-bar-animation-duration) infinite ease-in-out var(--progress-bar-active-transition-start-delay),\n progress-bar-indeterminant1b var(--progress-bar-animation-duration) infinite ease-in-out var(--progress-bar-active-transition-start-delay);\n}\n.progress-bar-indeterminant:not([hidden])::after {\n animation:\n progress-bar-indeterminant2a var(--progress-bar-animation-duration) infinite ease-in-out calc(var(--progress-bar-active-transition-start-delay) + 0.375 * var(--progress-bar-animation-duration)),\n progress-bar-indeterminant2b var(--progress-bar-animation-duration) infinite ease-in-out calc(var(--progress-bar-active-transition-start-delay) + 0.375 * var(--progress-bar-animation-duration));\n}\n.top-progress-bar-container {\n position: sticky;\n top: 0;\n height: 0;\n pointer-events: none;\n z-index: 10;\n}\n\n\n/* Frame resizer */\n.frame-resizer-container {\n position: fixed;\n bottom: 0;\n right: 0;\n z-index: 100;\n background: transparent;\n pointer-events: none;\n user-select: none;\n}\n.frame-resizer-sizer1 {\n padding-top: 100%;\n line-height: 0;\n}\n.frame-resizer-sizer2 {\n display: inline-block;\n overflow-x: hidden;\n overflow-y: scroll;\n vertical-align: bottom;\n}\n.frame-resizer-sizer2.frame-resizer-sizer2-with-min-size {\n min-width: 1em;\n}\n.frame-resizer-svg {\n display: block;\n position: absolute;\n bottom: 0;\n right: 0;\n width: 75%;\n height: 75%;\n}\n.frame-resizer-handle {\n fill: var(--text-color);\n opacity: 0.125;\n cursor: se-resize;\n pointer-events: auto;\n transition:\n fill var(--animation-duration) linear,\n opacity var(--animation-duration) linear;\n}\n.frame-resizer-handle:hover,\n:root[data-is-resizing=true] .frame-resizer-handle {\n fill: var(--accent-color);\n opacity: 1;\n}\n\n\n/* Footer notifications */\n.footer-notification {\n display: flex;\n flex-flow: row nowrap;\n align-items: flex-start;\n pointer-events: auto;\n border-radius: 0.25em;\n background-color: var(--notification-background-color);\n box-shadow: 0 0.125em 0.25em 0 var(--notification-shadow-color);\n color: var(--notification-text-color);\n margin: 0.5em;\n padding: 0;\n transition: opacity var(--animation-duration) ease-out;\n position: relative;\n overflow: auto;\n max-height: calc(0.5em * 2 + var(--line-height) * 4 * 1em);\n}\n.footer-notification[hidden] {\n display: flex;\n opacity: 0;\n transition: opacity var(--animation-duration) ease-in;\n}\n.footer-notification-body {\n flex: 1 1 auto;\n padding: 0.5em 0.75em;\n white-space: pre-line;\n}\n.footer-notification-close-button-container {\n align-self: stretch;\n display: flex;\n flex-flow: column nowrap;\n align-items: center;\n justify-content: center;\n padding: 0.25em 0.75em 0.25em 0;\n position: sticky;\n top: 0;\n right: 0;\n}\nbutton.footer-notification-close-button {\n --button-content-color: var(--notification-text-color);\n --button-border-color: transparent;\n --button-background-color: transparent;\n --button-shadow: none;\n\n --button-hover-border-color: transparent;\n --button-hover-background-color: transparent;\n --button-hover-shadow: none;\n\n --button-active-border-color: transparent;\n --button-active-background-color: transparent;\n --button-active-shadow: none;\n\n --button-focus-visible-border-color: transparent;\n --button-focus-visible-background-color: var(--notification-background-color-light);\n --button-focus-visible-shadow: none;\n\n flex: 0 0 auto;\n margin: -0.25em;\n padding: 0.5em;\n border-style: none;\n border-width: 0;\n cursor: pointer;\n font-size: inherit;\n}\n.footer-notification-close-button-icon {\n display: block;\n width: calc(16em / var(--font-size-no-units));\n height: calc(16em / var(--font-size-no-units));\n background-color: var(--button-content-color);\n}\n.tag-details-disambiguation-list>.tag-details-disambiguation:not(:last-child)::after {\n content: var(--disambiguation-separator);\n}\n.footer-notification a {\n color: var(--notification-text-color);\n}\n\n\n/* Overlays */\n.overlay-panel-container {\n pointer-events: none;\n position: absolute;\n left: 0;\n top: 0;\n bottom: 0;\n right: 0;\n z-index: 6;\n}\n.overlay-panel {\n pointer-events: auto;\n background-color: var(--background-color);\n display: block;\n position: absolute;\n left: 0;\n top: 0;\n bottom: 0;\n width: var(--content-width);\n max-width: 100%;\n box-sizing: border-box;\n margin: 0 auto;\n padding: var(--main-content-vertical-padding) var(--main-content-horizontal-padding);\n overflow-y: scroll;\n transform: none;\n opacity: 1;\n visibility: visible;\n transition:\n opacity var(--animation-duration2) ease-out,\n visibility 0s linear,\n transform var(--animation-duration2) ease-out;\n}\n.overlay-panel[hidden] {\n transform: translate(var(--overlay-panel-translate-distance), 0);\n opacity: 0;\n visibility: hidden;\n transition:\n opacity var(--animation-duration2) ease-in,\n visibility 0s linear var(--animation-duration2),\n transform var(--animation-duration2) ease-in;\n}\n.overlay-panel[hidden]:not(.hidden-animating) {\n display: none;\n}\n:root[data-popup-action-bar-location=left] .overlay-panel[hidden] {\n transform: translate(calc(-1 * var(--overlay-panel-translate-distance)), 0);\n}\n:root[data-popup-action-bar-location=top] .overlay-panel[hidden] {\n transform: translate(0, calc(-1 * var(--overlay-panel-translate-distance)));\n}\n:root[data-popup-action-bar-location=bottom] .overlay-panel[hidden] {\n transform: translate(0, var(--overlay-panel-translate-distance));\n}\n.overlay-panel-inner {\n padding: var(--entry-vertical-padding) var(--entry-horizontal-padding);\n}\n\n\n/* Profile panel */\n.profile-list {\n display: flex;\n flex-flow: column nowrap;\n align-items: stretch;\n}\n.profile-list-item {\n display: flex;\n flex-flow: row nowrap;\n align-items: center;\n cursor: pointer;\n}\n.profile-list-item-selection {\n flex: 0 0 auto;\n text-align: center;\n padding: 0.25em 0.5em 0.25em 0;\n}\n.profile-list-item-name {\n flex: 1 1 auto;\n padding: 0.25em 0;\n}\n\n\n/* Audio menu */\n.audio-button-popup-menu[data-show-icons=false] .popup-menu-item-audio-button .popup-menu-item-icon {\n display: none;\n}\n.audio-button-popup-menu .popup-menu-item-icon[data-icon=checkmark] {\n background-color: var(--success-color);\n}\n.audio-button-popup-menu .popup-menu-item-icon[data-icon=cross] {\n background-color: var(--danger-color);\n}\n.audio-button-popup-menu .popup-menu-item-group[data-source-in-options=false][data-valid=null] .popup-menu-item {\n color: var(--text-color-light1);\n}\n.popup-menu-item-audio-button .popup-menu-item-label {\n padding-right: 2.5em;\n}\n.popup-menu-item-set-primary-audio-button {\n flex-flow: row nowrap;\n align-items: center;\n justify-content: center;\n position: absolute;\n right: 0;\n top: 0;\n bottom: 0;\n width: 2.5em;\n}\n.popup-menu-item-set-primary-audio-button:not([hidden]) {\n display: flex;\n}\n.popup-menu-item-set-primary-audio-button .popup-menu-item-icon {\n opacity: 0;\n transition: opacity var(--animation-duration) linear;\n}\n.popup-menu-item-audio-button:hover~.popup-menu-item-set-primary-audio-button .popup-menu-item-icon,\n.popup-menu-item-audio-button:active~.popup-menu-item-set-primary-audio-button .popup-menu-item-icon,\n.popup-menu-item-audio-button:focus~.popup-menu-item-set-primary-audio-button .popup-menu-item-icon {\n opacity: 0.25;\n}\n.popup-menu-item-set-primary-audio-button:hover .popup-menu-item-icon,\n.popup-menu-item-set-primary-audio-button:active .popup-menu-item-icon,\n.popup-menu-item-set-primary-audio-button:focus .popup-menu-item-icon {\n opacity: 0.375;\n}\n.popup-menu-item-set-primary-audio-button:focus:not(:focus-visible) .popup-menu-item-icon {\n opacity: 0;\n}\n.popup-menu-item-audio-button:hover~.popup-menu-item-set-primary-audio-button:not(:focus-visible) .popup-menu-item-icon,\n.popup-menu-item-audio-button:active~.popup-menu-item-set-primary-audio-button:not(:focus-visible) .popup-menu-item-icon,\n.popup-menu-item-audio-button:focus~.popup-menu-item-set-primary-audio-button:not(:focus-visible) .popup-menu-item-icon {\n opacity: 0.25;\n}\n.popup-menu-item-set-primary-audio-button:hover:not(:focus-visible) .popup-menu-item-icon,\n.popup-menu-item-set-primary-audio-button:active:not(:focus-visible) .popup-menu-item-icon {\n opacity: 0.375;\n}\n.popup-menu-item-group[data-is-primary-card-audio=true]>.popup-menu-item-audio-button~.popup-menu-item-set-primary-audio-button .popup-menu-item-icon,\n.popup-menu-item-group[data-is-primary-card-audio=true]>.popup-menu-item-audio-button~.popup-menu-item-set-primary-audio-button:hover .popup-menu-item-icon,\n.popup-menu-item-group[data-is-primary-card-audio=true]>.popup-menu-item-audio-button~.popup-menu-item-set-primary-audio-button:active .popup-menu-item-icon,\n.popup-menu-item-group[data-is-primary-card-audio=true]>.popup-menu-item-audio-button~.popup-menu-item-set-primary-audio-button:focus .popup-menu-item-icon {\n opacity: 1;\n}\n\n\n/* Anki errors */\n.anki-note-error-list {\n margin: 0;\n padding-left: 1.5em;\n list-style: disc;\n}\n.anki-note-error-info {\n color: var(--danger-color);\n}\n.anki-note-error-header {\n font-weight: bold;\n}\n\n\n/* Conditional styles */\n:root:not([data-enable-search-tags=true]) .tag[data-category=search] {\n display: none;\n}\n:root[data-compact-tags=true] .tag[data-redundant=true] {\n display: none;\n}\n\n:root:not([data-debug=true]) .action-button[data-action=menu] {\n display: none;\n}\n:root[data-anki-enabled=false] .action-button[data-action=view-note],\n:root[data-anki-enabled=false] .action-button[data-action=save-note] {\n display: none;\n}\n\n:root[data-average-frequency=true] .frequency-group-item:not([data-details='Average']) {\n display: none;\n}\n\n:root[data-average-frequency=false] .frequency-group-item[data-details='Average'] {\n display: none;\n}\n\n:root[data-audio-enabled=false] .action-button[data-action=play-audio] {\n display: none;\n}\n:root[data-glossary-layout-mode^=compact] .definition-tag-list,\n:root[data-glossary-layout-mode^=compact] .definition-disambiguation-list:not([data-count='0']) {\n display: inline;\n}\n:root[data-glossary-layout-mode^=compact] .gloss-list {\n display: inline;\n list-style: none;\n padding-left: 0;\n}\n:root[data-glossary-layout-mode^=compact] .gloss-item {\n display: inline;\n}\n:root[data-glossary-layout-mode^=compact] .gloss-item:not(:first-child)::before {\n white-space: pre-wrap;\n content: var(--compact-list-separator);\n display: inline;\n color: var(--text-color-light3);\n}\n:root[data-glossary-layout-mode^=compact] .gloss-content {\n display: inline;\n}\n:root[data-glossary-layout-mode^=compact] .gloss-separator {\n display: inline;\n}\n\n:root[data-show-pronunciation-text=true] .pronunciation-disambiguation-list[data-term-count='0'],\n:root[data-show-pronunciation-text=true] .pronunciation-disambiguation[data-type=reading] {\n display: none;\n}\n:root[data-show-pronunciation-text=false] .pronunciation[data-pronunciation-type=pitch-accent]>.pronunciation-representation-list>.pronunciation-text-container {\n display: none;\n}\n:root[data-show-pronunciation-downstep-position=false] .pronunciation-downstep-notation-container {\n display: none;\n}\n:root[data-show-pronunciation-graph=false] .pronunciation-graph-container {\n display: none;\n}\n\n:root[data-glossary-layout-mode^=compact][data-show-pronunciation-graph=false] .pronunciation-list:not([data-has-tags=true]) {\n display: inline;\n list-style: none;\n padding-left: 0;\n}\n:root[data-glossary-layout-mode^=compact][data-show-pronunciation-graph=false] .pronunciation-list:not([data-has-tags=true]) .pronunciation {\n display: inline;\n}\n:root[data-glossary-layout-mode^=compact][data-show-pronunciation-graph=false] .pronunciation-list:not([data-has-tags=true]) .pronunciation:not(:first-child)::before {\n white-space: pre-wrap;\n content: var(--compact-list-separator);\n display: inline;\n color: var(--text-color-light3);\n}\n\n:root[data-popup-display-mode=full-width] .frame-resizer-container {\n display: none;\n}\n`;\n","/*\n * Copyright (C) 2023-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 * The structured content CSS styles from the Yomitan extension.\n * Sourced from Yomitan's ext/css/structured-content.css.\n */\nexport const STRUCTURED_CONTENT_CSS = `/*\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 entrys 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/* Glossary images */\n.gloss-image-container {\n display: inline-block;\n white-space: nowrap;\n max-width: 100%;\n max-height: 100vh;\n position: relative;\n vertical-align: top;\n line-height: 0;\n font-size: calc(1em / var(--font-size-no-units));\n overflow: hidden;\n}\n.gloss-image-link[data-background=true]>.gloss-image-container {\n background-color: var(--gloss-image-background-color);\n}\n.gloss-image-link {\n cursor: inherit;\n color: var(--accent-color);\n display: inline-block;\n position: relative;\n line-height: 1;\n max-width: 100%;\n}\n.gloss-image-link:hover {\n color: var(--accent-color-dark);\n cursor: pointer;\n}\n.gloss-image-container-overlay {\n position: absolute;\n left: 0;\n top: 0;\n width: 100%;\n height: 100%;\n font-size: calc(1em * var(--font-size-no-units));\n line-height: var(--line-height);\n display: table;\n table-layout: fixed;\n white-space: normal;\n color: var(--text-color-light3);\n}\n.gloss-image-link[data-has-image=true][data-image-load-state=load-error] .gloss-image-container-overlay::after {\n content: 'Image failed to load';\n display: table-cell;\n width: 100%;\n height: 100%;\n vertical-align: middle;\n text-align: center;\n padding: 0.25em;\n}\n.gloss-image-background {\n --image: none;\n\n position: absolute;\n left: 0;\n top: 0;\n width: 100%;\n height: 100%;\n background-color: var(--text-color);\n -webkit-mask-repeat: no-repeat;\n -webkit-mask-position: center center;\n -webkit-mask-mode: alpha;\n -webkit-mask-size: contain;\n -webkit-mask-image: var(--image);\n mask-repeat: no-repeat;\n mask-position: center center;\n mask-mode: alpha;\n mask-size: contain;\n mask-image: var(--image);\n display: none;\n}\n.gloss-image {\n display: inline-block;\n vertical-align: top;\n object-fit: contain;\n border: none;\n outline: none;\n}\n.gloss-image-link[data-has-aspect-ratio=true] .gloss-image {\n position: absolute;\n left: 0;\n top: 0;\n width: 100%;\n height: 100%;\n}\n.gloss-image-link[data-image-rendering=pixelated] .gloss-image,\n.gloss-image-link[data-image-rendering=pixelated] .gloss-image-background {\n image-rendering: auto;\n image-rendering: -moz-crisp-edges;\n image-rendering: -webkit-optimize-contrast;\n image-rendering: pixelated;\n image-rendering: crisp-edges;\n}\n.gloss-image-link[data-image-rendering=crisp-edges] .gloss-image,\n.gloss-image-link[data-image-rendering=crisp-edges] .gloss-image-background {\n image-rendering: auto;\n image-rendering: -moz-crisp-edges;\n image-rendering: -webkit-optimize-contrast;\n image-rendering: crisp-edges;\n}\n:root[data-browser=firefox] .gloss-image-link[data-image-rendering=crisp-edges] .gloss-image,\n:root[data-browser=firefox] .gloss-image-link[data-image-rendering=crisp-edges] .gloss-image-background,\n:root[data-browser=firefox-mobile] .gloss-image-link[data-image-rendering=crisp-edges] .gloss-image,\n:root[data-browser=firefox-mobile] .gloss-image-link[data-image-rendering=crisp-edges] .gloss-image-background {\n image-rendering: auto;\n}\n.gloss-image-link[data-has-aspect-ratio=true] .gloss-image-sizer {\n display: inline-block;\n width: 0;\n vertical-align: top;\n font-size: 0;\n}\n.gloss-image-link-text {\n display: none;\n line-height: var(--line-height);\n}\n.gloss-image-link-text::before {\n content: '[';\n}\n.gloss-image-link-text::after {\n content: ']';\n}\n.gloss-image-description {\n display: block;\n white-space: pre-line;\n}\n\n.gloss-image-link[data-appearance=monochrome] .gloss-image {\n /* Workaround for coloring monochrome gloss images due to issues with masking using a canvas without loading extra media */\n /* drop-shadow with 0.01px blur is at minimum required for Firefox to render the shadow when used on a canvas */\n --shadow-settings: 0 0 0.01px var(--text-color);\n filter: grayscale(1) opacity(0.5) drop-shadow(var(--shadow-settings)) drop-shadow(var(--shadow-settings)) saturate(1000%) brightness(1000%);\n}\n\n.gloss-image-link[data-size-units=em] .gloss-image-container {\n font-size: 1em;\n}\n\n.gloss-image-link[data-vertical-align=baseline] { vertical-align: baseline; }\n.gloss-image-link[data-vertical-align=sub] { vertical-align: sub; }\n.gloss-image-link[data-vertical-align=super] { vertical-align: super; }\n.gloss-image-link[data-vertical-align=text-top] { vertical-align: top; }\n.gloss-image-link[data-vertical-align=text-bottom] { vertical-align: bottom; }\n.gloss-image-link[data-vertical-align=middle] { vertical-align: middle; }\n.gloss-image-link[data-vertical-align=top] { vertical-align: top; }\n.gloss-image-link[data-vertical-align=bottom] { vertical-align: bottom; }\n.gloss-image-link[data-collapsed=true],\n:root[data-glossary-layout-mode^=compact] .gloss-image-link[data-collapsible=true] {\n vertical-align: baseline;\n}\n\n.gloss-image-link[data-collapsed=true] .gloss-image-container,\n:root[data-glossary-layout-mode^=compact] .gloss-image-link[data-collapsible=true] .gloss-image-container {\n display: none;\n position: absolute;\n left: 0;\n top: 100%;\n z-index: 1;\n}\n.entry:nth-last-of-type(1):not(:nth-of-type(1)) .gloss-image-link[data-collapsed=true] .gloss-image-container,\n:root[data-glossary-layout-mode^=compact] .entry:nth-last-of-type(1):not(:nth-of-type(1)) .gloss-image-link[data-collapsible=true] .gloss-image-container,\n:root[data-glossary-layout-mode^=compact] .definition-item:nth-last-of-type(1) .gloss-image-link[data-collapsible=true] .gloss-image-container {\n bottom: 100%;\n top: auto;\n}\n.gloss-image-link[data-collapsed=true]:hover .gloss-image-container,\n.gloss-image-link[data-collapsed=true]:focus .gloss-image-container,\n:root[data-glossary-layout-mode^=compact] .gloss-image-link[data-collapsible=true]:hover .gloss-image-container,\n:root[data-glossary-layout-mode^=compact] .gloss-image-link[data-collapsible=true]:focus .gloss-image-container {\n display: block;\n}\n.gloss-image-link[data-collapsed=true] .gloss-image-link-text,\n:root[data-glossary-layout-mode^=compact] .gloss-image-link[data-collapsible=true] .gloss-image-link-text {\n display: inline;\n}\n.gloss-image-link[data-collapsed=true]~.gloss-image-description,\n:root[data-glossary-layout-mode^=compact] .gloss-image-description {\n display: inline;\n}\n\n\n/* Links */\n.gloss-link-text {\n vertical-align: baseline;\n}\n.gloss-link-external-icon {\n display: inline-block;\n vertical-align: middle;\n width: calc(16em / var(--font-size-no-units));\n height: calc(16em / var(--font-size-no-units));\n margin-left: 0.25em;\n background-color: var(--link-color);\n position: relative;\n}\n\n\n/* Structured content glossary styles */\n.gloss-sc-table-container {\n display: block;\n}\n.gloss-sc-table {\n table-layout: auto;\n border-collapse: collapse;\n}\n.gloss-sc-thead,\n.gloss-sc-tfoot,\n.gloss-sc-th {\n font-weight: bold;\n background-color: var(--background-color-dark1);\n}\n.gloss-sc-th,\n.gloss-sc-td {\n border-width: calc(1em / var(--font-size-no-units));\n border-style: solid;\n border-color: var(--text-color-light2);\n padding: 0.25em;\n vertical-align: top;\n}\n.gloss-sc-ol,\n.gloss-sc-ul {\n padding-left: var(--list-padding2);\n}\n:root[data-glossary-layout-mode^=compact] .gloss-sc-ul[data-sc-content=glossary] {\n display: inline;\n list-style: none;\n padding-left: 0;\n}\n:root[data-glossary-layout-mode^=compact] .gloss-sc-ul[data-sc-content=glossary] .gloss-sc-li {\n display: inline;\n}\n:root[data-glossary-layout-mode^=compact] .gloss-sc-ul[data-sc-content=glossary] .gloss-sc-li:not(:first-child)::before {\n white-space: pre-wrap;\n content: var(--compact-list-separator);\n display: inline;\n color: var(--text-color-light3);\n}\n.gloss-sc-details {\n padding-left: var(--list-padding1);\n}\n.gloss-sc-summary {\n list-style-position: outside;\n}\n`;\n","/*\n * Copyright (C) 2023-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 * The pronunciation CSS styles from the Yomitan extension.\n * Sourced from Yomitan's ext/css/display-pronunciation.css.\n */\nexport const PRONUNCIATION_CSS = `/*\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 entrys 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:root {\n --pronunciation-annotation-color: #000000;\n}\n:root[data-theme=dark] {\n --pronunciation-annotation-color: #ffffff;\n}\n\n.pronunciation-downstep-notation {\n display: inline;\n}\n\n.pronunciation-text {\n display: inline;\n}\n.pronunciation-mora {\n display: inline-block;\n position: relative;\n}\n.pronunciation-mora-line {\n border-color: var(--pronunciation-annotation-color);\n}\n.pronunciation-mora[data-pitch=high]>.pronunciation-mora-line {\n display: block;\n user-select: none;\n pointer-events: none;\n position: absolute;\n top: 0.1em;\n left: 0;\n right: 0;\n height: 0;\n border-top-width: 0.1em;\n border-top-style: solid;\n}\n.pronunciation-mora[data-pitch=high][data-pitch-next=low]>.pronunciation-mora-line {\n right: -0.1em;\n height: 0.4em;\n border-right-width: 0.1em;\n border-right-style: solid;\n}\n.pronunciation-mora[data-pitch=high][data-pitch-next=low] {\n padding-right: 0.1em;\n margin-right: 0.1em;\n}\n.pronunciation-devoice-indicator {\n display: block;\n position: absolute;\n left: 50%;\n top: 50%;\n width: 1.125em;\n height: 1.125em;\n border: calc(1.5em / var(--font-size-no-units)) dotted var(--danger-color);\n border-radius: 50%;\n box-sizing: border-box;\n z-index: 1;\n transform: translate(-50%, -50%);\n}\n.pronunciation-nasal-indicator {\n display: block;\n position: absolute;\n right: -0.125em;\n top: 0.125em;\n width: 0.375em;\n height: 0.375em;\n border: calc(1.5em / var(--font-size-no-units)) solid var(--danger-color);\n border-radius: 50%;\n box-sizing: border-box;\n z-index: 1;\n}\n.pronunciation-nasal-diacritic {\n position: absolute;\n width: 0;\n height: 0;\n opacity: 0;\n}\n.pronunciation-character {\n display: inline;\n}\n.pronunciation-character-group {\n display: inline-block;\n position: relative;\n}\n\n.pronunciation-graph {\n display: inline-block;\n vertical-align: middle;\n height: 1.5em;\n}\n.pronunciation-graph-line,\n.pronunciation-graph-line-tail {\n fill: none;\n stroke: var(--pronunciation-annotation-color);\n stroke-width: 5;\n}\n.pronunciation-graph-line-tail {\n stroke-dasharray: 5 5;\n}\n.pronunciation-graph-dot {\n fill: var(--pronunciation-annotation-color);\n stroke: var(--pronunciation-annotation-color);\n stroke-width: 5;\n}\n.pronunciation-graph-dot-downstep1 {\n fill: none;\n stroke: var(--pronunciation-annotation-color);\n stroke-width: 5;\n}\n.pronunciation-graph-dot-downstep2 {\n fill: var(--pronunciation-annotation-color);\n}\n.pronunciation-graph-triangle {\n fill: none;\n stroke: var(--pronunciation-annotation-color);\n stroke-width: 5;\n}\n`;\n"],"mappings":";;;;;;;;;;;;;AAiDA,IAAa,qBAAb,MAA0D;CACtD,UAAUA,OAAeC,aAAqBC,YAA4B;AACtE,SAAO;CACV;CAED,YAAYC,SAA4BC,MAAcC,WAA0B;AAC5E,UAAQ,OAAO;CAClB;CAED,YAAkB,CAAE;AACvB;;;;;;;;;;;;;;AC/BD,SAAgB,YAAYC,KAAqB;CAC7C,MAAM,YAAY,IAAI;AACtB,WAAU,YAAY,IAAI;AAC1B,QAAO,MAAM,KAAK,UAAU,SAAS,CAChC,IAAI,CAAC,SAAS,KAAK,WAAW,GAAG,CACjC,KAAK,KAAK;AAClB;;;;;;;;AASD,SAAgB,cAAcA,KAAaC,eAA+B;AACtE,SAAQ,EAAE,cAAc,IAAI,IAAI;AACnC;;;;;;;;;AAUD,SAAgB,oBAAoBD,KAAaC,eAA+B;AAC5E,KAAI;EACA,MAAM,aAAa,IAAI;AACvB,aAAW,YAAY,IAAI;EAC3B,MAAMC,cAAwB,CAAE;AAChC,OAAK,MAAM,WAAW,MAAM,KAAK,WAAW,SAAS,EAAE;AACnD,SAAM,kBAAkB,SACpB;GAGJ,MAAM,YAAY;GAClB,MAAMC,eAAyB,CAAE;AACjC,QAAK,MAAM,YAAY,UAAU,aAAa,MAAM,IAAI,CACpD,cAAa,MAAM,EAAE,cAAc,GAAG,SAAS,EAAE;GAErD,MAAM,UAAU,UAAU,QAAQ,QAAQ,UAAU,cAAc,aAAa,KAAK,KAAK,CAAC;AAC1F,eAAY,KAAK,QAAQ;EAC5B;AACD,aAAW,YAAY,YAAY,KAAK,KAAK,CAAC;AAC9C,SAAO,MAAM,KAAK,WAAW,SAAS,CACjC,IAAI,CAAC,SAAS,KAAK,WAAW,GAAG,CACjC,KAAK,KAAK;CAClB,SAAQ,IAAI;AACT,SAAO,cAAc,KAAK,cAAc;CAC3C;AACJ;;;;;;;;;AC1DD,MAAa,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACDlC,MAAa,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACA5B,MAAa,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACAvC,MAAa,qBAAqB"}
@@ -0,0 +1,126 @@
1
+ import { distributeFurigana } from "./furigana-B3-0y231.js";
2
+
3
+ //#region src/lookup/sentence-parser.ts
4
+ /**
5
+ * Parses text into segments with dictionary lookups using a left-to-right
6
+ * sliding window (longest match) algorithm.
7
+ */
8
+ var SentenceParser = class {
9
+ _translator;
10
+ constructor(translator) {
11
+ this._translator = translator;
12
+ }
13
+ /**
14
+ * Parses the given text into lines of parsed segments.
15
+ * For each position, attempts to find the longest dictionary match by
16
+ * querying the translator with progressively shorter substrings.
17
+ * Generates furigana for Japanese text segments.
18
+ */
19
+ async parseText(text, language, options) {
20
+ const maxLength = options.maxLength ?? 20;
21
+ const enabledDictionaryMap = this._buildFindTermDictionaryMap(options.enabledDictionaryMap);
22
+ const lines = text.split("\n");
23
+ const results = [];
24
+ for (const line of lines) {
25
+ const segments = await this._parseLine(line, language, enabledDictionaryMap, maxLength);
26
+ results.push({ segments });
27
+ }
28
+ return results;
29
+ }
30
+ /**
31
+ * Parses a single line of text into segments.
32
+ */
33
+ async _parseLine(line, language, enabledDictionaryMap, maxLength) {
34
+ const segments = [];
35
+ let position = 0;
36
+ while (position < line.length) {
37
+ const remaining = line.substring(position);
38
+ const searchLength = Math.min(remaining.length, maxLength);
39
+ let bestMatch = null;
40
+ for (let len = searchLength; len > 0; --len) {
41
+ const substring = remaining.substring(0, len);
42
+ const findTermsOptions = this._createFindTermsOptions(language, enabledDictionaryMap);
43
+ try {
44
+ const { dictionaryEntries, originalTextLength } = await this._translator.findTerms("simple", substring, findTermsOptions);
45
+ if (dictionaryEntries.length > 0 && originalTextLength > 0) {
46
+ const firstEntry = dictionaryEntries[0];
47
+ const headword = firstEntry.headwords[0];
48
+ bestMatch = {
49
+ length: originalTextLength,
50
+ entries: dictionaryEntries,
51
+ term: headword.term,
52
+ reading: headword.reading
53
+ };
54
+ break;
55
+ }
56
+ } catch {}
57
+ }
58
+ if (bestMatch !== null) {
59
+ const surfaceText = remaining.substring(0, bestMatch.length);
60
+ const furigana = language === "ja" ? distributeFurigana(surfaceText, bestMatch.reading) : [{
61
+ text: surfaceText,
62
+ reading: ""
63
+ }];
64
+ segments.push({
65
+ text: surfaceText,
66
+ reading: bestMatch.reading,
67
+ term: bestMatch.term,
68
+ entries: bestMatch.entries,
69
+ furigana
70
+ });
71
+ position += bestMatch.length;
72
+ } else {
73
+ const char = remaining.substring(0, 1);
74
+ segments.push({
75
+ text: char,
76
+ reading: "",
77
+ term: char,
78
+ entries: [],
79
+ furigana: [{
80
+ text: char,
81
+ reading: ""
82
+ }]
83
+ });
84
+ position += char.length;
85
+ }
86
+ }
87
+ return segments;
88
+ }
89
+ /**
90
+ * Builds a FindTermDictionary map from the simplified input format.
91
+ */
92
+ _buildFindTermDictionaryMap(inputMap) {
93
+ const result = new Map();
94
+ for (const [name, { index }] of inputMap.entries()) result.set(name, {
95
+ index,
96
+ alias: name,
97
+ allowSecondarySearches: false,
98
+ partsOfSpeechFilter: true,
99
+ useDeinflections: true
100
+ });
101
+ return result;
102
+ }
103
+ /**
104
+ * Creates a FindTermsOptions for simple lookup.
105
+ */
106
+ _createFindTermsOptions(language, enabledDictionaryMap) {
107
+ return {
108
+ matchType: "exact",
109
+ deinflect: true,
110
+ primaryReading: "",
111
+ mainDictionary: "",
112
+ sortFrequencyDictionary: null,
113
+ sortFrequencyDictionaryOrder: "descending",
114
+ removeNonJapaneseCharacters: language === "ja" || language === "zh" || language === "yue" || language === "ko",
115
+ textReplacements: [null],
116
+ enabledDictionaryMap,
117
+ excludeDictionaryDefinitions: null,
118
+ searchResolution: "letter",
119
+ language
120
+ };
121
+ }
122
+ };
123
+
124
+ //#endregion
125
+ export { SentenceParser };
126
+ //# sourceMappingURL=sentence-parser-BPAJNzqW.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sentence-parser-BPAJNzqW.js","names":["translator: Translator","text: string","language: string","options: SentenceParserOptions","results: ParsedLine[]","line: string","enabledDictionaryMap: Map<string, FindTermDictionary>","maxLength: number","segments: ParsedSegment[]","bestMatch: {\n length: number;\n entries: TermDictionaryEntry[];\n term: string;\n reading: string;\n } | null","inputMap: Map<string, { index: number; priority: number }>"],"sources":["../src/lookup/sentence-parser.ts"],"sourcesContent":["/*\n * Copyright (C) 2023-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\nimport { distributeFurigana } from '../language/ja/furigana';\nimport type { FuriganaSegment } from '../language/ja/furigana';\nimport type { TermDictionaryEntry } from '../types/dictionary';\nimport type { FindTermDictionary } from '../types/translation';\nimport type { Translator } from './translator';\n\nexport interface ParsedSegment {\n /** The surface text of this segment. */\n text: string;\n /** The reading (furigana) for this segment, or empty string if no reading. */\n reading: string;\n /** The dictionary form (headword term) matched for this segment, or the surface text if no match. */\n term: string;\n /** The dictionary entries found for this segment. */\n entries: TermDictionaryEntry[];\n /** Furigana distribution for this segment. */\n furigana: FuriganaSegment[];\n}\n\nexport interface ParsedLine {\n /** The parsed segments for this line. */\n segments: ParsedSegment[];\n}\n\nexport interface SentenceParserOptions {\n /** The enabled dictionary map for lookups. */\n enabledDictionaryMap: Map<string, { index: number; priority: number }>;\n /** Maximum character length for substring lookups. Defaults to 20. */\n maxLength?: number;\n}\n\n/**\n * Parses text into segments with dictionary lookups using a left-to-right\n * sliding window (longest match) algorithm.\n */\nexport class SentenceParser {\n private _translator: Translator;\n\n constructor(translator: Translator) {\n this._translator = translator;\n }\n\n /**\n * Parses the given text into lines of parsed segments.\n * For each position, attempts to find the longest dictionary match by\n * querying the translator with progressively shorter substrings.\n * Generates furigana for Japanese text segments.\n */\n async parseText(text: string, language: string, options: SentenceParserOptions): Promise<ParsedLine[]> {\n const maxLength = options.maxLength ?? 20;\n const enabledDictionaryMap = this._buildFindTermDictionaryMap(options.enabledDictionaryMap);\n\n const lines = text.split('\\n');\n const results: ParsedLine[] = [];\n\n for (const line of lines) {\n const segments = await this._parseLine(line, language, enabledDictionaryMap, maxLength);\n results.push({ segments });\n }\n\n return results;\n }\n\n /**\n * Parses a single line of text into segments.\n */\n private async _parseLine(\n line: string,\n language: string,\n enabledDictionaryMap: Map<string, FindTermDictionary>,\n maxLength: number,\n ): Promise<ParsedSegment[]> {\n const segments: ParsedSegment[] = [];\n let position = 0;\n\n while (position < line.length) {\n const remaining = line.substring(position);\n const searchLength = Math.min(remaining.length, maxLength);\n\n let bestMatch: {\n length: number;\n entries: TermDictionaryEntry[];\n term: string;\n reading: string;\n } | null = null;\n\n // Try progressively shorter substrings from longest to shortest\n for (let len = searchLength; len > 0; --len) {\n const substring = remaining.substring(0, len);\n\n const findTermsOptions = this._createFindTermsOptions(language, enabledDictionaryMap);\n\n try {\n const { dictionaryEntries, originalTextLength } = await this._translator.findTerms(\n 'simple',\n substring,\n findTermsOptions,\n );\n\n if (dictionaryEntries.length > 0 && originalTextLength > 0) {\n const firstEntry = dictionaryEntries[0];\n const headword = firstEntry.headwords[0];\n bestMatch = {\n length: originalTextLength,\n entries: dictionaryEntries,\n term: headword.term,\n reading: headword.reading,\n };\n break;\n }\n } catch {}\n }\n\n if (bestMatch !== null) {\n const surfaceText = remaining.substring(0, bestMatch.length);\n const furigana =\n language === 'ja'\n ? distributeFurigana(surfaceText, bestMatch.reading)\n : [{ text: surfaceText, reading: '' }];\n\n segments.push({\n text: surfaceText,\n reading: bestMatch.reading,\n term: bestMatch.term,\n entries: bestMatch.entries,\n furigana,\n });\n position += bestMatch.length;\n } else {\n // No match found; consume one character\n const char = remaining.substring(0, 1);\n segments.push({\n text: char,\n reading: '',\n term: char,\n entries: [],\n furigana: [{ text: char, reading: '' }],\n });\n position += char.length;\n }\n }\n\n return segments;\n }\n\n /**\n * Builds a FindTermDictionary map from the simplified input format.\n */\n private _buildFindTermDictionaryMap(\n inputMap: Map<string, { index: number; priority: number }>,\n ): Map<string, FindTermDictionary> {\n const result = new Map<string, FindTermDictionary>();\n for (const [name, { index }] of inputMap.entries()) {\n result.set(name, {\n index,\n alias: name,\n allowSecondarySearches: false,\n partsOfSpeechFilter: true,\n useDeinflections: true,\n });\n }\n return result;\n }\n\n /**\n * Creates a FindTermsOptions for simple lookup.\n */\n private _createFindTermsOptions(language: string, enabledDictionaryMap: Map<string, FindTermDictionary>) {\n return {\n matchType: 'exact' as const,\n deinflect: true,\n primaryReading: '',\n mainDictionary: '',\n sortFrequencyDictionary: null,\n sortFrequencyDictionaryOrder: 'descending' as const,\n removeNonJapaneseCharacters:\n language === 'ja' || language === 'zh' || language === 'yue' || language === 'ko',\n textReplacements: [null],\n enabledDictionaryMap,\n excludeDictionaryDefinitions: null,\n searchResolution: 'letter' as const,\n language,\n };\n }\n}\n"],"mappings":";;;;;;;AAoDA,IAAa,iBAAb,MAA4B;CACxB,AAAQ;CAER,YAAYA,YAAwB;AAChC,OAAK,cAAc;CACtB;;;;;;;CAQD,MAAM,UAAUC,MAAcC,UAAkBC,SAAuD;EACnG,MAAM,YAAY,QAAQ,aAAa;EACvC,MAAM,uBAAuB,KAAK,4BAA4B,QAAQ,qBAAqB;EAE3F,MAAM,QAAQ,KAAK,MAAM,KAAK;EAC9B,MAAMC,UAAwB,CAAE;AAEhC,OAAK,MAAM,QAAQ,OAAO;GACtB,MAAM,WAAW,MAAM,KAAK,WAAW,MAAM,UAAU,sBAAsB,UAAU;AACvF,WAAQ,KAAK,EAAE,SAAU,EAAC;EAC7B;AAED,SAAO;CACV;;;;CAKD,MAAc,WACVC,MACAH,UACAI,sBACAC,WACwB;EACxB,MAAMC,WAA4B,CAAE;EACpC,IAAI,WAAW;AAEf,SAAO,WAAW,KAAK,QAAQ;GAC3B,MAAM,YAAY,KAAK,UAAU,SAAS;GAC1C,MAAM,eAAe,KAAK,IAAI,UAAU,QAAQ,UAAU;GAE1D,IAAIC,YAKO;AAGX,QAAK,IAAI,MAAM,cAAc,MAAM,GAAG,EAAE,KAAK;IACzC,MAAM,YAAY,UAAU,UAAU,GAAG,IAAI;IAE7C,MAAM,mBAAmB,KAAK,wBAAwB,UAAU,qBAAqB;AAErF,QAAI;KACA,MAAM,EAAE,mBAAmB,oBAAoB,GAAG,MAAM,KAAK,YAAY,UACrE,UACA,WACA,iBACH;AAED,SAAI,kBAAkB,SAAS,KAAK,qBAAqB,GAAG;MACxD,MAAM,aAAa,kBAAkB;MACrC,MAAM,WAAW,WAAW,UAAU;AACtC,kBAAY;OACR,QAAQ;OACR,SAAS;OACT,MAAM,SAAS;OACf,SAAS,SAAS;MACrB;AACD;KACH;IACJ,QAAO,CAAE;GACb;AAED,OAAI,cAAc,MAAM;IACpB,MAAM,cAAc,UAAU,UAAU,GAAG,UAAU,OAAO;IAC5D,MAAM,WACF,aAAa,OACP,mBAAmB,aAAa,UAAU,QAAQ,GAClD,CAAC;KAAE,MAAM;KAAa,SAAS;IAAI,CAAC;AAE9C,aAAS,KAAK;KACV,MAAM;KACN,SAAS,UAAU;KACnB,MAAM,UAAU;KAChB,SAAS,UAAU;KACnB;IACH,EAAC;AACF,gBAAY,UAAU;GACzB,OAAM;IAEH,MAAM,OAAO,UAAU,UAAU,GAAG,EAAE;AACtC,aAAS,KAAK;KACV,MAAM;KACN,SAAS;KACT,MAAM;KACN,SAAS,CAAE;KACX,UAAU,CAAC;MAAE,MAAM;MAAM,SAAS;KAAI,CAAC;IAC1C,EAAC;AACF,gBAAY,KAAK;GACpB;EACJ;AAED,SAAO;CACV;;;;CAKD,AAAQ,4BACJC,UAC+B;EAC/B,MAAM,SAAS,IAAI;AACnB,OAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,SAAS,SAAS,CAC9C,QAAO,IAAI,MAAM;GACb;GACA,OAAO;GACP,wBAAwB;GACxB,qBAAqB;GACrB,kBAAkB;EACrB,EAAC;AAEN,SAAO;CACV;;;;CAKD,AAAQ,wBAAwBR,UAAkBI,sBAAuD;AACrG,SAAO;GACH,WAAW;GACX,WAAW;GACX,gBAAgB;GAChB,gBAAgB;GAChB,yBAAyB;GACzB,8BAA8B;GAC9B,6BACI,aAAa,QAAQ,aAAa,QAAQ,aAAa,SAAS,aAAa;GACjF,kBAAkB,CAAC,IAAK;GACxB;GACA,8BAA8B;GAC9B,kBAAkB;GAClB;EACH;CACJ;AACJ"}
@@ -0,0 +1,132 @@
1
+ "use strict";
2
+ const require_furigana = require('./furigana-DpZLcues.cjs');
3
+
4
+ //#region src/lookup/sentence-parser.ts
5
+ /**
6
+ * Parses text into segments with dictionary lookups using a left-to-right
7
+ * sliding window (longest match) algorithm.
8
+ */
9
+ var SentenceParser = class {
10
+ _translator;
11
+ constructor(translator) {
12
+ this._translator = translator;
13
+ }
14
+ /**
15
+ * Parses the given text into lines of parsed segments.
16
+ * For each position, attempts to find the longest dictionary match by
17
+ * querying the translator with progressively shorter substrings.
18
+ * Generates furigana for Japanese text segments.
19
+ */
20
+ async parseText(text, language, options) {
21
+ const maxLength = options.maxLength ?? 20;
22
+ const enabledDictionaryMap = this._buildFindTermDictionaryMap(options.enabledDictionaryMap);
23
+ const lines = text.split("\n");
24
+ const results = [];
25
+ for (const line of lines) {
26
+ const segments = await this._parseLine(line, language, enabledDictionaryMap, maxLength);
27
+ results.push({ segments });
28
+ }
29
+ return results;
30
+ }
31
+ /**
32
+ * Parses a single line of text into segments.
33
+ */
34
+ async _parseLine(line, language, enabledDictionaryMap, maxLength) {
35
+ const segments = [];
36
+ let position = 0;
37
+ while (position < line.length) {
38
+ const remaining = line.substring(position);
39
+ const searchLength = Math.min(remaining.length, maxLength);
40
+ let bestMatch = null;
41
+ for (let len = searchLength; len > 0; --len) {
42
+ const substring = remaining.substring(0, len);
43
+ const findTermsOptions = this._createFindTermsOptions(language, enabledDictionaryMap);
44
+ try {
45
+ const { dictionaryEntries, originalTextLength } = await this._translator.findTerms("simple", substring, findTermsOptions);
46
+ if (dictionaryEntries.length > 0 && originalTextLength > 0) {
47
+ const firstEntry = dictionaryEntries[0];
48
+ const headword = firstEntry.headwords[0];
49
+ bestMatch = {
50
+ length: originalTextLength,
51
+ entries: dictionaryEntries,
52
+ term: headword.term,
53
+ reading: headword.reading
54
+ };
55
+ break;
56
+ }
57
+ } catch {}
58
+ }
59
+ if (bestMatch !== null) {
60
+ const surfaceText = remaining.substring(0, bestMatch.length);
61
+ const furigana = language === "ja" ? require_furigana.distributeFurigana(surfaceText, bestMatch.reading) : [{
62
+ text: surfaceText,
63
+ reading: ""
64
+ }];
65
+ segments.push({
66
+ text: surfaceText,
67
+ reading: bestMatch.reading,
68
+ term: bestMatch.term,
69
+ entries: bestMatch.entries,
70
+ furigana
71
+ });
72
+ position += bestMatch.length;
73
+ } else {
74
+ const char = remaining.substring(0, 1);
75
+ segments.push({
76
+ text: char,
77
+ reading: "",
78
+ term: char,
79
+ entries: [],
80
+ furigana: [{
81
+ text: char,
82
+ reading: ""
83
+ }]
84
+ });
85
+ position += char.length;
86
+ }
87
+ }
88
+ return segments;
89
+ }
90
+ /**
91
+ * Builds a FindTermDictionary map from the simplified input format.
92
+ */
93
+ _buildFindTermDictionaryMap(inputMap) {
94
+ const result = new Map();
95
+ for (const [name, { index }] of inputMap.entries()) result.set(name, {
96
+ index,
97
+ alias: name,
98
+ allowSecondarySearches: false,
99
+ partsOfSpeechFilter: true,
100
+ useDeinflections: true
101
+ });
102
+ return result;
103
+ }
104
+ /**
105
+ * Creates a FindTermsOptions for simple lookup.
106
+ */
107
+ _createFindTermsOptions(language, enabledDictionaryMap) {
108
+ return {
109
+ matchType: "exact",
110
+ deinflect: true,
111
+ primaryReading: "",
112
+ mainDictionary: "",
113
+ sortFrequencyDictionary: null,
114
+ sortFrequencyDictionaryOrder: "descending",
115
+ removeNonJapaneseCharacters: language === "ja" || language === "zh" || language === "yue" || language === "ko",
116
+ textReplacements: [null],
117
+ enabledDictionaryMap,
118
+ excludeDictionaryDefinitions: null,
119
+ searchResolution: "letter",
120
+ language
121
+ };
122
+ }
123
+ };
124
+
125
+ //#endregion
126
+ Object.defineProperty(exports, 'SentenceParser', {
127
+ enumerable: true,
128
+ get: function () {
129
+ return SentenceParser;
130
+ }
131
+ });
132
+ //# sourceMappingURL=sentence-parser-BVIOI64h.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sentence-parser-BVIOI64h.cjs","names":["translator: Translator","text: string","language: string","options: SentenceParserOptions","results: ParsedLine[]","line: string","enabledDictionaryMap: Map<string, FindTermDictionary>","maxLength: number","segments: ParsedSegment[]","bestMatch: {\n length: number;\n entries: TermDictionaryEntry[];\n term: string;\n reading: string;\n } | null","inputMap: Map<string, { index: number; priority: number }>"],"sources":["../src/lookup/sentence-parser.ts"],"sourcesContent":["/*\n * Copyright (C) 2023-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\nimport { distributeFurigana } from '../language/ja/furigana';\nimport type { FuriganaSegment } from '../language/ja/furigana';\nimport type { TermDictionaryEntry } from '../types/dictionary';\nimport type { FindTermDictionary } from '../types/translation';\nimport type { Translator } from './translator';\n\nexport interface ParsedSegment {\n /** The surface text of this segment. */\n text: string;\n /** The reading (furigana) for this segment, or empty string if no reading. */\n reading: string;\n /** The dictionary form (headword term) matched for this segment, or the surface text if no match. */\n term: string;\n /** The dictionary entries found for this segment. */\n entries: TermDictionaryEntry[];\n /** Furigana distribution for this segment. */\n furigana: FuriganaSegment[];\n}\n\nexport interface ParsedLine {\n /** The parsed segments for this line. */\n segments: ParsedSegment[];\n}\n\nexport interface SentenceParserOptions {\n /** The enabled dictionary map for lookups. */\n enabledDictionaryMap: Map<string, { index: number; priority: number }>;\n /** Maximum character length for substring lookups. Defaults to 20. */\n maxLength?: number;\n}\n\n/**\n * Parses text into segments with dictionary lookups using a left-to-right\n * sliding window (longest match) algorithm.\n */\nexport class SentenceParser {\n private _translator: Translator;\n\n constructor(translator: Translator) {\n this._translator = translator;\n }\n\n /**\n * Parses the given text into lines of parsed segments.\n * For each position, attempts to find the longest dictionary match by\n * querying the translator with progressively shorter substrings.\n * Generates furigana for Japanese text segments.\n */\n async parseText(text: string, language: string, options: SentenceParserOptions): Promise<ParsedLine[]> {\n const maxLength = options.maxLength ?? 20;\n const enabledDictionaryMap = this._buildFindTermDictionaryMap(options.enabledDictionaryMap);\n\n const lines = text.split('\\n');\n const results: ParsedLine[] = [];\n\n for (const line of lines) {\n const segments = await this._parseLine(line, language, enabledDictionaryMap, maxLength);\n results.push({ segments });\n }\n\n return results;\n }\n\n /**\n * Parses a single line of text into segments.\n */\n private async _parseLine(\n line: string,\n language: string,\n enabledDictionaryMap: Map<string, FindTermDictionary>,\n maxLength: number,\n ): Promise<ParsedSegment[]> {\n const segments: ParsedSegment[] = [];\n let position = 0;\n\n while (position < line.length) {\n const remaining = line.substring(position);\n const searchLength = Math.min(remaining.length, maxLength);\n\n let bestMatch: {\n length: number;\n entries: TermDictionaryEntry[];\n term: string;\n reading: string;\n } | null = null;\n\n // Try progressively shorter substrings from longest to shortest\n for (let len = searchLength; len > 0; --len) {\n const substring = remaining.substring(0, len);\n\n const findTermsOptions = this._createFindTermsOptions(language, enabledDictionaryMap);\n\n try {\n const { dictionaryEntries, originalTextLength } = await this._translator.findTerms(\n 'simple',\n substring,\n findTermsOptions,\n );\n\n if (dictionaryEntries.length > 0 && originalTextLength > 0) {\n const firstEntry = dictionaryEntries[0];\n const headword = firstEntry.headwords[0];\n bestMatch = {\n length: originalTextLength,\n entries: dictionaryEntries,\n term: headword.term,\n reading: headword.reading,\n };\n break;\n }\n } catch {}\n }\n\n if (bestMatch !== null) {\n const surfaceText = remaining.substring(0, bestMatch.length);\n const furigana =\n language === 'ja'\n ? distributeFurigana(surfaceText, bestMatch.reading)\n : [{ text: surfaceText, reading: '' }];\n\n segments.push({\n text: surfaceText,\n reading: bestMatch.reading,\n term: bestMatch.term,\n entries: bestMatch.entries,\n furigana,\n });\n position += bestMatch.length;\n } else {\n // No match found; consume one character\n const char = remaining.substring(0, 1);\n segments.push({\n text: char,\n reading: '',\n term: char,\n entries: [],\n furigana: [{ text: char, reading: '' }],\n });\n position += char.length;\n }\n }\n\n return segments;\n }\n\n /**\n * Builds a FindTermDictionary map from the simplified input format.\n */\n private _buildFindTermDictionaryMap(\n inputMap: Map<string, { index: number; priority: number }>,\n ): Map<string, FindTermDictionary> {\n const result = new Map<string, FindTermDictionary>();\n for (const [name, { index }] of inputMap.entries()) {\n result.set(name, {\n index,\n alias: name,\n allowSecondarySearches: false,\n partsOfSpeechFilter: true,\n useDeinflections: true,\n });\n }\n return result;\n }\n\n /**\n * Creates a FindTermsOptions for simple lookup.\n */\n private _createFindTermsOptions(language: string, enabledDictionaryMap: Map<string, FindTermDictionary>) {\n return {\n matchType: 'exact' as const,\n deinflect: true,\n primaryReading: '',\n mainDictionary: '',\n sortFrequencyDictionary: null,\n sortFrequencyDictionaryOrder: 'descending' as const,\n removeNonJapaneseCharacters:\n language === 'ja' || language === 'zh' || language === 'yue' || language === 'ko',\n textReplacements: [null],\n enabledDictionaryMap,\n excludeDictionaryDefinitions: null,\n searchResolution: 'letter' as const,\n language,\n };\n }\n}\n"],"mappings":";;;;;;;;AAoDA,IAAa,iBAAb,MAA4B;CACxB,AAAQ;CAER,YAAYA,YAAwB;AAChC,OAAK,cAAc;CACtB;;;;;;;CAQD,MAAM,UAAUC,MAAcC,UAAkBC,SAAuD;EACnG,MAAM,YAAY,QAAQ,aAAa;EACvC,MAAM,uBAAuB,KAAK,4BAA4B,QAAQ,qBAAqB;EAE3F,MAAM,QAAQ,KAAK,MAAM,KAAK;EAC9B,MAAMC,UAAwB,CAAE;AAEhC,OAAK,MAAM,QAAQ,OAAO;GACtB,MAAM,WAAW,MAAM,KAAK,WAAW,MAAM,UAAU,sBAAsB,UAAU;AACvF,WAAQ,KAAK,EAAE,SAAU,EAAC;EAC7B;AAED,SAAO;CACV;;;;CAKD,MAAc,WACVC,MACAH,UACAI,sBACAC,WACwB;EACxB,MAAMC,WAA4B,CAAE;EACpC,IAAI,WAAW;AAEf,SAAO,WAAW,KAAK,QAAQ;GAC3B,MAAM,YAAY,KAAK,UAAU,SAAS;GAC1C,MAAM,eAAe,KAAK,IAAI,UAAU,QAAQ,UAAU;GAE1D,IAAIC,YAKO;AAGX,QAAK,IAAI,MAAM,cAAc,MAAM,GAAG,EAAE,KAAK;IACzC,MAAM,YAAY,UAAU,UAAU,GAAG,IAAI;IAE7C,MAAM,mBAAmB,KAAK,wBAAwB,UAAU,qBAAqB;AAErF,QAAI;KACA,MAAM,EAAE,mBAAmB,oBAAoB,GAAG,MAAM,KAAK,YAAY,UACrE,UACA,WACA,iBACH;AAED,SAAI,kBAAkB,SAAS,KAAK,qBAAqB,GAAG;MACxD,MAAM,aAAa,kBAAkB;MACrC,MAAM,WAAW,WAAW,UAAU;AACtC,kBAAY;OACR,QAAQ;OACR,SAAS;OACT,MAAM,SAAS;OACf,SAAS,SAAS;MACrB;AACD;KACH;IACJ,QAAO,CAAE;GACb;AAED,OAAI,cAAc,MAAM;IACpB,MAAM,cAAc,UAAU,UAAU,GAAG,UAAU,OAAO;IAC5D,MAAM,WACF,aAAa,OACP,oCAAmB,aAAa,UAAU,QAAQ,GAClD,CAAC;KAAE,MAAM;KAAa,SAAS;IAAI,CAAC;AAE9C,aAAS,KAAK;KACV,MAAM;KACN,SAAS,UAAU;KACnB,MAAM,UAAU;KAChB,SAAS,UAAU;KACnB;IACH,EAAC;AACF,gBAAY,UAAU;GACzB,OAAM;IAEH,MAAM,OAAO,UAAU,UAAU,GAAG,EAAE;AACtC,aAAS,KAAK;KACV,MAAM;KACN,SAAS;KACT,MAAM;KACN,SAAS,CAAE;KACX,UAAU,CAAC;MAAE,MAAM;MAAM,SAAS;KAAI,CAAC;IAC1C,EAAC;AACF,gBAAY,KAAK;GACpB;EACJ;AAED,SAAO;CACV;;;;CAKD,AAAQ,4BACJC,UAC+B;EAC/B,MAAM,SAAS,IAAI;AACnB,OAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,SAAS,SAAS,CAC9C,QAAO,IAAI,MAAM;GACb;GACA,OAAO;GACP,wBAAwB;GACxB,qBAAqB;GACrB,kBAAkB;EACrB,EAAC;AAEN,SAAO;CACV;;;;CAKD,AAAQ,wBAAwBR,UAAkBI,sBAAuD;AACrG,SAAO;GACH,WAAW;GACX,WAAW;GACX,gBAAgB;GAChB,gBAAgB;GAChB,yBAAyB;GACzB,8BAA8B;GAC9B,6BACI,aAAa,QAAQ,aAAa,QAAQ,aAAa,SAAS,aAAa;GACjF,kBAAkB,CAAC,IAAK;GACxB;GACA,8BAA8B;GAC9B,kBAAkB;GAClB;EACH;CACJ;AACJ"}
@@ -0,0 +1,5 @@
1
+ import "./cjk-util-DubXBGDG.js";
2
+ import "./furigana-B3-0y231.js";
3
+ import { SentenceParser } from "./sentence-parser-BPAJNzqW.js";
4
+
5
+ export { SentenceParser };
@@ -0,0 +1,5 @@
1
+ require('./cjk-util-Dp0ZU0sh.cjs');
2
+ require('./furigana-DpZLcues.cjs');
3
+ const require_sentence_parser = require('./sentence-parser-BVIOI64h.cjs');
4
+
5
+ exports.SentenceParser = require_sentence_parser.SentenceParser
@@ -0,0 +1,4 @@
1
+ require('./text-utilities-Del2Ivkg.cjs');
2
+ const require_structured_content_generator = require('./structured-content-generator-DrwkB0-k.cjs');
3
+
4
+ exports.StructuredContentGenerator = require_structured_content_generator.StructuredContentGenerator
@@ -0,0 +1,4 @@
1
+ import "./text-utilities-B7PIythe.js";
2
+ import { StructuredContentGenerator } from "./structured-content-generator-CLnybumI.js";
3
+
4
+ export { StructuredContentGenerator };