henkan 2.3.0 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/LICENSE.md +1 -1
  2. package/dist/index.cjs.js +145 -147
  3. package/dist/index.cjs.js.map +3 -3
  4. package/dist/index.mjs +128 -119
  5. package/dist/index.mjs.map +2 -2
  6. package/dist/types/constants.d.ts.map +1 -1
  7. package/dist/types/types.d.ts +5 -5
  8. package/dist/types/types.d.ts.map +1 -1
  9. package/dist/types/utils.d.ts +7 -0
  10. package/dist/types/utils.d.ts.map +1 -1
  11. package/docs/api/README.md +1 -0
  12. package/docs/api/functions/convertJMdict.md +1 -1
  13. package/docs/api/functions/convertJawiktionaryAsync.md +1 -1
  14. package/docs/api/functions/convertJawiktionarySync.md +1 -1
  15. package/docs/api/functions/convertKanjiDic.md +1 -1
  16. package/docs/api/functions/convertKradFile.md +1 -1
  17. package/docs/api/functions/convertRadkFile.md +1 -1
  18. package/docs/api/functions/convertTanakaCorpus.md +1 -1
  19. package/docs/api/functions/convertTanakaCorpusWithFurigana.md +1 -1
  20. package/docs/api/functions/createEntryMaps.md +1 -1
  21. package/docs/api/functions/generateAnkiNote.md +1 -1
  22. package/docs/api/functions/generateAnkiNotesFile.md +1 -1
  23. package/docs/api/functions/generateFurigana.md +33 -0
  24. package/docs/api/functions/getKanji.md +1 -1
  25. package/docs/api/functions/getKanjiExtended.md +1 -1
  26. package/docs/api/functions/getValidForms.md +1 -1
  27. package/docs/api/functions/getWord.md +1 -1
  28. package/docs/api/functions/getWordDefinitions.md +1 -1
  29. package/docs/api/functions/getWordDefinitionsWithFurigana.md +1 -1
  30. package/docs/api/interfaces/DefaultNoteInfo.md +4 -4
  31. package/docs/api/interfaces/Definition.md +4 -4
  32. package/docs/api/interfaces/DictKanji.md +5 -5
  33. package/docs/api/interfaces/DictKanjiMisc.md +5 -5
  34. package/docs/api/interfaces/DictKanjiReading.md +3 -3
  35. package/docs/api/interfaces/DictKanjiReadingMeaning.md +3 -3
  36. package/docs/api/interfaces/DictKanjiReadingMeaningGroup.md +3 -3
  37. package/docs/api/interfaces/DictKanjiWithRadicals.md +3 -3
  38. package/docs/api/interfaces/DictMeaning.md +11 -11
  39. package/docs/api/interfaces/DictRadical.md +4 -4
  40. package/docs/api/interfaces/DictWord.md +8 -8
  41. package/docs/api/interfaces/EntryMaps.md +7 -7
  42. package/docs/api/interfaces/ExamplePart.md +7 -7
  43. package/docs/api/interfaces/GlossSpecificNumber.md +3 -3
  44. package/docs/api/interfaces/Grammar.md +15 -15
  45. package/docs/api/interfaces/GrammarMeaning.md +3 -3
  46. package/docs/api/interfaces/JaWiktionaryEntry.md +9 -9
  47. package/docs/api/interfaces/Kana.md +11 -11
  48. package/docs/api/interfaces/Kanji.md +23 -23
  49. package/docs/api/interfaces/KanjiComponent.md +3 -3
  50. package/docs/api/interfaces/KanjiForm.md +4 -4
  51. package/docs/api/interfaces/NoteAndTag.md +3 -3
  52. package/docs/api/interfaces/NoteHeaderKeys.md +7 -7
  53. package/docs/api/interfaces/Phrase.md +5 -5
  54. package/docs/api/interfaces/Radical.md +16 -16
  55. package/docs/api/interfaces/Reading.md +5 -5
  56. package/docs/api/interfaces/ResultEntry.md +7 -7
  57. package/docs/api/interfaces/TanakaExample.md +7 -7
  58. package/docs/api/interfaces/Translation.md +3 -3
  59. package/docs/api/interfaces/UsefulRegExps.md +8 -8
  60. package/docs/api/interfaces/Word.md +15 -15
  61. package/docs/api/interfaces/WordDefinitionPair.md +4 -4
  62. package/docs/api/type-aliases/Dict.md +1 -1
  63. package/docs/api/type-aliases/DictTranslation.md +1 -1
  64. package/docs/api/type-aliases/EntryType.md +1 -1
  65. package/docs/api/type-aliases/KanjiEntryMap.md +1 -1
  66. package/docs/api/type-aliases/KanjiSVGMap.md +1 -1
  67. package/docs/api/type-aliases/KanjiWordsMap.md +1 -1
  68. package/docs/api/type-aliases/Result.md +1 -1
  69. package/docs/api/type-aliases/WordDefinitionsMap.md +1 -1
  70. package/docs/api/type-aliases/WordExamplesMap.md +1 -1
  71. package/docs/api/type-aliases/WordIDEntryMap.md +1 -1
  72. package/package.json +5 -3
  73. package/src/constants.ts +2 -1
  74. package/src/types.ts +5 -7
  75. package/src/utils.ts +127 -100
  76. package/tsconfig.json +60 -0
  77. package/tsconfig.types.json +9 -0
package/LICENSE.md CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2025 Ronokof
3
+ Copyright (c) 2026 Ronokof
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/dist/index.cjs.js CHANGED
@@ -42,6 +42,7 @@ __export(index_exports, {
42
42
  createEntryMaps: () => createEntryMaps,
43
43
  generateAnkiNote: () => generateAnkiNote,
44
44
  generateAnkiNotesFile: () => generateAnkiNotesFile,
45
+ generateFurigana: () => generateFurigana,
45
46
  getKanji: () => getKanji,
46
47
  getKanjiExtended: () => getKanjiExtended,
47
48
  getValidForms: () => getValidForms,
@@ -154,8 +155,9 @@ var noteMap = /* @__PURE__ */ new Map([
154
155
  ["tsugaru-ben", ["dialect::tsugaru-ben", "Dialect: Tsugaru-ben"]],
155
156
  ["aichi dialect", ["dialect::aichi", "Dialect: Aichi"]],
156
157
  ["tochigi dialect", ["dialect::tochigi", "Dialect: Tochigi"]],
157
- ["lit", ["literal_meaning", "Literal meaning"]],
158
158
  ["expl", ["explanation", "Explanation"]],
159
+ ["fig", ["figurative", "Figurative"]],
160
+ ["lit", ["literal_meaning", "Literal meaning"]],
159
161
  ["tm", ["trademark", "Trademark"]],
160
162
  ["adjective (keiyoushi)", ["adjective::i", "\u3044-adjective", "\u5F62\u5BB9\u8A5E"]],
161
163
  ["'taru' adjective", ["adjective::taru", "\u305F\u308B-adjective", "\u5F62\u5BB9\u52D5\u8A5E"]],
@@ -1340,6 +1342,22 @@ function katakanaToHiragana(input) {
1340
1342
  }
1341
1343
  return output.join("").normalize("NFC");
1342
1344
  }
1345
+ async function generateFurigana(text, bindedFunction) {
1346
+ if (!text.includes("\u30FB"))
1347
+ return String(
1348
+ await bindedFunction(text, {
1349
+ to: "hiragana",
1350
+ mode: "furigana"
1351
+ })
1352
+ );
1353
+ else
1354
+ return (await Promise.all(
1355
+ text.split("\u30FB").map(async (t) => {
1356
+ const tFurigana = await generateFurigana(t, bindedFunction);
1357
+ return tFurigana;
1358
+ })
1359
+ )).join("");
1360
+ }
1343
1361
  function getValidForms(readings, kanjiForms, wordIsCommon) {
1344
1362
  const kanjiFormRestrictions = /* @__PURE__ */ new Set();
1345
1363
  const validReadings = readings.filter(
@@ -1357,10 +1375,10 @@ function getValidForms(readings, kanjiForms, wordIsCommon) {
1357
1375
  return false;
1358
1376
  }
1359
1377
  );
1360
- const existValidKf = kanjiForms == null ? void 0 : kanjiForms.some(
1378
+ const existValidKf = kanjiForms?.some(
1361
1379
  (kf, index) => index !== 0 && (kf.notes === void 0 || !kf.notes.some((note) => notSearchedForms.has(note)) && (wordIsCommon === void 0 || kf.commonness !== void 0) || kanjiFormRestrictions.has(kf.form))
1362
1380
  );
1363
- const validKanjiForms = kanjiForms == null ? void 0 : kanjiForms.filter(
1381
+ const validKanjiForms = kanjiForms?.filter(
1364
1382
  (kanjiForm, index) => {
1365
1383
  if (index === 0) return true;
1366
1384
  if (existValidKf === true)
@@ -1435,13 +1453,16 @@ function convertJMdict(xmlString, examples) {
1435
1453
  const meaningObj = { partOfSpeech: [], translations: [] };
1436
1454
  meaningObj.partOfSpeech = meaning.pos;
1437
1455
  meaningObj.translations = [];
1438
- for (const gloss of meaning.gloss)
1439
- if (typeof gloss === "string") meaningObj.translations.push(gloss);
1440
- else if (typeof gloss === "object" && typeof gloss._ === "string" && typeof gloss.$ === "object" && (gloss.$.g_type === "lit" || gloss.$.g_type === "expl" || gloss.$.g_type === "tm"))
1456
+ for (const gloss of meaning.gloss) {
1457
+ const translation = String(gloss._ ?? gloss).trim();
1458
+ const type = typeof gloss.$ === "object" && typeof gloss.$.g_type === "string" ? gloss.$.g_type : void 0;
1459
+ if (translation.length > 0 && type !== void 0 && type.length > 0)
1441
1460
  meaningObj.translations.push({
1442
- translation: gloss._,
1443
- type: gloss.$.g_type
1461
+ translation,
1462
+ type
1444
1463
  });
1464
+ else meaningObj.translations.push(translation);
1465
+ }
1445
1466
  if (isStringArray(meaning.xref)) meaningObj.references = meaning.xref;
1446
1467
  if (isStringArray(meaning.stagk))
1447
1468
  meaningObj.kanjiFormRestrictions = meaning.stagk;
@@ -1563,7 +1584,6 @@ function convertKanjiDic(xmlString) {
1563
1584
  return dict;
1564
1585
  }
1565
1586
  function convertTanakaCorpus(tanakaString) {
1566
- var _a, _b;
1567
1587
  const tanakaArray = [];
1568
1588
  const tanakaParsed = tanakaString.split("\n");
1569
1589
  for (let i = 0; i <= tanakaParsed.length; i += 2) {
@@ -1572,7 +1592,7 @@ function convertTanakaCorpus(tanakaString) {
1572
1592
  if (a !== void 0 && b !== void 0 && a.startsWith("A: ") && b.startsWith("B: ")) {
1573
1593
  a = a.replace("A: ", "");
1574
1594
  b = b.replace("B: ", "");
1575
- const idMatch = (_b = (_a = regexps.tanakaID.exec(a)) == null ? void 0 : _a.groups["id"]) == null ? void 0 : _b.trim();
1595
+ const idMatch = regexps.tanakaID.exec(a)?.groups.id?.trim();
1576
1596
  const idParts = String(idMatch).split("_");
1577
1597
  const id = `${Number(idParts[0])}_${Number(idParts[1])}`;
1578
1598
  const aParts = a.replace(regexps.tanakaID, "").split(" ");
@@ -1580,17 +1600,15 @@ function convertTanakaCorpus(tanakaString) {
1580
1600
  const bParts = [];
1581
1601
  for (const part of bRawParts) {
1582
1602
  const partMatches = regexps.tanakaPart.exec(part);
1583
- const baseForm = partMatches == null ? void 0 : partMatches.groups["base"];
1603
+ const baseForm = partMatches?.groups.base;
1584
1604
  const examplePart = { baseForm };
1585
- const reading = partMatches == null ? void 0 : partMatches.groups["reading"];
1586
- const glossNumber = partMatches == null ? void 0 : partMatches.groups["glossnum"];
1587
- const inflectedForm = partMatches == null ? void 0 : partMatches.groups["inflection"];
1605
+ const reading = partMatches?.groups.reading;
1606
+ const glossNumber = partMatches?.groups.glossnum;
1607
+ const inflectedForm = partMatches?.groups.inflection;
1588
1608
  if (reading !== void 0)
1589
1609
  if (regexps.tanakaReferenceID.test(reading)) {
1590
1610
  const referenceID = regexps.tanakaReferenceID.exec(reading);
1591
- examplePart.referenceID = `${Number(
1592
- referenceID == null ? void 0 : referenceID.groups["entryid"]
1593
- )}`;
1611
+ examplePart.referenceID = `${Number(referenceID?.groups.entryid)}`;
1594
1612
  } else examplePart.reading = reading;
1595
1613
  if (glossNumber !== void 0)
1596
1614
  examplePart.glossNumber = glossNumber.startsWith("0") ? Number.parseInt(glossNumber.substring(1)) : Number.parseInt(glossNumber);
@@ -1620,13 +1638,10 @@ async function convertTanakaCorpusWithFurigana(tanakaString) {
1620
1638
  await kuroshiro.init(new KuromojiAnalyzer());
1621
1639
  const convert = kuroshiro.convert.bind(kuroshiro);
1622
1640
  for (let i = 0; i < tanakaArray.length; i++)
1623
- if (!tanakaArray[i].phrase.includes("\u30FB"))
1624
- tanakaArray[i].furigana = String(
1625
- await convert(tanakaArray[i].phrase, {
1626
- to: "hiragana",
1627
- mode: "furigana"
1628
- })
1629
- );
1641
+ tanakaArray[i].furigana = await generateFurigana(
1642
+ tanakaArray[i].phrase,
1643
+ convert
1644
+ );
1630
1645
  return tanakaArray;
1631
1646
  }
1632
1647
  function convertRadkFile(radkBuffer, kanjiDic) {
@@ -1679,7 +1694,7 @@ function convertKradFile(kradBuffer, kanjiDic, katakanaList) {
1679
1694
  const foundRadical = kanjiDic.find(
1680
1695
  (dictKanji) => dictKanji.kanji === radical
1681
1696
  );
1682
- let radicalObj = foundRadical != null ? foundRadical : { kanji: radical };
1697
+ let radicalObj = foundRadical ?? { kanji: radical };
1683
1698
  if (foundRadical === void 0) {
1684
1699
  const katakanaChar = katakanaList.find(
1685
1700
  (kana) => kana.kana === radical
@@ -1707,7 +1722,6 @@ function convertKradFile(kradBuffer, kanjiDic, katakanaList) {
1707
1722
  return kanjiWithRadicals;
1708
1723
  }
1709
1724
  function createEntryMaps(jmDict, kanjiDic, tanakaExamples, wordDefinitionPairs, svgList) {
1710
- var _a;
1711
1725
  const kanjiEntryMap = /* @__PURE__ */ new Map();
1712
1726
  const wordIDEntryMap = /* @__PURE__ */ new Map();
1713
1727
  const kanjiWordsMap = /* @__PURE__ */ new Map();
@@ -1808,7 +1822,7 @@ function createEntryMaps(jmDict, kanjiDic, tanakaExamples, wordDefinitionPairs,
1808
1822
  const seenEx = /* @__PURE__ */ new Set();
1809
1823
  const validExamples = [];
1810
1824
  for (const p of wordPartsMap.get(word.id)) {
1811
- const examplesForPart = (_a = partExamplesMap.get(p)) == null ? void 0 : _a.filter((ex) => !seenEx.has(ex.id));
1825
+ const examplesForPart = partExamplesMap.get(p)?.filter((ex) => !seenEx.has(ex.id));
1812
1826
  if (examplesForPart === void 0) continue;
1813
1827
  for (const ex of examplesForPart) {
1814
1828
  seenEx.add(ex.id);
@@ -1830,26 +1844,30 @@ function createEntryMaps(jmDict, kanjiDic, tanakaExamples, wordDefinitionPairs,
1830
1844
  };
1831
1845
  }
1832
1846
  function mapEntry(entry) {
1847
+ const senses = Array.from(
1848
+ entry.senses.filter(
1849
+ (sense) => isObjectArray(sense.form_of) && sense.form_of.every((form) => typeof form.word === "string") === true || isStringArray(sense.glosses)
1850
+ )
1851
+ );
1833
1852
  return {
1834
1853
  word: entry.word,
1835
1854
  pos_title: entry.pos_title,
1836
- senses: entry.senses.filter(
1837
- (sense) => (isObjectArray(sense.form_of) ? sense.form_of.every((form) => typeof form.word === "string") : isStringArray(sense.glosses)) === true || isStringArray(sense.glosses)
1838
- ).map((sense) => ({
1839
- ...isObjectArray(sense.form_of) ? {
1840
- form_of: sense.form_of.map((form) => String(form.word))
1841
- } : {},
1842
- glosses: sense.glosses
1843
- })),
1855
+ ...senses.length > 0 ? {
1856
+ senses: entry.senses.map((sense) => ({
1857
+ ...isObjectArray(sense.form_of) ? {
1858
+ form_of: sense.form_of.map((form) => String(form.word))
1859
+ } : {},
1860
+ glosses: sense.glosses
1861
+ }))
1862
+ } : {},
1844
1863
  ...isObjectArray(entry.forms) && entry.forms.every((form) => typeof form.form === "string") === true ? { forms: entry.forms.map((form) => String(form.form)) } : {}
1845
1864
  };
1846
1865
  }
1847
1866
  function convertJawiktionarySync(buffer) {
1848
- var _a;
1849
1867
  const lines = buffer.toString("utf-8").split("\n");
1850
1868
  const entries = [];
1851
1869
  for (let i = 0; i < lines.length; i++) {
1852
- const line = (_a = lines[i]) == null ? void 0 : _a.trim();
1870
+ const line = lines[i]?.trim();
1853
1871
  if (line === void 0 || line.length === 0) continue;
1854
1872
  const obj = JSON.parse(line);
1855
1873
  if (typeof obj === "object" && (obj.lang === "\u65E5\u672C\u8A9E" || obj.lang === "\u53E4\u5178\u65E5\u672C\u8A9E"))
@@ -1874,18 +1892,18 @@ async function convertJawiktionaryAsync(stream) {
1874
1892
  return entries;
1875
1893
  }
1876
1894
  function parseEntry(entry, definitions, definitionMap) {
1877
- for (const sense of entry.senses) {
1878
- const definition = sense.glosses.join("");
1879
- if (!definitions.some((def) => def.definition === definition)) {
1880
- if (!definitionMap.has(definition))
1881
- definitionMap.set(definition, { count: 1 });
1882
- else definitionMap.get(definition).count++;
1883
- definitions.push({ definition });
1895
+ if (entry.senses !== void 0)
1896
+ for (const sense of entry.senses) {
1897
+ const definition = sense.glosses.join("");
1898
+ if (!definitions.some((def) => def.definition === definition)) {
1899
+ if (!definitionMap.has(definition))
1900
+ definitionMap.set(definition, { count: 1 });
1901
+ else definitionMap.get(definition).count++;
1902
+ definitions.push({ definition });
1903
+ }
1884
1904
  }
1885
- }
1886
1905
  }
1887
1906
  function getWordDefinitions(wiktionaryEntries, jmDict) {
1888
- var _a, _b, _c, _d, _e;
1889
1907
  const entries = /* @__PURE__ */ new Map();
1890
1908
  for (const entry of wiktionaryEntries) {
1891
1909
  const ent = entries.get(entry.word);
@@ -1932,19 +1950,20 @@ function getWordDefinitions(wiktionaryEntries, jmDict) {
1932
1950
  let valid = false;
1933
1951
  if (validKanjiForms.has(entry.word)) {
1934
1952
  valid = true;
1935
- for (const sense of entry.senses) {
1936
- if (sense.form_of !== void 0 && sense.form_of.some((form) => validForms.has(form)))
1937
- validFormOfEntries.add(entry.word);
1938
- for (const gloss of sense.glosses) {
1939
- let hasForm = false;
1940
- for (const r of validForms)
1941
- if (gloss.includes(r)) {
1942
- hasForm = true;
1943
- break;
1944
- }
1945
- if (hasForm) validGlossesEntries.add(entry.word);
1953
+ if (entry.senses !== void 0)
1954
+ for (const sense of entry.senses) {
1955
+ if (sense.form_of !== void 0 && sense.form_of.some((form) => validForms.has(form)))
1956
+ validFormOfEntries.add(entry.word);
1957
+ for (const gloss of sense.glosses) {
1958
+ let hasForm = false;
1959
+ for (const r of validForms)
1960
+ if (gloss.includes(r)) {
1961
+ hasForm = true;
1962
+ break;
1963
+ }
1964
+ if (hasForm) validGlossesEntries.add(entry.word);
1965
+ }
1946
1966
  }
1947
- }
1948
1967
  if (entry.forms !== void 0) {
1949
1968
  for (const form of entry.forms)
1950
1969
  if (validForms.has(form)) validFormsEntries.add(entry.word);
@@ -2023,7 +2042,7 @@ function getWordDefinitions(wiktionaryEntries, jmDict) {
2023
2042
  for (const m of word.meanings)
2024
2043
  for (const note of m.partOfSpeech) {
2025
2044
  const noteEntry = noteMap.get(note);
2026
- if ((noteEntry == null ? void 0 : noteEntry.length) === 3) {
2045
+ if (noteEntry?.length === 3) {
2027
2046
  const notePos = noteEntry[2];
2028
2047
  if (Array.isArray(notePos))
2029
2048
  for (const pos of notePos) {
@@ -2042,8 +2061,8 @@ function getWordDefinitions(wiktionaryEntries, jmDict) {
2042
2061
  const posEntries = posMap.get(pos);
2043
2062
  if (rkf.kanjiForms !== void 0)
2044
2063
  for (const kf of rkf.kanjiForms) {
2045
- const te = (_a = posEntries.title) == null ? void 0 : _a.get(kf);
2046
- const fe = (_b = posEntries.form) == null ? void 0 : _b.get(kf);
2064
+ const te = posEntries.title?.get(kf);
2065
+ const fe = posEntries.form?.get(kf);
2047
2066
  if (te !== void 0)
2048
2067
  entriesWithTitles.push(
2049
2068
  ...te.filter(
@@ -2060,9 +2079,9 @@ function getWordDefinitions(wiktionaryEntries, jmDict) {
2060
2079
  );
2061
2080
  }
2062
2081
  for (const r of rkf.readings) {
2063
- const te = (_c = posEntries.title) == null ? void 0 : _c.get(r);
2064
- const fe = (_d = posEntries.form) == null ? void 0 : _d.get(r);
2065
- const fte = (_e = posEntries.formTitle) == null ? void 0 : _e.get(r);
2082
+ const te = posEntries.title?.get(r);
2083
+ const fe = posEntries.form?.get(r);
2084
+ const fte = posEntries.formTitle?.get(r);
2066
2085
  if (te !== void 0)
2067
2086
  entriesWithTitles.push(
2068
2087
  ...te.filter(
@@ -2150,25 +2169,26 @@ function getWordDefinitions(wiktionaryEntries, jmDict) {
2150
2169
  const hasForms = ent.forms !== void 0 && ent.forms.some((form) => pair.forms.has(form));
2151
2170
  if (pair.kanjiForms !== void 0 && pair.kanjiForms.has(ent.word)) {
2152
2171
  kanjiFormEntries.push(ent);
2153
- for (const sense of ent.senses) {
2154
- if (hasValidFormOf && sense.form_of !== void 0) {
2155
- for (const form of sense.form_of)
2156
- if (pair.forms.has(form)) {
2157
- const elem = titleFormMap.get(form);
2158
- if (elem === void 0)
2159
- titleFormMap.set(form, /* @__PURE__ */ new Set([ent.word]));
2160
- else elem.add(ent.word);
2161
- }
2172
+ if (ent.senses !== void 0)
2173
+ for (const sense of ent.senses) {
2174
+ if (hasValidFormOf && sense.form_of !== void 0) {
2175
+ for (const form of sense.form_of)
2176
+ if (pair.forms.has(form)) {
2177
+ const elem = titleFormMap.get(form);
2178
+ if (elem === void 0)
2179
+ titleFormMap.set(form, /* @__PURE__ */ new Set([ent.word]));
2180
+ else elem.add(ent.word);
2181
+ }
2182
+ }
2183
+ for (const gloss of sense.glosses)
2184
+ for (const f of pair.forms)
2185
+ if (gloss.includes(f)) {
2186
+ const elem = refsMap.get(f);
2187
+ if (elem === void 0)
2188
+ refsMap.set(f, /* @__PURE__ */ new Set([ent.word]));
2189
+ else elem.add(ent.word);
2190
+ }
2162
2191
  }
2163
- for (const gloss of sense.glosses)
2164
- for (const f of pair.forms)
2165
- if (gloss.includes(f)) {
2166
- const elem = refsMap.get(f);
2167
- if (elem === void 0)
2168
- refsMap.set(f, /* @__PURE__ */ new Set([ent.word]));
2169
- else elem.add(ent.word);
2170
- }
2171
- }
2172
2192
  if (hasValidForms && ent.forms !== void 0) {
2173
2193
  for (const form of ent.forms)
2174
2194
  if (pair.forms.has(form)) forms.add(form);
@@ -2249,13 +2269,10 @@ async function getWordDefinitionsWithFurigana(entryList, jmDict) {
2249
2269
  for (let i = 0; i < japaneseDefinitions.length; i++) {
2250
2270
  const pair = japaneseDefinitions[i];
2251
2271
  for (let j = 0; j < pair.definitions.length; j++)
2252
- if (!pair.definitions[j].definition.includes("\u30FB"))
2253
- pair.definitions[j].furigana = String(
2254
- await convert(pair.definitions[j].definition, {
2255
- to: "hiragana",
2256
- mode: "furigana"
2257
- })
2258
- );
2272
+ pair.definitions[j].furigana = await generateFurigana(
2273
+ pair.definitions[j].definition,
2274
+ convert
2275
+ );
2259
2276
  japaneseDefinitions[i] = pair;
2260
2277
  }
2261
2278
  return japaneseDefinitions;
@@ -2276,7 +2293,6 @@ var wordAddNoteArray = (arr, cb) => {
2276
2293
  for (const v of arr) cb(v);
2277
2294
  };
2278
2295
  function getKanji(searchedKanji, dict, jmDict, svgList, noteTypeName, deckPath) {
2279
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
2280
2296
  let dictKanji = void 0;
2281
2297
  if (typeof searchedKanji === "string" && dict !== void 0)
2282
2298
  dictKanji = dict instanceof Map ? dict.get(searchedKanji) : dict.find((entry) => entry.kanji === searchedKanji);
@@ -2285,9 +2301,9 @@ function getKanji(searchedKanji, dict, jmDict, svgList, noteTypeName, deckPath)
2285
2301
  const kanji = {
2286
2302
  kanji: dictKanji.kanji,
2287
2303
  strokes: dictKanji.misc.strokeNumber,
2288
- ...((_a = dictKanji.misc) == null ? void 0 : _a.grade) !== void 0 ? { grade: dictKanji.misc.grade } : {},
2289
- ...((_b = dictKanji.misc) == null ? void 0 : _b.frequency) !== void 0 ? { frequency: dictKanji.misc.frequency } : {},
2290
- ...((_c = dictKanji.misc) == null ? void 0 : _c.jlpt) !== void 0 ? { jlpt: dictKanji.misc.jlpt } : {},
2304
+ ...dictKanji.misc?.grade !== void 0 ? { grade: dictKanji.misc.grade } : {},
2305
+ ...dictKanji.misc?.frequency !== void 0 ? { frequency: dictKanji.misc.frequency } : {},
2306
+ ...dictKanji.misc?.jlpt !== void 0 ? { jlpt: dictKanji.misc.jlpt } : {},
2291
2307
  noteID: `kanji_${dictKanji.kanji}`,
2292
2308
  ...noteTypeName !== void 0 ? { noteTypeName } : {},
2293
2309
  ...deckPath !== void 0 ? { deckPath } : {},
@@ -2323,7 +2339,7 @@ function getKanji(searchedKanji, dict, jmDict, svgList, noteTypeName, deckPath)
2323
2339
  }
2324
2340
  if (jmDict !== void 0) {
2325
2341
  let kanjiWords = jmDict instanceof Map ? jmDict.get(kanji.kanji) : jmDict;
2326
- const firstKfWords = kanjiWords == null ? void 0 : kanjiWords.filter(
2342
+ const firstKfWords = kanjiWords?.filter(
2327
2343
  (word) => word.kanjiForms !== void 0 && word.kanjiForms[0].form.includes(kanji.kanji)
2328
2344
  );
2329
2345
  if (firstKfWords !== void 0 && firstKfWords.length > 0)
@@ -2331,17 +2347,17 @@ function getKanji(searchedKanji, dict, jmDict, svgList, noteTypeName, deckPath)
2331
2347
  if (kanjiWords !== void 0) {
2332
2348
  const validWords = [];
2333
2349
  for (const word of kanjiWords) {
2334
- const kanjiForm = (_d = firstKfWords !== void 0 && firstKfWords.length > 0 ? word.kanjiForms[0] : word.kanjiForms.find(
2350
+ const kanjiForm = (firstKfWords !== void 0 && firstKfWords.length > 0 ? word.kanjiForms[0] : word.kanjiForms.find(
2335
2351
  (kf) => kf.form.includes(kanji.kanji)
2336
- )) == null ? void 0 : _d.form;
2352
+ ))?.form;
2337
2353
  if (kanjiForm !== void 0) {
2338
- const reading = (_e = firstKfWords !== void 0 && firstKfWords.length > 0 ? word.readings[0] : word.readings.find(
2354
+ const reading = (firstKfWords !== void 0 && firstKfWords.length > 0 ? word.readings[0] : word.readings.find(
2339
2355
  (r) => r.kanjiFormRestrictions !== void 0 && r.kanjiFormRestrictions.includes(kanjiForm)
2340
- )) == null ? void 0 : _e.reading;
2356
+ ))?.reading;
2341
2357
  if (reading === void 0) continue;
2342
- const translation = (_f = firstKfWords !== void 0 && firstKfWords.length > 0 ? word.meanings[0] : word.meanings.find(
2358
+ const translation = (firstKfWords !== void 0 && firstKfWords.length > 0 ? word.meanings[0] : word.meanings.find(
2343
2359
  (m) => m.kanjiFormRestrictions !== void 0 && m.kanjiFormRestrictions.includes(kanjiForm)
2344
- )) == null ? void 0 : _f.translations.map(
2360
+ ))?.translations.map(
2345
2361
  (t) => typeof t === "string" ? t : t.translation
2346
2362
  )[0];
2347
2363
  if (translation === void 0) continue;
@@ -2378,10 +2394,10 @@ function getKanji(searchedKanji, dict, jmDict, svgList, noteTypeName, deckPath)
2378
2394
  ...kanji.frequency !== void 0 ? [`kanji::frequency::${kanji.frequency}`] : [],
2379
2395
  ...kanji.grade !== void 0 ? [`kanji::grade::${kanji.grade}`] : [],
2380
2396
  ...kanji.jlpt !== void 0 ? [`kanji::pre-2010_jlpt::${kanji.jlpt.toLowerCase()}`] : [],
2381
- `kanji::onyomi::${(_h = (_g = kanji.onyomi) == null ? void 0 : _g.length) != null ? _h : 0}`,
2382
- `kanji::kunyomi::${(_j = (_i = kanji.kunyomi) == null ? void 0 : _i.length) != null ? _j : 0}`,
2383
- `kanji::nanori::${(_l = (_k = kanji.nanori) == null ? void 0 : _k.length) != null ? _l : 0}`,
2384
- `kanji::words::${(_n = (_m = kanji.words) == null ? void 0 : _m.length) != null ? _n : 0}`,
2397
+ `kanji::onyomi::${kanji.onyomi?.length ?? 0}`,
2398
+ `kanji::kunyomi::${kanji.kunyomi?.length ?? 0}`,
2399
+ `kanji::nanori::${kanji.nanori?.length ?? 0}`,
2400
+ `kanji::words::${kanji.words?.length ?? 0}`,
2385
2401
  ...kanji.svg !== void 0 ? ["kanji::has_svg"] : []
2386
2402
  );
2387
2403
  return kanji;
@@ -2426,7 +2442,6 @@ function getKanjiExtended(info, kanji, dict, useWords, jmDict, svgList, noteType
2426
2442
  } else return void 0;
2427
2443
  }
2428
2444
  function getWord(searchedWord, dict, kanjiDic, examples, definitions, noteTypeName, deckPath) {
2429
- var _a, _b;
2430
2445
  let dictWord = void 0;
2431
2446
  if (typeof searchedWord === "string" && dict !== void 0) {
2432
2447
  if (Array.isArray(dict))
@@ -2560,7 +2575,7 @@ function getWord(searchedWord, dict, kanjiDic, examples, definitions, noteTypeNa
2560
2575
  seenChars.add(char);
2561
2576
  const kanjiEntry = kanjiDic instanceof Map ? kanjiDic.get(char) : void 0;
2562
2577
  const kanjiObj = getKanji(
2563
- kanjiEntry != null ? kanjiEntry : char,
2578
+ kanjiEntry ?? char,
2564
2579
  !(kanjiDic instanceof Map) ? kanjiDic : void 0
2565
2580
  );
2566
2581
  if (kanjiObj !== void 0)
@@ -2572,7 +2587,7 @@ function getWord(searchedWord, dict, kanjiDic, examples, definitions, noteTypeNa
2572
2587
  if (kanji.length > 0) word.kanji = kanji;
2573
2588
  }
2574
2589
  if (dictWord.hasPhrases === true && examples !== void 0) {
2575
- const exampleList = examples instanceof Map ? (_a = examples.get(dictWord.id)) != null ? _a : [] : examples;
2590
+ const exampleList = examples instanceof Map ? examples.get(dictWord.id) ?? [] : examples;
2576
2591
  const rkf = getValidForms(
2577
2592
  dictWord.readings,
2578
2593
  dictWord.kanjiForms,
@@ -2657,31 +2672,25 @@ function getWord(searchedWord, dict, kanjiDic, examples, definitions, noteTypeNa
2657
2672
  wordExamples = glossSpecificExamples;
2658
2673
  }
2659
2674
  if (wordExamples.length > 0) {
2660
- word.phrases = (glossSpecificExamples.length === 0 ? wordExamples.slice(0, 5) : wordExamples).map((ex) => {
2661
- var _a2;
2662
- return {
2663
- phrase: (_a2 = ex.ex.furigana) != null ? _a2 : ex.ex.phrase,
2664
- translation: ex.ex.translation,
2665
- originalPhrase: ex.ex.phrase,
2666
- ...ex.ex.glossNumber !== void 0 ? { glossNumber: ex.ex.glossNumber } : {}
2667
- };
2668
- });
2675
+ word.phrases = (glossSpecificExamples.length === 0 ? wordExamples.slice(0, 5) : wordExamples).map((ex) => ({
2676
+ phrase: ex.ex.furigana ?? ex.ex.phrase,
2677
+ translation: ex.ex.translation,
2678
+ originalPhrase: ex.ex.phrase,
2679
+ ...ex.ex.glossNumber !== void 0 ? { glossNumber: ex.ex.glossNumber } : {}
2680
+ }));
2669
2681
  word.tags.push("word::has_phrases");
2670
2682
  if (glossSpecificExamples.length > 0)
2671
2683
  word.tags.push("word::has_meaning-specific_phrases");
2672
2684
  }
2673
2685
  }
2674
2686
  if (definitions !== void 0) {
2675
- const defs = definitions instanceof Map ? definitions.get(word.id) : (_b = definitions.find(
2687
+ const defs = definitions instanceof Map ? definitions.get(word.id) : definitions.find(
2676
2688
  (wdp) => wdp.wordID === word.id
2677
- )) == null ? void 0 : _b.definitions;
2689
+ )?.definitions;
2678
2690
  if (defs !== void 0)
2679
2691
  word.definitions = [
2680
2692
  ...defs.toSorted(
2681
- (a, b) => {
2682
- var _a2, _b2;
2683
- return ((_a2 = a.mayNotBeAccurate) != null ? _a2 : 0) - ((_b2 = b.mayNotBeAccurate) != null ? _b2 : 0);
2684
- }
2693
+ (a, b) => (a.mayNotBeAccurate ?? 0) - (b.mayNotBeAccurate ?? 0)
2685
2694
  )
2686
2695
  ];
2687
2696
  }
@@ -2689,29 +2698,23 @@ function getWord(searchedWord, dict, kanjiDic, examples, definitions, noteTypeNa
2689
2698
  } else return void 0;
2690
2699
  }
2691
2700
  function isWord(entry) {
2692
- var _a, _b;
2693
- return isObjectArray((_a = Object.getOwnPropertyDescriptor(entry, "readings")) == null ? void 0 : _a.value) && isObjectArray((_b = Object.getOwnPropertyDescriptor(entry, "translations")) == null ? void 0 : _b.value);
2701
+ return isObjectArray(Object.getOwnPropertyDescriptor(entry, "readings")?.value) && isObjectArray(Object.getOwnPropertyDescriptor(entry, "translations")?.value);
2694
2702
  }
2695
2703
  function isRadical(entry) {
2696
- var _a;
2697
- return typeof ((_a = Object.getOwnPropertyDescriptor(entry, "radical")) == null ? void 0 : _a.value) === "string";
2704
+ return typeof Object.getOwnPropertyDescriptor(entry, "radical")?.value === "string";
2698
2705
  }
2699
2706
  function isKanji(entry) {
2700
- var _a;
2701
- return !Object.hasOwn(entry, "translations") && !Object.hasOwn(entry, "readings") && !Object.hasOwn(entry, "radical") && typeof ((_a = Object.getOwnPropertyDescriptor(entry, "kanji")) == null ? void 0 : _a.value) === "string";
2707
+ return !Object.hasOwn(entry, "translations") && !Object.hasOwn(entry, "readings") && !Object.hasOwn(entry, "radical") && typeof Object.getOwnPropertyDescriptor(entry, "kanji")?.value === "string";
2702
2708
  }
2703
2709
  function isKana(entry) {
2704
- var _a;
2705
- return typeof ((_a = Object.getOwnPropertyDescriptor(entry, "kana")) == null ? void 0 : _a.value) === "string";
2710
+ return typeof Object.getOwnPropertyDescriptor(entry, "kana")?.value === "string";
2706
2711
  }
2707
2712
  function isGrammar(entry) {
2708
- var _a;
2709
- return typeof ((_a = Object.getOwnPropertyDescriptor(entry, "point")) == null ? void 0 : _a.value) === "string";
2713
+ return typeof Object.getOwnPropertyDescriptor(entry, "point")?.value === "string";
2710
2714
  }
2711
2715
  var createNotes = (notes, phrase) => `${phrase === true ? "<details><summary>Show translation</summary>" : ""}<ul class="note-list">${notes.map((note) => `<li class="note">${note}</li>`).join("")}</ul>${phrase === true ? "</details>" : ""}`;
2712
2716
  var createEntry = (entry, notes, phrase, glossSpecific) => `<div class="entry${glossSpecific === true ? " gloss-specific" : ""}">${entry}${notes !== void 0 && notes.length > 0 ? createNotes(notes, phrase) : ""}</div>`;
2713
2717
  function generateAnkiNote(entry) {
2714
- var _a, _b;
2715
2718
  const fields = [];
2716
2719
  if (isWord(entry)) {
2717
2720
  const firstReading = createEntry(
@@ -2763,7 +2766,7 @@ function generateAnkiNote(entry) {
2763
2766
  );
2764
2767
  }).filter((translation) => translation !== "null").join("")}</details>` : "";
2765
2768
  const translationsField = `${firstThreeTranslations}${otherTranslations}`;
2766
- const firstFivePhrases = (_a = entry.phrases) == null ? void 0 : _a.slice(0, 5).map(
2769
+ const firstFivePhrases = entry.phrases?.slice(0, 5).map(
2767
2770
  (phraseEntry, index) => createEntry(
2768
2771
  `<span class="word word-phrase"><span class="word word-phrase-original">${phraseEntry.originalPhrase}</span><span class="word word-phrase-furigana">${phraseEntry.phrase}</span></span>`,
2769
2772
  [phraseEntry.translation],
@@ -2785,21 +2788,15 @@ function generateAnkiNote(entry) {
2785
2788
  );
2786
2789
  }).filter((phrase) => phrase !== "null").join("")}</details>` : "";
2787
2790
  const phrasesField = firstFivePhrases !== void 0 ? `${firstFivePhrases}${otherPhrases}` : '<span class="word word-phrase">(no phrases) (Search on dictionaries!)</span>';
2788
- const firstThreeDefinitions = (_b = entry.definitions) == null ? void 0 : _b.slice(0, 3).map(
2789
- (definitionEntry) => {
2790
- var _a2;
2791
- return createEntry(
2792
- `<span class="word word-definition${definitionEntry.mayNotBeAccurate === 2 ? " mnba2" : definitionEntry.mayNotBeAccurate === 1 ? " mnba1" : ""}"><span class="word word-definition-original">${definitionEntry.definition}</span><span class="word word-definition-furigana">${(_a2 = definitionEntry.furigana) != null ? _a2 : definitionEntry.definition}</span></span>`
2793
- );
2794
- }
2791
+ const firstThreeDefinitions = entry.definitions?.slice(0, 3).map(
2792
+ (definitionEntry) => createEntry(
2793
+ `<span class="word word-definition${definitionEntry.mayNotBeAccurate === 2 ? " mnba2" : definitionEntry.mayNotBeAccurate === 1 ? " mnba1" : ""}"><span class="word word-definition-original">${definitionEntry.definition}</span><span class="word word-definition-furigana">${definitionEntry.furigana ?? definitionEntry.definition}</span></span>`
2794
+ )
2795
2795
  ).join("");
2796
2796
  const otherDefinitions = entry.definitions !== void 0 && entry.definitions.length > 3 ? `<details><summary>Show other definitions</summary>${entry.definitions.map(
2797
- (definitionEntry, index) => {
2798
- var _a2;
2799
- return index > 2 ? createEntry(
2800
- `<span class="word word-definition${definitionEntry.mayNotBeAccurate === 2 ? " mnba2" : definitionEntry.mayNotBeAccurate === 1 ? " mnba1" : ""}"><span class="word word-definition-original">${definitionEntry.definition}</span><span class="word word-definition-furigana">${(_a2 = definitionEntry.furigana) != null ? _a2 : definitionEntry.definition}</span></span>`
2801
- ) : "null";
2802
- }
2797
+ (definitionEntry, index) => index > 2 ? createEntry(
2798
+ `<span class="word word-definition${definitionEntry.mayNotBeAccurate === 2 ? " mnba2" : definitionEntry.mayNotBeAccurate === 1 ? " mnba1" : ""}"><span class="word word-definition-original">${definitionEntry.definition}</span><span class="word word-definition-furigana">${definitionEntry.furigana ?? definitionEntry.definition}</span></span>`
2799
+ ) : "null"
2803
2800
  ).filter((definition) => definition !== "null").join("")}</details>` : "";
2804
2801
  const definitionsField = firstThreeDefinitions !== void 0 ? `${firstThreeDefinitions}${otherDefinitions}` : '<span class="word word-definition">(no definitions)</span>';
2805
2802
  fields.push(
@@ -3020,6 +3017,7 @@ ${ankiNotes}`;
3020
3017
  createEntryMaps,
3021
3018
  generateAnkiNote,
3022
3019
  generateAnkiNotesFile,
3020
+ generateFurigana,
3023
3021
  getKanji,
3024
3022
  getKanjiExtended,
3025
3023
  getValidForms,