mirror of
https://github.com/OFFIS-ESC/constellation-analyzer
synced 2026-01-26 23:43:40 +00:00
feat: add PubMed and software citation format support
Extends bibliography smart import capabilities with additional citation.js plugins: - @citation-js/plugin-pubmed: Support for PubMed IDs (PMID/PMCID) - @citation-js/plugin-software-formats: Support for software citations (CFF, GitHub, npm, Zenodo) Updates smart-parser.ts to recognize and validate Zenodo DOI format (10.5281/zenodo.xxxxx). Improves input type detection for better user feedback. Includes code formatting improvements to bibliographyStore.ts for consistency. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
14ccb2da5b
commit
ef16b9d060
4 changed files with 169 additions and 86 deletions
106
package-lock.json
generated
106
package-lock.json
generated
|
|
@ -12,7 +12,9 @@
|
|||
"@citation-js/plugin-bibtex": "^0.7.18",
|
||||
"@citation-js/plugin-csl": "^0.7.18",
|
||||
"@citation-js/plugin-doi": "^0.7.18",
|
||||
"@citation-js/plugin-pubmed": "^0.3.0",
|
||||
"@citation-js/plugin-ris": "^0.7.18",
|
||||
"@citation-js/plugin-software-formats": "^0.6.1",
|
||||
"@emotion/react": "^11.11.3",
|
||||
"@emotion/styled": "^11.11.0",
|
||||
"@mui/icons-material": "^5.15.10",
|
||||
|
|
@ -377,6 +379,18 @@
|
|||
"@citation-js/core": "^0.7.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@citation-js/plugin-cff": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@citation-js/plugin-cff/-/plugin-cff-0.6.1.tgz",
|
||||
"integrity": "sha512-tLjTgsfzNOdQWGn5mNc2NAaydHnlRucSERoyAXLN7u0BQBfp7j5zwdxCmxcQD/N7hH3fpDKMG+qDzbqpJuKyNA==",
|
||||
"dependencies": {
|
||||
"@citation-js/date": "^0.5.0",
|
||||
"@citation-js/plugin-yaml": "^0.6.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@citation-js/plugin-csl": {
|
||||
"version": "0.7.18",
|
||||
"resolved": "https://registry.npmjs.org/@citation-js/plugin-csl/-/plugin-csl-0.7.18.tgz",
|
||||
|
|
@ -406,6 +420,41 @@
|
|||
"@citation-js/core": "^0.7.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@citation-js/plugin-github": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@citation-js/plugin-github/-/plugin-github-0.6.1.tgz",
|
||||
"integrity": "sha512-1ZeSgQ5AoYsa8n2acVooUeRk76oA8rLszYNBjzj5z6MPa11BZlQJ9O+Gy4tHjlImvsENLbLPx5f8/V1VHXaCfQ==",
|
||||
"dependencies": {
|
||||
"@citation-js/date": "^0.5.0",
|
||||
"@citation-js/name": "^0.4.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@citation-js/plugin-npm": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@citation-js/plugin-npm/-/plugin-npm-0.6.1.tgz",
|
||||
"integrity": "sha512-rojJA+l/p2KBpDoY+8n0YfNyQO1Aw03fQR5BN+gXD1LNAP1V+8wqvdPsaHnzPsrhrd4ZXDR7ch/Nk0yynPkJ3Q==",
|
||||
"dependencies": {
|
||||
"@citation-js/date": "^0.5.0",
|
||||
"@citation-js/name": "^0.4.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@citation-js/plugin-pubmed": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@citation-js/plugin-pubmed/-/plugin-pubmed-0.3.0.tgz",
|
||||
"integrity": "sha512-E3l83VP5UnTh6lLJaTaNBIkNgIx3U6IjDNf7j5l4geBOaOwDIhkl9X+Ss33/MMNEIMNDsBoodoMJTZ8Cq+C/ug==",
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@citation-js/core": ">=0.5.1 <=0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/@citation-js/plugin-ris": {
|
||||
"version": "0.7.18",
|
||||
"resolved": "https://registry.npmjs.org/@citation-js/plugin-ris/-/plugin-ris-0.7.18.tgz",
|
||||
|
|
@ -421,6 +470,44 @@
|
|||
"@citation-js/core": "^0.7.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@citation-js/plugin-software-formats": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@citation-js/plugin-software-formats/-/plugin-software-formats-0.6.1.tgz",
|
||||
"integrity": "sha512-BDF9rqi56K0hoTgYTVANCFVRSbWKC9V06Uap7oa8SjqCTgnHJAy8t/F3NxsyYPPG+zmRsLW9VNbcIsJOl0eu/w==",
|
||||
"dependencies": {
|
||||
"@citation-js/plugin-cff": "^0.6.1",
|
||||
"@citation-js/plugin-github": "^0.6.1",
|
||||
"@citation-js/plugin-npm": "^0.6.1",
|
||||
"@citation-js/plugin-yaml": "^0.6.1",
|
||||
"@citation-js/plugin-zenodo": "^0.6.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@citation-js/plugin-yaml": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@citation-js/plugin-yaml/-/plugin-yaml-0.6.1.tgz",
|
||||
"integrity": "sha512-XEVVks1cJTqRbjy+nmthfw/puR6NwRB3fyJWi1tX13UYXlkhP/h45nsv4zjgLLGekdcMHQvhad9MAYunOftGKA==",
|
||||
"dependencies": {
|
||||
"js-yaml": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@citation-js/plugin-zenodo": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@citation-js/plugin-zenodo/-/plugin-zenodo-0.6.1.tgz",
|
||||
"integrity": "sha512-bUybENHoZqJ6gheUqgkumjI+mu+fA2bg6VoniDmZTb7Qng9iEpi+IWEAR26/vBE0gK0EWrJjczyDW3HCwrhvVw==",
|
||||
"dependencies": {
|
||||
"@citation-js/date": "^0.5.0",
|
||||
"@citation-js/name": "^0.4.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@emotion/babel-plugin": {
|
||||
"version": "11.13.5",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.13.5.tgz",
|
||||
|
|
@ -2103,6 +2190,7 @@
|
|||
"version": "18.3.26",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.26.tgz",
|
||||
"integrity": "sha512-RFA/bURkcKzx/X9oumPG9Vp3D3JUgus/d0b67KB0t5S/raciymilkOa66olh78MUI92QLbEJevO7rvqU/kjwKA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/prop-types": "*",
|
||||
"csstype": "^3.0.2"
|
||||
|
|
@ -2436,8 +2524,7 @@
|
|||
"node_modules/argparse": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
||||
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
|
||||
"dev": true
|
||||
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
|
||||
},
|
||||
"node_modules/array-union": {
|
||||
"version": "2.1.0",
|
||||
|
|
@ -3784,7 +3871,6 @@
|
|||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
|
||||
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"argparse": "^2.0.1"
|
||||
},
|
||||
|
|
@ -5402,20 +5488,6 @@
|
|||
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/yaml": {
|
||||
"version": "2.8.1",
|
||||
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz",
|
||||
"integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"yaml": "bin.mjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14.6"
|
||||
}
|
||||
},
|
||||
"node_modules/yocto-queue": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
|
||||
|
|
|
|||
|
|
@ -14,7 +14,9 @@
|
|||
"@citation-js/plugin-bibtex": "^0.7.18",
|
||||
"@citation-js/plugin-csl": "^0.7.18",
|
||||
"@citation-js/plugin-doi": "^0.7.18",
|
||||
"@citation-js/plugin-pubmed": "^0.3.0",
|
||||
"@citation-js/plugin-ris": "^0.7.18",
|
||||
"@citation-js/plugin-software-formats": "^0.6.1",
|
||||
"@emotion/react": "^11.11.3",
|
||||
"@emotion/styled": "^11.11.0",
|
||||
"@mui/icons-material": "^5.15.10",
|
||||
|
|
|
|||
|
|
@ -1,29 +1,31 @@
|
|||
import { create } from 'zustand';
|
||||
import { create } from "zustand";
|
||||
// @ts-expect-error - citation.js doesn't have TypeScript definitions
|
||||
import { Cite } from '@citation-js/core';
|
||||
import { Cite } from "@citation-js/core";
|
||||
// Load plugins
|
||||
import '@citation-js/plugin-csl';
|
||||
import '@citation-js/plugin-doi';
|
||||
import '@citation-js/plugin-bibtex';
|
||||
import '@citation-js/plugin-ris';
|
||||
import "@citation-js/plugin-csl";
|
||||
import "@citation-js/plugin-doi";
|
||||
import "@citation-js/plugin-bibtex";
|
||||
import "@citation-js/plugin-ris";
|
||||
import "@citation-js/plugin-pubmed";
|
||||
import "@citation-js/plugin-software-formats";
|
||||
|
||||
import type {
|
||||
BibliographyReference,
|
||||
CSLReference,
|
||||
ReferenceAppMetadata,
|
||||
BibliographySettings
|
||||
} from '../types/bibliography';
|
||||
BibliographySettings,
|
||||
} from "../types/bibliography";
|
||||
|
||||
interface BibliographyStore {
|
||||
// State
|
||||
citeInstance: Cite; // The citation.js instance
|
||||
appMetadata: Record<string, ReferenceAppMetadata>; // App-specific data
|
||||
citeInstance: Cite; // The citation.js instance
|
||||
appMetadata: Record<string, ReferenceAppMetadata>; // App-specific data
|
||||
settings: BibliographySettings;
|
||||
|
||||
// Getters
|
||||
getReferences: () => BibliographyReference[]; // Merges CSL + app data
|
||||
getReferences: () => BibliographyReference[]; // Merges CSL + app data
|
||||
getReferenceById: (id: string) => BibliographyReference | undefined;
|
||||
getCSLData: () => CSLReference[]; // Raw CSL-JSON from Cite
|
||||
getCSLData: () => CSLReference[]; // Raw CSL-JSON from Cite
|
||||
|
||||
// CRUD operations (use citation.js methods)
|
||||
addReference: (ref: Partial<CSLReference>) => string;
|
||||
|
|
@ -43,18 +45,22 @@ interface BibliographyStore {
|
|||
setSettings: (settings: BibliographySettings) => void;
|
||||
|
||||
// Citation.js powered operations
|
||||
formatReference: (id: string, style?: string, format?: 'html' | 'text') => string;
|
||||
formatBibliography: (style?: string, format?: 'html' | 'text') => string;
|
||||
formatReference: (
|
||||
id: string,
|
||||
style?: string,
|
||||
format?: "html" | "text",
|
||||
) => string;
|
||||
formatBibliography: (style?: string, format?: "html" | "text") => string;
|
||||
parseInput: (input: string) => Promise<CSLReference[]>;
|
||||
exportAs: (format: 'bibtex' | 'ris' | 'json') => string;
|
||||
exportAs: (format: "bibtex" | "ris" | "json") => string;
|
||||
}
|
||||
|
||||
export const useBibliographyStore = create<BibliographyStore>((set, get) => ({
|
||||
citeInstance: new Cite([]),
|
||||
appMetadata: {},
|
||||
settings: {
|
||||
defaultStyle: 'apa',
|
||||
sortOrder: 'author',
|
||||
defaultStyle: "apa",
|
||||
sortOrder: "author",
|
||||
},
|
||||
|
||||
getReferences: () => {
|
||||
|
|
@ -62,7 +68,7 @@ export const useBibliographyStore = create<BibliographyStore>((set, get) => ({
|
|||
const metadata = get().appMetadata;
|
||||
|
||||
// Merge CSL data with app metadata
|
||||
return csl.map(ref => ({
|
||||
return csl.map((ref) => ({
|
||||
...ref,
|
||||
_app: metadata[ref.id],
|
||||
}));
|
||||
|
|
@ -70,7 +76,7 @@ export const useBibliographyStore = create<BibliographyStore>((set, get) => ({
|
|||
|
||||
getReferenceById: (id) => {
|
||||
const refs = get().getReferences();
|
||||
return refs.find(ref => ref.id === id);
|
||||
return refs.find((ref) => ref.id === id);
|
||||
},
|
||||
|
||||
getCSLData: () => {
|
||||
|
|
@ -81,7 +87,8 @@ export const useBibliographyStore = create<BibliographyStore>((set, get) => ({
|
|||
const { citeInstance } = get();
|
||||
|
||||
// Generate ID if not provided
|
||||
const id = ref.id || `ref-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
|
||||
const id =
|
||||
ref.id || `ref-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
|
||||
const fullRef = { ...ref, id };
|
||||
|
||||
// Use citation.js add() method
|
||||
|
|
@ -89,7 +96,7 @@ export const useBibliographyStore = create<BibliographyStore>((set, get) => ({
|
|||
|
||||
// Add app metadata
|
||||
const now = new Date().toISOString();
|
||||
set(state => ({
|
||||
set((state) => ({
|
||||
appMetadata: {
|
||||
...state.appMetadata,
|
||||
[id]: {
|
||||
|
|
@ -109,15 +116,15 @@ export const useBibliographyStore = create<BibliographyStore>((set, get) => ({
|
|||
const data = citeInstance.data as CSLReference[];
|
||||
|
||||
// Find and update the reference
|
||||
const updatedData = data.map(ref =>
|
||||
ref.id === id ? { ...ref, ...updates } : ref
|
||||
const updatedData = data.map((ref) =>
|
||||
ref.id === id ? { ...ref, ...updates } : ref,
|
||||
);
|
||||
|
||||
// Use citation.js set() method to replace all data
|
||||
citeInstance.set(updatedData);
|
||||
|
||||
// Update metadata timestamp
|
||||
set(state => ({
|
||||
set((state) => ({
|
||||
appMetadata: {
|
||||
...state.appMetadata,
|
||||
[id]: {
|
||||
|
|
@ -133,11 +140,11 @@ export const useBibliographyStore = create<BibliographyStore>((set, get) => ({
|
|||
const data = citeInstance.data as CSLReference[];
|
||||
|
||||
// Remove from citation.js
|
||||
const filteredData = data.filter(ref => ref.id !== id);
|
||||
const filteredData = data.filter((ref) => ref.id !== id);
|
||||
citeInstance.set(filteredData);
|
||||
|
||||
// Remove metadata
|
||||
set(state => {
|
||||
set((state) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const { [id]: _removed, ...rest } = state.appMetadata;
|
||||
return { appMetadata: rest };
|
||||
|
|
@ -146,7 +153,7 @@ export const useBibliographyStore = create<BibliographyStore>((set, get) => ({
|
|||
|
||||
duplicateReference: (id) => {
|
||||
const original = get().getReferenceById(id);
|
||||
if (!original) return '';
|
||||
if (!original) return "";
|
||||
|
||||
const newId = `ref-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
|
||||
const duplicate = {
|
||||
|
|
@ -173,7 +180,7 @@ export const useBibliographyStore = create<BibliographyStore>((set, get) => ({
|
|||
const metadata: Record<string, ReferenceAppMetadata> = {};
|
||||
const now = new Date().toISOString();
|
||||
|
||||
refs.forEach(ref => {
|
||||
refs.forEach((ref) => {
|
||||
metadata[ref.id] = {
|
||||
id: ref.id,
|
||||
tags: [],
|
||||
|
|
@ -193,9 +200,9 @@ export const useBibliographyStore = create<BibliographyStore>((set, get) => ({
|
|||
|
||||
// Add metadata for new references
|
||||
const now = new Date().toISOString();
|
||||
set(state => {
|
||||
set((state) => {
|
||||
const newMetadata = { ...state.appMetadata };
|
||||
refs.forEach(ref => {
|
||||
refs.forEach((ref) => {
|
||||
if (!newMetadata[ref.id]) {
|
||||
newMetadata[ref.id] = {
|
||||
id: ref.id,
|
||||
|
|
@ -210,12 +217,12 @@ export const useBibliographyStore = create<BibliographyStore>((set, get) => ({
|
|||
},
|
||||
|
||||
clearAll: () => {
|
||||
get().citeInstance.reset(); // citation.js method to clear all data
|
||||
get().citeInstance.reset(); // citation.js method to clear all data
|
||||
set({ appMetadata: {} });
|
||||
},
|
||||
|
||||
updateMetadata: (id, updates) => {
|
||||
set(state => ({
|
||||
set((state) => ({
|
||||
appMetadata: {
|
||||
...state.appMetadata,
|
||||
[id]: {
|
||||
|
|
@ -229,34 +236,34 @@ export const useBibliographyStore = create<BibliographyStore>((set, get) => ({
|
|||
|
||||
setSettings: (settings) => set({ settings }),
|
||||
|
||||
formatReference: (id, style, format = 'html') => {
|
||||
formatReference: (id, style, format = "html") => {
|
||||
const { citeInstance, settings } = get();
|
||||
const styleToUse = style || settings.defaultStyle;
|
||||
|
||||
// Find the reference
|
||||
const ref = (citeInstance.data as CSLReference[]).find(r => r.id === id);
|
||||
if (!ref) return '';
|
||||
const ref = (citeInstance.data as CSLReference[]).find((r) => r.id === id);
|
||||
if (!ref) return "";
|
||||
|
||||
// Create temporary Cite instance for single reference
|
||||
const cite = new Cite(ref);
|
||||
|
||||
// Use citation.js format() method
|
||||
return cite.format('bibliography', {
|
||||
return cite.format("bibliography", {
|
||||
format: format,
|
||||
template: styleToUse,
|
||||
lang: 'en-US',
|
||||
lang: "en-US",
|
||||
});
|
||||
},
|
||||
|
||||
formatBibliography: (style, format = 'html') => {
|
||||
formatBibliography: (style, format = "html") => {
|
||||
const { citeInstance, settings } = get();
|
||||
const styleToUse = style || settings.defaultStyle;
|
||||
|
||||
// Use citation.js format() method on entire instance
|
||||
return citeInstance.format('bibliography', {
|
||||
return citeInstance.format("bibliography", {
|
||||
format: format,
|
||||
template: styleToUse,
|
||||
lang: 'en-US',
|
||||
lang: "en-US",
|
||||
});
|
||||
},
|
||||
|
||||
|
|
@ -267,8 +274,8 @@ export const useBibliographyStore = create<BibliographyStore>((set, get) => ({
|
|||
const cite = await Cite.async(input);
|
||||
return cite.data as CSLReference[];
|
||||
} catch (error) {
|
||||
console.error('Failed to parse input:', error);
|
||||
throw new Error('Could not parse citation data');
|
||||
console.error("Failed to parse input:", error);
|
||||
throw new Error("Could not parse citation data");
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -277,14 +284,14 @@ export const useBibliographyStore = create<BibliographyStore>((set, get) => ({
|
|||
|
||||
// Use citation.js format() method
|
||||
switch (format) {
|
||||
case 'bibtex':
|
||||
return citeInstance.format('bibtex');
|
||||
case 'ris':
|
||||
return citeInstance.format('ris');
|
||||
case 'json':
|
||||
case "bibtex":
|
||||
return citeInstance.format("bibtex");
|
||||
case "ris":
|
||||
return citeInstance.format("ris");
|
||||
case "json":
|
||||
return JSON.stringify(citeInstance.data, null, 2);
|
||||
default:
|
||||
return '';
|
||||
return "";
|
||||
}
|
||||
},
|
||||
}));
|
||||
|
|
@ -295,8 +302,8 @@ export const clearBibliographyForDocumentSwitch = () => {
|
|||
citeInstance: new Cite([]),
|
||||
appMetadata: {},
|
||||
settings: {
|
||||
defaultStyle: 'apa',
|
||||
sortOrder: 'author',
|
||||
defaultStyle: "apa",
|
||||
sortOrder: "author",
|
||||
},
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,17 +1,21 @@
|
|||
// @ts-expect-error - citation.js doesn't have TypeScript definitions
|
||||
import { Cite } from '@citation-js/core';
|
||||
import type { CSLReference } from '../../types/bibliography';
|
||||
import { Cite } from "@citation-js/core";
|
||||
import type { CSLReference } from "../../types/bibliography";
|
||||
|
||||
/**
|
||||
* Parse any citation input using citation.js
|
||||
* Handles: DOI, URL, BibTeX, RIS, ISBN, PubMed ID, etc.
|
||||
*/
|
||||
export const parseSmartInput = async (input: string): Promise<CSLReference[]> => {
|
||||
export const parseSmartInput = async (
|
||||
input: string,
|
||||
): Promise<CSLReference[]> => {
|
||||
try {
|
||||
const cite = await Cite.async(input);
|
||||
return cite.data as CSLReference[];
|
||||
} catch (error) {
|
||||
throw new Error(`Could not parse input: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
||||
throw new Error(
|
||||
`Could not parse input: ${error instanceof Error ? error.message : "Unknown error"}`,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -46,9 +50,8 @@ export const isValidCitationInput = (input: string): boolean => {
|
|||
// Wikidata ID (Q followed by numbers)
|
||||
if (/^(wikidata:)?Q\d+$/i.test(trimmed)) return true;
|
||||
|
||||
// Zenodo ID or URL
|
||||
if (/^zenodo\.\d+$/i.test(trimmed)) return true;
|
||||
if (/zenodo\.org\/record\/\d+/i.test(trimmed)) return true;
|
||||
// Zenodo DOI (10.5281/zenodo.xxxxx)
|
||||
if (/^10\.5281\/zenodo\.\d+/i.test(trimmed)) return true;
|
||||
|
||||
// CFF (Citation File Format) - YAML-based
|
||||
if (/^cff-version:/m.test(trimmed)) return true;
|
||||
|
|
@ -62,17 +65,16 @@ export const isValidCitationInput = (input: string): boolean => {
|
|||
export const getInputTypeHint = (input: string): string => {
|
||||
const trimmed = input.trim();
|
||||
|
||||
if (/^10\.\d{4,}\//.test(trimmed)) return 'DOI';
|
||||
if (/zenodo\.org\/record\/\d+/i.test(trimmed)) return 'Zenodo URL';
|
||||
if (/^zenodo\.\d+$/i.test(trimmed)) return 'Zenodo ID';
|
||||
if (/^https?:\/\//.test(trimmed)) return 'URL';
|
||||
if (/^@\w+\{/.test(trimmed)) return 'BibTeX';
|
||||
if (/^TY\s+-\s+/m.test(trimmed)) return 'RIS Format';
|
||||
if (/^PMID:/i.test(trimmed)) return 'PubMed ID (PMID)';
|
||||
if (/^PMC\d+/i.test(trimmed)) return 'PubMed Central ID (PMCID)';
|
||||
if (/^ISBN/i.test(trimmed)) return 'ISBN';
|
||||
if (/^(wikidata:)?Q\d+$/i.test(trimmed)) return 'Wikidata ID';
|
||||
if (/^cff-version:/m.test(trimmed)) return 'Citation File Format (CFF)';
|
||||
if (/^10\.5281\/zenodo\.\d+/i.test(trimmed)) return "Zenodo DOI";
|
||||
if (/^10\.\d{4,}\//.test(trimmed)) return "DOI";
|
||||
if (/^https?:\/\//.test(trimmed)) return "URL";
|
||||
if (/^@\w+\{/.test(trimmed)) return "BibTeX";
|
||||
if (/^TY\s+-\s+/m.test(trimmed)) return "RIS Format";
|
||||
if (/^PMID:/i.test(trimmed)) return "PubMed ID (PMID)";
|
||||
if (/^PMC\d+/i.test(trimmed)) return "PubMed Central ID (PMCID)";
|
||||
if (/^ISBN/i.test(trimmed)) return "ISBN";
|
||||
if (/^(wikidata:)?Q\d+$/i.test(trimmed)) return "Wikidata ID";
|
||||
if (/^cff-version:/m.test(trimmed)) return "Citation File Format (CFF)";
|
||||
|
||||
return 'Unknown';
|
||||
return "Unknown";
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue