henkan 2.4.11 → 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 +467 -50
  2. package/dist/index.cjs.js.map +2 -2
  3. package/dist/index.mjs +464 -50
  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 +815 -108
  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
  };
@@ -2449,17 +2606,34 @@ function getWord(searchedWord, dict, kanjiDic, examples, definitions, noteTypeNa
2449
2606
  ...dictReading.commonness !== void 0 && dictReading.commonness.length > 0 ? { common: true } : {}
2450
2607
  }));
2451
2608
  word.translations = [];
2609
+ const meanings = dictWord.hasPhrases === true && examples !== void 0 ? [] : void 0;
2610
+ const seenPhrases = /* @__PURE__ */ new Set();
2452
2611
  for (const dictMeaning of dictWord.meanings) {
2453
2612
  const translationTypes = [];
2454
2613
  const translations = dictMeaning.translations.map(
2455
2614
  (translation) => {
2456
- if (typeof translation === "string") return translation;
2457
- else {
2615
+ if (typeof translation === "string") {
2616
+ if (meanings !== void 0) {
2617
+ const cleanTranslation = translation.replaceAll(/\([^)]*\)|\[[^\]]*\]|\{[^}]*\}/g, "").trim();
2618
+ if (!seenPhrases.has(cleanTranslation)) {
2619
+ seenPhrases.add(cleanTranslation);
2620
+ meanings.push(cleanTranslation);
2621
+ }
2622
+ }
2623
+ return translation;
2624
+ } else {
2458
2625
  const translationNoteAndTag = noteMap.get(
2459
2626
  translation.type
2460
2627
  );
2461
2628
  translationTypes.push(translationNoteAndTag[1]);
2462
2629
  word.tags.push(`word::${translationNoteAndTag[0]}`);
2630
+ if (meanings !== void 0) {
2631
+ const cleanTranslation = translation.translation.replaceAll(/\([^)]*\)|\[[^\]]*\]|\{[^}]*\}/g, "").trim();
2632
+ if (!seenPhrases.has(cleanTranslation)) {
2633
+ seenPhrases.add(cleanTranslation);
2634
+ meanings.push(cleanTranslation);
2635
+ }
2636
+ }
2463
2637
  return translation.translation;
2464
2638
  }
2465
2639
  }
@@ -2513,6 +2687,7 @@ function getWord(searchedWord, dict, kanjiDic, examples, definitions, noteTypeNa
2513
2687
  word.usuallyInKana = true;
2514
2688
  word.tags.push("word::usually_in_kana_for_all_senses");
2515
2689
  }
2690
+ seenPhrases.clear();
2516
2691
  if (kanjiDic !== void 0 && word.kanjiForms !== void 0) {
2517
2692
  const kanji = [];
2518
2693
  const seenChars = /* @__PURE__ */ new Set();
@@ -2533,7 +2708,7 @@ function getWord(searchedWord, dict, kanjiDic, examples, definitions, noteTypeNa
2533
2708
  }
2534
2709
  if (kanji.length > 0) word.kanji = kanji;
2535
2710
  }
2536
- if (dictWord.hasPhrases === true && examples !== void 0) {
2711
+ if (meanings !== void 0) {
2537
2712
  const exampleList = examples instanceof Map ? examples.get(dictWord.id) ?? [] : examples;
2538
2713
  const rkf = getValidForms(
2539
2714
  dictWord.readings,
@@ -2544,22 +2719,9 @@ function getWord(searchedWord, dict, kanjiDic, examples, definitions, noteTypeNa
2544
2719
  rkf.readings.map((r) => r.reading)
2545
2720
  );
2546
2721
  const kanjiForms = rkf.kanjiForms !== void 0 ? new Set(rkf.kanjiForms.map((kf) => kf.form)) : void 0;
2547
- const meanings = new Set(
2548
- dictWord.meanings.flatMap(
2549
- (m) => m.translations.map((t) => {
2550
- if (typeof t === "string")
2551
- return t.replaceAll(/\([^)]*\)|\[[^\]]*\]|\{[^}]*\}/g, "").trim();
2552
- else
2553
- return t.translation.replaceAll(/\([^)]*\)|\[[^\]]*\]|\{[^}]*\}/g, "").trim();
2554
- })
2555
- )
2556
- ).values().toArray();
2722
+ const readingMatchingKanjiFormExamples = [];
2557
2723
  let kanjiFormExamples = [];
2558
- let readingMatchingKanjiFormExamples = [];
2559
2724
  let readingExamples = [];
2560
- let readingMatchingKanjiForms = /* @__PURE__ */ new Set();
2561
- const readingMatchingKanjiFormsWithTranslations = /* @__PURE__ */ new Set();
2562
- const seenPhrases = /* @__PURE__ */ new Set();
2563
2725
  for (const example of exampleList)
2564
2726
  for (let i = 0; i < example.parts.length; i++) {
2565
2727
  if (seenPhrases.has(example.phrase)) break;
@@ -2571,17 +2733,15 @@ function getWord(searchedWord, dict, kanjiDic, examples, definitions, noteTypeNa
2571
2733
  const readingAsInflectedFormMatch = part.inflectedForm !== void 0 && readings.has(part.inflectedForm);
2572
2734
  const referenceIDMatch = part.referenceID === dictWord.id;
2573
2735
  if (kanjiForms !== void 0 && kanjiForms.has(part.baseForm)) {
2574
- if (readingAsReadingMatch || readingAsInflectedFormMatch || referenceIDMatch) {
2736
+ if (readingAsReadingMatch || readingAsInflectedFormMatch || referenceIDMatch)
2575
2737
  readingMatchingKanjiFormExamples.push({
2576
2738
  ex: example,
2577
2739
  partIndex: i,
2578
2740
  form: part.baseForm,
2741
+ ...referenceIDMatch ? { referenceIDMatch: true } : {},
2579
2742
  ...includesTranslation ? { includesTranslation: true } : {}
2580
2743
  });
2581
- readingMatchingKanjiForms.add(part.baseForm);
2582
- if (includesTranslation)
2583
- readingMatchingKanjiFormsWithTranslations.add(part.baseForm);
2584
- } else
2744
+ else
2585
2745
  kanjiFormExamples.push({
2586
2746
  ex: example,
2587
2747
  partIndex: i,
@@ -2597,29 +2757,24 @@ function getWord(searchedWord, dict, kanjiDic, examples, definitions, noteTypeNa
2597
2757
  ex: example,
2598
2758
  partIndex: i,
2599
2759
  ...referenceIDMatch ? { referenceIDMatch: true } : {},
2600
- ...!referenceIDMatch && includesTranslation ? { includesTranslation: true } : {}
2760
+ ...includesTranslation ? { includesTranslation: true } : {}
2601
2761
  });
2602
2762
  seenPhrases.add(example.phrase);
2603
2763
  break;
2604
2764
  }
2605
2765
  }
2606
- if (readingMatchingKanjiFormsWithTranslations.size > 0) {
2607
- readingMatchingKanjiForms = readingMatchingKanjiFormsWithTranslations;
2608
- readingMatchingKanjiFormExamples = readingMatchingKanjiFormExamples.filter(
2766
+ if (kanjiFormExamples.length > 0 && kanjiFormExamples.some(
2767
+ (ex) => ex.includesTranslation === true || ex.ex.parts.some(
2768
+ (part) => ex.form === part.baseForm && part.glossNumber !== void 0
2769
+ )
2770
+ ))
2771
+ kanjiFormExamples = kanjiFormExamples.filter(
2609
2772
  (ex) => ex.includesTranslation === true || ex.ex.parts.some(
2610
- (part) => readingMatchingKanjiForms.has(part.baseForm) && part.glossNumber !== void 0
2773
+ (part) => ex.form === part.baseForm && part.glossNumber !== void 0
2611
2774
  )
2612
2775
  );
2613
- }
2614
- const hasKfExamplesWithTranslation = kanjiFormExamples.some(
2615
- (ex) => ex.includesTranslation === true
2616
- );
2617
- if (kanjiFormExamples.length > 0 && readingMatchingKanjiForms.size > 0)
2618
- kanjiFormExamples = kanjiFormExamples.filter(
2619
- (ex) => readingMatchingKanjiForms.has(ex.form) && (!hasKfExamplesWithTranslation || ex.includesTranslation === true || ex.ex.parts.some(
2620
- (part) => readingMatchingKanjiForms.has(part.baseForm) && part.glossNumber !== void 0
2621
- ))
2622
- );
2776
+ else if (kanjiFormExamples.length > 0 && readingMatchingKanjiFormExamples.length > 0)
2777
+ kanjiFormExamples.length = 0;
2623
2778
  if (readingExamples.length > 0 && readingExamples.some(
2624
2779
  (ex) => ex.includesTranslation === true || ex.referenceIDMatch === true
2625
2780
  ))
@@ -2628,9 +2783,7 @@ function getWord(searchedWord, dict, kanjiDic, examples, definitions, noteTypeNa
2628
2783
  );
2629
2784
  let wordExamples = [
2630
2785
  ...word.kanjiForms !== void 0 ? [...readingMatchingKanjiFormExamples, ...kanjiFormExamples] : readingExamples
2631
- ].toSorted(
2632
- (a, b) => a.ex.phrase.length - b.ex.phrase.length
2633
- );
2786
+ ];
2634
2787
  seenPhrases.clear();
2635
2788
  const glossSpecificExamples = [];
2636
2789
  for (let i = 0; i < word.translations.length; i++)
@@ -2663,12 +2816,14 @@ function getWord(searchedWord, dict, kanjiDic, examples, definitions, noteTypeNa
2663
2816
  wordExamples = glossSpecificExamples;
2664
2817
  }
2665
2818
  if (wordExamples.length > 0) {
2666
- word.phrases = (glossSpecificExamples.length === 0 ? wordExamples.slice(0, 5) : wordExamples).map((ex) => ({
2667
- phrase: ex.ex.furigana ?? ex.ex.phrase,
2668
- translation: ex.ex.translation,
2669
- originalPhrase: ex.ex.phrase,
2670
- ...ex.ex.glossNumber !== void 0 ? { glossNumber: ex.ex.glossNumber } : {}
2671
- }));
2819
+ word.phrases = (glossSpecificExamples.length === 0 ? wordExamples.slice(0, 5) : wordExamples).map(
2820
+ (ex) => ({
2821
+ phrase: ex.ex.furigana ?? ex.ex.phrase,
2822
+ translation: ex.ex.translation,
2823
+ originalPhrase: ex.ex.phrase,
2824
+ ...ex.ex.glossNumber !== void 0 ? { glossNumber: ex.ex.glossNumber } : {}
2825
+ })
2826
+ );
2672
2827
  word.tags.push("word::has_phrases");
2673
2828
  if (glossSpecificExamples.length > 0)
2674
2829
  word.tags.push("word::has_meaning-specific_phrases");
@@ -2688,9 +2843,179 @@ function getWord(searchedWord, dict, kanjiDic, examples, definitions, noteTypeNa
2688
2843
  return word;
2689
2844
  } else return void 0;
2690
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
+ }
2691
3011
  function isWord(entry) {
2692
3012
  return isObjectArray(Object.getOwnPropertyDescriptor(entry, "readings")?.value) && isObjectArray(Object.getOwnPropertyDescriptor(entry, "translations")?.value);
2693
3013
  }
3014
+ function isName(entry) {
3015
+ return isObjectArray(
3016
+ Object.getOwnPropertyDescriptor(entry, "nameReadings")?.value
3017
+ ) && isObjectArray(Object.getOwnPropertyDescriptor(entry, "translations")?.value);
3018
+ }
2694
3019
  function isRadical(entry) {
2695
3020
  return typeof Object.getOwnPropertyDescriptor(entry, "radical")?.value === "string";
2696
3021
  }
@@ -2828,6 +3153,92 @@ function generateAnkiNote(entry, customData, additionalTags) {
2828
3153
  searchField
2829
3154
  );
2830
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
+ }
2831
3242
  if (isRadical(entry))
2832
3243
  fields.push(
2833
3244
  `${customData !== void 0 ? `<div id="custom-data" style="display: none" data-custom="${customData}"></div>` : ""}${createEntry(
@@ -3005,6 +3416,7 @@ ${ankiNotes}`;
3005
3416
  export {
3006
3417
  capitalizeString,
3007
3418
  convertJMdict,
3419
+ convertJMnedict,
3008
3420
  convertJawiktionaryAsync,
3009
3421
  convertJawiktionarySync,
3010
3422
  convertKanjiDic,
@@ -3018,6 +3430,7 @@ export {
3018
3430
  generateFurigana,
3019
3431
  getKanji,
3020
3432
  getKanjiExtended,
3433
+ getName,
3021
3434
  getValidForms,
3022
3435
  getWord,
3023
3436
  getWordDefinitions,
@@ -3026,6 +3439,7 @@ export {
3026
3439
  isGrammar,
3027
3440
  isKana,
3028
3441
  isKanji,
3442
+ isName,
3029
3443
  isObjectArray,
3030
3444
  isRadical,
3031
3445
  isStringArray,