@ncukondo/reference-manager 0.27.2 → 0.28.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 (76) hide show
  1. package/dist/chunks/{SearchableMultiSelect-0cyizees.js → SearchableMultiSelect-BVp72Ptt.js} +2 -2
  2. package/dist/chunks/{SearchableMultiSelect-0cyizees.js.map → SearchableMultiSelect-BVp72Ptt.js.map} +1 -1
  3. package/dist/chunks/{action-menu-Crcd5X1-.js → action-menu-BhuUnwdz.js} +3 -3
  4. package/dist/chunks/{action-menu-Crcd5X1-.js.map → action-menu-BhuUnwdz.js.map} +1 -1
  5. package/dist/chunks/{checker-gLAPe44T.js → checker-CP8vSC-S.js} +5 -5
  6. package/dist/chunks/{checker-gLAPe44T.js.map → checker-CP8vSC-S.js.map} +1 -1
  7. package/dist/chunks/{crossref-client-CXw0mw4n.js → crossref-client-C1HVx8LA.js} +2 -2
  8. package/dist/chunks/{crossref-client-CXw0mw4n.js.map → crossref-client-C1HVx8LA.js.map} +1 -1
  9. package/dist/chunks/{file-watcher-Dlx0PolG.js → file-watcher-CWHg1yol.js} +48 -2
  10. package/dist/chunks/file-watcher-CWHg1yol.js.map +1 -0
  11. package/dist/chunks/{fix-interaction-BCtx4Q9F.js → fix-interaction-pDdwGbp1.js} +5 -5
  12. package/dist/chunks/{fix-interaction-BCtx4Q9F.js.map → fix-interaction-pDdwGbp1.js.map} +1 -1
  13. package/dist/chunks/{index-SwsAKyQr.js → index-DM3Q5lW4.js} +3 -3
  14. package/dist/chunks/index-DM3Q5lW4.js.map +1 -0
  15. package/dist/chunks/{index-DkJT7s7N.js → index-Dk83ayti.js} +76 -55
  16. package/dist/chunks/index-Dk83ayti.js.map +1 -0
  17. package/dist/chunks/{index-BdLVfbj0.js → index-T-edKSzd.js} +198 -19
  18. package/dist/chunks/index-T-edKSzd.js.map +1 -0
  19. package/dist/chunks/{index-Cf5bYLrr.js → index-gwWeJC-c.js} +4 -4
  20. package/dist/chunks/{index-Cf5bYLrr.js.map → index-gwWeJC-c.js.map} +1 -1
  21. package/dist/chunks/{loader-B-fte1uv.js → loader-B6sytmQd.js} +2 -2
  22. package/dist/chunks/{loader-B-fte1uv.js.map → loader-B6sytmQd.js.map} +1 -1
  23. package/dist/chunks/{metadata-comparator-C5zfoYdK.js → metadata-comparator-DvqzC5tX.js} +5 -3
  24. package/dist/chunks/metadata-comparator-DvqzC5tX.js.map +1 -0
  25. package/dist/chunks/{pubmed-client-DH9y2tEZ.js → pubmed-client-DEo6eaH7.js} +2 -2
  26. package/dist/chunks/{pubmed-client-DH9y2tEZ.js.map → pubmed-client-DEo6eaH7.js.map} +1 -1
  27. package/dist/chunks/{reference-select-Ce9pG8cC.js → reference-select-9GUq-x2d.js} +4 -4
  28. package/dist/chunks/{reference-select-Ce9pG8cC.js.map → reference-select-9GUq-x2d.js.map} +1 -1
  29. package/dist/chunks/{style-select-AvDsSnlB.js → style-select-DvH9N4Jg.js} +3 -3
  30. package/dist/chunks/{style-select-AvDsSnlB.js.map → style-select-DvH9N4Jg.js.map} +1 -1
  31. package/dist/cli/commands/server.d.ts.map +1 -1
  32. package/dist/cli/completion.d.ts.map +1 -1
  33. package/dist/cli/index.d.ts.map +1 -1
  34. package/dist/cli.js +2 -2
  35. package/dist/core/csl-json/types.d.ts +67 -0
  36. package/dist/core/csl-json/types.d.ts.map +1 -1
  37. package/dist/features/attachments/types.d.ts +8 -16
  38. package/dist/features/attachments/types.d.ts.map +1 -1
  39. package/dist/features/check/metadata-similarity.d.ts +1 -0
  40. package/dist/features/check/metadata-similarity.d.ts.map +1 -1
  41. package/dist/features/duplicate/detector.d.ts.map +1 -1
  42. package/dist/features/duplicate/types.d.ts +2 -1
  43. package/dist/features/duplicate/types.d.ts.map +1 -1
  44. package/dist/features/format/citation-fallback.d.ts.map +1 -1
  45. package/dist/features/format/pretty.d.ts.map +1 -1
  46. package/dist/features/format/resource-indicators.d.ts.map +1 -1
  47. package/dist/features/import/cache.d.ts +7 -1
  48. package/dist/features/import/cache.d.ts.map +1 -1
  49. package/dist/features/import/detector.d.ts +15 -2
  50. package/dist/features/import/detector.d.ts.map +1 -1
  51. package/dist/features/import/fetcher.d.ts +7 -0
  52. package/dist/features/import/fetcher.d.ts.map +1 -1
  53. package/dist/features/import/importer.d.ts.map +1 -1
  54. package/dist/features/import/normalizer.d.ts +16 -0
  55. package/dist/features/import/normalizer.d.ts.map +1 -1
  56. package/dist/features/import/rate-limiter.d.ts +1 -1
  57. package/dist/features/import/rate-limiter.d.ts.map +1 -1
  58. package/dist/features/operations/attachments/get.d.ts.map +1 -1
  59. package/dist/features/operations/attachments/list.d.ts.map +1 -1
  60. package/dist/features/operations/attachments/open.d.ts.map +1 -1
  61. package/dist/features/operations/fulltext/convert.d.ts.map +1 -1
  62. package/dist/features/operations/fulltext/detach.d.ts.map +1 -1
  63. package/dist/features/operations/fulltext/discover.d.ts.map +1 -1
  64. package/dist/features/operations/fulltext/fetch.d.ts.map +1 -1
  65. package/dist/features/operations/fulltext/get.d.ts.map +1 -1
  66. package/dist/features/operations/fulltext/open.d.ts.map +1 -1
  67. package/dist/features/operations/remove.d.ts.map +1 -1
  68. package/dist/features/search/matcher.d.ts.map +1 -1
  69. package/dist/index.js +3 -3
  70. package/dist/server.js +2 -2
  71. package/package.json +1 -1
  72. package/dist/chunks/file-watcher-Dlx0PolG.js.map +0 -1
  73. package/dist/chunks/index-BdLVfbj0.js.map +0 -1
  74. package/dist/chunks/index-DkJT7s7N.js.map +0 -1
  75. package/dist/chunks/index-SwsAKyQr.js.map +0 -1
  76. package/dist/chunks/metadata-comparator-C5zfoYdK.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-SwsAKyQr.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"metadata-comparator-C5zfoYdK.js","sources":["../../src/features/check/metadata-similarity.ts","../../src/features/check/metadata-comparator.ts"],"sourcesContent":["/**\n * Metadata similarity functions for comparing local vs remote reference metadata.\n */\n\nimport { normalize } from \"../search/normalizer.js\";\n\ntype AuthorName = { family?: string; given?: string };\n\n/**\n * Tokenize a title into a set of normalized words.\n */\nfunction titleToWordSet(title: string): Set<string> {\n const normalized = normalize(title);\n if (normalized === \"\") return new Set();\n return new Set(normalized.split(\" \"));\n}\n\n/**\n * Check if two titles are similar using Jaccard similarity and Containment coefficient.\n * Returns true (similar) if Jaccard >= 0.5 OR Containment >= 0.8.\n * Returns true if either title is empty/undefined (not enough data to compare).\n */\nexport function isTitleSimilar(local: string | undefined, remote: string | undefined): boolean {\n if (!local || !remote) return true;\n\n const localWords = titleToWordSet(local);\n const remoteWords = titleToWordSet(remote);\n\n if (localWords.size === 0 || remoteWords.size === 0) return true;\n\n // Intersection\n let intersectionSize = 0;\n for (const word of localWords) {\n if (remoteWords.has(word)) intersectionSize++;\n }\n\n // Jaccard = |A∩B| / |A∪B|\n const unionSize = localWords.size + remoteWords.size - intersectionSize;\n const jaccard = unionSize > 0 ? intersectionSize / unionSize : 0;\n\n // Containment = |A∩B| / min(|A|, |B|)\n const minSize = Math.min(localWords.size, remoteWords.size);\n const containment = minSize > 0 ? intersectionSize / minSize : 0;\n\n return jaccard >= 0.5 || containment >= 0.8;\n}\n\n/**\n * Extract and normalize family names from an author array.\n */\nfunction extractFamilyNames(authors: AuthorName[]): Set<string> {\n const families = new Set<string>();\n for (const author of authors) {\n if (author.family) {\n families.add(normalize(author.family));\n }\n }\n return families;\n}\n\n/**\n * Check if author lists are similar using family name overlap ratio.\n * Overlap = |local_families ∩ remote_families| / |local_families|\n * Returns true (similar) if overlap >= 0.5.\n * Returns true if either side has no authors (not enough data).\n */\nexport function isAuthorSimilar(\n local: AuthorName[] | undefined,\n remote: AuthorName[] | undefined\n): boolean {\n if (!local || !remote || local.length === 0 || remote.length === 0) return true;\n\n const localFamilies = extractFamilyNames(local);\n const remoteFamilies = extractFamilyNames(remote);\n\n if (localFamilies.size === 0 || remoteFamilies.size === 0) return true;\n\n let overlapCount = 0;\n for (const family of localFamilies) {\n if (remoteFamilies.has(family)) overlapCount++;\n }\n\n // Asymmetric by design: measures how many local authors appear in remote.\n // This correctly handles co-authors being added to the remote record (local is\n // a subset of remote → overlap = 1.0). The trade-off is that if remote has many\n // extra unrelated authors plus one coincidental match, overlap could be high.\n // In practice, this is rare for academic metadata.\n const overlap = overlapCount / localFamilies.size;\n return overlap >= 0.5;\n}\n","/**\n * Metadata comparator for classifying differences between local and remote metadata.\n */\n\nimport type { RemoteMetadata } from \"./crossref-client.js\";\nimport { isAuthorSimilar, isTitleSimilar } from \"./metadata-similarity.js\";\n\nexport interface MetadataComparisonResult {\n classification: \"metadata_mismatch\" | \"metadata_outdated\" | \"no_change\";\n changedFields: string[];\n fieldDiffs: Array<{\n field: string;\n local: string | null;\n remote: string | null;\n }>;\n}\n\n/**\n * Local item fields relevant for metadata comparison.\n */\nexport interface LocalMetadataFields {\n title?: string;\n author?: Array<{ family?: string; given?: string }>;\n \"container-title\"?: string;\n type?: string;\n page?: string;\n volume?: string;\n issue?: string;\n issued?: { \"date-parts\"?: number[][] };\n}\n\n/**\n * Map Crossref type to CSL type for comparison.\n */\nconst CROSSREF_TO_CSL_TYPE: Record<string, string> = {\n \"journal-article\": \"article-journal\",\n \"book-chapter\": \"chapter\",\n \"proceedings-article\": \"paper-conference\",\n \"posted-content\": \"article\",\n monograph: \"book\",\n \"edited-book\": \"book\",\n \"reference-book\": \"book\",\n report: \"report\",\n dataset: \"dataset\",\n dissertation: \"thesis\",\n \"peer-review\": \"review\",\n \"book-part\": \"chapter\",\n \"reference-entry\": \"entry\",\n component: \"article\",\n};\n\nfunction normalizeType(type: string | undefined, isCrossref: boolean): string | null {\n if (!type) return null;\n if (isCrossref) return CROSSREF_TO_CSL_TYPE[type] ?? type;\n return type;\n}\n\nfunction formatAuthors(\n authors: Array<{ family?: string; given?: string }> | undefined\n): string | null {\n if (!authors || authors.length === 0) return null;\n return authors.map((a) => [a.family, a.given].filter(Boolean).join(\", \")).join(\"; \");\n}\n\nfunction formatDateParts(issued: { \"date-parts\"?: number[][] } | undefined): string | null {\n const parts = issued?.[\"date-parts\"]?.[0];\n if (!parts || parts.length === 0) return null;\n return parts.join(\"-\");\n}\n\ntype FieldDiff = MetadataComparisonResult[\"fieldDiffs\"][number];\n\nfunction addDiffIfChanged(\n diffs: FieldDiff[],\n fields: string[],\n name: string,\n local: string | null,\n remote: string | null\n): void {\n if (local === remote) return;\n if (local === null && remote === null) return;\n fields.push(name);\n diffs.push({ field: name, local, remote });\n}\n\nfunction collectFieldDiffs(\n local: LocalMetadataFields,\n remote: RemoteMetadata\n): { changedFields: string[]; fieldDiffs: FieldDiff[] } {\n const changedFields: string[] = [];\n const fieldDiffs: FieldDiff[] = [];\n\n // Title\n addDiffIfChanged(fieldDiffs, changedFields, \"title\", local.title ?? null, remote.title ?? null);\n\n // Author\n addDiffIfChanged(\n fieldDiffs,\n changedFields,\n \"author\",\n formatAuthors(local.author),\n formatAuthors(remote.author)\n );\n\n // Container title\n // NOTE: Compared as raw strings. Abbreviation differences (e.g., \"J. Am. Chem. Soc.\"\n // vs \"Journal of the American Chemical Society\") will show as diffs. This is acceptable\n // because such differences are classified as \"outdated\" (not \"mismatch\"), and updating\n // to the canonical remote form is generally desirable.\n addDiffIfChanged(\n fieldDiffs,\n changedFields,\n \"container-title\",\n local[\"container-title\"] ?? null,\n remote.containerTitle ?? null\n );\n\n // Type (with mapping)\n addDiffIfChanged(\n fieldDiffs,\n changedFields,\n \"type\",\n normalizeType(local.type, false),\n normalizeType(remote.type, true)\n );\n\n // Publication fields\n addDiffIfChanged(fieldDiffs, changedFields, \"page\", local.page ?? null, remote.page ?? null);\n addDiffIfChanged(\n fieldDiffs,\n changedFields,\n \"volume\",\n local.volume ?? null,\n remote.volume ?? null\n );\n addDiffIfChanged(fieldDiffs, changedFields, \"issue\", local.issue ?? null, remote.issue ?? null);\n addDiffIfChanged(\n fieldDiffs,\n changedFields,\n \"issued\",\n formatDateParts(local.issued),\n formatDateParts(remote.issued)\n );\n\n return { changedFields, fieldDiffs };\n}\n\n/**\n * Compare local metadata fields against remote (Crossref) metadata.\n * Classifies differences as metadata_mismatch, metadata_outdated, or no_change.\n */\nexport function compareMetadata(\n local: LocalMetadataFields,\n remote: RemoteMetadata\n): MetadataComparisonResult {\n const { changedFields, fieldDiffs } = collectFieldDiffs(local, remote);\n\n if (changedFields.length === 0) {\n return { classification: \"no_change\", changedFields, fieldDiffs };\n }\n\n const titleSimilar = isTitleSimilar(local.title, remote.title);\n const authorSimilar = isAuthorSimilar(local.author, remote.author);\n\n if (!titleSimilar || !authorSimilar) {\n return { classification: \"metadata_mismatch\", changedFields, fieldDiffs };\n }\n\n return { classification: \"metadata_outdated\", changedFields, fieldDiffs };\n}\n"],"names":[],"mappings":"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"}