constellation-analyzer/src/utils/bibliography/smart-parser.ts
Jan-Henrik Bruhn 36f44d61ac feat: add comprehensive bibliography and citation system
Implements complete bibliography management with citation assignment to
nodes and edges, following CSL-JSON standard.

Features:
- Bibliography store with Zustand and citation.js integration
- Smart import supporting DOI, BibTeX, PubMed ID, and URLs
- Manual entry and editing forms for references
- Citation selector with autocomplete text field interface
- History tracking for undo/redo support
- Workspace integration for import/export
- Support for multiple reference types including interview and other
- Description/notes field for additional reference information

Components:
- CitationSelector: autocomplete UI for selecting citations
- BibliographyConfigModal: main bibliography management interface
- QuickAddReferenceForm: smart import and manual entry
- EditReferenceInline: full reference editing form
- ReferenceManagementList: list view with citation counts

Integration:
- NodeEditorPanel: citation assignment to actors
- EdgeEditorPanel: citation assignment to relations
- MenuBar: bibliography menu item
- WorkspaceStore: bibliography persistence in workspace files

Technical details:
- CSL-JSON format for bibliographic data
- citation.js for parsing and formatting
- TypeScript with proper type definitions
- Debounced updates for performance
- Citation count tracking across graph elements

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-17 14:43:55 +02:00

56 lines
1.6 KiB
TypeScript

// @ts-expect-error - citation.js doesn't have TypeScript definitions
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[]> => {
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'}`);
}
};
/**
* Check if input looks like it can be parsed
*/
export const isValidCitationInput = (input: string): boolean => {
const trimmed = input.trim();
// DOI patterns
if (/^(https?:\/\/)?(dx\.)?doi\.org\/10\.\d{4,}/i.test(trimmed)) return true;
if (/^10\.\d{4,}\/.+/.test(trimmed)) return true;
// URL patterns
if (/^https?:\/\/.+/.test(trimmed)) return true;
// BibTeX patterns
if (/^@\w+\{/.test(trimmed)) return true;
// PubMed ID
if (/^PMID:\s*\d+/i.test(trimmed)) return true;
// ISBN
if (/^ISBN[:\s]*[\d-]+/i.test(trimmed)) return true;
return false;
};
/**
* Get input type hint for user
*/
export const getInputTypeHint = (input: string): string => {
const trimmed = input.trim();
if (/^10\.\d{4,}\//.test(trimmed)) return 'DOI';
if (/^https?:\/\//.test(trimmed)) return 'URL';
if (/^@\w+\{/.test(trimmed)) return 'BibTeX';
if (/^PMID:/i.test(trimmed)) return 'PubMed ID';
if (/^ISBN/i.test(trimmed)) return 'ISBN';
return 'Unknown';
};