henkan 0.8.0 → 0.9.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 (57) hide show
  1. package/README.md +1 -1
  2. package/dist/index.cjs.js +47 -66
  3. package/dist/index.cjs.js.map +3 -3
  4. package/dist/index.mjs +49 -66
  5. package/dist/index.mjs.map +2 -2
  6. package/dist/types/utils.d.ts +8 -11
  7. package/dist/types/utils.d.ts.map +1 -1
  8. package/docs/api/functions/capitalizeString.md +1 -1
  9. package/docs/api/functions/convertJMdict.md +1 -1
  10. package/docs/api/functions/convertKanjiDic.md +1 -1
  11. package/docs/api/functions/convertKradFile.md +1 -1
  12. package/docs/api/functions/convertRadkFile.md +1 -1
  13. package/docs/api/functions/convertTanakaCorpus.md +1 -1
  14. package/docs/api/functions/generateAnkiNote.md +1 -1
  15. package/docs/api/functions/generateAnkiNotesFile.md +1 -1
  16. package/docs/api/functions/getKanji.md +1 -1
  17. package/docs/api/functions/getKanjiExtended.md +1 -1
  18. package/docs/api/functions/getWord.md +1 -1
  19. package/docs/api/functions/isStringArray.md +1 -1
  20. package/docs/api/functions/isValidArray.md +1 -1
  21. package/docs/api/functions/isValidArrayWithFirstElement.md +1 -1
  22. package/docs/api/functions/shuffleArray.md +1 -1
  23. package/docs/api/functions/synthesizeSpeech.md +13 -25
  24. package/docs/api/interfaces/DictKanji.md +5 -5
  25. package/docs/api/interfaces/DictKanjiForm.md +4 -4
  26. package/docs/api/interfaces/DictKanjiMisc.md +5 -5
  27. package/docs/api/interfaces/DictKanjiReading.md +3 -3
  28. package/docs/api/interfaces/DictKanjiReadingMeaning.md +3 -3
  29. package/docs/api/interfaces/DictKanjiReadingMeaningGroup.md +3 -3
  30. package/docs/api/interfaces/DictKanjiWithRadicals.md +3 -3
  31. package/docs/api/interfaces/DictMeaning.md +11 -11
  32. package/docs/api/interfaces/DictRadical.md +4 -4
  33. package/docs/api/interfaces/DictReading.md +5 -5
  34. package/docs/api/interfaces/DictWord.md +8 -8
  35. package/docs/api/interfaces/ExamplePart.md +7 -7
  36. package/docs/api/interfaces/GlossSpecificNumber.md +3 -3
  37. package/docs/api/interfaces/Grammar.md +15 -15
  38. package/docs/api/interfaces/GrammarMeaning.md +3 -3
  39. package/docs/api/interfaces/Kana.md +11 -11
  40. package/docs/api/interfaces/Kanji.md +22 -22
  41. package/docs/api/interfaces/KanjiComponent.md +3 -3
  42. package/docs/api/interfaces/KanjiForm.md +4 -4
  43. package/docs/api/interfaces/NoteAndTag.md +3 -3
  44. package/docs/api/interfaces/Phrase.md +5 -5
  45. package/docs/api/interfaces/Radical.md +16 -16
  46. package/docs/api/interfaces/Reading.md +5 -5
  47. package/docs/api/interfaces/ResultEntry.md +7 -7
  48. package/docs/api/interfaces/TanakaExample.md +7 -7
  49. package/docs/api/interfaces/Translation.md +3 -3
  50. package/docs/api/interfaces/UsefulRegExps.md +8 -8
  51. package/docs/api/interfaces/Word.md +14 -14
  52. package/docs/api/type-aliases/Dict.md +1 -1
  53. package/docs/api/type-aliases/DictName.md +1 -1
  54. package/docs/api/type-aliases/EntryType.md +1 -1
  55. package/docs/api/type-aliases/JLPT.md +1 -1
  56. package/docs/api/type-aliases/Result.md +1 -1
  57. package/package.json +4 -4
package/README.md CHANGED
@@ -36,7 +36,7 @@ pnpm add henkan
36
36
  - JMdict, KANJIDIC, Tanaka Corpus, RADK and KRAD conversion
37
37
  - User-friendly schemas for dictionary entries
38
38
  - Anki note generation
39
- - Other useful tools (TTSFree.com audio generation, Japanese RegExps, array checking etc.)
39
+ - Other useful tools (Amazon Polly audio generation, Japanese RegExps, array checking etc.)
40
40
 
41
41
  ---
42
42
 
package/dist/index.cjs.js CHANGED
@@ -1134,7 +1134,7 @@ var noteMap = /* @__PURE__ */ new Map([
1134
1134
  var import_libxmljs2 = __toESM(require("libxmljs2"));
1135
1135
  var import_xml2js = __toESM(require("xml2js"));
1136
1136
  var import_iconv_lite = __toESM(require("iconv-lite"));
1137
- var import_node_fetch = __toESM(require("node-fetch"));
1137
+ var import_client_polly = require("@aws-sdk/client-polly");
1138
1138
  var Kuroshiro = require("kuroshiro");
1139
1139
  var KuromojiAnalyzer = require("kuroshiro-analyzer-kuromoji");
1140
1140
  function capitalizeString(value) {
@@ -1722,7 +1722,7 @@ function getWord(dict, id, kanjiDic, examples, dictWord, noteTypeName, deckPath)
1722
1722
  )) && (word.common === void 0 || reading.common === true)
1723
1723
  ).map((reading) => reading.reading)
1724
1724
  );
1725
- const kanjiForms = word.kanjiForms ? new Set(
1725
+ const kanjiForms = word.kanjiForms && word.kanjiForms.length > 0 ? new Set(
1726
1726
  word.kanjiForms.map(
1727
1727
  (kanjiForm) => kanjiForm.kanjiForm
1728
1728
  )
@@ -1730,56 +1730,49 @@ function getWord(dict, id, kanjiDic, examples, dictWord, noteTypeName, deckPath)
1730
1730
  const kanjiFormExamples = [];
1731
1731
  const readingMatchingKanjiFormExamples = [];
1732
1732
  const readingExamples = [];
1733
- const partParts = /* @__PURE__ */ new Set();
1734
1733
  for (const example of examples)
1735
- for (const part of example.parts) {
1736
- const readingAsReadingMatch = part.reading !== void 0 && readings.has(part.reading) || part.inflectedForm !== void 0 && readings.has(part.inflectedForm);
1737
- if (kanjiForms && kanjiForms.size > 0 && kanjiForms.has(part.baseForm)) {
1738
- if (readingAsReadingMatch) {
1739
- readingMatchingKanjiFormExamples.push(example);
1740
- partParts.add(part.baseForm).add(part.reading);
1741
- } else {
1742
- kanjiFormExamples.push(example);
1743
- partParts.add(part.baseForm);
1744
- }
1734
+ for (let i = 0; i < example.parts.length; i++) {
1735
+ const part = example.parts[i];
1736
+ const readingAsReadingMatch = part.reading !== void 0 && readings.has(part.reading);
1737
+ const readingAsInflectedFormMatch = part.inflectedForm !== void 0 && readings.has(part.inflectedForm);
1738
+ const referenceIDMatch = part.referenceID !== void 0 && word.id !== void 0 && part.referenceID === word.id;
1739
+ if (kanjiForms && kanjiForms.has(part.baseForm) || referenceIDMatch) {
1740
+ if (readingAsReadingMatch || readingAsInflectedFormMatch)
1741
+ readingMatchingKanjiFormExamples.push({
1742
+ ex: example,
1743
+ partIndex: i
1744
+ });
1745
+ else kanjiFormExamples.push({ ex: example, partIndex: i });
1745
1746
  break;
1746
1747
  }
1747
1748
  const readingAsBaseFormMatch = readings.has(part.baseForm);
1748
- const referenceIDMatch = part.referenceID !== void 0 && word.id !== void 0 && part.referenceID === word.id;
1749
- if (readingAsBaseFormMatch || referenceIDMatch) {
1750
- readingExamples.push(example);
1751
- if (readingAsBaseFormMatch) partParts.add(part.baseForm);
1752
- if (referenceIDMatch) partParts.add(part.referenceID);
1749
+ if ((readingAsBaseFormMatch || referenceIDMatch) && kanjiForms === void 0) {
1750
+ readingExamples.push({ ex: example, partIndex: i });
1753
1751
  break;
1754
1752
  }
1755
1753
  }
1756
- const exampleSize = readingMatchingKanjiFormExamples.length + kanjiFormExamples.length + readingExamples.length;
1757
- const includeReadingThreshold = Math.max(
1758
- 10,
1759
- Math.round(exampleSize * 0.5)
1760
- );
1761
1754
  const includeKanjiFormExamples = word.kanjiForms !== void 0;
1762
- const includeReadingExamples = readingExamples.length >= includeReadingThreshold && readingExamples.length >= readingMatchingKanjiFormExamples.length && readingExamples.length >= kanjiFormExamples.length || readingExamples.length >= includeReadingThreshold && word.usuallyInKana === true || word.kanjiForms === void 0;
1763
1755
  let wordExamples = [
1764
- ...readingMatchingKanjiFormExamples,
1765
- ...includeKanjiFormExamples ? kanjiFormExamples : [],
1766
- ...includeReadingExamples ? readingExamples : []
1756
+ ...includeKanjiFormExamples ? [...readingMatchingKanjiFormExamples, ...kanjiFormExamples] : [],
1757
+ ...!includeKanjiFormExamples ? readingExamples : []
1767
1758
  ];
1768
1759
  const glossSpecificExamples = [];
1769
1760
  const seenPhrases = /* @__PURE__ */ new Set();
1770
1761
  for (let i = 0; i < word.translations.length; i++) {
1771
1762
  outer: for (const example of wordExamples) {
1772
- if (seenPhrases.has(example.phrase)) continue;
1773
- for (const part of example.parts)
1774
- if (part.glossNumber === i + 1 && (partParts.has(part.baseForm) || includeReadingExamples && (part.reading && partParts.has(part.reading) || part.inflectedForm && partParts.has(part.inflectedForm) || part.referenceID && partParts.has(part.referenceID)))) {
1775
- example.glossNumber = {
1763
+ if (seenPhrases.has(example.ex.phrase)) continue;
1764
+ for (let j = 0; j < example.ex.parts.length; i++) {
1765
+ const part = example.ex.parts[j];
1766
+ if (j === example.partIndex && part.glossNumber === i + 1) {
1767
+ example.ex.glossNumber = {
1776
1768
  wordId: word.id,
1777
1769
  glossNumber: i + 1
1778
1770
  };
1779
1771
  glossSpecificExamples.push(example);
1780
- seenPhrases.add(example.phrase);
1772
+ seenPhrases.add(example.ex.phrase);
1781
1773
  break outer;
1782
1774
  }
1775
+ }
1783
1776
  }
1784
1777
  if (glossSpecificExamples.length === 5) break;
1785
1778
  }
@@ -1788,16 +1781,18 @@ function getWord(dict, id, kanjiDic, examples, dictWord, noteTypeName, deckPath)
1788
1781
  else if (glossSpecificExamples.length > 0)
1789
1782
  wordExamples = [
1790
1783
  ...glossSpecificExamples,
1791
- ...wordExamples.filter((ex) => !seenPhrases.has(ex.phrase)).slice(0, 5 - glossSpecificExamples.length)
1784
+ ...wordExamples.filter(
1785
+ (ex) => !seenPhrases.has(ex.ex.phrase)
1786
+ ).slice(0, 5 - glossSpecificExamples.length)
1792
1787
  ];
1793
1788
  if (wordExamples.length > 0)
1794
1789
  word.phrases = (wordExamples.length > 5 ? wordExamples.slice(0, 5) : wordExamples).map((ex) => {
1795
1790
  var _a;
1796
1791
  return {
1797
- phrase: (_a = ex.furigana) != null ? _a : ex.phrase,
1798
- translation: ex.translation,
1799
- originalPhrase: ex.phrase,
1800
- ...ex.glossNumber ? { glossNumber: ex.glossNumber } : {}
1792
+ phrase: (_a = ex.ex.furigana) != null ? _a : ex.ex.phrase,
1793
+ translation: ex.ex.translation,
1794
+ originalPhrase: ex.ex.phrase,
1795
+ ...ex.ex.glossNumber ? { glossNumber: ex.ex.glossNumber } : {}
1801
1796
  };
1802
1797
  });
1803
1798
  }
@@ -2002,34 +1997,17 @@ function getKanjiExtended(kanjiChar, info, dict, useJpdbWords, jmDict, svgList,
2002
1997
  throw err;
2003
1998
  }
2004
1999
  }
2005
- async function synthesizeSpeech(textOrSSML, apiKey, options) {
2000
+ async function synthesizeSpeech(client, input, options) {
2006
2001
  return await new Promise(
2007
2002
  async (resolve, reject) => {
2008
2003
  try {
2009
- const res = await (0, import_node_fetch.default)("https://ttsfree.com/api/v1/tts", {
2010
- method: "POST",
2011
- body: JSON.stringify({
2012
- text: textOrSSML,
2013
- ...options
2014
- }),
2015
- headers: {
2016
- "Content-Type": "application/json",
2017
- apikey: apiKey
2018
- }
2004
+ const command = new import_client_polly.SynthesizeSpeechCommand({
2005
+ Text: input,
2006
+ ...options
2019
2007
  });
2020
- if (!res.ok)
2021
- throw new Error(
2022
- `TTS request failed:
2023
- ${res.status}: ${res.statusText}`
2024
- );
2025
- const data = await res.json();
2026
- if (data.status !== "success" || data.mess !== "success" || data.audioData.length === 0)
2027
- throw new Error("Invalid TTS response data");
2028
- const mp3Buffer = Buffer.from(
2029
- data.audioData,
2030
- "base64"
2031
- );
2032
- resolve(mp3Buffer);
2008
+ const response = await client.send(command);
2009
+ const stream = response.AudioStream ? Buffer.from(await response.AudioStream.transformToByteArray()) : null;
2010
+ resolve(stream);
2033
2011
  } catch (err) {
2034
2012
  reject(err);
2035
2013
  }
@@ -2052,7 +2030,7 @@ function isGrammar(entry) {
2052
2030
  return entry.point !== void 0 && entry.meaning !== void 0;
2053
2031
  }
2054
2032
  var createNotes = (notes, phrase) => `${phrase === true ? "<details><summary>Show translation</summary>" : ""}<ul class="note-list">${notes.map((note) => `<li class="note">${note}</li>`).join("")}</ul>${phrase === true ? "</details>" : ""}`;
2055
- var createEntry = (entry, notes, phrase) => `<div class="entry">${entry}${notes && notes.length > 0 ? createNotes(notes, phrase) : ""}</div>`;
2033
+ var createEntry = (entry, notes, phrase, glossSpecific) => `<div class="entry${glossSpecific ? " gloss-specific" : ""}">${entry}${notes && notes.length > 0 ? createNotes(notes, phrase) : ""}</div>`;
2056
2034
  var noKanjiForms = '<span class="word word-kanjiform">(no kanji forms)</span>';
2057
2035
  function generateAnkiNote(entry) {
2058
2036
  if (!entry.noteID) throw new Error("Invalid note ID");
@@ -2076,7 +2054,7 @@ function generateAnkiNote(entry) {
2076
2054
  ).join("") : noKanjiForms
2077
2055
  ],
2078
2056
  entry.translations.map(
2079
- (translationEntry, index) => `<span class="word word-index${entry.phrases && entry.phrases.some((phrase, index2) => index === index2 && phrase.glossNumber && phrase.glossNumber.wordId === entry.id && phrase.glossNumber.glossNumber === index + 1) ? " gloss-specific" : ""}">${index + 1}</span>${index > 2 ? "<details><summary>Show translation</summary>" : ""}${createEntry(`<span class="word word-translation">${translationEntry.translation}</span>`, translationEntry.notes)}${index > 2 ? "</details>" : ""}`
2057
+ (translationEntry, index) => `${index > 2 ? "<details><summary>Show translation</summary>" : ""}${createEntry(`<span class="word word-translation">${translationEntry.translation}</span>`, translationEntry.notes, void 0, entry.phrases && entry.phrases.some((phrase, index2) => index === index2 && phrase.glossNumber && phrase.glossNumber.wordId === entry.id && phrase.glossNumber.glossNumber === index + 1) ? true : void 0)}${index > 2 ? "</details>" : ""}`
2080
2058
  ).join(""),
2081
2059
  entry.kanji ? entry.kanji.map(
2082
2060
  (kanjiEntry) => createEntry(
@@ -2085,11 +2063,14 @@ function generateAnkiNote(entry) {
2085
2063
  )
2086
2064
  ).join("") : '<span class="word word-kanji">(no kanji)</span>',
2087
2065
  entry.phrases ? entry.phrases.map(
2088
- (phraseEntry, index) => `<span class="word word-index${entry.translations.some((_translation, index2) => index === index2 && phraseEntry.glossNumber && phraseEntry.glossNumber.wordId === entry.id && phraseEntry.glossNumber.glossNumber === index2 + 1) ? " gloss-specific" : ""}">${index + 1}</span>${createEntry(
2066
+ (phraseEntry, index) => createEntry(
2089
2067
  `<span class="word word-phrase"><span class="word word-phrase-original">${phraseEntry.originalPhrase}</span><span class="word word-phrase-furigana">${phraseEntry.phrase}</span></span>`,
2090
2068
  [phraseEntry.translation],
2091
- true
2092
- )}`
2069
+ true,
2070
+ entry.translations.some(
2071
+ (_translation, index2) => index === index2 && phraseEntry.glossNumber && phraseEntry.glossNumber.wordId === entry.id && phraseEntry.glossNumber.glossNumber === index2 + 1
2072
+ ) ? true : void 0
2073
+ )
2093
2074
  ).join("") : '<span class="word word-phrase">(no phrases) (Search on dictionaries!)</span>',
2094
2075
  ...entry.tags && entry.tags.length > 0 ? [
2095
2076
  entry.tags.map(