henkan 2.0.3 → 2.1.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 (72) hide show
  1. package/dist/index.cjs.js +621 -694
  2. package/dist/index.cjs.js.map +2 -2
  3. package/dist/index.mjs +615 -689
  4. package/dist/index.mjs.map +2 -2
  5. package/dist/types/constants.d.ts.map +1 -1
  6. package/dist/types/types.d.ts +40 -19
  7. package/dist/types/types.d.ts.map +1 -1
  8. package/dist/types/utils.d.ts +32 -24
  9. package/dist/types/utils.d.ts.map +1 -1
  10. package/docs/api/README.md +4 -1
  11. package/docs/api/functions/capitalizeString.md +1 -1
  12. package/docs/api/functions/convertJMdict.md +1 -1
  13. package/docs/api/functions/convertJawiktionaryAsync.md +1 -1
  14. package/docs/api/functions/convertJawiktionarySync.md +1 -1
  15. package/docs/api/functions/convertKanjiDic.md +1 -1
  16. package/docs/api/functions/convertKradFile.md +1 -1
  17. package/docs/api/functions/convertRadkFile.md +1 -1
  18. package/docs/api/functions/convertTanakaCorpus.md +1 -1
  19. package/docs/api/functions/convertTanakaCorpusWithFurigana.md +1 -1
  20. package/docs/api/functions/generateAnkiNote.md +1 -1
  21. package/docs/api/functions/generateAnkiNotesFile.md +1 -1
  22. package/docs/api/functions/getKanji.md +7 -7
  23. package/docs/api/functions/getKanjiExtended.md +6 -6
  24. package/docs/api/functions/getValidForms.md +39 -0
  25. package/docs/api/functions/getWord.md +9 -9
  26. package/docs/api/functions/getWordDefinitions.md +1 -1
  27. package/docs/api/functions/getWordDefinitionsWithFurigana.md +1 -1
  28. package/docs/api/functions/isObjectArray.md +27 -0
  29. package/docs/api/functions/isStringArray.md +2 -2
  30. package/docs/api/functions/isValidArrayWithFirstElement.md +2 -2
  31. package/docs/api/functions/shuffleArray.md +1 -1
  32. package/docs/api/interfaces/DefaultNoteInfo.md +4 -4
  33. package/docs/api/interfaces/Definition.md +4 -4
  34. package/docs/api/interfaces/DictKanji.md +5 -5
  35. package/docs/api/interfaces/DictKanjiForm.md +4 -4
  36. package/docs/api/interfaces/DictKanjiMisc.md +5 -5
  37. package/docs/api/interfaces/DictKanjiReading.md +3 -3
  38. package/docs/api/interfaces/DictKanjiReadingMeaning.md +3 -3
  39. package/docs/api/interfaces/DictKanjiReadingMeaningGroup.md +3 -3
  40. package/docs/api/interfaces/DictKanjiWithRadicals.md +3 -3
  41. package/docs/api/interfaces/DictMeaning.md +15 -15
  42. package/docs/api/interfaces/DictRadical.md +4 -4
  43. package/docs/api/interfaces/DictReading.md +5 -5
  44. package/docs/api/interfaces/DictWord.md +9 -9
  45. package/docs/api/interfaces/ExamplePart.md +8 -8
  46. package/docs/api/interfaces/GlossSpecificNumber.md +4 -4
  47. package/docs/api/interfaces/Grammar.md +15 -15
  48. package/docs/api/interfaces/GrammarMeaning.md +3 -3
  49. package/docs/api/interfaces/JaWiktionaryEntry.md +8 -20
  50. package/docs/api/interfaces/Kana.md +11 -11
  51. package/docs/api/interfaces/Kanji.md +24 -24
  52. package/docs/api/interfaces/KanjiComponent.md +3 -3
  53. package/docs/api/interfaces/KanjiForm.md +4 -4
  54. package/docs/api/interfaces/NoteAndTag.md +3 -3
  55. package/docs/api/interfaces/NoteHeaderKeys.md +7 -7
  56. package/docs/api/interfaces/Phrase.md +5 -5
  57. package/docs/api/interfaces/Radical.md +16 -16
  58. package/docs/api/interfaces/Reading.md +5 -5
  59. package/docs/api/interfaces/ReadingsKanjiFormsPair.md +31 -0
  60. package/docs/api/interfaces/ResultEntry.md +7 -7
  61. package/docs/api/interfaces/TanakaExample.md +7 -7
  62. package/docs/api/interfaces/Translation.md +3 -3
  63. package/docs/api/interfaces/UsefulRegExps.md +8 -8
  64. package/docs/api/interfaces/Word.md +15 -15
  65. package/docs/api/interfaces/WordDefinitionPair.md +4 -4
  66. package/docs/api/type-aliases/Dict.md +1 -1
  67. package/docs/api/type-aliases/DictTranslation.md +1 -1
  68. package/docs/api/type-aliases/EntryType.md +1 -1
  69. package/docs/api/type-aliases/Result.md +1 -1
  70. package/docs/api/type-aliases/StringNumber.md +13 -0
  71. package/package.json +2 -2
  72. package/docs/api/functions/isValidArray.md +0 -27
package/dist/index.mjs CHANGED
@@ -55,6 +55,9 @@ var noteMap = /* @__PURE__ */ new Map([
55
55
  ["tsugaru-ben", ["dialect::tsugaru-ben", "Dialect: Tsugaru-ben"]],
56
56
  ["aichi dialect", ["dialect::aichi", "Dialect: Aichi"]],
57
57
  ["tochigi dialect", ["dialect::tochigi", "Dialect: Tochigi"]],
58
+ ["lit", ["literal_meaning", "Literal meaning"]],
59
+ ["expl", ["explanation", "Explanation"]],
60
+ ["tm", ["trademark", "Trademark"]],
58
61
  ["adjective (keiyoushi)", ["adjective::i", "\u3044-adjective", "\u5F62\u5BB9\u8A5E"]],
59
62
  ["'taru' adjective", ["adjective::taru", "\u305F\u308B-adjective", "\u5F62\u5BB9\u52D5\u8A5E"]],
60
63
  [
@@ -1189,14 +1192,14 @@ var KuromojiAnalyzer = __require("kuroshiro-analyzer-kuromoji");
1189
1192
  function capitalizeString(value) {
1190
1193
  return value.charAt(0).toUpperCase() + value.slice(1);
1191
1194
  }
1192
- function isValidArray(arg) {
1193
- return arg !== null && arg !== void 0 && Array.isArray(arg);
1194
- }
1195
1195
  function isValidArrayWithFirstElement(arg) {
1196
- return arg !== null && arg !== void 0 && Array.isArray(arg) && arg[0] !== null && arg[0] !== void 0;
1196
+ return Array.isArray(arg) && arg.length > 0;
1197
1197
  }
1198
1198
  function isStringArray(arg) {
1199
- return arg !== null && arg !== void 0 && Array.isArray(arg) && arg.every((element) => typeof element === "string");
1199
+ return isValidArrayWithFirstElement(arg) && arg.every((element) => typeof element === "string");
1200
+ }
1201
+ function isObjectArray(arg) {
1202
+ return isValidArrayWithFirstElement(arg) && arg.every((element) => typeof element === "object");
1200
1203
  }
1201
1204
  function shuffleArray(arr) {
1202
1205
  const a = arr.slice();
@@ -1208,6 +1211,37 @@ function shuffleArray(arr) {
1208
1211
  }
1209
1212
  return a;
1210
1213
  }
1214
+ function getValidForms(readings, kanjiForms, wordIsCommon) {
1215
+ const kanjiFormRestrictions = /* @__PURE__ */ new Set();
1216
+ const validReadings = readings.filter(
1217
+ (reading) => {
1218
+ if (reading.notes === void 0 || !reading.notes.some((note) => notSearchedForms.has(note))) {
1219
+ if (reading.kanjiFormRestrictions) {
1220
+ for (const kfr of reading.kanjiFormRestrictions)
1221
+ kanjiFormRestrictions.add(kfr);
1222
+ return true;
1223
+ }
1224
+ if (wordIsCommon === void 0 || reading.commonness !== void 0)
1225
+ return true;
1226
+ }
1227
+ return false;
1228
+ }
1229
+ );
1230
+ const existValidKf = kanjiForms ? kanjiForms.some(
1231
+ (kf) => (kf.notes === void 0 || !kf.notes.some((note) => notSearchedForms.has(note))) && (wordIsCommon === void 0 || kf.commonness !== void 0) || kanjiFormRestrictions.has(kf.form)
1232
+ ) : void 0;
1233
+ const validKanjiForms = kanjiForms ? kanjiForms.filter((kanjiForm) => {
1234
+ if (existValidKf === true)
1235
+ return (kanjiForm.notes === void 0 || !kanjiForm.notes.some(
1236
+ (note) => notSearchedForms.has(note)
1237
+ )) && (wordIsCommon === void 0 || kanjiForm.commonness !== void 0) || kanjiFormRestrictions.has(kanjiForm.form);
1238
+ else return true;
1239
+ }) : void 0;
1240
+ return {
1241
+ readings: validReadings,
1242
+ ...validKanjiForms ? { kanjiForms: validKanjiForms } : {}
1243
+ };
1244
+ }
1211
1245
  function convertJMdict(xmlString, examples) {
1212
1246
  const dictParsed = libxml.parseXml(xmlString, {
1213
1247
  dtdvalid: true,
@@ -1216,144 +1250,116 @@ function convertJMdict(xmlString, examples) {
1216
1250
  recover: false
1217
1251
  });
1218
1252
  const dict = [];
1219
- xml.parseString(dictParsed, (err, result) => {
1220
- if (err === null) {
1221
- const tanakaParts = examples && examples.length > 0 ? new Set(
1222
- examples.map(
1223
- (example) => example.parts.map((part) => [
1224
- part.baseForm,
1225
- ...part.reading ? [part.reading] : [],
1226
- ...part.referenceID ? [part.referenceID] : []
1227
- ])
1228
- ).flat(2)
1229
- ) : void 0;
1230
- if (result.JMdict && typeof result.JMdict === "object" && isValidArray(result.JMdict.entry))
1231
- for (const entry of result.JMdict.entry) {
1232
- const entryObj = {
1233
- id: entry.ent_seq[0],
1234
- readings: [],
1235
- meanings: []
1253
+ xml.parseString(dictParsed, (_err, result) => {
1254
+ const tanakaParts = examples && examples.length > 0 ? new Set(
1255
+ examples.flatMap(
1256
+ (example) => example.parts.flatMap((part) => [
1257
+ part.baseForm,
1258
+ ...part.reading ? [part.reading] : [],
1259
+ ...part.inflectedForm ? [part.inflectedForm] : [],
1260
+ ...part.referenceID ? [part.referenceID] : []
1261
+ ])
1262
+ )
1263
+ ) : void 0;
1264
+ for (const entry of result.JMdict.entry) {
1265
+ const entryObj = {
1266
+ id: entry.ent_seq[0],
1267
+ readings: [],
1268
+ meanings: []
1269
+ };
1270
+ const kanjiForms = entry.k_ele;
1271
+ const readings = entry.r_ele;
1272
+ const meanings = entry.sense;
1273
+ if (isObjectArray(kanjiForms)) {
1274
+ entryObj.kanjiForms = [];
1275
+ for (const kanjiForm of kanjiForms) {
1276
+ const form = {
1277
+ form: kanjiForm.keb[0]
1236
1278
  };
1237
- if (typeof entryObj.id === "string") {
1238
- const kanjiForms = entry.k_ele;
1239
- const readings = entry.r_ele;
1240
- const meanings = entry.sense;
1241
- if (isValidArray(kanjiForms)) {
1242
- entryObj.kanjiForms = [];
1243
- for (const kanjiForm of kanjiForms) {
1244
- const form = {
1245
- form: kanjiForm.keb[0]
1246
- };
1247
- if (typeof form.form === "string") {
1248
- if (isStringArray(kanjiForm.ke_inf))
1249
- form.notes = kanjiForm.ke_inf;
1250
- if (isStringArray(kanjiForm.ke_pri)) {
1251
- form.commonness = kanjiForm.ke_pri;
1252
- if (entryObj.isCommon === void 0)
1253
- entryObj.isCommon = true;
1254
- }
1255
- entryObj.kanjiForms.push(form);
1256
- }
1257
- }
1258
- }
1259
- if (isValidArray(readings))
1260
- for (const reading of readings) {
1261
- const readingObj = {
1262
- reading: reading.reb[0]
1263
- };
1264
- if (typeof readingObj.reading === "string") {
1265
- if (isStringArray(reading.re_inf))
1266
- readingObj.notes = reading.re_inf;
1267
- if (isStringArray(reading.re_restr))
1268
- readingObj.kanjiFormRestrictions = reading.re_restr;
1269
- if (isStringArray(reading.re_pri)) {
1270
- readingObj.commonness = reading.re_pri;
1271
- if (entryObj.isCommon === void 0)
1272
- entryObj.isCommon = true;
1273
- }
1274
- entryObj.readings.push(readingObj);
1275
- }
1276
- }
1277
- if (isValidArray(meanings)) {
1278
- let usuallyInKanaMeanings = 0;
1279
- for (const meaning of meanings) {
1280
- const meaningObj = {};
1281
- if (isStringArray(meaning.pos))
1282
- meaningObj.partOfSpeech = meaning.pos;
1283
- if (isValidArray(meaning.gloss)) {
1284
- meaningObj.translations = [];
1285
- for (const gloss of meaning.gloss)
1286
- if (typeof gloss === "string")
1287
- meaningObj.translations.push(gloss);
1288
- 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"))
1289
- meaningObj.translations.push({
1290
- translation: gloss._,
1291
- type: gloss.$.g_type
1292
- });
1293
- }
1294
- if (isStringArray(meaning.xref))
1295
- meaningObj.references = meaning.xref;
1296
- if (isStringArray(meaning.stagk))
1297
- meaningObj.kanjiFormRestrictions = meaning.stagk;
1298
- if (isStringArray(meaning.stagr))
1299
- meaningObj.readingRestrictions = meaning.stagr;
1300
- if (isStringArray(meaning.ant))
1301
- meaningObj.antonyms = meaning.ant;
1302
- if (isStringArray(meaning.field))
1303
- meaningObj.fields = meaning.field;
1304
- if (isStringArray(meaning.s_inf))
1305
- meaningObj.info = meaning.s_inf;
1306
- if (isStringArray(meaning.misc)) {
1307
- meaningObj.misc = meaning.misc;
1308
- if (meaningObj.misc && meaningObj.misc.includes(
1309
- "word usually written using kana alone"
1310
- ))
1311
- usuallyInKanaMeanings++;
1312
- }
1313
- if (isStringArray(meaning.dial))
1314
- meaningObj.dialects = meaning.dial;
1315
- if (meaningObj.partOfSpeech && meaningObj.partOfSpeech.length > 0)
1316
- entryObj.meanings.push(meaningObj);
1317
- }
1318
- if (entryObj.meanings.length === usuallyInKanaMeanings)
1319
- entryObj.usuallyInKana = true;
1320
- }
1321
- if (examples) {
1322
- const readings2 = new Set(
1323
- entryObj.readings.filter(
1324
- (reading) => reading.notes === void 0 || !reading.notes.some(
1325
- (note) => notSearchedForms.has(note)
1326
- ) || reading.commonness
1327
- ).map((reading) => reading.reading)
1328
- );
1329
- const kanjiForms2 = entryObj.kanjiForms ? new Set(
1330
- entryObj.kanjiForms.map(
1331
- (kanjiForm) => kanjiForm.form
1332
- )
1333
- ) : void 0;
1334
- let existsExample = false;
1335
- if (kanjiForms2 && kanjiForms2.size > 0 && tanakaParts) {
1336
- for (const kf of kanjiForms2)
1337
- if (tanakaParts.has(kf)) {
1338
- existsExample = true;
1339
- break;
1340
- }
1341
- }
1342
- if (!existsExample && readings2.size > 0 && tanakaParts) {
1343
- for (const r of readings2)
1344
- if (tanakaParts.has(r)) {
1345
- existsExample = true;
1346
- break;
1347
- }
1279
+ if (isStringArray(kanjiForm.ke_inf)) form.notes = kanjiForm.ke_inf;
1280
+ if (isStringArray(kanjiForm.ke_pri)) {
1281
+ form.commonness = kanjiForm.ke_pri;
1282
+ if (entryObj.isCommon === void 0) entryObj.isCommon = true;
1283
+ }
1284
+ entryObj.kanjiForms.push(form);
1285
+ }
1286
+ }
1287
+ for (const reading of readings) {
1288
+ const readingObj = {
1289
+ reading: reading.reb[0]
1290
+ };
1291
+ if (isStringArray(reading.re_inf)) readingObj.notes = reading.re_inf;
1292
+ if (isStringArray(reading.re_restr))
1293
+ readingObj.kanjiFormRestrictions = reading.re_restr;
1294
+ if (isStringArray(reading.re_pri)) {
1295
+ readingObj.commonness = reading.re_pri;
1296
+ if (entryObj.isCommon === void 0) entryObj.isCommon = true;
1297
+ }
1298
+ entryObj.readings.push(readingObj);
1299
+ }
1300
+ let usuallyInKanaMeanings = 0;
1301
+ for (const meaning of meanings) {
1302
+ const meaningObj = { partOfSpeech: [], translations: [] };
1303
+ meaningObj.partOfSpeech = meaning.pos;
1304
+ meaningObj.translations = [];
1305
+ for (const gloss of meaning.gloss)
1306
+ if (typeof gloss === "string") meaningObj.translations.push(gloss);
1307
+ 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"))
1308
+ meaningObj.translations.push({
1309
+ translation: gloss._,
1310
+ type: gloss.$.g_type
1311
+ });
1312
+ if (isStringArray(meaning.xref)) meaningObj.references = meaning.xref;
1313
+ if (isStringArray(meaning.stagk))
1314
+ meaningObj.kanjiFormRestrictions = meaning.stagk;
1315
+ if (isStringArray(meaning.stagr))
1316
+ meaningObj.readingRestrictions = meaning.stagr;
1317
+ if (isStringArray(meaning.ant)) meaningObj.antonyms = meaning.ant;
1318
+ if (isStringArray(meaning.field)) meaningObj.fields = meaning.field;
1319
+ if (isStringArray(meaning.s_inf)) meaningObj.info = meaning.s_inf;
1320
+ if (isStringArray(meaning.misc)) {
1321
+ meaningObj.misc = meaning.misc;
1322
+ if (meaningObj.misc && meaningObj.misc.includes("word usually written using kana alone"))
1323
+ usuallyInKanaMeanings++;
1324
+ }
1325
+ if (isStringArray(meaning.dial)) meaningObj.dialects = meaning.dial;
1326
+ entryObj.meanings.push(meaningObj);
1327
+ }
1328
+ if (entryObj.meanings.length === usuallyInKanaMeanings)
1329
+ entryObj.usuallyInKana = true;
1330
+ if (examples) {
1331
+ let existsExample = false;
1332
+ if (tanakaParts && tanakaParts.has(entryObj.id)) existsExample = true;
1333
+ if (!existsExample) {
1334
+ const rkf = getValidForms(
1335
+ entryObj.readings,
1336
+ entryObj.kanjiForms,
1337
+ entryObj.isCommon
1338
+ );
1339
+ const readings2 = new Set(
1340
+ rkf.readings.map((r) => r.reading)
1341
+ );
1342
+ const kanjiForms2 = rkf.kanjiForms ? new Set(
1343
+ rkf.kanjiForms.map((kf) => kf.form)
1344
+ ) : void 0;
1345
+ if (kanjiForms2 && kanjiForms2.size > 0 && tanakaParts) {
1346
+ for (const kf of kanjiForms2)
1347
+ if (tanakaParts.has(kf)) {
1348
+ existsExample = true;
1349
+ break;
1348
1350
  }
1349
- if (tanakaParts && tanakaParts.has(entryObj.id))
1351
+ }
1352
+ if (entryObj.kanjiForms === void 0 && readings2.size > 0 && tanakaParts) {
1353
+ for (const r of readings2)
1354
+ if (tanakaParts.has(r)) {
1350
1355
  existsExample = true;
1351
- if (existsExample) entryObj.hasPhrases = true;
1352
- }
1353
- if (entryObj.id.length > 0 && entryObj.readings.length > 0 && entryObj.meanings.length > 0)
1354
- dict.push(entryObj);
1356
+ break;
1357
+ }
1355
1358
  }
1356
1359
  }
1360
+ if (existsExample) entryObj.hasPhrases = true;
1361
+ }
1362
+ dict.push(entryObj);
1357
1363
  }
1358
1364
  });
1359
1365
  return dict;
@@ -1366,75 +1372,64 @@ function convertKanjiDic(xmlString) {
1366
1372
  recover: false
1367
1373
  });
1368
1374
  const dict = [];
1369
- xml.parseString(dictParsed, (err, result) => {
1370
- if (err === null) {
1371
- if (result.kanjidic2 && typeof result.kanjidic2 === "object" && isValidArray(result.kanjidic2.character))
1372
- for (const entry of result.kanjidic2.character) {
1373
- const kanjiObj = {
1374
- kanji: entry.literal[0]
1375
- };
1376
- if (typeof kanjiObj.kanji === "string" && kanjiObj.kanji.length === 1) {
1377
- if (isValidArrayWithFirstElement(entry.misc) && typeof entry.misc[0] === "object") {
1378
- const misc = entry.misc[0];
1379
- kanjiObj.misc = {};
1380
- if (isValidArrayWithFirstElement(misc.stroke_count) && typeof misc.stroke_count[0] === "string")
1381
- kanjiObj.misc.strokeNumber = misc.stroke_count[0];
1382
- if (isValidArrayWithFirstElement(misc.grade) && typeof misc.grade[0] === "string")
1383
- kanjiObj.misc.grade = misc.grade[0];
1384
- if (isValidArrayWithFirstElement(misc.freq) && typeof misc.freq[0] === "string")
1385
- kanjiObj.misc.frequency = misc.freq[0];
1386
- if (isValidArrayWithFirstElement(misc.jlpt) && typeof misc.jlpt[0] === "string" && ["5", "4", "3", "2", "1"].includes(misc.jlpt[0]))
1387
- kanjiObj.misc.jlpt = `N${misc.jlpt[0]}`;
1388
- }
1389
- if (isValidArray(entry.reading_meaning))
1390
- for (const rm of entry.reading_meaning) {
1391
- const rmObj = { groups: [] };
1392
- if (isValidArray(rm.rmgroup))
1393
- for (const group of rm.rmgroup) {
1394
- const groupObj = {
1395
- readings: [],
1396
- meanings: []
1397
- };
1398
- if (isValidArray(group.reading)) {
1399
- for (const reading of group.reading)
1400
- if (reading._ && typeof reading._ === "string" && reading.$ && typeof reading.$ === "object" && reading.$.r_type && (reading.$.r_type === "ja_on" || reading.$.r_type === "ja_kun"))
1401
- groupObj.readings.push({
1402
- reading: reading._,
1403
- type: reading.$.r_type
1404
- });
1405
- }
1406
- if (isValidArray(group.meaning)) {
1407
- for (const meaning of group.meaning)
1408
- if (typeof meaning === "string") {
1409
- if (kanjiObj.isKokuji === void 0 && meaning === "(kokuji)")
1410
- kanjiObj.isKokuji = true;
1411
- groupObj.meanings.push(meaning);
1412
- }
1413
- }
1414
- if (groupObj.readings.length > 0 || groupObj.meanings.length > 0) {
1415
- if (groupObj.readings.length === 0)
1416
- delete groupObj.readings;
1417
- if (groupObj.meanings.length === 0)
1418
- delete groupObj.meanings;
1419
- rmObj.groups.push(groupObj);
1375
+ xml.parseString(dictParsed, (_err, result) => {
1376
+ for (const entry of result.kanjidic2.character) {
1377
+ const kanjiObj = {
1378
+ kanji: entry.literal[0],
1379
+ readingMeaning: []
1380
+ };
1381
+ if (typeof kanjiObj.kanji === "string" && kanjiObj.kanji.length === 1) {
1382
+ const misc = entry.misc[0];
1383
+ kanjiObj.misc = { strokeNumber: misc.stroke_count[0] };
1384
+ if (isStringArray(misc.grade)) kanjiObj.misc.grade = misc.grade[0];
1385
+ if (isStringArray(misc.freq)) kanjiObj.misc.frequency = misc.freq[0];
1386
+ if (isStringArray(misc.jlpt) && ["5", "4", "3", "2", "1"].includes(misc.jlpt[0]))
1387
+ kanjiObj.misc.jlpt = `N${misc.jlpt[0]}`;
1388
+ if (isObjectArray(entry.reading_meaning))
1389
+ for (const rm of entry.reading_meaning) {
1390
+ const rmObj = { groups: [] };
1391
+ for (const group of rm.rmgroup) {
1392
+ const groupObj = {
1393
+ readings: [],
1394
+ meanings: []
1395
+ };
1396
+ if (isObjectArray(group.reading)) {
1397
+ for (const reading of group.reading)
1398
+ if (reading._ && typeof reading._ === "string" && reading.$ && typeof reading.$ === "object" && reading.$.r_type && (reading.$.r_type === "ja_on" || reading.$.r_type === "ja_kun"))
1399
+ groupObj.readings.push({
1400
+ reading: reading._,
1401
+ type: reading.$.r_type
1402
+ });
1403
+ }
1404
+ if (Array.isArray(group.meaning)) {
1405
+ for (const meaning of group.meaning)
1406
+ if (typeof meaning === "string") {
1407
+ if (kanjiObj.isKokuji === void 0 && meaning === "(kokuji)") {
1408
+ kanjiObj.isKokuji = true;
1409
+ continue;
1420
1410
  }
1411
+ groupObj.meanings.push(meaning);
1421
1412
  }
1422
- if (isStringArray(rm.nanori) && rm.nanori.length > 0)
1423
- rmObj.nanori = rm.nanori;
1424
- if (rmObj.groups.length > 0 || rmObj.nanori) {
1425
- if (kanjiObj.readingMeaning === void 0)
1426
- kanjiObj.readingMeaning = [];
1427
- kanjiObj.readingMeaning.push(rmObj);
1428
- }
1429
1413
  }
1430
- dict.push(kanjiObj);
1414
+ if (groupObj.readings.length > 0 || groupObj.meanings.length > 0) {
1415
+ if (groupObj.readings.length === 0) delete groupObj.readings;
1416
+ if (groupObj.meanings.length === 0) delete groupObj.meanings;
1417
+ rmObj.groups.push(groupObj);
1418
+ }
1419
+ }
1420
+ if (isStringArray(rm.nanori) && rm.nanori.length > 0)
1421
+ rmObj.nanori = rm.nanori;
1422
+ if (rmObj.groups.length > 0 || rmObj.nanori)
1423
+ kanjiObj.readingMeaning.push(rmObj);
1431
1424
  }
1432
- }
1425
+ dict.push(kanjiObj);
1426
+ }
1433
1427
  }
1434
1428
  });
1435
1429
  return dict;
1436
1430
  }
1437
1431
  function convertTanakaCorpus(tanakaString) {
1432
+ var _a;
1438
1433
  const tanakaArray = [];
1439
1434
  const tanakaParsed = tanakaString.split("\n");
1440
1435
  for (let i = 0; i <= tanakaParsed.length; i += 2) {
@@ -1444,46 +1439,38 @@ function convertTanakaCorpus(tanakaString) {
1444
1439
  a = a.replace("A: ", "");
1445
1440
  b = b.replace("B: ", "");
1446
1441
  const idMatch = regexps.tanakaID.exec(a);
1447
- if (idMatch && idMatch.groups && idMatch.groups["id"]) {
1448
- const aParts = a.replace(regexps.tanakaID, "").split(" ");
1449
- const bRawParts = b.split(" ").filter((part) => part.trim().length !== 0);
1450
- const bParts = [];
1451
- for (const part of bRawParts) {
1452
- const partMatches = regexps.tanakaPart.exec(part);
1453
- if (partMatches && partMatches.groups && partMatches.length > 0) {
1454
- const baseForm = partMatches.groups["base"];
1455
- if (baseForm) {
1456
- const examplePart = { baseForm };
1457
- const reading = partMatches.groups["reading"];
1458
- const glossNumber = partMatches.groups["glossnum"];
1459
- const inflectedForm = partMatches.groups["inflection"];
1460
- if (reading)
1461
- if (regexps.tanakaReferenceID.test(reading)) {
1462
- const referenceID = regexps.tanakaReferenceID.exec(reading);
1463
- if (referenceID && referenceID.groups && referenceID.groups["entryid"])
1464
- examplePart.referenceID = referenceID.groups["entryid"];
1465
- } else examplePart.reading = reading;
1466
- if (glossNumber)
1467
- examplePart.glossNumber = glossNumber.startsWith("0") ? Number.parseInt(glossNumber.substring(1)) : Number.parseInt(glossNumber);
1468
- if (inflectedForm) examplePart.inflectedForm = inflectedForm;
1469
- if (baseForm.endsWith("~")) {
1470
- examplePart.edited = true;
1471
- examplePart.baseForm = examplePart.baseForm.replace("~", "");
1472
- }
1473
- bParts.push(examplePart);
1474
- }
1475
- }
1442
+ const aParts = a.replace(regexps.tanakaID, "").split(" ");
1443
+ const bRawParts = b.split(" ").filter((part) => part.trim().length !== 0);
1444
+ const bParts = [];
1445
+ for (const part of bRawParts) {
1446
+ const partMatches = regexps.tanakaPart.exec(part);
1447
+ const baseForm = partMatches == null ? void 0 : partMatches.groups["base"];
1448
+ const examplePart = { baseForm };
1449
+ const reading = partMatches == null ? void 0 : partMatches.groups["reading"];
1450
+ const glossNumber = partMatches == null ? void 0 : partMatches.groups["glossnum"];
1451
+ const inflectedForm = partMatches == null ? void 0 : partMatches.groups["inflection"];
1452
+ if (reading)
1453
+ if (regexps.tanakaReferenceID.test(reading)) {
1454
+ const referenceID = regexps.tanakaReferenceID.exec(reading);
1455
+ examplePart.referenceID = referenceID == null ? void 0 : referenceID.groups["entryid"];
1456
+ } else examplePart.reading = reading;
1457
+ if (glossNumber)
1458
+ examplePart.glossNumber = glossNumber.startsWith("0") ? Number.parseInt(glossNumber.substring(1)) : Number.parseInt(glossNumber);
1459
+ if (inflectedForm) examplePart.inflectedForm = inflectedForm;
1460
+ if (baseForm.endsWith("~")) {
1461
+ examplePart.edited = true;
1462
+ examplePart.baseForm = examplePart.baseForm.replace("~", "");
1476
1463
  }
1477
- const phrase = aParts[0];
1478
- const translation = aParts[1];
1479
- if (phrase && translation)
1480
- tanakaArray.push({
1481
- id: idMatch.groups["id"].trim(),
1482
- phrase: phrase.trim(),
1483
- translation: translation.trim(),
1484
- parts: bParts
1485
- });
1464
+ bParts.push(examplePart);
1486
1465
  }
1466
+ const phrase = aParts[0];
1467
+ const translation = aParts[1];
1468
+ tanakaArray.push({
1469
+ id: (_a = idMatch == null ? void 0 : idMatch.groups["id"]) == null ? void 0 : _a.trim(),
1470
+ phrase: phrase.trim(),
1471
+ translation: translation.trim(),
1472
+ parts: bParts
1473
+ });
1487
1474
  }
1488
1475
  }
1489
1476
  return tanakaArray;
@@ -1523,27 +1510,23 @@ function convertRadkFile(radkBuffer, kanjiDic) {
1523
1510
  };
1524
1511
  let j = i + 1;
1525
1512
  let kanjiLine = fileParsed[j];
1526
- if (kanjiLine) {
1527
- const kanjiList = [];
1528
- while (kanjiLine && !kanjiLine.startsWith("$ ")) {
1529
- const kanjis = kanjiLine.split("");
1530
- for (const kanji of kanjis) {
1531
- const foundKanji = kanjiDic.find(
1532
- (dictKanji) => dictKanji.kanji === kanji
1533
- );
1534
- let kanjiObj = { kanji };
1535
- if (foundKanji) kanjiObj = foundKanji;
1536
- kanjiList.push(kanjiObj);
1537
- }
1538
- j++;
1539
- kanjiLine = fileParsed[j];
1540
- if (!kanjiLine) continue;
1541
- if (kanjiLine.startsWith("$ ")) i = j - 1;
1513
+ const kanjiList = [];
1514
+ while (kanjiLine && !kanjiLine.startsWith("$ ")) {
1515
+ const kanjis = kanjiLine.split("");
1516
+ for (const kanji of kanjis) {
1517
+ const foundKanji = kanjiDic.find(
1518
+ (dictKanji) => dictKanji.kanji === kanji
1519
+ );
1520
+ let kanjiObj = { kanji };
1521
+ kanjiObj = foundKanji;
1522
+ kanjiList.push(kanjiObj);
1542
1523
  }
1543
- if (kanjiList.length > 0) radical.kanji = kanjiList;
1544
- if (radical.radical.length === 1 && radical.strokes.length > 0)
1545
- radicals.push(radical);
1524
+ kanjiLine = fileParsed[++j];
1525
+ if (!kanjiLine) continue;
1526
+ if (kanjiLine.startsWith("$ ")) i = j - 1;
1546
1527
  }
1528
+ if (kanjiList.length > 0) radical.kanji = kanjiList;
1529
+ radicals.push(radical);
1547
1530
  }
1548
1531
  }
1549
1532
  return radicals;
@@ -1556,45 +1539,39 @@ function convertKradFile(kradBuffer, kanjiDic, katakanaList) {
1556
1539
  const split = line.split(" : ");
1557
1540
  const kanjiChar = split[0];
1558
1541
  const radicalsRow = split[1];
1559
- if (kanjiChar && radicalsRow) {
1560
- const kanji = {
1561
- kanji: kanjiChar,
1562
- radicals: []
1563
- };
1564
- if (kanji.kanji.length === 1) {
1565
- const radicals = radicalsRow.split(" ");
1566
- for (const radical of radicals) {
1567
- const foundRadical = kanjiDic.find(
1568
- (dictKanji) => dictKanji.kanji === radical
1569
- );
1570
- let radicalObj = foundRadical ?? { kanji: radical };
1571
- if (!foundRadical) {
1572
- const katakanaChar = katakanaList.find(
1573
- (kana) => kana.kana === radical
1574
- );
1575
- if (!katakanaChar) continue;
1576
- radicalObj = {
1577
- kanji: katakanaChar.kana,
1578
- readingMeaning: [
1542
+ const kanji = {
1543
+ kanji: kanjiChar,
1544
+ radicals: []
1545
+ };
1546
+ const radicals = radicalsRow.split(" ");
1547
+ for (const radical of radicals) {
1548
+ const foundRadical = kanjiDic.find(
1549
+ (dictKanji) => dictKanji.kanji === radical
1550
+ );
1551
+ let radicalObj = foundRadical ?? { kanji: radical };
1552
+ if (!foundRadical) {
1553
+ const katakanaChar = katakanaList.find(
1554
+ (kana) => kana.kana === radical
1555
+ );
1556
+ if (!katakanaChar) continue;
1557
+ radicalObj = {
1558
+ kanji: katakanaChar.kana,
1559
+ readingMeaning: [
1560
+ {
1561
+ groups: [
1579
1562
  {
1580
- groups: [
1581
- {
1582
- readings: [
1583
- { reading: katakanaChar.kana, type: "ja_on" }
1584
- ],
1585
- meanings: [katakanaChar.reading]
1586
- }
1587
- ]
1563
+ readings: [{ reading: katakanaChar.kana, type: "ja_on" }],
1564
+ meanings: [katakanaChar.reading]
1588
1565
  }
1589
1566
  ]
1590
- };
1591
- }
1592
- kanji.radicals.push(radicalObj);
1593
- }
1567
+ }
1568
+ ]
1569
+ };
1594
1570
  }
1595
- if (kanji.kanji.length === 1 && kanji.radicals.length > 0)
1596
- kanjiWithRadicals.push(kanji);
1571
+ kanji.radicals.push(radicalObj);
1597
1572
  }
1573
+ if (kanji.kanji.length === 1 && kanji.radicals.length > 0)
1574
+ kanjiWithRadicals.push(kanji);
1598
1575
  }
1599
1576
  }
1600
1577
  return kanjiWithRadicals;
@@ -1604,18 +1581,16 @@ function mapEntry(entry) {
1604
1581
  word: entry.word,
1605
1582
  pos_title: entry.pos_title,
1606
1583
  senses: entry.senses.filter(
1607
- (sense) => isValidArray(sense.form_of) && sense.form_of.every(
1584
+ (sense) => isObjectArray(sense.form_of) && sense.form_of.every(
1608
1585
  (form) => form.word && typeof form.word === "string"
1609
1586
  ) || isStringArray(sense.glosses)
1610
1587
  ).map((sense) => ({
1611
1588
  ...sense.form_of ? {
1612
- form_of: sense.form_of.map((form) => ({
1613
- word: form.word
1614
- }))
1589
+ form_of: sense.form_of.map((form) => form.word)
1615
1590
  } : {},
1616
1591
  glosses: sense.glosses
1617
1592
  })),
1618
- ...isValidArray(entry.forms) && entry.forms.every((form) => typeof form.form === "string") ? { forms: entry.forms.map((form) => ({ form: form.form })) } : {}
1593
+ ...isObjectArray(entry.forms) && entry.forms.every((form) => typeof form.form === "string") ? { forms: entry.forms.map((form) => form.form) } : {}
1619
1594
  };
1620
1595
  }
1621
1596
  function convertJawiktionarySync(buffer) {
@@ -1651,17 +1626,14 @@ async function convertJawiktionaryAsync(stream) {
1651
1626
  );
1652
1627
  }
1653
1628
  function parseEntry(entry, definitions, definitionMap) {
1654
- if (isValidArray(entry.senses)) {
1655
- for (const sense of entry.senses)
1656
- if (isStringArray(sense.glosses)) {
1657
- const definition = sense.glosses.join("");
1658
- if (!definitions.some((def) => def.definition === definition)) {
1659
- if (!definitionMap.has(definition))
1660
- definitionMap.set(definition, { count: 1 });
1661
- else definitionMap.get(definition).count++;
1662
- definitions.push({ definition });
1663
- }
1664
- }
1629
+ for (const sense of entry.senses) {
1630
+ const definition = sense.glosses.join("");
1631
+ if (!definitions.some((def) => def.definition === definition)) {
1632
+ if (!definitionMap.has(definition))
1633
+ definitionMap.set(definition, { count: 1 });
1634
+ else definitionMap.get(definition).count++;
1635
+ definitions.push({ definition });
1636
+ }
1665
1637
  }
1666
1638
  }
1667
1639
  function getWordDefinitions(entryList, jmDict) {
@@ -1669,31 +1641,26 @@ function getWordDefinitions(entryList, jmDict) {
1669
1641
  const entries = /* @__PURE__ */ new Map();
1670
1642
  for (const entry of entryList) {
1671
1643
  const ent = entries.get(entry.word);
1672
- if (ent) ent.push(mapEntry(entry));
1673
- else entries.set(entry.word, [mapEntry(entry)]);
1644
+ if (ent) ent.push(entry);
1645
+ else entries.set(entry.word, [entry]);
1674
1646
  }
1675
1647
  const japaneseDefinitions = [];
1676
1648
  const definitionMap = /* @__PURE__ */ new Map();
1677
1649
  const validWords = [];
1678
1650
  const validReadings = /* @__PURE__ */ new Set();
1679
1651
  const validKanjiForms = /* @__PURE__ */ new Set();
1680
- if (jmDict.length > 0)
1681
- for (const word of jmDict) {
1682
- let valid = false;
1683
- for (const r of word.readings)
1684
- if ((r.notes === void 0 || !r.notes.some((note) => notSearchedForms.has(note)) || r.commonness !== void 0) && !validReadings.has(r.reading)) {
1685
- validReadings.add(r.reading);
1686
- if (!valid) valid = true;
1687
- }
1688
- if (word.kanjiForms) {
1689
- for (const kf of word.kanjiForms)
1690
- if ((kf.notes === void 0 || !kf.notes.some((note) => notSearchedForms.has(note)) || kf.commonness !== void 0) && !validKanjiForms.has(kf.form)) {
1691
- validKanjiForms.add(kf.form);
1692
- if (!valid) valid = true;
1693
- }
1694
- }
1695
- if (valid) validWords.push(word);
1696
- }
1652
+ for (const word of jmDict) {
1653
+ const rkf = getValidForms(
1654
+ word.readings,
1655
+ word.kanjiForms,
1656
+ word.isCommon
1657
+ );
1658
+ if (rkf.readings.length > 0)
1659
+ for (const r of rkf.readings) validReadings.add(r.reading);
1660
+ if (rkf.kanjiForms && rkf.kanjiForms.length > 0)
1661
+ for (const kf of rkf.kanjiForms) validKanjiForms.add(kf.form);
1662
+ validWords.push(word);
1663
+ }
1697
1664
  const validTitleEntries = /* @__PURE__ */ new Map();
1698
1665
  const entriesWithFormTitlesGlobal = /* @__PURE__ */ new Map();
1699
1666
  const entriesWithFormsGlobal = /* @__PURE__ */ new Map();
@@ -1705,34 +1672,27 @@ function getWordDefinitions(entryList, jmDict) {
1705
1672
  let valid = false;
1706
1673
  if (validKanjiForms && validKanjiForms.has(entry.word)) {
1707
1674
  valid = true;
1708
- if (isValidArray(entry.senses))
1709
- for (const sense of entry.senses) {
1710
- if (isValidArray(sense.form_of) && sense.form_of.some(
1711
- (form) => form.word && typeof form.word === "string" && validReadings.has(form.word)
1712
- ))
1713
- validFormOfEntries.add(entry.word);
1714
- else if (isStringArray(sense.glosses)) {
1715
- for (const gloss of sense.glosses) {
1716
- let reading = void 0;
1717
- if (gloss !== void 0) {
1718
- if (gloss.trim().includes("\u6F22\u5B57\u8868\u8A18") || gloss.trim().includes("\u53C2\u7167")) {
1719
- for (const r of validReadings)
1720
- if (gloss.trim().includes(r)) {
1721
- reading = r;
1722
- break;
1723
- }
1724
- }
1675
+ for (const sense of entry.senses) {
1676
+ if (sense.form_of && sense.form_of.some((form) => validReadings.has(form)))
1677
+ validFormOfEntries.add(entry.word);
1678
+ for (const gloss of sense.glosses) {
1679
+ let reading = void 0;
1680
+ if (gloss.trim().includes("\u6F22\u5B57\u8868\u8A18") || gloss.trim().includes("\u53C2\u7167")) {
1681
+ for (const r of validReadings)
1682
+ if (gloss.trim().includes(r)) {
1683
+ reading = r;
1684
+ break;
1725
1685
  }
1726
- if (reading) validGlossesEntries.add(entry.word);
1727
- }
1728
1686
  }
1687
+ if (reading) validGlossesEntries.add(entry.word);
1729
1688
  }
1730
- if (isValidArray(entry.forms)) {
1689
+ }
1690
+ if (entry.forms) {
1731
1691
  for (const form of entry.forms)
1732
- if (form.form && typeof form.form === "string" && validReadings.has(form.form))
1733
- validFormsEntries.add(entry.word);
1692
+ if (validReadings.has(form)) validFormsEntries.add(entry.word);
1734
1693
  }
1735
- } else if (validReadings.has(entry.word)) {
1694
+ }
1695
+ if (validReadings.has(entry.word)) {
1736
1696
  valid = true;
1737
1697
  const ftEntry = entriesWithFormTitlesGlobal.get(entry.word);
1738
1698
  if (ftEntry) ftEntry.push(entry);
@@ -1743,8 +1703,8 @@ function getWordDefinitions(entryList, jmDict) {
1743
1703
  if (tEntry) tEntry.push(entry);
1744
1704
  else validTitleEntries.set(entry.word, [entry]);
1745
1705
  }
1746
- if (isValidArray(entry.forms) && (validKanjiForms.has(entry.word) || validReadings.has(entry.word)) && entry.forms.some(
1747
- (form) => validKanjiForms.has(form.form) || validReadings.has(form.form)
1706
+ if (entry.forms && (validKanjiForms.has(entry.word) || validReadings.has(entry.word)) && entry.forms.some(
1707
+ (form) => validKanjiForms.has(form) || validReadings.has(form)
1748
1708
  )) {
1749
1709
  const wfEntry = entriesWithFormsGlobal.get(entry.word);
1750
1710
  if (wfEntry) wfEntry.push(entry);
@@ -1799,7 +1759,7 @@ function getWordDefinitions(entryList, jmDict) {
1799
1759
  "\u982D\u5B57\u8A9E",
1800
1760
  "\u63A5\u5C3E\u8A9E"
1801
1761
  ]) {
1802
- if (!posMap.has(pos)) posMap.set(pos, {});
1762
+ posMap.set(pos, {});
1803
1763
  for (const te of vte)
1804
1764
  if (te.pos_title === pos || te.pos_title === "\u548C\u8A9E\u306E\u6F22\u5B57\u8868\u8A18") {
1805
1765
  const posEntries = posMap.get(pos);
@@ -1838,79 +1798,74 @@ function getWordDefinitions(entryList, jmDict) {
1838
1798
  const wordEntriesPairs = [];
1839
1799
  for (const word of validWords) {
1840
1800
  const poses = /* @__PURE__ */ new Set();
1841
- for (const m of word.meanings) {
1842
- if (m.partOfSpeech)
1843
- for (const note of m.partOfSpeech) {
1844
- const noteEntry = noteMap.get(note);
1845
- if (noteEntry && noteEntry.length === 3) {
1846
- const notePos = noteEntry[2];
1847
- if (Array.isArray(notePos))
1848
- for (const pos of notePos) {
1849
- if (!poses.has(pos)) poses.add(pos);
1850
- }
1851
- else if (typeof notePos === "string" && !poses.has(notePos))
1852
- poses.add(notePos);
1853
- }
1801
+ for (const m of word.meanings)
1802
+ for (const note of m.partOfSpeech) {
1803
+ const noteEntry = noteMap.get(note);
1804
+ if (noteEntry && noteEntry.length === 3) {
1805
+ const notePos = noteEntry[2];
1806
+ if (Array.isArray(notePos))
1807
+ for (const pos of notePos) {
1808
+ if (!poses.has(pos)) poses.add(pos);
1809
+ }
1810
+ else if (typeof notePos === "string" && !poses.has(notePos))
1811
+ poses.add(notePos);
1854
1812
  }
1855
- }
1813
+ }
1814
+ const rkf = getValidForms(
1815
+ word.readings,
1816
+ word.kanjiForms,
1817
+ word.isCommon
1818
+ );
1856
1819
  const validWordReadings = new Set(
1857
- word.readings.filter(
1858
- (r) => r.notes === void 0 || !r.notes.some((note) => notSearchedForms.has(note)) || r.commonness !== void 0
1859
- ).map((r) => r.reading)
1820
+ rkf.readings.map((r) => r.reading)
1860
1821
  );
1861
- const validWordKanjiForms = word.kanjiForms ? new Set(
1862
- word.kanjiForms.filter(
1863
- (kf) => kf.notes === void 0 || !kf.notes.some((note) => notSearchedForms.has(note)) || kf.commonness !== void 0
1864
- ).map((kf) => kf.form)
1865
- ) : void 0;
1822
+ const validWordKanjiForms = rkf.kanjiForms ? new Set(rkf.kanjiForms.map((kf) => kf.form)) : void 0;
1866
1823
  const entriesWithTitles = [];
1867
1824
  const entriesWithFormTitles = [];
1868
1825
  const entriesWithForms = [];
1869
1826
  if (poses.size > 0)
1870
1827
  for (const pos of poses) {
1871
1828
  const posEntries = posMap.get(pos);
1872
- if (posEntries) {
1873
- if (validWordKanjiForms)
1874
- for (const kf of validWordKanjiForms) {
1875
- const te = (_a = posEntries.title) == null ? void 0 : _a.get(kf);
1876
- const fe = (_b = posEntries.form) == null ? void 0 : _b.get(kf);
1877
- if (te)
1878
- entriesWithTitles.push(
1879
- ...te.filter(
1880
- (ent) => validFormOfEntries.has(ent.word) || validGlossesEntries.has(ent.word) || validFormsEntries.has(ent.word)
1881
- )
1882
- );
1883
- if (fe)
1884
- entriesWithForms.push(
1885
- ...fe.filter(
1886
- (ent) => ent.forms && ent.forms.some(
1887
- (form) => validWordKanjiForms.has(form.form) || validWordReadings.has(form.form)
1888
- )
1889
- )
1890
- );
1891
- }
1892
- for (const r of validWordReadings) {
1893
- const te = (_c = posEntries.title) == null ? void 0 : _c.get(r);
1894
- const fe = (_d = posEntries.form) == null ? void 0 : _d.get(r);
1895
- const fte = (_e = posEntries.formTitle) == null ? void 0 : _e.get(r);
1829
+ if (validWordKanjiForms)
1830
+ for (const kf of validWordKanjiForms) {
1831
+ const te = (_a = posEntries.title) == null ? void 0 : _a.get(kf);
1832
+ const fe = (_b = posEntries.form) == null ? void 0 : _b.get(kf);
1896
1833
  if (te)
1897
1834
  entriesWithTitles.push(
1898
1835
  ...te.filter(
1899
- (ent) => ent.forms && validWordKanjiForms && ent.forms.some(
1900
- (form) => validWordKanjiForms.has(form.form)
1901
- ) || validWordKanjiForms === void 0
1836
+ (ent) => validFormOfEntries.has(ent.word) || validGlossesEntries.has(ent.word) || validFormsEntries.has(ent.word)
1902
1837
  )
1903
1838
  );
1904
1839
  if (fe)
1905
1840
  entriesWithForms.push(
1906
1841
  ...fe.filter(
1907
1842
  (ent) => ent.forms && ent.forms.some(
1908
- (form) => validWordKanjiForms && validWordKanjiForms.has(form.form) || validWordReadings.has(form.form)
1843
+ (form) => validWordKanjiForms.has(form) || validWordReadings.has(form)
1909
1844
  )
1910
1845
  )
1911
1846
  );
1912
- if (fte) entriesWithFormTitles.push(...fte);
1913
1847
  }
1848
+ for (const r of validWordReadings) {
1849
+ const te = (_c = posEntries.title) == null ? void 0 : _c.get(r);
1850
+ const fe = (_d = posEntries.form) == null ? void 0 : _d.get(r);
1851
+ const fte = (_e = posEntries.formTitle) == null ? void 0 : _e.get(r);
1852
+ if (te)
1853
+ entriesWithTitles.push(
1854
+ ...te.filter(
1855
+ (ent) => ent.forms && validWordKanjiForms && ent.forms.some(
1856
+ (form) => validWordKanjiForms.has(form)
1857
+ ) || validWordKanjiForms === void 0
1858
+ )
1859
+ );
1860
+ if (fe)
1861
+ entriesWithForms.push(
1862
+ ...fe.filter(
1863
+ (ent) => ent.forms && ent.forms.some(
1864
+ (form) => validWordKanjiForms && validWordKanjiForms.has(form) || validWordReadings.has(form)
1865
+ )
1866
+ )
1867
+ );
1868
+ if (fte) entriesWithFormTitles.push(...fte);
1914
1869
  }
1915
1870
  }
1916
1871
  if (entriesWithTitles.length === 0 && entriesWithFormTitles.length === 0 && entriesWithForms.length === 0) {
@@ -1928,7 +1883,7 @@ function getWordDefinitions(entryList, jmDict) {
1928
1883
  entriesWithForms.push(
1929
1884
  ...fe.filter(
1930
1885
  (ent) => ent.forms && ent.forms.some(
1931
- (form) => validWordKanjiForms.has(form.form) || validWordReadings.has(form.form)
1886
+ (form) => validWordKanjiForms.has(form) || validWordReadings.has(form)
1932
1887
  )
1933
1888
  )
1934
1889
  );
@@ -1941,7 +1896,7 @@ function getWordDefinitions(entryList, jmDict) {
1941
1896
  entriesWithTitles.push(
1942
1897
  ...te.filter(
1943
1898
  (ent) => ent.forms && validWordKanjiForms && ent.forms.some(
1944
- (form) => validWordKanjiForms.has(form.form)
1899
+ (form) => validWordKanjiForms.has(form)
1945
1900
  ) || validWordKanjiForms === void 0
1946
1901
  )
1947
1902
  );
@@ -1949,7 +1904,7 @@ function getWordDefinitions(entryList, jmDict) {
1949
1904
  entriesWithForms.push(
1950
1905
  ...fe.filter(
1951
1906
  (ent) => ent.forms && ent.forms.some(
1952
- (form) => validWordKanjiForms && validWordKanjiForms.has(form.form) || validWordReadings.has(form.form)
1907
+ (form) => validWordKanjiForms && validWordKanjiForms.has(form) || validWordReadings.has(form)
1953
1908
  )
1954
1909
  )
1955
1910
  );
@@ -1978,31 +1933,29 @@ function getWordDefinitions(entryList, jmDict) {
1978
1933
  const validFormOf = validFormOfEntries.has(ent.word);
1979
1934
  const validGlosses = validGlossesEntries.has(ent.word);
1980
1935
  const validForms = validFormsEntries.has(ent.word);
1936
+ const hasKanjiForms = ent.forms !== void 0 && pair.kanjiForms !== void 0 && ent.forms.some((form) => pair.kanjiForms.has(form));
1981
1937
  if (pair.kanjiForms && pair.kanjiForms.has(ent.word) && (validFormOf || validGlosses || validForms)) {
1982
1938
  kanjiFormEntries.push(ent);
1983
- if ((validFormOf || validGlosses) && isValidArray(ent.senses))
1939
+ if ((validFormOf || validGlosses) && ent.senses)
1984
1940
  for (const sense of ent.senses) {
1985
- if (validFormOf && isValidArray(sense.form_of)) {
1941
+ if (validFormOf && sense.form_of) {
1986
1942
  for (const form of sense.form_of)
1987
- if (form.word && typeof form.word === "string" && pair.readings.has(form.word)) {
1988
- const elem = titleFormMap.get(
1989
- form.word
1990
- );
1943
+ if (pair.readings.has(form)) {
1944
+ const elem = titleFormMap.get(form);
1991
1945
  if (!elem)
1992
- titleFormMap.set(form.word, /* @__PURE__ */ new Set([ent.word]));
1946
+ titleFormMap.set(form, /* @__PURE__ */ new Set([ent.word]));
1993
1947
  else elem.add(ent.word);
1994
1948
  }
1995
- } else if (validGlosses && isStringArray(sense.glosses)) {
1949
+ }
1950
+ if (validGlosses) {
1996
1951
  for (const gloss of sense.glosses) {
1997
1952
  let reading = void 0;
1998
- if (gloss !== void 0) {
1999
- if (gloss.trim().includes("\u6F22\u5B57\u8868\u8A18") || gloss.trim().includes("\u53C2\u7167")) {
2000
- for (const r of pair.readings)
2001
- if (gloss.trim().includes(r)) {
2002
- reading = r;
2003
- break;
2004
- }
2005
- }
1953
+ if (gloss.trim().includes("\u6F22\u5B57\u8868\u8A18") || gloss.trim().includes("\u53C2\u7167")) {
1954
+ for (const r of pair.readings)
1955
+ if (gloss.trim().includes(r)) {
1956
+ reading = r;
1957
+ break;
1958
+ }
2006
1959
  }
2007
1960
  if (reading) {
2008
1961
  const elem = refsMap.get(reading);
@@ -2012,19 +1965,19 @@ function getWordDefinitions(entryList, jmDict) {
2012
1965
  }
2013
1966
  }
2014
1967
  }
2015
- if (validForms && isValidArray(ent.forms)) {
1968
+ if (validForms && ent.forms) {
2016
1969
  for (const form of ent.forms)
2017
- if (form.form && typeof form.form === "string" && pair.readings.has(form.form))
2018
- readingForms.add(form.form);
1970
+ if (pair.readings.has(form)) readingForms.add(form);
2019
1971
  }
2020
- } else if (pair.readings.has(ent.word) && isValidArray(ent.forms) && pair.kanjiForms && ent.forms.some((form) => pair.kanjiForms.has(form.form)))
1972
+ }
1973
+ if (pair.readings.has(ent.word) && hasKanjiForms)
2021
1974
  readingWithFormsEntries.push(ent);
2022
- else if (pair.kanjiForms === void 0 && pair.readings.has(ent.word))
1975
+ if (pair.kanjiForms === void 0 && pair.readings.has(ent.word))
2023
1976
  readingEntries.push(ent);
2024
1977
  }
2025
1978
  for (const entry of pair.entriesWithForms) {
2026
1979
  const elem = titleFormMap.get(entry.word);
2027
- if (elem && entry.forms.some((form) => elem.has(form.form)))
1980
+ if (elem && entry.forms && entry.forms.some((form) => elem.has(form)))
2028
1981
  readingWithFormsEntries.push(entry);
2029
1982
  }
2030
1983
  for (const entry of pair.entriesWithFormTitles) {
@@ -2101,12 +2054,12 @@ async function getWordDefinitionsWithFurigana(entryList, jmDict) {
2101
2054
  function lookupWordNote(key, notes, tags) {
2102
2055
  const info = noteMap.get(key.toLowerCase());
2103
2056
  if (!info) {
2104
- if (notes) notes.push(key);
2057
+ notes.push(key);
2105
2058
  return { note: key };
2106
2059
  }
2107
2060
  const tag = `word::${info[0]}`;
2108
- if (tags && !tags.includes(tag)) tags.push(tag);
2109
- if (notes) notes.push(info[1]);
2061
+ if (!tags.includes(tag)) tags.push(tag);
2062
+ notes.push(info[1]);
2110
2063
  return { note: info[1], tag };
2111
2064
  }
2112
2065
  var wordAddNoteArray = (arr, cb) => {
@@ -2116,9 +2069,14 @@ var wordAddNoteArray = (arr, cb) => {
2116
2069
  function getWord(word, dict, kanjiDic, examples, definitions, noteTypeName, deckPath) {
2117
2070
  var _a;
2118
2071
  let dictWord = void 0;
2119
- if (typeof word === "string" && dict)
2120
- dictWord = dict.find((entry) => entry.id === word);
2121
- else if (typeof word === "object") dictWord = word;
2072
+ if (typeof word === "string" && dict) {
2073
+ if (Array.isArray(dict))
2074
+ dictWord = dict.find(
2075
+ (entry) => entry.id === word
2076
+ );
2077
+ if (dict instanceof Map) dictWord = dict.get(word);
2078
+ }
2079
+ if (typeof word === "object") dictWord = word;
2122
2080
  if (dictWord) {
2123
2081
  const word2 = {
2124
2082
  id: dictWord.id,
@@ -2141,7 +2099,7 @@ function getWord(word, dict, kanjiDic, examples, definitions, noteTypeName, deck
2141
2099
  notes: dictKanjiForm.notes.map((note) => {
2142
2100
  const noteAndTag = lookupWordNote(
2143
2101
  note,
2144
- void 0,
2102
+ [],
2145
2103
  word2.tags
2146
2104
  );
2147
2105
  return capitalizeString(noteAndTag.note);
@@ -2160,7 +2118,7 @@ function getWord(word, dict, kanjiDic, examples, definitions, noteTypeName, deck
2160
2118
  ...dictReading.notes ? dictReading.notes.map((note) => {
2161
2119
  const noteAndTag = lookupWordNote(
2162
2120
  note,
2163
- void 0,
2121
+ [],
2164
2122
  word2.tags
2165
2123
  );
2166
2124
  return capitalizeString(noteAndTag.note);
@@ -2170,72 +2128,66 @@ function getWord(word, dict, kanjiDic, examples, definitions, noteTypeName, deck
2170
2128
  ...dictReading.commonness && dictReading.commonness.length > 0 ? { common: true } : {}
2171
2129
  }));
2172
2130
  word2.translations = [];
2173
- for (const dictMeaning of dictWord.meanings)
2174
- if (dictMeaning.translations) {
2175
- const translationTypes = [];
2176
- const translations = dictMeaning.translations.map(
2177
- (translation) => {
2178
- if (typeof translation === "string") return translation;
2179
- else {
2180
- if (translation.type === "lit") {
2181
- translationTypes.push("Literal meaning");
2182
- word2.tags.push("word::literal_meaning");
2183
- } else if (translation.type === "expl") {
2184
- translationTypes.push("Explanation");
2185
- word2.tags.push("word::explanation");
2186
- } else if (translation.type === "tm") {
2187
- translationTypes.push("Trademark");
2188
- word2.tags.push("word::trademark");
2189
- }
2190
- return translation.translation;
2191
- }
2131
+ for (const dictMeaning of dictWord.meanings) {
2132
+ const translationTypes = [];
2133
+ const translations = dictMeaning.translations.map(
2134
+ (translation) => {
2135
+ if (typeof translation === "string") return translation;
2136
+ else {
2137
+ const translationNoteAndTag = noteMap.get(
2138
+ translation.type
2139
+ );
2140
+ translationTypes.push(translationNoteAndTag[1]);
2141
+ word2.tags.push(`word::${translationNoteAndTag[0]}`);
2142
+ return translation.translation;
2192
2143
  }
2193
- );
2194
- const notes = [];
2195
- wordAddNoteArray(
2196
- dictMeaning.kanjiFormRestrictions,
2197
- (restriction) => notes.push(`Meaning restricted to ${restriction}`)
2198
- );
2199
- wordAddNoteArray(
2200
- dictMeaning.readingRestrictions,
2201
- (restriction) => notes.push(`Meaning restricted to ${restriction}`)
2202
- );
2203
- for (const t of translationTypes) notes.push(t);
2204
- wordAddNoteArray(
2205
- dictMeaning.partOfSpeech,
2206
- (pos) => lookupWordNote(pos, notes, word2.tags)
2207
- );
2208
- wordAddNoteArray(
2209
- dictMeaning.fields,
2210
- (field) => lookupWordNote(field, notes, word2.tags)
2211
- );
2212
- wordAddNoteArray(
2213
- dictMeaning.dialects,
2214
- (dialect) => lookupWordNote(dialect, notes, word2.tags)
2215
- );
2216
- wordAddNoteArray(
2217
- dictMeaning.antonyms,
2218
- (antonym) => notes.push(`Antonym: ${antonym}`)
2219
- );
2220
- wordAddNoteArray(
2221
- dictMeaning.references,
2222
- (reference) => notes.push(`Related: ${reference}`)
2223
- );
2224
- wordAddNoteArray(
2225
- dictMeaning.info,
2226
- (info) => lookupWordNote(info, notes, word2.tags)
2227
- );
2228
- wordAddNoteArray(
2229
- dictMeaning.misc,
2230
- (misc) => lookupWordNote(misc, notes, word2.tags)
2231
- );
2232
- for (let i = 0; i < notes.length; i++)
2233
- notes[i] = capitalizeString(notes[i]);
2234
- word2.translations.push({
2235
- translation: translations.join("; "),
2236
- notes
2237
- });
2238
- }
2144
+ }
2145
+ );
2146
+ const notes = [];
2147
+ wordAddNoteArray(
2148
+ dictMeaning.kanjiFormRestrictions,
2149
+ (restriction) => notes.push(`Meaning restricted to ${restriction}`)
2150
+ );
2151
+ wordAddNoteArray(
2152
+ dictMeaning.readingRestrictions,
2153
+ (restriction) => notes.push(`Meaning restricted to ${restriction}`)
2154
+ );
2155
+ for (const t of translationTypes) notes.push(t);
2156
+ wordAddNoteArray(
2157
+ dictMeaning.partOfSpeech,
2158
+ (pos) => lookupWordNote(pos, notes, word2.tags)
2159
+ );
2160
+ wordAddNoteArray(
2161
+ dictMeaning.fields,
2162
+ (field) => lookupWordNote(field, notes, word2.tags)
2163
+ );
2164
+ wordAddNoteArray(
2165
+ dictMeaning.dialects,
2166
+ (dialect) => lookupWordNote(dialect, notes, word2.tags)
2167
+ );
2168
+ wordAddNoteArray(
2169
+ dictMeaning.antonyms,
2170
+ (antonym) => notes.push(`Antonym: ${antonym}`)
2171
+ );
2172
+ wordAddNoteArray(
2173
+ dictMeaning.references,
2174
+ (reference) => notes.push(`Related: ${reference}`)
2175
+ );
2176
+ wordAddNoteArray(
2177
+ dictMeaning.info,
2178
+ (info) => lookupWordNote(info, notes, word2.tags)
2179
+ );
2180
+ wordAddNoteArray(
2181
+ dictMeaning.misc,
2182
+ (misc) => lookupWordNote(misc, notes, word2.tags)
2183
+ );
2184
+ for (let i = 0; i < notes.length; i++)
2185
+ notes[i] = capitalizeString(notes[i]);
2186
+ word2.translations.push({
2187
+ translation: translations.join("; "),
2188
+ notes
2189
+ });
2190
+ }
2239
2191
  if (dictWord.usuallyInKana === true) {
2240
2192
  word2.usuallyInKana = true;
2241
2193
  word2.tags.push("word::usually_in_kana_for_all_senses");
@@ -2258,127 +2210,114 @@ function getWord(word, dict, kanjiDic, examples, definitions, noteTypeName, deck
2258
2210
  }
2259
2211
  if (kanji.length > 0) word2.kanji = kanji;
2260
2212
  }
2261
- if (dictWord.hasPhrases === true && examples) {
2262
- const exampleList = Array.isArray(
2263
- examples
2264
- ) ? examples : examples.get(word2.id);
2265
- if (exampleList) {
2266
- const readings = new Set(
2267
- word2.readings.filter(
2268
- (reading) => (reading.notes === void 0 || !reading.notes.some(
2269
- (note) => notSearchedForms.has(note)
2270
- )) && (word2.common === void 0 || reading.common === true)
2271
- ).map((reading) => reading.reading)
2272
- );
2273
- const existValidKf = word2.kanjiForms && word2.kanjiForms.length > 0 ? word2.kanjiForms.some(
2274
- (kf) => (kf.notes === void 0 || !kf.notes.some(
2275
- (note) => notSearchedForms.has(note)
2276
- )) && (word2.common === void 0 || kf.common === true)
2277
- ) : void 0;
2278
- const kanjiForms = word2.kanjiForms && word2.kanjiForms.length > 0 ? new Set(
2279
- word2.kanjiForms.filter((kanjiForm) => {
2280
- if (existValidKf === true)
2281
- return (kanjiForm.notes === void 0 || !kanjiForm.notes.some(
2282
- (note) => notSearchedForms.has(note)
2283
- )) && (word2.common === void 0 || kanjiForm.common === true);
2284
- else return true;
2285
- }).map((kanjiForm) => kanjiForm.kanjiForm)
2286
- ) : void 0;
2287
- let kanjiFormExamples = [];
2288
- const readingMatchingKanjiFormExamples = [];
2289
- const readingExamples = [];
2290
- const readingMatchingKanjiForms = /* @__PURE__ */ new Set();
2291
- for (const example of exampleList)
2292
- for (let i = 0; i < example.parts.length; i++) {
2293
- const part = example.parts[i];
2294
- const readingAsReadingMatch = part.reading !== void 0 && readings.has(part.reading);
2295
- const readingAsInflectedFormMatch = part.inflectedForm !== void 0 && readings.has(part.inflectedForm);
2296
- const referenceIDMatch = part.referenceID !== void 0 && word2.id !== void 0 && part.referenceID === word2.id;
2297
- if (kanjiForms && kanjiForms.has(part.baseForm) || referenceIDMatch) {
2298
- if (readingAsReadingMatch || readingAsInflectedFormMatch) {
2299
- readingMatchingKanjiFormExamples.push({
2300
- ex: example,
2301
- partIndex: i
2302
- });
2303
- readingMatchingKanjiForms.add(part.baseForm);
2304
- } else
2305
- kanjiFormExamples.push({
2306
- ex: example,
2307
- partIndex: i,
2308
- form: part.baseForm
2309
- });
2310
- break;
2311
- }
2312
- const readingAsBaseFormMatch = readings.has(part.baseForm);
2313
- if ((readingAsBaseFormMatch || referenceIDMatch) && kanjiForms === void 0) {
2314
- readingExamples.push({ ex: example, partIndex: i });
2315
- break;
2316
- }
2213
+ if (dictWord.hasPhrases !== void 0 && examples) {
2214
+ const exampleList = Array.isArray(examples) ? examples : examples.get(
2215
+ dictWord.id
2216
+ ) ?? [];
2217
+ const rkf = getValidForms(
2218
+ dictWord.readings,
2219
+ dictWord.kanjiForms,
2220
+ dictWord.isCommon
2221
+ );
2222
+ const readings = new Set(
2223
+ rkf.readings.map((r) => r.reading)
2224
+ );
2225
+ const kanjiForms = rkf.kanjiForms ? new Set(rkf.kanjiForms.map((kf) => kf.form)) : void 0;
2226
+ let kanjiFormExamples = [];
2227
+ const readingMatchingKanjiFormExamples = [];
2228
+ const readingExamples = [];
2229
+ const readingMatchingKanjiForms = /* @__PURE__ */ new Set();
2230
+ for (const example of exampleList)
2231
+ for (let i = 0; i < example.parts.length; i++) {
2232
+ const part = example.parts[i];
2233
+ const readingAsReadingMatch = part.reading !== void 0 && readings.has(part.reading);
2234
+ const readingAsInflectedFormMatch = part.inflectedForm !== void 0 && readings.has(part.inflectedForm);
2235
+ const referenceIDMatch = part.referenceID === dictWord.id;
2236
+ if (kanjiForms && kanjiForms.has(part.baseForm) || referenceIDMatch) {
2237
+ if (readingAsReadingMatch || readingAsInflectedFormMatch) {
2238
+ readingMatchingKanjiFormExamples.push({
2239
+ ex: example,
2240
+ partIndex: i
2241
+ });
2242
+ readingMatchingKanjiForms.add(part.baseForm);
2243
+ } else
2244
+ kanjiFormExamples.push({
2245
+ ex: example,
2246
+ partIndex: i,
2247
+ form: part.baseForm
2248
+ });
2249
+ break;
2317
2250
  }
2318
- if (readingMatchingKanjiForms.size > 0)
2319
- kanjiFormExamples = kanjiFormExamples.filter(
2320
- (ex) => ex.form && readingMatchingKanjiForms.has(ex.form)
2321
- );
2322
- const includeKanjiFormExamples = word2.kanjiForms !== void 0;
2323
- let wordExamples = [
2324
- ...includeKanjiFormExamples ? [...readingMatchingKanjiFormExamples, ...kanjiFormExamples] : [],
2325
- ...!includeKanjiFormExamples ? readingExamples : []
2326
- ];
2327
- readingMatchingKanjiForms.clear();
2328
- const glossSpecificExamples = [];
2329
- const seenPhrases = /* @__PURE__ */ new Set();
2330
- for (let i = 0; i < word2.translations.length; i++) {
2331
- outer: for (const example of wordExamples) {
2332
- if (seenPhrases.has(example.ex.phrase)) continue;
2333
- for (let j = 0; j < example.ex.parts.length; j++) {
2334
- const part = example.ex.parts[j];
2335
- if (j === example.partIndex && part.glossNumber === i + 1) {
2336
- example.ex.glossNumber = {
2337
- wordId: word2.id,
2338
- glossNumber: i + 1
2339
- };
2340
- glossSpecificExamples.push(example);
2341
- seenPhrases.add(example.ex.phrase);
2342
- break outer;
2343
- }
2344
- }
2251
+ const readingAsBaseFormMatch = readings.has(part.baseForm);
2252
+ if ((readingAsBaseFormMatch || referenceIDMatch) && kanjiForms === void 0) {
2253
+ readingExamples.push({ ex: example, partIndex: i });
2254
+ break;
2345
2255
  }
2346
- if (glossSpecificExamples.length === 5) break;
2347
2256
  }
2348
- if (glossSpecificExamples.length === 5)
2349
- wordExamples = [...glossSpecificExamples];
2350
- else if (glossSpecificExamples.length > 0)
2351
- wordExamples = [
2352
- ...glossSpecificExamples,
2353
- ...wordExamples.filter(
2354
- (ex) => !seenPhrases.has(ex.ex.phrase)
2355
- ).slice(0, 5 - glossSpecificExamples.length)
2356
- ];
2357
- if (wordExamples.length > 0) {
2358
- word2.phrases = (wordExamples.length > 5 ? wordExamples.slice(0, 5) : wordExamples).map((ex) => ({
2359
- phrase: ex.ex.furigana ?? ex.ex.phrase,
2360
- translation: ex.ex.translation,
2361
- originalPhrase: ex.ex.phrase,
2362
- ...ex.ex.glossNumber ? { glossNumber: ex.ex.glossNumber } : {}
2363
- }));
2364
- word2.tags.push("word::has_phrases");
2365
- if (glossSpecificExamples.length > 0)
2366
- word2.tags.push("word::has_meaning-specific_phrases");
2257
+ if (readingMatchingKanjiForms.size > 0)
2258
+ kanjiFormExamples = kanjiFormExamples.filter(
2259
+ (ex) => ex.form && readingMatchingKanjiForms.has(ex.form)
2260
+ );
2261
+ const includeKanjiFormExamples = word2.kanjiForms !== void 0;
2262
+ let wordExamples = [
2263
+ ...includeKanjiFormExamples ? [...readingMatchingKanjiFormExamples, ...kanjiFormExamples] : readingExamples
2264
+ ];
2265
+ readingMatchingKanjiForms.clear();
2266
+ const glossSpecificExamples = [];
2267
+ const seenPhrases = /* @__PURE__ */ new Set();
2268
+ for (let i = 0; i < word2.translations.length; i++) {
2269
+ outer: for (const example of wordExamples) {
2270
+ if (seenPhrases.has(example.ex.phrase)) continue;
2271
+ for (let j = 0; j < example.ex.parts.length; j++) {
2272
+ const part = example.ex.parts[j];
2273
+ if (j === example.partIndex && part.glossNumber === i + 1) {
2274
+ example.ex.glossNumber = {
2275
+ wordId: word2.id,
2276
+ glossNumber: i + 1
2277
+ };
2278
+ glossSpecificExamples.push(example);
2279
+ seenPhrases.add(example.ex.phrase);
2280
+ break outer;
2281
+ }
2282
+ }
2367
2283
  }
2284
+ if (glossSpecificExamples.length === 5) break;
2285
+ }
2286
+ if (glossSpecificExamples.length === 5)
2287
+ wordExamples = [...glossSpecificExamples];
2288
+ else if (glossSpecificExamples.length > 0)
2289
+ wordExamples = [
2290
+ ...glossSpecificExamples,
2291
+ ...wordExamples.filter(
2292
+ (ex) => !seenPhrases.has(ex.ex.phrase)
2293
+ ).slice(0, 5 - glossSpecificExamples.length)
2294
+ ];
2295
+ if (wordExamples.length > 0) {
2296
+ word2.phrases = (wordExamples.length > 5 ? wordExamples.slice(0, 5) : wordExamples).map((ex) => ({
2297
+ phrase: ex.ex.furigana ?? ex.ex.phrase,
2298
+ translation: ex.ex.translation,
2299
+ originalPhrase: ex.ex.phrase,
2300
+ ...ex.ex.glossNumber ? { glossNumber: ex.ex.glossNumber } : {}
2301
+ }));
2302
+ word2.tags.push("word::has_phrases");
2303
+ if (glossSpecificExamples.length > 0)
2304
+ word2.tags.push("word::has_meaning-specific_phrases");
2368
2305
  }
2369
2306
  }
2370
2307
  if (definitions) {
2371
- const defs = Array.isArray(definitions) ? (_a = definitions.find((wdp) => wdp.wordID === word2.id)) == null ? void 0 : _a.definitions : definitions.get(word2.id);
2308
+ const defs = Array.isArray(definitions) ? (_a = definitions.find((wdp) => wdp.wordID === word2.id)) == null ? void 0 : _a.definitions : definitions.get(
2309
+ word2.id
2310
+ );
2372
2311
  if (defs) word2.definitions = [...defs];
2373
2312
  }
2374
2313
  return word2;
2375
2314
  } else return void 0;
2376
2315
  }
2377
2316
  function getKanji(kanji, dict, jmDict, svgList, noteTypeName, deckPath) {
2378
- var _a, _b, _c, _d, _e, _f, _g, _h;
2317
+ var _a, _b, _c, _d, _e, _f, _g;
2379
2318
  let dictKanji = void 0;
2380
2319
  if (typeof kanji === "string" && dict)
2381
- dictKanji = dict.find((entry) => entry.kanji === kanji);
2320
+ dictKanji = Array.isArray(dict) ? dict.find((entry) => entry.kanji === kanji) : dict.get(kanji);
2382
2321
  else if (typeof kanji === "object") dictKanji = kanji;
2383
2322
  if (dictKanji) {
2384
2323
  const kanji2 = {
@@ -2399,23 +2338,20 @@ function getKanji(kanji, dict, jmDict, svgList, noteTypeName, deckPath) {
2399
2338
  const kunyomi = [];
2400
2339
  for (const rm of dictKanji.readingMeaning) {
2401
2340
  if (rm.nanori && rm.nanori.length > 0) nanori.push(...rm.nanori);
2402
- if (rm.groups)
2403
- for (const group of rm.groups) {
2404
- if (group.readings) {
2405
- onyomi.push(
2406
- ...group.readings.filter(
2407
- (reading) => reading.type === "ja_on"
2408
- ).map((reading) => reading.reading)
2409
- );
2410
- kunyomi.push(
2411
- ...group.readings.filter(
2412
- (reading) => reading.type === "ja_kun"
2413
- ).map((reading) => reading.reading)
2414
- );
2415
- }
2416
- if (group.meanings && group.meanings.length > 0)
2417
- meanings.push(...group.meanings);
2341
+ for (const group of rm.groups) {
2342
+ if (group.readings) {
2343
+ onyomi.push(
2344
+ ...group.readings.filter((reading) => reading.type === "ja_on").map((reading) => reading.reading)
2345
+ );
2346
+ kunyomi.push(
2347
+ ...group.readings.filter(
2348
+ (reading) => reading.type === "ja_kun"
2349
+ ).map((reading) => reading.reading)
2350
+ );
2418
2351
  }
2352
+ if (group.meanings && group.meanings.length > 0)
2353
+ meanings.push(...group.meanings);
2354
+ }
2419
2355
  }
2420
2356
  if (meanings.length > 0) kanji2.meanings = meanings;
2421
2357
  if (nanori.length > 0) kanji2.nanori = nanori;
@@ -2430,71 +2366,62 @@ function getKanji(kanji, dict, jmDict, svgList, noteTypeName, deckPath) {
2430
2366
  (word) => word.kanjiForms && word.kanjiForms[0].form.includes(kanji2.kanji)
2431
2367
  );
2432
2368
  if (firstKfWords && firstKfWords.length > 0) kanjiWords = firstKfWords;
2433
- else if (kanjiWords) kanjiWords = kanjiWords;
2434
2369
  if (kanjiWords) {
2435
2370
  const validWords = [];
2436
2371
  for (const word of kanjiWords) {
2437
2372
  const kanjiForm = (_a = firstKfWords && firstKfWords.length > 0 ? word.kanjiForms[0] : word.kanjiForms.find(
2438
2373
  (kf) => kf.form.includes(kanji2.kanji)
2439
2374
  )) == null ? void 0 : _a.form;
2440
- if (!kanjiForm) continue;
2441
- const reading = (_b = firstKfWords && firstKfWords.length > 0 ? word.readings[0] : word.readings.find(
2442
- (reading2) => reading2.kanjiFormRestrictions && reading2.kanjiFormRestrictions.includes(kanjiForm)
2443
- )) == null ? void 0 : _b.reading;
2444
- if (!reading) continue;
2445
- const meaning = firstKfWords && firstKfWords.length > 0 ? (_c = word.meanings[0]) == null ? void 0 : _c.translations[0] : (_d = word.meanings.find(
2446
- (m) => m.translations && m.kanjiFormRestrictions && m.kanjiFormRestrictions.includes(kanjiForm)
2447
- )) == null ? void 0 : _d.translations[0];
2448
- if (!meaning) continue;
2449
- validWords.push({
2450
- kanjiForms: [{ kanjiForm }],
2451
- readings: [{ reading }],
2452
- translations: [
2453
- {
2454
- translation: typeof meaning === "string" ? meaning : meaning.translation
2455
- }
2456
- ]
2457
- });
2375
+ if (kanjiForm) {
2376
+ const reading = (_b = firstKfWords && firstKfWords.length > 0 ? word.readings[0] : word.readings.find(
2377
+ (reading2) => reading2.kanjiFormRestrictions && reading2.kanjiFormRestrictions.includes(kanjiForm)
2378
+ )) == null ? void 0 : _b.reading;
2379
+ if (!reading) continue;
2380
+ const translation = (_c = firstKfWords && firstKfWords.length > 0 ? word.meanings[0] : word.meanings.find(
2381
+ (m) => m.translations && m.kanjiFormRestrictions && m.kanjiFormRestrictions.includes(kanjiForm)
2382
+ )) == null ? void 0 : _c.translations.map(
2383
+ (t) => typeof t === "string" ? t : t.translation
2384
+ )[0];
2385
+ if (!translation) continue;
2386
+ validWords.push({
2387
+ kanjiForms: [{ kanjiForm }],
2388
+ readings: [{ reading }],
2389
+ translations: [
2390
+ {
2391
+ translation
2392
+ }
2393
+ ]
2394
+ });
2395
+ }
2458
2396
  if (validWords.length === 3) break;
2459
2397
  }
2460
2398
  if (validWords.length > 0) kanji2.words = validWords;
2461
2399
  }
2462
2400
  }
2463
2401
  if (svgList) {
2464
- let codePoint = kanji2.kanji.codePointAt(0);
2465
- if (codePoint !== void 0) {
2466
- codePoint = codePoint.toString(16);
2467
- const fileNames = [
2468
- `0${codePoint}.svg`,
2469
- `${codePoint}.svg`
2470
- ];
2471
- const svg = svgList.find(
2472
- (svgFile) => fileNames.includes(svgFile.toLowerCase())
2473
- );
2474
- if (svg) kanji2.svg = svg;
2475
- }
2402
+ const codePoint = kanji2.kanji.codePointAt(0).toString(16).toLowerCase();
2403
+ const svg = Array.isArray(svgList) ? svgList.find(
2404
+ (svgFile) => [`${codePoint}.svg`, `0${codePoint}.svg`].includes(
2405
+ svgFile.toLowerCase()
2406
+ )
2407
+ ) : svgList.get(kanji2.kanji);
2408
+ if (svg) kanji2.svg = svg;
2476
2409
  }
2477
2410
  if (kanji2.tags && dictKanji.isKokuji === true) {
2478
2411
  kanji2.kokuji = true;
2479
2412
  kanji2.tags.push("kanji::kokuji");
2480
- if (kanji2.meanings)
2481
- kanji2.meanings.splice(
2482
- kanji2.meanings.findIndex((meaning) => meaning === "(kokuji)"),
2483
- 1
2484
- );
2485
2413
  }
2486
- if (kanji2.tags)
2487
- kanji2.tags.push(
2488
- `kanji::strokes::${kanji2.strokes}`,
2489
- ...kanji2.frequency ? [`kanji::frequency::${kanji2.frequency}`] : [],
2490
- ...kanji2.grade ? [`kanji::grade::${kanji2.grade}`] : [],
2491
- ...kanji2.jlpt ? [`kanji::pre-2010_jlpt::${kanji2.jlpt.toLowerCase()}`] : [],
2492
- `kanji::onyomi::${((_e = kanji2.onyomi) == null ? void 0 : _e.length) ?? 0}`,
2493
- `kanji::kunyomi::${((_f = kanji2.kunyomi) == null ? void 0 : _f.length) ?? 0}`,
2494
- `kanji::nanori::${((_g = kanji2.nanori) == null ? void 0 : _g.length) ?? 0}`,
2495
- `kanji::words::${((_h = kanji2.words) == null ? void 0 : _h.length) ?? 0}`,
2496
- ...kanji2.svg ? ["kanji::has_svg"] : []
2497
- );
2414
+ kanji2.tags.push(
2415
+ `kanji::strokes::${kanji2.strokes}`,
2416
+ ...kanji2.frequency ? [`kanji::frequency::${kanji2.frequency}`] : [],
2417
+ ...kanji2.grade ? [`kanji::grade::${kanji2.grade}`] : [],
2418
+ ...kanji2.jlpt ? [`kanji::pre-2010_jlpt::${kanji2.jlpt.toLowerCase()}`] : [],
2419
+ `kanji::onyomi::${((_d = kanji2.onyomi) == null ? void 0 : _d.length) ?? 0}`,
2420
+ `kanji::kunyomi::${((_e = kanji2.kunyomi) == null ? void 0 : _e.length) ?? 0}`,
2421
+ `kanji::nanori::${((_f = kanji2.nanori) == null ? void 0 : _f.length) ?? 0}`,
2422
+ `kanji::words::${((_g = kanji2.words) == null ? void 0 : _g.length) ?? 0}`,
2423
+ ...kanji2.svg ? ["kanji::has_svg"] : []
2424
+ );
2498
2425
  return kanji2;
2499
2426
  } else return void 0;
2500
2427
  }
@@ -2521,22 +2448,20 @@ function getKanjiExtended(info, kanji, dict, useWords, jmDict, svgList, noteType
2521
2448
  kanjiObj.words = info.words;
2522
2449
  usedInfo = true;
2523
2450
  }
2524
- if (kanjiObj.tags) {
2525
- if (kanjiObj.components)
2526
- kanjiObj.tags.push(`kanji::components::${kanjiObj.components.length}`);
2527
- if (kanjiObj.mnemonic && kanjiObj.mnemonic.length > 0)
2528
- kanjiObj.tags.push("kanji::has_mnemonic");
2529
- if (useWords === true && kanjiObj.words && info.words)
2530
- kanjiObj.tags.forEach((tag, index) => {
2531
- if (tag.startsWith("kanji::words::") && kanjiObj.words && kanjiObj.tags) {
2532
- kanjiObj.tags.splice(
2533
- index,
2534
- 1,
2535
- `kanji::words::${kanjiObj.words.length}`
2536
- );
2537
- }
2538
- });
2539
- }
2451
+ if (kanjiObj.components)
2452
+ kanjiObj.tags.push(`kanji::components::${kanjiObj.components.length}`);
2453
+ if (kanjiObj.mnemonic && kanjiObj.mnemonic.length > 0)
2454
+ kanjiObj.tags.push("kanji::has_mnemonic");
2455
+ if (useWords === true && kanjiObj.words && info.words)
2456
+ kanjiObj.tags.forEach((tag, index) => {
2457
+ if (tag.startsWith("kanji::words::") && kanjiObj.words) {
2458
+ kanjiObj.tags.splice(
2459
+ index,
2460
+ 1,
2461
+ `kanji::words::${kanjiObj.words.length}`
2462
+ );
2463
+ }
2464
+ });
2540
2465
  if (sourceURL && info.externalInfo === true && usedInfo)
2541
2466
  kanjiObj.source = sourceURL;
2542
2467
  return kanjiObj;
@@ -2793,15 +2718,15 @@ function generateAnkiNotesFile(list, defaultNoteInfo) {
2793
2718
  if (typeof defaultNoteInfo.deckPath === "string" && result.deckPath === void 0)
2794
2719
  result.deckPath = defaultNoteInfo.deckPath;
2795
2720
  if (!hasHeader.guid && result.noteID) {
2796
- headers.push(`${noteHeaderKeys.guid}:${++headerCount}`);
2721
+ headers.push(`${noteHeaderKeys.guid}${++headerCount}`);
2797
2722
  hasHeader.guid = true;
2798
2723
  }
2799
2724
  if (!hasHeader.noteType && result.noteTypeName) {
2800
- headers.push(`${noteHeaderKeys.notetype}:${++headerCount}`);
2725
+ headers.push(`${noteHeaderKeys.notetype}${++headerCount}`);
2801
2726
  hasHeader.noteType = true;
2802
2727
  }
2803
2728
  if (!hasHeader.deckPath && result.deckPath) {
2804
- headers.push(`${noteHeaderKeys.deck}:${++headerCount}`);
2729
+ headers.push(`${noteHeaderKeys.deck}${++headerCount}`);
2805
2730
  hasHeader.deckPath = true;
2806
2731
  }
2807
2732
  const note = generateAnkiNote(result);
@@ -2830,15 +2755,16 @@ export {
2830
2755
  generateAnkiNotesFile,
2831
2756
  getKanji,
2832
2757
  getKanjiExtended,
2758
+ getValidForms,
2833
2759
  getWord,
2834
2760
  getWordDefinitions,
2835
2761
  getWordDefinitionsWithFurigana,
2836
2762
  isGrammar,
2837
2763
  isKana,
2838
2764
  isKanji,
2765
+ isObjectArray,
2839
2766
  isRadical,
2840
2767
  isStringArray,
2841
- isValidArray,
2842
2768
  isValidArrayWithFirstElement,
2843
2769
  isWord,
2844
2770
  notSearchedForms,