henkan 0.6.1 → 0.8.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.
- package/README.md +4 -2
- package/dist/index.cjs.js +53 -165
- package/dist/index.cjs.js.map +3 -3
- package/dist/index.mjs +53 -163
- package/dist/index.mjs.map +2 -2
- package/dist/types/constants.d.ts +0 -3
- package/dist/types/constants.d.ts.map +1 -1
- package/dist/types/types.d.ts +21 -6
- package/dist/types/types.d.ts.map +1 -1
- package/dist/types/utils.d.ts +10 -14
- package/dist/types/utils.d.ts.map +1 -1
- package/docs/api/README.md +1 -1
- package/docs/api/functions/capitalizeString.md +1 -1
- package/docs/api/functions/convertJMdict.md +1 -1
- package/docs/api/functions/convertKanjiDic.md +1 -1
- package/docs/api/functions/convertKradFile.md +1 -1
- package/docs/api/functions/convertRadkFile.md +1 -1
- package/docs/api/functions/convertTanakaCorpus.md +1 -1
- package/docs/api/functions/generateAnkiNote.md +1 -1
- package/docs/api/functions/generateAnkiNotesFile.md +1 -1
- package/docs/api/functions/getKanji.md +1 -1
- package/docs/api/functions/getKanjiExtended.md +1 -1
- package/docs/api/functions/getWord.md +1 -1
- package/docs/api/functions/isStringArray.md +1 -1
- package/docs/api/functions/isValidArray.md +1 -1
- package/docs/api/functions/isValidArrayWithFirstElement.md +1 -1
- package/docs/api/functions/shuffleArray.md +1 -1
- package/docs/api/functions/synthesizeSpeech.md +25 -13
- package/docs/api/interfaces/DictKanji.md +5 -5
- package/docs/api/interfaces/DictKanjiForm.md +4 -4
- package/docs/api/interfaces/DictKanjiMisc.md +5 -5
- package/docs/api/interfaces/DictKanjiReading.md +3 -3
- package/docs/api/interfaces/DictKanjiReadingMeaning.md +3 -3
- package/docs/api/interfaces/DictKanjiReadingMeaningGroup.md +3 -3
- package/docs/api/interfaces/DictKanjiWithRadicals.md +3 -3
- package/docs/api/interfaces/DictMeaning.md +11 -11
- package/docs/api/interfaces/DictRadical.md +4 -4
- package/docs/api/interfaces/DictReading.md +5 -5
- package/docs/api/interfaces/DictWord.md +8 -8
- package/docs/api/interfaces/ExamplePart.md +7 -7
- package/docs/api/interfaces/GlossSpecificNumber.md +31 -0
- package/docs/api/interfaces/Grammar.md +15 -15
- package/docs/api/interfaces/GrammarMeaning.md +3 -3
- package/docs/api/interfaces/Kana.md +11 -11
- package/docs/api/interfaces/Kanji.md +22 -22
- package/docs/api/interfaces/KanjiComponent.md +3 -3
- package/docs/api/interfaces/KanjiForm.md +4 -4
- package/docs/api/interfaces/NoteAndTag.md +3 -3
- package/docs/api/interfaces/Phrase.md +16 -4
- package/docs/api/interfaces/Radical.md +16 -16
- package/docs/api/interfaces/Reading.md +5 -5
- package/docs/api/interfaces/ResultEntry.md +7 -7
- package/docs/api/interfaces/TanakaExample.md +16 -6
- package/docs/api/interfaces/Translation.md +3 -3
- package/docs/api/interfaces/UsefulRegExps.md +8 -20
- package/docs/api/interfaces/Word.md +14 -14
- package/docs/api/type-aliases/Dict.md +1 -1
- package/docs/api/type-aliases/DictName.md +1 -1
- package/docs/api/type-aliases/EntryType.md +1 -1
- package/docs/api/type-aliases/JLPT.md +1 -1
- package/docs/api/type-aliases/Result.md +1 -1
- package/package.json +5 -5
- package/docs/api/functions/makeSSML.md +0 -33
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 (
|
|
39
|
+
- Other useful tools (TTSFree.com audio generation, Japanese RegExps, array checking etc.)
|
|
40
40
|
|
|
41
41
|
---
|
|
42
42
|
|
|
@@ -55,12 +55,14 @@ const dictContent = fs.readFileSync(dictPath, 'utf-8');
|
|
|
55
55
|
|
|
56
56
|
const dictWords = convertJMdict(dictContent);
|
|
57
57
|
|
|
58
|
+
const jmDict = undefined, id = undefined, kanjiDic = undefined, tanakaCorpus = undefined;
|
|
59
|
+
|
|
58
60
|
const noteTypeName = 'Word';
|
|
59
61
|
const deckName = 'Japanese::Vocabulary::No kanji form words';
|
|
60
62
|
|
|
61
63
|
const noKanjiFormWords = dictWords
|
|
62
64
|
.filter(word => word.kanjiForms === undefined)
|
|
63
|
-
.map(word => getWord(
|
|
65
|
+
.map(word => getWord(jmDict, id, kanjiDic, tanakaCorpus, word, noteTypeName, deckName));
|
|
64
66
|
|
|
65
67
|
const ankiNotesFile = generateAnkiNotesFile(noKanjiFormWords);
|
|
66
68
|
|
package/dist/index.cjs.js
CHANGED
|
@@ -49,14 +49,10 @@ __export(index_exports, {
|
|
|
49
49
|
isValidArray: () => isValidArray,
|
|
50
50
|
isValidArrayWithFirstElement: () => isValidArrayWithFirstElement,
|
|
51
51
|
isWord: () => isWord,
|
|
52
|
-
makeSSML: () => makeSSML,
|
|
53
52
|
notSearchedForms: () => notSearchedForms,
|
|
54
53
|
noteMap: () => noteMap,
|
|
55
|
-
numberMap: () => numberMap,
|
|
56
54
|
regexps: () => regexps,
|
|
57
|
-
romajiMap: () => romajiMap,
|
|
58
55
|
shuffleArray: () => shuffleArray,
|
|
59
|
-
symbolMap: () => symbolMap,
|
|
60
56
|
synthesizeSpeech: () => synthesizeSpeech
|
|
61
57
|
});
|
|
62
58
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -66,60 +62,11 @@ var regexps = {
|
|
|
66
62
|
hiragana: /[\u{3040}-\u{309F}]/u,
|
|
67
63
|
katakana: /[\u{30A0}-\u{30FF}]/u,
|
|
68
64
|
kanji: new RegExp("\\p{Script=Han}+", "u"),
|
|
69
|
-
scriptSplit: /([\p{sc=Han}]+|[\p{sc=Hiragana}]+|[\p{sc=Katakana}]+|[^\p{sc=Han}\p{sc=Hiragana}\p{sc=Katakana}]+)/u,
|
|
70
65
|
regExChars: /[-\/\\^$*+?.()|[\]{}]/,
|
|
71
66
|
tanakaID: /#ID=(?<id>\d+_\d+)$/,
|
|
72
67
|
tanakaPart: /(?<base>[^()\[\]\{\}\s]+)(?:\((?<reading>[\S]+)\))?(?:\[(?<glossnum>[\S]+)\])?(?:\{(?<inflection>[\S]+)\})?/,
|
|
73
68
|
tanakaReferenceID: /#(?<entryid>[\d]+)/
|
|
74
69
|
};
|
|
75
|
-
var romajiMap = {
|
|
76
|
-
A: "\u30A8\u30FC",
|
|
77
|
-
B: "\u30D3\u30FC",
|
|
78
|
-
C: "\u30B7\u30FC",
|
|
79
|
-
D: "\u30C7\u30A3\u30FC",
|
|
80
|
-
E: "\u30A4\u30FC",
|
|
81
|
-
F: "\u30A8\u30D5",
|
|
82
|
-
G: "\u30B8\u30FC",
|
|
83
|
-
H: "\u30A8\u30A4\u30C1",
|
|
84
|
-
I: "\u30A2\u30A4",
|
|
85
|
-
J: "\u30B8\u30A7\u30FC",
|
|
86
|
-
K: "\u30B1\u30FC",
|
|
87
|
-
L: "\u30A8\u30EB",
|
|
88
|
-
M: "\u30A8\u30E0",
|
|
89
|
-
N: "\u30A8\u30CC",
|
|
90
|
-
O: "\u30AA\u30FC",
|
|
91
|
-
P: "\u30D4\u30FC",
|
|
92
|
-
Q: "\u30AD\u30E5\u30FC",
|
|
93
|
-
R: "\u30A2\u30FC\u30EB",
|
|
94
|
-
S: "\u30A8\u30B9",
|
|
95
|
-
T: "\u30C6\u30A3\u30FC",
|
|
96
|
-
U: "\u30E6\u30FC",
|
|
97
|
-
V: "\u30D6\u30A4",
|
|
98
|
-
W: "\u30C0\u30D6\u30EA\u30E5\u30FC",
|
|
99
|
-
X: "\u30A8\u30C3\u30AF\u30B9",
|
|
100
|
-
Y: "\u30EF\u30A4",
|
|
101
|
-
Z: "\u30BC\u30C3\u30C8"
|
|
102
|
-
};
|
|
103
|
-
var numberMap = {
|
|
104
|
-
"0": "\u30BC\u30ED",
|
|
105
|
-
"1": "\u30A4\u30C1",
|
|
106
|
-
"2": "\u30CB",
|
|
107
|
-
"3": "\u30B5\u30F3",
|
|
108
|
-
"4": "\u30E8\u30F3",
|
|
109
|
-
"5": "\u30B4",
|
|
110
|
-
"6": "\u30ED\u30AF",
|
|
111
|
-
"7": "\u30CA\u30CA",
|
|
112
|
-
"8": "\u30CF\u30C1",
|
|
113
|
-
"9": "\u30AD\u30E5\u30A6"
|
|
114
|
-
};
|
|
115
|
-
var symbolMap = {
|
|
116
|
-
"\uFF04": "\u30C9\u30EB",
|
|
117
|
-
"%": "\u30D1\u30FC\u30BB\u30F3\u30C8",
|
|
118
|
-
"\xA5": "\u30A8\u30F3",
|
|
119
|
-
"#": "\u30B7\u30E3\u30FC\u30D7",
|
|
120
|
-
"@": "\u30A2\u30C3\u30C8",
|
|
121
|
-
"&": "\u30A2\u30F3\u30C9"
|
|
122
|
-
};
|
|
123
70
|
var notSearchedForms = /* @__PURE__ */ new Set([
|
|
124
71
|
"search-only kana form",
|
|
125
72
|
"Search-only kana form",
|
|
@@ -1187,7 +1134,7 @@ var noteMap = /* @__PURE__ */ new Map([
|
|
|
1187
1134
|
var import_libxmljs2 = __toESM(require("libxmljs2"));
|
|
1188
1135
|
var import_xml2js = __toESM(require("xml2js"));
|
|
1189
1136
|
var import_iconv_lite = __toESM(require("iconv-lite"));
|
|
1190
|
-
var
|
|
1137
|
+
var import_node_fetch = __toESM(require("node-fetch"));
|
|
1191
1138
|
var Kuroshiro = require("kuroshiro");
|
|
1192
1139
|
var KuromojiAnalyzer = require("kuroshiro-analyzer-kuromoji");
|
|
1193
1140
|
function capitalizeString(value) {
|
|
@@ -1333,11 +1280,9 @@ function convertJMdict(xmlString, examples) {
|
|
|
1333
1280
|
).map((reading) => reading.reading)
|
|
1334
1281
|
);
|
|
1335
1282
|
const kanjiForms2 = entryObj.kanjiForms ? new Set(
|
|
1336
|
-
entryObj.kanjiForms.
|
|
1337
|
-
(kanjiForm) =>
|
|
1338
|
-
|
|
1339
|
-
)) && (entryObj.isCommon === void 0 || kanjiForm.commonness && kanjiForm.commonness.length > 0)
|
|
1340
|
-
).map((kanjiForm) => kanjiForm.form)
|
|
1283
|
+
entryObj.kanjiForms.map(
|
|
1284
|
+
(kanjiForm) => kanjiForm.form
|
|
1285
|
+
)
|
|
1341
1286
|
) : void 0;
|
|
1342
1287
|
let existsExample = false;
|
|
1343
1288
|
if (kanjiForms2 && kanjiForms2.size > 0 && tanakaParts) {
|
|
@@ -1519,9 +1464,9 @@ function convertRadkFile(radkBuffer, kanjiDic) {
|
|
|
1519
1464
|
try {
|
|
1520
1465
|
const fileParsed = import_iconv_lite.default.decode(radkBuffer, "euc-jp").split("\n").filter((line) => !line.startsWith("#"));
|
|
1521
1466
|
const radicals = [];
|
|
1522
|
-
for (let i = 0; i
|
|
1467
|
+
for (let i = 0; i < fileParsed.length; i++) {
|
|
1523
1468
|
const line = fileParsed[i];
|
|
1524
|
-
if (!line)
|
|
1469
|
+
if (!line) continue;
|
|
1525
1470
|
if (line.startsWith("$ ")) {
|
|
1526
1471
|
const radical = {
|
|
1527
1472
|
radical: line.charAt(2).trim(),
|
|
@@ -1529,7 +1474,7 @@ function convertRadkFile(radkBuffer, kanjiDic) {
|
|
|
1529
1474
|
};
|
|
1530
1475
|
let j = i + 1;
|
|
1531
1476
|
let kanjiLine = fileParsed[j];
|
|
1532
|
-
if (!kanjiLine)
|
|
1477
|
+
if (!kanjiLine) continue;
|
|
1533
1478
|
const kanjiList = [];
|
|
1534
1479
|
while (kanjiLine && !kanjiLine.startsWith("$ ")) {
|
|
1535
1480
|
const kanjis = kanjiLine.split("");
|
|
@@ -1565,8 +1510,7 @@ function convertKradFile(kradBuffer, kanjiDic, katakanaList) {
|
|
|
1565
1510
|
const split = line.split(" : ");
|
|
1566
1511
|
const kanjiChar = split[0];
|
|
1567
1512
|
const radicalsRow = split[1];
|
|
1568
|
-
if (!kanjiChar || !radicalsRow)
|
|
1569
|
-
throw new Error("Invalid kradfile2 buffer");
|
|
1513
|
+
if (!kanjiChar || !radicalsRow) continue;
|
|
1570
1514
|
const kanji = {
|
|
1571
1515
|
...kanjiChar && radicalsRow && kanjiChar.length === 1 && radicalsRow.length > 0 ? { kanji: kanjiChar } : { kanji: "" },
|
|
1572
1516
|
radicals: []
|
|
@@ -1779,11 +1723,9 @@ function getWord(dict, id, kanjiDic, examples, dictWord, noteTypeName, deckPath)
|
|
|
1779
1723
|
).map((reading) => reading.reading)
|
|
1780
1724
|
);
|
|
1781
1725
|
const kanjiForms = word.kanjiForms ? new Set(
|
|
1782
|
-
word.kanjiForms.
|
|
1783
|
-
(kanjiForm) =>
|
|
1784
|
-
|
|
1785
|
-
)) && (word.common === void 0 || kanjiForm.common === true)
|
|
1786
|
-
).map((kanjiForm) => kanjiForm.kanjiForm)
|
|
1726
|
+
word.kanjiForms.map(
|
|
1727
|
+
(kanjiForm) => kanjiForm.kanjiForm
|
|
1728
|
+
)
|
|
1787
1729
|
) : void 0;
|
|
1788
1730
|
const kanjiFormExamples = [];
|
|
1789
1731
|
const readingMatchingKanjiFormExamples = [];
|
|
@@ -1791,7 +1733,7 @@ function getWord(dict, id, kanjiDic, examples, dictWord, noteTypeName, deckPath)
|
|
|
1791
1733
|
const partParts = /* @__PURE__ */ new Set();
|
|
1792
1734
|
for (const example of examples)
|
|
1793
1735
|
for (const part of example.parts) {
|
|
1794
|
-
const readingAsReadingMatch = part.reading !== void 0 && readings.has(part.reading);
|
|
1736
|
+
const readingAsReadingMatch = part.reading !== void 0 && readings.has(part.reading) || part.inflectedForm !== void 0 && readings.has(part.inflectedForm);
|
|
1795
1737
|
if (kanjiForms && kanjiForms.size > 0 && kanjiForms.has(part.baseForm)) {
|
|
1796
1738
|
if (readingAsReadingMatch) {
|
|
1797
1739
|
readingMatchingKanjiFormExamples.push(example);
|
|
@@ -1804,17 +1746,20 @@ function getWord(dict, id, kanjiDic, examples, dictWord, noteTypeName, deckPath)
|
|
|
1804
1746
|
}
|
|
1805
1747
|
const readingAsBaseFormMatch = readings.has(part.baseForm);
|
|
1806
1748
|
const referenceIDMatch = part.referenceID !== void 0 && word.id !== void 0 && part.referenceID === word.id;
|
|
1807
|
-
if (
|
|
1749
|
+
if (readingAsBaseFormMatch || referenceIDMatch) {
|
|
1808
1750
|
readingExamples.push(example);
|
|
1809
|
-
if (readingAsReadingMatch) partParts.add(part.reading);
|
|
1810
1751
|
if (readingAsBaseFormMatch) partParts.add(part.baseForm);
|
|
1811
1752
|
if (referenceIDMatch) partParts.add(part.referenceID);
|
|
1812
1753
|
break;
|
|
1813
1754
|
}
|
|
1814
1755
|
}
|
|
1815
1756
|
const exampleSize = readingMatchingKanjiFormExamples.length + kanjiFormExamples.length + readingExamples.length;
|
|
1816
|
-
const
|
|
1817
|
-
|
|
1757
|
+
const includeReadingThreshold = Math.max(
|
|
1758
|
+
10,
|
|
1759
|
+
Math.round(exampleSize * 0.5)
|
|
1760
|
+
);
|
|
1761
|
+
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;
|
|
1818
1763
|
let wordExamples = [
|
|
1819
1764
|
...readingMatchingKanjiFormExamples,
|
|
1820
1765
|
...includeKanjiFormExamples ? kanjiFormExamples : [],
|
|
@@ -1826,7 +1771,11 @@ function getWord(dict, id, kanjiDic, examples, dictWord, noteTypeName, deckPath)
|
|
|
1826
1771
|
outer: for (const example of wordExamples) {
|
|
1827
1772
|
if (seenPhrases.has(example.phrase)) continue;
|
|
1828
1773
|
for (const part of example.parts)
|
|
1829
|
-
if (part.glossNumber === i + 1 && (partParts.has(part.baseForm) || part.reading && partParts.has(part.reading) || part.referenceID && partParts.has(part.referenceID))) {
|
|
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 = {
|
|
1776
|
+
wordId: word.id,
|
|
1777
|
+
glossNumber: i + 1
|
|
1778
|
+
};
|
|
1830
1779
|
glossSpecificExamples.push(example);
|
|
1831
1780
|
seenPhrases.add(example.phrase);
|
|
1832
1781
|
break outer;
|
|
@@ -1847,7 +1796,8 @@ function getWord(dict, id, kanjiDic, examples, dictWord, noteTypeName, deckPath)
|
|
|
1847
1796
|
return {
|
|
1848
1797
|
phrase: (_a = ex.furigana) != null ? _a : ex.phrase,
|
|
1849
1798
|
translation: ex.translation,
|
|
1850
|
-
originalPhrase: ex.phrase
|
|
1799
|
+
originalPhrase: ex.phrase,
|
|
1800
|
+
...ex.glossNumber ? { glossNumber: ex.glossNumber } : {}
|
|
1851
1801
|
};
|
|
1852
1802
|
});
|
|
1853
1803
|
}
|
|
@@ -2052,92 +2002,34 @@ function getKanjiExtended(kanjiChar, info, dict, useJpdbWords, jmDict, svgList,
|
|
|
2052
2002
|
throw err;
|
|
2053
2003
|
}
|
|
2054
2004
|
}
|
|
2055
|
-
|
|
2056
|
-
if (regexps.kanji.test(char)) return "kanji";
|
|
2057
|
-
if (regexps.hiragana.test(char)) return "hiragana";
|
|
2058
|
-
if (regexps.katakana.test(char)) return "katakana";
|
|
2059
|
-
return "other";
|
|
2060
|
-
};
|
|
2061
|
-
var splitByScript = (text) => text.match(regexps.scriptSplit) || [];
|
|
2062
|
-
var convertToHiragana = (str) => str.replace(
|
|
2063
|
-
regexps.katakana,
|
|
2064
|
-
(c) => String.fromCharCode(c.charCodeAt(0) - 96)
|
|
2065
|
-
);
|
|
2066
|
-
var convertOtherToKatakana = (str) => str.split("").map((c) => {
|
|
2067
|
-
if (romajiMap[c.toUpperCase()]) return romajiMap[c.toUpperCase()];
|
|
2068
|
-
if (numberMap[c]) return numberMap[c];
|
|
2069
|
-
if (symbolMap[c]) return symbolMap[c];
|
|
2070
|
-
return c;
|
|
2071
|
-
}).join("");
|
|
2072
|
-
function makeSSML(formText, fullReading) {
|
|
2073
|
-
let ssml = "";
|
|
2074
|
-
const allTypes = Array.from(
|
|
2075
|
-
formText
|
|
2076
|
-
).map((c) => getCharType(c));
|
|
2077
|
-
const uniqueTypes = Array.from(new Set(allTypes));
|
|
2078
|
-
if (uniqueTypes.length === 1)
|
|
2079
|
-
switch (uniqueTypes[0]) {
|
|
2080
|
-
case "kanji":
|
|
2081
|
-
ssml = `<speak><phoneme alphabet="x-amazon-yomigana" ph="${fullReading}">${formText}</phoneme></speak>`;
|
|
2082
|
-
break;
|
|
2083
|
-
case "katakana":
|
|
2084
|
-
ssml = `<speak><phoneme alphabet="x-amazon-pron-kana" ph="${formText}">${formText}</phoneme></speak>`;
|
|
2085
|
-
break;
|
|
2086
|
-
case "hiragana":
|
|
2087
|
-
default:
|
|
2088
|
-
ssml = `<speak>${formText}</speak>`;
|
|
2089
|
-
}
|
|
2090
|
-
else {
|
|
2091
|
-
const segments = splitByScript(formText);
|
|
2092
|
-
let pureKanjiReading = convertToHiragana(fullReading);
|
|
2093
|
-
segments.forEach((seg) => {
|
|
2094
|
-
const type = getCharType(
|
|
2095
|
-
seg[0]
|
|
2096
|
-
);
|
|
2097
|
-
if (type !== "kanji") {
|
|
2098
|
-
const converted = type === "other" ? convertToHiragana(convertOtherToKatakana(seg)) : convertToHiragana(seg);
|
|
2099
|
-
pureKanjiReading = pureKanjiReading.replace(converted, "");
|
|
2100
|
-
}
|
|
2101
|
-
});
|
|
2102
|
-
const kanjiSegments = segments.filter(
|
|
2103
|
-
(seg) => getCharType(seg[0]) === "kanji"
|
|
2104
|
-
);
|
|
2105
|
-
let readingPointer = 0;
|
|
2106
|
-
const ssmlSegments = segments.map((seg) => {
|
|
2107
|
-
const type = getCharType(
|
|
2108
|
-
seg[0]
|
|
2109
|
-
);
|
|
2110
|
-
if (type === "kanji") {
|
|
2111
|
-
const expectedLength = pureKanjiReading.length / kanjiSegments.length;
|
|
2112
|
-
const allocated = pureKanjiReading.slice(
|
|
2113
|
-
readingPointer,
|
|
2114
|
-
readingPointer + Math.ceil(expectedLength)
|
|
2115
|
-
);
|
|
2116
|
-
readingPointer += allocated.length;
|
|
2117
|
-
return `<phoneme alphabet="x-amazon-yomigana" ph="${allocated}">${seg}</phoneme>`;
|
|
2118
|
-
} else if (type === "katakana")
|
|
2119
|
-
return `<phoneme alphabet="x-amazon-pron-kana" ph="${seg}">${seg}</phoneme>`;
|
|
2120
|
-
else if (type === "other") {
|
|
2121
|
-
const katakanaReading = convertOtherToKatakana(seg);
|
|
2122
|
-
return `<phoneme alphabet="x-amazon-pron-kana" ph="${katakanaReading}">${seg}</phoneme>`;
|
|
2123
|
-
} else return seg;
|
|
2124
|
-
});
|
|
2125
|
-
ssml = `<speak>${ssmlSegments.join("")}</speak>`;
|
|
2126
|
-
}
|
|
2127
|
-
return ssml;
|
|
2128
|
-
}
|
|
2129
|
-
async function synthesizeSpeech(client, ssmlText, options) {
|
|
2005
|
+
async function synthesizeSpeech(textOrSSML, apiKey, options) {
|
|
2130
2006
|
return await new Promise(
|
|
2131
2007
|
async (resolve, reject) => {
|
|
2132
2008
|
try {
|
|
2133
|
-
const
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
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
|
+
}
|
|
2137
2019
|
});
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
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);
|
|
2141
2033
|
} catch (err) {
|
|
2142
2034
|
reject(err);
|
|
2143
2035
|
}
|
|
@@ -2184,7 +2076,7 @@ function generateAnkiNote(entry) {
|
|
|
2184
2076
|
).join("") : noKanjiForms
|
|
2185
2077
|
],
|
|
2186
2078
|
entry.translations.map(
|
|
2187
|
-
(translationEntry, index) =>
|
|
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>" : ""}`
|
|
2188
2080
|
).join(""),
|
|
2189
2081
|
entry.kanji ? entry.kanji.map(
|
|
2190
2082
|
(kanjiEntry) => createEntry(
|
|
@@ -2193,11 +2085,11 @@ function generateAnkiNote(entry) {
|
|
|
2193
2085
|
)
|
|
2194
2086
|
).join("") : '<span class="word word-kanji">(no kanji)</span>',
|
|
2195
2087
|
entry.phrases ? entry.phrases.map(
|
|
2196
|
-
(phraseEntry) => createEntry(
|
|
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(
|
|
2197
2089
|
`<span class="word word-phrase"><span class="word word-phrase-original">${phraseEntry.originalPhrase}</span><span class="word word-phrase-furigana">${phraseEntry.phrase}</span></span>`,
|
|
2198
2090
|
[phraseEntry.translation],
|
|
2199
2091
|
true
|
|
2200
|
-
)
|
|
2092
|
+
)}`
|
|
2201
2093
|
).join("") : '<span class="word word-phrase">(no phrases) (Search on dictionaries!)</span>',
|
|
2202
2094
|
...entry.tags && entry.tags.length > 0 ? [
|
|
2203
2095
|
entry.tags.map(
|
|
@@ -2379,14 +2271,10 @@ ${ankiNotes}`;
|
|
|
2379
2271
|
isValidArray,
|
|
2380
2272
|
isValidArrayWithFirstElement,
|
|
2381
2273
|
isWord,
|
|
2382
|
-
makeSSML,
|
|
2383
2274
|
notSearchedForms,
|
|
2384
2275
|
noteMap,
|
|
2385
|
-
numberMap,
|
|
2386
2276
|
regexps,
|
|
2387
|
-
romajiMap,
|
|
2388
2277
|
shuffleArray,
|
|
2389
|
-
symbolMap,
|
|
2390
2278
|
synthesizeSpeech
|
|
2391
2279
|
});
|
|
2392
2280
|
//# sourceMappingURL=index.cjs.js.map
|