henkan 1.1.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/README.md +1 -1
  2. package/dist/index.cjs.js +1051 -1118
  3. package/dist/index.cjs.js.map +3 -3
  4. package/dist/index.mjs +1044 -1114
  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 +49 -40
  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
2067
  }
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
- }
2110
- }
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);
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);
2123
2072
  }
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,69 +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) {
2178
- try {
2179
- if (!dictWord && id && dict)
2180
- dictWord = dict.find((entry) => entry.id === id);
2181
- if (dictWord) {
2182
- const word = {
2183
- id: dictWord.id,
2184
- readings: [],
2185
- translations: [],
2186
- noteID: `word_${dictWord.id}`,
2187
- ...noteTypeName ? { noteTypeName } : {},
2188
- ...deckPath ? { deckPath } : {},
2189
- tags: []
2190
- };
2191
- if (dictWord.isCommon === true) {
2192
- word.common = true;
2193
- word.tags.push("word::common");
2194
- }
2195
- if (dictWord.kanjiForms)
2196
- word.kanjiForms = dictWord.kanjiForms.map(
2197
- (dictKanjiForm) => ({
2198
- kanjiForm: dictKanjiForm.form,
2199
- ...dictKanjiForm.notes ? {
2200
- notes: dictKanjiForm.notes.map((note) => {
2201
- var _a;
2202
- const noteAndTag = lookupWordNote(
2203
- note,
2204
- void 0,
2205
- word.tags,
2206
- false,
2207
- note
2208
- );
2209
- return capitalizeString((_a = noteAndTag.note) != null ? _a : note);
2210
- })
2211
- } : {},
2212
- ...dictKanjiForm.commonness && dictKanjiForm.commonness.length > 0 ? { common: true } : {}
2213
- })
2214
- );
2215
- word.readings = dictWord.readings.map((dictReading) => ({
2216
- reading: dictReading.reading,
2217
- ...dictReading.kanjiFormRestrictions || dictReading.notes ? {
2218
- notes: [
2219
- ...dictReading.kanjiFormRestrictions ? dictReading.kanjiFormRestrictions.map(
2220
- (restriction) => `Reading restricted to ${restriction}`
2221
- ) : [],
2222
- ...dictReading.notes ? dictReading.notes.map((note) => {
2223
- var _a;
2169
+ function getWord(word, dict, kanjiDic, examples, definitions, noteTypeName, deckPath) {
2170
+ var _a;
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) => {
2224
2195
  const noteAndTag = lookupWordNote(
2225
2196
  note,
2226
2197
  void 0,
2227
- word.tags,
2228
- false,
2229
- note
2198
+ word2.tags
2230
2199
  );
2231
- return capitalizeString((_a = noteAndTag.note) != null ? _a : note);
2232
- }) : []
2233
- ]
2234
- } : {},
2235
- ...dictReading.commonness && dictReading.commonness.length > 0 ? { common: true } : {}
2236
- }));
2237
- word.translations = dictWord.meanings.map((dictMeaning) => {
2238
- if (!dictMeaning.translations)
2239
- 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) {
2240
2228
  const translationTypes = [];
2241
2229
  const translations = dictMeaning.translations.map(
2242
2230
  (translation) => {
@@ -2244,13 +2232,13 @@ function getWord(dict, id, kanjiDic, examples, definitions, dictWord, noteTypeNa
2244
2232
  else {
2245
2233
  if (translation.type === "lit") {
2246
2234
  translationTypes.push("Literal meaning");
2247
- word.tags.push("word::literal_meaning");
2235
+ word2.tags.push("word::literal_meaning");
2248
2236
  } else if (translation.type === "expl") {
2249
2237
  translationTypes.push("Explanation");
2250
- word.tags.push("word::explanation");
2238
+ word2.tags.push("word::explanation");
2251
2239
  } else if (translation.type === "tm") {
2252
2240
  translationTypes.push("Trademark");
2253
- word.tags.push("word::trademark");
2241
+ word2.tags.push("word::trademark");
2254
2242
  }
2255
2243
  return translation.translation;
2256
2244
  }
@@ -2268,15 +2256,15 @@ function getWord(dict, id, kanjiDic, examples, definitions, dictWord, noteTypeNa
2268
2256
  for (const t of translationTypes) notes.push(t);
2269
2257
  wordAddNoteArray(
2270
2258
  dictMeaning.partOfSpeech,
2271
- (pos) => lookupWordNote(pos, notes, word.tags, true)
2259
+ (pos) => lookupWordNote(pos, notes, word2.tags)
2272
2260
  );
2273
2261
  wordAddNoteArray(
2274
2262
  dictMeaning.fields,
2275
- (field) => lookupWordNote(field, notes, word.tags, false, field)
2263
+ (field) => lookupWordNote(field, notes, word2.tags)
2276
2264
  );
2277
2265
  wordAddNoteArray(
2278
2266
  dictMeaning.dialects,
2279
- (dialect) => lookupWordNote(dialect, notes, word.tags, true)
2267
+ (dialect) => lookupWordNote(dialect, notes, word2.tags)
2280
2268
  );
2281
2269
  wordAddNoteArray(
2282
2270
  dictMeaning.antonyms,
@@ -2288,64 +2276,64 @@ function getWord(dict, id, kanjiDic, examples, definitions, dictWord, noteTypeNa
2288
2276
  );
2289
2277
  wordAddNoteArray(
2290
2278
  dictMeaning.info,
2291
- (info) => lookupWordNote(info, notes, word.tags, false, info)
2279
+ (info) => lookupWordNote(info, notes, word2.tags)
2292
2280
  );
2293
2281
  wordAddNoteArray(
2294
2282
  dictMeaning.misc,
2295
- (misc) => lookupWordNote(misc, notes, word.tags, false, misc)
2283
+ (misc) => lookupWordNote(misc, notes, word2.tags)
2296
2284
  );
2297
2285
  for (let i = 0; i < notes.length; i++)
2298
2286
  notes[i] = capitalizeString(notes[i]);
2299
- return {
2287
+ word2.translations.push({
2300
2288
  translation: translations.join("; "),
2301
2289
  notes
2302
- };
2303
- });
2304
- if (dictWord.usuallyInKana === true) {
2305
- word.usuallyInKana = true;
2306
- word.tags.push("word::usually_in_kana_for_all_senses");
2290
+ });
2307
2291
  }
2308
- if (kanjiDic && word.kanjiForms) {
2309
- word.kanji = [];
2310
- for (const kanjiForm of word.kanjiForms)
2311
- for (const char of kanjiForm.kanjiForm) {
2312
- if (word.kanji.some((kanji) => kanji.kanji === char))
2313
- continue;
2314
- const dictKanji = kanjiDic.find(
2315
- (kanji) => kanji.kanji === char
2316
- );
2317
- if (dictKanji) {
2318
- const kanjiObj = getKanji(kanjiDic, void 0, dictKanji);
2319
- word.kanji.push({
2320
- kanji: kanjiObj.kanji,
2321
- ...kanjiObj.meanings ? { meanings: kanjiObj.meanings } : {}
2322
- });
2323
- }
2324
- }
2325
- if (word.kanji.length === 0) {
2326
- delete word.kanji;
2327
- 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
+ });
2328
2311
  }
2329
- }
2330
- 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) {
2331
2319
  const readings = new Set(
2332
- word.readings.filter(
2320
+ word2.readings.filter(
2333
2321
  (reading) => (reading.notes === void 0 || !reading.notes.some(
2334
2322
  (note) => notSearchedForms.has(note)
2335
- )) && (word.common === void 0 || reading.common === true)
2323
+ )) && (word2.common === void 0 || reading.common === true)
2336
2324
  ).map((reading) => reading.reading)
2337
2325
  );
2338
- const existValidKf = word.kanjiForms && word.kanjiForms.length > 0 ? word.kanjiForms.some(
2326
+ const existValidKf = word2.kanjiForms && word2.kanjiForms.length > 0 ? word2.kanjiForms.some(
2339
2327
  (kf) => (kf.notes === void 0 || !kf.notes.some(
2340
2328
  (note) => notSearchedForms.has(note)
2341
- )) && (word.common === void 0 || kf.common === true)
2329
+ )) && (word2.common === void 0 || kf.common === true)
2342
2330
  ) : void 0;
2343
- const kanjiForms = word.kanjiForms && word.kanjiForms.length > 0 ? new Set(
2344
- word.kanjiForms.filter((kanjiForm) => {
2331
+ const kanjiForms = word2.kanjiForms && word2.kanjiForms.length > 0 ? new Set(
2332
+ word2.kanjiForms.filter((kanjiForm) => {
2345
2333
  if (existValidKf === true)
2346
2334
  return (kanjiForm.notes === void 0 || !kanjiForm.notes.some(
2347
2335
  (note) => notSearchedForms.has(note)
2348
- )) && (word.common === void 0 || kanjiForm.common === true);
2336
+ )) && (word2.common === void 0 || kanjiForm.common === true);
2349
2337
  else return true;
2350
2338
  }).map((kanjiForm) => kanjiForm.kanjiForm)
2351
2339
  ) : void 0;
@@ -2353,12 +2341,12 @@ function getWord(dict, id, kanjiDic, examples, definitions, dictWord, noteTypeNa
2353
2341
  const readingMatchingKanjiFormExamples = [];
2354
2342
  const readingExamples = [];
2355
2343
  const readingMatchingKanjiForms = /* @__PURE__ */ new Set();
2356
- for (const example of examples)
2344
+ for (const example of exampleList)
2357
2345
  for (let i = 0; i < example.parts.length; i++) {
2358
2346
  const part = example.parts[i];
2359
2347
  const readingAsReadingMatch = part.reading !== void 0 && readings.has(part.reading);
2360
2348
  const readingAsInflectedFormMatch = part.inflectedForm !== void 0 && readings.has(part.inflectedForm);
2361
- 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;
2362
2350
  if (kanjiForms && kanjiForms.has(part.baseForm) || referenceIDMatch) {
2363
2351
  if (readingAsReadingMatch || readingAsInflectedFormMatch) {
2364
2352
  readingMatchingKanjiFormExamples.push({
@@ -2384,7 +2372,7 @@ function getWord(dict, id, kanjiDic, examples, definitions, dictWord, noteTypeNa
2384
2372
  kanjiFormExamples = kanjiFormExamples.filter(
2385
2373
  (ex) => ex.form && readingMatchingKanjiForms.has(ex.form)
2386
2374
  );
2387
- const includeKanjiFormExamples = word.kanjiForms !== void 0;
2375
+ const includeKanjiFormExamples = word2.kanjiForms !== void 0;
2388
2376
  let wordExamples = [
2389
2377
  ...includeKanjiFormExamples ? [...readingMatchingKanjiFormExamples, ...kanjiFormExamples] : [],
2390
2378
  ...!includeKanjiFormExamples ? readingExamples : []
@@ -2392,14 +2380,14 @@ function getWord(dict, id, kanjiDic, examples, definitions, dictWord, noteTypeNa
2392
2380
  readingMatchingKanjiForms.clear();
2393
2381
  const glossSpecificExamples = [];
2394
2382
  const seenPhrases = /* @__PURE__ */ new Set();
2395
- for (let i = 0; i < word.translations.length; i++) {
2383
+ for (let i = 0; i < word2.translations.length; i++) {
2396
2384
  outer: for (const example of wordExamples) {
2397
2385
  if (seenPhrases.has(example.ex.phrase)) continue;
2398
2386
  for (let j = 0; j < example.ex.parts.length; j++) {
2399
2387
  const part = example.ex.parts[j];
2400
2388
  if (j === example.partIndex && part.glossNumber === i + 1) {
2401
2389
  example.ex.glossNumber = {
2402
- wordId: word.id,
2390
+ wordId: word2.id,
2403
2391
  glossNumber: i + 1
2404
2392
  };
2405
2393
  glossSpecificExamples.push(example);
@@ -2420,287 +2408,197 @@ function getWord(dict, id, kanjiDic, examples, definitions, dictWord, noteTypeNa
2420
2408
  ).slice(0, 5 - glossSpecificExamples.length)
2421
2409
  ];
2422
2410
  if (wordExamples.length > 0) {
2423
- word.phrases = (wordExamples.length > 5 ? wordExamples.slice(0, 5) : wordExamples).map((ex) => {
2424
- var _a;
2411
+ word2.phrases = (wordExamples.length > 5 ? wordExamples.slice(0, 5) : wordExamples).map((ex) => {
2412
+ var _a2;
2425
2413
  return {
2426
- phrase: (_a = ex.ex.furigana) != null ? _a : ex.ex.phrase,
2414
+ phrase: (_a2 = ex.ex.furigana) != null ? _a2 : ex.ex.phrase,
2427
2415
  translation: ex.ex.translation,
2428
2416
  originalPhrase: ex.ex.phrase,
2429
2417
  ...ex.ex.glossNumber ? { glossNumber: ex.ex.glossNumber } : {}
2430
2418
  };
2431
2419
  });
2432
- word.tags.push("word::has_phrases");
2420
+ word2.tags.push("word::has_phrases");
2433
2421
  if (glossSpecificExamples.length > 0)
2434
- word.tags.push("word::has_meaning-specific_phrases");
2422
+ word2.tags.push("word::has_meaning-specific_phrases");
2435
2423
  }
2436
2424
  }
2437
- if (definitions) {
2438
- const pair = definitions.find(
2439
- (wdp) => wdp.wordID === word.id
2440
- );
2441
- if (pair) word.definitions = pair.definitions;
2442
- }
2443
- return word;
2444
- } else throw new Error(`Word${id ? ` ${id}` : ""} not found`);
2445
- } catch (err) {
2446
- throw err;
2447
- }
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;
2448
2432
  }
2449
- function getKanji(dict, kanjiChar, dictKanji, jmDict, svgList, noteTypeName, deckPath) {
2433
+ function getKanji(kanji, dict, jmDict, svgList, noteTypeName, deckPath) {
2450
2434
  var _a, _b, _c, _d, _e, _f, _g, _h, _i;
2451
- try {
2452
- if (!dictKanji && kanjiChar)
2453
- dictKanji = dict.find((entry) => entry.kanji === kanjiChar);
2454
- if (dictKanji) {
2455
- const kanji = {
2456
- kanji: dictKanji.kanji,
2457
- ...dictKanji.misc ? { strokes: dictKanji.misc.strokeNumber } : {},
2458
- ...dictKanji.misc && dictKanji.misc.grade ? { grade: dictKanji.misc.grade } : {},
2459
- ...dictKanji.misc && dictKanji.misc.frequency ? { frequency: dictKanji.misc.frequency } : {},
2460
- ...dictKanji.misc && dictKanji.misc.jlpt ? { jlpt: dictKanji.misc.jlpt } : {},
2461
- noteID: `kanji_${dictKanji.kanji}`,
2462
- ...noteTypeName ? { noteTypeName } : {},
2463
- ...deckPath ? { deckPath } : {}
2464
- };
2465
- if (dictKanji.readingMeaning) {
2466
- kanji.meanings = [];
2467
- kanji.nanori = [];
2468
- kanji.onyomi = [];
2469
- kanji.kunyomi = [];
2470
- for (const rm of dictKanji.readingMeaning) {
2471
- if (rm.nanori && rm.nanori.length > 0)
2472
- 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)
2473
2459
  for (const group of rm.groups) {
2474
- kanji.onyomi.push(
2475
- ...group.readings.filter((reading) => reading.type === "ja_on").map((reading) => reading.reading)
2476
- );
2477
- kanji.kunyomi.push(
2478
- ...group.readings.filter(
2479
- (reading) => reading.type === "ja_kun"
2480
- ).map((reading) => reading.reading)
2481
- );
2482
- 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);
2483
2474
  }
2484
- }
2485
- if (kanji.meanings && kanji.meanings.length === 0)
2486
- delete kanji.meanings;
2487
- if (kanji.nanori && kanji.nanori.length === 0) delete kanji.nanori;
2488
- if (kanji.onyomi && kanji.onyomi.length === 0) delete kanji.onyomi;
2489
- if (kanji.kunyomi && kanji.kunyomi.length === 0) delete kanji.kunyomi;
2490
2475
  }
2491
- if (jmDict) {
2492
- let kanjiWords = jmDict.filter(
2493
- (word) => word.kanjiForms && word.kanjiForms[0].form.includes(kanji.kanji)
2494
- );
2495
- if (kanjiWords.length > 3) kanjiWords = kanjiWords.slice(0, 2);
2496
- if (kanjiWords.length > 0)
2497
- kanji.words = kanjiWords.map((word) => {
2498
- const wordObj = getWord(
2499
- void 0,
2500
- void 0,
2501
- void 0,
2502
- void 0,
2503
- void 0,
2504
- word,
2505
- void 0
2506
- );
2507
- if (!wordObj.translations)
2508
- throw new Error(`Invalid word: ${word.id}`);
2509
- const kanjiForm = wordObj.kanjiForms[0];
2510
- let reading = wordObj.readings.find(
2511
- (reading2) => reading2.notes && reading2.notes.some(
2512
- (note) => note.toLowerCase().startsWith("reading restricted to ") && note.endsWith(kanjiForm.kanjiForm)
2513
- )
2514
- );
2515
- let translation = wordObj.translations.find(
2516
- (translation2) => translation2.notes && translation2.notes.some(
2517
- (note) => note.toLowerCase().startsWith("meaning restricted to ") && (note.endsWith(kanjiForm.kanjiForm) || reading && note.endsWith(reading.reading))
2518
- )
2519
- );
2520
- if (!reading) reading = wordObj.readings[0];
2521
- if (!translation) translation = wordObj.translations[0];
2522
- return {
2523
- kanjiForms: [kanjiForm],
2524
- readings: [reading],
2525
- translations: [translation]
2526
- };
2527
- });
2528
- if (kanjiWords.length !== 3) {
2529
- const wordNumber = 3 - kanjiWords.length;
2530
- kanjiWords = jmDict.filter(
2531
- (word) => word.kanjiForms && word.kanjiForms.some(
2532
- (kanjiForm) => kanjiForm.form.includes(kanji.kanji)
2533
- )
2534
- ).map((word) => {
2535
- const wordObj = getWord(
2536
- void 0,
2537
- void 0,
2538
- void 0,
2539
- void 0,
2540
- void 0,
2541
- word,
2542
- void 0
2543
- );
2544
- if (!wordObj.translations)
2545
- throw new Error(`Invalid word: ${word.id}`);
2546
- const kanjiForm = wordObj.kanjiForms.find(
2547
- (kanjiForm2) => kanjiForm2.kanjiForm.includes(kanji.kanji)
2548
- );
2549
- if (!kanjiForm) throw new Error("Invalid kanji form");
2550
- let reading = wordObj.readings.find(
2551
- (reading2) => reading2.notes && reading2.notes.some(
2552
- (note) => note.toLowerCase().startsWith("reading restricted to ") && note.endsWith(kanjiForm.kanjiForm)
2553
- )
2554
- );
2555
- let translation = wordObj.translations.find(
2556
- (translation2) => translation2.notes && translation2.notes.some(
2557
- (note) => note.toLowerCase().startsWith("meaning restricted to ") && (note.endsWith(kanjiForm.kanjiForm) || reading && note.endsWith(reading.reading))
2558
- )
2559
- );
2560
- if (!reading) reading = wordObj.readings[0];
2561
- if (!translation) translation = wordObj.translations[0];
2562
- return {
2563
- kanjiForms: [kanjiForm],
2564
- readings: [reading],
2565
- translations: [translation]
2566
- };
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 }]
2567
2494
  });
2568
- if (kanjiWords.length > wordNumber)
2569
- kanjiWords = kanjiWords.slice(0, wordNumber - 1);
2570
- if (kanjiWords.length > 0)
2571
- if (kanji.words) kanji.words.push(...kanjiWords);
2572
- else kanji.words = kanjiWords;
2573
2495
  }
2496
+ if (validWords.length > 0) kanji2.words = validWords;
2574
2497
  }
2575
- if (svgList) {
2576
- let codePoint = kanji.kanji.codePointAt(0);
2577
- if (codePoint !== void 0) {
2578
- codePoint = codePoint.toString(16);
2579
- const fileNames = [
2580
- `0${codePoint}.svg`,
2581
- `${codePoint}.svg`
2582
- ];
2583
- const svg = svgList.find(
2584
- (svgFile) => fileNames.includes(svgFile.toLowerCase())
2585
- );
2586
- if (svg) kanji.svg = svg;
2587
- }
2588
- }
2589
- kanji.tags = [];
2590
- if (dictKanji.isKokuji === true) {
2591
- kanji.kokuji = true;
2592
- kanji.tags.push("kanji::kokuji");
2593
- if (kanji.meanings)
2594
- kanji.meanings.splice(
2595
- kanji.meanings.findIndex(
2596
- (meaning) => meaning === "(kokuji)"
2597
- ),
2598
- 1
2599
- );
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;
2600
2511
  }
2601
- kanji.tags.push(
2602
- `kanji::strokes::${(_a = kanji.strokes) != null ? _a : "unknown"}`,
2603
- ...kanji.frequency ? [`kanji::frequency::${kanji.frequency}`] : [],
2604
- ...kanji.grade ? [`kanji::grade::${kanji.grade}`] : [],
2605
- ...kanji.jlpt ? [`kanji::pre-2010_jlpt::${kanji.jlpt.toLowerCase()}`] : [],
2606
- `kanji::onyomi::${(_c = (_b = kanji.onyomi) == null ? void 0 : _b.length) != null ? _c : 0}`,
2607
- `kanji::kunyomi::${(_e = (_d = kanji.kunyomi) == null ? void 0 : _d.length) != null ? _e : 0}`,
2608
- `kanji::nanori::${(_g = (_f = kanji.nanori) == null ? void 0 : _f.length) != null ? _g : 0}`,
2609
- `kanji::words::${(_i = (_h = kanji.words) == null ? void 0 : _h.length) != null ? _i : 0}`,
2610
- ...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"] : []
2611
2533
  );
2612
- return kanji;
2613
- } else
2614
- throw new Error(`Kanji not found${kanjiChar ? `: ${kanjiChar}` : ""}`);
2615
- } catch (err) {
2616
- throw err;
2617
- }
2534
+ return kanji2;
2535
+ } else return void 0;
2618
2536
  }
2619
- function getKanjiExtended(info, dict, kanjiChar, dictKanji, useWords, jmDict, svgList, noteTypeName, deckPath) {
2620
- var _a, _b, _c, _d;
2621
- try {
2622
- const kanji = getKanji(
2623
- dict,
2624
- kanjiChar,
2625
- dictKanji,
2626
- jmDict,
2627
- svgList,
2628
- noteTypeName,
2629
- deckPath
2630
- );
2631
- if (info.components && info.components.length > 0)
2632
- kanji.components = info.components;
2633
- if (info.mnemonic && info.mnemonic.length > 0)
2634
- kanji.mnemonic = info.mnemonic;
2635
- if (useWords === true && info.words && info.words.length > 0)
2636
- kanji.words = info.words;
2637
- if (kanji.tags) {
2638
- kanji.tags.push(`kanji::components::${(_b = (_a = kanji.components) == null ? void 0 : _a.length) != null ? _b : 0}`);
2639
- if (kanji.mnemonic && kanji.mnemonic.length > 0)
2640
- kanji.tags.push("kanji::has_mnemonic");
2641
- if (useWords === true && kanji.words) {
2642
- if (!kanji.tags.some((tag, index) => {
2643
- var _a2, _b2;
2644
- if (tag.startsWith("kanji::words::")) {
2645
- 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(
2646
2569
  index,
2647
2570
  1,
2648
- `kanji::words::${(_b2 = (_a2 = kanji.words) == null ? void 0 : _a2.length) != null ? _b2 : 0}`
2571
+ `kanji::words::${kanjiObj.words.length}`
2649
2572
  );
2650
- return true;
2651
- } else return false;
2652
- }))
2653
- kanji.tags.push(`kanji::words::${(_d = (_c = kanji.words) == null ? void 0 : _c.length) != null ? _d : 0}`);
2654
- }
2655
- }
2656
- if (info.fromJpdb === true && (kanji.mnemonic || kanji.components || kanji.words && useWords === true))
2657
- kanji.source = `https://jpdb.io/kanji/${kanji.kanji}`;
2658
- return kanji;
2659
- } catch (err) {
2660
- throw err;
2661
- }
2662
- }
2663
- async function synthesizeSpeech(client, input, options) {
2664
- return await new Promise(
2665
- async (resolve, reject) => {
2666
- try {
2667
- const command = new import_client_polly.SynthesizeSpeechCommand({
2668
- Text: input,
2669
- ...options
2573
+ }
2670
2574
  });
2671
- const response = await client.send(command);
2672
- const stream = response.AudioStream ? Buffer.from(await response.AudioStream.transformToByteArray()) : null;
2673
- resolve(stream);
2674
- } catch (err) {
2675
- reject(err);
2676
- }
2677
2575
  }
2678
- );
2576
+ if (sourceURL && info.externalInfo === true && usedInfo)
2577
+ kanjiObj.source = sourceURL;
2578
+ return kanjiObj;
2579
+ } else return void 0;
2679
2580
  }
2680
2581
  function isWord(entry) {
2681
2582
  return entry.translations !== void 0 && entry.readings !== void 0;
2682
2583
  }
2683
2584
  function isRadical(entry) {
2684
- return entry.radical !== void 0 && entry.reading !== void 0 && entry.meanings !== void 0;
2585
+ return entry.radical !== void 0;
2685
2586
  }
2686
2587
  function isKanji(entry) {
2687
2588
  return entry.translations === void 0 && entry.readings === void 0 && entry.radical === void 0 && entry.kanji !== void 0;
2688
2589
  }
2689
2590
  function isKana(entry) {
2690
- return entry.kana !== void 0 && entry.reading !== void 0;
2591
+ return entry.kana !== void 0;
2691
2592
  }
2692
2593
  function isGrammar(entry) {
2693
- return entry.point !== void 0 && entry.meaning !== void 0;
2594
+ return entry.point !== void 0;
2694
2595
  }
2695
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>" : ""}`;
2696
2597
  var createEntry = (entry, notes, phrase, glossSpecific) => `<div class="entry${glossSpecific ? " gloss-specific" : ""}">${entry}${notes && notes.length > 0 ? createNotes(notes, phrase) : ""}</div>`;
2697
2598
  var noKanjiForms = '<span class="word word-kanjiform">(no kanji forms)</span>';
2698
2599
  function generateAnkiNote(entry) {
2699
- if (!entry.noteID) throw new Error("Invalid note ID");
2700
2600
  const fields = [];
2701
2601
  if (isWord(entry)) {
2702
- if (!entry.translations || entry.readings.length === 0)
2703
- throw new Error(`Invalid word: ${entry.noteID}`);
2704
2602
  const firstReading = createEntry(
2705
2603
  `<span class="word word-reading">${entry.readings[0].reading}${entry.readings[0].audio !== void 0 ? `<br>[sound:${entry.readings[0].audio}]` : ""}</span>`,
2706
2604
  entry.readings[0].notes
@@ -2757,7 +2655,7 @@ function generateAnkiNote(entry) {
2757
2655
  (definitionEntry) => {
2758
2656
  var _a;
2759
2657
  return createEntry(
2760
- `<span class="word word-definition${definitionEntry.mayNotBeAccurate === true ? " mnba" : ""}>"<span class="word word-definition-original">${definitionEntry.definition}</span><span class="word word-definition-furigana">${(_a = definitionEntry.furigana) != null ? _a : definitionEntry.definition}</span></span>`
2658
+ `<span class="word word-definition${definitionEntry.mayNotBeAccurate === true ? " mnba" : ""}"><span class="word word-definition-original">${definitionEntry.definition}</span><span class="word word-definition-furigana">${(_a = definitionEntry.furigana) != null ? _a : definitionEntry.definition}</span></span>`
2761
2659
  );
2762
2660
  }
2763
2661
  ).join("") : '<span class="word word-definition">(no definitions)</span>',
@@ -2798,7 +2696,7 @@ function generateAnkiNote(entry) {
2798
2696
  entry.strokes ? createEntry(
2799
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>`
2800
2698
  ) : '<span class="radical radical-strokes">(no stroke number)</span>',
2801
- 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>',
2802
2700
  ...entry.tags && entry.tags.length > 0 ? [
2803
2701
  entry.tags.map(
2804
2702
  (tag) => tag.trim().toLowerCase().replaceAll(" ", "::")
@@ -2836,11 +2734,9 @@ function generateAnkiNote(entry) {
2836
2734
  entry.mnemonic ? createEntry(
2837
2735
  `<span class="kanji kanji-mnemonic">${entry.mnemonic}</span>`
2838
2736
  ) : '<span class="kanji kanji-mnemonic">(no mnemonic) (Come up with your own!)</span>',
2839
- entry.words ? entry.words.filter(
2840
- (word) => word.translations && word.translations.length > 0
2841
- ).map(
2737
+ entry.words ? entry.words.map(
2842
2738
  (word) => createEntry(
2843
- `<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>`
2844
2740
  )
2845
2741
  ).join("") : '<span class="kanji kanji-words">(no words) (Search on dictionaries!)</span>',
2846
2742
  entry.strokes ? createEntry(
@@ -2898,48 +2794,85 @@ function generateAnkiNote(entry) {
2898
2794
  ).join(" ")
2899
2795
  ] : []
2900
2796
  );
2901
- if (fields.length > 0)
2902
- return fields.map((field) => field.replaceAll("\n", "<br>"));
2903
- else throw new Error("Invalid entry");
2797
+ return fields.map((field) => field.replaceAll("\n", "<br>"));
2904
2798
  }
2905
- function generateAnkiNotesFile(list) {
2799
+ function generateAnkiNotesFile(list, defaultNoteInfo) {
2800
+ const headers = [noteHeaderKeys.separator, noteHeaderKeys.html];
2801
+ let ankiNotes = "";
2906
2802
  if (list.length > 0) {
2907
- const headers = [
2908
- "#separator:tab",
2909
- "#html:true",
2910
- "#guid column:1",
2911
- "#notetype column:2",
2912
- "#deck column:3"
2913
- ];
2914
- const ankiNotes = list.filter((result) => result.doNotCreateNote === void 0).map((result) => {
2915
- if (!result.noteID || !result.noteTypeName || !result.deckPath)
2916
- 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
+ }
2917
2846
  const note = generateAnkiNote(result);
2918
- if (headers.length === 5)
2919
- headers.push(`#tags column:${note.length + 3}
2920
- `);
2921
- 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(" ")}`;
2922
2852
  }).join("\n").trim();
2923
- if (ankiNotes.length === 0) throw new Error("Invalid list");
2924
- return `${headers.join("\n")}
2853
+ }
2854
+ return `${headers.join("\n")}
2855
+
2925
2856
  ${ankiNotes}`;
2926
- } else throw new Error("No entries available for Anki notes creation");
2927
2857
  }
2928
2858
  // Annotate the CommonJS export names for ESM import in node:
2929
2859
  0 && (module.exports = {
2930
2860
  capitalizeString,
2931
2861
  convertJMdict,
2932
- convertJawiktionary,
2862
+ convertJawiktionaryAsync,
2863
+ convertJawiktionarySync,
2933
2864
  convertKanjiDic,
2934
2865
  convertKradFile,
2935
2866
  convertRadkFile,
2936
2867
  convertTanakaCorpus,
2868
+ convertTanakaCorpusWithFurigana,
2937
2869
  generateAnkiNote,
2938
2870
  generateAnkiNotesFile,
2939
2871
  getKanji,
2940
2872
  getKanjiExtended,
2941
2873
  getWord,
2942
2874
  getWordDefinitions,
2875
+ getWordDefinitionsWithFurigana,
2943
2876
  isGrammar,
2944
2877
  isKana,
2945
2878
  isKanji,
@@ -2949,9 +2882,9 @@ ${ankiNotes}`;
2949
2882
  isValidArrayWithFirstElement,
2950
2883
  isWord,
2951
2884
  notSearchedForms,
2885
+ noteHeaderKeys,
2952
2886
  noteMap,
2953
2887
  regexps,
2954
- shuffleArray,
2955
- synthesizeSpeech
2888
+ shuffleArray
2956
2889
  });
2957
2890
  //# sourceMappingURL=index.cjs.js.map