henkan 0.1.2 → 0.2.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 (58) hide show
  1. package/dist/index.cjs.js +106 -71
  2. package/dist/index.cjs.js.map +3 -3
  3. package/dist/index.mjs +104 -71
  4. package/dist/index.mjs.map +3 -3
  5. package/dist/types/types.d.ts +24 -3
  6. package/dist/types/types.d.ts.map +1 -1
  7. package/dist/types/utils.d.ts.map +1 -1
  8. package/docs/api/README.md +1 -0
  9. package/docs/api/functions/capitalizeString.md +1 -1
  10. package/docs/api/functions/convertJMdict.md +1 -1
  11. package/docs/api/functions/convertKanjiDic.md +1 -1
  12. package/docs/api/functions/convertKradFile.md +1 -1
  13. package/docs/api/functions/convertRadkFile.md +1 -1
  14. package/docs/api/functions/convertTanakaCorpus.md +1 -1
  15. package/docs/api/functions/generateAnkiNote.md +1 -1
  16. package/docs/api/functions/generateAnkiNotesFile.md +1 -1
  17. package/docs/api/functions/getKanji.md +1 -1
  18. package/docs/api/functions/getKanjiExtended.md +1 -1
  19. package/docs/api/functions/getWord.md +1 -1
  20. package/docs/api/functions/isStringArray.md +1 -1
  21. package/docs/api/functions/isValidArray.md +1 -1
  22. package/docs/api/functions/isValidArrayWithFirstElement.md +1 -1
  23. package/docs/api/functions/makeSSML.md +1 -1
  24. package/docs/api/functions/shuffleArray.md +1 -1
  25. package/docs/api/functions/synthesizeSpeech.md +1 -1
  26. package/docs/api/interfaces/DictKanji.md +14 -4
  27. package/docs/api/interfaces/DictKanjiForm.md +4 -4
  28. package/docs/api/interfaces/DictKanjiMisc.md +5 -5
  29. package/docs/api/interfaces/DictKanjiReading.md +3 -3
  30. package/docs/api/interfaces/DictKanjiReadingMeaning.md +3 -3
  31. package/docs/api/interfaces/DictKanjiReadingMeaningGroup.md +3 -3
  32. package/docs/api/interfaces/DictKanjiWithRadicals.md +3 -3
  33. package/docs/api/interfaces/DictMeaning.md +11 -11
  34. package/docs/api/interfaces/DictRadical.md +4 -4
  35. package/docs/api/interfaces/DictReading.md +5 -5
  36. package/docs/api/interfaces/DictWord.md +8 -8
  37. package/docs/api/interfaces/ExamplePart.md +7 -7
  38. package/docs/api/interfaces/Grammar.md +15 -15
  39. package/docs/api/interfaces/GrammarMeaning.md +3 -3
  40. package/docs/api/interfaces/Kana.md +11 -11
  41. package/docs/api/interfaces/Kanji.md +31 -21
  42. package/docs/api/interfaces/KanjiComponent.md +3 -3
  43. package/docs/api/interfaces/KanjiForm.md +3 -3
  44. package/docs/api/interfaces/NoteAndTag.md +31 -0
  45. package/docs/api/interfaces/Phrase.md +4 -4
  46. package/docs/api/interfaces/Radical.md +16 -16
  47. package/docs/api/interfaces/Reading.md +4 -4
  48. package/docs/api/interfaces/ResultEntry.md +7 -7
  49. package/docs/api/interfaces/TanakaExample.md +7 -7
  50. package/docs/api/interfaces/Translation.md +3 -3
  51. package/docs/api/interfaces/UsefulRegExps.md +9 -9
  52. package/docs/api/interfaces/Word.md +14 -14
  53. package/docs/api/type-aliases/Dict.md +1 -1
  54. package/docs/api/type-aliases/DictName.md +1 -1
  55. package/docs/api/type-aliases/EntryType.md +1 -1
  56. package/docs/api/type-aliases/JLPT.md +1 -1
  57. package/docs/api/type-aliases/Result.md +1 -1
  58. package/package.json +3 -3
package/dist/index.mjs CHANGED
@@ -1160,6 +1160,13 @@ function convertJMdict(xmlString, examples) {
1160
1160
  const dict = [];
1161
1161
  xml.parseString(dictParsed, (err, result) => {
1162
1162
  if (err) throw err;
1163
+ let tanakaBaseParts = void 0;
1164
+ if (examples)
1165
+ tanakaBaseParts = new Set(
1166
+ examples.map(
1167
+ (example) => example.parts.map((part) => part.baseForm)
1168
+ ).flat()
1169
+ );
1163
1170
  if (result.JMdict && typeof result.JMdict === "object" && isValidArray(result.JMdict.entry))
1164
1171
  for (const entry of result.JMdict.entry) {
1165
1172
  const entryObj = {
@@ -1255,21 +1262,19 @@ function convertJMdict(xmlString, examples) {
1255
1262
  ) : void 0;
1256
1263
  let kanjiFormExamples = false;
1257
1264
  let readingExamples = false;
1258
- if (kanjiForms2) {
1259
- outer: for (const example of examples)
1260
- for (const part of example.parts)
1261
- if (kanjiForms2.has(part.baseForm)) {
1262
- kanjiFormExamples = true;
1263
- break outer;
1264
- }
1265
+ if (kanjiForms2 && kanjiForms2.size > 0 && tanakaBaseParts) {
1266
+ for (const kf of kanjiForms2)
1267
+ if (tanakaBaseParts.has(kf)) {
1268
+ kanjiFormExamples = true;
1269
+ break;
1270
+ }
1265
1271
  }
1266
- if (!kanjiFormExamples) {
1267
- outer: for (const example of examples)
1268
- for (const part of example.parts)
1269
- if (readings2.has(part.baseForm)) {
1270
- readingExamples = true;
1271
- break outer;
1272
- }
1272
+ if (!kanjiFormExamples && readings2.size > 0 && tanakaBaseParts) {
1273
+ for (const r of readings2)
1274
+ if (tanakaBaseParts.has(r)) {
1275
+ readingExamples = true;
1276
+ break;
1277
+ }
1273
1278
  }
1274
1279
  if (kanjiFormExamples || readingExamples)
1275
1280
  entryObj.hasPhrases = true;
@@ -1338,8 +1343,11 @@ function convertKanjiDic(xmlString) {
1338
1343
  }
1339
1344
  if (isValidArray(group.meaning)) {
1340
1345
  for (const meaning of group.meaning)
1341
- if (typeof meaning === "string")
1346
+ if (typeof meaning === "string") {
1347
+ if (kanjiObj.isKokuji === void 0 && meaning === "(kokuji)")
1348
+ kanjiObj.isKokuji = true;
1342
1349
  groupObj.meanings.push(meaning);
1350
+ }
1343
1351
  }
1344
1352
  if (groupObj.readings.length > 0 || groupObj.meanings.length > 0)
1345
1353
  rmObj.groups.push(groupObj);
@@ -1521,11 +1529,12 @@ function lookupWordNote(key, notes, tags, required, fallback) {
1521
1529
  );
1522
1530
  if (!info) {
1523
1531
  if (required) throw new Error(`Invalid note info for ${key}`);
1524
- notes.push(fallback ?? key);
1525
- return;
1532
+ if (notes) notes.push(fallback ?? key);
1533
+ return { note: fallback ?? key };
1526
1534
  }
1527
- tags.push(info[0]);
1528
- notes.push(info[1]);
1535
+ if (tags) tags.push(`word::${info[0]}`);
1536
+ if (notes) notes.push(info[1]);
1537
+ return { note: info[1], tag: `word::${info[0]}` };
1529
1538
  }
1530
1539
  var wordAddNoteArray = (arr, cb) => {
1531
1540
  if (!arr) return;
@@ -1542,40 +1551,48 @@ function getWord(dict, id, kanjiDic, examples, dictWord, noteTypeName, deckPath)
1542
1551
  translations: [],
1543
1552
  noteID: `word_${dictWord.id}`,
1544
1553
  ...noteTypeName ? { noteTypeName } : {},
1545
- ...deckPath ? { deckPath } : {}
1554
+ ...deckPath ? { deckPath } : {},
1555
+ tags: []
1546
1556
  };
1557
+ if (dictWord.isCommon === true) word.common = true;
1547
1558
  if (dictWord.kanjiForms)
1548
1559
  word.kanjiForms = dictWord.kanjiForms.map(
1549
- (dictKanjiForm) => {
1550
- if (dictKanjiForm.commonness && dictKanjiForm.commonness.length > 0 && word.common === void 0)
1551
- word.common = true;
1552
- return {
1553
- kanjiForm: dictKanjiForm.form,
1554
- ...dictKanjiForm.notes ? {
1555
- notes: dictKanjiForm.notes.map(
1556
- (note) => capitalizeString(note)
1557
- )
1558
- } : {}
1559
- };
1560
- }
1560
+ (dictKanjiForm) => ({
1561
+ kanjiForm: dictKanjiForm.form,
1562
+ ...dictKanjiForm.notes ? {
1563
+ notes: dictKanjiForm.notes.map((note) => {
1564
+ const noteAndTag = lookupWordNote(
1565
+ note,
1566
+ void 0,
1567
+ word.tags,
1568
+ false,
1569
+ note
1570
+ );
1571
+ return capitalizeString(noteAndTag.note ?? note);
1572
+ })
1573
+ } : {}
1574
+ })
1561
1575
  );
1562
- word.readings = dictWord.readings.map((dictReading) => {
1563
- if (dictReading.commonness && dictReading.commonness.length > 0 && word.common === void 0)
1564
- word.common = true;
1565
- return {
1566
- reading: dictReading.reading,
1567
- ...dictReading.kanjiFormRestrictions || dictReading.notes ? {
1568
- notes: [
1569
- ...dictReading.kanjiFormRestrictions ? dictReading.kanjiFormRestrictions.map(
1570
- (restriction) => `Reading restricted to ${restriction}`
1571
- ) : [],
1572
- ...dictReading.notes ? dictReading.notes.map(
1573
- (note) => capitalizeString(note)
1574
- ) : []
1575
- ]
1576
- } : {}
1577
- };
1578
- });
1576
+ word.readings = dictWord.readings.map((dictReading) => ({
1577
+ reading: dictReading.reading,
1578
+ ...dictReading.kanjiFormRestrictions || dictReading.notes ? {
1579
+ notes: [
1580
+ ...dictReading.kanjiFormRestrictions ? dictReading.kanjiFormRestrictions.map(
1581
+ (restriction) => `Reading restricted to ${restriction}`
1582
+ ) : [],
1583
+ ...dictReading.notes ? dictReading.notes.map((note) => {
1584
+ const noteAndTag = lookupWordNote(
1585
+ note,
1586
+ void 0,
1587
+ word.tags,
1588
+ false,
1589
+ note
1590
+ );
1591
+ return capitalizeString(noteAndTag.note ?? note);
1592
+ }) : []
1593
+ ]
1594
+ } : {}
1595
+ }));
1579
1596
  let usuallyInKanaMeanings = 0;
1580
1597
  word.translations = dictWord.meanings.map((dictMeaning) => {
1581
1598
  if (!dictMeaning.translations)
@@ -1596,7 +1613,6 @@ function getWord(dict, id, kanjiDic, examples, dictWord, noteTypeName, deckPath)
1596
1613
  }
1597
1614
  );
1598
1615
  const notes = [];
1599
- word.tags = [];
1600
1616
  wordAddNoteArray(
1601
1617
  dictMeaning.kanjiFormRestrictions,
1602
1618
  (restriction) => notes.push(`Meaning restricted to ${restriction}`)
@@ -1667,7 +1683,7 @@ function getWord(dict, id, kanjiDic, examples, dictWord, noteTypeName, deckPath)
1667
1683
  }
1668
1684
  if (word.kanji.length === 0) delete word.kanji;
1669
1685
  }
1670
- if (examples) {
1686
+ if (examples && dictWord.hasPhrases === true) {
1671
1687
  const readings = new Set(
1672
1688
  word.readings.filter(
1673
1689
  (reading) => !reading.notes || reading.notes && !reading.notes.some(
@@ -1736,6 +1752,7 @@ function getWord(dict, id, kanjiDic, examples, dictWord, noteTypeName, deckPath)
1736
1752
  }
1737
1753
  }
1738
1754
  function getKanji(kanjiChar, dict, jmDict, svgList, noteTypeName, deckPath) {
1755
+ var _a, _b, _c, _d;
1739
1756
  try {
1740
1757
  const dictKanji = dict.find(
1741
1758
  (entry) => entry.kanji === kanjiChar
@@ -1850,26 +1867,28 @@ function getKanji(kanjiChar, dict, jmDict, svgList, noteTypeName, deckPath) {
1850
1867
  let codePoint = kanji.kanji.codePointAt(0);
1851
1868
  if (codePoint !== void 0) {
1852
1869
  codePoint = codePoint.toString(16);
1870
+ const fileNames = [
1871
+ `0${codePoint}.svg`,
1872
+ `${codePoint}.svg`
1873
+ ];
1853
1874
  const svg = svgList.find(
1854
- (svgFile) => svgFile.toLowerCase() === `0${codePoint}.svg` || svgFile.toLowerCase() === `${codePoint}.svg`
1875
+ (svgFile) => fileNames.includes(svgFile.toLowerCase())
1855
1876
  );
1856
1877
  if (svg) kanji.svg = svg;
1857
1878
  }
1858
1879
  }
1859
1880
  kanji.tags = [];
1860
- if (kanji.meanings && kanji.meanings.some((meaning) => meaning === "(kokuji)")) {
1861
- kanji.tags.push("kokuji");
1862
- kanji.meanings = kanji.meanings.filter(
1863
- (meaning) => meaning !== "(kokuji)"
1864
- );
1881
+ if (dictKanji.isKokuji === true) {
1882
+ kanji.kokuji = true;
1883
+ kanji.tags.push("kanji::kokuji");
1865
1884
  }
1866
1885
  kanji.tags.push(
1867
- ...!kanji.onyomi ? ["no::onyomi"] : [],
1868
- ...!kanji.kunyomi ? ["no::kunyomi"] : [],
1869
- ...kanji.nanori ? ["has::nanori"] : [],
1870
- ...kanji.svg ? ["has::svg"] : [],
1871
- ...kanji.strokes && kanji.strokes.length > 0 ? [`strokes::${kanji.strokes}`] : [],
1872
- ...kanji.words ? ["has::words"] : []
1886
+ `kanji::onyomi::${((_a = kanji.onyomi) == null ? void 0 : _a.length) ?? 0}`,
1887
+ `kanji::kunyomi::${((_b = kanji.kunyomi) == null ? void 0 : _b.length) ?? 0}`,
1888
+ `kanji::nanori::${((_c = kanji.nanori) == null ? void 0 : _c.length) ?? 0}`,
1889
+ `kanji::strokes::${kanji.strokes ?? "unknown"}`,
1890
+ `kanji::words::${((_d = kanji.words) == null ? void 0 : _d.length) ?? 0}`,
1891
+ ...kanji.svg ? ["kanji::has_svg"] : []
1873
1892
  );
1874
1893
  return kanji;
1875
1894
  } else throw new Error(`Kanji ${kanjiChar} not found`);
@@ -1878,6 +1897,7 @@ function getKanji(kanjiChar, dict, jmDict, svgList, noteTypeName, deckPath) {
1878
1897
  }
1879
1898
  }
1880
1899
  function getKanjiExtended(kanjiChar, info, dict, useJpdbWords, jmDict, svgList, noteTypeName, deckPath) {
1900
+ var _a, _b;
1881
1901
  try {
1882
1902
  const kanji = getKanji(
1883
1903
  kanjiChar,
@@ -1893,12 +1913,25 @@ function getKanjiExtended(kanjiChar, info, dict, useJpdbWords, jmDict, svgList,
1893
1913
  kanji.mnemonic = info.mnemonic;
1894
1914
  if (useJpdbWords === true && info.words && info.words.length > 0)
1895
1915
  kanji.words = info.words;
1896
- if (kanji.mnemonic && kanji.mnemonic.length > 0 && kanji.tags)
1897
- kanji.tags.push("has::mnemonic");
1898
- if (kanji.components && kanji.components.length > 0 && kanji.tags)
1899
- kanji.tags.push(`components::${kanji.components.length}`);
1900
- if (kanji.words && kanji.tags && !kanji.tags.includes("has::words"))
1901
- kanji.tags.push("has::words");
1916
+ if (kanji.tags) {
1917
+ kanji.tags.push(`kanji::components::${((_a = kanji.components) == null ? void 0 : _a.length) ?? 0}`);
1918
+ if (kanji.mnemonic && kanji.mnemonic.length > 0)
1919
+ kanji.tags.push("kanji::has_mnemonic");
1920
+ if (useJpdbWords === true && kanji.words) {
1921
+ if (!kanji.tags.some((tag, index) => {
1922
+ var _a2;
1923
+ if (tag.startsWith("kanji::words::")) {
1924
+ kanji.tags.splice(
1925
+ index,
1926
+ 1,
1927
+ `kanji::words::${((_a2 = kanji.words) == null ? void 0 : _a2.length) ?? 0}`
1928
+ );
1929
+ return true;
1930
+ } else return false;
1931
+ }))
1932
+ kanji.tags.push(`kanji::words::${((_b = kanji.words) == null ? void 0 : _b.length) ?? 0}`);
1933
+ }
1934
+ }
1902
1935
  if (kanji.fromJpdb === true && (kanji.mnemonic || kanji.components && kanji.components.length > 0 || kanji.words))
1903
1936
  kanji.source = `https://jpdb.io/kanji/${kanji.kanji}#a`;
1904
1937
  return kanji;
@@ -2103,12 +2136,12 @@ function generateAnkiNote(entry) {
2103
2136
  (onyomiEntry) => createEntry(
2104
2137
  `<span class="kanji kanji-onyomi">${onyomiEntry}</span>`
2105
2138
  )
2106
- ).join("") : '<span class="kanji kanji-onyomi">(no onyomi) (kokuji)</span>',
2139
+ ).join("") : `<span class="kanji kanji-onyomi">(no onyomi) ${entry.kokuji === true ? "(kokuji)" : ""}</span`,
2107
2140
  entry.kunyomi ? entry.kunyomi.map(
2108
2141
  (kunyomiEntry) => createEntry(
2109
2142
  `<span class="kanji kanji-kunyomi">${kunyomiEntry}</span>`
2110
2143
  )
2111
- ).join("") : '<span class="kanji kanji-kunyomi">(no kunyomi)</span>',
2144
+ ).join("") : `<span class="kanji kanji-kunyomi">(no kunyomi) ${entry.kokuji === true ? "(kokuji)" : ""}</span>`,
2112
2145
  entry.nanori ? entry.nanori.map(
2113
2146
  (nanoriEntry) => createEntry(
2114
2147
  `<span class="kanji kanji-nanori">${nanoriEntry}</span>`