yomitan-core 1.0.1 → 1.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.
- package/README.md +17 -6
- package/dist/anki.cjs +2 -2
- package/dist/anki.js +2 -2
- package/dist/{display-generator-D_BNq27-.cjs → display-generator-BegC-lK-.cjs} +3 -3
- package/dist/{display-generator-CyzsQ0gI.js → display-generator-CEJQTOYP.js} +3 -3
- package/dist/{display-generator-lVhYMgbS.cjs → display-generator-CSWA_AMa.cjs} +24 -3
- package/dist/display-generator-CSWA_AMa.cjs.map +1 -0
- package/dist/{display-generator-Bp6tf6lY.js → display-generator-vxdAYHeK.js} +24 -3
- package/dist/display-generator-vxdAYHeK.js.map +1 -0
- package/dist/{furigana-CI6LUA-6.js → furigana-BpFJbm9M.js} +2 -2
- package/dist/{furigana-CI6LUA-6.js.map → furigana-BpFJbm9M.js.map} +1 -1
- package/dist/furigana-C3JCmlrA.js +5 -0
- package/dist/{furigana-BnY7-dJ-.cjs → furigana-dSFngFbc.cjs} +2 -2
- package/dist/{furigana-BnY7-dJ-.cjs.map → furigana-dSFngFbc.cjs.map} +1 -1
- package/dist/furigana-q-DH5eJV.cjs +5 -0
- package/dist/index.cjs +14 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -7
- package/dist/index.js.map +1 -1
- package/dist/{japanese-BVV1Ctk-.cjs → japanese-C83fmEfb.cjs} +1 -1
- package/dist/{japanese-BVV1Ctk-.cjs.map → japanese-C83fmEfb.cjs.map} +1 -1
- package/dist/{japanese-DhmmW35J.js → japanese-CKPyY5k_.js} +1 -1
- package/dist/{japanese-DhmmW35J.js.map → japanese-CKPyY5k_.js.map} +1 -1
- package/dist/language.cjs +11 -11
- package/dist/language.d.cts +41 -3
- package/dist/language.d.cts.map +1 -1
- package/dist/language.d.ts +41 -3
- package/dist/language.d.ts.map +1 -1
- package/dist/language.js +4 -4
- package/dist/lookup.cjs +4 -4
- package/dist/lookup.d.cts +5 -78
- package/dist/lookup.d.cts.map +1 -1
- package/dist/lookup.d.ts +5 -78
- package/dist/lookup.d.ts.map +1 -1
- package/dist/lookup.js +4 -4
- package/dist/multi-language-transformer-DvjBcuyp.js +12503 -0
- package/dist/multi-language-transformer-DvjBcuyp.js.map +1 -0
- package/dist/{multi-language-transformer-B2133Zg_.cjs → multi-language-transformer-N66Mmb2E.cjs} +9614 -5
- package/dist/multi-language-transformer-N66Mmb2E.cjs.map +1 -0
- package/dist/render.cjs +674 -546
- package/dist/render.cjs.map +1 -1
- package/dist/render.d.cts +67 -4
- package/dist/render.d.cts.map +1 -1
- package/dist/render.d.ts +67 -4
- package/dist/render.d.ts.map +1 -1
- package/dist/render.js +671 -547
- package/dist/render.js.map +1 -1
- package/dist/{translator-TiTDVbmS.d.cts → sentence-parser-BQpu2oSA.d.cts} +80 -4
- package/dist/sentence-parser-BQpu2oSA.d.cts.map +1 -0
- package/dist/{sentence-parser-sx7y6Oyh.js → sentence-parser-C8OC1Ix_.js} +18 -42
- package/dist/sentence-parser-C8OC1Ix_.js.map +1 -0
- package/dist/sentence-parser-CUoYJvJv.cjs +5 -0
- package/dist/sentence-parser-DG_7Th_q.js +5 -0
- package/dist/{translator-CYvGmODX.d.ts → sentence-parser-DnY0NA5g.d.ts} +80 -4
- package/dist/sentence-parser-DnY0NA5g.d.ts.map +1 -0
- package/dist/{sentence-parser-DUQJ3cTT.cjs → sentence-parser-ZSC_ntAi.cjs} +18 -42
- package/dist/sentence-parser-ZSC_ntAi.cjs.map +1 -0
- package/dist/translator-B5InyZJa.js +7 -0
- package/dist/{translator-CrDE1UJW.js → translator-COZI9EQT.js} +2 -2
- package/dist/{translator-CrDE1UJW.js.map → translator-COZI9EQT.js.map} +1 -1
- package/dist/{translator-B1uTusjx.cjs → translator-CYvu9gr1.cjs} +2 -2
- package/dist/{translator-B1uTusjx.cjs.map → translator-CYvu9gr1.cjs.map} +1 -1
- package/dist/translator-DAL8ugoC.cjs +7 -0
- package/package.json +1 -1
- package/dist/display-generator-Bp6tf6lY.js.map +0 -1
- package/dist/display-generator-lVhYMgbS.cjs.map +0 -1
- package/dist/furigana-cpPhFnBv.cjs +0 -5
- package/dist/furigana-kZjqnnFC.js +0 -5
- package/dist/japanese-DdsS8rT1.d.ts +0 -41
- package/dist/japanese-DdsS8rT1.d.ts.map +0 -1
- package/dist/japanese-DgmP3i76.d.cts +0 -41
- package/dist/japanese-DgmP3i76.d.cts.map +0 -1
- package/dist/multi-language-transformer-B2133Zg_.cjs.map +0 -1
- package/dist/multi-language-transformer-BkwMTV2g.js +0 -2893
- package/dist/multi-language-transformer-BkwMTV2g.js.map +0 -1
- package/dist/sentence-parser-B-gM8mKk.js +0 -5
- package/dist/sentence-parser-Cp3cm_QU.cjs +0 -5
- package/dist/sentence-parser-DUQJ3cTT.cjs.map +0 -1
- package/dist/sentence-parser-sx7y6Oyh.js.map +0 -1
- package/dist/translator-BiTHo9Nm.js +0 -7
- package/dist/translator-CYvGmODX.d.ts.map +0 -1
- package/dist/translator-TiTDVbmS.d.cts.map +0 -1
- package/dist/translator-Y7Haj_qJ.cjs +0 -7
package/README.md
CHANGED
|
@@ -310,20 +310,31 @@ const fields = await anki.getModelFieldNames('Basic');
|
|
|
310
310
|
import { parseHTML } from 'linkedom';
|
|
311
311
|
import {
|
|
312
312
|
DisplayGenerator,
|
|
313
|
-
HtmlTemplateCollection,
|
|
314
313
|
DISPLAY_TEMPLATES,
|
|
315
314
|
DISPLAY_CSS,
|
|
315
|
+
NoOpContentManager,
|
|
316
|
+
applyExtensionDisplayDefaults,
|
|
317
|
+
applyPopupTheme,
|
|
316
318
|
} from 'yomitan-core/render';
|
|
317
319
|
|
|
318
|
-
const { document } = parseHTML('<!DOCTYPE html><html><body></body></html>');
|
|
320
|
+
const { document } = parseHTML('<!DOCTYPE html><html><head></head><body></body></html>');
|
|
321
|
+
applyExtensionDisplayDefaults(document.documentElement);
|
|
322
|
+
|
|
323
|
+
// Optional: control popup body theme mode (light | dark | browser | site).
|
|
324
|
+
applyPopupTheme(document.documentElement, {theme: 'dark'});
|
|
325
|
+
// Equivalent examples:
|
|
326
|
+
// applyPopupTheme(document.documentElement, {theme: 'browser'});
|
|
327
|
+
// applyPopupTheme(document.documentElement, {theme: 'site', siteTheme: 'light'});
|
|
319
328
|
|
|
320
|
-
const
|
|
321
|
-
|
|
329
|
+
const style = document.createElement('style');
|
|
330
|
+
style.textContent = DISPLAY_CSS; // Includes display + structured content + pronunciation styles; uses data-theme for popup body theme
|
|
331
|
+
document.head.appendChild(style);
|
|
322
332
|
|
|
323
|
-
const generator = new DisplayGenerator(document,
|
|
333
|
+
const generator = new DisplayGenerator(document, new NoOpContentManager(), DISPLAY_TEMPLATES);
|
|
324
334
|
|
|
325
335
|
// Render a term entry to DOM nodes
|
|
326
|
-
const node = generator.createTermEntry(dictionaryEntry);
|
|
336
|
+
const node = generator.createTermEntry(dictionaryEntry, dictionaryInfo);
|
|
337
|
+
// Dictionary-specific styles.css from imported dictionaries are injected automatically per entry.
|
|
327
338
|
console.log(node.outerHTML);
|
|
328
339
|
```
|
|
329
340
|
|
package/dist/anki.cjs
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const require_utilities = require('./utilities-C-lbZaJE.cjs');
|
|
3
3
|
require('./cjk-util-Dp0ZU0sh.cjs');
|
|
4
|
-
const require_japanese = require('./japanese-
|
|
4
|
+
const require_japanese = require('./japanese-C83fmEfb.cjs');
|
|
5
5
|
const require_errors = require('./errors-ZI2FcGUl.cjs');
|
|
6
6
|
const require_dictionary_data_util = require('./dictionary-data-util-BY_72f3u.cjs');
|
|
7
7
|
require('./json-CyQBn52D.cjs');
|
|
8
|
-
require('./furigana-
|
|
8
|
+
require('./furigana-dSFngFbc.cjs');
|
|
9
9
|
const require_anki_connect = require('./anki-connect-B_YpChhu.cjs');
|
|
10
10
|
|
|
11
11
|
//#region src/anki/anki-note-builder.ts
|
package/dist/anki.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { deferPromise } from "./utilities-bi3EF-q5.js";
|
|
2
2
|
import "./cjk-util-DubXBGDG.js";
|
|
3
|
-
import { distributeFurigana } from "./japanese-
|
|
3
|
+
import { distributeFurigana } from "./japanese-CKPyY5k_.js";
|
|
4
4
|
import { YomitanError } from "./errors-D2JfYV-C.js";
|
|
5
5
|
import { getDisambiguations, getGroupedPronunciations, getPronunciationsOfType, getTermFrequency, groupTermTags, isNonNounVerbOrAdjective } from "./dictionary-data-util-CKDT7n2t.js";
|
|
6
6
|
import "./json-DTq_IXXF.js";
|
|
7
|
-
import "./furigana-
|
|
7
|
+
import "./furigana-BpFJbm9M.js";
|
|
8
8
|
import { AnkiConnect, cloneFieldMarkerPattern, getRootDeckName } from "./anki-connect-697E04LF.js";
|
|
9
9
|
|
|
10
10
|
//#region src/anki/anki-note-builder.ts
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
require('./cjk-util-Dp0ZU0sh.cjs');
|
|
2
|
-
require('./japanese-
|
|
2
|
+
require('./japanese-C83fmEfb.cjs');
|
|
3
3
|
require('./dictionary-data-util-BY_72f3u.cjs');
|
|
4
|
-
require('./furigana-
|
|
4
|
+
require('./furigana-dSFngFbc.cjs');
|
|
5
5
|
require('./text-utilities-CFDC9Bkr.cjs');
|
|
6
|
-
const require_display_generator = require('./display-generator-
|
|
6
|
+
const require_display_generator = require('./display-generator-CSWA_AMa.cjs');
|
|
7
7
|
require('./pronunciation-generator-B8y__W7I.cjs');
|
|
8
8
|
require('./structured-content-generator-C5Hhaurz.cjs');
|
|
9
9
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import "./cjk-util-DubXBGDG.js";
|
|
2
|
-
import "./japanese-
|
|
2
|
+
import "./japanese-CKPyY5k_.js";
|
|
3
3
|
import "./dictionary-data-util-CKDT7n2t.js";
|
|
4
|
-
import "./furigana-
|
|
4
|
+
import "./furigana-BpFJbm9M.js";
|
|
5
5
|
import "./text-utilities-D5eno9GK.js";
|
|
6
|
-
import { DisplayGenerator } from "./display-generator-
|
|
6
|
+
import { DisplayGenerator } from "./display-generator-vxdAYHeK.js";
|
|
7
7
|
import "./pronunciation-generator-cNtAQi5s.js";
|
|
8
8
|
import "./structured-content-generator-aJieXElq.js";
|
|
9
9
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
const require_japanese = require('./japanese-
|
|
2
|
+
const require_japanese = require('./japanese-C83fmEfb.cjs');
|
|
3
3
|
const require_dictionary_data_util = require('./dictionary-data-util-BY_72f3u.cjs');
|
|
4
4
|
const require_text_utilities = require('./text-utilities-CFDC9Bkr.cjs');
|
|
5
5
|
const require_pronunciation_generator = require('./pronunciation-generator-B8y__W7I.cjs');
|
|
@@ -27,7 +27,9 @@ var HtmlTemplateCollection = class {
|
|
|
27
27
|
* @param html - The HTML string containing `<template>` elements.
|
|
28
28
|
*/
|
|
29
29
|
loadFromString(html) {
|
|
30
|
-
const
|
|
30
|
+
const DOMParserConstructor = this._document.defaultView?.DOMParser ?? globalThis.DOMParser;
|
|
31
|
+
if (typeof DOMParserConstructor !== "function") throw new Error("DOMParser is unavailable for HtmlTemplateCollection.");
|
|
32
|
+
const parser = new DOMParserConstructor();
|
|
31
33
|
const templatesDocument = parser.parseFromString(html, "text/html");
|
|
32
34
|
this.load(templatesDocument);
|
|
33
35
|
}
|
|
@@ -229,6 +231,8 @@ var DisplayGenerator = class {
|
|
|
229
231
|
definitionsContainer.appendChild(node2);
|
|
230
232
|
}
|
|
231
233
|
definitionsContainer.dataset.count = `${definitions.length}`;
|
|
234
|
+
const dictionaryScopedStyleNode = this._createDictionaryScopedStyleNode(definitions, dictionaryInfo);
|
|
235
|
+
if (dictionaryScopedStyleNode !== null) node.appendChild(dictionaryScopedStyleNode);
|
|
232
236
|
return node;
|
|
233
237
|
}
|
|
234
238
|
/**
|
|
@@ -371,6 +375,23 @@ var DisplayGenerator = class {
|
|
|
371
375
|
this._appendMultiple(entriesContainer, this._createTermDefinitionEntry.bind(this), entries, dictionary);
|
|
372
376
|
return node;
|
|
373
377
|
}
|
|
378
|
+
_createDictionaryScopedStyleNode(definitions, dictionaryInfo) {
|
|
379
|
+
const usedDictionaries = new Set();
|
|
380
|
+
for (const { dictionary } of definitions) usedDictionaries.add(dictionary);
|
|
381
|
+
let scopedCss = "";
|
|
382
|
+
for (const dictionary of usedDictionaries) {
|
|
383
|
+
const info = dictionaryInfo.find(({ title }) => title === dictionary);
|
|
384
|
+
const styles = info?.styles?.trim() ?? "";
|
|
385
|
+
if (styles.length === 0) continue;
|
|
386
|
+
const escapedTitle = dictionary.replaceAll("\\", "\\\\").replaceAll("\"", "\\\"");
|
|
387
|
+
scopedCss += `\n[data-dictionary="${escapedTitle}"] {${styles}\n}`;
|
|
388
|
+
}
|
|
389
|
+
if (scopedCss.length === 0) return null;
|
|
390
|
+
const node = this._document.createElement("style");
|
|
391
|
+
node.className = "dictionary-entry-styles";
|
|
392
|
+
node.textContent = scopedCss;
|
|
393
|
+
return node;
|
|
394
|
+
}
|
|
374
395
|
_createTermDefinitionEntry(entry, dictionary) {
|
|
375
396
|
switch (typeof entry) {
|
|
376
397
|
case "string": return this._createTermDefinitionEntryText(entry);
|
|
@@ -755,4 +776,4 @@ Object.defineProperty(exports, 'HtmlTemplateCollection', {
|
|
|
755
776
|
return HtmlTemplateCollection;
|
|
756
777
|
}
|
|
757
778
|
});
|
|
758
|
-
//# sourceMappingURL=display-generator-
|
|
779
|
+
//# sourceMappingURL=display-generator-CSWA_AMa.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"display-generator-CSWA_AMa.cjs","names":["doc: Document","html: string","source: Document","name: string","template: HTMLTemplateElement","removeNodes: Node[]","doc: Document","contentManager: ContentManager","templateHtml: string","StructuredContentGenerator","PronunciationGenerator","language: string","dictionaryEntry: Dictionary.TermDictionaryEntry","dictionaryInfo: DictionaryImporter.Summary[]","dictionaryContentArray: string[]","dictionaryEntry: Dictionary.KanjiDictionaryEntry","name: string","headword: Dictionary.TermHeadword","headwordIndex: number","pronunciations: Dictionary.TermPronunciation[]","inflectionRuleChain: Dictionary.InflectionRuleChainCandidate","source: Dictionary.InflectionSource","inflection: Dictionary.InflectionRule","definition: Dictionary.TermDefinition","dictionaryTag: Dictionary.Tag","headwords: Dictionary.TermHeadword[]","uniqueTerms: Set<string>","uniqueReadings: Set<string>","definitions: Dictionary.TermDefinition[]","entry: DictionaryData.TermGlossaryContent","dictionary: string","text: string","data: DictionaryData.TermGlossaryImage","content: StructuredContent.Content","disambiguation: string","character: string","reading: string","details: Dictionary.KanjiStat[]","details: Dictionary.KanjiStat","tag: Dictionary.Tag","tagInfo: DictionaryDataUtil.TagGroup","totalHeadwordCount: number","category: string","details: DictionaryDataUtil.DictionaryGroupedPronunciations","details: DictionaryDataUtil.GroupedPronunciation","pronunciation: Dictionary.PhoneticTranscription","pitchAccent: Dictionary.PitchAccent","container: HTMLElement","exclusiveTerms: string[]","exclusiveReadings: string[]","details:\n | DictionaryDataUtil.DictionaryFrequency<DictionaryDataUtil.TermFrequency>\n | DictionaryDataUtil.DictionaryFrequency<DictionaryDataUtil.KanjiFrequency>","kanji: boolean","details: DictionaryDataUtil.TermFrequency","dictionaryAlias: string","freqCount: string | undefined","details: DictionaryDataUtil.KanjiFrequency","node: HTMLElement","values: DictionaryDataUtil.FrequencyValue[]","node2","createItem: (item: TItem, arg: TExtraArg) => Node | null","detailsArray: TItem[]","arg?: TExtraArg","term: string","addText: (element: HTMLElement, text: string) => void","value: string","language?: string","element: HTMLElement","language: string | undefined","content: string","termPronunciations: Dictionary.TermPronunciation[]","wordClasses: string[]","element: Element | DocumentFragment","selector: string"],"sources":["../src/render/html-template-collection.ts","../src/render/display-generator.ts"],"sourcesContent":["/*\n * Copyright (C) 2023-2025 Yomitan Authors\n * Copyright (C) 2020-2022 Yomichan Authors\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program. If not, see <https://www.gnu.org/licenses/>.\n */\n\n/**\n * A collection of HTML templates parsed from raw HTML strings.\n * Templates are identified by their `id` attribute, which must end with `-template`.\n * The prefix before `-template` is used as the template name.\n */\nexport class HtmlTemplateCollection {\n private _templates: Map<string, HTMLTemplateElement>;\n private _document: Document;\n\n /**\n * Creates a new HtmlTemplateCollection.\n * @param doc - The Document object to use for DOM operations.\n */\n constructor(doc: Document) {\n this._templates = new Map();\n this._document = doc;\n }\n\n /**\n * Loads templates from a raw HTML string.\n * @param html - The HTML string containing `<template>` elements.\n */\n loadFromString(html: string): void {\n const DOMParserConstructor =\n (this._document.defaultView as unknown as { DOMParser?: typeof DOMParser } | null)?.DOMParser ??\n globalThis.DOMParser;\n if (typeof DOMParserConstructor !== 'function') {\n throw new Error('DOMParser is unavailable for HtmlTemplateCollection.');\n }\n const parser = new DOMParserConstructor();\n const templatesDocument = parser.parseFromString(html, 'text/html');\n this.load(templatesDocument);\n }\n\n /**\n * Loads templates from a Document source.\n * @param source - The Document containing template elements.\n */\n load(source: Document): void {\n const pattern = /^([\\w\\W]+)-template$/;\n for (const template of Array.from(source.querySelectorAll('template')) as HTMLTemplateElement[]) {\n const match = pattern.exec(template.id);\n if (match === null) {\n continue;\n }\n this._prepareTemplate(template);\n this._templates.set(match[1], template);\n }\n }\n\n /**\n * Instantiates a template by name, returning the first element child as a deep clone.\n * @param name - The template name (without the `-template` suffix).\n * @returns The cloned first element child.\n * @throws Error if the template or its content element is not found.\n */\n instantiate(name: string): HTMLElement {\n const { firstElementChild } = this.getTemplateContent(name);\n if (firstElementChild === null) {\n throw new Error(`Failed to find template content element: ${name}`);\n }\n return this._document.importNode(firstElementChild, true) as HTMLElement;\n }\n\n /**\n * Instantiates a template by name, returning the entire content as a DocumentFragment clone.\n * @param name - The template name (without the `-template` suffix).\n * @returns The cloned DocumentFragment.\n */\n instantiateFragment(name: string): DocumentFragment {\n return this._document.importNode(this.getTemplateContent(name), true);\n }\n\n /**\n * Gets the content DocumentFragment of a named template.\n * @param name - The template name (without the `-template` suffix).\n * @returns The template's content DocumentFragment.\n * @throws Error if the template is not found.\n */\n getTemplateContent(name: string): DocumentFragment {\n const template = this._templates.get(name);\n if (typeof template === 'undefined') {\n throw new Error(`Failed to find template: ${name}`);\n }\n return template.content;\n }\n\n /**\n * Returns an iterator over all template elements.\n */\n getAllTemplates(): IterableIterator<HTMLTemplateElement> {\n return this._templates.values();\n }\n\n // Private\n\n private _prepareTemplate(template: HTMLTemplateElement): void {\n if (template.dataset.removeWhitespaceText === 'true') {\n this._removeWhitespaceText(template);\n }\n }\n\n private _removeWhitespaceText(template: HTMLTemplateElement): void {\n const { content } = template;\n const { TEXT_NODE } = this._document.defaultView\n ? (this._document.defaultView as unknown as { Node: typeof Node }).Node\n : { TEXT_NODE: 3 };\n const iterator = this._document.createNodeIterator(content, 4 /* NodeFilter.SHOW_TEXT */);\n const removeNodes: Node[] = [];\n while (true) {\n const node = iterator.nextNode();\n if (node === null) {\n break;\n }\n if (node.nodeType === TEXT_NODE && (node.nodeValue ?? '').trim().length === 0) {\n removeNodes.push(node);\n }\n }\n for (const node of removeNodes) {\n const { parentNode } = node;\n if (parentNode !== null) {\n parentNode.removeChild(node);\n }\n }\n }\n}\n","/*\n * Copyright (C) 2023-2025 Yomitan Authors\n * Copyright (C) 2019-2022 Yomichan Authors\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program. If not, see <https://www.gnu.org/licenses/>.\n */\n\nimport { distributeFurigana } from '../language/ja/furigana.js';\nimport { getLanguageFromText } from '../language/text-utilities.js';\nimport type * as DictionaryDataUtil from '../types/dictionary-data-util.js';\nimport type * as DictionaryData from '../types/dictionary-data.js';\nimport type * as DictionaryImporter from '../types/dictionary-importer.js';\nimport type * as Dictionary from '../types/dictionary.js';\nimport type * as StructuredContent from '../types/structured-content.js';\nimport {\n getDisambiguations,\n getGroupedPronunciations,\n getTermFrequency,\n groupKanjiFrequencies,\n groupTermFrequencies,\n groupTermTags,\n isNonNounVerbOrAdjective,\n} from '../util/dictionary-data-util.js';\nimport type { ContentManager } from './content-manager.js';\nimport { HtmlTemplateCollection } from './html-template-collection.js';\nimport { getKanaMorae, getPitchCategory, isCodePointKanji } from './japanese-util.js';\nimport type { PitchCategory } from './japanese-util.js';\nimport { PronunciationGenerator } from './pronunciation-generator.js';\nimport { StructuredContentGenerator } from './structured-content-generator.js';\n\n/**\n * Generates DOM elements for displaying dictionary entries.\n * This is the main rendering class that creates term entries, kanji entries,\n * and all associated sub-elements (headwords, definitions, tags, frequencies, etc.).\n */\nexport class DisplayGenerator {\n private _contentManager: ContentManager;\n private _templates: HtmlTemplateCollection;\n private _structuredContentGenerator: StructuredContentGenerator;\n private _pronunciationGenerator: PronunciationGenerator;\n private _language: string;\n private _document: Document;\n\n /**\n * Creates a new DisplayGenerator.\n * @param doc - The Document object to use for DOM operations.\n * @param contentManager - The content manager for loading media.\n * @param templateHtml - The HTML string containing display templates.\n */\n constructor(doc: Document, contentManager: ContentManager, templateHtml: string) {\n this._document = doc;\n this._contentManager = contentManager;\n this._templates = new HtmlTemplateCollection(doc);\n this._templates.loadFromString(templateHtml);\n this._structuredContentGenerator = new StructuredContentGenerator(this._contentManager, doc);\n this._pronunciationGenerator = new PronunciationGenerator(doc);\n this._language = 'ja';\n }\n\n /** The current content manager. */\n get contentManager(): ContentManager {\n return this._contentManager;\n }\n\n set contentManager(contentManager: ContentManager) {\n this._contentManager = contentManager;\n }\n\n /**\n * Updates the target language for rendering.\n * @param language - The BCP 47 language tag (e.g. 'ja', 'zh').\n */\n updateLanguage(language: string): void {\n this._language = language;\n }\n\n /**\n * Creates a complete term entry element from a dictionary entry.\n * @param dictionaryEntry - The term dictionary entry data.\n * @param dictionaryInfo - Array of dictionary summary information.\n * @returns An HTMLElement representing the full term entry.\n */\n createTermEntry(\n dictionaryEntry: Dictionary.TermDictionaryEntry,\n dictionaryInfo: DictionaryImporter.Summary[],\n ): HTMLElement {\n const node = this._instantiate('term-entry');\n\n const headwordsContainer = this._querySelector(node, '.headword-list');\n const inflectionRuleChainsContainer = this._querySelector(node, '.inflection-rule-chains');\n const groupedPronunciationsContainer = this._querySelector(node, '.pronunciation-group-list');\n const frequencyGroupListContainer = this._querySelector(node, '.frequency-group-list');\n const definitionsContainer = this._querySelector(node, '.definition-list');\n const headwordTagsContainer = this._querySelector(node, '.headword-list-tag-list');\n\n const { headwords, type, inflectionRuleChainCandidates, definitions, frequencies, pronunciations } =\n dictionaryEntry;\n const groupedPronunciations = getGroupedPronunciations(dictionaryEntry);\n const pronunciationCount = groupedPronunciations.reduce((i, v) => i + v.pronunciations.length, 0);\n const groupedFrequencies = groupTermFrequencies(dictionaryEntry, dictionaryInfo);\n const termTags = groupTermTags(dictionaryEntry);\n\n const uniqueTerms = new Set<string>();\n const uniqueReadings = new Set<string>();\n const primaryMatchTypes = new Set<Dictionary.TermSourceMatchType>();\n for (const { term, reading, sources } of headwords) {\n uniqueTerms.add(term);\n uniqueReadings.add(reading);\n for (const { matchType, isPrimary } of sources) {\n if (!isPrimary) {\n continue;\n }\n primaryMatchTypes.add(matchType);\n }\n }\n\n node.dataset.format = type;\n node.dataset.headwordCount = `${headwords.length}`;\n node.dataset.definitionCount = `${definitions.length}`;\n node.dataset.pronunciationDictionaryCount = `${groupedPronunciations.length}`;\n node.dataset.pronunciationCount = `${pronunciationCount}`;\n node.dataset.uniqueTermCount = `${uniqueTerms.size}`;\n node.dataset.uniqueReadingCount = `${uniqueReadings.size}`;\n node.dataset.frequencyCount = `${frequencies.length}`;\n node.dataset.groupedFrequencyCount = `${groupedFrequencies.length}`;\n node.dataset.primaryMatchTypes = [...primaryMatchTypes].join(' ');\n\n for (let i = 0, ii = headwords.length; i < ii; ++i) {\n const node2 = this._createTermHeadword(headwords[i], i, pronunciations);\n node2.dataset.index = `${i}`;\n headwordsContainer.appendChild(node2);\n }\n headwordsContainer.dataset.count = `${headwords.length}`;\n\n this._appendMultiple(\n inflectionRuleChainsContainer,\n this._createInflectionRuleChain.bind(this),\n inflectionRuleChainCandidates,\n );\n this._appendMultiple(\n frequencyGroupListContainer,\n this._createFrequencyGroup.bind(this),\n groupedFrequencies,\n false,\n );\n this._appendMultiple(\n groupedPronunciationsContainer,\n this._createGroupedPronunciation.bind(this),\n groupedPronunciations,\n );\n this._appendMultiple(headwordTagsContainer, this._createTermTag.bind(this), termTags, headwords.length);\n\n for (const term of uniqueTerms) {\n headwordTagsContainer.appendChild(this._createSearchTag(term));\n }\n for (const reading of uniqueReadings) {\n if (uniqueTerms.has(reading)) {\n continue;\n }\n headwordTagsContainer.appendChild(this._createSearchTag(reading));\n }\n\n // Add definitions\n const dictionaryTag = this._createDictionaryTag('');\n for (let i = 0, ii = definitions.length; i < ii; ++i) {\n const definition = definitions[i];\n const { dictionary, dictionaryAlias } = definition;\n\n if (dictionaryTag.dictionaries.includes(dictionary)) {\n dictionaryTag.redundant = true;\n } else {\n dictionaryTag.redundant = false;\n dictionaryTag.dictionaries.push(dictionary);\n dictionaryTag.name = dictionaryAlias;\n dictionaryTag.content = [dictionary];\n\n const currentDictionaryInfo = dictionaryInfo.find(({ title }) => title === dictionary);\n if (currentDictionaryInfo) {\n const dictionaryContentArray: string[] = [];\n dictionaryContentArray.push(currentDictionaryInfo.title);\n if (currentDictionaryInfo.author) {\n dictionaryContentArray.push(`Author: ${currentDictionaryInfo.author}`);\n }\n if (currentDictionaryInfo.description) {\n dictionaryContentArray.push(`Description: ${currentDictionaryInfo.description}`);\n }\n if (currentDictionaryInfo.url) {\n dictionaryContentArray.push(`URL: ${currentDictionaryInfo.url}`);\n }\n\n const totalTerms = currentDictionaryInfo?.counts?.terms?.total;\n if (totalTerms !== undefined && totalTerms > 0) {\n dictionaryContentArray.push(`Term Count: ${totalTerms.toString()}`);\n }\n\n dictionaryTag.content = dictionaryContentArray;\n }\n }\n\n const node2 = this._createTermDefinition(definition, dictionaryTag, headwords, uniqueTerms, uniqueReadings);\n node2.dataset.index = `${i}`;\n definitionsContainer.appendChild(node2);\n }\n definitionsContainer.dataset.count = `${definitions.length}`;\n\n const dictionaryScopedStyleNode = this._createDictionaryScopedStyleNode(definitions, dictionaryInfo);\n if (dictionaryScopedStyleNode !== null) {\n node.appendChild(dictionaryScopedStyleNode);\n }\n\n return node;\n }\n\n /**\n * Creates a complete kanji entry element from a dictionary entry.\n * @param dictionaryEntry - The kanji dictionary entry data.\n * @param dictionaryInfo - Array of dictionary summary information.\n * @returns An HTMLElement representing the full kanji entry.\n */\n createKanjiEntry(\n dictionaryEntry: Dictionary.KanjiDictionaryEntry,\n dictionaryInfo: DictionaryImporter.Summary[],\n ): HTMLElement {\n const node = this._instantiate('kanji-entry');\n node.dataset.dictionary = dictionaryEntry.dictionary;\n\n const glyphContainer = this._querySelector(node, '.kanji-glyph');\n const frequencyGroupListContainer = this._querySelector(node, '.frequency-group-list');\n const tagContainer = this._querySelector(node, '.kanji-tag-list');\n const definitionsContainer = this._querySelector(node, '.kanji-gloss-list');\n const chineseReadingsContainer = this._querySelector(node, '.kanji-readings-chinese');\n const japaneseReadingsContainer = this._querySelector(node, '.kanji-readings-japanese');\n const statisticsContainer = this._querySelector(node, '.kanji-statistics');\n const classificationsContainer = this._querySelector(node, '.kanji-classifications');\n const codepointsContainer = this._querySelector(node, '.kanji-codepoints');\n const dictionaryIndicesContainer = this._querySelector(node, '.kanji-dictionary-indices');\n\n this._setTextContent(glyphContainer, dictionaryEntry.character, this._language);\n if (this._language === 'ja') {\n glyphContainer.style.fontFamily = 'kanji-stroke-orders, sans-serif';\n }\n const groupedFrequencies = groupKanjiFrequencies(dictionaryEntry.frequencies, dictionaryInfo);\n\n const dictionaryTag = this._createDictionaryTag('');\n dictionaryTag.name = dictionaryEntry.dictionaryAlias;\n dictionaryTag.content = [dictionaryEntry.dictionary];\n const currentDictionaryInfo = dictionaryInfo.find(({ title }) => title === dictionaryEntry.dictionary);\n if (currentDictionaryInfo) {\n const dictionaryContentArray: string[] = [];\n dictionaryContentArray.push(currentDictionaryInfo.title);\n if (currentDictionaryInfo.author) {\n dictionaryContentArray.push(`Author: ${currentDictionaryInfo.author}`);\n }\n if (currentDictionaryInfo.description) {\n dictionaryContentArray.push(`Description: ${currentDictionaryInfo.description}`);\n }\n if (currentDictionaryInfo.url) {\n dictionaryContentArray.push(`URL: ${currentDictionaryInfo.url}`);\n }\n\n const totalKanji = currentDictionaryInfo?.counts?.kanji?.total;\n if (totalKanji !== undefined && totalKanji > 0) {\n dictionaryContentArray.push(`Kanji Count: ${totalKanji.toString()}`);\n }\n\n dictionaryTag.content = dictionaryContentArray;\n }\n\n this._appendMultiple(\n frequencyGroupListContainer,\n this._createFrequencyGroup.bind(this),\n groupedFrequencies,\n true,\n );\n this._appendMultiple(tagContainer, this._createTag.bind(this), [...dictionaryEntry.tags, dictionaryTag]);\n this._appendMultiple(definitionsContainer, this._createKanjiDefinition.bind(this), dictionaryEntry.definitions);\n this._appendMultiple(chineseReadingsContainer, this._createKanjiReading.bind(this), dictionaryEntry.onyomi);\n this._appendMultiple(japaneseReadingsContainer, this._createKanjiReading.bind(this), dictionaryEntry.kunyomi);\n\n statisticsContainer.appendChild(this._createKanjiInfoTable(dictionaryEntry.stats.misc));\n classificationsContainer.appendChild(this._createKanjiInfoTable(dictionaryEntry.stats.class));\n codepointsContainer.appendChild(this._createKanjiInfoTable(dictionaryEntry.stats.code));\n dictionaryIndicesContainer.appendChild(this._createKanjiInfoTable(dictionaryEntry.stats.index));\n\n return node;\n }\n\n /**\n * Creates an empty footer notification element.\n */\n createEmptyFooterNotification(): HTMLElement {\n return this._instantiate('footer-notification');\n }\n\n /**\n * Instantiates a named template, returning the first element child.\n * @param name - The template name.\n */\n instantiateTemplate(name: string): HTMLElement {\n return this._instantiate(name);\n }\n\n /**\n * Instantiates a named template, returning the full DocumentFragment.\n * @param name - The template name.\n */\n instantiateTemplateFragment(name: string): DocumentFragment {\n return this._templates.instantiateFragment(name);\n }\n\n // Private\n\n private _createTermHeadword(\n headword: Dictionary.TermHeadword,\n headwordIndex: number,\n pronunciations: Dictionary.TermPronunciation[],\n ): HTMLElement {\n const { term, reading, tags, sources } = headword;\n\n let isPrimaryAny = false;\n const matchTypes = new Set<string>();\n const matchSources = new Set<string>();\n for (const { matchType, matchSource, isPrimary } of sources) {\n if (isPrimary) {\n isPrimaryAny = true;\n }\n matchTypes.add(matchType);\n matchSources.add(matchSource);\n }\n\n const node = this._instantiate('headword');\n\n const termContainer = this._querySelector(node, '.headword-term');\n\n node.dataset.isPrimary = `${isPrimaryAny}`;\n node.dataset.readingIsSame = `${reading === term}`;\n node.dataset.frequency = getTermFrequency(tags);\n node.dataset.matchTypes = [...matchTypes].join(' ');\n node.dataset.matchSources = [...matchSources].join(' ');\n\n const { wordClasses } = headword;\n const pronunciationCategories = this._getPronunciationCategories(\n reading,\n pronunciations,\n wordClasses,\n headwordIndex,\n );\n if (pronunciationCategories !== null) {\n node.dataset.pronunciationCategories = pronunciationCategories;\n }\n if (wordClasses.length > 0) {\n node.dataset.wordClasses = wordClasses.join(' ');\n }\n\n const headwordReading = this._querySelector(node, '.headword-reading');\n this._setTextContent(headwordReading, reading);\n\n this._appendFurigana(termContainer, term, reading, this._appendKanjiLinks.bind(this));\n\n return node;\n }\n\n private _createInflectionRuleChain(\n inflectionRuleChain: Dictionary.InflectionRuleChainCandidate,\n ): HTMLElement | null {\n const { source, inflectionRules } = inflectionRuleChain;\n if (!Array.isArray(inflectionRules) || inflectionRules.length === 0) {\n return null;\n }\n const fragment = this._instantiate('inflection-rule-chain');\n\n const sourceIcon = this._getInflectionSourceIcon(source);\n fragment.appendChild(sourceIcon);\n\n this._appendMultiple(fragment, this._createTermInflection.bind(this), inflectionRules);\n return fragment;\n }\n\n private _getInflectionSourceIcon(source: Dictionary.InflectionSource): HTMLElement {\n const icon = this._document.createElement('span');\n icon.classList.add('inflection-source-icon');\n icon.dataset.inflectionSource = source;\n switch (source) {\n case 'dictionary':\n icon.title = 'Dictionary Deinflection';\n return icon;\n case 'algorithm':\n icon.title = 'Algorithm Deinflection';\n return icon;\n case 'both':\n icon.title = 'Dictionary and Algorithm Deinflection';\n return icon;\n }\n }\n\n private _createTermInflection(inflection: Dictionary.InflectionRule): DocumentFragment {\n const { name, description } = inflection;\n const fragment = this._templates.instantiateFragment('inflection');\n const node = this._querySelector(fragment, '.inflection');\n this._setTextContent(node, name);\n if (description) {\n node.title = description;\n }\n node.dataset.reason = name;\n return fragment;\n }\n\n private _createTermDefinition(\n definition: Dictionary.TermDefinition,\n dictionaryTag: Dictionary.Tag,\n headwords: Dictionary.TermHeadword[],\n uniqueTerms: Set<string>,\n uniqueReadings: Set<string>,\n ): HTMLElement {\n const { dictionary, tags, headwordIndices, entries } = definition;\n const disambiguations = getDisambiguations(headwords, headwordIndices, uniqueTerms, uniqueReadings);\n\n const node = this._instantiate('definition-item');\n\n const tagListContainer = this._querySelector(node, '.definition-tag-list');\n const onlyListContainer = this._querySelector(node, '.definition-disambiguation-list');\n const entriesContainer = this._querySelector(node, '.gloss-list');\n\n node.dataset.dictionary = dictionary;\n\n this._appendMultiple(tagListContainer, this._createTag.bind(this), [...tags, dictionaryTag]);\n this._appendMultiple(onlyListContainer, this._createTermDisambiguation.bind(this), disambiguations);\n this._appendMultiple(entriesContainer, this._createTermDefinitionEntry.bind(this), entries, dictionary);\n return node;\n }\n\n private _createDictionaryScopedStyleNode(\n definitions: Dictionary.TermDefinition[],\n dictionaryInfo: DictionaryImporter.Summary[],\n ): HTMLStyleElement | null {\n const usedDictionaries = new Set<string>();\n for (const { dictionary } of definitions) {\n usedDictionaries.add(dictionary);\n }\n\n let scopedCss = '';\n for (const dictionary of usedDictionaries) {\n const info = dictionaryInfo.find(({ title }) => title === dictionary);\n const styles = info?.styles?.trim() ?? '';\n if (styles.length === 0) {\n continue;\n }\n\n // Match extension behavior: scope dictionary CSS to entry elements using data-dictionary.\n const escapedTitle = dictionary.replaceAll('\\\\', '\\\\\\\\').replaceAll('\"', '\\\\\"');\n scopedCss += `\\n[data-dictionary=\"${escapedTitle}\"] {${styles}\\n}`;\n }\n\n if (scopedCss.length === 0) {\n return null;\n }\n\n const node = this._document.createElement('style');\n node.className = 'dictionary-entry-styles';\n node.textContent = scopedCss;\n return node;\n }\n\n private _createTermDefinitionEntry(\n entry: DictionaryData.TermGlossaryContent,\n dictionary: string,\n ): HTMLElement | null {\n switch (typeof entry) {\n case 'string':\n return this._createTermDefinitionEntryText(entry);\n case 'object': {\n switch (entry.type) {\n case 'image':\n return this._createTermDefinitionEntryImage(entry, dictionary);\n case 'structured-content':\n return this._createTermDefinitionEntryStructuredContent(entry.content, dictionary);\n case 'text':\n break;\n }\n break;\n }\n }\n return null;\n }\n\n private _createTermDefinitionEntryText(text: string): HTMLElement {\n const node = this._instantiate('gloss-item');\n const container = this._querySelector(node, '.gloss-content');\n this._setMultilineTextContent(container, text);\n return node;\n }\n\n private _createTermDefinitionEntryImage(data: DictionaryData.TermGlossaryImage, dictionary: string): HTMLElement {\n const { description } = data;\n\n const node = this._instantiate('gloss-item');\n\n const contentContainer = this._querySelector(node, '.gloss-content');\n const image = this._structuredContentGenerator.createDefinitionImage(data, dictionary);\n contentContainer.appendChild(image);\n\n if (typeof description === 'string') {\n const fragment = this._templates.instantiateFragment('gloss-item-image-description');\n const container = this._querySelector(fragment, '.gloss-image-description');\n this._setMultilineTextContent(container, description);\n contentContainer.appendChild(fragment);\n }\n\n return node;\n }\n\n private _createTermDefinitionEntryStructuredContent(\n content: StructuredContent.Content,\n dictionary: string,\n ): HTMLElement {\n const node = this._instantiate('gloss-item');\n const contentContainer = this._querySelector(node, '.gloss-content');\n this._structuredContentGenerator.appendStructuredContent(contentContainer, content, dictionary);\n return node;\n }\n\n private _createTermDisambiguation(disambiguation: string): HTMLElement {\n const node = this._instantiate('definition-disambiguation');\n node.dataset.term = disambiguation;\n this._setTextContent(node, disambiguation, this._language);\n return node;\n }\n\n private _createKanjiLink(character: string): HTMLAnchorElement {\n const node = this._document.createElement('a');\n node.className = 'headword-kanji-link';\n this._setTextContent(node, character, this._language);\n return node;\n }\n\n private _createKanjiDefinition(text: string): HTMLElement {\n const node = this._instantiate('kanji-gloss-item');\n const container = this._querySelector(node, '.kanji-gloss-content');\n this._setMultilineTextContent(container, text);\n return node;\n }\n\n private _createKanjiReading(reading: string): HTMLElement {\n const node = this._instantiate('kanji-reading');\n this._setTextContent(node, reading, this._language);\n return node;\n }\n\n private _createKanjiInfoTable(details: Dictionary.KanjiStat[]): HTMLElement {\n const node = this._instantiate('kanji-info-table');\n const container = this._querySelector(node, '.kanji-info-table-body');\n\n const count = this._appendMultiple(container, this._createKanjiInfoTableItem.bind(this), details);\n if (count === 0) {\n const n = this._createKanjiInfoTableItemEmpty();\n container.appendChild(n);\n }\n\n return node;\n }\n\n private _createKanjiInfoTableItem(details: Dictionary.KanjiStat): HTMLElement {\n const { content, name, value } = details;\n const node = this._instantiate('kanji-info-table-item');\n const nameNode = this._querySelector(node, '.kanji-info-table-item-header');\n const valueNode = this._querySelector(node, '.kanji-info-table-item-value');\n this._setTextContent(nameNode, content.length > 0 ? content : name);\n this._setTextContent(valueNode, typeof value === 'string' ? value : `${value}`);\n return node;\n }\n\n private _createKanjiInfoTableItemEmpty(): HTMLElement {\n return this._instantiate('kanji-info-table-empty');\n }\n\n private _createTag(tag: Dictionary.Tag): HTMLElement {\n const { content, name, category, redundant } = tag;\n const node = this._instantiate('tag');\n\n const inner = this._querySelector(node, '.tag-label-content');\n\n const contentString = content.join('\\n');\n\n node.title = contentString;\n this._setTextContent(inner, name);\n node.dataset.details = contentString.length > 0 ? contentString : name;\n node.dataset.category = category;\n if (redundant) {\n node.dataset.redundant = 'true';\n }\n\n return node;\n }\n\n private _createTermTag(tagInfo: DictionaryDataUtil.TagGroup, totalHeadwordCount: number): HTMLElement {\n const { tag, headwordIndices } = tagInfo;\n const node = this._createTag(tag);\n node.dataset.headwords = headwordIndices.join(' ');\n node.dataset.totalHeadwordCount = `${totalHeadwordCount}`;\n node.dataset.matchedHeadwordCount = `${headwordIndices.length}`;\n node.dataset.unmatchedHeadwordCount = `${Math.max(0, totalHeadwordCount - headwordIndices.length)}`;\n return node;\n }\n\n private _createTagData(name: string, category: string): Dictionary.Tag {\n return {\n name,\n category,\n order: 0,\n score: 0,\n content: [],\n dictionaries: [],\n redundant: false,\n };\n }\n\n private _createSearchTag(text: string): HTMLElement {\n return this._createTag(this._createTagData(text, 'search'));\n }\n\n private _createGroupedPronunciation(details: DictionaryDataUtil.DictionaryGroupedPronunciations): HTMLElement {\n const { dictionary, dictionaryAlias, pronunciations } = details;\n\n const node = this._instantiate('pronunciation-group');\n node.dataset.dictionary = dictionary;\n node.dataset.pronunciationsMulti = 'true';\n node.dataset.pronunciationsCount = `${pronunciations.length}`;\n\n const n1 = this._querySelector(node, '.pronunciation-group-tag-list');\n const tag = this._createTag(this._createTagData(dictionaryAlias, 'pronunciation-dictionary'));\n tag.dataset.details = dictionary;\n n1.appendChild(tag);\n\n let hasTags = false;\n for (const {\n pronunciation: { tags },\n } of pronunciations) {\n if (tags.length > 0) {\n hasTags = true;\n break;\n }\n }\n\n const n = this._querySelector(node, '.pronunciation-list');\n n.dataset.hasTags = `${hasTags}`;\n this._appendMultiple(n, this._createPronunciation.bind(this), pronunciations);\n\n return node;\n }\n\n private _createPronunciation(details: DictionaryDataUtil.GroupedPronunciation): HTMLElement {\n const { pronunciation } = details;\n switch (pronunciation.type) {\n case 'pitch-accent':\n return this._createPronunciationPitchAccent(pronunciation, details);\n case 'phonetic-transcription':\n return this._createPronunciationPhoneticTranscription(pronunciation, details);\n }\n }\n\n private _createPronunciationPhoneticTranscription(\n pronunciation: Dictionary.PhoneticTranscription,\n details: DictionaryDataUtil.GroupedPronunciation,\n ): HTMLElement {\n const { ipa, tags } = pronunciation;\n const { exclusiveTerms, exclusiveReadings } = details;\n\n const node = this._instantiate('pronunciation');\n\n node.dataset.pronunciationType = pronunciation.type;\n node.dataset.tagCount = `${tags.length}`;\n\n let n = this._querySelector(node, '.pronunciation-tag-list');\n this._appendMultiple(n, this._createTag.bind(this), tags);\n\n n = this._querySelector(node, '.pronunciation-disambiguation-list');\n this._createPronunciationDisambiguations(n, exclusiveTerms, exclusiveReadings);\n\n n = this._querySelector(node, '.pronunciation-text-container');\n this._setTextContent(n, ipa);\n\n return node;\n }\n\n private _createPronunciationPitchAccent(\n pitchAccent: Dictionary.PitchAccent,\n details: DictionaryDataUtil.GroupedPronunciation,\n ): HTMLElement {\n const { positions, nasalPositions, devoicePositions, tags } = pitchAccent;\n const { reading, exclusiveTerms, exclusiveReadings } = details;\n const morae = getKanaMorae(reading);\n\n const node = this._instantiate('pronunciation');\n\n node.dataset.pitchAccentDownstepPosition = `${positions}`;\n node.dataset.pronunciationType = pitchAccent.type;\n if (nasalPositions.length > 0) {\n node.dataset.nasalMoraPosition = nasalPositions.join(' ');\n }\n if (devoicePositions.length > 0) {\n node.dataset.devoiceMoraPosition = devoicePositions.join(' ');\n }\n node.dataset.tagCount = `${tags.length}`;\n\n let n = this._querySelector(node, '.pronunciation-tag-list');\n this._appendMultiple(n, this._createTag.bind(this), tags);\n\n n = this._querySelector(node, '.pronunciation-disambiguation-list');\n this._createPronunciationDisambiguations(n, exclusiveTerms, exclusiveReadings);\n\n n = this._querySelector(node, '.pronunciation-downstep-notation-container');\n n.appendChild(this._pronunciationGenerator.createPronunciationDownstepPosition(positions));\n\n n = this._querySelector(node, '.pronunciation-text-container');\n n.lang = this._language;\n n.appendChild(\n this._pronunciationGenerator.createPronunciationText(morae, positions, nasalPositions, devoicePositions),\n );\n\n n = this._querySelector(node, '.pronunciation-graph-container');\n n.appendChild(this._pronunciationGenerator.createPronunciationGraph(morae, positions));\n\n return node;\n }\n\n private _createPronunciationDisambiguations(\n container: HTMLElement,\n exclusiveTerms: string[],\n exclusiveReadings: string[],\n ): void {\n const templateName = 'pronunciation-disambiguation';\n for (const term of exclusiveTerms) {\n const node = this._instantiate(templateName);\n node.dataset.type = 'term';\n this._setTextContent(node, term, this._language);\n container.appendChild(node);\n }\n\n for (const exclusiveReading of exclusiveReadings) {\n const node = this._instantiate(templateName);\n node.dataset.type = 'reading';\n this._setTextContent(node, exclusiveReading, this._language);\n container.appendChild(node);\n }\n\n container.dataset.count = `${exclusiveTerms.length + exclusiveReadings.length}`;\n container.dataset.termCount = `${exclusiveTerms.length}`;\n container.dataset.readingCount = `${exclusiveReadings.length}`;\n }\n\n private _createFrequencyGroup(\n details:\n | DictionaryDataUtil.DictionaryFrequency<DictionaryDataUtil.TermFrequency>\n | DictionaryDataUtil.DictionaryFrequency<DictionaryDataUtil.KanjiFrequency>,\n kanji: boolean,\n ): HTMLElement {\n const { dictionary, dictionaryAlias, frequencies, freqCount } = details;\n\n const node = this._instantiate('frequency-group-item');\n const body = this._querySelector(node, '.tag-body-content');\n\n const tagLabel = this._querySelector(node, '.tag-label-content');\n const tag = this._querySelector(node, '.tag');\n\n this._setTextContent(tagLabel, dictionaryAlias);\n\n const ii = frequencies.length;\n for (let i = 0; i < ii; ++i) {\n const item = frequencies[i];\n const itemNode = kanji\n ? this._createKanjiFrequency(\n item as DictionaryDataUtil.KanjiFrequency,\n dictionary,\n dictionaryAlias,\n freqCount?.toString(),\n )\n : this._createTermFrequency(\n item as DictionaryDataUtil.TermFrequency,\n dictionary,\n dictionaryAlias,\n freqCount?.toString(),\n );\n itemNode.dataset.index = `${i}`;\n body.appendChild(itemNode);\n }\n\n body.dataset.count = `${ii}`;\n node.dataset.count = `${ii}`;\n node.dataset.details = dictionary;\n tag.dataset.details = `${dictionary}\\nDictionary size: ${freqCount?.toString()}${kanji ? ' kanji' : ' terms'}`;\n return node;\n }\n\n private _createTermFrequency(\n details: DictionaryDataUtil.TermFrequency,\n dictionary: string,\n dictionaryAlias: string,\n freqCount: string | undefined,\n ): HTMLElement {\n const { term, reading, values } = details;\n const node = this._instantiate('term-frequency-item');\n const tagLabel = this._querySelector(node, '.tag-label-content');\n const tag = this._querySelector(node, '.tag');\n const disambiguationTerm = this._querySelector(node, '.frequency-disambiguation-term');\n const disambiguationReading = this._querySelector(node, '.frequency-disambiguation-reading');\n const frequencyValueList = this._querySelector(node, '.frequency-value-list');\n\n this._setTextContent(tagLabel, dictionaryAlias);\n this._setTextContent(disambiguationTerm, term, this._language);\n this._setTextContent(disambiguationReading, reading !== null ? reading : '', this._language);\n this._populateFrequencyValueList(frequencyValueList, values);\n\n node.dataset.term = term;\n if (typeof reading === 'string') {\n node.dataset.reading = reading;\n }\n node.dataset.hasReading = `${reading !== null}`;\n node.dataset.readingIsSame = `${reading === term}`;\n node.dataset.dictionary = dictionary;\n node.dataset.details = dictionary;\n tag.dataset.details = `${dictionary}\\nDictionary size: ${freqCount ?? ''} terms`;\n return node;\n }\n\n private _createKanjiFrequency(\n details: DictionaryDataUtil.KanjiFrequency,\n dictionary: string,\n dictionaryAlias: string,\n freqCount: string | undefined,\n ): HTMLElement {\n const { character, values } = details;\n const node = this._instantiate('kanji-frequency-item');\n const tagLabel = this._querySelector(node, '.tag-label-content');\n const tag = this._querySelector(node, '.tag');\n const frequencyValueList = this._querySelector(node, '.frequency-value-list');\n\n this._setTextContent(tagLabel, dictionaryAlias);\n this._populateFrequencyValueList(frequencyValueList, values);\n\n node.dataset.character = character;\n node.dataset.dictionary = dictionary;\n node.dataset.details = dictionary;\n tag.dataset.details = `${dictionary}\\nDictionary size: ${freqCount ?? ''} kanji`;\n\n return node;\n }\n\n private _populateFrequencyValueList(node: HTMLElement, values: DictionaryDataUtil.FrequencyValue[]): void {\n let fullFrequency = '';\n for (let i = 0, ii = values.length; i < ii; ++i) {\n const { frequency, displayValue } = values[i];\n const frequencyString = `${frequency}`;\n const text = displayValue !== null ? displayValue : `${frequency}`;\n\n if (i > 0) {\n const node2 = this._document.createElement('span');\n node2.className = 'frequency-value';\n node2.dataset.frequency = `${frequency}`;\n node2.textContent = ', ';\n node.appendChild(node2);\n fullFrequency += ', ';\n }\n\n const node2 = this._document.createElement('span');\n node2.className = 'frequency-value';\n node2.dataset.frequency = frequencyString;\n if (displayValue !== null) {\n node2.dataset.displayValue = `${displayValue}`;\n if (displayValue !== frequencyString) {\n node2.title = frequencyString;\n }\n }\n this._setTextContent(node2, text, this._language);\n node.appendChild(node2);\n\n fullFrequency += text;\n }\n\n node.dataset.frequency = fullFrequency;\n }\n\n private _appendKanjiLinks(container: HTMLElement, text: string): void {\n let part = '';\n for (const c of text) {\n if (isCodePointKanji(c.codePointAt(0) as number)) {\n if (part.length > 0) {\n container.appendChild(this._document.createTextNode(part));\n part = '';\n }\n\n const link = this._createKanjiLink(c);\n container.appendChild(link);\n } else {\n part += c;\n }\n }\n if (part.length > 0) {\n container.appendChild(this._document.createTextNode(part));\n }\n }\n\n private _appendMultiple<TItem, TExtraArg = void>(\n container: HTMLElement,\n createItem: (item: TItem, arg: TExtraArg) => Node | null,\n detailsArray: TItem[],\n arg?: TExtraArg,\n ): number {\n let count = 0;\n const ELEMENT_NODE = 1;\n if (Array.isArray(detailsArray)) {\n for (const details of detailsArray) {\n const item = createItem(details, arg as TExtraArg);\n if (item === null) {\n continue;\n }\n container.appendChild(item);\n if (item.nodeType === ELEMENT_NODE) {\n (item as HTMLElement).dataset.index = `${count}`;\n }\n ++count;\n }\n }\n\n container.dataset.count = `${count}`;\n\n return count;\n }\n\n private _appendFurigana(\n container: HTMLElement,\n term: string,\n reading: string,\n addText: (element: HTMLElement, text: string) => void,\n ): void {\n container.lang = this._language;\n const segments = distributeFurigana(term, reading);\n for (const { text, reading: furigana } of segments) {\n if (furigana) {\n const ruby = this._document.createElement('ruby');\n const rt = this._document.createElement('rt');\n addText(ruby, text);\n ruby.appendChild(rt);\n rt.appendChild(this._document.createTextNode(furigana));\n container.appendChild(ruby);\n } else {\n addText(container, text);\n }\n }\n }\n\n private _createDictionaryTag(dictionary: string): Dictionary.Tag {\n return this._createTagData(dictionary, 'dictionary');\n }\n\n private _setTextContent(node: HTMLElement, value: string, language?: string): void {\n this._setElementLanguage(node, language, value);\n node.textContent = value;\n }\n\n private _setMultilineTextContent(node: HTMLElement, value: string, language?: string): void {\n this._setElementLanguage(node, language, value);\n\n let start = 0;\n while (true) {\n const end = value.indexOf('\\n', start);\n if (end < 0) {\n break;\n }\n node.appendChild(this._document.createTextNode(value.substring(start, end)));\n node.appendChild(this._document.createElement('br'));\n start = end + 1;\n }\n\n if (start < value.length) {\n node.appendChild(this._document.createTextNode(start === 0 ? value : value.substring(start)));\n }\n }\n\n private _setElementLanguage(element: HTMLElement, language: string | undefined, content: string): void {\n if (typeof language === 'string') {\n element.lang = language;\n } else {\n const language2 = getLanguageFromText(content, this._language);\n if (language2 !== null) {\n element.lang = language2;\n }\n }\n }\n\n private _getPronunciationCategories(\n reading: string,\n termPronunciations: Dictionary.TermPronunciation[],\n wordClasses: string[],\n headwordIndex: number,\n ): string | null {\n if (termPronunciations.length === 0) {\n return null;\n }\n const isVerbOrAdjective = isNonNounVerbOrAdjective(wordClasses);\n const categories = new Set<PitchCategory>();\n for (const termPronunciation of termPronunciations) {\n if (termPronunciation.headwordIndex !== headwordIndex) {\n continue;\n }\n for (const pronunciation of termPronunciation.pronunciations) {\n if (pronunciation.type !== 'pitch-accent') {\n continue;\n }\n const category = getPitchCategory(reading, pronunciation.positions, isVerbOrAdjective);\n if (category !== null) {\n categories.add(category);\n }\n }\n }\n return categories.size > 0 ? [...categories].join(' ') : null;\n }\n\n private _instantiate(name: string): HTMLElement {\n return this._templates.instantiate(name);\n }\n\n private _querySelector(element: Element | DocumentFragment, selector: string): HTMLElement {\n const result = element.querySelector(selector);\n if (result === null) {\n throw new Error(`Failed to find element: ${selector}`);\n }\n return result as HTMLElement;\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { distributeFurigana } from "./japanese-
|
|
1
|
+
import { distributeFurigana } from "./japanese-CKPyY5k_.js";
|
|
2
2
|
import { getDisambiguations, getGroupedPronunciations, getTermFrequency, groupKanjiFrequencies, groupTermFrequencies, groupTermTags, isNonNounVerbOrAdjective } from "./dictionary-data-util-CKDT7n2t.js";
|
|
3
3
|
import { getLanguageFromText } from "./text-utilities-D5eno9GK.js";
|
|
4
4
|
import { PronunciationGenerator, getKanaMorae, getPitchCategory, isCodePointKanji } from "./pronunciation-generator-cNtAQi5s.js";
|
|
@@ -26,7 +26,9 @@ var HtmlTemplateCollection = class {
|
|
|
26
26
|
* @param html - The HTML string containing `<template>` elements.
|
|
27
27
|
*/
|
|
28
28
|
loadFromString(html) {
|
|
29
|
-
const
|
|
29
|
+
const DOMParserConstructor = this._document.defaultView?.DOMParser ?? globalThis.DOMParser;
|
|
30
|
+
if (typeof DOMParserConstructor !== "function") throw new Error("DOMParser is unavailable for HtmlTemplateCollection.");
|
|
31
|
+
const parser = new DOMParserConstructor();
|
|
30
32
|
const templatesDocument = parser.parseFromString(html, "text/html");
|
|
31
33
|
this.load(templatesDocument);
|
|
32
34
|
}
|
|
@@ -228,6 +230,8 @@ var DisplayGenerator = class {
|
|
|
228
230
|
definitionsContainer.appendChild(node2);
|
|
229
231
|
}
|
|
230
232
|
definitionsContainer.dataset.count = `${definitions.length}`;
|
|
233
|
+
const dictionaryScopedStyleNode = this._createDictionaryScopedStyleNode(definitions, dictionaryInfo);
|
|
234
|
+
if (dictionaryScopedStyleNode !== null) node.appendChild(dictionaryScopedStyleNode);
|
|
231
235
|
return node;
|
|
232
236
|
}
|
|
233
237
|
/**
|
|
@@ -370,6 +374,23 @@ var DisplayGenerator = class {
|
|
|
370
374
|
this._appendMultiple(entriesContainer, this._createTermDefinitionEntry.bind(this), entries, dictionary);
|
|
371
375
|
return node;
|
|
372
376
|
}
|
|
377
|
+
_createDictionaryScopedStyleNode(definitions, dictionaryInfo) {
|
|
378
|
+
const usedDictionaries = new Set();
|
|
379
|
+
for (const { dictionary } of definitions) usedDictionaries.add(dictionary);
|
|
380
|
+
let scopedCss = "";
|
|
381
|
+
for (const dictionary of usedDictionaries) {
|
|
382
|
+
const info = dictionaryInfo.find(({ title }) => title === dictionary);
|
|
383
|
+
const styles = info?.styles?.trim() ?? "";
|
|
384
|
+
if (styles.length === 0) continue;
|
|
385
|
+
const escapedTitle = dictionary.replaceAll("\\", "\\\\").replaceAll("\"", "\\\"");
|
|
386
|
+
scopedCss += `\n[data-dictionary="${escapedTitle}"] {${styles}\n}`;
|
|
387
|
+
}
|
|
388
|
+
if (scopedCss.length === 0) return null;
|
|
389
|
+
const node = this._document.createElement("style");
|
|
390
|
+
node.className = "dictionary-entry-styles";
|
|
391
|
+
node.textContent = scopedCss;
|
|
392
|
+
return node;
|
|
393
|
+
}
|
|
373
394
|
_createTermDefinitionEntry(entry, dictionary) {
|
|
374
395
|
switch (typeof entry) {
|
|
375
396
|
case "string": return this._createTermDefinitionEntryText(entry);
|
|
@@ -743,4 +764,4 @@ var DisplayGenerator = class {
|
|
|
743
764
|
|
|
744
765
|
//#endregion
|
|
745
766
|
export { DisplayGenerator, HtmlTemplateCollection };
|
|
746
|
-
//# sourceMappingURL=display-generator-
|
|
767
|
+
//# sourceMappingURL=display-generator-vxdAYHeK.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"display-generator-vxdAYHeK.js","names":["doc: Document","html: string","source: Document","name: string","template: HTMLTemplateElement","removeNodes: Node[]","doc: Document","contentManager: ContentManager","templateHtml: string","language: string","dictionaryEntry: Dictionary.TermDictionaryEntry","dictionaryInfo: DictionaryImporter.Summary[]","dictionaryContentArray: string[]","dictionaryEntry: Dictionary.KanjiDictionaryEntry","name: string","headword: Dictionary.TermHeadword","headwordIndex: number","pronunciations: Dictionary.TermPronunciation[]","inflectionRuleChain: Dictionary.InflectionRuleChainCandidate","source: Dictionary.InflectionSource","inflection: Dictionary.InflectionRule","definition: Dictionary.TermDefinition","dictionaryTag: Dictionary.Tag","headwords: Dictionary.TermHeadword[]","uniqueTerms: Set<string>","uniqueReadings: Set<string>","definitions: Dictionary.TermDefinition[]","entry: DictionaryData.TermGlossaryContent","dictionary: string","text: string","data: DictionaryData.TermGlossaryImage","content: StructuredContent.Content","disambiguation: string","character: string","reading: string","details: Dictionary.KanjiStat[]","details: Dictionary.KanjiStat","tag: Dictionary.Tag","tagInfo: DictionaryDataUtil.TagGroup","totalHeadwordCount: number","category: string","details: DictionaryDataUtil.DictionaryGroupedPronunciations","details: DictionaryDataUtil.GroupedPronunciation","pronunciation: Dictionary.PhoneticTranscription","pitchAccent: Dictionary.PitchAccent","container: HTMLElement","exclusiveTerms: string[]","exclusiveReadings: string[]","details:\n | DictionaryDataUtil.DictionaryFrequency<DictionaryDataUtil.TermFrequency>\n | DictionaryDataUtil.DictionaryFrequency<DictionaryDataUtil.KanjiFrequency>","kanji: boolean","details: DictionaryDataUtil.TermFrequency","dictionaryAlias: string","freqCount: string | undefined","details: DictionaryDataUtil.KanjiFrequency","node: HTMLElement","values: DictionaryDataUtil.FrequencyValue[]","node2","createItem: (item: TItem, arg: TExtraArg) => Node | null","detailsArray: TItem[]","arg?: TExtraArg","term: string","addText: (element: HTMLElement, text: string) => void","value: string","language?: string","element: HTMLElement","language: string | undefined","content: string","termPronunciations: Dictionary.TermPronunciation[]","wordClasses: string[]","element: Element | DocumentFragment","selector: string"],"sources":["../src/render/html-template-collection.ts","../src/render/display-generator.ts"],"sourcesContent":["/*\n * Copyright (C) 2023-2025 Yomitan Authors\n * Copyright (C) 2020-2022 Yomichan Authors\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program. If not, see <https://www.gnu.org/licenses/>.\n */\n\n/**\n * A collection of HTML templates parsed from raw HTML strings.\n * Templates are identified by their `id` attribute, which must end with `-template`.\n * The prefix before `-template` is used as the template name.\n */\nexport class HtmlTemplateCollection {\n private _templates: Map<string, HTMLTemplateElement>;\n private _document: Document;\n\n /**\n * Creates a new HtmlTemplateCollection.\n * @param doc - The Document object to use for DOM operations.\n */\n constructor(doc: Document) {\n this._templates = new Map();\n this._document = doc;\n }\n\n /**\n * Loads templates from a raw HTML string.\n * @param html - The HTML string containing `<template>` elements.\n */\n loadFromString(html: string): void {\n const DOMParserConstructor =\n (this._document.defaultView as unknown as { DOMParser?: typeof DOMParser } | null)?.DOMParser ??\n globalThis.DOMParser;\n if (typeof DOMParserConstructor !== 'function') {\n throw new Error('DOMParser is unavailable for HtmlTemplateCollection.');\n }\n const parser = new DOMParserConstructor();\n const templatesDocument = parser.parseFromString(html, 'text/html');\n this.load(templatesDocument);\n }\n\n /**\n * Loads templates from a Document source.\n * @param source - The Document containing template elements.\n */\n load(source: Document): void {\n const pattern = /^([\\w\\W]+)-template$/;\n for (const template of Array.from(source.querySelectorAll('template')) as HTMLTemplateElement[]) {\n const match = pattern.exec(template.id);\n if (match === null) {\n continue;\n }\n this._prepareTemplate(template);\n this._templates.set(match[1], template);\n }\n }\n\n /**\n * Instantiates a template by name, returning the first element child as a deep clone.\n * @param name - The template name (without the `-template` suffix).\n * @returns The cloned first element child.\n * @throws Error if the template or its content element is not found.\n */\n instantiate(name: string): HTMLElement {\n const { firstElementChild } = this.getTemplateContent(name);\n if (firstElementChild === null) {\n throw new Error(`Failed to find template content element: ${name}`);\n }\n return this._document.importNode(firstElementChild, true) as HTMLElement;\n }\n\n /**\n * Instantiates a template by name, returning the entire content as a DocumentFragment clone.\n * @param name - The template name (without the `-template` suffix).\n * @returns The cloned DocumentFragment.\n */\n instantiateFragment(name: string): DocumentFragment {\n return this._document.importNode(this.getTemplateContent(name), true);\n }\n\n /**\n * Gets the content DocumentFragment of a named template.\n * @param name - The template name (without the `-template` suffix).\n * @returns The template's content DocumentFragment.\n * @throws Error if the template is not found.\n */\n getTemplateContent(name: string): DocumentFragment {\n const template = this._templates.get(name);\n if (typeof template === 'undefined') {\n throw new Error(`Failed to find template: ${name}`);\n }\n return template.content;\n }\n\n /**\n * Returns an iterator over all template elements.\n */\n getAllTemplates(): IterableIterator<HTMLTemplateElement> {\n return this._templates.values();\n }\n\n // Private\n\n private _prepareTemplate(template: HTMLTemplateElement): void {\n if (template.dataset.removeWhitespaceText === 'true') {\n this._removeWhitespaceText(template);\n }\n }\n\n private _removeWhitespaceText(template: HTMLTemplateElement): void {\n const { content } = template;\n const { TEXT_NODE } = this._document.defaultView\n ? (this._document.defaultView as unknown as { Node: typeof Node }).Node\n : { TEXT_NODE: 3 };\n const iterator = this._document.createNodeIterator(content, 4 /* NodeFilter.SHOW_TEXT */);\n const removeNodes: Node[] = [];\n while (true) {\n const node = iterator.nextNode();\n if (node === null) {\n break;\n }\n if (node.nodeType === TEXT_NODE && (node.nodeValue ?? '').trim().length === 0) {\n removeNodes.push(node);\n }\n }\n for (const node of removeNodes) {\n const { parentNode } = node;\n if (parentNode !== null) {\n parentNode.removeChild(node);\n }\n }\n }\n}\n","/*\n * Copyright (C) 2023-2025 Yomitan Authors\n * Copyright (C) 2019-2022 Yomichan Authors\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program. If not, see <https://www.gnu.org/licenses/>.\n */\n\nimport { distributeFurigana } from '../language/ja/furigana.js';\nimport { getLanguageFromText } from '../language/text-utilities.js';\nimport type * as DictionaryDataUtil from '../types/dictionary-data-util.js';\nimport type * as DictionaryData from '../types/dictionary-data.js';\nimport type * as DictionaryImporter from '../types/dictionary-importer.js';\nimport type * as Dictionary from '../types/dictionary.js';\nimport type * as StructuredContent from '../types/structured-content.js';\nimport {\n getDisambiguations,\n getGroupedPronunciations,\n getTermFrequency,\n groupKanjiFrequencies,\n groupTermFrequencies,\n groupTermTags,\n isNonNounVerbOrAdjective,\n} from '../util/dictionary-data-util.js';\nimport type { ContentManager } from './content-manager.js';\nimport { HtmlTemplateCollection } from './html-template-collection.js';\nimport { getKanaMorae, getPitchCategory, isCodePointKanji } from './japanese-util.js';\nimport type { PitchCategory } from './japanese-util.js';\nimport { PronunciationGenerator } from './pronunciation-generator.js';\nimport { StructuredContentGenerator } from './structured-content-generator.js';\n\n/**\n * Generates DOM elements for displaying dictionary entries.\n * This is the main rendering class that creates term entries, kanji entries,\n * and all associated sub-elements (headwords, definitions, tags, frequencies, etc.).\n */\nexport class DisplayGenerator {\n private _contentManager: ContentManager;\n private _templates: HtmlTemplateCollection;\n private _structuredContentGenerator: StructuredContentGenerator;\n private _pronunciationGenerator: PronunciationGenerator;\n private _language: string;\n private _document: Document;\n\n /**\n * Creates a new DisplayGenerator.\n * @param doc - The Document object to use for DOM operations.\n * @param contentManager - The content manager for loading media.\n * @param templateHtml - The HTML string containing display templates.\n */\n constructor(doc: Document, contentManager: ContentManager, templateHtml: string) {\n this._document = doc;\n this._contentManager = contentManager;\n this._templates = new HtmlTemplateCollection(doc);\n this._templates.loadFromString(templateHtml);\n this._structuredContentGenerator = new StructuredContentGenerator(this._contentManager, doc);\n this._pronunciationGenerator = new PronunciationGenerator(doc);\n this._language = 'ja';\n }\n\n /** The current content manager. */\n get contentManager(): ContentManager {\n return this._contentManager;\n }\n\n set contentManager(contentManager: ContentManager) {\n this._contentManager = contentManager;\n }\n\n /**\n * Updates the target language for rendering.\n * @param language - The BCP 47 language tag (e.g. 'ja', 'zh').\n */\n updateLanguage(language: string): void {\n this._language = language;\n }\n\n /**\n * Creates a complete term entry element from a dictionary entry.\n * @param dictionaryEntry - The term dictionary entry data.\n * @param dictionaryInfo - Array of dictionary summary information.\n * @returns An HTMLElement representing the full term entry.\n */\n createTermEntry(\n dictionaryEntry: Dictionary.TermDictionaryEntry,\n dictionaryInfo: DictionaryImporter.Summary[],\n ): HTMLElement {\n const node = this._instantiate('term-entry');\n\n const headwordsContainer = this._querySelector(node, '.headword-list');\n const inflectionRuleChainsContainer = this._querySelector(node, '.inflection-rule-chains');\n const groupedPronunciationsContainer = this._querySelector(node, '.pronunciation-group-list');\n const frequencyGroupListContainer = this._querySelector(node, '.frequency-group-list');\n const definitionsContainer = this._querySelector(node, '.definition-list');\n const headwordTagsContainer = this._querySelector(node, '.headword-list-tag-list');\n\n const { headwords, type, inflectionRuleChainCandidates, definitions, frequencies, pronunciations } =\n dictionaryEntry;\n const groupedPronunciations = getGroupedPronunciations(dictionaryEntry);\n const pronunciationCount = groupedPronunciations.reduce((i, v) => i + v.pronunciations.length, 0);\n const groupedFrequencies = groupTermFrequencies(dictionaryEntry, dictionaryInfo);\n const termTags = groupTermTags(dictionaryEntry);\n\n const uniqueTerms = new Set<string>();\n const uniqueReadings = new Set<string>();\n const primaryMatchTypes = new Set<Dictionary.TermSourceMatchType>();\n for (const { term, reading, sources } of headwords) {\n uniqueTerms.add(term);\n uniqueReadings.add(reading);\n for (const { matchType, isPrimary } of sources) {\n if (!isPrimary) {\n continue;\n }\n primaryMatchTypes.add(matchType);\n }\n }\n\n node.dataset.format = type;\n node.dataset.headwordCount = `${headwords.length}`;\n node.dataset.definitionCount = `${definitions.length}`;\n node.dataset.pronunciationDictionaryCount = `${groupedPronunciations.length}`;\n node.dataset.pronunciationCount = `${pronunciationCount}`;\n node.dataset.uniqueTermCount = `${uniqueTerms.size}`;\n node.dataset.uniqueReadingCount = `${uniqueReadings.size}`;\n node.dataset.frequencyCount = `${frequencies.length}`;\n node.dataset.groupedFrequencyCount = `${groupedFrequencies.length}`;\n node.dataset.primaryMatchTypes = [...primaryMatchTypes].join(' ');\n\n for (let i = 0, ii = headwords.length; i < ii; ++i) {\n const node2 = this._createTermHeadword(headwords[i], i, pronunciations);\n node2.dataset.index = `${i}`;\n headwordsContainer.appendChild(node2);\n }\n headwordsContainer.dataset.count = `${headwords.length}`;\n\n this._appendMultiple(\n inflectionRuleChainsContainer,\n this._createInflectionRuleChain.bind(this),\n inflectionRuleChainCandidates,\n );\n this._appendMultiple(\n frequencyGroupListContainer,\n this._createFrequencyGroup.bind(this),\n groupedFrequencies,\n false,\n );\n this._appendMultiple(\n groupedPronunciationsContainer,\n this._createGroupedPronunciation.bind(this),\n groupedPronunciations,\n );\n this._appendMultiple(headwordTagsContainer, this._createTermTag.bind(this), termTags, headwords.length);\n\n for (const term of uniqueTerms) {\n headwordTagsContainer.appendChild(this._createSearchTag(term));\n }\n for (const reading of uniqueReadings) {\n if (uniqueTerms.has(reading)) {\n continue;\n }\n headwordTagsContainer.appendChild(this._createSearchTag(reading));\n }\n\n // Add definitions\n const dictionaryTag = this._createDictionaryTag('');\n for (let i = 0, ii = definitions.length; i < ii; ++i) {\n const definition = definitions[i];\n const { dictionary, dictionaryAlias } = definition;\n\n if (dictionaryTag.dictionaries.includes(dictionary)) {\n dictionaryTag.redundant = true;\n } else {\n dictionaryTag.redundant = false;\n dictionaryTag.dictionaries.push(dictionary);\n dictionaryTag.name = dictionaryAlias;\n dictionaryTag.content = [dictionary];\n\n const currentDictionaryInfo = dictionaryInfo.find(({ title }) => title === dictionary);\n if (currentDictionaryInfo) {\n const dictionaryContentArray: string[] = [];\n dictionaryContentArray.push(currentDictionaryInfo.title);\n if (currentDictionaryInfo.author) {\n dictionaryContentArray.push(`Author: ${currentDictionaryInfo.author}`);\n }\n if (currentDictionaryInfo.description) {\n dictionaryContentArray.push(`Description: ${currentDictionaryInfo.description}`);\n }\n if (currentDictionaryInfo.url) {\n dictionaryContentArray.push(`URL: ${currentDictionaryInfo.url}`);\n }\n\n const totalTerms = currentDictionaryInfo?.counts?.terms?.total;\n if (totalTerms !== undefined && totalTerms > 0) {\n dictionaryContentArray.push(`Term Count: ${totalTerms.toString()}`);\n }\n\n dictionaryTag.content = dictionaryContentArray;\n }\n }\n\n const node2 = this._createTermDefinition(definition, dictionaryTag, headwords, uniqueTerms, uniqueReadings);\n node2.dataset.index = `${i}`;\n definitionsContainer.appendChild(node2);\n }\n definitionsContainer.dataset.count = `${definitions.length}`;\n\n const dictionaryScopedStyleNode = this._createDictionaryScopedStyleNode(definitions, dictionaryInfo);\n if (dictionaryScopedStyleNode !== null) {\n node.appendChild(dictionaryScopedStyleNode);\n }\n\n return node;\n }\n\n /**\n * Creates a complete kanji entry element from a dictionary entry.\n * @param dictionaryEntry - The kanji dictionary entry data.\n * @param dictionaryInfo - Array of dictionary summary information.\n * @returns An HTMLElement representing the full kanji entry.\n */\n createKanjiEntry(\n dictionaryEntry: Dictionary.KanjiDictionaryEntry,\n dictionaryInfo: DictionaryImporter.Summary[],\n ): HTMLElement {\n const node = this._instantiate('kanji-entry');\n node.dataset.dictionary = dictionaryEntry.dictionary;\n\n const glyphContainer = this._querySelector(node, '.kanji-glyph');\n const frequencyGroupListContainer = this._querySelector(node, '.frequency-group-list');\n const tagContainer = this._querySelector(node, '.kanji-tag-list');\n const definitionsContainer = this._querySelector(node, '.kanji-gloss-list');\n const chineseReadingsContainer = this._querySelector(node, '.kanji-readings-chinese');\n const japaneseReadingsContainer = this._querySelector(node, '.kanji-readings-japanese');\n const statisticsContainer = this._querySelector(node, '.kanji-statistics');\n const classificationsContainer = this._querySelector(node, '.kanji-classifications');\n const codepointsContainer = this._querySelector(node, '.kanji-codepoints');\n const dictionaryIndicesContainer = this._querySelector(node, '.kanji-dictionary-indices');\n\n this._setTextContent(glyphContainer, dictionaryEntry.character, this._language);\n if (this._language === 'ja') {\n glyphContainer.style.fontFamily = 'kanji-stroke-orders, sans-serif';\n }\n const groupedFrequencies = groupKanjiFrequencies(dictionaryEntry.frequencies, dictionaryInfo);\n\n const dictionaryTag = this._createDictionaryTag('');\n dictionaryTag.name = dictionaryEntry.dictionaryAlias;\n dictionaryTag.content = [dictionaryEntry.dictionary];\n const currentDictionaryInfo = dictionaryInfo.find(({ title }) => title === dictionaryEntry.dictionary);\n if (currentDictionaryInfo) {\n const dictionaryContentArray: string[] = [];\n dictionaryContentArray.push(currentDictionaryInfo.title);\n if (currentDictionaryInfo.author) {\n dictionaryContentArray.push(`Author: ${currentDictionaryInfo.author}`);\n }\n if (currentDictionaryInfo.description) {\n dictionaryContentArray.push(`Description: ${currentDictionaryInfo.description}`);\n }\n if (currentDictionaryInfo.url) {\n dictionaryContentArray.push(`URL: ${currentDictionaryInfo.url}`);\n }\n\n const totalKanji = currentDictionaryInfo?.counts?.kanji?.total;\n if (totalKanji !== undefined && totalKanji > 0) {\n dictionaryContentArray.push(`Kanji Count: ${totalKanji.toString()}`);\n }\n\n dictionaryTag.content = dictionaryContentArray;\n }\n\n this._appendMultiple(\n frequencyGroupListContainer,\n this._createFrequencyGroup.bind(this),\n groupedFrequencies,\n true,\n );\n this._appendMultiple(tagContainer, this._createTag.bind(this), [...dictionaryEntry.tags, dictionaryTag]);\n this._appendMultiple(definitionsContainer, this._createKanjiDefinition.bind(this), dictionaryEntry.definitions);\n this._appendMultiple(chineseReadingsContainer, this._createKanjiReading.bind(this), dictionaryEntry.onyomi);\n this._appendMultiple(japaneseReadingsContainer, this._createKanjiReading.bind(this), dictionaryEntry.kunyomi);\n\n statisticsContainer.appendChild(this._createKanjiInfoTable(dictionaryEntry.stats.misc));\n classificationsContainer.appendChild(this._createKanjiInfoTable(dictionaryEntry.stats.class));\n codepointsContainer.appendChild(this._createKanjiInfoTable(dictionaryEntry.stats.code));\n dictionaryIndicesContainer.appendChild(this._createKanjiInfoTable(dictionaryEntry.stats.index));\n\n return node;\n }\n\n /**\n * Creates an empty footer notification element.\n */\n createEmptyFooterNotification(): HTMLElement {\n return this._instantiate('footer-notification');\n }\n\n /**\n * Instantiates a named template, returning the first element child.\n * @param name - The template name.\n */\n instantiateTemplate(name: string): HTMLElement {\n return this._instantiate(name);\n }\n\n /**\n * Instantiates a named template, returning the full DocumentFragment.\n * @param name - The template name.\n */\n instantiateTemplateFragment(name: string): DocumentFragment {\n return this._templates.instantiateFragment(name);\n }\n\n // Private\n\n private _createTermHeadword(\n headword: Dictionary.TermHeadword,\n headwordIndex: number,\n pronunciations: Dictionary.TermPronunciation[],\n ): HTMLElement {\n const { term, reading, tags, sources } = headword;\n\n let isPrimaryAny = false;\n const matchTypes = new Set<string>();\n const matchSources = new Set<string>();\n for (const { matchType, matchSource, isPrimary } of sources) {\n if (isPrimary) {\n isPrimaryAny = true;\n }\n matchTypes.add(matchType);\n matchSources.add(matchSource);\n }\n\n const node = this._instantiate('headword');\n\n const termContainer = this._querySelector(node, '.headword-term');\n\n node.dataset.isPrimary = `${isPrimaryAny}`;\n node.dataset.readingIsSame = `${reading === term}`;\n node.dataset.frequency = getTermFrequency(tags);\n node.dataset.matchTypes = [...matchTypes].join(' ');\n node.dataset.matchSources = [...matchSources].join(' ');\n\n const { wordClasses } = headword;\n const pronunciationCategories = this._getPronunciationCategories(\n reading,\n pronunciations,\n wordClasses,\n headwordIndex,\n );\n if (pronunciationCategories !== null) {\n node.dataset.pronunciationCategories = pronunciationCategories;\n }\n if (wordClasses.length > 0) {\n node.dataset.wordClasses = wordClasses.join(' ');\n }\n\n const headwordReading = this._querySelector(node, '.headword-reading');\n this._setTextContent(headwordReading, reading);\n\n this._appendFurigana(termContainer, term, reading, this._appendKanjiLinks.bind(this));\n\n return node;\n }\n\n private _createInflectionRuleChain(\n inflectionRuleChain: Dictionary.InflectionRuleChainCandidate,\n ): HTMLElement | null {\n const { source, inflectionRules } = inflectionRuleChain;\n if (!Array.isArray(inflectionRules) || inflectionRules.length === 0) {\n return null;\n }\n const fragment = this._instantiate('inflection-rule-chain');\n\n const sourceIcon = this._getInflectionSourceIcon(source);\n fragment.appendChild(sourceIcon);\n\n this._appendMultiple(fragment, this._createTermInflection.bind(this), inflectionRules);\n return fragment;\n }\n\n private _getInflectionSourceIcon(source: Dictionary.InflectionSource): HTMLElement {\n const icon = this._document.createElement('span');\n icon.classList.add('inflection-source-icon');\n icon.dataset.inflectionSource = source;\n switch (source) {\n case 'dictionary':\n icon.title = 'Dictionary Deinflection';\n return icon;\n case 'algorithm':\n icon.title = 'Algorithm Deinflection';\n return icon;\n case 'both':\n icon.title = 'Dictionary and Algorithm Deinflection';\n return icon;\n }\n }\n\n private _createTermInflection(inflection: Dictionary.InflectionRule): DocumentFragment {\n const { name, description } = inflection;\n const fragment = this._templates.instantiateFragment('inflection');\n const node = this._querySelector(fragment, '.inflection');\n this._setTextContent(node, name);\n if (description) {\n node.title = description;\n }\n node.dataset.reason = name;\n return fragment;\n }\n\n private _createTermDefinition(\n definition: Dictionary.TermDefinition,\n dictionaryTag: Dictionary.Tag,\n headwords: Dictionary.TermHeadword[],\n uniqueTerms: Set<string>,\n uniqueReadings: Set<string>,\n ): HTMLElement {\n const { dictionary, tags, headwordIndices, entries } = definition;\n const disambiguations = getDisambiguations(headwords, headwordIndices, uniqueTerms, uniqueReadings);\n\n const node = this._instantiate('definition-item');\n\n const tagListContainer = this._querySelector(node, '.definition-tag-list');\n const onlyListContainer = this._querySelector(node, '.definition-disambiguation-list');\n const entriesContainer = this._querySelector(node, '.gloss-list');\n\n node.dataset.dictionary = dictionary;\n\n this._appendMultiple(tagListContainer, this._createTag.bind(this), [...tags, dictionaryTag]);\n this._appendMultiple(onlyListContainer, this._createTermDisambiguation.bind(this), disambiguations);\n this._appendMultiple(entriesContainer, this._createTermDefinitionEntry.bind(this), entries, dictionary);\n return node;\n }\n\n private _createDictionaryScopedStyleNode(\n definitions: Dictionary.TermDefinition[],\n dictionaryInfo: DictionaryImporter.Summary[],\n ): HTMLStyleElement | null {\n const usedDictionaries = new Set<string>();\n for (const { dictionary } of definitions) {\n usedDictionaries.add(dictionary);\n }\n\n let scopedCss = '';\n for (const dictionary of usedDictionaries) {\n const info = dictionaryInfo.find(({ title }) => title === dictionary);\n const styles = info?.styles?.trim() ?? '';\n if (styles.length === 0) {\n continue;\n }\n\n // Match extension behavior: scope dictionary CSS to entry elements using data-dictionary.\n const escapedTitle = dictionary.replaceAll('\\\\', '\\\\\\\\').replaceAll('\"', '\\\\\"');\n scopedCss += `\\n[data-dictionary=\"${escapedTitle}\"] {${styles}\\n}`;\n }\n\n if (scopedCss.length === 0) {\n return null;\n }\n\n const node = this._document.createElement('style');\n node.className = 'dictionary-entry-styles';\n node.textContent = scopedCss;\n return node;\n }\n\n private _createTermDefinitionEntry(\n entry: DictionaryData.TermGlossaryContent,\n dictionary: string,\n ): HTMLElement | null {\n switch (typeof entry) {\n case 'string':\n return this._createTermDefinitionEntryText(entry);\n case 'object': {\n switch (entry.type) {\n case 'image':\n return this._createTermDefinitionEntryImage(entry, dictionary);\n case 'structured-content':\n return this._createTermDefinitionEntryStructuredContent(entry.content, dictionary);\n case 'text':\n break;\n }\n break;\n }\n }\n return null;\n }\n\n private _createTermDefinitionEntryText(text: string): HTMLElement {\n const node = this._instantiate('gloss-item');\n const container = this._querySelector(node, '.gloss-content');\n this._setMultilineTextContent(container, text);\n return node;\n }\n\n private _createTermDefinitionEntryImage(data: DictionaryData.TermGlossaryImage, dictionary: string): HTMLElement {\n const { description } = data;\n\n const node = this._instantiate('gloss-item');\n\n const contentContainer = this._querySelector(node, '.gloss-content');\n const image = this._structuredContentGenerator.createDefinitionImage(data, dictionary);\n contentContainer.appendChild(image);\n\n if (typeof description === 'string') {\n const fragment = this._templates.instantiateFragment('gloss-item-image-description');\n const container = this._querySelector(fragment, '.gloss-image-description');\n this._setMultilineTextContent(container, description);\n contentContainer.appendChild(fragment);\n }\n\n return node;\n }\n\n private _createTermDefinitionEntryStructuredContent(\n content: StructuredContent.Content,\n dictionary: string,\n ): HTMLElement {\n const node = this._instantiate('gloss-item');\n const contentContainer = this._querySelector(node, '.gloss-content');\n this._structuredContentGenerator.appendStructuredContent(contentContainer, content, dictionary);\n return node;\n }\n\n private _createTermDisambiguation(disambiguation: string): HTMLElement {\n const node = this._instantiate('definition-disambiguation');\n node.dataset.term = disambiguation;\n this._setTextContent(node, disambiguation, this._language);\n return node;\n }\n\n private _createKanjiLink(character: string): HTMLAnchorElement {\n const node = this._document.createElement('a');\n node.className = 'headword-kanji-link';\n this._setTextContent(node, character, this._language);\n return node;\n }\n\n private _createKanjiDefinition(text: string): HTMLElement {\n const node = this._instantiate('kanji-gloss-item');\n const container = this._querySelector(node, '.kanji-gloss-content');\n this._setMultilineTextContent(container, text);\n return node;\n }\n\n private _createKanjiReading(reading: string): HTMLElement {\n const node = this._instantiate('kanji-reading');\n this._setTextContent(node, reading, this._language);\n return node;\n }\n\n private _createKanjiInfoTable(details: Dictionary.KanjiStat[]): HTMLElement {\n const node = this._instantiate('kanji-info-table');\n const container = this._querySelector(node, '.kanji-info-table-body');\n\n const count = this._appendMultiple(container, this._createKanjiInfoTableItem.bind(this), details);\n if (count === 0) {\n const n = this._createKanjiInfoTableItemEmpty();\n container.appendChild(n);\n }\n\n return node;\n }\n\n private _createKanjiInfoTableItem(details: Dictionary.KanjiStat): HTMLElement {\n const { content, name, value } = details;\n const node = this._instantiate('kanji-info-table-item');\n const nameNode = this._querySelector(node, '.kanji-info-table-item-header');\n const valueNode = this._querySelector(node, '.kanji-info-table-item-value');\n this._setTextContent(nameNode, content.length > 0 ? content : name);\n this._setTextContent(valueNode, typeof value === 'string' ? value : `${value}`);\n return node;\n }\n\n private _createKanjiInfoTableItemEmpty(): HTMLElement {\n return this._instantiate('kanji-info-table-empty');\n }\n\n private _createTag(tag: Dictionary.Tag): HTMLElement {\n const { content, name, category, redundant } = tag;\n const node = this._instantiate('tag');\n\n const inner = this._querySelector(node, '.tag-label-content');\n\n const contentString = content.join('\\n');\n\n node.title = contentString;\n this._setTextContent(inner, name);\n node.dataset.details = contentString.length > 0 ? contentString : name;\n node.dataset.category = category;\n if (redundant) {\n node.dataset.redundant = 'true';\n }\n\n return node;\n }\n\n private _createTermTag(tagInfo: DictionaryDataUtil.TagGroup, totalHeadwordCount: number): HTMLElement {\n const { tag, headwordIndices } = tagInfo;\n const node = this._createTag(tag);\n node.dataset.headwords = headwordIndices.join(' ');\n node.dataset.totalHeadwordCount = `${totalHeadwordCount}`;\n node.dataset.matchedHeadwordCount = `${headwordIndices.length}`;\n node.dataset.unmatchedHeadwordCount = `${Math.max(0, totalHeadwordCount - headwordIndices.length)}`;\n return node;\n }\n\n private _createTagData(name: string, category: string): Dictionary.Tag {\n return {\n name,\n category,\n order: 0,\n score: 0,\n content: [],\n dictionaries: [],\n redundant: false,\n };\n }\n\n private _createSearchTag(text: string): HTMLElement {\n return this._createTag(this._createTagData(text, 'search'));\n }\n\n private _createGroupedPronunciation(details: DictionaryDataUtil.DictionaryGroupedPronunciations): HTMLElement {\n const { dictionary, dictionaryAlias, pronunciations } = details;\n\n const node = this._instantiate('pronunciation-group');\n node.dataset.dictionary = dictionary;\n node.dataset.pronunciationsMulti = 'true';\n node.dataset.pronunciationsCount = `${pronunciations.length}`;\n\n const n1 = this._querySelector(node, '.pronunciation-group-tag-list');\n const tag = this._createTag(this._createTagData(dictionaryAlias, 'pronunciation-dictionary'));\n tag.dataset.details = dictionary;\n n1.appendChild(tag);\n\n let hasTags = false;\n for (const {\n pronunciation: { tags },\n } of pronunciations) {\n if (tags.length > 0) {\n hasTags = true;\n break;\n }\n }\n\n const n = this._querySelector(node, '.pronunciation-list');\n n.dataset.hasTags = `${hasTags}`;\n this._appendMultiple(n, this._createPronunciation.bind(this), pronunciations);\n\n return node;\n }\n\n private _createPronunciation(details: DictionaryDataUtil.GroupedPronunciation): HTMLElement {\n const { pronunciation } = details;\n switch (pronunciation.type) {\n case 'pitch-accent':\n return this._createPronunciationPitchAccent(pronunciation, details);\n case 'phonetic-transcription':\n return this._createPronunciationPhoneticTranscription(pronunciation, details);\n }\n }\n\n private _createPronunciationPhoneticTranscription(\n pronunciation: Dictionary.PhoneticTranscription,\n details: DictionaryDataUtil.GroupedPronunciation,\n ): HTMLElement {\n const { ipa, tags } = pronunciation;\n const { exclusiveTerms, exclusiveReadings } = details;\n\n const node = this._instantiate('pronunciation');\n\n node.dataset.pronunciationType = pronunciation.type;\n node.dataset.tagCount = `${tags.length}`;\n\n let n = this._querySelector(node, '.pronunciation-tag-list');\n this._appendMultiple(n, this._createTag.bind(this), tags);\n\n n = this._querySelector(node, '.pronunciation-disambiguation-list');\n this._createPronunciationDisambiguations(n, exclusiveTerms, exclusiveReadings);\n\n n = this._querySelector(node, '.pronunciation-text-container');\n this._setTextContent(n, ipa);\n\n return node;\n }\n\n private _createPronunciationPitchAccent(\n pitchAccent: Dictionary.PitchAccent,\n details: DictionaryDataUtil.GroupedPronunciation,\n ): HTMLElement {\n const { positions, nasalPositions, devoicePositions, tags } = pitchAccent;\n const { reading, exclusiveTerms, exclusiveReadings } = details;\n const morae = getKanaMorae(reading);\n\n const node = this._instantiate('pronunciation');\n\n node.dataset.pitchAccentDownstepPosition = `${positions}`;\n node.dataset.pronunciationType = pitchAccent.type;\n if (nasalPositions.length > 0) {\n node.dataset.nasalMoraPosition = nasalPositions.join(' ');\n }\n if (devoicePositions.length > 0) {\n node.dataset.devoiceMoraPosition = devoicePositions.join(' ');\n }\n node.dataset.tagCount = `${tags.length}`;\n\n let n = this._querySelector(node, '.pronunciation-tag-list');\n this._appendMultiple(n, this._createTag.bind(this), tags);\n\n n = this._querySelector(node, '.pronunciation-disambiguation-list');\n this._createPronunciationDisambiguations(n, exclusiveTerms, exclusiveReadings);\n\n n = this._querySelector(node, '.pronunciation-downstep-notation-container');\n n.appendChild(this._pronunciationGenerator.createPronunciationDownstepPosition(positions));\n\n n = this._querySelector(node, '.pronunciation-text-container');\n n.lang = this._language;\n n.appendChild(\n this._pronunciationGenerator.createPronunciationText(morae, positions, nasalPositions, devoicePositions),\n );\n\n n = this._querySelector(node, '.pronunciation-graph-container');\n n.appendChild(this._pronunciationGenerator.createPronunciationGraph(morae, positions));\n\n return node;\n }\n\n private _createPronunciationDisambiguations(\n container: HTMLElement,\n exclusiveTerms: string[],\n exclusiveReadings: string[],\n ): void {\n const templateName = 'pronunciation-disambiguation';\n for (const term of exclusiveTerms) {\n const node = this._instantiate(templateName);\n node.dataset.type = 'term';\n this._setTextContent(node, term, this._language);\n container.appendChild(node);\n }\n\n for (const exclusiveReading of exclusiveReadings) {\n const node = this._instantiate(templateName);\n node.dataset.type = 'reading';\n this._setTextContent(node, exclusiveReading, this._language);\n container.appendChild(node);\n }\n\n container.dataset.count = `${exclusiveTerms.length + exclusiveReadings.length}`;\n container.dataset.termCount = `${exclusiveTerms.length}`;\n container.dataset.readingCount = `${exclusiveReadings.length}`;\n }\n\n private _createFrequencyGroup(\n details:\n | DictionaryDataUtil.DictionaryFrequency<DictionaryDataUtil.TermFrequency>\n | DictionaryDataUtil.DictionaryFrequency<DictionaryDataUtil.KanjiFrequency>,\n kanji: boolean,\n ): HTMLElement {\n const { dictionary, dictionaryAlias, frequencies, freqCount } = details;\n\n const node = this._instantiate('frequency-group-item');\n const body = this._querySelector(node, '.tag-body-content');\n\n const tagLabel = this._querySelector(node, '.tag-label-content');\n const tag = this._querySelector(node, '.tag');\n\n this._setTextContent(tagLabel, dictionaryAlias);\n\n const ii = frequencies.length;\n for (let i = 0; i < ii; ++i) {\n const item = frequencies[i];\n const itemNode = kanji\n ? this._createKanjiFrequency(\n item as DictionaryDataUtil.KanjiFrequency,\n dictionary,\n dictionaryAlias,\n freqCount?.toString(),\n )\n : this._createTermFrequency(\n item as DictionaryDataUtil.TermFrequency,\n dictionary,\n dictionaryAlias,\n freqCount?.toString(),\n );\n itemNode.dataset.index = `${i}`;\n body.appendChild(itemNode);\n }\n\n body.dataset.count = `${ii}`;\n node.dataset.count = `${ii}`;\n node.dataset.details = dictionary;\n tag.dataset.details = `${dictionary}\\nDictionary size: ${freqCount?.toString()}${kanji ? ' kanji' : ' terms'}`;\n return node;\n }\n\n private _createTermFrequency(\n details: DictionaryDataUtil.TermFrequency,\n dictionary: string,\n dictionaryAlias: string,\n freqCount: string | undefined,\n ): HTMLElement {\n const { term, reading, values } = details;\n const node = this._instantiate('term-frequency-item');\n const tagLabel = this._querySelector(node, '.tag-label-content');\n const tag = this._querySelector(node, '.tag');\n const disambiguationTerm = this._querySelector(node, '.frequency-disambiguation-term');\n const disambiguationReading = this._querySelector(node, '.frequency-disambiguation-reading');\n const frequencyValueList = this._querySelector(node, '.frequency-value-list');\n\n this._setTextContent(tagLabel, dictionaryAlias);\n this._setTextContent(disambiguationTerm, term, this._language);\n this._setTextContent(disambiguationReading, reading !== null ? reading : '', this._language);\n this._populateFrequencyValueList(frequencyValueList, values);\n\n node.dataset.term = term;\n if (typeof reading === 'string') {\n node.dataset.reading = reading;\n }\n node.dataset.hasReading = `${reading !== null}`;\n node.dataset.readingIsSame = `${reading === term}`;\n node.dataset.dictionary = dictionary;\n node.dataset.details = dictionary;\n tag.dataset.details = `${dictionary}\\nDictionary size: ${freqCount ?? ''} terms`;\n return node;\n }\n\n private _createKanjiFrequency(\n details: DictionaryDataUtil.KanjiFrequency,\n dictionary: string,\n dictionaryAlias: string,\n freqCount: string | undefined,\n ): HTMLElement {\n const { character, values } = details;\n const node = this._instantiate('kanji-frequency-item');\n const tagLabel = this._querySelector(node, '.tag-label-content');\n const tag = this._querySelector(node, '.tag');\n const frequencyValueList = this._querySelector(node, '.frequency-value-list');\n\n this._setTextContent(tagLabel, dictionaryAlias);\n this._populateFrequencyValueList(frequencyValueList, values);\n\n node.dataset.character = character;\n node.dataset.dictionary = dictionary;\n node.dataset.details = dictionary;\n tag.dataset.details = `${dictionary}\\nDictionary size: ${freqCount ?? ''} kanji`;\n\n return node;\n }\n\n private _populateFrequencyValueList(node: HTMLElement, values: DictionaryDataUtil.FrequencyValue[]): void {\n let fullFrequency = '';\n for (let i = 0, ii = values.length; i < ii; ++i) {\n const { frequency, displayValue } = values[i];\n const frequencyString = `${frequency}`;\n const text = displayValue !== null ? displayValue : `${frequency}`;\n\n if (i > 0) {\n const node2 = this._document.createElement('span');\n node2.className = 'frequency-value';\n node2.dataset.frequency = `${frequency}`;\n node2.textContent = ', ';\n node.appendChild(node2);\n fullFrequency += ', ';\n }\n\n const node2 = this._document.createElement('span');\n node2.className = 'frequency-value';\n node2.dataset.frequency = frequencyString;\n if (displayValue !== null) {\n node2.dataset.displayValue = `${displayValue}`;\n if (displayValue !== frequencyString) {\n node2.title = frequencyString;\n }\n }\n this._setTextContent(node2, text, this._language);\n node.appendChild(node2);\n\n fullFrequency += text;\n }\n\n node.dataset.frequency = fullFrequency;\n }\n\n private _appendKanjiLinks(container: HTMLElement, text: string): void {\n let part = '';\n for (const c of text) {\n if (isCodePointKanji(c.codePointAt(0) as number)) {\n if (part.length > 0) {\n container.appendChild(this._document.createTextNode(part));\n part = '';\n }\n\n const link = this._createKanjiLink(c);\n container.appendChild(link);\n } else {\n part += c;\n }\n }\n if (part.length > 0) {\n container.appendChild(this._document.createTextNode(part));\n }\n }\n\n private _appendMultiple<TItem, TExtraArg = void>(\n container: HTMLElement,\n createItem: (item: TItem, arg: TExtraArg) => Node | null,\n detailsArray: TItem[],\n arg?: TExtraArg,\n ): number {\n let count = 0;\n const ELEMENT_NODE = 1;\n if (Array.isArray(detailsArray)) {\n for (const details of detailsArray) {\n const item = createItem(details, arg as TExtraArg);\n if (item === null) {\n continue;\n }\n container.appendChild(item);\n if (item.nodeType === ELEMENT_NODE) {\n (item as HTMLElement).dataset.index = `${count}`;\n }\n ++count;\n }\n }\n\n container.dataset.count = `${count}`;\n\n return count;\n }\n\n private _appendFurigana(\n container: HTMLElement,\n term: string,\n reading: string,\n addText: (element: HTMLElement, text: string) => void,\n ): void {\n container.lang = this._language;\n const segments = distributeFurigana(term, reading);\n for (const { text, reading: furigana } of segments) {\n if (furigana) {\n const ruby = this._document.createElement('ruby');\n const rt = this._document.createElement('rt');\n addText(ruby, text);\n ruby.appendChild(rt);\n rt.appendChild(this._document.createTextNode(furigana));\n container.appendChild(ruby);\n } else {\n addText(container, text);\n }\n }\n }\n\n private _createDictionaryTag(dictionary: string): Dictionary.Tag {\n return this._createTagData(dictionary, 'dictionary');\n }\n\n private _setTextContent(node: HTMLElement, value: string, language?: string): void {\n this._setElementLanguage(node, language, value);\n node.textContent = value;\n }\n\n private _setMultilineTextContent(node: HTMLElement, value: string, language?: string): void {\n this._setElementLanguage(node, language, value);\n\n let start = 0;\n while (true) {\n const end = value.indexOf('\\n', start);\n if (end < 0) {\n break;\n }\n node.appendChild(this._document.createTextNode(value.substring(start, end)));\n node.appendChild(this._document.createElement('br'));\n start = end + 1;\n }\n\n if (start < value.length) {\n node.appendChild(this._document.createTextNode(start === 0 ? value : value.substring(start)));\n }\n }\n\n private _setElementLanguage(element: HTMLElement, language: string | undefined, content: string): void {\n if (typeof language === 'string') {\n element.lang = language;\n } else {\n const language2 = getLanguageFromText(content, this._language);\n if (language2 !== null) {\n element.lang = language2;\n }\n }\n }\n\n private _getPronunciationCategories(\n reading: string,\n termPronunciations: Dictionary.TermPronunciation[],\n wordClasses: string[],\n headwordIndex: number,\n ): string | null {\n if (termPronunciations.length === 0) {\n return null;\n }\n const isVerbOrAdjective = isNonNounVerbOrAdjective(wordClasses);\n const categories = new Set<PitchCategory>();\n for (const termPronunciation of termPronunciations) {\n if (termPronunciation.headwordIndex !== headwordIndex) {\n continue;\n }\n for (const pronunciation of termPronunciation.pronunciations) {\n if (pronunciation.type !== 'pitch-accent') {\n continue;\n }\n const category = getPitchCategory(reading, pronunciation.positions, isVerbOrAdjective);\n if (category !== null) {\n categories.add(category);\n }\n }\n }\n return categories.size > 0 ? [...categories].join(' ') : null;\n }\n\n private _instantiate(name: string): HTMLElement {\n return this._templates.instantiate(name);\n }\n\n private _querySelector(element: Element | DocumentFragment, selector: string): HTMLElement {\n const result = element.querySelector(selector);\n if (result === null) {\n throw new Error(`Failed to find element: ${selector}`);\n }\n return result as HTMLElement;\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { distributeFurigana } from "./japanese-
|
|
1
|
+
import { distributeFurigana } from "./japanese-CKPyY5k_.js";
|
|
2
2
|
|
|
3
3
|
//#region src/language/ja/furigana.ts
|
|
4
4
|
function generateFurigana(text, reading) {
|
|
@@ -7,4 +7,4 @@ function generateFurigana(text, reading) {
|
|
|
7
7
|
|
|
8
8
|
//#endregion
|
|
9
9
|
export { generateFurigana };
|
|
10
|
-
//# sourceMappingURL=furigana-
|
|
10
|
+
//# sourceMappingURL=furigana-BpFJbm9M.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"furigana-
|
|
1
|
+
{"version":3,"file":"furigana-BpFJbm9M.js","names":["text: string","reading: string"],"sources":["../src/language/ja/furigana.ts"],"sourcesContent":["export type { FuriganaSegment } from './japanese';\nexport { distributeFurigana, distributeFuriganaInflected } from './japanese';\n\nimport { distributeFurigana } from './japanese';\nimport type { FuriganaSegment } from './japanese';\n\nexport function generateFurigana(text: string, reading: string): FuriganaSegment[] {\n return distributeFurigana(text, reading);\n}\n"],"mappings":";;;AAMA,SAAgB,iBAAiBA,MAAcC,SAAoC;AAC/E,QAAO,mBAAmB,MAAM,QAAQ;AAC3C"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
const require_japanese = require('./japanese-
|
|
2
|
+
const require_japanese = require('./japanese-C83fmEfb.cjs');
|
|
3
3
|
|
|
4
4
|
//#region src/language/ja/furigana.ts
|
|
5
5
|
function generateFurigana(text, reading) {
|
|
@@ -13,4 +13,4 @@ Object.defineProperty(exports, 'generateFurigana', {
|
|
|
13
13
|
return generateFurigana;
|
|
14
14
|
}
|
|
15
15
|
});
|
|
16
|
-
//# sourceMappingURL=furigana-
|
|
16
|
+
//# sourceMappingURL=furigana-dSFngFbc.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"furigana-
|
|
1
|
+
{"version":3,"file":"furigana-dSFngFbc.cjs","names":["text: string","reading: string"],"sources":["../src/language/ja/furigana.ts"],"sourcesContent":["export type { FuriganaSegment } from './japanese';\nexport { distributeFurigana, distributeFuriganaInflected } from './japanese';\n\nimport { distributeFurigana } from './japanese';\nimport type { FuriganaSegment } from './japanese';\n\nexport function generateFurigana(text: string, reading: string): FuriganaSegment[] {\n return distributeFurigana(text, reading);\n}\n"],"mappings":";;;;AAMA,SAAgB,iBAAiBA,MAAcC,SAAoC;AAC/E,QAAO,oCAAmB,MAAM,QAAQ;AAC3C"}
|