henkan 1.1.2 → 2.0.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 (51) hide show
  1. package/README.md +3 -3
  2. package/dist/index.cjs.js +1047 -1115
  3. package/dist/index.cjs.js.map +3 -3
  4. package/dist/index.mjs +1042 -1113
  5. package/dist/index.mjs.map +3 -3
  6. package/dist/types/constants.d.ts +3 -2
  7. package/dist/types/constants.d.ts.map +1 -1
  8. package/dist/types/types.d.ts +74 -15
  9. package/dist/types/types.d.ts.map +1 -1
  10. package/dist/types/utils.d.ts +51 -42
  11. package/dist/types/utils.d.ts.map +1 -1
  12. package/docs/api/README.md +6 -2
  13. package/docs/api/functions/capitalizeString.md +1 -1
  14. package/docs/api/functions/convertJMdict.md +2 -2
  15. package/docs/api/functions/convertJawiktionaryAsync.md +29 -0
  16. package/docs/api/functions/convertJawiktionarySync.md +29 -0
  17. package/docs/api/functions/convertKanjiDic.md +1 -1
  18. package/docs/api/functions/convertKradFile.md +3 -3
  19. package/docs/api/functions/convertRadkFile.md +2 -2
  20. package/docs/api/functions/convertTanakaCorpus.md +3 -9
  21. package/docs/api/functions/convertTanakaCorpusWithFurigana.md +27 -0
  22. package/docs/api/functions/generateAnkiNote.md +1 -1
  23. package/docs/api/functions/generateAnkiNotesFile.md +9 -3
  24. package/docs/api/functions/getKanji.md +13 -19
  25. package/docs/api/functions/getKanjiExtended.md +18 -18
  26. package/docs/api/functions/getWord.md +17 -23
  27. package/docs/api/functions/getWordDefinitions.md +6 -12
  28. package/docs/api/functions/getWordDefinitionsWithFurigana.md +33 -0
  29. package/docs/api/functions/isStringArray.md +1 -1
  30. package/docs/api/functions/isValidArray.md +1 -1
  31. package/docs/api/functions/isValidArrayWithFirstElement.md +1 -1
  32. package/docs/api/functions/shuffleArray.md +2 -2
  33. package/docs/api/interfaces/DefaultNoteInfo.md +51 -0
  34. package/docs/api/interfaces/DictKanjiMisc.md +2 -2
  35. package/docs/api/interfaces/DictKanjiReadingMeaning.md +2 -2
  36. package/docs/api/interfaces/DictKanjiReadingMeaningGroup.md +4 -4
  37. package/docs/api/interfaces/DictKanjiWithRadicals.md +2 -2
  38. package/docs/api/interfaces/DictWord.md +1 -1
  39. package/docs/api/interfaces/Grammar.md +2 -2
  40. package/docs/api/interfaces/Kana.md +2 -2
  41. package/docs/api/interfaces/Kanji.md +12 -12
  42. package/docs/api/interfaces/NoteAndTag.md +2 -2
  43. package/docs/api/interfaces/NoteHeaderKeys.md +75 -0
  44. package/docs/api/interfaces/Radical.md +5 -5
  45. package/docs/api/interfaces/ResultEntry.md +2 -2
  46. package/docs/api/interfaces/TanakaExample.md +1 -1
  47. package/docs/api/interfaces/UsefulRegExps.md +8 -8
  48. package/docs/api/interfaces/Word.md +2 -2
  49. package/package.json +11 -12
  50. package/docs/api/functions/convertJawiktionary.md +0 -29
  51. package/docs/api/functions/synthesizeSpeech.md +0 -39
package/dist/index.cjs.js CHANGED
@@ -32,17 +32,20 @@ var index_exports = {};
32
32
  __export(index_exports, {
33
33
  capitalizeString: () => capitalizeString,
34
34
  convertJMdict: () => convertJMdict,
35
- convertJawiktionary: () => convertJawiktionary,
35
+ convertJawiktionaryAsync: () => convertJawiktionaryAsync,
36
+ convertJawiktionarySync: () => convertJawiktionarySync,
36
37
  convertKanjiDic: () => convertKanjiDic,
37
38
  convertKradFile: () => convertKradFile,
38
39
  convertRadkFile: () => convertRadkFile,
39
40
  convertTanakaCorpus: () => convertTanakaCorpus,
41
+ convertTanakaCorpusWithFurigana: () => convertTanakaCorpusWithFurigana,
40
42
  generateAnkiNote: () => generateAnkiNote,
41
43
  generateAnkiNotesFile: () => generateAnkiNotesFile,
42
44
  getKanji: () => getKanji,
43
45
  getKanjiExtended: () => getKanjiExtended,
44
46
  getWord: () => getWord,
45
47
  getWordDefinitions: () => getWordDefinitions,
48
+ getWordDefinitionsWithFurigana: () => getWordDefinitionsWithFurigana,
46
49
  isGrammar: () => isGrammar,
47
50
  isKana: () => isKana,
48
51
  isKanji: () => isKanji,
@@ -52,10 +55,10 @@ __export(index_exports, {
52
55
  isValidArrayWithFirstElement: () => isValidArrayWithFirstElement,
53
56
  isWord: () => isWord,
54
57
  notSearchedForms: () => notSearchedForms,
58
+ noteHeaderKeys: () => noteHeaderKeys,
55
59
  noteMap: () => noteMap,
56
60
  regexps: () => regexps,
57
- shuffleArray: () => shuffleArray,
58
- synthesizeSpeech: () => synthesizeSpeech
61
+ shuffleArray: () => shuffleArray
59
62
  });
60
63
  module.exports = __toCommonJS(index_exports);
61
64
 
@@ -69,6 +72,14 @@ var regexps = {
69
72
  tanakaPart: /(?<base>[^()\[\]\{\}\s]+)(?:\((?<reading>[\S]+)\))?(?:\[(?<glossnum>[\S]+)\])?(?:\{(?<inflection>[\S]+)\})?/,
70
73
  tanakaReferenceID: /#(?<entryid>[\d]+)/
71
74
  };
75
+ var noteHeaderKeys = {
76
+ separator: "#separator:tab",
77
+ html: "#html:true",
78
+ guid: "#guid column:",
79
+ notetype: "#notetype column:",
80
+ deck: "#deck column:",
81
+ tags: "#tags column:"
82
+ };
72
83
  var notSearchedForms = /* @__PURE__ */ new Set([
73
84
  "search-only kana form",
74
85
  "Search-only kana form",
@@ -1225,7 +1236,6 @@ var noteMap = /* @__PURE__ */ new Map([
1225
1236
  var import_libxmljs2 = __toESM(require("libxmljs2"));
1226
1237
  var import_xml2js = __toESM(require("xml2js"));
1227
1238
  var import_iconv_lite = __toESM(require("iconv-lite"));
1228
- var import_client_polly = require("@aws-sdk/client-polly");
1229
1239
  var import_readline = require("readline");
1230
1240
  var Kuroshiro = require("kuroshiro");
1231
1241
  var KuromojiAnalyzer = require("kuroshiro-analyzer-kuromoji");
@@ -1242,29 +1252,25 @@ function isStringArray(arg) {
1242
1252
  return arg !== null && arg !== void 0 && Array.isArray(arg) && arg.every((element) => typeof element === "string");
1243
1253
  }
1244
1254
  function shuffleArray(arr) {
1245
- if (arr.length < 2) return arr;
1246
1255
  const a = arr.slice();
1247
1256
  for (let i = a.length - 1; i > 0; i--) {
1248
1257
  const j = Math.floor(Math.random() * (i + 1));
1249
1258
  const tmp = a[i];
1250
- const tmp2 = a[j];
1251
- if (!tmp || !tmp2) throw new Error("Invalid array");
1252
- a[i] = tmp2;
1259
+ a[i] = a[j];
1253
1260
  a[j] = tmp;
1254
1261
  }
1255
1262
  return a;
1256
1263
  }
1257
1264
  function convertJMdict(xmlString, examples) {
1258
- try {
1259
- const dictParsed = import_libxmljs2.default.parseXml(xmlString, {
1260
- dtdvalid: true,
1261
- nonet: false,
1262
- noent: true,
1263
- recover: false
1264
- });
1265
- const dict = [];
1266
- import_xml2js.default.parseString(dictParsed, (err, result) => {
1267
- if (err) throw err;
1265
+ const dictParsed = import_libxmljs2.default.parseXml(xmlString, {
1266
+ dtdvalid: true,
1267
+ nonet: false,
1268
+ noent: true,
1269
+ recover: false
1270
+ });
1271
+ const dict = [];
1272
+ import_xml2js.default.parseString(dictParsed, (err, result) => {
1273
+ if (err === null) {
1268
1274
  const tanakaParts = examples && examples.length > 0 ? new Set(
1269
1275
  examples.map(
1270
1276
  (example) => example.parts.map((part) => [
@@ -1277,239 +1283,229 @@ function convertJMdict(xmlString, examples) {
1277
1283
  if (result.JMdict && typeof result.JMdict === "object" && isValidArray(result.JMdict.entry))
1278
1284
  for (const entry of result.JMdict.entry) {
1279
1285
  const entryObj = {
1280
- ...isValidArray(entry.ent_seq) && entry.ent_seq[0] && typeof entry.ent_seq[0] === "string" ? { id: entry.ent_seq[0] } : { id: "" },
1286
+ id: entry.ent_seq[0],
1281
1287
  readings: [],
1282
1288
  meanings: []
1283
1289
  };
1284
- if (entryObj.id.length === 0) throw new Error("Invalid JMdict entry");
1285
- const kanjiForms = entry.k_ele;
1286
- const readings = entry.r_ele;
1287
- const meanings = entry.sense;
1288
- if (isValidArray(kanjiForms)) {
1289
- entryObj.kanjiForms = [];
1290
- for (const kanjiForm of kanjiForms) {
1291
- const form = {
1292
- ...isValidArrayWithFirstElement(kanjiForm.keb) && typeof kanjiForm.keb[0] === "string" ? { form: kanjiForm.keb[0] } : { form: "" }
1293
- };
1294
- if (form.form.length === 0)
1295
- throw new Error(
1296
- `Invalid JMdict entry kanji form: ${entryObj.id}`
1297
- );
1298
- if (isStringArray(kanjiForm.ke_inf))
1299
- form.notes = kanjiForm.ke_inf;
1300
- if (isStringArray(kanjiForm.ke_pri)) {
1301
- form.commonness = kanjiForm.ke_pri;
1302
- if (entryObj.isCommon === void 0) entryObj.isCommon = true;
1290
+ if (typeof entryObj.id === "string") {
1291
+ const kanjiForms = entry.k_ele;
1292
+ const readings = entry.r_ele;
1293
+ const meanings = entry.sense;
1294
+ if (isValidArray(kanjiForms)) {
1295
+ entryObj.kanjiForms = [];
1296
+ for (const kanjiForm of kanjiForms) {
1297
+ const form = {
1298
+ form: kanjiForm.keb[0]
1299
+ };
1300
+ if (typeof form.form === "string") {
1301
+ if (isStringArray(kanjiForm.ke_inf))
1302
+ form.notes = kanjiForm.ke_inf;
1303
+ if (isStringArray(kanjiForm.ke_pri)) {
1304
+ form.commonness = kanjiForm.ke_pri;
1305
+ if (entryObj.isCommon === void 0)
1306
+ entryObj.isCommon = true;
1307
+ }
1308
+ entryObj.kanjiForms.push(form);
1309
+ }
1303
1310
  }
1304
- if (form.form.length > 0) entryObj.kanjiForms.push(form);
1305
1311
  }
1306
- }
1307
- if (isValidArray(readings))
1308
- for (const reading of readings) {
1309
- const readingObj = {
1310
- ...isValidArrayWithFirstElement(reading.reb) && typeof reading.reb[0] === "string" ? { reading: reading.reb[0] } : { reading: "" }
1311
- };
1312
- if (readingObj.reading.length === 0)
1313
- throw new Error(`Invalid JMdict entry reading: ${entryObj.id}`);
1314
- if (isStringArray(reading.re_inf))
1315
- readingObj.notes = reading.re_inf;
1316
- if (isStringArray(reading.re_restr))
1317
- readingObj.kanjiFormRestrictions = reading.re_restr;
1318
- if (isStringArray(reading.re_pri)) {
1319
- readingObj.commonness = reading.re_pri;
1320
- if (entryObj.isCommon === void 0) entryObj.isCommon = true;
1312
+ if (isValidArray(readings))
1313
+ for (const reading of readings) {
1314
+ const readingObj = {
1315
+ reading: reading.reb[0]
1316
+ };
1317
+ if (typeof readingObj.reading === "string") {
1318
+ if (isStringArray(reading.re_inf))
1319
+ readingObj.notes = reading.re_inf;
1320
+ if (isStringArray(reading.re_restr))
1321
+ readingObj.kanjiFormRestrictions = reading.re_restr;
1322
+ if (isStringArray(reading.re_pri)) {
1323
+ readingObj.commonness = reading.re_pri;
1324
+ if (entryObj.isCommon === void 0)
1325
+ entryObj.isCommon = true;
1326
+ }
1327
+ entryObj.readings.push(readingObj);
1328
+ }
1329
+ }
1330
+ if (isValidArray(meanings)) {
1331
+ let usuallyInKanaMeanings = 0;
1332
+ for (const meaning of meanings) {
1333
+ const meaningObj = {};
1334
+ if (isStringArray(meaning.pos))
1335
+ meaningObj.partOfSpeech = meaning.pos;
1336
+ if (isValidArray(meaning.gloss)) {
1337
+ meaningObj.translations = [];
1338
+ for (const gloss of meaning.gloss)
1339
+ if (typeof gloss === "string")
1340
+ meaningObj.translations.push(gloss);
1341
+ else if (typeof gloss === "object" && gloss._ && typeof gloss._ === "string" && gloss.$ && typeof gloss.$ === "object" && gloss.$.g_type && (gloss.$.g_type === "lit" || gloss.$.g_type === "expl" || gloss.$.g_type === "tm"))
1342
+ meaningObj.translations.push({
1343
+ translation: gloss._,
1344
+ type: gloss.$.g_type
1345
+ });
1346
+ }
1347
+ if (isStringArray(meaning.xref))
1348
+ meaningObj.references = meaning.xref;
1349
+ if (isStringArray(meaning.stagk))
1350
+ meaningObj.kanjiFormRestrictions = meaning.stagk;
1351
+ if (isStringArray(meaning.stagr))
1352
+ meaningObj.readingRestrictions = meaning.stagr;
1353
+ if (isStringArray(meaning.ant))
1354
+ meaningObj.antonyms = meaning.ant;
1355
+ if (isStringArray(meaning.field))
1356
+ meaningObj.fields = meaning.field;
1357
+ if (isStringArray(meaning.s_inf))
1358
+ meaningObj.info = meaning.s_inf;
1359
+ if (isStringArray(meaning.misc)) {
1360
+ meaningObj.misc = meaning.misc;
1361
+ if (meaningObj.misc && meaningObj.misc.includes(
1362
+ "word usually written using kana alone"
1363
+ ))
1364
+ usuallyInKanaMeanings++;
1365
+ }
1366
+ if (isStringArray(meaning.dial))
1367
+ meaningObj.dialects = meaning.dial;
1368
+ if (meaningObj.partOfSpeech && meaningObj.partOfSpeech.length > 0)
1369
+ entryObj.meanings.push(meaningObj);
1321
1370
  }
1322
- if (readingObj.reading.length > 0)
1323
- entryObj.readings.push(readingObj);
1371
+ if (entryObj.meanings.length === usuallyInKanaMeanings)
1372
+ entryObj.usuallyInKana = true;
1324
1373
  }
1325
- if (isValidArray(meanings)) {
1326
- let usuallyInKanaMeanings = 0;
1327
- for (const meaning of meanings) {
1328
- const meaningObj = {};
1329
- if (isStringArray(meaning.pos))
1330
- meaningObj.partOfSpeech = meaning.pos;
1331
- if (isValidArray(meaning.gloss)) {
1332
- meaningObj.translations = [];
1333
- for (const gloss of meaning.gloss)
1334
- if (typeof gloss === "string")
1335
- meaningObj.translations.push(gloss);
1336
- else if (typeof gloss === "object" && gloss._ && typeof gloss._ === "string" && gloss.$ && typeof gloss.$ === "object" && gloss.$.g_type && (gloss.$.g_type === "lit" || gloss.$.g_type === "expl" || gloss.$.g_type === "tm"))
1337
- meaningObj.translations.push({
1338
- translation: gloss._,
1339
- type: gloss.$.g_type
1340
- });
1374
+ if (examples) {
1375
+ const readings2 = new Set(
1376
+ entryObj.readings.filter(
1377
+ (reading) => reading.notes === void 0 || !reading.notes.some(
1378
+ (note) => notSearchedForms.has(note)
1379
+ ) || reading.commonness
1380
+ ).map((reading) => reading.reading)
1381
+ );
1382
+ const kanjiForms2 = entryObj.kanjiForms ? new Set(
1383
+ entryObj.kanjiForms.map(
1384
+ (kanjiForm) => kanjiForm.form
1385
+ )
1386
+ ) : void 0;
1387
+ let existsExample = false;
1388
+ if (kanjiForms2 && kanjiForms2.size > 0 && tanakaParts) {
1389
+ for (const kf of kanjiForms2)
1390
+ if (tanakaParts.has(kf)) {
1391
+ existsExample = true;
1392
+ break;
1393
+ }
1341
1394
  }
1342
- if (isStringArray(meaning.xref))
1343
- meaningObj.references = meaning.xref;
1344
- if (isStringArray(meaning.stagk))
1345
- meaningObj.kanjiFormRestrictions = meaning.stagk;
1346
- if (isStringArray(meaning.stagr))
1347
- meaningObj.readingRestrictions = meaning.stagr;
1348
- if (isStringArray(meaning.ant)) meaningObj.antonyms = meaning.ant;
1349
- if (isStringArray(meaning.field))
1350
- meaningObj.fields = meaning.field;
1351
- if (isStringArray(meaning.s_inf)) meaningObj.info = meaning.s_inf;
1352
- if (isStringArray(meaning.misc)) {
1353
- meaningObj.misc = meaning.misc;
1354
- if (meaningObj.misc && meaningObj.misc.includes(
1355
- "word usually written using kana alone"
1356
- ))
1357
- usuallyInKanaMeanings++;
1395
+ if (!existsExample && readings2.size > 0 && tanakaParts) {
1396
+ for (const r of readings2)
1397
+ if (tanakaParts.has(r)) {
1398
+ existsExample = true;
1399
+ break;
1400
+ }
1358
1401
  }
1359
- if (isStringArray(meaning.dial))
1360
- meaningObj.dialects = meaning.dial;
1361
- if (meaningObj.partOfSpeech && meaningObj.partOfSpeech.length > 0 || meaningObj.translations)
1362
- entryObj.meanings.push(meaningObj);
1363
- }
1364
- if (entryObj.meanings.length === usuallyInKanaMeanings)
1365
- entryObj.usuallyInKana = true;
1366
- }
1367
- if (examples) {
1368
- const readings2 = new Set(
1369
- entryObj.readings.filter(
1370
- (reading) => reading.notes === void 0 || !reading.notes.some(
1371
- (note) => notSearchedForms.has(note)
1372
- ) || reading.commonness
1373
- ).map((reading) => reading.reading)
1374
- );
1375
- const kanjiForms2 = entryObj.kanjiForms ? new Set(
1376
- entryObj.kanjiForms.map(
1377
- (kanjiForm) => kanjiForm.form
1378
- )
1379
- ) : void 0;
1380
- let existsExample = false;
1381
- if (kanjiForms2 && kanjiForms2.size > 0 && tanakaParts) {
1382
- for (const kf of kanjiForms2)
1383
- if (tanakaParts.has(kf)) {
1384
- existsExample = true;
1385
- break;
1386
- }
1387
- }
1388
- if (!existsExample && readings2.size > 0 && tanakaParts) {
1389
- for (const r of readings2)
1390
- if (tanakaParts.has(r)) {
1391
- existsExample = true;
1392
- break;
1393
- }
1402
+ if (tanakaParts && tanakaParts.has(entryObj.id))
1403
+ existsExample = true;
1404
+ if (existsExample) entryObj.hasPhrases = true;
1394
1405
  }
1395
- if (!existsExample && tanakaParts && tanakaParts.has(entryObj.id))
1396
- existsExample = true;
1397
- if (existsExample) entryObj.hasPhrases = true;
1406
+ if (entryObj.id.length > 0 && entryObj.readings.length > 0 && entryObj.meanings.length > 0)
1407
+ dict.push(entryObj);
1398
1408
  }
1399
- if (entryObj.id.length > 0 && entryObj.readings.length > 0 && entryObj.meanings.length > 0)
1400
- dict.push(entryObj);
1401
1409
  }
1402
- });
1403
- return dict;
1404
- } catch (err) {
1405
- throw err;
1406
- }
1410
+ }
1411
+ });
1412
+ return dict;
1407
1413
  }
1408
1414
  function convertKanjiDic(xmlString) {
1409
- try {
1410
- const dictParsed = import_libxmljs2.default.parseXml(xmlString, {
1411
- dtdvalid: true,
1412
- nonet: false,
1413
- noent: true,
1414
- recover: false
1415
- });
1416
- const dict = [];
1417
- import_xml2js.default.parseString(dictParsed, (err, result) => {
1418
- if (err) throw err;
1415
+ const dictParsed = import_libxmljs2.default.parseXml(xmlString, {
1416
+ dtdvalid: true,
1417
+ nonet: false,
1418
+ noent: true,
1419
+ recover: false
1420
+ });
1421
+ const dict = [];
1422
+ import_xml2js.default.parseString(dictParsed, (err, result) => {
1423
+ if (err === null) {
1419
1424
  if (result.kanjidic2 && typeof result.kanjidic2 === "object" && isValidArray(result.kanjidic2.character))
1420
1425
  for (const entry of result.kanjidic2.character) {
1421
1426
  const kanjiObj = {
1422
- ...isValidArrayWithFirstElement(entry.literal) && typeof entry.literal[0] === "string" ? { kanji: entry.literal[0] } : { kanji: "" },
1423
- misc: {
1424
- strokeNumber: ""
1425
- },
1426
- readingMeaning: []
1427
+ kanji: entry.literal[0]
1427
1428
  };
1428
- if (kanjiObj.kanji.length === 0)
1429
- throw new Error("Invalid KANJIDIC entry");
1430
- if (isValidArrayWithFirstElement(entry.misc) && typeof entry.misc[0] === "object") {
1431
- const misc = entry.misc[0];
1432
- kanjiObj.misc = {
1433
- ...isValidArrayWithFirstElement(misc.stroke_count) && typeof misc.stroke_count[0] === "string" ? { strokeNumber: misc.stroke_count[0] } : { strokeNumber: "" }
1434
- };
1435
- if (kanjiObj.misc.strokeNumber.length === 0)
1436
- throw new Error(`Invalid KANJIDIC entry: ${kanjiObj.kanji}`);
1437
- if (isValidArrayWithFirstElement(misc.grade) && typeof misc.grade[0] === "string")
1438
- kanjiObj.misc.grade = misc.grade[0];
1439
- if (isValidArrayWithFirstElement(misc.freq) && typeof misc.freq[0] === "string")
1440
- kanjiObj.misc.frequency = misc.freq[0];
1441
- if (isValidArrayWithFirstElement(misc.jlpt) && typeof misc.jlpt[0] === "string" && ["5", "4", "3", "2", "1"].includes(misc.jlpt[0]))
1442
- kanjiObj.misc.jlpt = `N${misc.jlpt[0]}`;
1443
- }
1444
- if (isValidArray(entry.reading_meaning))
1445
- for (const rm of entry.reading_meaning) {
1446
- const rmObj = { groups: [] };
1447
- if (isValidArray(rm.rmgroup))
1448
- for (const group of rm.rmgroup) {
1449
- const groupObj = {
1450
- readings: [],
1451
- meanings: []
1452
- };
1453
- if (isValidArray(group.reading)) {
1454
- for (const reading of group.reading)
1455
- if (reading._ && typeof reading._ === "string" && reading.$ && typeof reading.$ === "object" && reading.$.r_type && (reading.$.r_type === "ja_on" || reading.$.r_type === "ja_kun"))
1456
- groupObj.readings.push({
1457
- reading: reading._,
1458
- type: reading.$.r_type
1459
- });
1460
- }
1461
- if (isValidArray(group.meaning)) {
1462
- for (const meaning of group.meaning)
1463
- if (typeof meaning === "string") {
1464
- if (kanjiObj.isKokuji === void 0 && meaning === "(kokuji)")
1465
- kanjiObj.isKokuji = true;
1466
- groupObj.meanings.push(meaning);
1467
- }
1429
+ if (typeof kanjiObj.kanji === "string" && kanjiObj.kanji.length === 1) {
1430
+ if (isValidArrayWithFirstElement(entry.misc) && typeof entry.misc[0] === "object") {
1431
+ const misc = entry.misc[0];
1432
+ kanjiObj.misc = {};
1433
+ if (isValidArrayWithFirstElement(misc.stroke_count) && typeof misc.stroke_count[0] === "string")
1434
+ kanjiObj.misc.strokeNumber = misc.stroke_count[0];
1435
+ if (isValidArrayWithFirstElement(misc.grade) && typeof misc.grade[0] === "string")
1436
+ kanjiObj.misc.grade = misc.grade[0];
1437
+ if (isValidArrayWithFirstElement(misc.freq) && typeof misc.freq[0] === "string")
1438
+ kanjiObj.misc.frequency = misc.freq[0];
1439
+ if (isValidArrayWithFirstElement(misc.jlpt) && typeof misc.jlpt[0] === "string" && ["5", "4", "3", "2", "1"].includes(misc.jlpt[0]))
1440
+ kanjiObj.misc.jlpt = `N${misc.jlpt[0]}`;
1441
+ }
1442
+ if (isValidArray(entry.reading_meaning))
1443
+ for (const rm of entry.reading_meaning) {
1444
+ const rmObj = { groups: [] };
1445
+ if (isValidArray(rm.rmgroup))
1446
+ for (const group of rm.rmgroup) {
1447
+ const groupObj = {
1448
+ readings: [],
1449
+ meanings: []
1450
+ };
1451
+ if (isValidArray(group.reading)) {
1452
+ for (const reading of group.reading)
1453
+ if (reading._ && typeof reading._ === "string" && reading.$ && typeof reading.$ === "object" && reading.$.r_type && (reading.$.r_type === "ja_on" || reading.$.r_type === "ja_kun"))
1454
+ groupObj.readings.push({
1455
+ reading: reading._,
1456
+ type: reading.$.r_type
1457
+ });
1458
+ }
1459
+ if (isValidArray(group.meaning)) {
1460
+ for (const meaning of group.meaning)
1461
+ if (typeof meaning === "string") {
1462
+ if (kanjiObj.isKokuji === void 0 && meaning === "(kokuji)")
1463
+ kanjiObj.isKokuji = true;
1464
+ groupObj.meanings.push(meaning);
1465
+ }
1466
+ }
1467
+ if (groupObj.readings.length > 0 || groupObj.meanings.length > 0) {
1468
+ if (groupObj.readings.length === 0)
1469
+ delete groupObj.readings;
1470
+ if (groupObj.meanings.length === 0)
1471
+ delete groupObj.meanings;
1472
+ rmObj.groups.push(groupObj);
1473
+ }
1468
1474
  }
1469
- if (groupObj.readings.length > 0 || groupObj.meanings.length > 0)
1470
- rmObj.groups.push(groupObj);
1475
+ if (isStringArray(rm.nanori) && rm.nanori.length > 0)
1476
+ rmObj.nanori = rm.nanori;
1477
+ if (rmObj.groups.length > 0 || rmObj.nanori) {
1478
+ if (kanjiObj.readingMeaning === void 0)
1479
+ kanjiObj.readingMeaning = [];
1480
+ kanjiObj.readingMeaning.push(rmObj);
1471
1481
  }
1472
- if (isStringArray(rm.nanori)) rmObj.nanori = rm.nanori;
1473
- if (rmObj.groups.length > 0 && kanjiObj.readingMeaning)
1474
- kanjiObj.readingMeaning.push(rmObj);
1475
- }
1476
- if (kanjiObj.readingMeaning && kanjiObj.readingMeaning.length === 0)
1477
- delete kanjiObj.readingMeaning;
1478
- if (kanjiObj.kanji.length === 1 && kanjiObj.misc && kanjiObj.misc.strokeNumber.length > 0)
1482
+ }
1479
1483
  dict.push(kanjiObj);
1484
+ }
1480
1485
  }
1481
- });
1482
- return dict;
1483
- } catch (err) {
1484
- throw err;
1485
- }
1486
+ }
1487
+ });
1488
+ return dict;
1486
1489
  }
1487
- async function convertTanakaCorpus(tanakaString, generateFurigana) {
1488
- return await new Promise(
1489
- async (resolve, reject) => {
1490
- try {
1491
- const tanakaArray = [];
1492
- const tanakaParsed = tanakaString.split("\n");
1493
- const kuroshiro = generateFurigana === true ? new Kuroshiro.default() : null;
1494
- if (kuroshiro !== null) await kuroshiro.init(new KuromojiAnalyzer());
1495
- const convert = kuroshiro !== null ? kuroshiro.convert.bind(kuroshiro) : null;
1496
- for (let i = 0; i <= tanakaParsed.length; i += 2) {
1497
- let a = tanakaParsed[i];
1498
- let b = tanakaParsed[i + 1];
1499
- if (a && b && a.startsWith("A: ") && b.startsWith("B: ")) {
1500
- a = a.replace("A: ", "");
1501
- b = b.replace("B: ", "");
1502
- const idMatch = regexps.tanakaID.exec(a);
1503
- if (!idMatch || !idMatch.groups || !idMatch.groups["id"])
1504
- throw new Error(`Invalid phrase ID for ${a}`);
1505
- const aParts = a.replace(regexps.tanakaID, "").split(" ");
1506
- const bParts = b.split(" ").filter((part) => part.trim().length !== 0).map((part) => {
1507
- const partMatches = regexps.tanakaPart.exec(part);
1508
- if (!partMatches || !partMatches.groups || partMatches.length === 0)
1509
- throw new Error(`Invalid B part: ${part}`);
1510
- const baseForm = partMatches.groups["base"];
1511
- if (!baseForm)
1512
- throw new Error(`Invalid base form of B part: ${part}`);
1490
+ function convertTanakaCorpus(tanakaString) {
1491
+ const tanakaArray = [];
1492
+ const tanakaParsed = tanakaString.split("\n");
1493
+ for (let i = 0; i <= tanakaParsed.length; i += 2) {
1494
+ let a = tanakaParsed[i];
1495
+ let b = tanakaParsed[i + 1];
1496
+ if (a && b && a.startsWith("A: ") && b.startsWith("B: ")) {
1497
+ a = a.replace("A: ", "");
1498
+ b = b.replace("B: ", "");
1499
+ const idMatch = regexps.tanakaID.exec(a);
1500
+ if (idMatch && idMatch.groups && idMatch.groups["id"]) {
1501
+ const aParts = a.replace(regexps.tanakaID, "").split(" ");
1502
+ const bRawParts = b.split(" ").filter((part) => part.trim().length !== 0);
1503
+ const bParts = [];
1504
+ for (const part of bRawParts) {
1505
+ const partMatches = regexps.tanakaPart.exec(part);
1506
+ if (partMatches && partMatches.groups && partMatches.length > 0) {
1507
+ const baseForm = partMatches.groups["base"];
1508
+ if (baseForm) {
1513
1509
  const examplePart = { baseForm };
1514
1510
  const reading = partMatches.groups["reading"];
1515
1511
  const glossNumber = partMatches.groups["glossnum"];
@@ -1517,9 +1513,8 @@ async function convertTanakaCorpus(tanakaString, generateFurigana) {
1517
1513
  if (reading)
1518
1514
  if (regexps.tanakaReferenceID.test(reading)) {
1519
1515
  const referenceID = regexps.tanakaReferenceID.exec(reading);
1520
- if (!referenceID || !referenceID.groups || !referenceID.groups["entryid"])
1521
- throw new Error(`Invalid reference ID: ${reading}`);
1522
- examplePart.referenceID = referenceID.groups["entryid"];
1516
+ if (referenceID && referenceID.groups && referenceID.groups["entryid"])
1517
+ examplePart.referenceID = referenceID.groups["entryid"];
1523
1518
  } else examplePart.reading = reading;
1524
1519
  if (glossNumber)
1525
1520
  examplePart.glossNumber = glossNumber.startsWith("0") ? Number.parseInt(glossNumber.substring(1)) : Number.parseInt(glossNumber);
@@ -1528,50 +1523,60 @@ async function convertTanakaCorpus(tanakaString, generateFurigana) {
1528
1523
  examplePart.edited = true;
1529
1524
  examplePart.baseForm = examplePart.baseForm.replace("~", "");
1530
1525
  }
1531
- return examplePart;
1532
- });
1533
- const phrase = aParts[0];
1534
- const translation = aParts[1];
1535
- if (phrase && translation) {
1536
- let furigana = void 0;
1537
- if (convert !== null && !phrase.includes("\u30FB"))
1538
- furigana = await convert(phrase, {
1539
- to: "hiragana",
1540
- mode: "furigana"
1541
- });
1542
- tanakaArray.push({
1543
- id: idMatch.groups["id"].trim(),
1544
- phrase: phrase.trim(),
1545
- translation: translation.trim(),
1546
- parts: bParts,
1547
- ...furigana ? { furigana } : {}
1548
- });
1526
+ bParts.push(examplePart);
1549
1527
  }
1550
1528
  }
1551
1529
  }
1552
- tanakaParsed.length = 0;
1553
- resolve(tanakaArray);
1554
- } catch (err) {
1555
- reject(err);
1530
+ const phrase = aParts[0];
1531
+ const translation = aParts[1];
1532
+ if (phrase && translation)
1533
+ tanakaArray.push({
1534
+ id: idMatch.groups["id"].trim(),
1535
+ phrase: phrase.trim(),
1536
+ translation: translation.trim(),
1537
+ parts: bParts
1538
+ });
1556
1539
  }
1557
1540
  }
1541
+ }
1542
+ return tanakaArray;
1543
+ }
1544
+ async function convertTanakaCorpusWithFurigana(tanakaString) {
1545
+ return new Promise(
1546
+ async (resolve) => {
1547
+ let tanakaArray = convertTanakaCorpus(tanakaString);
1548
+ const kuroshiro = new Kuroshiro.default();
1549
+ await kuroshiro.init(new KuromojiAnalyzer());
1550
+ const convert = kuroshiro.convert.bind(kuroshiro);
1551
+ tanakaArray = await Promise.all(
1552
+ tanakaArray.map(async (ex) => {
1553
+ let furigana = void 0;
1554
+ if (convert !== null && !ex.phrase.includes("\u30FB"))
1555
+ furigana = await convert(ex.phrase, {
1556
+ to: "hiragana",
1557
+ mode: "furigana"
1558
+ });
1559
+ if (furigana) ex.furigana = furigana;
1560
+ return ex;
1561
+ })
1562
+ );
1563
+ resolve(tanakaArray);
1564
+ }
1558
1565
  );
1559
1566
  }
1560
1567
  function convertRadkFile(radkBuffer, kanjiDic) {
1561
- try {
1562
- const fileParsed = import_iconv_lite.default.decode(radkBuffer, "euc-jp").split("\n").filter((line) => !line.startsWith("#"));
1563
- const radicals = [];
1564
- for (let i = 0; i < fileParsed.length; i++) {
1565
- const line = fileParsed[i];
1566
- if (!line) continue;
1567
- if (line.startsWith("$ ")) {
1568
- const radical = {
1569
- radical: line.charAt(2).trim(),
1570
- strokes: line.substring(4).trim()
1571
- };
1572
- let j = i + 1;
1573
- let kanjiLine = fileParsed[j];
1574
- if (!kanjiLine) continue;
1568
+ const fileParsed = import_iconv_lite.default.decode(radkBuffer, "euc-jp").split("\n").filter((line) => !line.startsWith("#"));
1569
+ const radicals = [];
1570
+ for (let i = 0; i < fileParsed.length; i++) {
1571
+ const line = fileParsed[i];
1572
+ if (line && line.startsWith("$ ")) {
1573
+ const radical = {
1574
+ radical: line.charAt(2).trim(),
1575
+ strokes: line.substring(4).trim()
1576
+ };
1577
+ let j = i + 1;
1578
+ let kanjiLine = fileParsed[j];
1579
+ if (kanjiLine) {
1575
1580
  const kanjiList = [];
1576
1581
  while (kanjiLine && !kanjiLine.startsWith("$ ")) {
1577
1582
  const kanjis = kanjiLine.split("");
@@ -1579,8 +1584,9 @@ function convertRadkFile(radkBuffer, kanjiDic) {
1579
1584
  const foundKanji = kanjiDic.find(
1580
1585
  (dictKanji) => dictKanji.kanji === kanji
1581
1586
  );
1582
- if (foundKanji) kanjiList.push(foundKanji);
1583
- else kanjiList.push({ kanji });
1587
+ let kanjiObj = { kanji };
1588
+ if (foundKanji) kanjiObj = foundKanji;
1589
+ kanjiList.push(kanjiObj);
1584
1590
  }
1585
1591
  j++;
1586
1592
  kanjiLine = fileParsed[j];
@@ -1592,133 +1598,116 @@ function convertRadkFile(radkBuffer, kanjiDic) {
1592
1598
  radicals.push(radical);
1593
1599
  }
1594
1600
  }
1595
- fileParsed.length = 0;
1596
- return radicals;
1597
- } catch (err) {
1598
- throw err;
1599
1601
  }
1602
+ return radicals;
1600
1603
  }
1601
1604
  function convertKradFile(kradBuffer, kanjiDic, katakanaList) {
1602
- try {
1603
- const fileParsed = import_iconv_lite.default.decode(kradBuffer, "euc-jp").split("\n").filter((line) => !line.startsWith("#"));
1604
- const kanjiWithRadicals = [];
1605
- for (const line of fileParsed) {
1606
- if (line.length === 0) continue;
1605
+ const fileParsed = import_iconv_lite.default.decode(kradBuffer, "euc-jp").split("\n").filter((line) => !line.startsWith("#"));
1606
+ const kanjiWithRadicals = [];
1607
+ for (const line of fileParsed) {
1608
+ if (line.length > 0) {
1607
1609
  const split = line.split(" : ");
1608
1610
  const kanjiChar = split[0];
1609
1611
  const radicalsRow = split[1];
1610
- if (!kanjiChar || !radicalsRow) continue;
1611
- const kanji = {
1612
- ...kanjiChar && radicalsRow && kanjiChar.length === 1 && radicalsRow.length > 0 ? { kanji: kanjiChar } : { kanji: "" },
1613
- radicals: []
1614
- };
1615
- if (kanji.kanji.length === 1) {
1616
- const radicals = radicalsRow.split(" ");
1617
- for (const radical of radicals) {
1618
- let foundRadical = kanjiDic.find(
1619
- (dictKanji) => dictKanji.kanji === radical
1620
- );
1621
- if (!foundRadical) {
1622
- const katakanaChar = katakanaList.find(
1623
- (kana) => kana.kana === radical
1612
+ if (kanjiChar && radicalsRow) {
1613
+ const kanji = {
1614
+ kanji: kanjiChar,
1615
+ radicals: []
1616
+ };
1617
+ if (kanji.kanji.length === 1) {
1618
+ const radicals = radicalsRow.split(" ");
1619
+ for (const radical of radicals) {
1620
+ const foundRadical = kanjiDic.find(
1621
+ (dictKanji) => dictKanji.kanji === radical
1624
1622
  );
1625
- if (!katakanaChar) continue;
1626
- foundRadical = {
1627
- kanji: katakanaChar.kana,
1628
- readingMeaning: [
1629
- {
1630
- groups: [
1631
- {
1632
- readings: [{ reading: katakanaChar.kana, type: "ja_on" }],
1633
- meanings: [katakanaChar.reading]
1634
- }
1635
- ]
1636
- }
1637
- ]
1638
- };
1623
+ let radicalObj = foundRadical != null ? foundRadical : { kanji: radical };
1624
+ if (!foundRadical) {
1625
+ const katakanaChar = katakanaList.find(
1626
+ (kana) => kana.kana === radical
1627
+ );
1628
+ if (!katakanaChar) continue;
1629
+ radicalObj = {
1630
+ kanji: katakanaChar.kana,
1631
+ readingMeaning: [
1632
+ {
1633
+ groups: [
1634
+ {
1635
+ readings: [
1636
+ { reading: katakanaChar.kana, type: "ja_on" }
1637
+ ],
1638
+ meanings: [katakanaChar.reading]
1639
+ }
1640
+ ]
1641
+ }
1642
+ ]
1643
+ };
1644
+ }
1645
+ kanji.radicals.push(radicalObj);
1639
1646
  }
1640
- kanji.radicals.push(foundRadical ? foundRadical : radical);
1641
1647
  }
1648
+ if (kanji.kanji.length === 1 && kanji.radicals.length > 0)
1649
+ kanjiWithRadicals.push(kanji);
1642
1650
  }
1643
- if (kanji.kanji.length === 1 && kanji.radicals.length > 0)
1644
- kanjiWithRadicals.push(kanji);
1645
1651
  }
1646
- fileParsed.length = 0;
1647
- return kanjiWithRadicals;
1648
- } catch (err) {
1649
- throw err;
1650
1652
  }
1651
- }
1652
- async function convertJawiktionary(stream) {
1653
- const rl = (0, import_readline.createInterface)({
1654
- input: stream,
1655
- crlfDelay: Infinity
1656
- });
1657
- let lineNumber = 0;
1658
- return await new Promise(
1659
- async (resolve, reject) => {
1660
- try {
1661
- const entries = [];
1662
- for await (const line of rl) {
1663
- lineNumber++;
1664
- let obj = void 0;
1665
- try {
1666
- obj = JSON.parse(line.trim());
1667
- } catch (err) {
1668
- rl.close();
1669
- throw new Error(
1670
- `Invalid JSONL at line ${lineNumber}: ${err.message}`
1671
- );
1672
- }
1673
- if (obj !== void 0 && obj !== null && typeof obj === "object" && obj.lang_code === "ja" && obj.lang === "\u65E5\u672C\u8A9E")
1674
- entries.push(obj);
1675
- }
1676
- rl.close();
1677
- stream.close();
1678
- stream.destroy();
1679
- resolve(entries);
1680
- } catch (err) {
1681
- reject(err);
1682
- }
1683
- }
1684
- );
1653
+ return kanjiWithRadicals;
1685
1654
  }
1686
1655
  function mapEntry(entry) {
1687
- if (entry.word === void 0 || typeof entry.word !== "string")
1688
- throw new Error("Invalid ja.wiktionary entry");
1689
1656
  return {
1690
1657
  word: entry.word,
1691
- ...entry.pos_title && typeof entry.pos_title === "string" ? { pos_title: entry.pos_title } : {},
1692
- ...isValidArray(entry.senses) ? {
1693
- senses: entry.senses.filter(
1694
- (sense) => isValidArray(sense.form_of) && sense.form_of.every(
1695
- (form) => form.word && typeof form.word === "string"
1696
- ) || isStringArray(sense.glosses)
1697
- ).map((sense) => ({
1698
- ...sense.form_of ? {
1699
- form_of: sense.form_of.map((form) => ({
1700
- word: form.word
1701
- }))
1702
- } : {},
1703
- ...sense.glosses ? { glosses: sense.glosses } : {}
1704
- }))
1705
- } : {},
1658
+ pos_title: entry.pos_title,
1659
+ senses: entry.senses.filter(
1660
+ (sense) => isValidArray(sense.form_of) && sense.form_of.every(
1661
+ (form) => form.word && typeof form.word === "string"
1662
+ ) || isStringArray(sense.glosses)
1663
+ ).map((sense) => ({
1664
+ ...sense.form_of ? {
1665
+ form_of: sense.form_of.map((form) => ({
1666
+ word: form.word
1667
+ }))
1668
+ } : {},
1669
+ glosses: sense.glosses
1670
+ })),
1706
1671
  ...isValidArray(entry.forms) && entry.forms.every((form) => typeof form.form === "string") ? { forms: entry.forms.map((form) => ({ form: form.form })) } : {}
1707
1672
  };
1708
1673
  }
1674
+ function convertJawiktionarySync(buffer) {
1675
+ const lines = buffer.toString("utf-8").split("\n");
1676
+ const entries = [];
1677
+ for (let i = 0; i < lines.length; i++) {
1678
+ const line = lines[i];
1679
+ if (!line) continue;
1680
+ const obj = JSON.parse(line);
1681
+ if (obj && typeof obj === "object" && obj.lang_code === "ja" && obj.lang === "\u65E5\u672C\u8A9E")
1682
+ entries.push(mapEntry(obj));
1683
+ }
1684
+ return entries;
1685
+ }
1686
+ async function convertJawiktionaryAsync(stream) {
1687
+ return new Promise(
1688
+ async (resolve) => {
1689
+ const rl = (0, import_readline.createInterface)({
1690
+ input: stream,
1691
+ crlfDelay: Infinity
1692
+ });
1693
+ const entries = [];
1694
+ for await (const line of rl) {
1695
+ const obj = JSON.parse(line.trim());
1696
+ if (obj && typeof obj === "object" && obj.lang_code === "ja" && obj.lang === "\u65E5\u672C\u8A9E")
1697
+ entries.push(mapEntry(obj));
1698
+ }
1699
+ rl.close();
1700
+ stream.close();
1701
+ stream.destroy();
1702
+ resolve(entries);
1703
+ }
1704
+ );
1705
+ }
1709
1706
  function parseEntry(entry, definitions, definitionMap) {
1710
1707
  if (isValidArray(entry.senses)) {
1711
1708
  for (const sense of entry.senses)
1712
1709
  if (isStringArray(sense.glosses)) {
1713
- let definition = "";
1714
- for (let i = 0; i < sense.glosses.length; i += 2) {
1715
- if (i !== 0) {
1716
- let prev = sense.glosses[i - 1];
1717
- let cur = sense.glosses[i];
1718
- if (prev && cur)
1719
- definition += `${prev}${!prev.endsWith("\u3002") ? "\u3002" : ""}${cur}`;
1720
- } else definition += sense.glosses[i];
1721
- }
1710
+ const definition = sense.glosses.join("");
1722
1711
  if (!definitions.some((def) => def.definition === definition)) {
1723
1712
  if (!definitionMap.has(definition))
1724
1713
  definitionMap.set(definition, { count: 1 });
@@ -1728,262 +1717,216 @@ function parseEntry(entry, definitions, definitionMap) {
1728
1717
  }
1729
1718
  }
1730
1719
  }
1731
- async function getWordDefinitions(entryList, jmDict, generateFurigana) {
1732
- return await new Promise(async (resolve, reject) => {
1733
- var _a, _b, _c, _d, _e;
1734
- try {
1735
- const entries = /* @__PURE__ */ new Map();
1736
- for (const entry of entryList) {
1737
- const ent = entries.get(entry.word);
1738
- if (ent) ent.push(mapEntry(entry));
1739
- else entries.set(entry.word, [mapEntry(entry)]);
1740
- }
1741
- const japaneseDefinitions = [];
1742
- const definitionMap = /* @__PURE__ */ new Map();
1743
- const validWords = [];
1744
- const validReadings = /* @__PURE__ */ new Set();
1745
- const validKanjiForms = /* @__PURE__ */ new Set();
1746
- for (const word of jmDict) {
1747
- let valid = false;
1748
- for (const r of word.readings)
1749
- if ((r.notes === void 0 || !r.notes.some((note) => notSearchedForms.has(note)) || r.commonness !== void 0) && !validReadings.has(r.reading)) {
1750
- validReadings.add(r.reading);
1720
+ function getWordDefinitions(entryList, jmDict) {
1721
+ var _a, _b, _c, _d, _e;
1722
+ const entries = /* @__PURE__ */ new Map();
1723
+ for (const entry of entryList) {
1724
+ const ent = entries.get(entry.word);
1725
+ if (ent) ent.push(mapEntry(entry));
1726
+ else entries.set(entry.word, [mapEntry(entry)]);
1727
+ }
1728
+ const japaneseDefinitions = [];
1729
+ const definitionMap = /* @__PURE__ */ new Map();
1730
+ const validWords = [];
1731
+ const validReadings = /* @__PURE__ */ new Set();
1732
+ const validKanjiForms = /* @__PURE__ */ new Set();
1733
+ if (jmDict.length > 0)
1734
+ for (const word of jmDict) {
1735
+ let valid = false;
1736
+ for (const r of word.readings)
1737
+ if ((r.notes === void 0 || !r.notes.some((note) => notSearchedForms.has(note)) || r.commonness !== void 0) && !validReadings.has(r.reading)) {
1738
+ validReadings.add(r.reading);
1739
+ if (!valid) valid = true;
1740
+ }
1741
+ if (word.kanjiForms) {
1742
+ for (const kf of word.kanjiForms)
1743
+ if ((kf.notes === void 0 || !kf.notes.some((note) => notSearchedForms.has(note)) || kf.commonness !== void 0) && !validKanjiForms.has(kf.form)) {
1744
+ validKanjiForms.add(kf.form);
1751
1745
  if (!valid) valid = true;
1752
1746
  }
1753
- if (word.kanjiForms) {
1754
- for (const kf of word.kanjiForms)
1755
- if ((kf.notes === void 0 || !kf.notes.some((note) => notSearchedForms.has(note)) || kf.commonness !== void 0) && !validKanjiForms.has(kf.form)) {
1756
- validKanjiForms.add(kf.form);
1757
- if (!valid) valid = true;
1758
- }
1759
- }
1760
- if (valid) validWords.push(word);
1761
1747
  }
1762
- const validTitleEntries = /* @__PURE__ */ new Map();
1763
- const entriesWithFormTitlesGlobal = /* @__PURE__ */ new Map();
1764
- const entriesWithFormsGlobal = /* @__PURE__ */ new Map();
1765
- const validFormOfEntries = /* @__PURE__ */ new Set();
1766
- const validGlossesEntries = /* @__PURE__ */ new Set();
1767
- const validFormsEntries = /* @__PURE__ */ new Set();
1768
- const ents = Array.from(entries.values()).flat();
1769
- for (const entry of ents) {
1770
- let valid = false;
1771
- if (validKanjiForms && validKanjiForms.has(entry.word)) {
1772
- valid = true;
1773
- if (isValidArray(entry.senses))
1774
- for (const sense of entry.senses) {
1775
- if (isValidArray(sense.form_of) && sense.form_of.some(
1776
- (form) => form.word && typeof form.word === "string" && validReadings.has(form.word)
1777
- ))
1778
- validFormOfEntries.add(entry.word);
1779
- else if (isStringArray(sense.glosses)) {
1780
- for (const gloss of sense.glosses) {
1781
- let reading = void 0;
1782
- if (gloss !== void 0) {
1783
- if (gloss.trim().includes("\u306E\u6F22\u5B57\u8868\u8A18\u3002") || gloss.trim().includes("\u3092\u53C2\u7167\u3002")) {
1784
- for (const r of validReadings)
1785
- if (gloss.trim().includes(r)) {
1786
- reading = r;
1787
- break;
1788
- }
1748
+ if (valid) validWords.push(word);
1749
+ }
1750
+ const validTitleEntries = /* @__PURE__ */ new Map();
1751
+ const entriesWithFormTitlesGlobal = /* @__PURE__ */ new Map();
1752
+ const entriesWithFormsGlobal = /* @__PURE__ */ new Map();
1753
+ const validFormOfEntries = /* @__PURE__ */ new Set();
1754
+ const validGlossesEntries = /* @__PURE__ */ new Set();
1755
+ const validFormsEntries = /* @__PURE__ */ new Set();
1756
+ const ents = Array.from(entries.values()).flat();
1757
+ for (const entry of ents) {
1758
+ let valid = false;
1759
+ if (validKanjiForms && validKanjiForms.has(entry.word)) {
1760
+ valid = true;
1761
+ if (isValidArray(entry.senses))
1762
+ for (const sense of entry.senses) {
1763
+ if (isValidArray(sense.form_of) && sense.form_of.some(
1764
+ (form) => form.word && typeof form.word === "string" && validReadings.has(form.word)
1765
+ ))
1766
+ validFormOfEntries.add(entry.word);
1767
+ else if (isStringArray(sense.glosses)) {
1768
+ for (const gloss of sense.glosses) {
1769
+ let reading = void 0;
1770
+ if (gloss !== void 0) {
1771
+ if (gloss.trim().includes("\u306E\u6F22\u5B57\u8868\u8A18\u3002") || gloss.trim().includes("\u3092\u53C2\u7167\u3002")) {
1772
+ for (const r of validReadings)
1773
+ if (gloss.trim().includes(r)) {
1774
+ reading = r;
1775
+ break;
1789
1776
  }
1790
- }
1791
- if (reading) validGlossesEntries.add(entry.word);
1792
1777
  }
1793
1778
  }
1779
+ if (reading) validGlossesEntries.add(entry.word);
1794
1780
  }
1795
- if (isValidArray(entry.forms)) {
1796
- for (const form of entry.forms)
1797
- if (form.form && typeof form.form === "string" && validReadings.has(form.form))
1798
- validFormsEntries.add(entry.word);
1799
1781
  }
1800
- } else if (validReadings.has(entry.word)) {
1801
- valid = true;
1802
- const ftEntry = entriesWithFormTitlesGlobal.get(entry.word);
1803
- if (ftEntry) ftEntry.push(entry);
1804
- else entriesWithFormTitlesGlobal.set(entry.word, [entry]);
1805
- }
1806
- if (valid) {
1807
- const tEntry = validTitleEntries.get(entry.word);
1808
- if (tEntry) tEntry.push(entry);
1809
- else validTitleEntries.set(entry.word, [entry]);
1810
- }
1811
- if (isValidArray(entry.forms) && (validKanjiForms.has(entry.word) || validReadings.has(entry.word)) && entry.forms.some(
1812
- (form) => validKanjiForms.has(form.form) || validReadings.has(form.form)
1813
- )) {
1814
- const wfEntry = entriesWithFormsGlobal.get(entry.word);
1815
- if (wfEntry) wfEntry.push(entry);
1816
- else entriesWithFormsGlobal.set(entry.word, [entry]);
1817
1782
  }
1783
+ if (isValidArray(entry.forms)) {
1784
+ for (const form of entry.forms)
1785
+ if (form.form && typeof form.form === "string" && validReadings.has(form.form))
1786
+ validFormsEntries.add(entry.word);
1818
1787
  }
1819
- ents.length = 0;
1820
- const posMap = /* @__PURE__ */ new Map();
1821
- const vte = Array.from(
1822
- validTitleEntries.values()
1823
- ).flat();
1824
- const fge = Array.from(
1825
- entriesWithFormTitlesGlobal.values()
1826
- ).flat();
1827
- const wfe = Array.from(
1828
- entriesWithFormsGlobal.values()
1829
- ).flat();
1830
- for (const pos of [
1831
- "\u540D\u8A5E",
1832
- "\u52D5\u8A5E",
1833
- "\u6210\u53E5",
1834
- "\u526F\u8A5E",
1835
- "\u5F62\u5BB9\u52D5\u8A5E",
1836
- "\u52A9\u8A5E",
1837
- "\u611F\u52D5\u8A5E",
1838
- "\u4EE3\u540D\u8A5E",
1839
- "\u63A5\u5C3E\u8F9E",
1840
- "\u63A5\u982D\u8A9E",
1841
- "\u9020\u8A9E\u6210\u5206",
1842
- "\u7565\u8A9E",
1843
- "\u56FA\u6709\u540D\u8A5E",
1844
- "\u4EBA\u79F0\u4EE3\u540D\u8A5E",
1845
- "\u63A5\u982D\u8F9E",
1846
- "\u63A5\u7D9A\u52A9\u8A5E",
1847
- "\u9593\u6295\u8A5E",
1848
- "\u52A9\u52D5\u8A5E",
1849
- "\u5F62\u5BB9\u8A5E",
1850
- "\u7E2E\u7D04\u5F62",
1851
- "\u63A5\u8F9E",
1852
- "\u63A5\u7D9A\u8A5E",
1853
- "\u9023\u4F53\u8A5E",
1854
- "\u4EBA\u540D",
1855
- "\u8A18\u53F7",
1856
- "\u6570\u8A5E",
1857
- "\u6163\u7528\u53E5",
1858
- "\u3053\u3068\u308F\u3056",
1859
- "\u52A9\u6570\u8A5E",
1860
- "\u82F1\u6570\u5B57\u6DF7\u5408\u8868\u8A18",
1861
- "\u52D5\u8A5E\u53E5",
1862
- "\u6210\u8A9E",
1863
- "\u610F\u7FA9",
1864
- "\u982D\u5B57\u8A9E",
1865
- "\u63A5\u5C3E\u8A9E"
1866
- ]) {
1867
- for (const te of vte)
1868
- if (te.pos_title === pos || te.pos_title === "\u548C\u8A9E\u306E\u6F22\u5B57\u8868\u8A18") {
1869
- if (!posMap.has(pos)) posMap.set(pos, {});
1870
- const posEntries = posMap.get(pos);
1871
- if (posEntries.title === void 0)
1872
- posEntries.title = /* @__PURE__ */ new Map();
1873
- const entryList2 = posEntries.title.get(te.word);
1874
- if (entryList2) entryList2.push(te);
1875
- else posEntries.title.set(te.word, [te]);
1876
- }
1877
- for (const ft of fge)
1878
- if (ft.pos_title === pos) {
1879
- if (!posMap.has(pos)) posMap.set(pos, {});
1880
- const posEntries = posMap.get(pos);
1881
- if (posEntries.formTitle === void 0)
1882
- posEntries.formTitle = /* @__PURE__ */ new Map();
1883
- const entryList2 = posEntries.formTitle.get(ft.word);
1884
- if (entryList2) entryList2.push(ft);
1885
- else posEntries.formTitle.set(ft.word, [ft]);
1886
- }
1887
- for (const wf of wfe)
1888
- if (wf.pos_title === pos) {
1889
- if (!posMap.has(pos)) posMap.set(pos, {});
1890
- const posEntries = posMap.get(pos);
1891
- if (posEntries.form === void 0)
1892
- posEntries.form = /* @__PURE__ */ new Map();
1893
- const entryList2 = posEntries.form.get(wf.word);
1894
- if (entryList2) entryList2.push(wf);
1895
- else posEntries.form.set(wf.word, [wf]);
1896
- }
1788
+ } else if (validReadings.has(entry.word)) {
1789
+ valid = true;
1790
+ const ftEntry = entriesWithFormTitlesGlobal.get(entry.word);
1791
+ if (ftEntry) ftEntry.push(entry);
1792
+ else entriesWithFormTitlesGlobal.set(entry.word, [entry]);
1793
+ }
1794
+ if (valid) {
1795
+ const tEntry = validTitleEntries.get(entry.word);
1796
+ if (tEntry) tEntry.push(entry);
1797
+ else validTitleEntries.set(entry.word, [entry]);
1798
+ }
1799
+ if (isValidArray(entry.forms) && (validKanjiForms.has(entry.word) || validReadings.has(entry.word)) && entry.forms.some(
1800
+ (form) => validKanjiForms.has(form.form) || validReadings.has(form.form)
1801
+ )) {
1802
+ const wfEntry = entriesWithFormsGlobal.get(entry.word);
1803
+ if (wfEntry) wfEntry.push(entry);
1804
+ else entriesWithFormsGlobal.set(entry.word, [entry]);
1805
+ }
1806
+ }
1807
+ ents.length = 0;
1808
+ const posMap = /* @__PURE__ */ new Map();
1809
+ const vte = Array.from(
1810
+ validTitleEntries.values()
1811
+ ).flat();
1812
+ const fge = Array.from(
1813
+ entriesWithFormTitlesGlobal.values()
1814
+ ).flat();
1815
+ const wfe = Array.from(
1816
+ entriesWithFormsGlobal.values()
1817
+ ).flat();
1818
+ for (const pos of [
1819
+ "\u540D\u8A5E",
1820
+ "\u52D5\u8A5E",
1821
+ "\u6210\u53E5",
1822
+ "\u526F\u8A5E",
1823
+ "\u5F62\u5BB9\u52D5\u8A5E",
1824
+ "\u52A9\u8A5E",
1825
+ "\u611F\u52D5\u8A5E",
1826
+ "\u4EE3\u540D\u8A5E",
1827
+ "\u63A5\u5C3E\u8F9E",
1828
+ "\u63A5\u982D\u8A9E",
1829
+ "\u9020\u8A9E\u6210\u5206",
1830
+ "\u7565\u8A9E",
1831
+ "\u56FA\u6709\u540D\u8A5E",
1832
+ "\u4EBA\u79F0\u4EE3\u540D\u8A5E",
1833
+ "\u63A5\u982D\u8F9E",
1834
+ "\u63A5\u7D9A\u52A9\u8A5E",
1835
+ "\u9593\u6295\u8A5E",
1836
+ "\u52A9\u52D5\u8A5E",
1837
+ "\u5F62\u5BB9\u8A5E",
1838
+ "\u7E2E\u7D04\u5F62",
1839
+ "\u63A5\u8F9E",
1840
+ "\u63A5\u7D9A\u8A5E",
1841
+ "\u9023\u4F53\u8A5E",
1842
+ "\u4EBA\u540D",
1843
+ "\u8A18\u53F7",
1844
+ "\u6570\u8A5E",
1845
+ "\u6163\u7528\u53E5",
1846
+ "\u3053\u3068\u308F\u3056",
1847
+ "\u52A9\u6570\u8A5E",
1848
+ "\u82F1\u6570\u5B57\u6DF7\u5408\u8868\u8A18",
1849
+ "\u52D5\u8A5E\u53E5",
1850
+ "\u6210\u8A9E",
1851
+ "\u610F\u7FA9",
1852
+ "\u982D\u5B57\u8A9E",
1853
+ "\u63A5\u5C3E\u8A9E"
1854
+ ]) {
1855
+ if (!posMap.has(pos)) posMap.set(pos, {});
1856
+ for (const te of vte)
1857
+ if (te.pos_title === pos || te.pos_title === "\u548C\u8A9E\u306E\u6F22\u5B57\u8868\u8A18") {
1858
+ const posEntries = posMap.get(pos);
1859
+ if (posEntries.title === void 0)
1860
+ posEntries.title = /* @__PURE__ */ new Map();
1861
+ const entryList2 = posEntries.title.get(
1862
+ te.word
1863
+ );
1864
+ if (entryList2) entryList2.push(te);
1865
+ else posEntries.title.set(te.word, [te]);
1897
1866
  }
1898
- vte.length = 0;
1899
- fge.length = 0;
1900
- wfe.length = 0;
1901
- const wordEntriesPairs = [];
1902
- for (const word of validWords) {
1903
- const poses = /* @__PURE__ */ new Set();
1904
- for (const m of word.meanings) {
1905
- if (m.partOfSpeech)
1906
- for (const note of m.partOfSpeech) {
1907
- const noteEntry = noteMap.get(note);
1908
- if (noteEntry && noteEntry.length === 3) {
1909
- const notePos = noteEntry[2];
1910
- if (Array.isArray(notePos))
1911
- for (const pos of notePos) {
1912
- if (!poses.has(pos)) poses.add(pos);
1913
- }
1914
- else if (typeof notePos === "string" && !poses.has(notePos))
1915
- poses.add(notePos);
1916
- }
1917
- }
1918
- }
1919
- const validWordReadings = new Set(
1920
- word.readings.filter(
1921
- (r) => r.notes === void 0 || !r.notes.some((note) => notSearchedForms.has(note)) || r.commonness !== void 0
1922
- ).map((r) => r.reading)
1867
+ for (const ft of fge)
1868
+ if (ft.pos_title === pos) {
1869
+ const posEntries = posMap.get(pos);
1870
+ if (posEntries.formTitle === void 0)
1871
+ posEntries.formTitle = /* @__PURE__ */ new Map();
1872
+ const entryList2 = posEntries.formTitle.get(ft.word);
1873
+ if (entryList2) entryList2.push(ft);
1874
+ else posEntries.formTitle.set(ft.word, [ft]);
1875
+ }
1876
+ for (const wf of wfe)
1877
+ if (wf.pos_title === pos) {
1878
+ const posEntries = posMap.get(pos);
1879
+ if (posEntries.form === void 0)
1880
+ posEntries.form = /* @__PURE__ */ new Map();
1881
+ const entryList2 = posEntries.form.get(
1882
+ wf.word
1923
1883
  );
1924
- const validWordKanjiForms = word.kanjiForms ? new Set(
1925
- word.kanjiForms.filter(
1926
- (kf) => kf.notes === void 0 || !kf.notes.some(
1927
- (note) => notSearchedForms.has(note)
1928
- ) || kf.commonness !== void 0
1929
- ).map((kf) => kf.form)
1930
- ) : void 0;
1931
- const entriesWithTitles = [];
1932
- const entriesWithFormTitles = [];
1933
- const entriesWithForms = [];
1934
- if (poses.size > 0)
1935
- for (const pos of poses) {
1936
- const posEntries = posMap.get(pos);
1937
- if (posEntries) {
1938
- if (validWordKanjiForms && (posEntries.title || posEntries.form))
1939
- for (const kf of validWordKanjiForms) {
1940
- const te = (_a = posEntries.title) == null ? void 0 : _a.get(kf);
1941
- const fe = (_b = posEntries.form) == null ? void 0 : _b.get(kf);
1942
- if (te)
1943
- entriesWithTitles.push(
1944
- ...te.filter(
1945
- (ent) => validFormOfEntries.has(ent.word) || validGlossesEntries.has(ent.word) || validFormsEntries.has(ent.word)
1946
- )
1947
- );
1948
- if (fe)
1949
- entriesWithForms.push(
1950
- ...fe.filter(
1951
- (ent) => ent.forms && ent.forms.some(
1952
- (form) => validWordKanjiForms.has(form.form) || validWordReadings.has(form.form)
1953
- )
1954
- )
1955
- );
1956
- }
1957
- if (posEntries.title || posEntries.formTitle || posEntries.form)
1958
- for (const r of validWordReadings) {
1959
- const te = (_c = posEntries.title) == null ? void 0 : _c.get(r);
1960
- const fe = (_d = posEntries.form) == null ? void 0 : _d.get(r);
1961
- const fte = (_e = posEntries.formTitle) == null ? void 0 : _e.get(r);
1962
- if (te)
1963
- entriesWithTitles.push(
1964
- ...te.filter(
1965
- (ent) => ent.forms && validWordKanjiForms && ent.forms.some(
1966
- (form) => validWordKanjiForms.has(form.form)
1967
- ) || validWordKanjiForms === void 0
1968
- )
1969
- );
1970
- if (fe)
1971
- entriesWithForms.push(
1972
- ...fe.filter(
1973
- (ent) => ent.forms && ent.forms.some(
1974
- (form) => validWordKanjiForms && validWordKanjiForms.has(form.form) || validWordReadings.has(form.form)
1975
- )
1976
- )
1977
- );
1978
- if (fte) entriesWithFormTitles.push(...fte);
1979
- }
1980
- }
1884
+ if (entryList2) entryList2.push(wf);
1885
+ else posEntries.form.set(wf.word, [wf]);
1886
+ }
1887
+ }
1888
+ vte.length = 0;
1889
+ fge.length = 0;
1890
+ wfe.length = 0;
1891
+ const wordEntriesPairs = [];
1892
+ for (const word of validWords) {
1893
+ const poses = /* @__PURE__ */ new Set();
1894
+ for (const m of word.meanings) {
1895
+ if (m.partOfSpeech)
1896
+ for (const note of m.partOfSpeech) {
1897
+ const noteEntry = noteMap.get(note);
1898
+ if (noteEntry && noteEntry.length === 3) {
1899
+ const notePos = noteEntry[2];
1900
+ if (Array.isArray(notePos))
1901
+ for (const pos of notePos) {
1902
+ if (!poses.has(pos)) poses.add(pos);
1903
+ }
1904
+ else if (typeof notePos === "string" && !poses.has(notePos))
1905
+ poses.add(notePos);
1981
1906
  }
1982
- if (entriesWithTitles.length === 0 && entriesWithFormTitles.length === 0 && entriesWithForms.length === 0) {
1907
+ }
1908
+ }
1909
+ const validWordReadings = new Set(
1910
+ word.readings.filter(
1911
+ (r) => r.notes === void 0 || !r.notes.some((note) => notSearchedForms.has(note)) || r.commonness !== void 0
1912
+ ).map((r) => r.reading)
1913
+ );
1914
+ const validWordKanjiForms = word.kanjiForms ? new Set(
1915
+ word.kanjiForms.filter(
1916
+ (kf) => kf.notes === void 0 || !kf.notes.some((note) => notSearchedForms.has(note)) || kf.commonness !== void 0
1917
+ ).map((kf) => kf.form)
1918
+ ) : void 0;
1919
+ const entriesWithTitles = [];
1920
+ const entriesWithFormTitles = [];
1921
+ const entriesWithForms = [];
1922
+ if (poses.size > 0)
1923
+ for (const pos of poses) {
1924
+ const posEntries = posMap.get(pos);
1925
+ if (posEntries) {
1983
1926
  if (validWordKanjiForms)
1984
1927
  for (const kf of validWordKanjiForms) {
1985
- const te = validTitleEntries.get(kf);
1986
- const fe = entriesWithFormsGlobal.get(kf);
1928
+ const te = (_a = posEntries.title) == null ? void 0 : _a.get(kf);
1929
+ const fe = (_b = posEntries.form) == null ? void 0 : _b.get(kf);
1987
1930
  if (te)
1988
1931
  entriesWithTitles.push(
1989
1932
  ...te.filter(
@@ -2000,9 +1943,9 @@ async function getWordDefinitions(entryList, jmDict, generateFurigana) {
2000
1943
  );
2001
1944
  }
2002
1945
  for (const r of validWordReadings) {
2003
- const te = validTitleEntries.get(r);
2004
- const fe = entriesWithFormsGlobal.get(r);
2005
- const fte = entriesWithFormTitlesGlobal.get(r);
1946
+ const te = (_c = posEntries.title) == null ? void 0 : _c.get(r);
1947
+ const fe = (_d = posEntries.form) == null ? void 0 : _d.get(r);
1948
+ const fte = (_e = posEntries.formTitle) == null ? void 0 : _e.get(r);
2006
1949
  if (te)
2007
1950
  entriesWithTitles.push(
2008
1951
  ...te.filter(
@@ -2022,148 +1965,197 @@ async function getWordDefinitions(entryList, jmDict, generateFurigana) {
2022
1965
  if (fte) entriesWithFormTitles.push(...fte);
2023
1966
  }
2024
1967
  }
2025
- if (entriesWithTitles.length > 0 && (entriesWithFormTitles.length > 0 || entriesWithForms.length > 0))
2026
- wordEntriesPairs.push({
2027
- word,
2028
- readings: validWordReadings,
2029
- ...validWordKanjiForms ? { kanjiForms: validWordKanjiForms } : {},
2030
- entriesWithTitles,
2031
- entriesWithFormTitles,
2032
- entriesWithForms
2033
- });
2034
1968
  }
2035
- for (const pair of wordEntriesPairs) {
2036
- const definitions = [];
2037
- const kanjiFormEntries = [];
2038
- const readingWithFormsEntries = [];
2039
- const readingEntries = [];
2040
- const titleFormMap = /* @__PURE__ */ new Map();
2041
- const refsMap = /* @__PURE__ */ new Map();
2042
- const readingForms = /* @__PURE__ */ new Set();
2043
- for (const ent of pair.entriesWithTitles) {
2044
- const validFormOf = validFormOfEntries.has(ent.word);
2045
- const validGlosses = validGlossesEntries.has(ent.word);
2046
- const validForms = validFormsEntries.has(ent.word);
2047
- if (pair.kanjiForms && pair.kanjiForms.has(ent.word) && (validFormOf || validGlosses || validForms)) {
2048
- kanjiFormEntries.push(ent);
2049
- if ((validFormOf || validGlosses) && isValidArray(ent.senses))
2050
- for (const sense of ent.senses) {
2051
- if (validFormOf && isValidArray(sense.form_of)) {
2052
- for (const form of sense.form_of)
2053
- if (form.word && typeof form.word === "string" && pair.readings.has(form.word)) {
2054
- const elem = titleFormMap.get(
2055
- form.word
2056
- );
2057
- if (!elem)
2058
- titleFormMap.set(
2059
- form.word,
2060
- /* @__PURE__ */ new Set([ent.word])
2061
- );
2062
- else elem.add(ent.word);
2063
- }
2064
- } else if (validGlosses && isStringArray(sense.glosses)) {
2065
- for (const gloss of sense.glosses) {
2066
- let reading = void 0;
2067
- if (gloss !== void 0) {
2068
- if (gloss.trim().includes("\u306E\u6F22\u5B57\u8868\u8A18\u3002") || gloss.trim().includes("\u3092\u53C2\u7167\u3002")) {
2069
- for (const r of pair.readings)
2070
- if (gloss.trim().includes(r)) {
2071
- reading = r;
2072
- break;
2073
- }
1969
+ if (entriesWithTitles.length === 0 && entriesWithFormTitles.length === 0 && entriesWithForms.length === 0) {
1970
+ if (validWordKanjiForms)
1971
+ for (const kf of validWordKanjiForms) {
1972
+ const te = validTitleEntries.get(kf);
1973
+ const fe = entriesWithFormsGlobal.get(kf);
1974
+ if (te)
1975
+ entriesWithTitles.push(
1976
+ ...te.filter(
1977
+ (ent) => validFormOfEntries.has(ent.word) || validGlossesEntries.has(ent.word) || validFormsEntries.has(ent.word)
1978
+ )
1979
+ );
1980
+ if (fe)
1981
+ entriesWithForms.push(
1982
+ ...fe.filter(
1983
+ (ent) => ent.forms && ent.forms.some(
1984
+ (form) => validWordKanjiForms.has(form.form) || validWordReadings.has(form.form)
1985
+ )
1986
+ )
1987
+ );
1988
+ }
1989
+ for (const r of validWordReadings) {
1990
+ const te = validTitleEntries.get(r);
1991
+ const fe = entriesWithFormsGlobal.get(r);
1992
+ const fte = entriesWithFormTitlesGlobal.get(r);
1993
+ if (te)
1994
+ entriesWithTitles.push(
1995
+ ...te.filter(
1996
+ (ent) => ent.forms && validWordKanjiForms && ent.forms.some(
1997
+ (form) => validWordKanjiForms.has(form.form)
1998
+ ) || validWordKanjiForms === void 0
1999
+ )
2000
+ );
2001
+ if (fe)
2002
+ entriesWithForms.push(
2003
+ ...fe.filter(
2004
+ (ent) => ent.forms && ent.forms.some(
2005
+ (form) => validWordKanjiForms && validWordKanjiForms.has(form.form) || validWordReadings.has(form.form)
2006
+ )
2007
+ )
2008
+ );
2009
+ if (fte) entriesWithFormTitles.push(...fte);
2010
+ }
2011
+ }
2012
+ if (entriesWithTitles.length > 0 && (entriesWithFormTitles.length > 0 || entriesWithForms.length > 0))
2013
+ wordEntriesPairs.push({
2014
+ word,
2015
+ readings: validWordReadings,
2016
+ ...validWordKanjiForms ? { kanjiForms: validWordKanjiForms } : {},
2017
+ entriesWithTitles,
2018
+ entriesWithFormTitles,
2019
+ entriesWithForms
2020
+ });
2021
+ }
2022
+ for (const pair of wordEntriesPairs) {
2023
+ const definitions = [];
2024
+ const kanjiFormEntries = [];
2025
+ const readingWithFormsEntries = [];
2026
+ const readingEntries = [];
2027
+ const titleFormMap = /* @__PURE__ */ new Map();
2028
+ const refsMap = /* @__PURE__ */ new Map();
2029
+ const readingForms = /* @__PURE__ */ new Set();
2030
+ for (const ent of pair.entriesWithTitles) {
2031
+ const validFormOf = validFormOfEntries.has(ent.word);
2032
+ const validGlosses = validGlossesEntries.has(ent.word);
2033
+ const validForms = validFormsEntries.has(ent.word);
2034
+ if (pair.kanjiForms && pair.kanjiForms.has(ent.word) && (validFormOf || validGlosses || validForms)) {
2035
+ kanjiFormEntries.push(ent);
2036
+ if ((validFormOf || validGlosses) && isValidArray(ent.senses))
2037
+ for (const sense of ent.senses) {
2038
+ if (validFormOf && isValidArray(sense.form_of)) {
2039
+ for (const form of sense.form_of)
2040
+ if (form.word && typeof form.word === "string" && pair.readings.has(form.word)) {
2041
+ const elem = titleFormMap.get(
2042
+ form.word
2043
+ );
2044
+ if (!elem)
2045
+ titleFormMap.set(form.word, /* @__PURE__ */ new Set([ent.word]));
2046
+ else elem.add(ent.word);
2047
+ }
2048
+ } else if (validGlosses && isStringArray(sense.glosses)) {
2049
+ for (const gloss of sense.glosses) {
2050
+ let reading = void 0;
2051
+ if (gloss !== void 0) {
2052
+ if (gloss.trim().includes("\u306E\u6F22\u5B57\u8868\u8A18\u3002") || gloss.trim().includes("\u3092\u53C2\u7167\u3002")) {
2053
+ for (const r of pair.readings)
2054
+ if (gloss.trim().includes(r)) {
2055
+ reading = r;
2056
+ break;
2074
2057
  }
2075
- }
2076
- if (reading) {
2077
- const elem = refsMap.get(reading);
2078
- if (!elem)
2079
- refsMap.set(reading, /* @__PURE__ */ new Set([ent.word]));
2080
- else elem.add(ent.word);
2081
- }
2082
2058
  }
2083
2059
  }
2060
+ if (reading) {
2061
+ const elem = refsMap.get(reading);
2062
+ if (!elem) refsMap.set(reading, /* @__PURE__ */ new Set([ent.word]));
2063
+ else elem.add(ent.word);
2064
+ }
2084
2065
  }
2085
- if (validForms && isValidArray(ent.forms)) {
2086
- for (const form of ent.forms)
2087
- if (form.form && typeof form.form === "string" && pair.readings.has(form.form))
2088
- readingForms.add(form.form);
2089
2066
  }
2090
- } else if (pair.readings.has(ent.word) && isValidArray(ent.forms) && pair.kanjiForms && ent.forms.some((form) => pair.kanjiForms.has(form.form)))
2091
- readingWithFormsEntries.push(ent);
2092
- else if (pair.kanjiForms === void 0 && pair.readings.has(ent.word))
2093
- readingEntries.push(ent);
2094
- }
2095
- for (const entry of pair.entriesWithForms) {
2096
- const elem = titleFormMap.get(entry.word);
2097
- if (elem && entry.forms.some((form) => elem.has(form.form)))
2098
- readingWithFormsEntries.push(entry);
2099
- }
2100
- for (const entry of pair.entriesWithFormTitles) {
2101
- if (readingForms.has(entry.word)) {
2102
- readingWithFormsEntries.push(entry);
2103
- continue;
2104
- }
2105
- if (pair.kanjiForms) {
2106
- const ft = refsMap.get(entry.word);
2107
- if (ft && ft.intersection(pair.kanjiForms).size > 0)
2108
- readingWithFormsEntries.push(entry);
2109
2067
  }
2068
+ if (validForms && isValidArray(ent.forms)) {
2069
+ for (const form of ent.forms)
2070
+ if (form.form && typeof form.form === "string" && pair.readings.has(form.form))
2071
+ readingForms.add(form.form);
2110
2072
  }
2111
- let parsedReadingWithFormsEntries = false;
2112
- for (const entry of kanjiFormEntries)
2113
- if (entry.pos_title === "\u548C\u8A9E\u306E\u6F22\u5B57\u8868\u8A18" && readingWithFormsEntries.length > 0) {
2114
- if (!parsedReadingWithFormsEntries)
2115
- parsedReadingWithFormsEntries = true;
2116
- for (const ref of readingWithFormsEntries)
2117
- parseEntry(ref, definitions, definitionMap);
2118
- } else parseEntry(entry, definitions, definitionMap);
2119
- if (!parsedReadingWithFormsEntries && readingWithFormsEntries.length > 0) {
2120
- parsedReadingWithFormsEntries = true;
2121
- for (const ref of readingWithFormsEntries)
2122
- parseEntry(ref, definitions, definitionMap);
2123
- }
2124
- if (readingEntries.length > 0)
2125
- for (const readingEntry of readingEntries)
2126
- parseEntry(readingEntry, definitions, definitionMap);
2127
- if (definitions.length > 0)
2128
- japaneseDefinitions.push({
2129
- wordID: pair.word.id,
2130
- definitions
2131
- });
2073
+ } else if (pair.readings.has(ent.word) && isValidArray(ent.forms) && pair.kanjiForms && ent.forms.some((form) => pair.kanjiForms.has(form.form)))
2074
+ readingWithFormsEntries.push(ent);
2075
+ else if (pair.kanjiForms === void 0 && pair.readings.has(ent.word))
2076
+ readingEntries.push(ent);
2077
+ }
2078
+ for (const entry of pair.entriesWithForms) {
2079
+ const elem = titleFormMap.get(entry.word);
2080
+ if (elem && entry.forms.some((form) => elem.has(form.form)))
2081
+ readingWithFormsEntries.push(entry);
2082
+ }
2083
+ for (const entry of pair.entriesWithFormTitles) {
2084
+ if (readingForms.has(entry.word)) {
2085
+ readingWithFormsEntries.push(entry);
2086
+ continue;
2132
2087
  }
2133
- const kuroshiro = generateFurigana === true ? new Kuroshiro.default() : null;
2134
- if (kuroshiro !== null) await kuroshiro.init(new KuromojiAnalyzer());
2135
- const convert = kuroshiro !== null ? kuroshiro.convert.bind(kuroshiro) : null;
2136
- for (let i = 0; i < japaneseDefinitions.length; i++) {
2137
- const pair = japaneseDefinitions[i];
2138
- for (let j = 0; j < pair.definitions.length; j++) {
2139
- const defCount = definitionMap.get(
2140
- pair.definitions[j].definition
2141
- );
2142
- if (defCount && defCount.count > 1)
2143
- pair.definitions[j].mayNotBeAccurate = true;
2144
- if (convert !== null && !pair.definitions[j].definition.includes("\u30FB"))
2145
- pair.definitions[j].furigana = await convert(
2146
- pair.definitions[j].definition,
2147
- {
2148
- to: "hiragana",
2149
- mode: "furigana"
2150
- }
2151
- );
2152
- }
2153
- japaneseDefinitions[i] = pair;
2088
+ if (pair.kanjiForms) {
2089
+ const ft = refsMap.get(entry.word);
2090
+ if (ft && !ft.isDisjointFrom(pair.kanjiForms))
2091
+ readingWithFormsEntries.push(entry);
2154
2092
  }
2155
- resolve(japaneseDefinitions);
2156
- } catch (err) {
2157
- reject(err);
2158
2093
  }
2094
+ let parsedReadingWithFormsEntries = false;
2095
+ for (const entry of kanjiFormEntries)
2096
+ if (entry.pos_title === "\u548C\u8A9E\u306E\u6F22\u5B57\u8868\u8A18" && readingWithFormsEntries.length > 0) {
2097
+ if (!parsedReadingWithFormsEntries)
2098
+ parsedReadingWithFormsEntries = true;
2099
+ for (const ref of readingWithFormsEntries)
2100
+ parseEntry(ref, definitions, definitionMap);
2101
+ } else parseEntry(entry, definitions, definitionMap);
2102
+ if (!parsedReadingWithFormsEntries && readingWithFormsEntries.length > 0) {
2103
+ parsedReadingWithFormsEntries = true;
2104
+ for (const ref of readingWithFormsEntries)
2105
+ parseEntry(ref, definitions, definitionMap);
2106
+ }
2107
+ if (readingEntries.length > 0)
2108
+ for (const readingEntry of readingEntries)
2109
+ parseEntry(readingEntry, definitions, definitionMap);
2110
+ if (definitions.length > 0)
2111
+ japaneseDefinitions.push({
2112
+ wordID: pair.word.id,
2113
+ definitions
2114
+ });
2115
+ }
2116
+ for (let i = 0; i < japaneseDefinitions.length; i++) {
2117
+ const pair = japaneseDefinitions[i];
2118
+ for (let j = 0; j < pair.definitions.length; j++) {
2119
+ const defCount = definitionMap.get(
2120
+ pair.definitions[j].definition
2121
+ );
2122
+ if (defCount && defCount.count > 1)
2123
+ pair.definitions[j].mayNotBeAccurate = true;
2124
+ }
2125
+ japaneseDefinitions[i] = pair;
2126
+ }
2127
+ return japaneseDefinitions;
2128
+ }
2129
+ async function getWordDefinitionsWithFurigana(entryList, jmDict) {
2130
+ return new Promise(async (resolve) => {
2131
+ const japaneseDefinitions = getWordDefinitions(
2132
+ entryList,
2133
+ jmDict
2134
+ );
2135
+ const kuroshiro = new Kuroshiro.default();
2136
+ await kuroshiro.init(new KuromojiAnalyzer());
2137
+ const convert = kuroshiro.convert.bind(kuroshiro);
2138
+ for (let i = 0; i < japaneseDefinitions.length; i++) {
2139
+ const pair = japaneseDefinitions[i];
2140
+ for (let j = 0; j < pair.definitions.length; j++)
2141
+ if (!pair.definitions[j].definition.includes("\u30FB"))
2142
+ pair.definitions[j].furigana = await convert(
2143
+ pair.definitions[j].definition,
2144
+ {
2145
+ to: "hiragana",
2146
+ mode: "furigana"
2147
+ }
2148
+ );
2149
+ japaneseDefinitions[i] = pair;
2150
+ }
2151
+ resolve(japaneseDefinitions);
2159
2152
  });
2160
2153
  }
2161
- function lookupWordNote(key, notes, tags, required, fallback) {
2154
+ function lookupWordNote(key, notes, tags) {
2162
2155
  const info = noteMap.get(key.toLowerCase());
2163
2156
  if (!info) {
2164
- if (required) throw new Error(`Invalid note info for ${key}`);
2165
- if (notes) notes.push(fallback != null ? fallback : key);
2166
- return { note: fallback != null ? fallback : key };
2157
+ if (notes) notes.push(key);
2158
+ return { note: key };
2167
2159
  }
2168
2160
  const tag = `word::${info[0]}`;
2169
2161
  if (tags && !tags.includes(tag)) tags.push(tag);
@@ -2174,70 +2166,65 @@ var wordAddNoteArray = (arr, cb) => {
2174
2166
  if (!arr) return;
2175
2167
  for (const v of arr) cb(v);
2176
2168
  };
2177
- function getWord(dict, id, kanjiDic, examples, definitions, dictWord, noteTypeName, deckPath) {
2169
+ function getWord(word, dict, kanjiDic, examples, definitions, noteTypeName, deckPath) {
2178
2170
  var _a;
2179
- try {
2180
- if (!dictWord && id && dict)
2181
- dictWord = dict.find((entry) => entry.id === id);
2182
- if (dictWord) {
2183
- const word = {
2184
- id: dictWord.id,
2185
- readings: [],
2186
- translations: [],
2187
- noteID: `word_${dictWord.id}`,
2188
- ...noteTypeName ? { noteTypeName } : {},
2189
- ...deckPath ? { deckPath } : {},
2190
- tags: []
2191
- };
2192
- if (dictWord.isCommon === true) {
2193
- word.common = true;
2194
- word.tags.push("word::common");
2195
- }
2196
- if (dictWord.kanjiForms)
2197
- word.kanjiForms = dictWord.kanjiForms.map(
2198
- (dictKanjiForm) => ({
2199
- kanjiForm: dictKanjiForm.form,
2200
- ...dictKanjiForm.notes ? {
2201
- notes: dictKanjiForm.notes.map((note) => {
2202
- var _a2;
2203
- const noteAndTag = lookupWordNote(
2204
- note,
2205
- void 0,
2206
- word.tags,
2207
- false,
2208
- note
2209
- );
2210
- return capitalizeString((_a2 = noteAndTag.note) != null ? _a2 : note);
2211
- })
2212
- } : {},
2213
- ...dictKanjiForm.commonness && dictKanjiForm.commonness.length > 0 ? { common: true } : {}
2214
- })
2215
- );
2216
- word.readings = dictWord.readings.map((dictReading) => ({
2217
- reading: dictReading.reading,
2218
- ...dictReading.kanjiFormRestrictions || dictReading.notes ? {
2219
- notes: [
2220
- ...dictReading.kanjiFormRestrictions ? dictReading.kanjiFormRestrictions.map(
2221
- (restriction) => `Reading restricted to ${restriction}`
2222
- ) : [],
2223
- ...dictReading.notes ? dictReading.notes.map((note) => {
2224
- var _a2;
2171
+ let dictWord = void 0;
2172
+ if (typeof word === "string" && dict)
2173
+ dictWord = dict.find((entry) => entry.id === word);
2174
+ else if (typeof word === "object") dictWord = word;
2175
+ if (dictWord) {
2176
+ const word2 = {
2177
+ id: dictWord.id,
2178
+ readings: [],
2179
+ translations: [],
2180
+ noteID: `word_${dictWord.id}`,
2181
+ noteTypeName,
2182
+ deckPath,
2183
+ tags: []
2184
+ };
2185
+ if (dictWord.isCommon === true) {
2186
+ word2.common = true;
2187
+ word2.tags.push("word::common");
2188
+ }
2189
+ if (dictWord.kanjiForms)
2190
+ word2.kanjiForms = dictWord.kanjiForms.map(
2191
+ (dictKanjiForm) => ({
2192
+ kanjiForm: dictKanjiForm.form,
2193
+ ...dictKanjiForm.notes ? {
2194
+ notes: dictKanjiForm.notes.map((note) => {
2225
2195
  const noteAndTag = lookupWordNote(
2226
2196
  note,
2227
2197
  void 0,
2228
- word.tags,
2229
- false,
2230
- note
2198
+ word2.tags
2231
2199
  );
2232
- return capitalizeString((_a2 = noteAndTag.note) != null ? _a2 : note);
2233
- }) : []
2234
- ]
2235
- } : {},
2236
- ...dictReading.commonness && dictReading.commonness.length > 0 ? { common: true } : {}
2237
- }));
2238
- word.translations = dictWord.meanings.map((dictMeaning) => {
2239
- if (!dictMeaning.translations)
2240
- throw new Error(`No translations for ${dictWord.id}`);
2200
+ return capitalizeString(noteAndTag.note);
2201
+ })
2202
+ } : {},
2203
+ ...dictKanjiForm.commonness && dictKanjiForm.commonness.length > 0 ? { common: true } : {}
2204
+ })
2205
+ );
2206
+ word2.readings = dictWord.readings.map((dictReading) => ({
2207
+ reading: dictReading.reading,
2208
+ ...dictReading.kanjiFormRestrictions || dictReading.notes ? {
2209
+ notes: [
2210
+ ...dictReading.kanjiFormRestrictions ? dictReading.kanjiFormRestrictions.map(
2211
+ (restriction) => `Reading restricted to ${restriction}`
2212
+ ) : [],
2213
+ ...dictReading.notes ? dictReading.notes.map((note) => {
2214
+ const noteAndTag = lookupWordNote(
2215
+ note,
2216
+ void 0,
2217
+ word2.tags
2218
+ );
2219
+ return capitalizeString(noteAndTag.note);
2220
+ }) : []
2221
+ ]
2222
+ } : {},
2223
+ ...dictReading.commonness && dictReading.commonness.length > 0 ? { common: true } : {}
2224
+ }));
2225
+ word2.translations = [];
2226
+ for (const dictMeaning of dictWord.meanings)
2227
+ if (dictMeaning.translations) {
2241
2228
  const translationTypes = [];
2242
2229
  const translations = dictMeaning.translations.map(
2243
2230
  (translation) => {
@@ -2245,13 +2232,13 @@ function getWord(dict, id, kanjiDic, examples, definitions, dictWord, noteTypeNa
2245
2232
  else {
2246
2233
  if (translation.type === "lit") {
2247
2234
  translationTypes.push("Literal meaning");
2248
- word.tags.push("word::literal_meaning");
2235
+ word2.tags.push("word::literal_meaning");
2249
2236
  } else if (translation.type === "expl") {
2250
2237
  translationTypes.push("Explanation");
2251
- word.tags.push("word::explanation");
2238
+ word2.tags.push("word::explanation");
2252
2239
  } else if (translation.type === "tm") {
2253
2240
  translationTypes.push("Trademark");
2254
- word.tags.push("word::trademark");
2241
+ word2.tags.push("word::trademark");
2255
2242
  }
2256
2243
  return translation.translation;
2257
2244
  }
@@ -2269,15 +2256,15 @@ function getWord(dict, id, kanjiDic, examples, definitions, dictWord, noteTypeNa
2269
2256
  for (const t of translationTypes) notes.push(t);
2270
2257
  wordAddNoteArray(
2271
2258
  dictMeaning.partOfSpeech,
2272
- (pos) => lookupWordNote(pos, notes, word.tags, true)
2259
+ (pos) => lookupWordNote(pos, notes, word2.tags)
2273
2260
  );
2274
2261
  wordAddNoteArray(
2275
2262
  dictMeaning.fields,
2276
- (field) => lookupWordNote(field, notes, word.tags, false, field)
2263
+ (field) => lookupWordNote(field, notes, word2.tags)
2277
2264
  );
2278
2265
  wordAddNoteArray(
2279
2266
  dictMeaning.dialects,
2280
- (dialect) => lookupWordNote(dialect, notes, word.tags, true)
2267
+ (dialect) => lookupWordNote(dialect, notes, word2.tags)
2281
2268
  );
2282
2269
  wordAddNoteArray(
2283
2270
  dictMeaning.antonyms,
@@ -2289,64 +2276,64 @@ function getWord(dict, id, kanjiDic, examples, definitions, dictWord, noteTypeNa
2289
2276
  );
2290
2277
  wordAddNoteArray(
2291
2278
  dictMeaning.info,
2292
- (info) => lookupWordNote(info, notes, word.tags, false, info)
2279
+ (info) => lookupWordNote(info, notes, word2.tags)
2293
2280
  );
2294
2281
  wordAddNoteArray(
2295
2282
  dictMeaning.misc,
2296
- (misc) => lookupWordNote(misc, notes, word.tags, false, misc)
2283
+ (misc) => lookupWordNote(misc, notes, word2.tags)
2297
2284
  );
2298
2285
  for (let i = 0; i < notes.length; i++)
2299
2286
  notes[i] = capitalizeString(notes[i]);
2300
- return {
2287
+ word2.translations.push({
2301
2288
  translation: translations.join("; "),
2302
2289
  notes
2303
- };
2304
- });
2305
- if (dictWord.usuallyInKana === true) {
2306
- word.usuallyInKana = true;
2307
- word.tags.push("word::usually_in_kana_for_all_senses");
2290
+ });
2308
2291
  }
2309
- if (kanjiDic && word.kanjiForms) {
2310
- word.kanji = [];
2311
- for (const kanjiForm of word.kanjiForms)
2312
- for (const char of kanjiForm.kanjiForm) {
2313
- if (word.kanji.some((kanji) => kanji.kanji === char))
2314
- continue;
2315
- const dictKanji = kanjiDic.find(
2316
- (kanji) => kanji.kanji === char
2317
- );
2318
- if (dictKanji) {
2319
- const kanjiObj = getKanji(kanjiDic, void 0, dictKanji);
2320
- word.kanji.push({
2321
- kanji: kanjiObj.kanji,
2322
- ...kanjiObj.meanings ? { meanings: kanjiObj.meanings } : {}
2323
- });
2324
- }
2325
- }
2326
- if (word.kanji.length === 0) {
2327
- delete word.kanji;
2328
- word.tags.push("word::no_kanji");
2292
+ if (dictWord.usuallyInKana === true) {
2293
+ word2.usuallyInKana = true;
2294
+ word2.tags.push("word::usually_in_kana_for_all_senses");
2295
+ }
2296
+ if (kanjiDic && word2.kanjiForms) {
2297
+ const kanji = [];
2298
+ for (const kanjiForm of word2.kanjiForms)
2299
+ for (const char of kanjiForm.kanjiForm) {
2300
+ if (!regexps.kanji.test(char) || kanji.some((kanji2) => kanji2.kanji === char))
2301
+ continue;
2302
+ const kanjiObj = getKanji(
2303
+ char,
2304
+ Array.isArray(kanjiDic) ? kanjiDic : kanjiDic.get(char)
2305
+ );
2306
+ if (kanjiObj)
2307
+ kanji.push({
2308
+ kanji: kanjiObj.kanji,
2309
+ ...kanjiObj.meanings && kanjiObj.meanings.length > 0 ? { meanings: kanjiObj.meanings } : {}
2310
+ });
2329
2311
  }
2330
- }
2331
- if (dictWord.hasPhrases === true && examples) {
2312
+ if (kanji.length > 0) word2.kanji = kanji;
2313
+ }
2314
+ if (dictWord.hasPhrases === true && examples) {
2315
+ const exampleList = Array.isArray(
2316
+ examples
2317
+ ) ? examples : examples.get(word2.id);
2318
+ if (exampleList) {
2332
2319
  const readings = new Set(
2333
- word.readings.filter(
2320
+ word2.readings.filter(
2334
2321
  (reading) => (reading.notes === void 0 || !reading.notes.some(
2335
2322
  (note) => notSearchedForms.has(note)
2336
- )) && (word.common === void 0 || reading.common === true)
2323
+ )) && (word2.common === void 0 || reading.common === true)
2337
2324
  ).map((reading) => reading.reading)
2338
2325
  );
2339
- const existValidKf = word.kanjiForms && word.kanjiForms.length > 0 ? word.kanjiForms.some(
2326
+ const existValidKf = word2.kanjiForms && word2.kanjiForms.length > 0 ? word2.kanjiForms.some(
2340
2327
  (kf) => (kf.notes === void 0 || !kf.notes.some(
2341
2328
  (note) => notSearchedForms.has(note)
2342
- )) && (word.common === void 0 || kf.common === true)
2329
+ )) && (word2.common === void 0 || kf.common === true)
2343
2330
  ) : void 0;
2344
- const kanjiForms = word.kanjiForms && word.kanjiForms.length > 0 ? new Set(
2345
- word.kanjiForms.filter((kanjiForm) => {
2331
+ const kanjiForms = word2.kanjiForms && word2.kanjiForms.length > 0 ? new Set(
2332
+ word2.kanjiForms.filter((kanjiForm) => {
2346
2333
  if (existValidKf === true)
2347
2334
  return (kanjiForm.notes === void 0 || !kanjiForm.notes.some(
2348
2335
  (note) => notSearchedForms.has(note)
2349
- )) && (word.common === void 0 || kanjiForm.common === true);
2336
+ )) && (word2.common === void 0 || kanjiForm.common === true);
2350
2337
  else return true;
2351
2338
  }).map((kanjiForm) => kanjiForm.kanjiForm)
2352
2339
  ) : void 0;
@@ -2354,12 +2341,12 @@ function getWord(dict, id, kanjiDic, examples, definitions, dictWord, noteTypeNa
2354
2341
  const readingMatchingKanjiFormExamples = [];
2355
2342
  const readingExamples = [];
2356
2343
  const readingMatchingKanjiForms = /* @__PURE__ */ new Set();
2357
- for (const example of examples)
2344
+ for (const example of exampleList)
2358
2345
  for (let i = 0; i < example.parts.length; i++) {
2359
2346
  const part = example.parts[i];
2360
2347
  const readingAsReadingMatch = part.reading !== void 0 && readings.has(part.reading);
2361
2348
  const readingAsInflectedFormMatch = part.inflectedForm !== void 0 && readings.has(part.inflectedForm);
2362
- const referenceIDMatch = part.referenceID !== void 0 && word.id !== void 0 && part.referenceID === word.id;
2349
+ const referenceIDMatch = part.referenceID !== void 0 && word2.id !== void 0 && part.referenceID === word2.id;
2363
2350
  if (kanjiForms && kanjiForms.has(part.baseForm) || referenceIDMatch) {
2364
2351
  if (readingAsReadingMatch || readingAsInflectedFormMatch) {
2365
2352
  readingMatchingKanjiFormExamples.push({
@@ -2385,7 +2372,7 @@ function getWord(dict, id, kanjiDic, examples, definitions, dictWord, noteTypeNa
2385
2372
  kanjiFormExamples = kanjiFormExamples.filter(
2386
2373
  (ex) => ex.form && readingMatchingKanjiForms.has(ex.form)
2387
2374
  );
2388
- const includeKanjiFormExamples = word.kanjiForms !== void 0;
2375
+ const includeKanjiFormExamples = word2.kanjiForms !== void 0;
2389
2376
  let wordExamples = [
2390
2377
  ...includeKanjiFormExamples ? [...readingMatchingKanjiFormExamples, ...kanjiFormExamples] : [],
2391
2378
  ...!includeKanjiFormExamples ? readingExamples : []
@@ -2393,14 +2380,14 @@ function getWord(dict, id, kanjiDic, examples, definitions, dictWord, noteTypeNa
2393
2380
  readingMatchingKanjiForms.clear();
2394
2381
  const glossSpecificExamples = [];
2395
2382
  const seenPhrases = /* @__PURE__ */ new Set();
2396
- for (let i = 0; i < word.translations.length; i++) {
2383
+ for (let i = 0; i < word2.translations.length; i++) {
2397
2384
  outer: for (const example of wordExamples) {
2398
2385
  if (seenPhrases.has(example.ex.phrase)) continue;
2399
2386
  for (let j = 0; j < example.ex.parts.length; j++) {
2400
2387
  const part = example.ex.parts[j];
2401
2388
  if (j === example.partIndex && part.glossNumber === i + 1) {
2402
2389
  example.ex.glossNumber = {
2403
- wordId: word.id,
2390
+ wordId: word2.id,
2404
2391
  glossNumber: i + 1
2405
2392
  };
2406
2393
  glossSpecificExamples.push(example);
@@ -2421,7 +2408,7 @@ function getWord(dict, id, kanjiDic, examples, definitions, dictWord, noteTypeNa
2421
2408
  ).slice(0, 5 - glossSpecificExamples.length)
2422
2409
  ];
2423
2410
  if (wordExamples.length > 0) {
2424
- word.phrases = (wordExamples.length > 5 ? wordExamples.slice(0, 5) : wordExamples).map((ex) => {
2411
+ word2.phrases = (wordExamples.length > 5 ? wordExamples.slice(0, 5) : wordExamples).map((ex) => {
2425
2412
  var _a2;
2426
2413
  return {
2427
2414
  phrase: (_a2 = ex.ex.furigana) != null ? _a2 : ex.ex.phrase,
@@ -2430,278 +2417,188 @@ function getWord(dict, id, kanjiDic, examples, definitions, dictWord, noteTypeNa
2430
2417
  ...ex.ex.glossNumber ? { glossNumber: ex.ex.glossNumber } : {}
2431
2418
  };
2432
2419
  });
2433
- word.tags.push("word::has_phrases");
2420
+ word2.tags.push("word::has_phrases");
2434
2421
  if (glossSpecificExamples.length > 0)
2435
- word.tags.push("word::has_meaning-specific_phrases");
2422
+ word2.tags.push("word::has_meaning-specific_phrases");
2436
2423
  }
2437
2424
  }
2438
- if (definitions) {
2439
- const defs = Array.isArray(definitions) ? (_a = definitions.find(
2440
- (wdp) => wdp.wordID === word.id
2441
- )) == null ? void 0 : _a.definitions : definitions.get(word.id);
2442
- if (defs) word.definitions = defs;
2443
- }
2444
- return word;
2445
- } else throw new Error(`Word${id ? ` ${id}` : ""} not found`);
2446
- } catch (err) {
2447
- throw err;
2448
- }
2425
+ }
2426
+ if (definitions) {
2427
+ const defs = Array.isArray(definitions) ? (_a = definitions.find((wdp) => wdp.wordID === word2.id)) == null ? void 0 : _a.definitions : definitions.get(word2.id);
2428
+ if (defs) word2.definitions = [...defs];
2429
+ }
2430
+ return word2;
2431
+ } else return void 0;
2449
2432
  }
2450
- function getKanji(dict, kanjiChar, dictKanji, jmDict, svgList, noteTypeName, deckPath) {
2433
+ function getKanji(kanji, dict, jmDict, svgList, noteTypeName, deckPath) {
2451
2434
  var _a, _b, _c, _d, _e, _f, _g, _h, _i;
2452
- try {
2453
- if (!dictKanji && kanjiChar)
2454
- dictKanji = dict.find((entry) => entry.kanji === kanjiChar);
2455
- if (dictKanji) {
2456
- const kanji = {
2457
- kanji: dictKanji.kanji,
2458
- ...dictKanji.misc ? { strokes: dictKanji.misc.strokeNumber } : {},
2459
- ...dictKanji.misc && dictKanji.misc.grade ? { grade: dictKanji.misc.grade } : {},
2460
- ...dictKanji.misc && dictKanji.misc.frequency ? { frequency: dictKanji.misc.frequency } : {},
2461
- ...dictKanji.misc && dictKanji.misc.jlpt ? { jlpt: dictKanji.misc.jlpt } : {},
2462
- noteID: `kanji_${dictKanji.kanji}`,
2463
- ...noteTypeName ? { noteTypeName } : {},
2464
- ...deckPath ? { deckPath } : {}
2465
- };
2466
- if (dictKanji.readingMeaning) {
2467
- kanji.meanings = [];
2468
- kanji.nanori = [];
2469
- kanji.onyomi = [];
2470
- kanji.kunyomi = [];
2471
- for (const rm of dictKanji.readingMeaning) {
2472
- if (rm.nanori && rm.nanori.length > 0)
2473
- kanji.nanori.push(...rm.nanori);
2435
+ let dictKanji = void 0;
2436
+ if (typeof kanji === "string" && dict)
2437
+ dictKanji = dict.find((entry) => entry.kanji === kanji);
2438
+ else if (typeof kanji === "object") dictKanji = kanji;
2439
+ if (dictKanji) {
2440
+ const kanji2 = {
2441
+ kanji: dictKanji.kanji,
2442
+ strokes: dictKanji.misc.strokeNumber,
2443
+ ...dictKanji.misc && dictKanji.misc.grade ? { grade: dictKanji.misc.grade } : {},
2444
+ ...dictKanji.misc && dictKanji.misc.frequency ? { frequency: dictKanji.misc.frequency } : {},
2445
+ ...dictKanji.misc && dictKanji.misc.jlpt ? { jlpt: dictKanji.misc.jlpt } : {},
2446
+ noteID: `kanji_${dictKanji.kanji}`,
2447
+ ...noteTypeName ? { noteTypeName } : {},
2448
+ ...deckPath ? { deckPath } : {},
2449
+ tags: []
2450
+ };
2451
+ if (dictKanji.readingMeaning && dictKanji.readingMeaning.length > 0) {
2452
+ const meanings = [];
2453
+ const nanori = [];
2454
+ const onyomi = [];
2455
+ const kunyomi = [];
2456
+ for (const rm of dictKanji.readingMeaning) {
2457
+ if (rm.nanori && rm.nanori.length > 0) nanori.push(...rm.nanori);
2458
+ if (rm.groups)
2474
2459
  for (const group of rm.groups) {
2475
- kanji.onyomi.push(
2476
- ...group.readings.filter((reading) => reading.type === "ja_on").map((reading) => reading.reading)
2477
- );
2478
- kanji.kunyomi.push(
2479
- ...group.readings.filter(
2480
- (reading) => reading.type === "ja_kun"
2481
- ).map((reading) => reading.reading)
2482
- );
2483
- kanji.meanings.push(...group.meanings);
2460
+ if (group.readings) {
2461
+ onyomi.push(
2462
+ ...group.readings.filter(
2463
+ (reading) => reading.type === "ja_on"
2464
+ ).map((reading) => reading.reading)
2465
+ );
2466
+ kunyomi.push(
2467
+ ...group.readings.filter(
2468
+ (reading) => reading.type === "ja_kun"
2469
+ ).map((reading) => reading.reading)
2470
+ );
2471
+ }
2472
+ if (group.meanings && group.meanings.length > 0)
2473
+ meanings.push(...group.meanings);
2484
2474
  }
2485
- }
2486
- if (kanji.meanings && kanji.meanings.length === 0)
2487
- delete kanji.meanings;
2488
- if (kanji.nanori && kanji.nanori.length === 0) delete kanji.nanori;
2489
- if (kanji.onyomi && kanji.onyomi.length === 0) delete kanji.onyomi;
2490
- if (kanji.kunyomi && kanji.kunyomi.length === 0) delete kanji.kunyomi;
2491
2475
  }
2492
- if (jmDict) {
2493
- let kanjiWords = jmDict.filter(
2494
- (word) => word.kanjiForms && word.kanjiForms[0].form.includes(kanji.kanji)
2495
- );
2496
- if (kanjiWords.length > 3) kanjiWords = kanjiWords.slice(0, 2);
2497
- if (kanjiWords.length > 0)
2498
- kanji.words = kanjiWords.map((word) => {
2499
- const wordObj = getWord(
2500
- void 0,
2501
- void 0,
2502
- void 0,
2503
- void 0,
2504
- void 0,
2505
- word,
2506
- void 0
2507
- );
2508
- if (!wordObj.translations)
2509
- throw new Error(`Invalid word: ${word.id}`);
2510
- const kanjiForm = wordObj.kanjiForms[0];
2511
- let reading = wordObj.readings.find(
2512
- (reading2) => reading2.notes && reading2.notes.some(
2513
- (note) => note.toLowerCase().startsWith("reading restricted to ") && note.endsWith(kanjiForm.kanjiForm)
2514
- )
2515
- );
2516
- let translation = wordObj.translations.find(
2517
- (translation2) => translation2.notes && translation2.notes.some(
2518
- (note) => note.toLowerCase().startsWith("meaning restricted to ") && (note.endsWith(kanjiForm.kanjiForm) || reading && note.endsWith(reading.reading))
2519
- )
2520
- );
2521
- if (!reading) reading = wordObj.readings[0];
2522
- if (!translation) translation = wordObj.translations[0];
2523
- return {
2524
- kanjiForms: [kanjiForm],
2525
- readings: [reading],
2526
- translations: [translation]
2527
- };
2528
- });
2529
- if (kanjiWords.length !== 3) {
2530
- const wordNumber = 3 - kanjiWords.length;
2531
- kanjiWords = jmDict.filter(
2532
- (word) => word.kanjiForms && word.kanjiForms.some(
2533
- (kanjiForm) => kanjiForm.form.includes(kanji.kanji)
2534
- )
2535
- ).map((word) => {
2536
- const wordObj = getWord(
2537
- void 0,
2538
- void 0,
2539
- void 0,
2540
- void 0,
2541
- void 0,
2542
- word,
2543
- void 0
2544
- );
2545
- if (!wordObj.translations)
2546
- throw new Error(`Invalid word: ${word.id}`);
2547
- const kanjiForm = wordObj.kanjiForms.find(
2548
- (kanjiForm2) => kanjiForm2.kanjiForm.includes(kanji.kanji)
2549
- );
2550
- if (!kanjiForm) throw new Error("Invalid kanji form");
2551
- let reading = wordObj.readings.find(
2552
- (reading2) => reading2.notes && reading2.notes.some(
2553
- (note) => note.toLowerCase().startsWith("reading restricted to ") && note.endsWith(kanjiForm.kanjiForm)
2554
- )
2555
- );
2556
- let translation = wordObj.translations.find(
2557
- (translation2) => translation2.notes && translation2.notes.some(
2558
- (note) => note.toLowerCase().startsWith("meaning restricted to ") && (note.endsWith(kanjiForm.kanjiForm) || reading && note.endsWith(reading.reading))
2559
- )
2560
- );
2561
- if (!reading) reading = wordObj.readings[0];
2562
- if (!translation) translation = wordObj.translations[0];
2563
- return {
2564
- kanjiForms: [kanjiForm],
2565
- readings: [reading],
2566
- translations: [translation]
2567
- };
2476
+ if (meanings.length > 0) kanji2.meanings = meanings;
2477
+ if (nanori.length > 0) kanji2.nanori = nanori;
2478
+ if (onyomi.length > 0) kanji2.onyomi = onyomi;
2479
+ if (kunyomi.length > 0) kanji2.kunyomi = kunyomi;
2480
+ }
2481
+ if (jmDict) {
2482
+ const kanjiWords = (_a = Array.isArray(jmDict) ? jmDict : jmDict.get(kanji2.kanji)) == null ? void 0 : _a.filter(
2483
+ (word) => word.kanjiForms && word.kanjiForms[0].form.includes(kanji2.kanji)
2484
+ ).slice(0, 3);
2485
+ if (kanjiWords) {
2486
+ const validWords = [];
2487
+ for (const word of kanjiWords) {
2488
+ const translation = word.meanings[0].translations[0];
2489
+ const translationText = typeof translation === "object" ? translation.translation : translation;
2490
+ validWords.push({
2491
+ kanjiForms: [{ kanjiForm: word.kanjiForms[0].form }],
2492
+ readings: [{ reading: word.readings[0].reading }],
2493
+ translations: [{ translation: translationText }]
2568
2494
  });
2569
- if (kanjiWords.length > wordNumber)
2570
- kanjiWords = kanjiWords.slice(0, wordNumber - 1);
2571
- if (kanjiWords.length > 0)
2572
- if (kanji.words) kanji.words.push(...kanjiWords);
2573
- else kanji.words = kanjiWords;
2574
2495
  }
2496
+ if (validWords.length > 0) kanji2.words = validWords;
2575
2497
  }
2576
- if (svgList) {
2577
- let codePoint = kanji.kanji.codePointAt(0);
2578
- if (codePoint !== void 0) {
2579
- codePoint = codePoint.toString(16);
2580
- const fileNames = [
2581
- `0${codePoint}.svg`,
2582
- `${codePoint}.svg`
2583
- ];
2584
- const svg = svgList.find(
2585
- (svgFile) => fileNames.includes(svgFile.toLowerCase())
2586
- );
2587
- if (svg) kanji.svg = svg;
2588
- }
2589
- }
2590
- kanji.tags = [];
2591
- if (dictKanji.isKokuji === true) {
2592
- kanji.kokuji = true;
2593
- kanji.tags.push("kanji::kokuji");
2594
- if (kanji.meanings)
2595
- kanji.meanings.splice(
2596
- kanji.meanings.findIndex(
2597
- (meaning) => meaning === "(kokuji)"
2598
- ),
2599
- 1
2600
- );
2498
+ }
2499
+ if (svgList) {
2500
+ let codePoint = kanji2.kanji.codePointAt(0);
2501
+ if (codePoint !== void 0) {
2502
+ codePoint = codePoint.toString(16);
2503
+ const fileNames = [
2504
+ `0${codePoint}.svg`,
2505
+ `${codePoint}.svg`
2506
+ ];
2507
+ const svg = svgList.find(
2508
+ (svgFile) => fileNames.includes(svgFile.toLowerCase())
2509
+ );
2510
+ if (svg) kanji2.svg = svg;
2601
2511
  }
2602
- kanji.tags.push(
2603
- `kanji::strokes::${(_a = kanji.strokes) != null ? _a : "unknown"}`,
2604
- ...kanji.frequency ? [`kanji::frequency::${kanji.frequency}`] : [],
2605
- ...kanji.grade ? [`kanji::grade::${kanji.grade}`] : [],
2606
- ...kanji.jlpt ? [`kanji::pre-2010_jlpt::${kanji.jlpt.toLowerCase()}`] : [],
2607
- `kanji::onyomi::${(_c = (_b = kanji.onyomi) == null ? void 0 : _b.length) != null ? _c : 0}`,
2608
- `kanji::kunyomi::${(_e = (_d = kanji.kunyomi) == null ? void 0 : _d.length) != null ? _e : 0}`,
2609
- `kanji::nanori::${(_g = (_f = kanji.nanori) == null ? void 0 : _f.length) != null ? _g : 0}`,
2610
- `kanji::words::${(_i = (_h = kanji.words) == null ? void 0 : _h.length) != null ? _i : 0}`,
2611
- ...kanji.svg ? ["kanji::has_svg"] : []
2512
+ }
2513
+ if (kanji2.tags && dictKanji.isKokuji === true) {
2514
+ kanji2.kokuji = true;
2515
+ kanji2.tags.push("kanji::kokuji");
2516
+ if (kanji2.meanings)
2517
+ kanji2.meanings.splice(
2518
+ kanji2.meanings.findIndex((meaning) => meaning === "(kokuji)"),
2519
+ 1
2520
+ );
2521
+ }
2522
+ if (kanji2.tags)
2523
+ kanji2.tags.push(
2524
+ `kanji::strokes::${kanji2.strokes}`,
2525
+ ...kanji2.frequency ? [`kanji::frequency::${kanji2.frequency}`] : [],
2526
+ ...kanji2.grade ? [`kanji::grade::${kanji2.grade}`] : [],
2527
+ ...kanji2.jlpt ? [`kanji::pre-2010_jlpt::${kanji2.jlpt.toLowerCase()}`] : [],
2528
+ `kanji::onyomi::${(_c = (_b = kanji2.onyomi) == null ? void 0 : _b.length) != null ? _c : 0}`,
2529
+ `kanji::kunyomi::${(_e = (_d = kanji2.kunyomi) == null ? void 0 : _d.length) != null ? _e : 0}`,
2530
+ `kanji::nanori::${(_g = (_f = kanji2.nanori) == null ? void 0 : _f.length) != null ? _g : 0}`,
2531
+ `kanji::words::${(_i = (_h = kanji2.words) == null ? void 0 : _h.length) != null ? _i : 0}`,
2532
+ ...kanji2.svg ? ["kanji::has_svg"] : []
2612
2533
  );
2613
- return kanji;
2614
- } else
2615
- throw new Error(`Kanji not found${kanjiChar ? `: ${kanjiChar}` : ""}`);
2616
- } catch (err) {
2617
- throw err;
2618
- }
2534
+ return kanji2;
2535
+ } else return void 0;
2619
2536
  }
2620
- function getKanjiExtended(info, dict, kanjiChar, dictKanji, useWords, jmDict, svgList, noteTypeName, deckPath) {
2621
- var _a, _b, _c, _d;
2622
- try {
2623
- const kanji = getKanji(
2624
- dict,
2625
- kanjiChar,
2626
- dictKanji,
2627
- jmDict,
2628
- svgList,
2629
- noteTypeName,
2630
- deckPath
2631
- );
2632
- if (info.components && info.components.length > 0)
2633
- kanji.components = info.components;
2634
- if (info.mnemonic && info.mnemonic.length > 0)
2635
- kanji.mnemonic = info.mnemonic;
2636
- if (useWords === true && info.words && info.words.length > 0)
2637
- kanji.words = info.words;
2638
- if (kanji.tags) {
2639
- kanji.tags.push(`kanji::components::${(_b = (_a = kanji.components) == null ? void 0 : _a.length) != null ? _b : 0}`);
2640
- if (kanji.mnemonic && kanji.mnemonic.length > 0)
2641
- kanji.tags.push("kanji::has_mnemonic");
2642
- if (useWords === true && kanji.words) {
2643
- if (!kanji.tags.some((tag, index) => {
2644
- var _a2, _b2;
2645
- if (tag.startsWith("kanji::words::")) {
2646
- kanji.tags.splice(
2537
+ function getKanjiExtended(info, kanji, dict, useWords, jmDict, svgList, noteTypeName, deckPath, sourceURL) {
2538
+ const kanjiObj = getKanji(
2539
+ kanji,
2540
+ dict,
2541
+ jmDict,
2542
+ svgList,
2543
+ noteTypeName,
2544
+ deckPath
2545
+ );
2546
+ if (kanjiObj) {
2547
+ let usedInfo = false;
2548
+ if (info.components) {
2549
+ kanjiObj.components = info.components;
2550
+ usedInfo = true;
2551
+ }
2552
+ if (info.mnemonic && info.mnemonic.length > 0) {
2553
+ kanjiObj.mnemonic = info.mnemonic;
2554
+ usedInfo = true;
2555
+ }
2556
+ if (useWords === true && info.words && info.words.length > 0) {
2557
+ kanjiObj.words = info.words;
2558
+ usedInfo = true;
2559
+ }
2560
+ if (kanjiObj.tags) {
2561
+ if (kanjiObj.components)
2562
+ kanjiObj.tags.push(`kanji::components::${kanjiObj.components.length}`);
2563
+ if (kanjiObj.mnemonic && kanjiObj.mnemonic.length > 0)
2564
+ kanjiObj.tags.push("kanji::has_mnemonic");
2565
+ if (useWords === true && kanjiObj.words && info.words)
2566
+ kanjiObj.tags.forEach((tag, index) => {
2567
+ if (tag.startsWith("kanji::words::") && kanjiObj.words && kanjiObj.tags) {
2568
+ kanjiObj.tags.splice(
2647
2569
  index,
2648
2570
  1,
2649
- `kanji::words::${(_b2 = (_a2 = kanji.words) == null ? void 0 : _a2.length) != null ? _b2 : 0}`
2571
+ `kanji::words::${kanjiObj.words.length}`
2650
2572
  );
2651
- return true;
2652
- } else return false;
2653
- }))
2654
- kanji.tags.push(`kanji::words::${(_d = (_c = kanji.words) == null ? void 0 : _c.length) != null ? _d : 0}`);
2655
- }
2656
- }
2657
- if (info.fromJpdb === true && (kanji.mnemonic || kanji.components || kanji.words && useWords === true))
2658
- kanji.source = `https://jpdb.io/kanji/${kanji.kanji}`;
2659
- return kanji;
2660
- } catch (err) {
2661
- throw err;
2662
- }
2663
- }
2664
- async function synthesizeSpeech(client, input, options) {
2665
- return await new Promise(
2666
- async (resolve, reject) => {
2667
- try {
2668
- const command = new import_client_polly.SynthesizeSpeechCommand({
2669
- Text: input,
2670
- ...options
2573
+ }
2671
2574
  });
2672
- const response = await client.send(command);
2673
- const stream = response.AudioStream ? Buffer.from(await response.AudioStream.transformToByteArray()) : null;
2674
- resolve(stream);
2675
- } catch (err) {
2676
- reject(err);
2677
- }
2678
2575
  }
2679
- );
2576
+ if (sourceURL && info.externalInfo === true && usedInfo)
2577
+ kanjiObj.source = sourceURL;
2578
+ return kanjiObj;
2579
+ } else return void 0;
2680
2580
  }
2681
2581
  function isWord(entry) {
2682
2582
  return entry.translations !== void 0 && entry.readings !== void 0;
2683
2583
  }
2684
2584
  function isRadical(entry) {
2685
- return entry.radical !== void 0 && entry.reading !== void 0 && entry.meanings !== void 0;
2585
+ return entry.radical !== void 0;
2686
2586
  }
2687
2587
  function isKanji(entry) {
2688
2588
  return entry.translations === void 0 && entry.readings === void 0 && entry.radical === void 0 && entry.kanji !== void 0;
2689
2589
  }
2690
2590
  function isKana(entry) {
2691
- return entry.kana !== void 0 && entry.reading !== void 0;
2591
+ return entry.kana !== void 0;
2692
2592
  }
2693
2593
  function isGrammar(entry) {
2694
- return entry.point !== void 0 && entry.meaning !== void 0;
2594
+ return entry.point !== void 0;
2695
2595
  }
2696
2596
  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>" : ""}`;
2697
2597
  var createEntry = (entry, notes, phrase, glossSpecific) => `<div class="entry${glossSpecific ? " gloss-specific" : ""}">${entry}${notes && notes.length > 0 ? createNotes(notes, phrase) : ""}</div>`;
2698
2598
  var noKanjiForms = '<span class="word word-kanjiform">(no kanji forms)</span>';
2699
2599
  function generateAnkiNote(entry) {
2700
- if (!entry.noteID) throw new Error("Invalid note ID");
2701
2600
  const fields = [];
2702
2601
  if (isWord(entry)) {
2703
- if (!entry.translations || entry.readings.length === 0)
2704
- throw new Error(`Invalid word: ${entry.noteID}`);
2705
2602
  const firstReading = createEntry(
2706
2603
  `<span class="word word-reading">${entry.readings[0].reading}${entry.readings[0].audio !== void 0 ? `<br>[sound:${entry.readings[0].audio}]` : ""}</span>`,
2707
2604
  entry.readings[0].notes
@@ -2799,7 +2696,7 @@ function generateAnkiNote(entry) {
2799
2696
  entry.strokes ? createEntry(
2800
2697
  `<span class="radical radical-strokes">${entry.strokes}<br>${entry.svg ? `<img class="radical radical-stroke-order" src="${entry.svg}" alt="${entry.radical} stroke order SVG">` : "(no stroke order SVG available)"}</span>`
2801
2698
  ) : '<span class="radical radical-strokes">(no stroke number)</span>',
2802
- entry.sources ? `<span class="radical radical-source">${entry.sources.map((source, index) => `<a href="${source}" target="_blank">Source ${index + 1}</a>`).join("<br>")}</span>` : '<span class="kanji kanji-source">(no sources)</span>',
2699
+ entry.sources ? `<span class="radical radical-source">${entry.sources.map((source, index) => `<a href="${source}" target="_blank">Source ${index + 1}</a>`).join("<br>")}</span>` : '<span class="radical radical-source">(no sources)</span>',
2803
2700
  ...entry.tags && entry.tags.length > 0 ? [
2804
2701
  entry.tags.map(
2805
2702
  (tag) => tag.trim().toLowerCase().replaceAll(" ", "::")
@@ -2837,11 +2734,9 @@ function generateAnkiNote(entry) {
2837
2734
  entry.mnemonic ? createEntry(
2838
2735
  `<span class="kanji kanji-mnemonic">${entry.mnemonic}</span>`
2839
2736
  ) : '<span class="kanji kanji-mnemonic">(no mnemonic) (Come up with your own!)</span>',
2840
- entry.words ? entry.words.filter(
2841
- (word) => word.translations && word.translations.length > 0
2842
- ).map(
2737
+ entry.words ? entry.words.map(
2843
2738
  (word) => createEntry(
2844
- `<span class="kanji kanji-words">${word.kanjiForms && word.kanjiForms.length > 0 ? word.kanjiForms[0].kanjiForm : "(no kanji form)"} / ${word.readings[0].reading} - ${word.translations[0].translation}</span>`
2739
+ `<span class="kanji kanji-words">${word.kanjiForms[0].kanjiForm} / ${word.readings[0].reading} - ${word.translations[0].translation}</span>`
2845
2740
  )
2846
2741
  ).join("") : '<span class="kanji kanji-words">(no words) (Search on dictionaries!)</span>',
2847
2742
  entry.strokes ? createEntry(
@@ -2899,48 +2794,85 @@ function generateAnkiNote(entry) {
2899
2794
  ).join(" ")
2900
2795
  ] : []
2901
2796
  );
2902
- if (fields.length > 0)
2903
- return fields.map((field) => field.replaceAll("\n", "<br>"));
2904
- else throw new Error("Invalid entry");
2797
+ return fields.map((field) => field.replaceAll("\n", "<br>"));
2905
2798
  }
2906
- function generateAnkiNotesFile(list) {
2799
+ function generateAnkiNotesFile(list, defaultNoteInfo) {
2800
+ const headers = [noteHeaderKeys.separator, noteHeaderKeys.html];
2801
+ let ankiNotes = "";
2907
2802
  if (list.length > 0) {
2908
- const headers = [
2909
- "#separator:tab",
2910
- "#html:true",
2911
- "#guid column:1",
2912
- "#notetype column:2",
2913
- "#deck column:3"
2914
- ];
2915
- const ankiNotes = list.filter((result) => result.doNotCreateNote === void 0).map((result) => {
2916
- if (!result.noteID || !result.noteTypeName || !result.deckPath)
2917
- throw new Error("Invalid result");
2803
+ if (defaultNoteInfo === void 0) defaultNoteInfo = {};
2804
+ const infoValues = Object.values(defaultNoteInfo);
2805
+ let invalidList = false;
2806
+ const firstEntry = list[0];
2807
+ const firstEntryInfo = {
2808
+ guid: typeof firstEntry.noteID,
2809
+ noteType: typeof firstEntry.noteTypeName,
2810
+ deckPath: typeof firstEntry.deckPath
2811
+ };
2812
+ if (infoValues.length === 0 || infoValues.some((value) => value === true || value === void 0)) {
2813
+ for (const res of list)
2814
+ if (defaultNoteInfo.guid === true && res.noteID === void 0 || defaultNoteInfo.noteType === true && res.noteTypeName === void 0 || defaultNoteInfo.deckPath === true && res.deckPath === void 0 || defaultNoteInfo.guid === void 0 && typeof res.noteID !== firstEntryInfo.guid || defaultNoteInfo.noteType === void 0 && typeof res.noteTypeName !== firstEntryInfo.noteType || defaultNoteInfo.deckPath === void 0 && typeof res.deckPath !== firstEntryInfo.deckPath) {
2815
+ invalidList = true;
2816
+ break;
2817
+ }
2818
+ }
2819
+ if (invalidList) throw new Error("Invalid result list");
2820
+ const hasHeader = { guid: false, noteType: false, deckPath: false, tags: false };
2821
+ let headerCount = 0;
2822
+ ankiNotes = list.filter((result) => result.doNotCreateNote === void 0).map((result) => {
2823
+ if (typeof defaultNoteInfo.guid === "string" && result.noteID === void 0) {
2824
+ if (isWord(result) && result.id) result.noteID = result.id;
2825
+ if (isKanji(result)) result.noteID = result.kanji;
2826
+ if (isRadical(result)) result.noteID = result.radical;
2827
+ if (isKana(result)) result.noteID = result.kana;
2828
+ if (isGrammar(result) && result.id) result.noteID = result.id;
2829
+ }
2830
+ if (typeof defaultNoteInfo.noteType === "string" && result.noteTypeName === void 0)
2831
+ result.noteTypeName = defaultNoteInfo.noteType;
2832
+ if (typeof defaultNoteInfo.deckPath === "string" && result.deckPath === void 0)
2833
+ result.deckPath = defaultNoteInfo.deckPath;
2834
+ if (!hasHeader.guid && result.noteID) {
2835
+ headers.push(`${noteHeaderKeys.guid}:${++headerCount}`);
2836
+ hasHeader.guid = true;
2837
+ }
2838
+ if (!hasHeader.noteType && result.noteTypeName) {
2839
+ headers.push(`${noteHeaderKeys.notetype}:${++headerCount}`);
2840
+ hasHeader.noteType = true;
2841
+ }
2842
+ if (!hasHeader.deckPath && result.deckPath) {
2843
+ headers.push(`${noteHeaderKeys.deck}:${++headerCount}`);
2844
+ hasHeader.deckPath = true;
2845
+ }
2918
2846
  const note = generateAnkiNote(result);
2919
- if (headers.length === 5)
2920
- headers.push(`#tags column:${note.length + 3}
2921
- `);
2922
- return `${result.noteID} ${result.noteTypeName} ${result.deckPath} ${note.join(" ")}`;
2847
+ if (!hasHeader.tags) {
2848
+ headers.push(`${noteHeaderKeys.tags}${note.length + headerCount}`);
2849
+ hasHeader.tags = true;
2850
+ }
2851
+ return `${result.noteID ? `${result.noteID} ` : ""}${result.noteTypeName ? `${result.noteTypeName} ` : ""}${result.deckPath ? `${result.deckPath} ` : ""}${note.join(" ")}`;
2923
2852
  }).join("\n").trim();
2924
- if (ankiNotes.length === 0) throw new Error("Invalid list");
2925
- return `${headers.join("\n")}
2853
+ }
2854
+ return `${headers.join("\n")}
2855
+
2926
2856
  ${ankiNotes}`;
2927
- } else throw new Error("No entries available for Anki notes creation");
2928
2857
  }
2929
2858
  // Annotate the CommonJS export names for ESM import in node:
2930
2859
  0 && (module.exports = {
2931
2860
  capitalizeString,
2932
2861
  convertJMdict,
2933
- convertJawiktionary,
2862
+ convertJawiktionaryAsync,
2863
+ convertJawiktionarySync,
2934
2864
  convertKanjiDic,
2935
2865
  convertKradFile,
2936
2866
  convertRadkFile,
2937
2867
  convertTanakaCorpus,
2868
+ convertTanakaCorpusWithFurigana,
2938
2869
  generateAnkiNote,
2939
2870
  generateAnkiNotesFile,
2940
2871
  getKanji,
2941
2872
  getKanjiExtended,
2942
2873
  getWord,
2943
2874
  getWordDefinitions,
2875
+ getWordDefinitionsWithFurigana,
2944
2876
  isGrammar,
2945
2877
  isKana,
2946
2878
  isKanji,
@@ -2950,9 +2882,9 @@ ${ankiNotes}`;
2950
2882
  isValidArrayWithFirstElement,
2951
2883
  isWord,
2952
2884
  notSearchedForms,
2885
+ noteHeaderKeys,
2953
2886
  noteMap,
2954
2887
  regexps,
2955
- shuffleArray,
2956
- synthesizeSpeech
2888
+ shuffleArray
2957
2889
  });
2958
2890
  //# sourceMappingURL=index.cjs.js.map