henkan 2.4.12 → 3.0.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 (86) hide show
  1. package/dist/index.cjs.js +431 -20
  2. package/dist/index.cjs.js.map +2 -2
  3. package/dist/index.mjs +428 -20
  4. package/dist/index.mjs.map +2 -2
  5. package/dist/types/types.d.ts +106 -15
  6. package/dist/types/types.d.ts.map +1 -1
  7. package/dist/types/utils.d.ts +28 -6
  8. package/dist/types/utils.d.ts.map +1 -1
  9. package/docs/api/README.md +8 -2
  10. package/docs/api/functions/capitalizeString.md +1 -1
  11. package/docs/api/functions/convertJMdict.md +1 -1
  12. package/docs/api/functions/convertJMnedict.md +33 -0
  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 +9 -3
  21. package/docs/api/functions/generateAnkiNote.md +2 -2
  22. package/docs/api/functions/generateAnkiNotesFile.md +1 -1
  23. package/docs/api/functions/generateFurigana.md +1 -1
  24. package/docs/api/functions/getKanji.md +1 -1
  25. package/docs/api/functions/getKanjiExtended.md +1 -1
  26. package/docs/api/functions/getName.md +57 -0
  27. package/docs/api/functions/getValidForms.md +1 -1
  28. package/docs/api/functions/getWord.md +3 -3
  29. package/docs/api/functions/getWordDefinitions.md +1 -1
  30. package/docs/api/functions/getWordDefinitionsWithFurigana.md +1 -1
  31. package/docs/api/functions/hiraganaToKatakana.md +1 -1
  32. package/docs/api/functions/isObjectArray.md +1 -1
  33. package/docs/api/functions/isStringArray.md +1 -1
  34. package/docs/api/functions/isValidArrayWithFirstElement.md +1 -1
  35. package/docs/api/functions/katakanaToHiragana.md +1 -1
  36. package/docs/api/functions/shuffleArray.md +1 -1
  37. package/docs/api/interfaces/DefaultNoteInfo.md +10 -10
  38. package/docs/api/interfaces/Definition.md +4 -4
  39. package/docs/api/interfaces/DictKanji.md +5 -5
  40. package/docs/api/interfaces/DictKanjiForm.md +2 -2
  41. package/docs/api/interfaces/DictKanjiMisc.md +5 -5
  42. package/docs/api/interfaces/DictKanjiReading.md +3 -3
  43. package/docs/api/interfaces/DictKanjiReadingMeaning.md +3 -3
  44. package/docs/api/interfaces/DictKanjiReadingMeaningGroup.md +3 -3
  45. package/docs/api/interfaces/DictKanjiWithRadicals.md +3 -3
  46. package/docs/api/interfaces/DictName.md +75 -0
  47. package/docs/api/interfaces/DictRadical.md +4 -4
  48. package/docs/api/interfaces/DictReading.md +2 -2
  49. package/docs/api/interfaces/EntryMaps.md +33 -9
  50. package/docs/api/interfaces/ExamplePart.md +7 -7
  51. package/docs/api/interfaces/GlossSpecificNumber.md +3 -3
  52. package/docs/api/interfaces/Grammar.md +15 -15
  53. package/docs/api/interfaces/GrammarMeaning.md +3 -3
  54. package/docs/api/interfaces/JaWiktionaryEntry.md +5 -5
  55. package/docs/api/interfaces/Kana.md +11 -11
  56. package/docs/api/interfaces/Kanji.md +23 -23
  57. package/docs/api/interfaces/KanjiComponent.md +3 -3
  58. package/docs/api/interfaces/KanjiForm.md +5 -5
  59. package/docs/api/interfaces/Name.md +163 -0
  60. package/docs/api/interfaces/NeDictMeaning.md +33 -0
  61. package/docs/api/interfaces/NoteAndTag.md +3 -3
  62. package/docs/api/interfaces/NoteHeaderKeys.md +7 -7
  63. package/docs/api/interfaces/Phrase.md +5 -5
  64. package/docs/api/interfaces/Radical.md +16 -16
  65. package/docs/api/interfaces/Reading.md +6 -6
  66. package/docs/api/interfaces/ResultEntry.md +8 -7
  67. package/docs/api/interfaces/TanakaExample.md +7 -7
  68. package/docs/api/interfaces/Translation.md +5 -5
  69. package/docs/api/interfaces/UsefulRegExps.md +8 -8
  70. package/docs/api/interfaces/Word.md +15 -15
  71. package/docs/api/interfaces/WordDefinitionPair.md +4 -4
  72. package/docs/api/type-aliases/Dict.md +1 -1
  73. package/docs/api/type-aliases/{DictName.md → DictNames.md} +3 -3
  74. package/docs/api/type-aliases/EntryExamplesMap.md +13 -0
  75. package/docs/api/type-aliases/EntryType.md +2 -2
  76. package/docs/api/type-aliases/KanjiEntryMap.md +1 -1
  77. package/docs/api/type-aliases/KanjiSVGMap.md +1 -1
  78. package/docs/api/type-aliases/KanjiWordsMap.md +1 -1
  79. package/docs/api/type-aliases/NameIDEntryMap.md +13 -0
  80. package/docs/api/type-aliases/Result.md +2 -2
  81. package/docs/api/type-aliases/WordDefinitionsMap.md +1 -1
  82. package/docs/api/type-aliases/WordIDEntryMap.md +1 -1
  83. package/package.json +8 -7
  84. package/src/types.ts +115 -15
  85. package/src/utils.ts +735 -80
  86. package/docs/api/type-aliases/WordExamplesMap.md +0 -13
package/dist/index.mjs CHANGED
@@ -1476,6 +1476,90 @@ function convertJMdict(xmlString, examples) {
1476
1476
  });
1477
1477
  return dict;
1478
1478
  }
1479
+ function convertJMnedict(xmlString, examples) {
1480
+ const dictParsed = libxml.parseXml(xmlString, {
1481
+ dtdvalid: true,
1482
+ nonet: false,
1483
+ noent: true,
1484
+ recover: false
1485
+ });
1486
+ const dict = [];
1487
+ xml.parseString(dictParsed, (_err, result) => {
1488
+ const tanakaParts = examples !== void 0 && examples.length > 0 ? new Set(
1489
+ examples.flatMap(
1490
+ (example) => example.parts.flatMap((part) => [
1491
+ part.baseForm,
1492
+ ...part.reading !== void 0 ? [part.reading] : [],
1493
+ ...part.inflectedForm !== void 0 ? [part.inflectedForm] : [],
1494
+ ...part.referenceID !== void 0 ? [part.referenceID] : []
1495
+ ])
1496
+ )
1497
+ ) : void 0;
1498
+ for (const entry of result.JMnedict.entry) {
1499
+ const entryObj = {
1500
+ id: entry.ent_seq[0],
1501
+ nameReadings: [],
1502
+ meanings: []
1503
+ };
1504
+ const kanjiForms = entry.k_ele;
1505
+ const readings = entry.r_ele;
1506
+ const translations = entry.trans;
1507
+ if (isObjectArray(kanjiForms)) {
1508
+ entryObj.kanjiForms = [];
1509
+ for (const kanjiForm of kanjiForms)
1510
+ entryObj.kanjiForms.push({ form: kanjiForm.keb[0] });
1511
+ }
1512
+ for (const reading of readings) {
1513
+ const readingObj = {
1514
+ reading: reading.reb[0]
1515
+ };
1516
+ if (isStringArray(reading.re_restr))
1517
+ readingObj.kanjiFormRestrictions = reading.re_restr;
1518
+ if (isStringArray(reading.re_pri)) {
1519
+ readingObj.commonness = reading.re_pri;
1520
+ entryObj.isCommon = true;
1521
+ }
1522
+ entryObj.nameReadings.push(readingObj);
1523
+ }
1524
+ for (const trans of translations)
1525
+ entryObj.meanings.push({
1526
+ translations: trans.trans_det,
1527
+ ...isStringArray(trans.name_type) ? { nameTypes: trans.name_type } : {}
1528
+ });
1529
+ if (examples !== void 0) {
1530
+ let existsExample = false;
1531
+ const rkf = getValidForms(
1532
+ entryObj.nameReadings,
1533
+ entryObj.kanjiForms,
1534
+ entryObj.isCommon
1535
+ );
1536
+ const validReadings = new Set(
1537
+ rkf.readings.map((r) => r.reading)
1538
+ );
1539
+ const validKanjiForms = rkf.kanjiForms !== void 0 ? new Set(
1540
+ rkf.kanjiForms.map((kf) => kf.form)
1541
+ ) : void 0;
1542
+ if (validKanjiForms !== void 0 && validKanjiForms.size > 0 && tanakaParts !== void 0) {
1543
+ for (const kf of validKanjiForms)
1544
+ if (tanakaParts.has(kf)) {
1545
+ existsExample = true;
1546
+ break;
1547
+ }
1548
+ }
1549
+ if (entryObj.kanjiForms === void 0 && validReadings.size > 0 && tanakaParts !== void 0) {
1550
+ for (const r of validReadings)
1551
+ if (tanakaParts.has(r)) {
1552
+ existsExample = true;
1553
+ break;
1554
+ }
1555
+ }
1556
+ if (existsExample) entryObj.hasPhrases = true;
1557
+ }
1558
+ dict.push(entryObj);
1559
+ }
1560
+ });
1561
+ return dict;
1562
+ }
1479
1563
  function convertKanjiDic(xmlString) {
1480
1564
  const dictParsed = libxml.parseXml(xmlString, {
1481
1565
  dtdvalid: true,
@@ -1678,16 +1762,15 @@ function convertKradFile(kradBuffer, kanjiDic, katakanaList) {
1678
1762
  }
1679
1763
  return kanjiWithRadicals;
1680
1764
  }
1681
- function createEntryMaps(jmDict, kanjiDic, tanakaExamples, wordDefinitionPairs, svgList) {
1765
+ function createEntryMaps(jmDict, jmNedict, kanjiDic, tanakaExamples, wordDefinitionPairs, svgList) {
1682
1766
  const kanjiEntryMap = /* @__PURE__ */ new Map();
1683
1767
  const wordIDEntryMap = /* @__PURE__ */ new Map();
1768
+ const nameIDEntryMap = /* @__PURE__ */ new Map();
1684
1769
  const kanjiWordsMap = /* @__PURE__ */ new Map();
1685
1770
  const wordExamplesMap = /* @__PURE__ */ new Map();
1771
+ const nameExamplesMap = /* @__PURE__ */ new Map();
1686
1772
  const wordDefinitionsMap = /* @__PURE__ */ new Map();
1687
1773
  const kanjiSVGMap = /* @__PURE__ */ new Map();
1688
- const wordPartsMap = /* @__PURE__ */ new Map();
1689
- const partExamplesMap = /* @__PURE__ */ new Map();
1690
- const entryParts = /* @__PURE__ */ new Set();
1691
1774
  if (kanjiDic !== void 0)
1692
1775
  for (const kanji of kanjiDic) kanjiEntryMap.set(kanji.kanji, kanji);
1693
1776
  if (wordDefinitionPairs !== void 0)
@@ -1703,6 +1786,9 @@ function createEntryMaps(jmDict, kanjiDic, tanakaExamples, wordDefinitionPairs,
1703
1786
  if (svg !== void 0) kanjiSVGMap.set(kanji.kanji, svg);
1704
1787
  }
1705
1788
  if (jmDict !== void 0) {
1789
+ const wordPartsMap = /* @__PURE__ */ new Map();
1790
+ const partExamplesMap = /* @__PURE__ */ new Map();
1791
+ const entryParts = /* @__PURE__ */ new Set();
1706
1792
  for (const word of jmDict) {
1707
1793
  wordIDEntryMap.set(word.id, word);
1708
1794
  if (word.kanjiForms !== void 0)
@@ -1781,11 +1867,82 @@ function createEntryMaps(jmDict, kanjiDic, tanakaExamples, wordDefinitionPairs,
1781
1867
  }
1782
1868
  }
1783
1869
  }
1870
+ if (jmNedict !== void 0) {
1871
+ const namePartsMap = /* @__PURE__ */ new Map();
1872
+ const partExamplesMap = /* @__PURE__ */ new Map();
1873
+ const entryParts = /* @__PURE__ */ new Set();
1874
+ for (const name of jmNedict) {
1875
+ nameIDEntryMap.set(name.id, name);
1876
+ if (tanakaExamples !== void 0) {
1877
+ const rkf = getValidForms(
1878
+ name.nameReadings,
1879
+ name.kanjiForms,
1880
+ name.isCommon
1881
+ );
1882
+ const localPartParts = /* @__PURE__ */ new Set();
1883
+ for (const reading of rkf.readings) {
1884
+ entryParts.add(reading.reading);
1885
+ localPartParts.add(reading.reading);
1886
+ }
1887
+ if (rkf.kanjiForms !== void 0 && rkf.kanjiForms.length > 0)
1888
+ for (const kanjiForm of rkf.kanjiForms) {
1889
+ entryParts.add(kanjiForm.form);
1890
+ localPartParts.add(kanjiForm.form);
1891
+ }
1892
+ entryParts.add(name.id);
1893
+ localPartParts.add(name.id);
1894
+ namePartsMap.set(name.id, localPartParts);
1895
+ }
1896
+ }
1897
+ if (tanakaExamples !== void 0) {
1898
+ for (const ex of tanakaExamples)
1899
+ for (const part of ex.parts) {
1900
+ if (entryParts.has(part.baseForm)) {
1901
+ const exList = partExamplesMap.get(
1902
+ part.baseForm
1903
+ );
1904
+ if (exList === void 0) partExamplesMap.set(part.baseForm, [ex]);
1905
+ else exList.push(ex);
1906
+ }
1907
+ if (part.reading !== void 0 && entryParts.has(part.reading)) {
1908
+ const exList = partExamplesMap.get(
1909
+ part.reading
1910
+ );
1911
+ if (exList === void 0) partExamplesMap.set(part.reading, [ex]);
1912
+ else exList.push(ex);
1913
+ }
1914
+ if (part.inflectedForm !== void 0 && entryParts.has(part.inflectedForm)) {
1915
+ const exList = partExamplesMap.get(
1916
+ part.inflectedForm
1917
+ );
1918
+ if (exList === void 0)
1919
+ partExamplesMap.set(part.inflectedForm, [ex]);
1920
+ else exList.push(ex);
1921
+ }
1922
+ }
1923
+ for (const name of jmNedict) {
1924
+ const seenEx = /* @__PURE__ */ new Set();
1925
+ const validExamples = [];
1926
+ for (const p of namePartsMap.get(name.id)) {
1927
+ const examplesForPart = partExamplesMap.get(p)?.filter((ex) => !seenEx.has(ex.id));
1928
+ if (examplesForPart === void 0) continue;
1929
+ for (const ex of examplesForPart) {
1930
+ seenEx.add(ex.id);
1931
+ validExamples.push(ex);
1932
+ }
1933
+ }
1934
+ if (validExamples.length > 0)
1935
+ nameExamplesMap.set(name.id, validExamples);
1936
+ }
1937
+ }
1938
+ }
1784
1939
  return {
1785
1940
  ...wordIDEntryMap.size > 0 ? { wordIDEntryMap } : {},
1941
+ ...nameIDEntryMap.size > 0 ? { nameIDEntryMap } : {},
1786
1942
  ...kanjiWordsMap.size > 0 ? { kanjiWordsMap } : {},
1787
1943
  ...kanjiEntryMap.size > 0 ? { kanjiEntryMap } : {},
1788
1944
  ...wordExamplesMap.size > 0 ? { wordExamplesMap } : {},
1945
+ ...nameExamplesMap.size > 0 ? { nameExamplesMap } : {},
1789
1946
  ...wordDefinitionsMap.size > 0 ? { wordDefinitionsMap } : {},
1790
1947
  ...kanjiSVGMap.size > 0 ? { kanjiSVGMap } : {}
1791
1948
  };
@@ -2562,10 +2719,9 @@ function getWord(searchedWord, dict, kanjiDic, examples, definitions, noteTypeNa
2562
2719
  rkf.readings.map((r) => r.reading)
2563
2720
  );
2564
2721
  const kanjiForms = rkf.kanjiForms !== void 0 ? new Set(rkf.kanjiForms.map((kf) => kf.form)) : void 0;
2565
- let readingMatchingKanjiFormExamples = [];
2722
+ const readingMatchingKanjiFormExamples = [];
2566
2723
  let kanjiFormExamples = [];
2567
2724
  let readingExamples = [];
2568
- let hasReadingMatchingKanjiFormWithTranslation = false;
2569
2725
  for (const example of exampleList)
2570
2726
  for (let i = 0; i < example.parts.length; i++) {
2571
2727
  if (seenPhrases.has(example.phrase)) break;
@@ -2577,7 +2733,7 @@ function getWord(searchedWord, dict, kanjiDic, examples, definitions, noteTypeNa
2577
2733
  const readingAsInflectedFormMatch = part.inflectedForm !== void 0 && readings.has(part.inflectedForm);
2578
2734
  const referenceIDMatch = part.referenceID === dictWord.id;
2579
2735
  if (kanjiForms !== void 0 && kanjiForms.has(part.baseForm)) {
2580
- if (readingAsReadingMatch || readingAsInflectedFormMatch || referenceIDMatch) {
2736
+ if (readingAsReadingMatch || readingAsInflectedFormMatch || referenceIDMatch)
2581
2737
  readingMatchingKanjiFormExamples.push({
2582
2738
  ex: example,
2583
2739
  partIndex: i,
@@ -2585,9 +2741,7 @@ function getWord(searchedWord, dict, kanjiDic, examples, definitions, noteTypeNa
2585
2741
  ...referenceIDMatch ? { referenceIDMatch: true } : {},
2586
2742
  ...includesTranslation ? { includesTranslation: true } : {}
2587
2743
  });
2588
- if (!hasReadingMatchingKanjiFormWithTranslation && includesTranslation)
2589
- hasReadingMatchingKanjiFormWithTranslation = true;
2590
- } else
2744
+ else
2591
2745
  kanjiFormExamples.push({
2592
2746
  ex: example,
2593
2747
  partIndex: i,
@@ -2609,23 +2763,18 @@ function getWord(searchedWord, dict, kanjiDic, examples, definitions, noteTypeNa
2609
2763
  break;
2610
2764
  }
2611
2765
  }
2612
- if (readingMatchingKanjiFormExamples.length > 0) {
2613
- if (hasReadingMatchingKanjiFormWithTranslation)
2614
- readingMatchingKanjiFormExamples = readingMatchingKanjiFormExamples.filter(
2615
- (ex) => ex.includesTranslation === true || ex.referenceIDMatch === true || ex.ex.parts.some(
2616
- (part) => ex.form === part.baseForm && part.glossNumber !== void 0
2617
- )
2618
- );
2619
- kanjiFormExamples.length = 0;
2620
- }
2621
2766
  if (kanjiFormExamples.length > 0 && kanjiFormExamples.some(
2622
- (ex) => ex.includesTranslation === true
2767
+ (ex) => ex.includesTranslation === true || ex.ex.parts.some(
2768
+ (part) => ex.form === part.baseForm && part.glossNumber !== void 0
2769
+ )
2623
2770
  ))
2624
2771
  kanjiFormExamples = kanjiFormExamples.filter(
2625
2772
  (ex) => ex.includesTranslation === true || ex.ex.parts.some(
2626
2773
  (part) => ex.form === part.baseForm && part.glossNumber !== void 0
2627
2774
  )
2628
2775
  );
2776
+ else if (kanjiFormExamples.length > 0 && readingMatchingKanjiFormExamples.length > 0)
2777
+ kanjiFormExamples.length = 0;
2629
2778
  if (readingExamples.length > 0 && readingExamples.some(
2630
2779
  (ex) => ex.includesTranslation === true || ex.referenceIDMatch === true
2631
2780
  ))
@@ -2694,9 +2843,179 @@ function getWord(searchedWord, dict, kanjiDic, examples, definitions, noteTypeNa
2694
2843
  return word;
2695
2844
  } else return void 0;
2696
2845
  }
2846
+ function getName(searchedName, dict, kanjiDic, examples, noteTypeName, deckPath) {
2847
+ let dictName = void 0;
2848
+ if (typeof searchedName === "string" && dict !== void 0) {
2849
+ if (Array.isArray(dict))
2850
+ dictName = dict.find(
2851
+ (entry) => entry.id === searchedName
2852
+ );
2853
+ if (dict instanceof Map) dictName = dict.get(searchedName);
2854
+ }
2855
+ if (typeof searchedName === "object") dictName = searchedName;
2856
+ if (dictName !== void 0) {
2857
+ const name = {
2858
+ id: dictName.id,
2859
+ nameReadings: [],
2860
+ translations: [],
2861
+ noteID: `name_${dictName.id}`,
2862
+ noteTypeName,
2863
+ deckPath,
2864
+ tags: []
2865
+ };
2866
+ if (dictName.isCommon === true) {
2867
+ name.common = true;
2868
+ name.tags.push("name::common");
2869
+ }
2870
+ if (dictName.kanjiForms !== void 0)
2871
+ name.kanjiForms = dictName.kanjiForms.map(
2872
+ (dictKanjiForm) => ({
2873
+ kanjiForm: dictKanjiForm.form
2874
+ })
2875
+ );
2876
+ name.nameReadings = dictName.nameReadings.map(
2877
+ (dictReading) => ({
2878
+ reading: dictReading.reading,
2879
+ ...dictReading.kanjiFormRestrictions !== void 0 ? {
2880
+ notes: dictReading.kanjiFormRestrictions.map(
2881
+ (restriction) => `Reading restricted to ${restriction}`
2882
+ )
2883
+ } : {},
2884
+ ...dictReading.commonness !== void 0 && dictReading.commonness.length > 0 ? { common: true } : {}
2885
+ })
2886
+ );
2887
+ name.translations = [];
2888
+ const meanings = dictName.hasPhrases === true && examples !== void 0 ? [] : void 0;
2889
+ const seenPhrases = /* @__PURE__ */ new Set();
2890
+ let hasNameTypes = false;
2891
+ for (const dictMeaning of dictName.meanings) {
2892
+ if (!hasNameTypes && dictMeaning.nameTypes !== void 0)
2893
+ hasNameTypes = true;
2894
+ name.translations.push({
2895
+ translation: dictMeaning.translations.map((translation) => {
2896
+ if (meanings !== void 0) {
2897
+ const cleanTranslation = translation.replaceAll(/\([^)]*\)|\[[^\]]*\]|\{[^}]*\}/g, "").trim();
2898
+ if (!seenPhrases.has(cleanTranslation)) {
2899
+ seenPhrases.add(cleanTranslation);
2900
+ meanings.push(cleanTranslation);
2901
+ }
2902
+ }
2903
+ return translation;
2904
+ }).join("; "),
2905
+ ...dictMeaning.nameTypes !== void 0 ? {
2906
+ notes: dictMeaning.nameTypes.map((type) => {
2907
+ const noteAndTag = lookupWordNote(
2908
+ type,
2909
+ [],
2910
+ name.tags
2911
+ );
2912
+ return capitalizeString(noteAndTag.note);
2913
+ })
2914
+ } : {}
2915
+ });
2916
+ }
2917
+ if (!hasNameTypes) name.tags.push("name::no_name_types");
2918
+ seenPhrases.clear();
2919
+ if (kanjiDic !== void 0 && name.kanjiForms !== void 0) {
2920
+ const kanji = [];
2921
+ const seenChars = /* @__PURE__ */ new Set();
2922
+ for (const kanjiForm of name.kanjiForms)
2923
+ for (const char of kanjiForm.kanjiForm.split("").filter((c) => regexps.kanji.test(c))) {
2924
+ if (seenChars.has(char)) continue;
2925
+ seenChars.add(char);
2926
+ const kanjiEntry = kanjiDic instanceof Map ? kanjiDic.get(char) : void 0;
2927
+ const kanjiObj = getKanji(
2928
+ kanjiEntry ?? char,
2929
+ !(kanjiDic instanceof Map) ? kanjiDic : void 0
2930
+ );
2931
+ if (kanjiObj !== void 0)
2932
+ kanji.push({
2933
+ kanji: kanjiObj.kanji,
2934
+ ...kanjiObj.meanings !== void 0 && kanjiObj.meanings.length > 0 ? { meanings: kanjiObj.meanings } : {}
2935
+ });
2936
+ }
2937
+ if (kanji.length > 0) name.kanji = kanji;
2938
+ }
2939
+ if (meanings !== void 0) {
2940
+ const exampleList = examples instanceof Map ? examples.get(dictName.id) ?? [] : examples;
2941
+ const rkf = getValidForms(
2942
+ dictName.nameReadings,
2943
+ dictName.kanjiForms,
2944
+ dictName.isCommon
2945
+ );
2946
+ const readings = new Set(
2947
+ rkf.readings.map((r) => r.reading)
2948
+ );
2949
+ const kanjiForms = rkf.kanjiForms !== void 0 ? new Set(rkf.kanjiForms.map((kf) => kf.form)) : void 0;
2950
+ let readingMatchingKanjiFormExamples = [];
2951
+ let readingExamples = [];
2952
+ let hasReadingMatchingKanjiFormWithTranslation = false;
2953
+ let hasReadingWithTranslation = false;
2954
+ for (const example of exampleList)
2955
+ for (let i = 0; i < example.parts.length; i++) {
2956
+ if (seenPhrases.has(example.phrase)) break;
2957
+ const includesTranslation = meanings.some(
2958
+ (m) => example.translation.includes(m)
2959
+ );
2960
+ const part = example.parts[i];
2961
+ const readingAsReadingMatch = part.reading !== void 0 && readings.has(part.reading);
2962
+ if (kanjiForms !== void 0 && kanjiForms.has(part.baseForm) && readingAsReadingMatch) {
2963
+ readingMatchingKanjiFormExamples.push({
2964
+ ex: example,
2965
+ ...includesTranslation ? { includesTranslation: true } : {}
2966
+ });
2967
+ if (!hasReadingMatchingKanjiFormWithTranslation && includesTranslation)
2968
+ hasReadingMatchingKanjiFormWithTranslation = true;
2969
+ seenPhrases.add(example.phrase);
2970
+ break;
2971
+ }
2972
+ const readingAsBaseFormMatch = readings.has(part.baseForm);
2973
+ if (readingAsBaseFormMatch && kanjiForms === void 0) {
2974
+ readingExamples.push({
2975
+ ex: example,
2976
+ ...includesTranslation ? { includesTranslation: true } : {}
2977
+ });
2978
+ if (!hasReadingWithTranslation && includesTranslation)
2979
+ hasReadingWithTranslation = true;
2980
+ seenPhrases.add(example.phrase);
2981
+ break;
2982
+ }
2983
+ }
2984
+ if (readingMatchingKanjiFormExamples.length > 0) {
2985
+ if (hasReadingMatchingKanjiFormWithTranslation)
2986
+ readingMatchingKanjiFormExamples = readingMatchingKanjiFormExamples.filter(
2987
+ (ex) => ex.includesTranslation === true
2988
+ );
2989
+ }
2990
+ if (readingExamples.length > 0 && hasReadingWithTranslation)
2991
+ readingExamples = readingExamples.filter(
2992
+ (ex) => ex.includesTranslation === true
2993
+ );
2994
+ const wordExamples = [
2995
+ ...name.kanjiForms !== void 0 ? readingMatchingKanjiFormExamples : readingExamples
2996
+ ];
2997
+ if (wordExamples.length > 0) {
2998
+ name.phrases = wordExamples.slice(0, 5).map(
2999
+ (ex) => ({
3000
+ phrase: ex.ex.furigana ?? ex.ex.phrase,
3001
+ translation: ex.ex.translation,
3002
+ originalPhrase: ex.ex.phrase
3003
+ })
3004
+ );
3005
+ name.tags.push("name::has_phrases");
3006
+ }
3007
+ }
3008
+ return name;
3009
+ } else return void 0;
3010
+ }
2697
3011
  function isWord(entry) {
2698
3012
  return isObjectArray(Object.getOwnPropertyDescriptor(entry, "readings")?.value) && isObjectArray(Object.getOwnPropertyDescriptor(entry, "translations")?.value);
2699
3013
  }
3014
+ function isName(entry) {
3015
+ return isObjectArray(
3016
+ Object.getOwnPropertyDescriptor(entry, "nameReadings")?.value
3017
+ ) && isObjectArray(Object.getOwnPropertyDescriptor(entry, "translations")?.value);
3018
+ }
2700
3019
  function isRadical(entry) {
2701
3020
  return typeof Object.getOwnPropertyDescriptor(entry, "radical")?.value === "string";
2702
3021
  }
@@ -2834,6 +3153,92 @@ function generateAnkiNote(entry, customData, additionalTags) {
2834
3153
  searchField
2835
3154
  );
2836
3155
  }
3156
+ if (isName(entry)) {
3157
+ const firstReading = createEntry(
3158
+ `<span class="name name-reading">${entry.nameReadings[0].reading}${entry.nameReadings[0].audio !== void 0 ? `<br>[sound:${entry.nameReadings[0].audio}]` : ""}</span>`,
3159
+ entry.nameReadings[0].notes
3160
+ );
3161
+ const otherReadings = entry.nameReadings.length > 1 ? `<details><summary>Show other readings</summary>${entry.nameReadings.slice(1).map(
3162
+ (readingEntry) => createEntry(
3163
+ `<span class="name name-reading">${readingEntry.reading}${readingEntry.audio !== void 0 ? `<br>[sound:${readingEntry.audio}]` : ""}</span>`,
3164
+ readingEntry.notes
3165
+ )
3166
+ ).join("")}</details>` : "";
3167
+ const readingsField = `${firstReading}${otherReadings}`;
3168
+ let readingsFieldWithoutAudio = '<div id="no-r-audio" style="display: none"></div>';
3169
+ let hasAudio = false;
3170
+ if (entry.nameReadings.some((r) => r.audio !== void 0)) {
3171
+ const firstReadingWithoutAudio = createEntry(
3172
+ `<span class="name name-reading">${entry.nameReadings[0].reading}</span>`,
3173
+ entry.nameReadings[0].notes
3174
+ );
3175
+ const otherReadingsWithoutAudio = entry.nameReadings.length > 1 ? `<details><summary>Show other readings</summary>${entry.nameReadings.slice(1).map(
3176
+ (readingEntry) => createEntry(
3177
+ `<span class="name name-reading">${readingEntry.reading}</span>`,
3178
+ readingEntry.notes
3179
+ )
3180
+ ).join("")}</details>` : "";
3181
+ readingsFieldWithoutAudio = `${firstReadingWithoutAudio}${otherReadingsWithoutAudio}`;
3182
+ hasAudio = true;
3183
+ }
3184
+ const firstKanjiForm = entry.kanjiForms !== void 0 ? createEntry(
3185
+ `<span class="name name-kanjiform"><ruby><rb>${entry.kanjiForms[0].kanjiForm}</rb><rt>${entry.nameReadings[0].reading}</rt></ruby></span>`,
3186
+ entry.kanjiForms[0].notes
3187
+ ) : void 0;
3188
+ const otherKanjiForms = entry.kanjiForms !== void 0 && entry.kanjiForms.length > 1 ? `<details><summary>Show other kanji forms</summary>${entry.kanjiForms.slice(1).map((kanjiFormEntry) => {
3189
+ const restrictedReading = entry.nameReadings.find(
3190
+ (r) => r.notes !== void 0 && r.notes.includes(
3191
+ `Reading restricted to ${kanjiFormEntry.kanjiForm}`
3192
+ )
3193
+ );
3194
+ return createEntry(
3195
+ `<span class="name name-kanjiform">${restrictedReading !== void 0 ? "<ruby><rb>" : ""}${kanjiFormEntry.kanjiForm}${restrictedReading !== void 0 ? `</rb><rt>${restrictedReading.reading}</rt></ruby>` : ""}</span>`,
3196
+ kanjiFormEntry.notes
3197
+ );
3198
+ }).join("")}</details>` : "";
3199
+ const kanjiFormsField = firstKanjiForm !== void 0 ? `${firstKanjiForm}${otherKanjiForms}` : '<span class="name name-kanjiform" id="no-kanjiforms">(no kanji forms)</span>';
3200
+ const firstThreeTranslations = entry.translations.slice(0, 3).map(
3201
+ (translationEntry) => createEntry(
3202
+ `<span class="name name-translation">${translationEntry.translation}</span>`,
3203
+ translationEntry.notes
3204
+ )
3205
+ ).join("");
3206
+ const otherTranslations = entry.translations.length > 3 ? `<details><summary>Show other translations</summary>${entry.translations.map((translationEntry, index) => {
3207
+ if (index < 3) return "null";
3208
+ return createEntry(
3209
+ `<span class="name name-translation">${translationEntry.translation}</span>`,
3210
+ translationEntry.notes
3211
+ );
3212
+ }).filter((translation) => translation !== "null").join("")}</details>` : "";
3213
+ const translationsField = `${firstThreeTranslations}${otherTranslations}`;
3214
+ const phrasesField = entry.phrases !== void 0 ? entry.phrases.map(
3215
+ (phraseEntry) => createEntry(
3216
+ `<span class="name name-phrase"><span class="name name-phrase-original">${phraseEntry.originalPhrase}</span><span class="name name-phrase-furigana">${phraseEntry.phrase}</span></span>`,
3217
+ [phraseEntry.translation],
3218
+ true
3219
+ )
3220
+ ).join("") : '<span class="name name-phrase" id="no-phrases">(no phrases)</span>';
3221
+ const searchField = `${entry.nameReadings.map((r) => r.reading).join(" ")}${entry.kanjiForms !== void 0 ? ` ${entry.kanjiForms.map((kf) => kf.kanjiForm).join(" ")}` : ""} ${entry.id}`;
3222
+ fields.push(
3223
+ ...entry.kanjiForms !== void 0 ? [
3224
+ `${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>`,
3225
+ `${hasAudio ? readingsFieldWithoutAudio : readingsField}<div id="r-pos" style="display: none" data-pos="2"></div>`
3226
+ ] : [
3227
+ `${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>`,
3228
+ `${hasAudio ? readingsFieldWithoutAudio : readingsField}<div id="r-pos" style="display: none" data-pos="1"></div>`
3229
+ ],
3230
+ `${hasAudio ? readingsField : readingsFieldWithoutAudio}<div id="r-pos" style="display: none" data-pos="${entry.kanjiForms !== void 0 ? "2" : "1"}"></div>`,
3231
+ translationsField,
3232
+ phrasesField,
3233
+ entry.kanji !== void 0 ? entry.kanji.map(
3234
+ (kanjiEntry) => createEntry(
3235
+ `<span class="name name-kanji">${kanjiEntry.kanji}${kanjiEntry.meanings === void 0 ? " (no meanings)" : ""}</span>`,
3236
+ kanjiEntry.meanings
3237
+ )
3238
+ ).join("") : '<span class="name name-kanji" id="no-kanji">(no kanji)</span>',
3239
+ searchField
3240
+ );
3241
+ }
2837
3242
  if (isRadical(entry))
2838
3243
  fields.push(
2839
3244
  `${customData !== void 0 ? `<div id="custom-data" style="display: none" data-custom="${customData}"></div>` : ""}${createEntry(
@@ -3011,6 +3416,7 @@ ${ankiNotes}`;
3011
3416
  export {
3012
3417
  capitalizeString,
3013
3418
  convertJMdict,
3419
+ convertJMnedict,
3014
3420
  convertJawiktionaryAsync,
3015
3421
  convertJawiktionarySync,
3016
3422
  convertKanjiDic,
@@ -3024,6 +3430,7 @@ export {
3024
3430
  generateFurigana,
3025
3431
  getKanji,
3026
3432
  getKanjiExtended,
3433
+ getName,
3027
3434
  getValidForms,
3028
3435
  getWord,
3029
3436
  getWordDefinitions,
@@ -3032,6 +3439,7 @@ export {
3032
3439
  isGrammar,
3033
3440
  isKana,
3034
3441
  isKanji,
3442
+ isName,
3035
3443
  isObjectArray,
3036
3444
  isRadical,
3037
3445
  isStringArray,