mirror of
https://github.com/OFFIS-ESC/constellation-analyzer
synced 2026-01-27 07:43:41 +00:00
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>
56 lines
1.6 KiB
TypeScript
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';
|
|
};
|