@ncukondo/reference-manager 0.25.0 → 0.27.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.
- package/README.md +14 -2
- package/dist/chunks/{SearchableMultiSelect-B7qEWPDT.js → SearchableMultiSelect-D6-pj_XI.js} +2 -2
- package/dist/chunks/{SearchableMultiSelect-B7qEWPDT.js.map → SearchableMultiSelect-D6-pj_XI.js.map} +1 -1
- package/dist/chunks/{action-menu-DD0RtNVD.js → action-menu-DP1rmCkH.js} +3 -3
- package/dist/chunks/{action-menu-DD0RtNVD.js.map → action-menu-DP1rmCkH.js.map} +1 -1
- package/dist/chunks/checker-B-SL7krG.js +170 -0
- package/dist/chunks/checker-B-SL7krG.js.map +1 -0
- package/dist/chunks/crossref-client-D6g3pLUI.js +94 -0
- package/dist/chunks/crossref-client-D6g3pLUI.js.map +1 -0
- package/dist/chunks/{fix-interaction-BpfMLRNY.js → fix-interaction-CTIvq9t4.js} +79 -20
- package/dist/chunks/fix-interaction-CTIvq9t4.js.map +1 -0
- package/dist/chunks/{index-QTYx5RaF.js → index-B8ST0WLa.js} +235 -79
- package/dist/chunks/index-B8ST0WLa.js.map +1 -0
- package/dist/chunks/{index-CYEise6v.js → index-Bo1JIDmF.js} +4 -4
- package/dist/chunks/{index-CYEise6v.js.map → index-Bo1JIDmF.js.map} +1 -1
- package/dist/chunks/{index-D2HsxXnK.js → index-DUpYvm-W.js} +43 -25
- package/dist/chunks/index-DUpYvm-W.js.map +1 -0
- package/dist/chunks/{index-PQkbePWV.js → index-F4gbDFWf.js} +3 -3
- package/dist/chunks/index-F4gbDFWf.js.map +1 -0
- package/dist/chunks/metadata-comparator-C5zfoYdK.js +137 -0
- package/dist/chunks/metadata-comparator-C5zfoYdK.js.map +1 -0
- package/dist/chunks/{pubmed-client-J18fg3fG.js → pubmed-client-mGn5jDIc.js} +2 -2
- package/dist/chunks/{pubmed-client-J18fg3fG.js.map → pubmed-client-mGn5jDIc.js.map} +1 -1
- package/dist/chunks/{reference-select-Qpgt9cbN.js → reference-select-DtzpiOvp.js} +3 -3
- package/dist/chunks/{reference-select-Qpgt9cbN.js.map → reference-select-DtzpiOvp.js.map} +1 -1
- package/dist/chunks/{style-select-mEMoWbM2.js → style-select-BT-HOyFf.js} +3 -3
- package/dist/chunks/{style-select-mEMoWbM2.js.map → style-select-BT-HOyFf.js.map} +1 -1
- package/dist/cli/commands/check.d.ts +2 -1
- package/dist/cli/commands/check.d.ts.map +1 -1
- package/dist/cli/commands/fulltext.d.ts +12 -7
- package/dist/cli/commands/fulltext.d.ts.map +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli.js +1 -1
- package/dist/features/check/checker.d.ts +1 -0
- package/dist/features/check/checker.d.ts.map +1 -1
- package/dist/features/check/crossref-client.d.ts +16 -0
- package/dist/features/check/crossref-client.d.ts.map +1 -1
- package/dist/features/check/fix-actions.d.ts +1 -1
- package/dist/features/check/fix-actions.d.ts.map +1 -1
- package/dist/features/check/fix-interaction.d.ts.map +1 -1
- package/dist/features/check/metadata-comparator.d.ts +37 -0
- package/dist/features/check/metadata-comparator.d.ts.map +1 -0
- package/dist/features/check/metadata-similarity.d.ts +22 -0
- package/dist/features/check/metadata-similarity.d.ts.map +1 -0
- package/dist/features/check/types.d.ts +6 -1
- package/dist/features/check/types.d.ts.map +1 -1
- package/dist/features/operations/check.d.ts +1 -0
- package/dist/features/operations/check.d.ts.map +1 -1
- package/dist/mcp/tools/check.d.ts +1 -0
- package/dist/mcp/tools/check.d.ts.map +1 -1
- package/dist/server/routes/check.d.ts.map +1 -1
- package/dist/server.js +1 -1
- package/package.json +1 -1
- package/dist/chunks/checker-7pzK2XSC.js +0 -92
- package/dist/chunks/checker-7pzK2XSC.js.map +0 -1
- package/dist/chunks/crossref-client-DGNz4PNW.js +0 -52
- package/dist/chunks/crossref-client-DGNz4PNW.js.map +0 -1
- package/dist/chunks/fix-interaction-BpfMLRNY.js.map +0 -1
- package/dist/chunks/index-D2HsxXnK.js.map +0 -1
- package/dist/chunks/index-PQkbePWV.js.map +0 -1
- package/dist/chunks/index-QTYx5RaF.js.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a } from "./index-
|
|
2
|
-
import { d, g, l, o, s } from "./index-
|
|
1
|
+
import { a } from "./index-DUpYvm-W.js";
|
|
2
|
+
import { d, g, l, o, s } from "./index-B8ST0WLa.js";
|
|
3
3
|
export {
|
|
4
4
|
a as addAttachment,
|
|
5
5
|
d as detachAttachment,
|
|
@@ -8,4 +8,4 @@ export {
|
|
|
8
8
|
o as openAttachment,
|
|
9
9
|
s as syncAttachments
|
|
10
10
|
};
|
|
11
|
-
//# sourceMappingURL=index-
|
|
11
|
+
//# sourceMappingURL=index-F4gbDFWf.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-F4gbDFWf.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { n as normalize } from "./file-watcher-Dlx0PolG.js";
|
|
2
|
+
function titleToWordSet(title) {
|
|
3
|
+
const normalized = normalize(title);
|
|
4
|
+
if (normalized === "") return /* @__PURE__ */ new Set();
|
|
5
|
+
return new Set(normalized.split(" "));
|
|
6
|
+
}
|
|
7
|
+
function isTitleSimilar(local, remote) {
|
|
8
|
+
if (!local || !remote) return true;
|
|
9
|
+
const localWords = titleToWordSet(local);
|
|
10
|
+
const remoteWords = titleToWordSet(remote);
|
|
11
|
+
if (localWords.size === 0 || remoteWords.size === 0) return true;
|
|
12
|
+
let intersectionSize = 0;
|
|
13
|
+
for (const word of localWords) {
|
|
14
|
+
if (remoteWords.has(word)) intersectionSize++;
|
|
15
|
+
}
|
|
16
|
+
const unionSize = localWords.size + remoteWords.size - intersectionSize;
|
|
17
|
+
const jaccard = unionSize > 0 ? intersectionSize / unionSize : 0;
|
|
18
|
+
const minSize = Math.min(localWords.size, remoteWords.size);
|
|
19
|
+
const containment = minSize > 0 ? intersectionSize / minSize : 0;
|
|
20
|
+
return jaccard >= 0.5 || containment >= 0.8;
|
|
21
|
+
}
|
|
22
|
+
function extractFamilyNames(authors) {
|
|
23
|
+
const families = /* @__PURE__ */ new Set();
|
|
24
|
+
for (const author of authors) {
|
|
25
|
+
if (author.family) {
|
|
26
|
+
families.add(normalize(author.family));
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return families;
|
|
30
|
+
}
|
|
31
|
+
function isAuthorSimilar(local, remote) {
|
|
32
|
+
if (!local || !remote || local.length === 0 || remote.length === 0) return true;
|
|
33
|
+
const localFamilies = extractFamilyNames(local);
|
|
34
|
+
const remoteFamilies = extractFamilyNames(remote);
|
|
35
|
+
if (localFamilies.size === 0 || remoteFamilies.size === 0) return true;
|
|
36
|
+
let overlapCount = 0;
|
|
37
|
+
for (const family of localFamilies) {
|
|
38
|
+
if (remoteFamilies.has(family)) overlapCount++;
|
|
39
|
+
}
|
|
40
|
+
const overlap = overlapCount / localFamilies.size;
|
|
41
|
+
return overlap >= 0.5;
|
|
42
|
+
}
|
|
43
|
+
const CROSSREF_TO_CSL_TYPE = {
|
|
44
|
+
"journal-article": "article-journal",
|
|
45
|
+
"book-chapter": "chapter",
|
|
46
|
+
"proceedings-article": "paper-conference",
|
|
47
|
+
"posted-content": "article",
|
|
48
|
+
monograph: "book",
|
|
49
|
+
"edited-book": "book",
|
|
50
|
+
"reference-book": "book",
|
|
51
|
+
report: "report",
|
|
52
|
+
dataset: "dataset",
|
|
53
|
+
dissertation: "thesis",
|
|
54
|
+
"peer-review": "review",
|
|
55
|
+
"book-part": "chapter",
|
|
56
|
+
"reference-entry": "entry",
|
|
57
|
+
component: "article"
|
|
58
|
+
};
|
|
59
|
+
function normalizeType(type, isCrossref) {
|
|
60
|
+
if (!type) return null;
|
|
61
|
+
if (isCrossref) return CROSSREF_TO_CSL_TYPE[type] ?? type;
|
|
62
|
+
return type;
|
|
63
|
+
}
|
|
64
|
+
function formatAuthors(authors) {
|
|
65
|
+
if (!authors || authors.length === 0) return null;
|
|
66
|
+
return authors.map((a) => [a.family, a.given].filter(Boolean).join(", ")).join("; ");
|
|
67
|
+
}
|
|
68
|
+
function formatDateParts(issued) {
|
|
69
|
+
const parts = issued?.["date-parts"]?.[0];
|
|
70
|
+
if (!parts || parts.length === 0) return null;
|
|
71
|
+
return parts.join("-");
|
|
72
|
+
}
|
|
73
|
+
function addDiffIfChanged(diffs, fields, name, local, remote) {
|
|
74
|
+
if (local === remote) return;
|
|
75
|
+
if (local === null && remote === null) return;
|
|
76
|
+
fields.push(name);
|
|
77
|
+
diffs.push({ field: name, local, remote });
|
|
78
|
+
}
|
|
79
|
+
function collectFieldDiffs(local, remote) {
|
|
80
|
+
const changedFields = [];
|
|
81
|
+
const fieldDiffs = [];
|
|
82
|
+
addDiffIfChanged(fieldDiffs, changedFields, "title", local.title ?? null, remote.title ?? null);
|
|
83
|
+
addDiffIfChanged(
|
|
84
|
+
fieldDiffs,
|
|
85
|
+
changedFields,
|
|
86
|
+
"author",
|
|
87
|
+
formatAuthors(local.author),
|
|
88
|
+
formatAuthors(remote.author)
|
|
89
|
+
);
|
|
90
|
+
addDiffIfChanged(
|
|
91
|
+
fieldDiffs,
|
|
92
|
+
changedFields,
|
|
93
|
+
"container-title",
|
|
94
|
+
local["container-title"] ?? null,
|
|
95
|
+
remote.containerTitle ?? null
|
|
96
|
+
);
|
|
97
|
+
addDiffIfChanged(
|
|
98
|
+
fieldDiffs,
|
|
99
|
+
changedFields,
|
|
100
|
+
"type",
|
|
101
|
+
normalizeType(local.type, false),
|
|
102
|
+
normalizeType(remote.type, true)
|
|
103
|
+
);
|
|
104
|
+
addDiffIfChanged(fieldDiffs, changedFields, "page", local.page ?? null, remote.page ?? null);
|
|
105
|
+
addDiffIfChanged(
|
|
106
|
+
fieldDiffs,
|
|
107
|
+
changedFields,
|
|
108
|
+
"volume",
|
|
109
|
+
local.volume ?? null,
|
|
110
|
+
remote.volume ?? null
|
|
111
|
+
);
|
|
112
|
+
addDiffIfChanged(fieldDiffs, changedFields, "issue", local.issue ?? null, remote.issue ?? null);
|
|
113
|
+
addDiffIfChanged(
|
|
114
|
+
fieldDiffs,
|
|
115
|
+
changedFields,
|
|
116
|
+
"issued",
|
|
117
|
+
formatDateParts(local.issued),
|
|
118
|
+
formatDateParts(remote.issued)
|
|
119
|
+
);
|
|
120
|
+
return { changedFields, fieldDiffs };
|
|
121
|
+
}
|
|
122
|
+
function compareMetadata(local, remote) {
|
|
123
|
+
const { changedFields, fieldDiffs } = collectFieldDiffs(local, remote);
|
|
124
|
+
if (changedFields.length === 0) {
|
|
125
|
+
return { classification: "no_change", changedFields, fieldDiffs };
|
|
126
|
+
}
|
|
127
|
+
const titleSimilar = isTitleSimilar(local.title, remote.title);
|
|
128
|
+
const authorSimilar = isAuthorSimilar(local.author, remote.author);
|
|
129
|
+
if (!titleSimilar || !authorSimilar) {
|
|
130
|
+
return { classification: "metadata_mismatch", changedFields, fieldDiffs };
|
|
131
|
+
}
|
|
132
|
+
return { classification: "metadata_outdated", changedFields, fieldDiffs };
|
|
133
|
+
}
|
|
134
|
+
export {
|
|
135
|
+
compareMetadata
|
|
136
|
+
};
|
|
137
|
+
//# sourceMappingURL=metadata-comparator-C5zfoYdK.js.map
|
|
@@ -0,0 +1 @@
|
|
|
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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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { g as getRateLimiter } from "./index-
|
|
1
|
+
import { g as getRateLimiter } from "./index-DUpYvm-W.js";
|
|
2
2
|
const PUBMED_ESUMMARY_BASE = "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esummary.fcgi";
|
|
3
3
|
function buildEsummaryUrl(pmid, config) {
|
|
4
4
|
const url = new URL(PUBMED_ESUMMARY_BASE);
|
|
@@ -48,4 +48,4 @@ async function queryPubmed(pmid, config) {
|
|
|
48
48
|
export {
|
|
49
49
|
queryPubmed
|
|
50
50
|
};
|
|
51
|
-
//# sourceMappingURL=pubmed-client-
|
|
51
|
+
//# sourceMappingURL=pubmed-client-mGn5jDIc.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pubmed-client-
|
|
1
|
+
{"version":3,"file":"pubmed-client-mGn5jDIc.js","sources":["../../src/features/check/pubmed-client.ts"],"sourcesContent":["import { getRateLimiter } from \"../import/rate-limiter.js\";\n\nconst PUBMED_ESUMMARY_BASE = \"https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esummary.fcgi\";\n\nexport type PubmedResult =\n | { success: true; isRetracted: boolean; hasConcern: boolean }\n | { success: false; error: string };\n\n/**\n * Build PubMed E-utilities esummary URL.\n */\nfunction buildEsummaryUrl(pmid: string, config?: { email?: string; apiKey?: string }): string {\n const url = new URL(PUBMED_ESUMMARY_BASE);\n url.searchParams.set(\"db\", \"pubmed\");\n url.searchParams.set(\"id\", pmid);\n url.searchParams.set(\"retmode\", \"json\");\n if (config?.email) {\n url.searchParams.set(\"email\", config.email);\n }\n if (config?.apiKey) {\n url.searchParams.set(\"api_key\", config.apiKey);\n }\n return url.toString();\n}\n\n/**\n * Query PubMed E-utilities for publication status of a PMID.\n *\n * @param pmid - The PubMed ID to query\n * @param config - Optional PubMed config (email, apiKey)\n * @returns PubMed result with retraction status\n */\nexport async function queryPubmed(\n pmid: string,\n config?: { email?: string; apiKey?: string }\n): Promise<PubmedResult> {\n const rateLimiterConfig = config?.apiKey ? { pubmedApiKey: config.apiKey } : {};\n const rateLimiter = getRateLimiter(\"pubmed\", rateLimiterConfig);\n await rateLimiter.acquire();\n\n try {\n const url = buildEsummaryUrl(pmid, config);\n const response = await fetch(url);\n\n if (!response.ok) {\n return {\n success: false,\n error: `PubMed API returned ${response.status} ${response.statusText}`,\n };\n }\n\n const data = (await response.json()) as Record<string, unknown>;\n const resultObj = data.result as Record<string, unknown> | undefined;\n const articleData = resultObj?.[pmid] as Record<string, unknown> | undefined;\n\n if (!articleData) {\n return { success: true, isRetracted: false, hasConcern: false };\n }\n\n const pubTypes = (articleData.pubtype ?? []) as string[];\n const isRetracted = pubTypes.some(\n (t) => t === \"Retracted Publication\" || t === \"Retraction of Publication\"\n );\n const hasConcern = pubTypes.some((t) => t === \"Expression of Concern\");\n\n return { success: true, isRetracted, hasConcern };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n"],"names":[],"mappings":";AAEA,MAAM,uBAAuB;AAS7B,SAAS,iBAAiB,MAAc,QAAsD;AAC5F,QAAM,MAAM,IAAI,IAAI,oBAAoB;AACxC,MAAI,aAAa,IAAI,MAAM,QAAQ;AACnC,MAAI,aAAa,IAAI,MAAM,IAAI;AAC/B,MAAI,aAAa,IAAI,WAAW,MAAM;AACtC,MAAI,QAAQ,OAAO;AACjB,QAAI,aAAa,IAAI,SAAS,OAAO,KAAK;AAAA,EAC5C;AACA,MAAI,QAAQ,QAAQ;AAClB,QAAI,aAAa,IAAI,WAAW,OAAO,MAAM;AAAA,EAC/C;AACA,SAAO,IAAI,SAAA;AACb;AASA,eAAsB,YACpB,MACA,QACuB;AACvB,QAAM,oBAAoB,QAAQ,SAAS,EAAE,cAAc,OAAO,OAAA,IAAW,CAAA;AAC7E,QAAM,cAAc,eAAe,UAAU,iBAAiB;AAC9D,QAAM,YAAY,QAAA;AAElB,MAAI;AACF,UAAM,MAAM,iBAAiB,MAAM,MAAM;AACzC,UAAM,WAAW,MAAM,MAAM,GAAG;AAEhC,QAAI,CAAC,SAAS,IAAI;AAChB,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO,uBAAuB,SAAS,MAAM,IAAI,SAAS,UAAU;AAAA,MAAA;AAAA,IAExE;AAEA,UAAM,OAAQ,MAAM,SAAS,KAAA;AAC7B,UAAM,YAAY,KAAK;AACvB,UAAM,cAAc,YAAY,IAAI;AAEpC,QAAI,CAAC,aAAa;AAChB,aAAO,EAAE,SAAS,MAAM,aAAa,OAAO,YAAY,MAAA;AAAA,IAC1D;AAEA,UAAM,WAAY,YAAY,WAAW,CAAA;AACzC,UAAM,cAAc,SAAS;AAAA,MAC3B,CAAC,MAAM,MAAM,2BAA2B,MAAM;AAAA,IAAA;AAEhD,UAAM,aAAa,SAAS,KAAK,CAAC,MAAM,MAAM,uBAAuB;AAErE,WAAO,EAAE,SAAS,MAAM,aAAa,WAAA;AAAA,EACvC,SAAS,OAAO;AACd,WAAO;AAAA,MACL,SAAS;AAAA,MACT,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,IAAA;AAAA,EAEhE;AACF;"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { t as tokenize, s as search } from "./file-watcher-Dlx0PolG.js";
|
|
2
2
|
import { render, useApp } from "ink";
|
|
3
3
|
import { createElement } from "react";
|
|
4
|
-
import { r as restoreStdinAfterInk } from "./index-
|
|
5
|
-
import { t as toChoice, c as calculateEffectiveLimit, S as SearchableMultiSelect } from "./SearchableMultiSelect-
|
|
4
|
+
import { r as restoreStdinAfterInk } from "./index-B8ST0WLa.js";
|
|
5
|
+
import { t as toChoice, c as calculateEffectiveLimit, S as SearchableMultiSelect } from "./SearchableMultiSelect-D6-pj_XI.js";
|
|
6
6
|
import { checkTTY } from "./tty-BMyaEOhX.js";
|
|
7
7
|
function SearchPromptApp({
|
|
8
8
|
choices,
|
|
@@ -126,4 +126,4 @@ export {
|
|
|
126
126
|
selectReferenceItemsOrExit,
|
|
127
127
|
selectReferencesOrExit
|
|
128
128
|
};
|
|
129
|
-
//# sourceMappingURL=reference-select-
|
|
129
|
+
//# sourceMappingURL=reference-select-DtzpiOvp.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reference-select-Qpgt9cbN.js","sources":["../../src/features/interactive/search-prompt.ts","../../src/features/interactive/reference-select.ts"],"sourcesContent":["/**\n * Interactive search prompt using React Ink\n *\n * Provides real-time incremental search with multiple selection support.\n */\n\nimport { render, useApp } from \"ink\";\nimport type React from \"react\";\nimport { createElement } from \"react\";\nimport type { CslItem } from \"../../core/csl-json/types.js\";\nimport type { SearchResult } from \"../search/types.js\";\nimport { restoreStdinAfterInk } from \"./alternate-screen.js\";\nimport { toChoice } from \"./choice-builder.js\";\nimport {\n type Choice,\n SearchableMultiSelect,\n type SortOption,\n calculateEffectiveLimit,\n getTerminalHeight,\n getTerminalWidth,\n} from \"./components/index.js\";\n\n/**\n * Configuration for the search prompt\n */\nexport interface SearchPromptConfig {\n /** Maximum number of results to display */\n limit: number;\n /** Debounce delay in milliseconds (not used in Ink version, kept for API compatibility) */\n debounceMs: number;\n}\n\n/**\n * Search function type for filtering references\n */\nexport type SearchFunction = (query: string) => SearchResult[];\n\n/**\n * Result from the search prompt\n */\nexport interface SearchPromptResult {\n /** Selected references */\n selected: CslItem[];\n /** Whether the prompt was cancelled */\n cancelled: boolean;\n}\n\nexport { calculateEffectiveLimit, getTerminalHeight, getTerminalWidth };\n\n/**\n * Props for the SearchPromptApp component\n */\ninterface SearchPromptAppProps {\n choices: Choice<CslItem>[];\n filterFn: (query: string, choices: Choice<CslItem>[]) => Choice<CslItem>[];\n visibleCount: number;\n defaultSort: SortOption;\n onSubmit: (selected: Choice<CslItem>[]) => void;\n onCancel: () => void;\n}\n\n/**\n * SearchPromptApp component - wraps SearchableMultiSelect for search prompt\n */\nfunction SearchPromptApp({\n choices,\n filterFn,\n visibleCount,\n defaultSort,\n onSubmit,\n onCancel,\n}: SearchPromptAppProps): React.ReactElement {\n const { exit } = useApp();\n\n const handleSubmit = (selected: Choice<CslItem>[]): void => {\n onSubmit(selected);\n exit();\n };\n\n const handleCancel = (): void => {\n onCancel();\n exit();\n };\n\n return createElement(SearchableMultiSelect<CslItem>, {\n choices,\n filterFn,\n visibleCount,\n onSubmit: handleSubmit,\n onCancel: handleCancel,\n header: \"Search references\",\n placeholder: \"Type to search...\",\n defaultSort,\n });\n}\n\n/**\n * Creates and runs an interactive search prompt\n */\nexport async function runSearchPrompt(\n allReferences: CslItem[],\n searchFn: SearchFunction,\n config: SearchPromptConfig,\n _initialQuery = \"\" // kept for API compatibility, not used in Ink version\n): Promise<SearchPromptResult> {\n // Convert references to choices\n const choices = allReferences.map(toChoice);\n\n // Calculate effective visible count\n const effectiveLimit = calculateEffectiveLimit(config.limit);\n\n // Create filter function using the provided search function\n const filterFn = (query: string, choices: Choice<CslItem>[]): Choice<CslItem>[] => {\n if (!query.trim()) return choices;\n\n const results = searchFn(query);\n return results.map((r) => toChoice(r.reference));\n };\n\n // Create a promise to capture the result\n return new Promise<SearchPromptResult>((resolve) => {\n let result: SearchPromptResult = { selected: [], cancelled: true };\n\n const handleSubmit = (selected: Choice<CslItem>[]): void => {\n result = {\n selected: selected.map((c) => c.value),\n cancelled: false,\n };\n };\n\n const handleCancel = (): void => {\n result = {\n selected: [],\n cancelled: true,\n };\n };\n\n // Render the Ink app\n const { waitUntilExit, clear } = render(\n createElement(SearchPromptApp, {\n choices,\n filterFn,\n visibleCount: effectiveLimit,\n defaultSort: \"updated-desc\",\n onSubmit: handleSubmit,\n onCancel: handleCancel,\n })\n );\n\n // Wait for the app to exit, clear the screen, then resolve\n waitUntilExit()\n .then(() => {\n clear();\n restoreStdinAfterInk();\n resolve(result);\n })\n .catch(() => {\n clear();\n restoreStdinAfterInk();\n resolve({\n selected: [],\n cancelled: true,\n });\n });\n });\n}\n","/**\n * Shared reference selection utility for interactive ID selection.\n *\n * This module provides a reusable function to select references interactively\n * using the existing search prompt infrastructure.\n */\n\nimport type { CslItem } from \"../../core/csl-json/types.js\";\nimport { search } from \"../search/matcher.js\";\nimport { tokenize } from \"../search/tokenizer.js\";\nimport { type SearchPromptConfig, runSearchPrompt } from \"./search-prompt.js\";\nimport { checkTTY } from \"./tty.js\";\n\n/**\n * Options for reference selection\n */\nexport interface ReferenceSelectOptions {\n /** Whether to allow multiple selection (default: true) */\n multiSelect: boolean;\n /** Custom prompt message */\n prompt?: string;\n /** Initial search query */\n initialQuery?: string;\n}\n\n/**\n * Result from reference selection\n */\nexport interface ReferenceSelectResult {\n /** Selected references */\n selected: CslItem[];\n /** Whether the selection was cancelled */\n cancelled: boolean;\n}\n\n/**\n * Run interactive reference selection.\n *\n * Launches an interactive search prompt to select references from the library.\n * Supports both single and multiple selection modes.\n *\n * @param allReferences - All references available for selection\n * @param options - Selection options\n * @param config - Interactive prompt configuration\n * @returns Selection result with selected references\n * @throws TTYError if not running in a TTY environment\n */\nexport async function runReferenceSelect(\n allReferences: CslItem[],\n options: ReferenceSelectOptions,\n config: SearchPromptConfig\n): Promise<ReferenceSelectResult> {\n // Check TTY requirement\n checkTTY();\n\n // Create search function for runSearchPrompt\n const searchFn = (query: string) => {\n const { tokens } = tokenize(query);\n return search(allReferences, tokens);\n };\n\n // Run search prompt\n const searchResult = await runSearchPrompt(\n allReferences,\n searchFn,\n config,\n options.initialQuery ?? \"\"\n );\n\n if (searchResult.cancelled) {\n return { selected: [], cancelled: true };\n }\n\n // For single-select mode, return only the first selected item\n const selected = options.multiSelect ? searchResult.selected : searchResult.selected.slice(0, 1);\n\n return {\n selected,\n cancelled: false,\n };\n}\n\n/**\n * Options for selectReferencesOrExit helper\n */\nexport interface SelectReferencesOrExitOptions {\n /** Whether to allow multiple selection */\n multiSelect: boolean;\n /** Initial search query */\n initialQuery?: string;\n}\n\n/**\n * Select references interactively or exit if cancelled/empty.\n *\n * This is a convenience wrapper around runReferenceSelect that handles\n * common patterns:\n * - Exits with code 0 if library is empty\n * - Exits with code 0 if selection is cancelled\n * - Returns selected identifiers\n *\n * @param allReferences - All references available for selection\n * @param options - Selection options\n * @param config - Interactive prompt configuration\n * @returns Array of selected reference IDs (never empty)\n */\nexport async function selectReferencesOrExit(\n allReferences: CslItem[],\n options: SelectReferencesOrExitOptions,\n config: SearchPromptConfig\n): Promise<string[]> {\n if (allReferences.length === 0) {\n process.stderr.write(\"No references in library.\\n\");\n process.exit(0);\n }\n\n const selectResult = await runReferenceSelect(allReferences, options, config);\n\n if (selectResult.cancelled || selectResult.selected.length === 0) {\n process.exit(0);\n }\n\n return selectResult.selected.map((item) => item.id);\n}\n\n/**\n * Select reference items interactively or exit if cancelled/empty.\n *\n * Similar to selectReferencesOrExit but returns full CslItem objects\n * instead of just identifiers. Useful when the caller needs access to\n * the full reference data (e.g., for confirmation dialogs).\n *\n * @param allReferences - All references available for selection\n * @param options - Selection options\n * @param config - Interactive prompt configuration\n * @returns Array of selected CslItem objects (never empty)\n */\nexport async function selectReferenceItemsOrExit(\n allReferences: CslItem[],\n options: SelectReferencesOrExitOptions,\n config: SearchPromptConfig\n): Promise<CslItem[]> {\n if (allReferences.length === 0) {\n process.stderr.write(\"No references in library.\\n\");\n process.exit(0);\n }\n\n const selectResult = await runReferenceSelect(allReferences, options, config);\n\n if (selectResult.cancelled || selectResult.selected.length === 0) {\n process.exit(0);\n }\n\n return selectResult.selected;\n}\n"],"names":["choices"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"reference-select-DtzpiOvp.js","sources":["../../src/features/interactive/search-prompt.ts","../../src/features/interactive/reference-select.ts"],"sourcesContent":["/**\n * Interactive search prompt using React Ink\n *\n * Provides real-time incremental search with multiple selection support.\n */\n\nimport { render, useApp } from \"ink\";\nimport type React from \"react\";\nimport { createElement } from \"react\";\nimport type { CslItem } from \"../../core/csl-json/types.js\";\nimport type { SearchResult } from \"../search/types.js\";\nimport { restoreStdinAfterInk } from \"./alternate-screen.js\";\nimport { toChoice } from \"./choice-builder.js\";\nimport {\n type Choice,\n SearchableMultiSelect,\n type SortOption,\n calculateEffectiveLimit,\n getTerminalHeight,\n getTerminalWidth,\n} from \"./components/index.js\";\n\n/**\n * Configuration for the search prompt\n */\nexport interface SearchPromptConfig {\n /** Maximum number of results to display */\n limit: number;\n /** Debounce delay in milliseconds (not used in Ink version, kept for API compatibility) */\n debounceMs: number;\n}\n\n/**\n * Search function type for filtering references\n */\nexport type SearchFunction = (query: string) => SearchResult[];\n\n/**\n * Result from the search prompt\n */\nexport interface SearchPromptResult {\n /** Selected references */\n selected: CslItem[];\n /** Whether the prompt was cancelled */\n cancelled: boolean;\n}\n\nexport { calculateEffectiveLimit, getTerminalHeight, getTerminalWidth };\n\n/**\n * Props for the SearchPromptApp component\n */\ninterface SearchPromptAppProps {\n choices: Choice<CslItem>[];\n filterFn: (query: string, choices: Choice<CslItem>[]) => Choice<CslItem>[];\n visibleCount: number;\n defaultSort: SortOption;\n onSubmit: (selected: Choice<CslItem>[]) => void;\n onCancel: () => void;\n}\n\n/**\n * SearchPromptApp component - wraps SearchableMultiSelect for search prompt\n */\nfunction SearchPromptApp({\n choices,\n filterFn,\n visibleCount,\n defaultSort,\n onSubmit,\n onCancel,\n}: SearchPromptAppProps): React.ReactElement {\n const { exit } = useApp();\n\n const handleSubmit = (selected: Choice<CslItem>[]): void => {\n onSubmit(selected);\n exit();\n };\n\n const handleCancel = (): void => {\n onCancel();\n exit();\n };\n\n return createElement(SearchableMultiSelect<CslItem>, {\n choices,\n filterFn,\n visibleCount,\n onSubmit: handleSubmit,\n onCancel: handleCancel,\n header: \"Search references\",\n placeholder: \"Type to search...\",\n defaultSort,\n });\n}\n\n/**\n * Creates and runs an interactive search prompt\n */\nexport async function runSearchPrompt(\n allReferences: CslItem[],\n searchFn: SearchFunction,\n config: SearchPromptConfig,\n _initialQuery = \"\" // kept for API compatibility, not used in Ink version\n): Promise<SearchPromptResult> {\n // Convert references to choices\n const choices = allReferences.map(toChoice);\n\n // Calculate effective visible count\n const effectiveLimit = calculateEffectiveLimit(config.limit);\n\n // Create filter function using the provided search function\n const filterFn = (query: string, choices: Choice<CslItem>[]): Choice<CslItem>[] => {\n if (!query.trim()) return choices;\n\n const results = searchFn(query);\n return results.map((r) => toChoice(r.reference));\n };\n\n // Create a promise to capture the result\n return new Promise<SearchPromptResult>((resolve) => {\n let result: SearchPromptResult = { selected: [], cancelled: true };\n\n const handleSubmit = (selected: Choice<CslItem>[]): void => {\n result = {\n selected: selected.map((c) => c.value),\n cancelled: false,\n };\n };\n\n const handleCancel = (): void => {\n result = {\n selected: [],\n cancelled: true,\n };\n };\n\n // Render the Ink app\n const { waitUntilExit, clear } = render(\n createElement(SearchPromptApp, {\n choices,\n filterFn,\n visibleCount: effectiveLimit,\n defaultSort: \"updated-desc\",\n onSubmit: handleSubmit,\n onCancel: handleCancel,\n })\n );\n\n // Wait for the app to exit, clear the screen, then resolve\n waitUntilExit()\n .then(() => {\n clear();\n restoreStdinAfterInk();\n resolve(result);\n })\n .catch(() => {\n clear();\n restoreStdinAfterInk();\n resolve({\n selected: [],\n cancelled: true,\n });\n });\n });\n}\n","/**\n * Shared reference selection utility for interactive ID selection.\n *\n * This module provides a reusable function to select references interactively\n * using the existing search prompt infrastructure.\n */\n\nimport type { CslItem } from \"../../core/csl-json/types.js\";\nimport { search } from \"../search/matcher.js\";\nimport { tokenize } from \"../search/tokenizer.js\";\nimport { type SearchPromptConfig, runSearchPrompt } from \"./search-prompt.js\";\nimport { checkTTY } from \"./tty.js\";\n\n/**\n * Options for reference selection\n */\nexport interface ReferenceSelectOptions {\n /** Whether to allow multiple selection (default: true) */\n multiSelect: boolean;\n /** Custom prompt message */\n prompt?: string;\n /** Initial search query */\n initialQuery?: string;\n}\n\n/**\n * Result from reference selection\n */\nexport interface ReferenceSelectResult {\n /** Selected references */\n selected: CslItem[];\n /** Whether the selection was cancelled */\n cancelled: boolean;\n}\n\n/**\n * Run interactive reference selection.\n *\n * Launches an interactive search prompt to select references from the library.\n * Supports both single and multiple selection modes.\n *\n * @param allReferences - All references available for selection\n * @param options - Selection options\n * @param config - Interactive prompt configuration\n * @returns Selection result with selected references\n * @throws TTYError if not running in a TTY environment\n */\nexport async function runReferenceSelect(\n allReferences: CslItem[],\n options: ReferenceSelectOptions,\n config: SearchPromptConfig\n): Promise<ReferenceSelectResult> {\n // Check TTY requirement\n checkTTY();\n\n // Create search function for runSearchPrompt\n const searchFn = (query: string) => {\n const { tokens } = tokenize(query);\n return search(allReferences, tokens);\n };\n\n // Run search prompt\n const searchResult = await runSearchPrompt(\n allReferences,\n searchFn,\n config,\n options.initialQuery ?? \"\"\n );\n\n if (searchResult.cancelled) {\n return { selected: [], cancelled: true };\n }\n\n // For single-select mode, return only the first selected item\n const selected = options.multiSelect ? searchResult.selected : searchResult.selected.slice(0, 1);\n\n return {\n selected,\n cancelled: false,\n };\n}\n\n/**\n * Options for selectReferencesOrExit helper\n */\nexport interface SelectReferencesOrExitOptions {\n /** Whether to allow multiple selection */\n multiSelect: boolean;\n /** Initial search query */\n initialQuery?: string;\n}\n\n/**\n * Select references interactively or exit if cancelled/empty.\n *\n * This is a convenience wrapper around runReferenceSelect that handles\n * common patterns:\n * - Exits with code 0 if library is empty\n * - Exits with code 0 if selection is cancelled\n * - Returns selected identifiers\n *\n * @param allReferences - All references available for selection\n * @param options - Selection options\n * @param config - Interactive prompt configuration\n * @returns Array of selected reference IDs (never empty)\n */\nexport async function selectReferencesOrExit(\n allReferences: CslItem[],\n options: SelectReferencesOrExitOptions,\n config: SearchPromptConfig\n): Promise<string[]> {\n if (allReferences.length === 0) {\n process.stderr.write(\"No references in library.\\n\");\n process.exit(0);\n }\n\n const selectResult = await runReferenceSelect(allReferences, options, config);\n\n if (selectResult.cancelled || selectResult.selected.length === 0) {\n process.exit(0);\n }\n\n return selectResult.selected.map((item) => item.id);\n}\n\n/**\n * Select reference items interactively or exit if cancelled/empty.\n *\n * Similar to selectReferencesOrExit but returns full CslItem objects\n * instead of just identifiers. Useful when the caller needs access to\n * the full reference data (e.g., for confirmation dialogs).\n *\n * @param allReferences - All references available for selection\n * @param options - Selection options\n * @param config - Interactive prompt configuration\n * @returns Array of selected CslItem objects (never empty)\n */\nexport async function selectReferenceItemsOrExit(\n allReferences: CslItem[],\n options: SelectReferencesOrExitOptions,\n config: SearchPromptConfig\n): Promise<CslItem[]> {\n if (allReferences.length === 0) {\n process.stderr.write(\"No references in library.\\n\");\n process.exit(0);\n }\n\n const selectResult = await runReferenceSelect(allReferences, options, config);\n\n if (selectResult.cancelled || selectResult.selected.length === 0) {\n process.exit(0);\n }\n\n return selectResult.selected;\n}\n"],"names":["choices"],"mappings":"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"}
|
|
@@ -2,8 +2,8 @@ import * as fs from "node:fs";
|
|
|
2
2
|
import * as path from "node:path";
|
|
3
3
|
import "ink";
|
|
4
4
|
import "react";
|
|
5
|
-
import { B as BUILTIN_STYLES } from "./index-
|
|
6
|
-
import "./index-
|
|
5
|
+
import { B as BUILTIN_STYLES } from "./index-DUpYvm-W.js";
|
|
6
|
+
import "./index-B8ST0WLa.js";
|
|
7
7
|
function expandTilde(filePath) {
|
|
8
8
|
if (filePath.startsWith("~/")) {
|
|
9
9
|
const home = process.env.HOME || process.env.USERPROFILE || "";
|
|
@@ -58,4 +58,4 @@ export {
|
|
|
58
58
|
buildStyleChoices,
|
|
59
59
|
listCustomStyles
|
|
60
60
|
};
|
|
61
|
-
//# sourceMappingURL=style-select-
|
|
61
|
+
//# sourceMappingURL=style-select-BT-HOyFf.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"style-select-
|
|
1
|
+
{"version":3,"file":"style-select-BT-HOyFf.js","sources":["../../src/features/interactive/style-select.ts"],"sourcesContent":["/**\n * Style selection prompt for citation style selection.\n *\n * Lists built-in styles and custom styles from csl_directory,\n * with the default style shown first.\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { render, useApp } from \"ink\";\nimport { createElement } from \"react\";\nimport type React from \"react\";\nimport { BUILTIN_STYLES } from \"../../config/csl-styles.js\";\nimport { restoreStdinAfterInk } from \"./alternate-screen.js\";\nimport { Select, type SelectOption } from \"./components/index.js\";\n\n/**\n * Options for style selection\n */\nexport interface StyleSelectOptions {\n /** Directory or directories containing custom CSL files */\n cslDirectory?: string | string[];\n /** Default style to show first */\n defaultStyle?: string;\n}\n\n/**\n * Result from style selection\n */\nexport interface StyleSelectResult {\n /** Selected style name */\n style?: string;\n /** Whether the selection was cancelled */\n cancelled: boolean;\n}\n\n/**\n * Expand tilde (~) in path to home directory\n */\nfunction expandTilde(filePath: string): string {\n if (filePath.startsWith(\"~/\")) {\n const home = process.env.HOME || process.env.USERPROFILE || \"\";\n return path.join(home, filePath.slice(2));\n }\n return filePath;\n}\n\n/**\n * List custom CSL style names from the specified directory/directories.\n *\n * @param cslDirectory - Directory or directories to search for CSL files\n * @returns Array of style names (without .csl extension)\n */\nexport function listCustomStyles(cslDirectory: string | string[] | undefined): string[] {\n if (!cslDirectory) {\n return [];\n }\n\n const directories = Array.isArray(cslDirectory) ? cslDirectory : [cslDirectory];\n const styles = new Set<string>();\n\n for (const dir of directories) {\n const expandedDir = expandTilde(dir);\n\n if (!fs.existsSync(expandedDir)) {\n continue;\n }\n\n try {\n const files = fs.readdirSync(expandedDir);\n for (const file of files) {\n if (file.endsWith(\".csl\")) {\n styles.add(file.slice(0, -4)); // Remove .csl extension\n }\n }\n } catch {\n // Ignore read errors\n }\n }\n\n return Array.from(styles).sort();\n}\n\n/**\n * Build style choices for the selection prompt.\n *\n * @param customStyles - Custom style names from csl_directory\n * @param defaultStyle - Default style to show first\n * @returns Array of SelectOption for Ink Select prompt\n */\nexport function buildStyleChoices(\n customStyles: string[],\n defaultStyle = \"apa\"\n): SelectOption<string>[] {\n const choices: SelectOption<string>[] = [];\n const addedStyles = new Set<string>();\n\n // Helper to add a style choice\n const addChoice = (styleName: string, isDefault: boolean): void => {\n if (addedStyles.has(styleName)) return;\n addedStyles.add(styleName);\n\n choices.push({\n label: isDefault ? `${styleName} (default)` : styleName,\n value: styleName,\n });\n };\n\n // Add default style first\n addChoice(defaultStyle, true);\n\n // Add built-in styles\n for (const style of BUILTIN_STYLES) {\n addChoice(style, false);\n }\n\n // Add custom styles (excluding any that match built-in names)\n for (const style of customStyles) {\n addChoice(style, false);\n }\n\n return choices;\n}\n\n/**\n * Props for the StyleSelectApp component\n */\ninterface StyleSelectAppProps {\n options: SelectOption<string>[];\n onSelect: (value: string) => void;\n onCancel: () => void;\n}\n\n/**\n * StyleSelectApp component - wraps Select for style selection\n */\nfunction StyleSelectApp({ options, onSelect, onCancel }: StyleSelectAppProps): React.ReactElement {\n const { exit } = useApp();\n\n const handleSelect = (value: string): void => {\n onSelect(value);\n exit();\n };\n\n const handleCancel = (): void => {\n onCancel();\n exit();\n };\n\n return createElement(Select<string>, {\n options,\n message: \"Select citation style:\",\n onSelect: handleSelect,\n onCancel: handleCancel,\n });\n}\n\n/**\n * Run the style selection prompt.\n *\n * @param options - Style selection options\n * @returns Selection result with style name\n */\nexport async function runStyleSelect(options: StyleSelectOptions): Promise<StyleSelectResult> {\n // List custom styles from csl_directory\n const customStyles = listCustomStyles(options.cslDirectory);\n\n // Build choices with default first\n const choices = buildStyleChoices(customStyles, options.defaultStyle);\n\n // Create a promise to capture the result\n return new Promise<StyleSelectResult>((resolve) => {\n let result: StyleSelectResult = { cancelled: true };\n\n const handleSelect = (value: string): void => {\n result = {\n style: value,\n cancelled: false,\n };\n };\n\n const handleCancel = (): void => {\n result = {\n cancelled: true,\n };\n };\n\n // Render the Ink app\n const { waitUntilExit, clear } = render(\n createElement(StyleSelectApp, {\n options: choices,\n onSelect: handleSelect,\n onCancel: handleCancel,\n })\n );\n\n // Wait for the app to exit, clear the screen, then resolve\n waitUntilExit()\n .then(() => {\n clear();\n restoreStdinAfterInk();\n resolve(result);\n })\n .catch(() => {\n clear();\n restoreStdinAfterInk();\n resolve({\n cancelled: true,\n });\n });\n });\n}\n"],"names":[],"mappings":";;;;;;AAuCA,SAAS,YAAY,UAA0B;AAC7C,MAAI,SAAS,WAAW,IAAI,GAAG;AAC7B,UAAM,OAAO,QAAQ,IAAI,QAAQ,QAAQ,IAAI,eAAe;AAC5D,WAAO,KAAK,KAAK,MAAM,SAAS,MAAM,CAAC,CAAC;AAAA,EAC1C;AACA,SAAO;AACT;AAQO,SAAS,iBAAiB,cAAuD;AACtF,MAAI,CAAC,cAAc;AACjB,WAAO,CAAA;AAAA,EACT;AAEA,QAAM,cAAc,MAAM,QAAQ,YAAY,IAAI,eAAe,CAAC,YAAY;AAC9E,QAAM,6BAAa,IAAA;AAEnB,aAAW,OAAO,aAAa;AAC7B,UAAM,cAAc,YAAY,GAAG;AAEnC,QAAI,CAAC,GAAG,WAAW,WAAW,GAAG;AAC/B;AAAA,IACF;AAEA,QAAI;AACF,YAAM,QAAQ,GAAG,YAAY,WAAW;AACxC,iBAAW,QAAQ,OAAO;AACxB,YAAI,KAAK,SAAS,MAAM,GAAG;AACzB,iBAAO,IAAI,KAAK,MAAM,GAAG,EAAE,CAAC;AAAA,QAC9B;AAAA,MACF;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,SAAO,MAAM,KAAK,MAAM,EAAE,KAAA;AAC5B;AASO,SAAS,kBACd,cACA,eAAe,OACS;AACxB,QAAM,UAAkC,CAAA;AACxC,QAAM,kCAAkB,IAAA;AAGxB,QAAM,YAAY,CAAC,WAAmB,cAA6B;AACjE,QAAI,YAAY,IAAI,SAAS,EAAG;AAChC,gBAAY,IAAI,SAAS;AAEzB,YAAQ,KAAK;AAAA,MACX,OAAO,YAAY,GAAG,SAAS,eAAe;AAAA,MAC9C,OAAO;AAAA,IAAA,CACR;AAAA,EACH;AAGA,YAAU,cAAc,IAAI;AAG5B,aAAW,SAAS,gBAAgB;AAClC,cAAU,OAAO,KAAK;AAAA,EACxB;AAGA,aAAW,SAAS,cAAc;AAChC,cAAU,OAAO,KAAK;AAAA,EACxB;AAEA,SAAO;AACT;"}
|
|
@@ -10,9 +10,10 @@ export interface CheckCommandOptions {
|
|
|
10
10
|
search?: string;
|
|
11
11
|
output?: "text" | "json";
|
|
12
12
|
full?: boolean;
|
|
13
|
-
|
|
13
|
+
save?: boolean;
|
|
14
14
|
days?: number;
|
|
15
15
|
fix?: boolean;
|
|
16
|
+
metadata?: boolean;
|
|
16
17
|
}
|
|
17
18
|
export type CheckCommandResult = CheckOperationResult;
|
|
18
19
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/check.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAC;AAE5D,OAAO,KAAK,EAAgB,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAC/E,OAAO,KAAK,EAEV,oBAAoB,EACrB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,KAAK,gBAAgB,EAA0B,MAAM,yBAAyB,CAAC;AASxF,MAAM,WAAW,mBAAmB;IAClC,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,
|
|
1
|
+
{"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/check.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAC;AAE5D,OAAO,KAAK,EAAgB,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAC/E,OAAO,KAAK,EAEV,oBAAoB,EACrB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,KAAK,gBAAgB,EAA0B,MAAM,yBAAyB,CAAC;AASxF,MAAM,WAAW,mBAAmB;IAClC,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,MAAM,kBAAkB,GAAG,oBAAoB,CAAC;AA6CtD;;GAEG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE,mBAAmB,EAC5B,OAAO,EAAE,gBAAgB,EACzB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,kBAAkB,CAAC,CAE7B;AA6GD;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,oBAAoB,GAAG,MAAM,CAqC1E;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC9B;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,oBAAoB,EAC5B,OAAO,CAAC,EAAE,sBAAsB,GAC/B,oBAAoB,GAAG;IAAE,OAAO,EAAE,CAAC,WAAW,GAAG;QAAE,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC,EAAE,CAAA;CAAE,CAW1E;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,WAAW,EAAE,MAAM,EAAE,EACrB,OAAO,EAAE,IAAI,CAAC,mBAAmB,EAAE,aAAa,CAAC,EACjD,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAClC,OAAO,CAAC,IAAI,CAAC,CA8Cf"}
|
|
@@ -154,20 +154,25 @@ export interface FulltextAttachActionOptions {
|
|
|
154
154
|
* Handle 'fulltext attach' command action.
|
|
155
155
|
*/
|
|
156
156
|
export declare function handleFulltextAttachAction(identifierArg: string | undefined, filePathArg: string | undefined, options: FulltextAttachActionOptions, globalOpts: Record<string, unknown>): Promise<void>;
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
157
|
+
export interface FulltextGetIdResult {
|
|
158
|
+
id: string;
|
|
159
|
+
result: FulltextGetResult;
|
|
160
|
+
}
|
|
161
|
+
export declare function formatMultiFulltextGetOutput(results: FulltextGetIdResult[]): {
|
|
162
|
+
stdout: string;
|
|
163
|
+
stderr: string;
|
|
164
|
+
};
|
|
165
|
+
export declare function formatFulltextGetJsonOutput(results: FulltextGetIdResult[]): string;
|
|
166
|
+
/** Options for fulltext get action */
|
|
160
167
|
export interface FulltextGetActionOptions {
|
|
161
168
|
pdf?: boolean;
|
|
162
169
|
markdown?: boolean;
|
|
163
170
|
prefer?: "pdf" | "markdown";
|
|
164
171
|
stdout?: boolean;
|
|
165
172
|
uuid?: boolean;
|
|
173
|
+
output?: "json" | "text";
|
|
166
174
|
}
|
|
167
|
-
|
|
168
|
-
* Handle 'fulltext get' command action.
|
|
169
|
-
*/
|
|
170
|
-
export declare function handleFulltextGetAction(identifierArg: string | undefined, options: FulltextGetActionOptions, globalOpts: Record<string, unknown>): Promise<void>;
|
|
175
|
+
export declare function handleFulltextGetAction(identifierArgs: string[], options: FulltextGetActionOptions, globalOpts: Record<string, unknown>): Promise<void>;
|
|
171
176
|
/**
|
|
172
177
|
* Options for fulltext detach action
|
|
173
178
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fulltext.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/fulltext.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAEtE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,EACL,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EAexB,MAAM,6CAA6C,CAAC;AACrD,OAAO,EAAE,KAAK,gBAAgB,EAA0B,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"fulltext.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/fulltext.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;AAiE5C;;GAEG;AACH,wBAAgB,aAAa,IAAI,OAAO,CAiDvC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;AAiE5C;;GAEG;AACH,wBAAgB,aAAa,IAAI,OAAO,CAiDvC;AAuyBD;;GAEG;AACH,wBAAsB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAmBxD"}
|
package/dist/cli.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"checker.d.ts","sourceRoot":"","sources":["../../../src/features/check/checker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAC;AAE5D,OAAO,KAAK,EAAgB,WAAW,EAAE,MAAM,YAAY,CAAC;AAE5D,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"checker.d.ts","sourceRoot":"","sources":["../../../src/features/check/checker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAC;AAE5D,OAAO,KAAK,EAAgB,WAAW,EAAE,MAAM,YAAY,CAAC;AAE5D,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7C,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAOD;;;;;;GAMG;AACH,wBAAsB,cAAc,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAwC9F"}
|
|
@@ -4,9 +4,25 @@ export interface CrossrefUpdateInfo {
|
|
|
4
4
|
label?: string;
|
|
5
5
|
date?: string;
|
|
6
6
|
}
|
|
7
|
+
export interface RemoteMetadata {
|
|
8
|
+
title?: string;
|
|
9
|
+
author?: Array<{
|
|
10
|
+
family?: string;
|
|
11
|
+
given?: string;
|
|
12
|
+
}>;
|
|
13
|
+
containerTitle?: string;
|
|
14
|
+
type?: string;
|
|
15
|
+
page?: string;
|
|
16
|
+
volume?: string;
|
|
17
|
+
issue?: string;
|
|
18
|
+
issued?: {
|
|
19
|
+
"date-parts"?: number[][];
|
|
20
|
+
};
|
|
21
|
+
}
|
|
7
22
|
export type CrossrefResult = {
|
|
8
23
|
success: true;
|
|
9
24
|
updates: CrossrefUpdateInfo[];
|
|
25
|
+
metadata?: RemoteMetadata;
|
|
10
26
|
} | {
|
|
11
27
|
success: false;
|
|
12
28
|
error: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"crossref-client.d.ts","sourceRoot":"","sources":["../../../src/features/check/crossref-client.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,cAAc,GACtB;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,kBAAkB,EAAE,CAAA;CAAE,
|
|
1
|
+
{"version":3,"file":"crossref-client.d.ts","sourceRoot":"","sources":["../../../src/features/check/crossref-client.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,KAAK,CAAC;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACpD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,MAAM,EAAE,EAAE,CAAA;KAAE,CAAC;CACxC;AAED,MAAM,MAAM,cAAc,GACtB;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,kBAAkB,EAAE,CAAC;IAAC,QAAQ,CAAC,EAAE,cAAc,CAAA;CAAE,GAC3E;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAsEtC;;;;;;GAMG;AACH,wBAAsB,aAAa,CACjC,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAC1B,OAAO,CAAC,cAAc,CAAC,CAkDzB"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { CslItem } from "../../core/csl-json/types.js";
|
|
2
2
|
import type { ILibrary } from "../../core/library-interface.js";
|
|
3
3
|
import type { CheckFinding } from "./types.js";
|
|
4
|
-
export type FixActionType = "add_retracted_tag" | "add_retraction_note" | "remove_from_library" | "update_from_published" | "add_version_tag" | "add_concern_tag" | "add_concern_note" | "skip";
|
|
4
|
+
export type FixActionType = "add_retracted_tag" | "add_retraction_note" | "remove_from_library" | "update_from_published" | "add_version_tag" | "add_concern_tag" | "add_concern_note" | "update_all_fields" | "update_selected_fields" | "skip";
|
|
5
5
|
export interface FixAction {
|
|
6
6
|
type: FixActionType;
|
|
7
7
|
label: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fix-actions.d.ts","sourceRoot":"","sources":["../../../src/features/check/fix-actions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAChE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,MAAM,MAAM,aAAa,GACrB,mBAAmB,GACnB,qBAAqB,GACrB,qBAAqB,GACrB,uBAAuB,GACvB,iBAAiB,GACjB,iBAAiB,GACjB,kBAAkB,GAClB,MAAM,CAAC;AAEX,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,aAAa,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,YAAY,GAAG,SAAS,EAAE,
|
|
1
|
+
{"version":3,"file":"fix-actions.d.ts","sourceRoot":"","sources":["../../../src/features/check/fix-actions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAChE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,MAAM,MAAM,aAAa,GACrB,mBAAmB,GACnB,qBAAqB,GACrB,qBAAqB,GACrB,uBAAuB,GACvB,iBAAiB,GACjB,iBAAiB,GACjB,kBAAkB,GAClB,mBAAmB,GACnB,wBAAwB,GACxB,MAAM,CAAC;AAEX,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,aAAa,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,YAAY,GAAG,SAAS,EAAE,CA8B1E;AA4HD,wBAAsB,cAAc,CAClC,OAAO,EAAE,QAAQ,EACjB,IAAI,EAAE,OAAO,EACb,OAAO,EAAE,YAAY,EACrB,UAAU,EAAE,aAAa,GACxB,OAAO,CAAC,eAAe,CAAC,CA4C1B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fix-interaction.d.ts","sourceRoot":"","sources":["../../../src/features/check/fix-interaction.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAKhE,OAAO,KAAK,EAAgB,WAAW,EAAE,MAAM,YAAY,CAAC;AAE5D,MAAM,WAAW,oBAAoB;IACnC,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;
|
|
1
|
+
{"version":3,"file":"fix-interaction.d.ts","sourceRoot":"","sources":["../../../src/features/check/fix-interaction.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAKhE,OAAO,KAAK,EAAgB,WAAW,EAAE,MAAM,YAAY,CAAC;AAE5D,MAAM,WAAW,oBAAoB;IACnC,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAgGD,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,WAAW,EAAE,EACtB,OAAO,EAAE,QAAQ,EACjB,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,GAAG,SAAS,GAC5C,OAAO,CAAC,oBAAoB,CAAC,CAoB/B"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Metadata comparator for classifying differences between local and remote metadata.
|
|
3
|
+
*/
|
|
4
|
+
import type { RemoteMetadata } from "./crossref-client.js";
|
|
5
|
+
export interface MetadataComparisonResult {
|
|
6
|
+
classification: "metadata_mismatch" | "metadata_outdated" | "no_change";
|
|
7
|
+
changedFields: string[];
|
|
8
|
+
fieldDiffs: Array<{
|
|
9
|
+
field: string;
|
|
10
|
+
local: string | null;
|
|
11
|
+
remote: string | null;
|
|
12
|
+
}>;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Local item fields relevant for metadata comparison.
|
|
16
|
+
*/
|
|
17
|
+
export interface LocalMetadataFields {
|
|
18
|
+
title?: string;
|
|
19
|
+
author?: Array<{
|
|
20
|
+
family?: string;
|
|
21
|
+
given?: string;
|
|
22
|
+
}>;
|
|
23
|
+
"container-title"?: string;
|
|
24
|
+
type?: string;
|
|
25
|
+
page?: string;
|
|
26
|
+
volume?: string;
|
|
27
|
+
issue?: string;
|
|
28
|
+
issued?: {
|
|
29
|
+
"date-parts"?: number[][];
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Compare local metadata fields against remote (Crossref) metadata.
|
|
34
|
+
* Classifies differences as metadata_mismatch, metadata_outdated, or no_change.
|
|
35
|
+
*/
|
|
36
|
+
export declare function compareMetadata(local: LocalMetadataFields, remote: RemoteMetadata): MetadataComparisonResult;
|
|
37
|
+
//# sourceMappingURL=metadata-comparator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadata-comparator.d.ts","sourceRoot":"","sources":["../../../src/features/check/metadata-comparator.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAG3D,MAAM,WAAW,wBAAwB;IACvC,cAAc,EAAE,mBAAmB,GAAG,mBAAmB,GAAG,WAAW,CAAC;IACxE,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,UAAU,EAAE,KAAK,CAAC;QAChB,KAAK,EAAE,MAAM,CAAC;QACd,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;QACrB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;KACvB,CAAC,CAAC;CACJ;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,KAAK,CAAC;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACpD,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,MAAM,EAAE,EAAE,CAAA;KAAE,CAAC;CACxC;AAsHD;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,mBAAmB,EAC1B,MAAM,EAAE,cAAc,GACrB,wBAAwB,CAe1B"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Metadata similarity functions for comparing local vs remote reference metadata.
|
|
3
|
+
*/
|
|
4
|
+
type AuthorName = {
|
|
5
|
+
family?: string;
|
|
6
|
+
given?: string;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Check if two titles are similar using Jaccard similarity and Containment coefficient.
|
|
10
|
+
* Returns true (similar) if Jaccard >= 0.5 OR Containment >= 0.8.
|
|
11
|
+
* Returns true if either title is empty/undefined (not enough data to compare).
|
|
12
|
+
*/
|
|
13
|
+
export declare function isTitleSimilar(local: string | undefined, remote: string | undefined): boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Check if author lists are similar using family name overlap ratio.
|
|
16
|
+
* Overlap = |local_families ∩ remote_families| / |local_families|
|
|
17
|
+
* Returns true (similar) if overlap >= 0.5.
|
|
18
|
+
* Returns true if either side has no authors (not enough data).
|
|
19
|
+
*/
|
|
20
|
+
export declare function isAuthorSimilar(local: AuthorName[] | undefined, remote: AuthorName[] | undefined): boolean;
|
|
21
|
+
export {};
|
|
22
|
+
//# sourceMappingURL=metadata-similarity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadata-similarity.d.ts","sourceRoot":"","sources":["../../../src/features/check/metadata-similarity.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,KAAK,UAAU,GAAG;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAWtD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAuB7F;AAeD;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,UAAU,EAAE,GAAG,SAAS,EAC/B,MAAM,EAAE,UAAU,EAAE,GAAG,SAAS,GAC/B,OAAO,CAoBT"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Check feature types
|
|
3
3
|
*/
|
|
4
|
-
export type CheckStatus = "ok" | "retracted" | "concern" | "version_changed" | "
|
|
4
|
+
export type CheckStatus = "ok" | "retracted" | "concern" | "version_changed" | "metadata_mismatch" | "metadata_outdated";
|
|
5
5
|
export interface CheckFinding {
|
|
6
6
|
type: CheckStatus;
|
|
7
7
|
message: string;
|
|
@@ -10,6 +10,11 @@ export interface CheckFinding {
|
|
|
10
10
|
retractionDate?: string;
|
|
11
11
|
newDoi?: string;
|
|
12
12
|
updatedFields?: string[];
|
|
13
|
+
fieldDiffs?: Array<{
|
|
14
|
+
field: string;
|
|
15
|
+
local: string | null;
|
|
16
|
+
remote: string | null;
|
|
17
|
+
}>;
|
|
13
18
|
};
|
|
14
19
|
}
|
|
15
20
|
export interface CheckResult {
|