henkan 0.3.3 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/dist/index.cjs.js +146 -144
  2. package/dist/index.cjs.js.map +3 -3
  3. package/dist/index.mjs +144 -140
  4. package/dist/index.mjs.map +2 -2
  5. package/dist/types/types.d.ts +16 -12
  6. package/dist/types/types.d.ts.map +1 -1
  7. package/dist/types/utils.d.ts +8 -8
  8. package/dist/types/utils.d.ts.map +1 -1
  9. package/docs/api/functions/capitalizeString.md +1 -1
  10. package/docs/api/functions/convertJMdict.md +3 -3
  11. package/docs/api/functions/convertKanjiDic.md +1 -1
  12. package/docs/api/functions/convertKradFile.md +4 -4
  13. package/docs/api/functions/convertRadkFile.md +4 -4
  14. package/docs/api/functions/convertTanakaCorpus.md +1 -1
  15. package/docs/api/functions/generateAnkiNote.md +1 -1
  16. package/docs/api/functions/generateAnkiNotesFile.md +1 -1
  17. package/docs/api/functions/getKanji.md +1 -1
  18. package/docs/api/functions/getKanjiExtended.md +1 -1
  19. package/docs/api/functions/getWord.md +1 -1
  20. package/docs/api/functions/isStringArray.md +1 -1
  21. package/docs/api/functions/isValidArray.md +1 -1
  22. package/docs/api/functions/isValidArrayWithFirstElement.md +1 -1
  23. package/docs/api/functions/makeSSML.md +1 -1
  24. package/docs/api/functions/shuffleArray.md +1 -1
  25. package/docs/api/functions/synthesizeSpeech.md +1 -1
  26. package/docs/api/interfaces/DictKanji.md +5 -5
  27. package/docs/api/interfaces/DictKanjiForm.md +4 -4
  28. package/docs/api/interfaces/DictKanjiMisc.md +5 -5
  29. package/docs/api/interfaces/DictKanjiReading.md +3 -3
  30. package/docs/api/interfaces/DictKanjiReadingMeaning.md +3 -3
  31. package/docs/api/interfaces/DictKanjiReadingMeaningGroup.md +3 -3
  32. package/docs/api/interfaces/DictKanjiWithRadicals.md +3 -3
  33. package/docs/api/interfaces/DictMeaning.md +11 -11
  34. package/docs/api/interfaces/DictRadical.md +4 -4
  35. package/docs/api/interfaces/DictReading.md +5 -5
  36. package/docs/api/interfaces/DictWord.md +29 -19
  37. package/docs/api/interfaces/ExamplePart.md +7 -7
  38. package/docs/api/interfaces/Grammar.md +15 -15
  39. package/docs/api/interfaces/GrammarMeaning.md +3 -3
  40. package/docs/api/interfaces/Kana.md +11 -11
  41. package/docs/api/interfaces/Kanji.md +22 -22
  42. package/docs/api/interfaces/KanjiComponent.md +3 -3
  43. package/docs/api/interfaces/KanjiForm.md +4 -4
  44. package/docs/api/interfaces/NoteAndTag.md +3 -3
  45. package/docs/api/interfaces/Phrase.md +4 -4
  46. package/docs/api/interfaces/Radical.md +16 -16
  47. package/docs/api/interfaces/Reading.md +5 -5
  48. package/docs/api/interfaces/ResultEntry.md +7 -7
  49. package/docs/api/interfaces/TanakaExample.md +17 -7
  50. package/docs/api/interfaces/Translation.md +3 -3
  51. package/docs/api/interfaces/UsefulRegExps.md +9 -9
  52. package/docs/api/interfaces/Word.md +18 -18
  53. package/docs/api/type-aliases/Dict.md +1 -1
  54. package/docs/api/type-aliases/DictName.md +1 -1
  55. package/docs/api/type-aliases/EntryType.md +1 -1
  56. package/docs/api/type-aliases/JLPT.md +1 -1
  57. package/docs/api/type-aliases/Result.md +1 -1
  58. package/package.json +6 -6
package/dist/index.cjs.js CHANGED
@@ -68,7 +68,7 @@ var regexps = {
68
68
  kanji: new RegExp("\\p{Script=Han}+", "u"),
69
69
  scriptSplit: /([\p{sc=Han}]+|[\p{sc=Hiragana}]+|[\p{sc=Katakana}]+|[^\p{sc=Han}\p{sc=Hiragana}\p{sc=Katakana}]+)/u,
70
70
  regExChars: /[-\/\\^$*+?.()|[\]{}]/,
71
- tanakaID: /#ID=\d+_\d+$/,
71
+ tanakaID: /#ID=(?<id>\d+_\d+)$/,
72
72
  tanakaPart: /(?<base>[^()\[\]\{\}\s]+)(?:\((?<reading>[\S]+)\))?(?:\[(?<glossnum>[\S]+)\])?(?:\{(?<inflection>[\S]+)\})?/,
73
73
  tanakaReferenceID: /#(?<entryid>[\d]+)/
74
74
  };
@@ -1222,18 +1222,10 @@ function convertJMdict(xmlString, examples) {
1222
1222
  noent: true,
1223
1223
  recover: false
1224
1224
  });
1225
- const dict = [];
1225
+ let dict = [];
1226
+ const partMatches = /* @__PURE__ */ new Set();
1226
1227
  import_xml2js.default.parseString(dictParsed, (err, result) => {
1227
1228
  if (err) throw err;
1228
- const tanakaParts = examples && examples.length > 0 ? new Set(
1229
- examples.map(
1230
- (example) => example.parts.map((part) => [
1231
- part.baseForm,
1232
- ...part.reading ? [part.reading] : [],
1233
- ...part.referenceID ? [part.referenceID] : []
1234
- ])
1235
- ).flat(2)
1236
- ) : void 0;
1237
1229
  if (result.JMdict && typeof result.JMdict === "object" && isValidArray(result.JMdict.entry))
1238
1230
  for (const entry of result.JMdict.entry) {
1239
1231
  const entryObj = {
@@ -1282,7 +1274,8 @@ function convertJMdict(xmlString, examples) {
1282
1274
  if (readingObj.reading.length > 0)
1283
1275
  entryObj.readings.push(readingObj);
1284
1276
  }
1285
- if (isValidArray(meanings))
1277
+ if (isValidArray(meanings)) {
1278
+ let usuallyInKanaMeanings = 0;
1286
1279
  for (const meaning of meanings) {
1287
1280
  const meaningObj = {};
1288
1281
  if (isStringArray(meaning.pos))
@@ -1308,50 +1301,133 @@ function convertJMdict(xmlString, examples) {
1308
1301
  if (isStringArray(meaning.field))
1309
1302
  meaningObj.fields = meaning.field;
1310
1303
  if (isStringArray(meaning.s_inf)) meaningObj.info = meaning.s_inf;
1311
- if (isStringArray(meaning.misc)) meaningObj.misc = meaning.misc;
1304
+ if (isStringArray(meaning.misc)) {
1305
+ meaningObj.misc = meaning.misc;
1306
+ if (meaningObj.misc && meaningObj.misc.includes(
1307
+ "word usually written using kana alone"
1308
+ ))
1309
+ usuallyInKanaMeanings++;
1310
+ }
1312
1311
  if (isStringArray(meaning.dial))
1313
1312
  meaningObj.dialects = meaning.dial;
1314
1313
  if (meaningObj.partOfSpeech && meaningObj.partOfSpeech.length > 0 || meaningObj.translations && meaningObj.translations.length > 0)
1315
1314
  entryObj.meanings.push(meaningObj);
1316
1315
  }
1316
+ if (entryObj.meanings.length === usuallyInKanaMeanings)
1317
+ entryObj.usuallyInKana = true;
1318
+ }
1317
1319
  if (examples) {
1318
- const readings2 = new Set(
1319
- entryObj.readings.filter(
1320
- (reading) => (!reading.notes || !reading.notes.some(
1321
- (note) => notSearchedForms.has(note)
1322
- )) && (entryObj.isCommon === void 0 || reading.commonness && reading.commonness.length > 0)
1323
- ).map((reading) => reading.reading)
1324
- );
1325
- const kanjiForms2 = entryObj.kanjiForms ? new Set(
1326
- entryObj.kanjiForms.filter(
1327
- (kanjiForm) => (!kanjiForm.notes || !kanjiForm.notes.some(
1328
- (note) => notSearchedForms.has(note)
1329
- )) && (entryObj.isCommon === void 0 || kanjiForm.commonness && kanjiForm.commonness.length > 0)
1330
- ).map((kanjiForm) => kanjiForm.form)
1331
- ) : void 0;
1332
- let existsExample = false;
1333
- if (kanjiForms2 && kanjiForms2.size > 0 && tanakaParts) {
1334
- for (const kf of kanjiForms2)
1335
- if (tanakaParts.has(kf)) {
1336
- existsExample = true;
1337
- break;
1338
- }
1339
- }
1340
- if (!existsExample && readings2.size > 0 && tanakaParts) {
1341
- for (const r of readings2)
1342
- if (tanakaParts.has(r)) {
1343
- existsExample = true;
1344
- break;
1345
- }
1346
- }
1347
- if (!existsExample && tanakaParts && tanakaParts.has(entryObj.id))
1348
- existsExample = true;
1349
- if (existsExample) entryObj.hasPhrases = true;
1320
+ const readings2 = entryObj.readings.filter(
1321
+ (reading) => (!reading.notes || !reading.notes.some(
1322
+ (note) => notSearchedForms.has(note)
1323
+ )) && (entryObj.isCommon === void 0 || reading.commonness && reading.commonness.length > 0)
1324
+ ).map((reading) => reading.reading);
1325
+ const kanjiForms2 = entryObj.kanjiForms ? entryObj.kanjiForms.filter(
1326
+ (kanjiForm) => (!kanjiForm.notes || !kanjiForm.notes.some(
1327
+ (note) => notSearchedForms.has(note)
1328
+ )) && (entryObj.isCommon === void 0 || kanjiForm.commonness && kanjiForm.commonness.length > 0)
1329
+ ).map((kanjiForm) => kanjiForm.form) : void 0;
1330
+ for (const reading of readings2) partMatches.add(reading);
1331
+ if (kanjiForms2)
1332
+ for (const kanjiForm of kanjiForms2) partMatches.add(kanjiForm);
1333
+ partMatches.add(entryObj.id);
1350
1334
  }
1351
1335
  if (entryObj.id.length > 0 && entryObj.readings.length > 0 && entryObj.meanings.length > 0)
1352
1336
  dict.push(entryObj);
1353
1337
  }
1354
1338
  });
1339
+ if (examples && dict.length > 0) {
1340
+ const filteredExamples = examples.filter(
1341
+ (ex) => {
1342
+ const parts = ex.parts.flatMap((part) => [
1343
+ part.baseForm,
1344
+ ...part.reading ? [part.reading] : [],
1345
+ ...part.referenceID ? [part.referenceID] : []
1346
+ ]);
1347
+ for (const part of parts) if (partMatches.has(part)) return true;
1348
+ return false;
1349
+ }
1350
+ );
1351
+ dict = dict.map((entryObj) => {
1352
+ const readings = new Set(
1353
+ entryObj.readings.filter(
1354
+ (reading) => (!reading.notes || !reading.notes.some(
1355
+ (note) => notSearchedForms.has(note)
1356
+ )) && (entryObj.isCommon === void 0 || reading.commonness && reading.commonness.length > 0)
1357
+ ).map((reading) => reading.reading)
1358
+ );
1359
+ const kanjiForms = entryObj.kanjiForms ? new Set(
1360
+ entryObj.kanjiForms.filter(
1361
+ (kanjiForm) => (!kanjiForm.notes || !kanjiForm.notes.some(
1362
+ (note) => notSearchedForms.has(note)
1363
+ )) && (entryObj.isCommon === void 0 || kanjiForm.commonness && kanjiForm.commonness.length > 0)
1364
+ ).map((kanjiForm) => kanjiForm.form)
1365
+ ) : void 0;
1366
+ const kanjiFormExamples = [];
1367
+ const readingMatchingKanjiFormExamples = [];
1368
+ const readingExamples = [];
1369
+ const partParts = /* @__PURE__ */ new Set();
1370
+ for (const example of filteredExamples)
1371
+ for (const part of example.parts) {
1372
+ const readingAsReadingMatch = part.reading !== void 0 && readings.has(part.reading);
1373
+ if (kanjiForms && kanjiForms.size > 0 && kanjiForms.has(part.baseForm)) {
1374
+ if (readingAsReadingMatch) {
1375
+ readingMatchingKanjiFormExamples.push(example);
1376
+ partParts.add(part.baseForm).add(part.reading);
1377
+ } else {
1378
+ kanjiFormExamples.push(example);
1379
+ partParts.add(part.baseForm);
1380
+ }
1381
+ break;
1382
+ }
1383
+ const readingAsBaseFormMatch = readings.has(part.baseForm);
1384
+ const referenceIDMatch = part.referenceID !== void 0 && entryObj.id !== void 0 && part.referenceID === entryObj.id;
1385
+ if (readingAsReadingMatch || readingAsBaseFormMatch || referenceIDMatch) {
1386
+ readingExamples.push(example);
1387
+ if (readingAsReadingMatch) partParts.add(part.reading);
1388
+ if (readingAsBaseFormMatch) partParts.add(part.baseForm);
1389
+ if (referenceIDMatch) partParts.add(part.referenceID);
1390
+ break;
1391
+ }
1392
+ }
1393
+ const exampleSize = readingMatchingKanjiFormExamples.length + kanjiFormExamples.length + readingExamples.length;
1394
+ const includeKanjiFormExamples = readingMatchingKanjiFormExamples.length < Math.max(2, Math.round(exampleSize * 0.05));
1395
+ const includeReadingExamples = entryObj.usuallyInKana === void 0 && includeKanjiFormExamples && readingExamples.length >= Math.max(10, Math.round(exampleSize * 0.15)) || entryObj.usuallyInKana === true && readingExamples.length >= Math.max(2, Math.round(exampleSize * 0.5));
1396
+ let wordExamples = [
1397
+ ...readingMatchingKanjiFormExamples,
1398
+ ...includeKanjiFormExamples ? kanjiFormExamples : [],
1399
+ ...includeReadingExamples ? readingExamples : []
1400
+ ];
1401
+ const glossSpecificExamples = [];
1402
+ const seenPhrases = /* @__PURE__ */ new Set();
1403
+ for (let i = 0; i < entryObj.meanings.length; i++) {
1404
+ outer: for (const example of wordExamples) {
1405
+ if (seenPhrases.has(example.phrase)) continue;
1406
+ for (const part of example.parts)
1407
+ if (part.glossNumber === i + 1 && (partParts.has(part.baseForm) || part.reading && partParts.has(part.reading) || part.referenceID && partParts.has(part.referenceID))) {
1408
+ glossSpecificExamples.push(example);
1409
+ seenPhrases.add(example.phrase);
1410
+ break outer;
1411
+ }
1412
+ }
1413
+ if (glossSpecificExamples.length === 5) break;
1414
+ }
1415
+ if (glossSpecificExamples.length === 5)
1416
+ wordExamples = glossSpecificExamples;
1417
+ else if (glossSpecificExamples.length > 0) {
1418
+ const seenPhrases2 = new Set(
1419
+ glossSpecificExamples.map((ex) => ex.phrase)
1420
+ );
1421
+ wordExamples = [
1422
+ ...glossSpecificExamples,
1423
+ ...wordExamples.filter((ex) => !seenPhrases2.has(ex.phrase)).slice(0, 5 - glossSpecificExamples.length)
1424
+ ];
1425
+ }
1426
+ if (wordExamples.length > 0)
1427
+ entryObj.phraseIDs = (wordExamples.length > 5 ? wordExamples.slice(0, 5) : wordExamples).map((ex) => ex.id);
1428
+ return entryObj;
1429
+ });
1430
+ }
1355
1431
  return dict;
1356
1432
  } catch (err) {
1357
1433
  throw err;
@@ -1445,9 +1521,12 @@ async function convertTanakaCorpus(tanakaString, generateFurigana) {
1445
1521
  let a = tanakaParsed[i];
1446
1522
  let b = tanakaParsed[i + 1];
1447
1523
  if (a && b && a.startsWith("A: ") && b.startsWith("B: ")) {
1448
- a = a.replace("A: ", "").replace(regexps.tanakaID, "");
1524
+ a = a.replace("A: ", "");
1449
1525
  b = b.replace("B: ", "");
1450
- const aParts = a.split(" ");
1526
+ const idMatch = regexps.tanakaID.exec(a);
1527
+ if (!idMatch || !idMatch.groups || !idMatch.groups["id"])
1528
+ throw new Error(`Invalid phrase ID for ${a}`);
1529
+ const aParts = a.replace(regexps.tanakaID, "").split(" ");
1451
1530
  const bParts = b.split(" ").filter((part) => part.trim().length !== 0).map((part) => {
1452
1531
  const partMatches = regexps.tanakaPart.exec(part);
1453
1532
  if (!partMatches || !partMatches.groups || partMatches.length === 0)
@@ -1485,8 +1564,9 @@ async function convertTanakaCorpus(tanakaString, generateFurigana) {
1485
1564
  mode: "furigana"
1486
1565
  });
1487
1566
  tanakaArray.push({
1488
- phrase,
1489
- translation,
1567
+ id: idMatch.groups["id"].trim(),
1568
+ phrase: phrase.trim(),
1569
+ translation: translation.trim(),
1490
1570
  parts: bParts,
1491
1571
  ...furigana ? { furigana } : {}
1492
1572
  });
@@ -1611,6 +1691,7 @@ var wordAddNoteArray = (arr, cb) => {
1611
1691
  for (const v of arr) cb(v);
1612
1692
  };
1613
1693
  function getWord(dict, id, kanjiDic, examples, dictWord, noteTypeName, deckPath) {
1694
+ var _a;
1614
1695
  try {
1615
1696
  if (!dictWord && id && dict)
1616
1697
  dictWord = dict.find((entry) => entry.id === id);
@@ -1631,7 +1712,7 @@ function getWord(dict, id, kanjiDic, examples, dictWord, noteTypeName, deckPath)
1631
1712
  kanjiForm: dictKanjiForm.form,
1632
1713
  ...dictKanjiForm.notes ? {
1633
1714
  notes: dictKanjiForm.notes.map((note) => {
1634
- var _a;
1715
+ var _a2;
1635
1716
  const noteAndTag = lookupWordNote(
1636
1717
  note,
1637
1718
  void 0,
@@ -1639,7 +1720,7 @@ function getWord(dict, id, kanjiDic, examples, dictWord, noteTypeName, deckPath)
1639
1720
  false,
1640
1721
  note
1641
1722
  );
1642
- return capitalizeString((_a = noteAndTag.note) != null ? _a : note);
1723
+ return capitalizeString((_a2 = noteAndTag.note) != null ? _a2 : note);
1643
1724
  })
1644
1725
  } : {},
1645
1726
  ...dictKanjiForm.commonness && dictKanjiForm.commonness.length > 0 ? { common: true } : {}
@@ -1653,7 +1734,7 @@ function getWord(dict, id, kanjiDic, examples, dictWord, noteTypeName, deckPath)
1653
1734
  (restriction) => `Reading restricted to ${restriction}`
1654
1735
  ) : [],
1655
1736
  ...dictReading.notes ? dictReading.notes.map((note) => {
1656
- var _a;
1737
+ var _a2;
1657
1738
  const noteAndTag = lookupWordNote(
1658
1739
  note,
1659
1740
  void 0,
@@ -1661,13 +1742,12 @@ function getWord(dict, id, kanjiDic, examples, dictWord, noteTypeName, deckPath)
1661
1742
  false,
1662
1743
  note
1663
1744
  );
1664
- return capitalizeString((_a = noteAndTag.note) != null ? _a : note);
1745
+ return capitalizeString((_a2 = noteAndTag.note) != null ? _a2 : note);
1665
1746
  }) : []
1666
1747
  ]
1667
1748
  } : {},
1668
1749
  ...dictReading.commonness && dictReading.commonness.length > 0 ? { common: true } : {}
1669
1750
  }));
1670
- let usuallyInKanaMeanings = 0;
1671
1751
  word.translations = dictWord.meanings.map((dictMeaning) => {
1672
1752
  if (!dictMeaning.translations)
1673
1753
  throw new Error(`No translations for ${dictWord.id}`);
@@ -1720,11 +1800,10 @@ function getWord(dict, id, kanjiDic, examples, dictWord, noteTypeName, deckPath)
1720
1800
  dictMeaning.info,
1721
1801
  (info) => lookupWordNote(info, notes, word.tags, false, info)
1722
1802
  );
1723
- wordAddNoteArray(dictMeaning.misc, (misc) => {
1724
- lookupWordNote(misc, notes, word.tags, false, misc);
1725
- if (misc.toLowerCase() === "word usually written using kana alone")
1726
- usuallyInKanaMeanings++;
1727
- });
1803
+ wordAddNoteArray(
1804
+ dictMeaning.misc,
1805
+ (misc) => lookupWordNote(misc, notes, word.tags, false, misc)
1806
+ );
1728
1807
  for (let i = 0; i < notes.length; i++)
1729
1808
  notes[i] = capitalizeString(notes[i]);
1730
1809
  return {
@@ -1732,8 +1811,7 @@ function getWord(dict, id, kanjiDic, examples, dictWord, noteTypeName, deckPath)
1732
1811
  notes
1733
1812
  };
1734
1813
  });
1735
- if (word.translations && word.translations.length === usuallyInKanaMeanings)
1736
- word.usuallyInKana = true;
1814
+ if (dictWord.usuallyInKana === true) word.usuallyInKana = true;
1737
1815
  if (kanjiDic && word.kanjiForms) {
1738
1816
  word.kanji = [];
1739
1817
  for (const kanjiForm of word.kanjiForms)
@@ -1757,92 +1835,16 @@ function getWord(dict, id, kanjiDic, examples, dictWord, noteTypeName, deckPath)
1757
1835
  }
1758
1836
  if (word.kanji.length === 0) delete word.kanji;
1759
1837
  }
1760
- if (examples && dictWord.hasPhrases === true) {
1761
- const readings = new Set(
1762
- word.readings.filter(
1763
- (reading) => (!reading.notes || !reading.notes.some(
1764
- (note) => notSearchedForms.has(note)
1765
- )) && (word.common === void 0 || reading.common === true)
1766
- ).map((reading) => reading.reading)
1767
- );
1768
- const kanjiForms = word.kanjiForms ? new Set(
1769
- word.kanjiForms.filter(
1770
- (kanjiForm) => (!kanjiForm.notes || !kanjiForm.notes.some(
1771
- (note) => notSearchedForms.has(note)
1772
- )) && (word.common === void 0 || kanjiForm.common === true)
1773
- ).map((kanjiForm) => kanjiForm.kanjiForm)
1774
- ) : void 0;
1775
- const kanjiFormExamples = [];
1776
- const readingMatchingKanjiFormExamples = [];
1777
- const readingExamples = [];
1778
- const partParts = /* @__PURE__ */ new Set();
1779
- for (const example of examples)
1780
- for (const part of example.parts) {
1781
- const readingAsReadingMatch = part.reading !== void 0 && readings.has(part.reading);
1782
- if (kanjiForms && kanjiForms.size > 0 && kanjiForms.has(part.baseForm)) {
1783
- if (readingAsReadingMatch) {
1784
- readingMatchingKanjiFormExamples.push(example);
1785
- partParts.add(part.baseForm).add(part.reading);
1786
- } else {
1787
- kanjiFormExamples.push(example);
1788
- partParts.add(part.baseForm);
1789
- }
1790
- break;
1791
- }
1792
- const readingAsBaseFormMatch = readings.has(part.baseForm);
1793
- const referenceIDMatch = part.referenceID !== void 0 && word.id !== void 0 && part.referenceID === word.id;
1794
- if (readingAsReadingMatch || readingAsBaseFormMatch || referenceIDMatch) {
1795
- readingExamples.push(example);
1796
- if (readingAsReadingMatch) partParts.add(part.reading);
1797
- if (readingAsBaseFormMatch) partParts.add(part.baseForm);
1798
- if (referenceIDMatch) partParts.add(part.referenceID);
1799
- break;
1800
- }
1801
- }
1802
- const exampleSize = readingMatchingKanjiFormExamples.length + kanjiFormExamples.length + readingExamples.length;
1803
- const includeKanjiFormExamples = readingMatchingKanjiFormExamples.length < Math.max(2, Math.round(exampleSize * 0.05));
1804
- const includeReadingExamples = word.usuallyInKana === void 0 && includeKanjiFormExamples && readingExamples.length >= Math.max(10, Math.round(exampleSize * 0.15)) || word.usuallyInKana === true && readingExamples.length >= Math.max(2, Math.round(exampleSize * 0.5));
1805
- let wordExamples = [
1806
- ...readingMatchingKanjiFormExamples,
1807
- ...includeKanjiFormExamples ? kanjiFormExamples : [],
1808
- ...includeReadingExamples ? readingExamples : []
1809
- ];
1810
- if (word.translations) {
1811
- const glossSpecificExamples = [];
1812
- const seenPhrases = /* @__PURE__ */ new Set();
1813
- for (let i = 0; i < word.translations.length; i++) {
1814
- outer: for (const example of wordExamples) {
1815
- if (seenPhrases.has(example.phrase)) continue;
1816
- for (const part of example.parts)
1817
- if (part.glossNumber === i + 1 && (partParts.has(part.baseForm) || part.reading && partParts.has(part.reading) || part.referenceID && partParts.has(part.referenceID))) {
1818
- glossSpecificExamples.push(example);
1819
- seenPhrases.add(example.phrase);
1820
- break outer;
1821
- }
1822
- }
1823
- if (glossSpecificExamples.length === 5) break;
1824
- }
1825
- if (glossSpecificExamples.length === 5)
1826
- wordExamples = [...glossSpecificExamples];
1827
- else if (glossSpecificExamples.length > 0) {
1828
- const seenPhrases2 = new Set(
1829
- glossSpecificExamples.map((ex) => ex.phrase)
1830
- );
1831
- wordExamples = [
1832
- ...glossSpecificExamples,
1833
- ...wordExamples.filter((ex) => !seenPhrases2.has(ex.phrase)).slice(0, 5 - glossSpecificExamples.length)
1834
- ];
1835
- }
1836
- }
1837
- if (wordExamples.length > 0)
1838
- word.phrases = (wordExamples.length > 5 ? wordExamples.slice(0, 5) : wordExamples).map((ex) => {
1839
- var _a;
1840
- return {
1838
+ if (examples && dictWord.phraseIDs && dictWord.phraseIDs.length > 0) {
1839
+ word.phrases = [];
1840
+ const phraseIDs = new Set(dictWord.phraseIDs);
1841
+ for (const ex of examples)
1842
+ if (phraseIDs.has(ex.id))
1843
+ word.phrases.push({
1841
1844
  phrase: (_a = ex.furigana) != null ? _a : ex.phrase,
1842
1845
  translation: ex.translation,
1843
1846
  originalPhrase: ex.phrase
1844
- };
1845
- });
1847
+ });
1846
1848
  }
1847
1849
  return word;
1848
1850
  } else throw new Error(`Word${id ? ` ${id}` : ""} not found`);