henkan 2.4.12 → 3.0.1

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 (87) hide show
  1. package/README.md +1 -1
  2. package/dist/index.cjs.js +439 -46
  3. package/dist/index.cjs.js.map +2 -2
  4. package/dist/index.mjs +436 -46
  5. package/dist/index.mjs.map +2 -2
  6. package/dist/types/types.d.ts +106 -15
  7. package/dist/types/types.d.ts.map +1 -1
  8. package/dist/types/utils.d.ts +28 -6
  9. package/dist/types/utils.d.ts.map +1 -1
  10. package/docs/api/README.md +8 -2
  11. package/docs/api/functions/capitalizeString.md +1 -1
  12. package/docs/api/functions/convertJMdict.md +1 -1
  13. package/docs/api/functions/convertJMnedict.md +33 -0
  14. package/docs/api/functions/convertJawiktionaryAsync.md +1 -1
  15. package/docs/api/functions/convertJawiktionarySync.md +1 -1
  16. package/docs/api/functions/convertKanjiDic.md +1 -1
  17. package/docs/api/functions/convertKradFile.md +1 -1
  18. package/docs/api/functions/convertRadkFile.md +1 -1
  19. package/docs/api/functions/convertTanakaCorpus.md +1 -1
  20. package/docs/api/functions/convertTanakaCorpusWithFurigana.md +1 -1
  21. package/docs/api/functions/createEntryMaps.md +9 -3
  22. package/docs/api/functions/generateAnkiNote.md +2 -2
  23. package/docs/api/functions/generateAnkiNotesFile.md +1 -1
  24. package/docs/api/functions/generateFurigana.md +1 -1
  25. package/docs/api/functions/getKanji.md +1 -1
  26. package/docs/api/functions/getKanjiExtended.md +1 -1
  27. package/docs/api/functions/getName.md +57 -0
  28. package/docs/api/functions/getValidForms.md +1 -1
  29. package/docs/api/functions/getWord.md +3 -3
  30. package/docs/api/functions/getWordDefinitions.md +1 -1
  31. package/docs/api/functions/getWordDefinitionsWithFurigana.md +1 -1
  32. package/docs/api/functions/hiraganaToKatakana.md +1 -1
  33. package/docs/api/functions/isObjectArray.md +1 -1
  34. package/docs/api/functions/isStringArray.md +1 -1
  35. package/docs/api/functions/isValidArrayWithFirstElement.md +1 -1
  36. package/docs/api/functions/katakanaToHiragana.md +1 -1
  37. package/docs/api/functions/shuffleArray.md +1 -1
  38. package/docs/api/interfaces/DefaultNoteInfo.md +10 -10
  39. package/docs/api/interfaces/Definition.md +4 -4
  40. package/docs/api/interfaces/DictKanji.md +5 -5
  41. package/docs/api/interfaces/DictKanjiForm.md +2 -2
  42. package/docs/api/interfaces/DictKanjiMisc.md +5 -5
  43. package/docs/api/interfaces/DictKanjiReading.md +3 -3
  44. package/docs/api/interfaces/DictKanjiReadingMeaning.md +3 -3
  45. package/docs/api/interfaces/DictKanjiReadingMeaningGroup.md +3 -3
  46. package/docs/api/interfaces/DictKanjiWithRadicals.md +3 -3
  47. package/docs/api/interfaces/DictName.md +75 -0
  48. package/docs/api/interfaces/DictRadical.md +4 -4
  49. package/docs/api/interfaces/DictReading.md +2 -2
  50. package/docs/api/interfaces/EntryMaps.md +33 -9
  51. package/docs/api/interfaces/ExamplePart.md +7 -7
  52. package/docs/api/interfaces/GlossSpecificNumber.md +3 -3
  53. package/docs/api/interfaces/Grammar.md +15 -15
  54. package/docs/api/interfaces/GrammarMeaning.md +3 -3
  55. package/docs/api/interfaces/JaWiktionaryEntry.md +5 -5
  56. package/docs/api/interfaces/Kana.md +11 -11
  57. package/docs/api/interfaces/Kanji.md +23 -23
  58. package/docs/api/interfaces/KanjiComponent.md +3 -3
  59. package/docs/api/interfaces/KanjiForm.md +5 -5
  60. package/docs/api/interfaces/Name.md +163 -0
  61. package/docs/api/interfaces/NeDictMeaning.md +33 -0
  62. package/docs/api/interfaces/NoteAndTag.md +3 -3
  63. package/docs/api/interfaces/NoteHeaderKeys.md +7 -7
  64. package/docs/api/interfaces/Phrase.md +5 -5
  65. package/docs/api/interfaces/Radical.md +16 -16
  66. package/docs/api/interfaces/Reading.md +6 -6
  67. package/docs/api/interfaces/ResultEntry.md +8 -7
  68. package/docs/api/interfaces/TanakaExample.md +7 -7
  69. package/docs/api/interfaces/Translation.md +5 -5
  70. package/docs/api/interfaces/UsefulRegExps.md +8 -8
  71. package/docs/api/interfaces/Word.md +15 -15
  72. package/docs/api/interfaces/WordDefinitionPair.md +4 -4
  73. package/docs/api/type-aliases/Dict.md +1 -1
  74. package/docs/api/type-aliases/{DictName.md → DictNames.md} +3 -3
  75. package/docs/api/type-aliases/EntryExamplesMap.md +13 -0
  76. package/docs/api/type-aliases/EntryType.md +2 -2
  77. package/docs/api/type-aliases/KanjiEntryMap.md +1 -1
  78. package/docs/api/type-aliases/KanjiSVGMap.md +1 -1
  79. package/docs/api/type-aliases/KanjiWordsMap.md +1 -1
  80. package/docs/api/type-aliases/NameIDEntryMap.md +13 -0
  81. package/docs/api/type-aliases/Result.md +2 -2
  82. package/docs/api/type-aliases/WordDefinitionsMap.md +1 -1
  83. package/docs/api/type-aliases/WordIDEntryMap.md +1 -1
  84. package/package.json +8 -7
  85. package/src/types.ts +115 -15
  86. package/src/utils.ts +733 -162
  87. package/docs/api/type-aliases/WordExamplesMap.md +0 -13
package/README.md CHANGED
@@ -33,7 +33,7 @@ pnpm add henkan
33
33
  ```
34
34
 
35
35
  # Features
36
- - JMdict, KANJIDIC, Tanaka Corpus, RADK and KRAD conversion
36
+ - JMdict, JMnedict, KANJIDIC, Tanaka Corpus, RADK and KRAD conversion
37
37
  - User-friendly schemas for dictionary entries
38
38
  - Anki note generation
39
39
  - "Japanese definition"-"JMdict entry" pairing (using `ja.wiktionary.org` dumps)
package/dist/index.cjs.js CHANGED
@@ -32,6 +32,7 @@ var index_exports = {};
32
32
  __export(index_exports, {
33
33
  capitalizeString: () => capitalizeString,
34
34
  convertJMdict: () => convertJMdict,
35
+ convertJMnedict: () => convertJMnedict,
35
36
  convertJawiktionaryAsync: () => convertJawiktionaryAsync,
36
37
  convertJawiktionarySync: () => convertJawiktionarySync,
37
38
  convertKanjiDic: () => convertKanjiDic,
@@ -45,6 +46,7 @@ __export(index_exports, {
45
46
  generateFurigana: () => generateFurigana,
46
47
  getKanji: () => getKanji,
47
48
  getKanjiExtended: () => getKanjiExtended,
49
+ getName: () => getName,
48
50
  getValidForms: () => getValidForms,
49
51
  getWord: () => getWord,
50
52
  getWordDefinitions: () => getWordDefinitions,
@@ -53,6 +55,7 @@ __export(index_exports, {
53
55
  isGrammar: () => isGrammar,
54
56
  isKana: () => isKana,
55
57
  isKanji: () => isKanji,
58
+ isName: () => isName,
56
59
  isObjectArray: () => isObjectArray,
57
60
  isRadical: () => isRadical,
58
61
  isStringArray: () => isStringArray,
@@ -1427,7 +1430,6 @@ function convertJMdict(xmlString, examples) {
1427
1430
  (example) => example.parts.flatMap((part) => [
1428
1431
  part.baseForm,
1429
1432
  ...part.reading !== void 0 ? [part.reading] : [],
1430
- ...part.inflectedForm !== void 0 ? [part.inflectedForm] : [],
1431
1433
  ...part.referenceID !== void 0 ? [part.referenceID] : []
1432
1434
  ])
1433
1435
  )
@@ -1539,6 +1541,89 @@ function convertJMdict(xmlString, examples) {
1539
1541
  });
1540
1542
  return dict;
1541
1543
  }
1544
+ function convertJMnedict(xmlString, examples) {
1545
+ const dictParsed = import_libxmljs2.default.parseXml(xmlString, {
1546
+ dtdvalid: true,
1547
+ nonet: false,
1548
+ noent: true,
1549
+ recover: false
1550
+ });
1551
+ const dict = [];
1552
+ import_xml2js.default.parseString(dictParsed, (_err, result) => {
1553
+ const tanakaParts = examples !== void 0 && examples.length > 0 ? new Set(
1554
+ examples.flatMap(
1555
+ (example) => example.parts.flatMap((part) => [
1556
+ part.baseForm,
1557
+ ...part.reading !== void 0 ? [part.reading] : [],
1558
+ ...part.referenceID !== void 0 ? [part.referenceID] : []
1559
+ ])
1560
+ )
1561
+ ) : void 0;
1562
+ for (const entry of result.JMnedict.entry) {
1563
+ const entryObj = {
1564
+ id: entry.ent_seq[0],
1565
+ nameReadings: [],
1566
+ meanings: []
1567
+ };
1568
+ const kanjiForms = entry.k_ele;
1569
+ const readings = entry.r_ele;
1570
+ const translations = entry.trans;
1571
+ if (isObjectArray(kanjiForms)) {
1572
+ entryObj.kanjiForms = [];
1573
+ for (const kanjiForm of kanjiForms)
1574
+ entryObj.kanjiForms.push({ form: kanjiForm.keb[0] });
1575
+ }
1576
+ for (const reading of readings) {
1577
+ const readingObj = {
1578
+ reading: reading.reb[0]
1579
+ };
1580
+ if (isStringArray(reading.re_restr))
1581
+ readingObj.kanjiFormRestrictions = reading.re_restr;
1582
+ if (isStringArray(reading.re_pri)) {
1583
+ readingObj.commonness = reading.re_pri;
1584
+ entryObj.isCommon = true;
1585
+ }
1586
+ entryObj.nameReadings.push(readingObj);
1587
+ }
1588
+ for (const trans of translations)
1589
+ entryObj.meanings.push({
1590
+ translations: trans.trans_det,
1591
+ ...isStringArray(trans.name_type) ? { nameTypes: trans.name_type } : {}
1592
+ });
1593
+ if (examples !== void 0) {
1594
+ let existsExample = false;
1595
+ const rkf = getValidForms(
1596
+ entryObj.nameReadings,
1597
+ entryObj.kanjiForms,
1598
+ entryObj.isCommon
1599
+ );
1600
+ const validReadings = new Set(
1601
+ rkf.readings.map((r) => r.reading)
1602
+ );
1603
+ const validKanjiForms = rkf.kanjiForms !== void 0 ? new Set(
1604
+ rkf.kanjiForms.map((kf) => kf.form)
1605
+ ) : void 0;
1606
+ if (validKanjiForms !== void 0 && validKanjiForms.size > 0 && tanakaParts !== void 0) {
1607
+ for (const kf of validKanjiForms)
1608
+ if (tanakaParts.has(kf)) {
1609
+ existsExample = true;
1610
+ break;
1611
+ }
1612
+ }
1613
+ if (entryObj.kanjiForms === void 0 && validReadings.size > 0 && tanakaParts !== void 0) {
1614
+ for (const r of validReadings)
1615
+ if (tanakaParts.has(r)) {
1616
+ existsExample = true;
1617
+ break;
1618
+ }
1619
+ }
1620
+ if (existsExample) entryObj.hasPhrases = true;
1621
+ }
1622
+ dict.push(entryObj);
1623
+ }
1624
+ });
1625
+ return dict;
1626
+ }
1542
1627
  function convertKanjiDic(xmlString) {
1543
1628
  const dictParsed = import_libxmljs2.default.parseXml(xmlString, {
1544
1629
  dtdvalid: true,
@@ -1741,16 +1826,15 @@ function convertKradFile(kradBuffer, kanjiDic, katakanaList) {
1741
1826
  }
1742
1827
  return kanjiWithRadicals;
1743
1828
  }
1744
- function createEntryMaps(jmDict, kanjiDic, tanakaExamples, wordDefinitionPairs, svgList) {
1829
+ function createEntryMaps(jmDict, jmNedict, kanjiDic, tanakaExamples, wordDefinitionPairs, svgList) {
1745
1830
  const kanjiEntryMap = /* @__PURE__ */ new Map();
1746
1831
  const wordIDEntryMap = /* @__PURE__ */ new Map();
1832
+ const nameIDEntryMap = /* @__PURE__ */ new Map();
1747
1833
  const kanjiWordsMap = /* @__PURE__ */ new Map();
1748
1834
  const wordExamplesMap = /* @__PURE__ */ new Map();
1835
+ const nameExamplesMap = /* @__PURE__ */ new Map();
1749
1836
  const wordDefinitionsMap = /* @__PURE__ */ new Map();
1750
1837
  const kanjiSVGMap = /* @__PURE__ */ new Map();
1751
- const wordPartsMap = /* @__PURE__ */ new Map();
1752
- const partExamplesMap = /* @__PURE__ */ new Map();
1753
- const entryParts = /* @__PURE__ */ new Set();
1754
1838
  if (kanjiDic !== void 0)
1755
1839
  for (const kanji of kanjiDic) kanjiEntryMap.set(kanji.kanji, kanji);
1756
1840
  if (wordDefinitionPairs !== void 0)
@@ -1766,6 +1850,9 @@ function createEntryMaps(jmDict, kanjiDic, tanakaExamples, wordDefinitionPairs,
1766
1850
  if (svg !== void 0) kanjiSVGMap.set(kanji.kanji, svg);
1767
1851
  }
1768
1852
  if (jmDict !== void 0) {
1853
+ const wordPartsMap = /* @__PURE__ */ new Map();
1854
+ const partExamplesMap = /* @__PURE__ */ new Map();
1855
+ const entryParts = /* @__PURE__ */ new Set();
1769
1856
  for (const word of jmDict) {
1770
1857
  wordIDEntryMap.set(word.id, word);
1771
1858
  if (word.kanjiForms !== void 0)
@@ -1811,14 +1898,6 @@ function createEntryMaps(jmDict, kanjiDic, tanakaExamples, wordDefinitionPairs,
1811
1898
  if (exList === void 0) partExamplesMap.set(part.reading, [ex]);
1812
1899
  else exList.push(ex);
1813
1900
  }
1814
- if (part.inflectedForm !== void 0 && entryParts.has(part.inflectedForm)) {
1815
- const exList = partExamplesMap.get(
1816
- part.inflectedForm
1817
- );
1818
- if (exList === void 0)
1819
- partExamplesMap.set(part.inflectedForm, [ex]);
1820
- else exList.push(ex);
1821
- }
1822
1901
  if (part.referenceID !== void 0 && entryParts.has(part.referenceID)) {
1823
1902
  const exList = partExamplesMap.get(
1824
1903
  part.referenceID
@@ -1844,11 +1923,74 @@ function createEntryMaps(jmDict, kanjiDic, tanakaExamples, wordDefinitionPairs,
1844
1923
  }
1845
1924
  }
1846
1925
  }
1926
+ if (jmNedict !== void 0) {
1927
+ const namePartsMap = /* @__PURE__ */ new Map();
1928
+ const partExamplesMap = /* @__PURE__ */ new Map();
1929
+ const entryParts = /* @__PURE__ */ new Set();
1930
+ for (const name of jmNedict) {
1931
+ nameIDEntryMap.set(name.id, name);
1932
+ if (tanakaExamples !== void 0) {
1933
+ const rkf = getValidForms(
1934
+ name.nameReadings,
1935
+ name.kanjiForms,
1936
+ name.isCommon
1937
+ );
1938
+ const localPartParts = /* @__PURE__ */ new Set();
1939
+ for (const reading of rkf.readings) {
1940
+ entryParts.add(reading.reading);
1941
+ localPartParts.add(reading.reading);
1942
+ }
1943
+ if (rkf.kanjiForms !== void 0 && rkf.kanjiForms.length > 0)
1944
+ for (const kanjiForm of rkf.kanjiForms) {
1945
+ entryParts.add(kanjiForm.form);
1946
+ localPartParts.add(kanjiForm.form);
1947
+ }
1948
+ entryParts.add(name.id);
1949
+ localPartParts.add(name.id);
1950
+ namePartsMap.set(name.id, localPartParts);
1951
+ }
1952
+ }
1953
+ if (tanakaExamples !== void 0) {
1954
+ for (const ex of tanakaExamples)
1955
+ for (const part of ex.parts) {
1956
+ if (entryParts.has(part.baseForm)) {
1957
+ const exList = partExamplesMap.get(
1958
+ part.baseForm
1959
+ );
1960
+ if (exList === void 0) partExamplesMap.set(part.baseForm, [ex]);
1961
+ else exList.push(ex);
1962
+ }
1963
+ if (part.reading !== void 0 && entryParts.has(part.reading)) {
1964
+ const exList = partExamplesMap.get(
1965
+ part.reading
1966
+ );
1967
+ if (exList === void 0) partExamplesMap.set(part.reading, [ex]);
1968
+ else exList.push(ex);
1969
+ }
1970
+ }
1971
+ for (const name of jmNedict) {
1972
+ const seenEx = /* @__PURE__ */ new Set();
1973
+ const validExamples = [];
1974
+ for (const p of namePartsMap.get(name.id)) {
1975
+ const examplesForPart = partExamplesMap.get(p)?.filter((ex) => !seenEx.has(ex.id));
1976
+ if (examplesForPart === void 0) continue;
1977
+ for (const ex of examplesForPart) {
1978
+ seenEx.add(ex.id);
1979
+ validExamples.push(ex);
1980
+ }
1981
+ }
1982
+ if (validExamples.length > 0)
1983
+ nameExamplesMap.set(name.id, validExamples);
1984
+ }
1985
+ }
1986
+ }
1847
1987
  return {
1848
1988
  ...wordIDEntryMap.size > 0 ? { wordIDEntryMap } : {},
1989
+ ...nameIDEntryMap.size > 0 ? { nameIDEntryMap } : {},
1849
1990
  ...kanjiWordsMap.size > 0 ? { kanjiWordsMap } : {},
1850
1991
  ...kanjiEntryMap.size > 0 ? { kanjiEntryMap } : {},
1851
1992
  ...wordExamplesMap.size > 0 ? { wordExamplesMap } : {},
1993
+ ...nameExamplesMap.size > 0 ? { nameExamplesMap } : {},
1852
1994
  ...wordDefinitionsMap.size > 0 ? { wordDefinitionsMap } : {},
1853
1995
  ...kanjiSVGMap.size > 0 ? { kanjiSVGMap } : {}
1854
1996
  };
@@ -2625,43 +2767,45 @@ function getWord(searchedWord, dict, kanjiDic, examples, definitions, noteTypeNa
2625
2767
  rkf.readings.map((r) => r.reading)
2626
2768
  );
2627
2769
  const kanjiForms = rkf.kanjiForms !== void 0 ? new Set(rkf.kanjiForms.map((kf) => kf.form)) : void 0;
2628
- let readingMatchingKanjiFormExamples = [];
2770
+ const readingMatchingKanjiFormExamples = [];
2629
2771
  let kanjiFormExamples = [];
2630
2772
  let readingExamples = [];
2631
- let hasReadingMatchingKanjiFormWithTranslation = false;
2773
+ let hasKanjiFormExamplesWithTranslation = false;
2774
+ let hasReadingExamplesWithTranslation = false;
2632
2775
  for (const example of exampleList)
2633
2776
  for (let i = 0; i < example.parts.length; i++) {
2634
2777
  if (seenPhrases.has(example.phrase)) break;
2635
- const includesTranslation = meanings.some(
2636
- (m) => example.translation.includes(m)
2637
- );
2638
2778
  const part = example.parts[i];
2639
2779
  const readingAsReadingMatch = part.reading !== void 0 && readings.has(part.reading);
2640
- const readingAsInflectedFormMatch = part.inflectedForm !== void 0 && readings.has(part.inflectedForm);
2641
2780
  const referenceIDMatch = part.referenceID === dictWord.id;
2642
2781
  if (kanjiForms !== void 0 && kanjiForms.has(part.baseForm)) {
2643
- if (readingAsReadingMatch || readingAsInflectedFormMatch || referenceIDMatch) {
2782
+ if (readingAsReadingMatch || referenceIDMatch)
2644
2783
  readingMatchingKanjiFormExamples.push({
2645
2784
  ex: example,
2646
- partIndex: i,
2647
- form: part.baseForm,
2648
- ...referenceIDMatch ? { referenceIDMatch: true } : {},
2649
- ...includesTranslation ? { includesTranslation: true } : {}
2785
+ partIndex: i
2650
2786
  });
2651
- if (!hasReadingMatchingKanjiFormWithTranslation && includesTranslation)
2652
- hasReadingMatchingKanjiFormWithTranslation = true;
2653
- } else
2787
+ else {
2788
+ const includesTranslation = meanings.some(
2789
+ (m) => example.translation.includes(m)
2790
+ );
2791
+ if (!hasKanjiFormExamplesWithTranslation && includesTranslation)
2792
+ hasKanjiFormExamplesWithTranslation = true;
2654
2793
  kanjiFormExamples.push({
2655
2794
  ex: example,
2656
2795
  partIndex: i,
2657
- form: part.baseForm,
2658
2796
  ...includesTranslation ? { includesTranslation: true } : {}
2659
2797
  });
2798
+ }
2660
2799
  seenPhrases.add(example.phrase);
2661
2800
  break;
2662
2801
  }
2663
2802
  const readingAsBaseFormMatch = readings.has(part.baseForm);
2664
2803
  if ((readingAsBaseFormMatch || referenceIDMatch) && kanjiForms === void 0) {
2804
+ const includesTranslation = meanings.some(
2805
+ (m) => example.translation.includes(m)
2806
+ );
2807
+ if (!hasReadingExamplesWithTranslation && includesTranslation)
2808
+ hasReadingExamplesWithTranslation = true;
2665
2809
  readingExamples.push({
2666
2810
  ex: example,
2667
2811
  partIndex: i,
@@ -2672,26 +2816,13 @@ function getWord(searchedWord, dict, kanjiDic, examples, definitions, noteTypeNa
2672
2816
  break;
2673
2817
  }
2674
2818
  }
2675
- if (readingMatchingKanjiFormExamples.length > 0) {
2676
- if (hasReadingMatchingKanjiFormWithTranslation)
2677
- readingMatchingKanjiFormExamples = readingMatchingKanjiFormExamples.filter(
2678
- (ex) => ex.includesTranslation === true || ex.referenceIDMatch === true || ex.ex.parts.some(
2679
- (part) => ex.form === part.baseForm && part.glossNumber !== void 0
2680
- )
2681
- );
2682
- kanjiFormExamples.length = 0;
2683
- }
2684
- if (kanjiFormExamples.length > 0 && kanjiFormExamples.some(
2685
- (ex) => ex.includesTranslation === true
2686
- ))
2819
+ if (kanjiFormExamples.length > 0 && hasKanjiFormExamplesWithTranslation)
2687
2820
  kanjiFormExamples = kanjiFormExamples.filter(
2688
- (ex) => ex.includesTranslation === true || ex.ex.parts.some(
2689
- (part) => ex.form === part.baseForm && part.glossNumber !== void 0
2690
- )
2821
+ (ex) => ex.includesTranslation === true
2691
2822
  );
2692
- if (readingExamples.length > 0 && readingExamples.some(
2693
- (ex) => ex.includesTranslation === true || ex.referenceIDMatch === true
2694
- ))
2823
+ else if (kanjiFormExamples.length > 0 && readingMatchingKanjiFormExamples.length > 0)
2824
+ kanjiFormExamples.length = 0;
2825
+ if (readingExamples.length > 0 && hasReadingExamplesWithTranslation)
2695
2826
  readingExamples = readingExamples.filter(
2696
2827
  (ex) => ex.includesTranslation === true || ex.referenceIDMatch === true
2697
2828
  );
@@ -2757,9 +2888,182 @@ function getWord(searchedWord, dict, kanjiDic, examples, definitions, noteTypeNa
2757
2888
  return word;
2758
2889
  } else return void 0;
2759
2890
  }
2891
+ function getName(searchedName, dict, kanjiDic, examples, noteTypeName, deckPath) {
2892
+ let dictName = void 0;
2893
+ if (typeof searchedName === "string" && dict !== void 0) {
2894
+ if (Array.isArray(dict))
2895
+ dictName = dict.find(
2896
+ (entry) => entry.id === searchedName
2897
+ );
2898
+ if (dict instanceof Map) dictName = dict.get(searchedName);
2899
+ }
2900
+ if (typeof searchedName === "object") dictName = searchedName;
2901
+ if (dictName !== void 0) {
2902
+ const name = {
2903
+ id: dictName.id,
2904
+ nameReadings: [],
2905
+ translations: [],
2906
+ noteID: `name_${dictName.id}`,
2907
+ noteTypeName,
2908
+ deckPath,
2909
+ tags: []
2910
+ };
2911
+ if (dictName.isCommon === true) {
2912
+ name.common = true;
2913
+ name.tags.push("name::common");
2914
+ }
2915
+ if (dictName.kanjiForms !== void 0)
2916
+ name.kanjiForms = dictName.kanjiForms.map(
2917
+ (dictKanjiForm) => ({
2918
+ kanjiForm: dictKanjiForm.form
2919
+ })
2920
+ );
2921
+ name.nameReadings = dictName.nameReadings.map(
2922
+ (dictReading) => ({
2923
+ reading: dictReading.reading,
2924
+ ...dictReading.kanjiFormRestrictions !== void 0 ? {
2925
+ notes: dictReading.kanjiFormRestrictions.map(
2926
+ (restriction) => `Reading restricted to ${restriction}`
2927
+ )
2928
+ } : {},
2929
+ ...dictReading.commonness !== void 0 && dictReading.commonness.length > 0 ? { common: true } : {}
2930
+ })
2931
+ );
2932
+ name.translations = [];
2933
+ const meanings = dictName.hasPhrases === true && examples !== void 0 ? [] : void 0;
2934
+ const seenPhrases = /* @__PURE__ */ new Set();
2935
+ let hasNameTypes = false;
2936
+ for (const dictMeaning of dictName.meanings) {
2937
+ if (!hasNameTypes && dictMeaning.nameTypes !== void 0)
2938
+ hasNameTypes = true;
2939
+ name.translations.push({
2940
+ translation: dictMeaning.translations.map((translation) => {
2941
+ if (meanings !== void 0) {
2942
+ const cleanTranslation = translation.replaceAll(/\([^)]*\)|\[[^\]]*\]|\{[^}]*\}/g, "").trim();
2943
+ if (!seenPhrases.has(cleanTranslation)) {
2944
+ seenPhrases.add(cleanTranslation);
2945
+ meanings.push(cleanTranslation);
2946
+ }
2947
+ }
2948
+ return translation;
2949
+ }).join("; "),
2950
+ ...dictMeaning.nameTypes !== void 0 ? {
2951
+ notes: dictMeaning.nameTypes.map((type) => {
2952
+ const noteAndTag = lookupWordNote(
2953
+ type,
2954
+ [],
2955
+ name.tags
2956
+ );
2957
+ return capitalizeString(noteAndTag.note);
2958
+ })
2959
+ } : {}
2960
+ });
2961
+ }
2962
+ if (!hasNameTypes) name.tags.push("name::no_name_types");
2963
+ seenPhrases.clear();
2964
+ if (kanjiDic !== void 0 && name.kanjiForms !== void 0) {
2965
+ const kanji = [];
2966
+ const seenChars = /* @__PURE__ */ new Set();
2967
+ for (const kanjiForm of name.kanjiForms)
2968
+ for (const char of kanjiForm.kanjiForm.split("").filter((c) => regexps.kanji.test(c))) {
2969
+ if (seenChars.has(char)) continue;
2970
+ seenChars.add(char);
2971
+ const kanjiEntry = kanjiDic instanceof Map ? kanjiDic.get(char) : void 0;
2972
+ const kanjiObj = getKanji(
2973
+ kanjiEntry ?? char,
2974
+ !(kanjiDic instanceof Map) ? kanjiDic : void 0
2975
+ );
2976
+ if (kanjiObj !== void 0)
2977
+ kanji.push({
2978
+ kanji: kanjiObj.kanji,
2979
+ ...kanjiObj.meanings !== void 0 && kanjiObj.meanings.length > 0 ? { meanings: kanjiObj.meanings } : {}
2980
+ });
2981
+ }
2982
+ if (kanji.length > 0) name.kanji = kanji;
2983
+ }
2984
+ if (meanings !== void 0) {
2985
+ const exampleList = examples instanceof Map ? examples.get(dictName.id) ?? [] : examples;
2986
+ const rkf = getValidForms(
2987
+ dictName.nameReadings,
2988
+ dictName.kanjiForms,
2989
+ dictName.isCommon
2990
+ );
2991
+ const readings = new Set(
2992
+ rkf.readings.map((r) => r.reading)
2993
+ );
2994
+ const kanjiForms = rkf.kanjiForms !== void 0 ? new Set(rkf.kanjiForms.map((kf) => kf.form)) : void 0;
2995
+ let readingMatchingKanjiFormExamples = [];
2996
+ let readingExamples = [];
2997
+ let hasReadingMatchingKanjiFormWithTranslation = false;
2998
+ let hasReadingWithTranslation = false;
2999
+ for (const example of exampleList)
3000
+ for (let i = 0; i < example.parts.length; i++) {
3001
+ if (seenPhrases.has(example.phrase)) break;
3002
+ const part = example.parts[i];
3003
+ const readingAsReadingMatch = part.reading !== void 0 && readings.has(part.reading);
3004
+ if (kanjiForms !== void 0 && kanjiForms.has(part.baseForm) && readingAsReadingMatch) {
3005
+ const includesTranslation = meanings.some(
3006
+ (m) => example.translation.includes(m)
3007
+ );
3008
+ if (!hasReadingMatchingKanjiFormWithTranslation && includesTranslation)
3009
+ hasReadingMatchingKanjiFormWithTranslation = true;
3010
+ readingMatchingKanjiFormExamples.push({
3011
+ ex: example,
3012
+ ...includesTranslation ? { includesTranslation: true } : {}
3013
+ });
3014
+ seenPhrases.add(example.phrase);
3015
+ break;
3016
+ }
3017
+ const readingAsBaseFormMatch = readings.has(part.baseForm);
3018
+ if (readingAsBaseFormMatch && kanjiForms === void 0) {
3019
+ const includesTranslation = meanings.some(
3020
+ (m) => example.translation.includes(m)
3021
+ );
3022
+ if (!hasReadingWithTranslation && includesTranslation)
3023
+ hasReadingWithTranslation = true;
3024
+ readingExamples.push({
3025
+ ex: example,
3026
+ ...includesTranslation ? { includesTranslation: true } : {}
3027
+ });
3028
+ seenPhrases.add(example.phrase);
3029
+ break;
3030
+ }
3031
+ }
3032
+ if (readingMatchingKanjiFormExamples.length > 0) {
3033
+ if (hasReadingMatchingKanjiFormWithTranslation)
3034
+ readingMatchingKanjiFormExamples = readingMatchingKanjiFormExamples.filter(
3035
+ (ex) => ex.includesTranslation === true
3036
+ );
3037
+ }
3038
+ if (readingExamples.length > 0 && hasReadingWithTranslation)
3039
+ readingExamples = readingExamples.filter(
3040
+ (ex) => ex.includesTranslation === true
3041
+ );
3042
+ const wordExamples = [
3043
+ ...name.kanjiForms !== void 0 ? readingMatchingKanjiFormExamples : readingExamples
3044
+ ];
3045
+ if (wordExamples.length > 0) {
3046
+ name.phrases = wordExamples.slice(0, 5).map(
3047
+ (ex) => ({
3048
+ phrase: ex.ex.furigana ?? ex.ex.phrase,
3049
+ translation: ex.ex.translation,
3050
+ originalPhrase: ex.ex.phrase
3051
+ })
3052
+ );
3053
+ name.tags.push("name::has_phrases");
3054
+ }
3055
+ }
3056
+ return name;
3057
+ } else return void 0;
3058
+ }
2760
3059
  function isWord(entry) {
2761
3060
  return isObjectArray(Object.getOwnPropertyDescriptor(entry, "readings")?.value) && isObjectArray(Object.getOwnPropertyDescriptor(entry, "translations")?.value);
2762
3061
  }
3062
+ function isName(entry) {
3063
+ return isObjectArray(
3064
+ Object.getOwnPropertyDescriptor(entry, "nameReadings")?.value
3065
+ ) && isObjectArray(Object.getOwnPropertyDescriptor(entry, "translations")?.value);
3066
+ }
2763
3067
  function isRadical(entry) {
2764
3068
  return typeof Object.getOwnPropertyDescriptor(entry, "radical")?.value === "string";
2765
3069
  }
@@ -2897,6 +3201,92 @@ function generateAnkiNote(entry, customData, additionalTags) {
2897
3201
  searchField
2898
3202
  );
2899
3203
  }
3204
+ if (isName(entry)) {
3205
+ const firstReading = createEntry(
3206
+ `<span class="name name-reading">${entry.nameReadings[0].reading}${entry.nameReadings[0].audio !== void 0 ? `<br>[sound:${entry.nameReadings[0].audio}]` : ""}</span>`,
3207
+ entry.nameReadings[0].notes
3208
+ );
3209
+ const otherReadings = entry.nameReadings.length > 1 ? `<details><summary>Show other readings</summary>${entry.nameReadings.slice(1).map(
3210
+ (readingEntry) => createEntry(
3211
+ `<span class="name name-reading">${readingEntry.reading}${readingEntry.audio !== void 0 ? `<br>[sound:${readingEntry.audio}]` : ""}</span>`,
3212
+ readingEntry.notes
3213
+ )
3214
+ ).join("")}</details>` : "";
3215
+ const readingsField = `${firstReading}${otherReadings}`;
3216
+ let readingsFieldWithoutAudio = '<div id="no-r-audio" style="display: none"></div>';
3217
+ let hasAudio = false;
3218
+ if (entry.nameReadings.some((r) => r.audio !== void 0)) {
3219
+ const firstReadingWithoutAudio = createEntry(
3220
+ `<span class="name name-reading">${entry.nameReadings[0].reading}</span>`,
3221
+ entry.nameReadings[0].notes
3222
+ );
3223
+ const otherReadingsWithoutAudio = entry.nameReadings.length > 1 ? `<details><summary>Show other readings</summary>${entry.nameReadings.slice(1).map(
3224
+ (readingEntry) => createEntry(
3225
+ `<span class="name name-reading">${readingEntry.reading}</span>`,
3226
+ readingEntry.notes
3227
+ )
3228
+ ).join("")}</details>` : "";
3229
+ readingsFieldWithoutAudio = `${firstReadingWithoutAudio}${otherReadingsWithoutAudio}`;
3230
+ hasAudio = true;
3231
+ }
3232
+ const firstKanjiForm = entry.kanjiForms !== void 0 ? createEntry(
3233
+ `<span class="name name-kanjiform"><ruby><rb>${entry.kanjiForms[0].kanjiForm}</rb><rt>${entry.nameReadings[0].reading}</rt></ruby></span>`,
3234
+ entry.kanjiForms[0].notes
3235
+ ) : void 0;
3236
+ const otherKanjiForms = entry.kanjiForms !== void 0 && entry.kanjiForms.length > 1 ? `<details><summary>Show other kanji forms</summary>${entry.kanjiForms.slice(1).map((kanjiFormEntry) => {
3237
+ const restrictedReading = entry.nameReadings.find(
3238
+ (r) => r.notes !== void 0 && r.notes.includes(
3239
+ `Reading restricted to ${kanjiFormEntry.kanjiForm}`
3240
+ )
3241
+ );
3242
+ return createEntry(
3243
+ `<span class="name name-kanjiform">${restrictedReading !== void 0 ? "<ruby><rb>" : ""}${kanjiFormEntry.kanjiForm}${restrictedReading !== void 0 ? `</rb><rt>${restrictedReading.reading}</rt></ruby>` : ""}</span>`,
3244
+ kanjiFormEntry.notes
3245
+ );
3246
+ }).join("")}</details>` : "";
3247
+ const kanjiFormsField = firstKanjiForm !== void 0 ? `${firstKanjiForm}${otherKanjiForms}` : '<span class="name name-kanjiform" id="no-kanjiforms">(no kanji forms)</span>';
3248
+ const firstThreeTranslations = entry.translations.slice(0, 3).map(
3249
+ (translationEntry) => createEntry(
3250
+ `<span class="name name-translation">${translationEntry.translation}</span>`,
3251
+ translationEntry.notes
3252
+ )
3253
+ ).join("");
3254
+ const otherTranslations = entry.translations.length > 3 ? `<details><summary>Show other translations</summary>${entry.translations.map((translationEntry, index) => {
3255
+ if (index < 3) return "null";
3256
+ return createEntry(
3257
+ `<span class="name name-translation">${translationEntry.translation}</span>`,
3258
+ translationEntry.notes
3259
+ );
3260
+ }).filter((translation) => translation !== "null").join("")}</details>` : "";
3261
+ const translationsField = `${firstThreeTranslations}${otherTranslations}`;
3262
+ const phrasesField = entry.phrases !== void 0 ? entry.phrases.map(
3263
+ (phraseEntry) => createEntry(
3264
+ `<span class="name name-phrase"><span class="name name-phrase-original">${phraseEntry.originalPhrase}</span><span class="name name-phrase-furigana">${phraseEntry.phrase}</span></span>`,
3265
+ [phraseEntry.translation],
3266
+ true
3267
+ )
3268
+ ).join("") : '<span class="name name-phrase" id="no-phrases">(no phrases)</span>';
3269
+ const searchField = `${entry.nameReadings.map((r) => r.reading).join(" ")}${entry.kanjiForms !== void 0 ? ` ${entry.kanjiForms.map((kf) => kf.kanjiForm).join(" ")}` : ""} ${entry.id}`;
3270
+ fields.push(
3271
+ ...entry.kanjiForms !== void 0 ? [
3272
+ `${customData !== void 0 ? `<div id="custom-data" style="display: none" data-custom="${customData}"></div>` : ""}${kanjiFormsField}<div id="kf-pos" style="display: none" data-pos="1"></div>`,
3273
+ `${hasAudio ? readingsFieldWithoutAudio : readingsField}<div id="r-pos" style="display: none" data-pos="2"></div>`
3274
+ ] : [
3275
+ `${customData !== void 0 ? `<div id="custom-data" style="display: none" data-custom="${customData}"></div>` : ""}${kanjiFormsField}<div id="kf-pos" style="display: none" data-pos="2"></div>`,
3276
+ `${hasAudio ? readingsFieldWithoutAudio : readingsField}<div id="r-pos" style="display: none" data-pos="1"></div>`
3277
+ ],
3278
+ `${hasAudio ? readingsField : readingsFieldWithoutAudio}<div id="r-pos" style="display: none" data-pos="${entry.kanjiForms !== void 0 ? "2" : "1"}"></div>`,
3279
+ translationsField,
3280
+ phrasesField,
3281
+ entry.kanji !== void 0 ? entry.kanji.map(
3282
+ (kanjiEntry) => createEntry(
3283
+ `<span class="name name-kanji">${kanjiEntry.kanji}${kanjiEntry.meanings === void 0 ? " (no meanings)" : ""}</span>`,
3284
+ kanjiEntry.meanings
3285
+ )
3286
+ ).join("") : '<span class="name name-kanji" id="no-kanji">(no kanji)</span>',
3287
+ searchField
3288
+ );
3289
+ }
2900
3290
  if (isRadical(entry))
2901
3291
  fields.push(
2902
3292
  `${customData !== void 0 ? `<div id="custom-data" style="display: none" data-custom="${customData}"></div>` : ""}${createEntry(
@@ -3075,6 +3465,7 @@ ${ankiNotes}`;
3075
3465
  0 && (module.exports = {
3076
3466
  capitalizeString,
3077
3467
  convertJMdict,
3468
+ convertJMnedict,
3078
3469
  convertJawiktionaryAsync,
3079
3470
  convertJawiktionarySync,
3080
3471
  convertKanjiDic,
@@ -3088,6 +3479,7 @@ ${ankiNotes}`;
3088
3479
  generateFurigana,
3089
3480
  getKanji,
3090
3481
  getKanjiExtended,
3482
+ getName,
3091
3483
  getValidForms,
3092
3484
  getWord,
3093
3485
  getWordDefinitions,
@@ -3096,6 +3488,7 @@ ${ankiNotes}`;
3096
3488
  isGrammar,
3097
3489
  isKana,
3098
3490
  isKanji,
3491
+ isName,
3099
3492
  isObjectArray,
3100
3493
  isRadical,
3101
3494
  isStringArray,