@ncukondo/reference-manager 0.22.2 → 0.22.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/dist/chunks/{action-menu-R-QKMCZJ.js → action-menu-CKMhb5fv.js} +3 -3
  2. package/dist/chunks/{action-menu-R-QKMCZJ.js.map → action-menu-CKMhb5fv.js.map} +1 -1
  3. package/dist/chunks/{format-uBMjeVAZ.js → format-B2MDhuHt.js} +2 -2
  4. package/dist/chunks/{format-uBMjeVAZ.js.map → format-B2MDhuHt.js.map} +1 -1
  5. package/dist/chunks/{index-CXZ_Trjb.js → index-4607sQqe.js} +3 -3
  6. package/dist/chunks/index-4607sQqe.js.map +1 -0
  7. package/dist/chunks/{index-DFhoO9RA.js → index-CNr_FIip.js} +20 -4
  8. package/dist/chunks/index-CNr_FIip.js.map +1 -0
  9. package/dist/chunks/{index-DxjW_BKA.js → index-CYp8N4gu.js} +62 -40
  10. package/dist/chunks/index-CYp8N4gu.js.map +1 -0
  11. package/dist/chunks/{index-B7NyGOm6.js → index-DjQiOVp_.js} +4 -4
  12. package/dist/chunks/{index-B7NyGOm6.js.map → index-DjQiOVp_.js.map} +1 -1
  13. package/dist/chunks/{loader-BZgpKsTG.js → loader-CJB3-kI5.js} +36 -14
  14. package/dist/chunks/loader-CJB3-kI5.js.map +1 -0
  15. package/dist/chunks/{reference-select-Cpq_Q4f6.js → reference-select-dvLqdttM.js} +3 -3
  16. package/dist/chunks/{reference-select-Cpq_Q4f6.js.map → reference-select-dvLqdttM.js.map} +1 -1
  17. package/dist/chunks/{style-select-CQIqnmWS.js → style-select-BpKQvCBz.js} +3 -3
  18. package/dist/chunks/{style-select-CQIqnmWS.js.map → style-select-BpKQvCBz.js.map} +1 -1
  19. package/dist/cli/commands/fulltext.d.ts +4 -0
  20. package/dist/cli/commands/fulltext.d.ts.map +1 -1
  21. package/dist/cli/index.d.ts.map +1 -1
  22. package/dist/cli.js +1 -1
  23. package/dist/config/defaults.d.ts.map +1 -1
  24. package/dist/config/env-override.d.ts.map +1 -1
  25. package/dist/config/key-parser.d.ts.map +1 -1
  26. package/dist/config/loader.d.ts.map +1 -1
  27. package/dist/config/schema.d.ts +22 -0
  28. package/dist/config/schema.d.ts.map +1 -1
  29. package/dist/features/operations/fulltext/get.d.ts +2 -0
  30. package/dist/features/operations/fulltext/get.d.ts.map +1 -1
  31. package/dist/features/operations/fulltext/open.d.ts +2 -0
  32. package/dist/features/operations/fulltext/open.d.ts.map +1 -1
  33. package/dist/index.js +1 -1
  34. package/dist/mcp/tools/fulltext.d.ts.map +1 -1
  35. package/dist/server.js +1 -1
  36. package/package.json +1 -1
  37. package/dist/chunks/index-CXZ_Trjb.js.map +0 -1
  38. package/dist/chunks/index-DFhoO9RA.js.map +0 -1
  39. package/dist/chunks/index-DxjW_BKA.js.map +0 -1
  40. package/dist/chunks/loader-BZgpKsTG.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-CNr_FIip.js","sources":["../../src/features/attachments/filename.ts","../../src/features/attachments/types.ts","../../src/utils/path.ts","../../src/features/attachments/directory.ts","../../src/features/attachments/directory-manager.ts","../../src/features/operations/attachments/add.ts","../../src/features/operations/fulltext-adapter/fulltext-adapter.ts","../../src/features/operations/fulltext/attach.ts","../../src/features/operations/fulltext/get.ts","../../node_modules/@ncukondo/academic-fulltext/dist/discovery/arxiv.js","../../node_modules/@ncukondo/academic-fulltext/dist/discovery/core.js","../../node_modules/@ncukondo/academic-fulltext/dist/discovery/pmc.js","../../node_modules/@ncukondo/academic-fulltext/dist/discovery/unpaywall.js","../../node_modules/@ncukondo/academic-fulltext/dist/discovery/index.js","../../node_modules/@ncukondo/academic-fulltext/dist/download/downloader.js","../../node_modules/@ncukondo/academic-fulltext/dist/download/pmc-xml.js","../../node_modules/fast-xml-parser/src/util.js","../../node_modules/fast-xml-parser/src/validator.js","../../node_modules/fast-xml-parser/src/xmlparser/OptionsBuilder.js","../../node_modules/fast-xml-parser/src/xmlparser/xmlNode.js","../../node_modules/fast-xml-parser/src/xmlparser/DocTypeReader.js","../../node_modules/strnum/strnum.js","../../node_modules/fast-xml-parser/src/ignoreAttributes.js","../../node_modules/fast-xml-parser/src/xmlparser/OrderedObjParser.js","../../node_modules/fast-xml-parser/src/xmlparser/node2json.js","../../node_modules/fast-xml-parser/src/xmlparser/XMLParser.js","../../node_modules/@ncukondo/academic-fulltext/dist/convert/jats-parser.js","../../node_modules/@ncukondo/academic-fulltext/dist/convert/markdown-writer.js","../../node_modules/@ncukondo/academic-fulltext/dist/convert/index.js","../../src/features/operations/fulltext/discover.ts","../../src/features/operations/fulltext/fetch.ts","../../src/features/operations/fulltext/convert.ts","../../src/features/format/citation-fallback.ts","../../src/features/format/citation-csl.ts","../../src/features/pagination/sorter.ts","../../src/features/pagination/paginate.ts","../../src/config/csl-styles.ts","../../src/features/operations/remove.ts","../../src/features/import/cache.ts","../../src/features/import/normalizer.ts","../../src/features/import/detector.ts","../../src/features/import/rate-limiter.ts","../../src/features/import/fetcher.ts","../../src/features/import/parser.ts","../../src/features/import/importer.ts","../../src/features/operations/add.ts","../../src/server/routes/add.ts","../../src/features/operations/cite.ts","../../src/server/routes/cite.ts","../../src/server/routes/health.ts","../../src/features/operations/list.ts","../../src/server/routes/list.ts","../../src/features/operations/update.ts","../../src/server/routes/references.ts","../../src/features/operations/search.ts","../../src/server/routes/search.ts","../../src/server/index.ts"],"sourcesContent":["import path from \"node:path\";\n\n/**\n * Filename utilities for attachments\n *\n * File format: {role}[-{label-slug}].{ext}\n * Examples:\n * - fulltext.pdf\n * - supplement-table-s1.xlsx\n * - notes-reading-analysis.md\n */\n\ninterface ParsedFilename {\n role: string;\n ext: string;\n label?: string;\n}\n\n/**\n * Convert a human-readable label to a filesystem-safe slug\n */\nexport function slugifyLabel(label: string): string {\n return label\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\") // Replace non-alphanumeric with hyphen\n .replace(/-+/g, \"-\") // Collapse multiple hyphens\n .replace(/^-|-$/g, \"\"); // Trim leading/trailing hyphens\n}\n\n/**\n * Generate filename from role, extension, and optional label\n */\nexport function generateFilename(role: string, ext: string, label?: string): string {\n if (label) {\n const slug = slugifyLabel(label);\n return `${role}-${slug}.${ext}`;\n }\n return `${role}.${ext}`;\n}\n\n/**\n * Parse filename to extract role, extension, and label\n *\n * Returns null for empty filenames\n */\nexport function parseFilename(filename: string): ParsedFilename | null {\n if (!filename) {\n return null;\n }\n\n const ext = path.extname(filename);\n const extWithoutDot = ext.startsWith(\".\") ? ext.slice(1) : ext;\n const basename = ext ? filename.slice(0, -ext.length) : filename;\n\n // Split basename by first hyphen to get role and potential label\n const firstHyphenIndex = basename.indexOf(\"-\");\n\n if (firstHyphenIndex === -1) {\n // No hyphen: just role, no label\n return {\n role: basename,\n ext: extWithoutDot,\n };\n }\n\n const role = basename.slice(0, firstHyphenIndex);\n const label = basename.slice(firstHyphenIndex + 1);\n\n if (label) {\n return {\n role,\n ext: extWithoutDot,\n label,\n };\n }\n\n return {\n role,\n ext: extWithoutDot,\n };\n}\n","import path from \"node:path\";\n\n/**\n * Attachment file metadata stored in reference's custom field\n */\nexport interface AttachmentFile {\n /** Filename without path (e.g., \"fulltext.pdf\") */\n filename: string;\n /** Role identifier (e.g., \"fulltext\", \"supplement\", \"notes\") */\n role: string;\n /** Human-readable label (optional) */\n label?: string;\n}\n\n/**\n * Attachments container stored in reference's custom.attachments field\n */\nexport interface Attachments {\n /** Directory name relative to attachments base (e.g., \"Smith-2024-PMID12345678-123e4567\") */\n directory: string;\n /** List of attached files */\n files: AttachmentFile[];\n}\n\n/**\n * Reserved role identifiers with special constraints\n */\nexport const RESERVED_ROLES = [\"fulltext\", \"supplement\", \"notes\", \"draft\"] as const;\n\nexport type ReservedRole = (typeof RESERVED_ROLES)[number];\n\n/**\n * Check if a role is a reserved role\n */\nexport function isReservedRole(role: string): role is ReservedRole {\n return RESERVED_ROLES.includes(role as ReservedRole);\n}\n\n/**\n * Get file extension from filename (without leading dot)\n */\nexport function getExtension(filename: string): string {\n const ext = path.extname(filename);\n return ext.startsWith(\".\") ? ext.slice(1).toLowerCase() : ext.toLowerCase();\n}\n\n/**\n * Check if fulltext files satisfy the constraint: max 2 files (1 PDF + 1 Markdown)\n */\nexport function isValidFulltextFiles(files: AttachmentFile[]): boolean {\n const fulltextFiles = files.filter((f) => f.role === \"fulltext\");\n\n if (fulltextFiles.length > 2) {\n return false;\n }\n\n if (fulltextFiles.length <= 1) {\n return true;\n }\n\n // Exactly 2 files: must be 1 PDF and 1 Markdown\n const extensions = fulltextFiles.map((f) => getExtension(f.filename));\n const pdfCount = extensions.filter((ext) => ext === \"pdf\").length;\n const mdCount = extensions.filter((ext) => ext === \"md\").length;\n\n return pdfCount === 1 && mdCount === 1;\n}\n","/**\n * Cross-platform path utilities\n *\n * IMPORTANT: Path handling conventions in this codebase:\n *\n * 1. File system operations (fs.readFile, fs.writeFile, etc.)\n * → Use NATIVE paths (path.join result as-is)\n *\n * 2. User-facing output (CLI output, API responses, result.path)\n * → Use NORMALIZED paths (forward slashes via normalizePathForOutput)\n *\n * 3. Test expectations for output paths\n * → Use NORMALIZED paths to match actual output\n */\n\n/**\n * Normalize path separators to forward slashes for consistent cross-platform output.\n *\n * Use this function ONLY for user-facing output, NOT for file system operations.\n *\n * @example\n * // In operation result\n * return { success: true, path: normalizePathForOutput(filePath) };\n *\n * // NOT for fs operations - use native path directly\n * await fs.readFile(filePath); // filePath from path.join, NOT normalized\n */\nexport function normalizePathForOutput(p: string): string {\n return p.replace(/\\\\/g, \"/\");\n}\n","/**\n * Directory name utilities for attachments\n *\n * Directory format: {id}[-PMID{pmid}]-{uuid-prefix}\n * Examples:\n * - With PMID: Smith-2024-PMID12345678-123e4567\n * - Without PMID: Smith-2024-123e4567\n */\n\ninterface ReferenceForDirectory {\n id: string;\n PMID?: string;\n custom?: { uuid?: string };\n}\n\ninterface ParsedDirectoryName {\n id: string;\n pmid?: string;\n uuidPrefix: string;\n}\n\n/**\n * Extract first 8 characters of UUID as prefix\n */\nexport function extractUuidPrefix(uuid: string): string {\n // Remove dashes and take first 8 chars\n const normalized = uuid.replace(/-/g, \"\");\n return normalized.slice(0, 8);\n}\n\n/**\n * Generate directory name for a reference\n */\nexport function generateDirectoryName(ref: ReferenceForDirectory): string {\n const uuid = ref.custom?.uuid;\n if (!uuid) {\n throw new Error(\"Reference must have custom.uuid\");\n }\n\n const uuidPrefix = extractUuidPrefix(uuid);\n const pmid = ref.PMID?.trim();\n\n if (pmid) {\n return `${ref.id}-PMID${pmid}-${uuidPrefix}`;\n }\n return `${ref.id}-${uuidPrefix}`;\n}\n\n/**\n * Parse directory name to extract components\n *\n * Returns null if the directory name doesn't match expected format\n */\nexport function parseDirectoryName(name: string): ParsedDirectoryName | null {\n if (!name) {\n return null;\n }\n\n // Pattern: {id}-PMID{pmid}-{uuidPrefix} or {id}-{uuidPrefix}\n // uuidPrefix is always 8 hex characters at the end\n const uuidPrefixPattern = /^[0-9a-f]{8}$/i;\n\n // Split by '-' and check last part is uuid prefix\n const parts = name.split(\"-\");\n if (parts.length < 2) {\n return null;\n }\n\n const lastPart = parts[parts.length - 1];\n if (!lastPart || !uuidPrefixPattern.test(lastPart)) {\n return null;\n }\n\n const uuidPrefix = lastPart;\n\n // Check for PMID pattern in second-to-last position\n const remainingParts = parts.slice(0, -1);\n const lastRemaining = remainingParts[remainingParts.length - 1];\n const pmidMatch = lastRemaining?.match(/^PMID(\\d+)$/);\n\n if (pmidMatch?.[1]) {\n // Has PMID\n const id = remainingParts.slice(0, -1).join(\"-\");\n if (!id) {\n return null;\n }\n return {\n id,\n pmid: pmidMatch[1],\n uuidPrefix,\n };\n }\n\n // No PMID\n const id = remainingParts.join(\"-\");\n if (!id) {\n return null;\n }\n return {\n id,\n uuidPrefix,\n };\n}\n","import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { normalizePathForOutput } from \"../../utils/path.js\";\nimport { generateDirectoryName } from \"./directory.js\";\nimport type { Attachments } from \"./types.js\";\n\n/**\n * Reference with attachment-related fields\n */\ninterface ReferenceForAttachments {\n id: string;\n PMID?: string;\n custom?: {\n uuid?: string;\n attachments?: Attachments;\n };\n}\n\n/**\n * Get the full directory path for a reference's attachments\n *\n * Uses existing directory name from metadata if available,\n * otherwise generates a new one.\n */\nexport function getDirectoryPath(ref: ReferenceForAttachments, baseDir: string): string {\n const existingDir = ref.custom?.attachments?.directory;\n if (existingDir) {\n // Normalize to forward slashes for consistent cross-platform output\n return normalizePathForOutput(path.join(baseDir, existingDir));\n }\n\n // Generate new directory name\n const dirName = generateDirectoryName(ref as Parameters<typeof generateDirectoryName>[0]);\n // Normalize to forward slashes for consistent cross-platform output\n return normalizePathForOutput(path.join(baseDir, dirName));\n}\n\n/**\n * Ensure the attachments directory exists for a reference\n *\n * Creates the directory if it doesn't exist.\n * Returns the full directory path.\n */\nexport async function ensureDirectory(\n ref: ReferenceForAttachments,\n baseDir: string\n): Promise<string> {\n const dirPath = getDirectoryPath(ref, baseDir);\n\n try {\n await fs.mkdir(dirPath, { recursive: true });\n } catch (error) {\n // Ignore if directory already exists\n if ((error as NodeJS.ErrnoException).code !== \"EEXIST\") {\n throw error;\n }\n }\n\n return dirPath;\n}\n\n/**\n * Delete a directory if it's empty\n *\n * Does nothing if the directory is not empty or doesn't exist.\n */\nexport async function deleteDirectoryIfEmpty(dirPath: string): Promise<void> {\n try {\n const files = await fs.readdir(dirPath);\n if (files.length === 0) {\n await fs.rmdir(dirPath);\n }\n } catch (error) {\n // Ignore if directory doesn't exist\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") {\n throw error;\n }\n }\n}\n\n/**\n * Rename a directory\n *\n * Does nothing if the paths are the same or old directory doesn't exist.\n */\nexport async function renameDirectory(oldPath: string, newPath: string): Promise<void> {\n if (oldPath === newPath) {\n return;\n }\n\n try {\n await fs.rename(oldPath, newPath);\n } catch (error) {\n // Ignore if old directory doesn't exist\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") {\n throw error;\n }\n }\n}\n","/**\n * Attachment add operation\n */\n\nimport { copyFile, rename, stat } from \"node:fs/promises\";\nimport { extname, join } from \"node:path\";\nimport type { CslItem } from \"../../../core/csl-json/types.js\";\nimport type { ILibrary, IdentifierType } from \"../../../core/library-interface.js\";\nimport { ensureDirectory } from \"../../attachments/directory-manager.js\";\nimport { generateDirectoryName } from \"../../attachments/directory.js\";\nimport { generateFilename } from \"../../attachments/filename.js\";\nimport {\n type AttachmentFile,\n type Attachments,\n getExtension,\n isValidFulltextFiles,\n} from \"../../attachments/types.js\";\n\n/**\n * Options for addAttachment operation\n */\nexport interface AddAttachmentOptions {\n /** Reference identifier (id or uuid) */\n identifier: string;\n /** Path to the file to attach */\n filePath: string;\n /** Role for the attachment */\n role: string;\n /** Human-readable label (optional) */\n label?: string;\n /** Move file instead of copy */\n move?: boolean;\n /** Force overwrite existing file */\n force?: boolean;\n /** Identifier type */\n idType?: IdentifierType;\n /** Base directory for attachments */\n attachmentsDirectory: string;\n}\n\n/**\n * Result of addAttachment operation\n */\nexport interface AddAttachmentResult {\n success: boolean;\n filename?: string;\n directory?: string;\n overwritten?: boolean;\n existingFile?: string;\n requiresConfirmation?: boolean;\n error?: string;\n}\n\n/**\n * Reference with attachment-related fields\n */\ninterface ReferenceForAttachments {\n id: string;\n PMID?: string;\n custom?: {\n uuid?: string;\n attachments?: Attachments;\n };\n}\n\n/**\n * Check if source file exists\n */\nasync function checkSourceFile(filePath: string): Promise<string | null> {\n try {\n await stat(filePath);\n return null;\n } catch {\n return `Source file not found: ${filePath}`;\n }\n}\n\n/**\n * Validate fulltext constraints\n */\nfunction validateFulltextConstraint(\n existingFiles: AttachmentFile[],\n newFile: AttachmentFile\n): string | null {\n if (newFile.role !== \"fulltext\") {\n return null;\n }\n\n const newExt = getExtension(newFile.filename);\n const existingFulltexts = existingFiles.filter((f) => f.role === \"fulltext\");\n\n // Check if same format already exists\n for (const existing of existingFulltexts) {\n const existingExt = getExtension(existing.filename);\n if (existingExt === newExt) {\n return `A fulltext ${newExt.toUpperCase()} already exists. Use --force to overwrite.`;\n }\n }\n\n // Check total count constraint\n const testFiles = [...existingFiles, newFile];\n if (!isValidFulltextFiles(testFiles)) {\n return \"fulltext role allows max 2 files (1 PDF + 1 Markdown)\";\n }\n\n return null;\n}\n\n/**\n * Check if file with same name already exists\n */\nfunction findExistingFile(files: AttachmentFile[], filename: string): AttachmentFile | undefined {\n return files.find((f) => f.filename === filename);\n}\n\n/**\n * Copy or move file to destination\n */\nasync function copyOrMoveFile(\n sourcePath: string,\n destPath: string,\n move: boolean\n): Promise<string | null> {\n try {\n if (move) {\n await rename(sourcePath, destPath);\n } else {\n await copyFile(sourcePath, destPath);\n }\n return null;\n } catch (error) {\n return `Failed to ${move ? \"move\" : \"copy\"} file: ${error instanceof Error ? error.message : String(error)}`;\n }\n}\n\n/**\n * Update library with new attachment metadata\n */\nasync function updateAttachmentMetadata(\n library: ILibrary,\n item: CslItem,\n updatedAttachments: Attachments\n): Promise<void> {\n await library.update(item.id, {\n custom: {\n ...item.custom,\n attachments: updatedAttachments,\n },\n } as Partial<CslItem>);\n}\n\n/**\n * Build updated files list\n */\nfunction buildUpdatedFiles(\n existingFiles: AttachmentFile[],\n newFile: AttachmentFile,\n existingFile: AttachmentFile | undefined\n): AttachmentFile[] {\n if (existingFile) {\n return existingFiles.map((f) => (f.filename === newFile.filename ? newFile : f));\n }\n return [...existingFiles, newFile];\n}\n\n/**\n * Add an attachment to a reference\n */\nexport async function addAttachment(\n library: ILibrary,\n options: AddAttachmentOptions\n): Promise<AddAttachmentResult> {\n const {\n identifier,\n filePath,\n role,\n label,\n move = false,\n force = false,\n idType = \"id\",\n attachmentsDirectory,\n } = options;\n\n // Find reference\n const item = await library.find(identifier, { idType });\n if (!item) {\n return { success: false, error: `Reference '${identifier}' not found` };\n }\n\n // Check UUID\n const uuid = (item as CslItem).custom?.uuid;\n if (!uuid) {\n return { success: false, error: \"Reference has no UUID. Cannot create attachment directory.\" };\n }\n\n // Check source file exists\n const sourceError = await checkSourceFile(filePath);\n if (sourceError) {\n return { success: false, error: sourceError };\n }\n\n // Generate filename\n const ext = extname(filePath).slice(1).toLowerCase();\n const filename = generateFilename(role, ext, label);\n\n // Get existing attachments\n const existingAttachments = (item as CslItem).custom?.attachments as Attachments | undefined;\n const existingFiles = existingAttachments?.files ?? [];\n\n // Create new attachment file entry\n const newFile: AttachmentFile = {\n filename,\n role,\n ...(label && { label }),\n };\n\n // Check if file with same name exists\n const existingFile = findExistingFile(existingFiles, filename);\n\n // Validate fulltext constraints first (provides better error messages)\n if (!existingFile || !force) {\n const constraintError = validateFulltextConstraint(existingFiles, newFile);\n if (constraintError) {\n return { success: false, error: constraintError };\n }\n }\n\n // Check if file with same name exists (non-fulltext case)\n if (existingFile && !force) {\n return {\n success: false,\n existingFile: filename,\n requiresConfirmation: true,\n };\n }\n\n // Ensure directory exists\n const ref = item as ReferenceForAttachments;\n const dirPath = await ensureDirectory(ref, attachmentsDirectory);\n const dirName =\n existingAttachments?.directory ??\n generateDirectoryName(ref as Parameters<typeof generateDirectoryName>[0]);\n\n // Copy or move file\n const destPath = join(dirPath, filename);\n const copyError = await copyOrMoveFile(filePath, destPath, move);\n if (copyError) {\n return { success: false, error: copyError };\n }\n\n // Update metadata\n const updatedFiles = buildUpdatedFiles(existingFiles, newFile, existingFile);\n const updatedAttachments: Attachments = {\n directory: dirName,\n files: updatedFiles,\n };\n\n await updateAttachmentMetadata(library, item as CslItem, updatedAttachments);\n await library.save();\n\n return {\n success: true,\n filename,\n directory: dirName,\n overwritten: !!existingFile,\n };\n}\n","/**\n * Fulltext-to-attachments adapter utilities\n *\n * Maps fulltext command options and data to the new attachments system.\n * This adapter enables the fulltext command to use attachments backend\n * while maintaining backward-compatible interface.\n */\n\nimport type { AttachmentFile, Attachments } from \"../../attachments/types.js\";\nimport { getExtension } from \"../../attachments/types.js\";\n\n/**\n * The role used for fulltext files in the attachments system\n */\nexport const FULLTEXT_ROLE = \"fulltext\" as const;\n\n/**\n * Fulltext format type (matching existing FulltextType)\n */\nexport type FulltextFormat = \"pdf\" | \"markdown\";\n\n/**\n * Convert fulltext format to file extension\n */\nexport function formatToExtension(format: FulltextFormat): string {\n return format === \"markdown\" ? \"md\" : format;\n}\n\n/**\n * Convert file extension to fulltext format\n * Returns undefined if extension is not a valid fulltext format\n */\nexport function extensionToFormat(ext: string): FulltextFormat | undefined {\n const normalized = ext.toLowerCase();\n if (normalized === \"pdf\") return \"pdf\";\n if (normalized === \"md\" || normalized === \"markdown\") return \"markdown\";\n return undefined;\n}\n\n/**\n * Get the standard filename for a fulltext file\n * Following the naming convention: fulltext.{ext}\n */\nexport function getFulltextFilename(format: FulltextFormat): string {\n const ext = formatToExtension(format);\n return `fulltext.${ext}`;\n}\n\n/**\n * Find a fulltext file of specific format in attachments\n */\nexport function findFulltextFile(\n attachments: Attachments | undefined,\n format: FulltextFormat\n): AttachmentFile | undefined {\n if (!attachments?.files) {\n return undefined;\n }\n\n const targetExt = formatToExtension(format);\n\n return attachments.files.find((file) => {\n if (file.role !== FULLTEXT_ROLE) {\n return false;\n }\n const fileExt = getExtension(file.filename);\n return fileExt === targetExt;\n });\n}\n\n/**\n * Find all fulltext files in attachments\n */\nexport function findFulltextFiles(attachments: Attachments | undefined): AttachmentFile[] {\n if (!attachments?.files) {\n return [];\n }\n\n return attachments.files.filter((file) => file.role === FULLTEXT_ROLE);\n}\n","/**\n * Fulltext attach operation\n *\n * Uses attachments system internally with role='fulltext'.\n */\n\nimport { mkdtempSync, writeFileSync } from \"node:fs\";\nimport { rm } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { extname, join } from \"node:path\";\nimport type { ILibrary, IdentifierType } from \"../../../core/library-interface.js\";\nimport { type AddAttachmentResult, addAttachment } from \"../attachments/add.js\";\nimport {\n FULLTEXT_ROLE,\n type FulltextFormat,\n formatToExtension,\n} from \"../fulltext-adapter/index.js\";\n\n/**\n * Fulltext type (matches existing FulltextType for backward compatibility)\n */\nexport type FulltextType = FulltextFormat;\n\n/**\n * Options for fulltextAttach operation\n */\nexport interface FulltextAttachOptions {\n /** Reference identifier (id or uuid) */\n identifier: string;\n /** Path to the file to attach */\n filePath?: string | undefined;\n /** Explicit file type (pdf or markdown) */\n type?: FulltextType | undefined;\n /** Move file instead of copy */\n move?: boolean | undefined;\n /** Force overwrite existing file */\n force?: boolean | undefined;\n /** Identifier type: 'id' (default), 'uuid', 'doi', 'pmid', or 'isbn' */\n idType?: IdentifierType | undefined;\n /** Directory for attachments (replaces fulltextDirectory) */\n fulltextDirectory: string;\n /** Content from stdin */\n stdinContent?: Buffer | undefined;\n}\n\n/**\n * Result of fulltextAttach operation\n */\nexport interface FulltextAttachResult {\n success: boolean;\n filename?: string | undefined;\n type?: FulltextType | undefined;\n overwritten?: boolean | undefined;\n existingFile?: string | undefined;\n requiresConfirmation?: boolean | undefined;\n error?: string | undefined;\n}\n\n/**\n * Detect fulltext type from file extension\n */\nfunction detectType(filePath: string): FulltextType | undefined {\n const ext = extname(filePath).toLowerCase();\n if (ext === \".pdf\") return \"pdf\";\n if (ext === \".md\" || ext === \".markdown\") return \"markdown\";\n return undefined;\n}\n\n/**\n * Resolve file type from options\n */\nfunction resolveFileType(\n explicitType: FulltextType | undefined,\n filePath: string | undefined,\n stdinContent: Buffer | undefined\n): FulltextType | { error: string } {\n let fileType = explicitType;\n if (!fileType && filePath) {\n fileType = detectType(filePath);\n }\n\n if (stdinContent && !fileType) {\n return {\n error: \"File type must be specified with --pdf or --markdown when reading from stdin.\",\n };\n }\n\n if (!fileType) {\n return { error: \"Cannot detect file type. Use --pdf or --markdown to specify the type.\" };\n }\n\n return fileType;\n}\n\n/**\n * Prepare source path from stdin content\n */\nfunction prepareStdinSource(\n stdinContent: Buffer,\n fileType: FulltextType\n): { sourcePath: string; tempDir: string } | { error: string } {\n try {\n const tempDir = mkdtempSync(join(tmpdir(), \"refmgr-\"));\n const ext = formatToExtension(fileType);\n const sourcePath = join(tempDir, `stdin.${ext}`);\n writeFileSync(sourcePath, stdinContent);\n return { sourcePath, tempDir };\n } catch (error) {\n return {\n error: `Failed to write stdin content: ${error instanceof Error ? error.message : String(error)}`,\n };\n }\n}\n\n/**\n * Clean up temp directory\n */\nasync function cleanupTempDir(tempDir: string | undefined): Promise<void> {\n if (tempDir) {\n await rm(tempDir, { recursive: true, force: true }).catch(() => {});\n }\n}\n\n/**\n * Prepare source path from options\n */\nfunction prepareSourcePath(\n filePath: string | undefined,\n stdinContent: Buffer | undefined,\n fileType: FulltextType\n): { sourcePath: string; tempDir?: string } | { error: string } {\n if (stdinContent) {\n return prepareStdinSource(stdinContent, fileType);\n }\n\n if (!filePath) {\n return { error: \"No file path or stdin content provided.\" };\n }\n\n return { sourcePath: filePath };\n}\n\n/**\n * Convert AddAttachmentResult to FulltextAttachResult\n */\nfunction convertResult(result: AddAttachmentResult, fileType: FulltextType): FulltextAttachResult {\n if (result.success) {\n return {\n success: true,\n filename: result.filename,\n type: fileType,\n overwritten: result.overwritten,\n };\n }\n\n if (result.requiresConfirmation) {\n return {\n success: false,\n existingFile: result.existingFile,\n requiresConfirmation: true,\n };\n }\n\n return {\n success: false,\n error: result.error,\n };\n}\n\n/**\n * Attach a fulltext file to a reference.\n *\n * @param library - The library containing the reference\n * @param options - Attach options\n * @returns Result of the attach operation\n */\nexport async function fulltextAttach(\n library: ILibrary,\n options: FulltextAttachOptions\n): Promise<FulltextAttachResult> {\n const {\n identifier,\n filePath,\n type: explicitType,\n move,\n force,\n idType = \"id\",\n fulltextDirectory,\n stdinContent,\n } = options;\n\n // Resolve file type first\n const fileTypeResult = resolveFileType(explicitType, filePath, stdinContent);\n if (typeof fileTypeResult === \"object\" && \"error\" in fileTypeResult) {\n // Check if reference exists (for consistent error messages)\n const item = await library.find(identifier, { idType });\n if (!item) {\n return { success: false, error: `Reference '${identifier}' not found` };\n }\n return { success: false, error: fileTypeResult.error };\n }\n const fileType = fileTypeResult;\n\n // Prepare source path\n const sourceResult = prepareSourcePath(filePath, stdinContent, fileType);\n if (\"error\" in sourceResult) {\n // Check if reference exists (for consistent error messages)\n const item = await library.find(identifier, { idType });\n if (!item) {\n return { success: false, error: `Reference '${identifier}' not found` };\n }\n return { success: false, error: sourceResult.error };\n }\n const { sourcePath, tempDir } = sourceResult;\n\n try {\n // Use attachments system with fulltext role\n const result = await addAttachment(library, {\n identifier,\n filePath: sourcePath,\n role: FULLTEXT_ROLE,\n move: move ?? false,\n force: force ?? false,\n idType,\n attachmentsDirectory: fulltextDirectory,\n });\n\n await cleanupTempDir(tempDir);\n\n return convertResult(result, fileType);\n } catch (error) {\n await cleanupTempDir(tempDir);\n throw error;\n }\n}\n","/**\n * Fulltext get operation\n *\n * Uses attachments system internally with role='fulltext'.\n */\n\nimport { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type { CslItem } from \"../../../core/csl-json/types.js\";\nimport type { ILibrary, IdentifierType } from \"../../../core/library-interface.js\";\nimport { normalizePathForOutput } from \"../../../utils/path.js\";\nimport type { AttachmentFile, Attachments } from \"../../attachments/types.js\";\nimport {\n type FulltextFormat,\n extensionToFormat,\n findFulltextFile,\n findFulltextFiles,\n} from \"../fulltext-adapter/index.js\";\n\n/**\n * Fulltext type (matches existing FulltextType for backward compatibility)\n */\nexport type FulltextType = FulltextFormat;\n\n/**\n * Options for fulltextGet operation\n */\nexport interface FulltextGetOptions {\n /** Reference identifier (id or uuid) */\n identifier: string;\n /** Specific type to get (pdf or markdown) */\n type?: FulltextType | undefined;\n /** Preferred type ordering when type is not specified (pdf or markdown) */\n preferredType?: FulltextType | undefined;\n /** If true, return file content instead of path */\n stdout?: boolean | undefined;\n /** Identifier type: 'id' (default), 'uuid', 'doi', 'pmid', or 'isbn' */\n idType?: IdentifierType | undefined;\n /** Directory for attachments (replaces fulltextDirectory) */\n fulltextDirectory: string;\n}\n\n/**\n * Result of fulltextGet operation\n */\nexport interface FulltextGetResult {\n success: boolean;\n paths?: {\n pdf?: string;\n markdown?: string;\n };\n content?: Buffer;\n error?: string;\n}\n\n/**\n * Build file path from attachments metadata\n */\nfunction buildFilePath(attachmentsDirectory: string, directory: string, filename: string): string {\n return normalizePathForOutput(join(attachmentsDirectory, directory, filename));\n}\n\n/**\n * Get file content for stdout mode\n */\nasync function getFileContent(filePath: string): Promise<FulltextGetResult> {\n const content = await readFile(filePath);\n return { success: true, content };\n}\n\n/**\n * Handle stdout mode - get file content\n */\nasync function handleStdoutMode(\n attachments: Attachments | undefined,\n type: FulltextType,\n identifier: string,\n fulltextDirectory: string\n): Promise<FulltextGetResult> {\n const file = findFulltextFile(attachments, type);\n if (!file || !attachments?.directory) {\n return { success: false, error: `No ${type} fulltext attached to '${identifier}'` };\n }\n const filePath = buildFilePath(fulltextDirectory, attachments.directory, file.filename);\n try {\n return await getFileContent(filePath);\n } catch {\n return { success: false, error: `No ${type} fulltext attached to '${identifier}'` };\n }\n}\n\n/**\n * Get single type path\n */\nfunction getSingleTypePath(\n attachments: Attachments | undefined,\n type: FulltextType,\n identifier: string,\n fulltextDirectory: string\n): FulltextGetResult {\n const file = findFulltextFile(attachments, type);\n if (!file || !attachments?.directory) {\n return { success: false, error: `No ${type} fulltext attached to '${identifier}'` };\n }\n const filePath = buildFilePath(fulltextDirectory, attachments.directory, file.filename);\n const paths: { pdf?: string; markdown?: string } = {};\n paths[type] = filePath;\n return { success: true, paths };\n}\n\n/**\n * Get all fulltext paths\n */\nfunction getAllFulltextPaths(\n attachments: Attachments,\n fulltextFiles: AttachmentFile[],\n fulltextDirectory: string,\n identifier: string,\n preferredType?: FulltextType\n): FulltextGetResult {\n const paths: { pdf?: string; markdown?: string } = {};\n for (const file of fulltextFiles) {\n const ext = file.filename.split(\".\").pop() || \"\";\n const format = extensionToFormat(ext);\n if (format) {\n const filePath = buildFilePath(fulltextDirectory, attachments.directory, file.filename);\n paths[format] = filePath;\n }\n }\n\n if (Object.keys(paths).length === 0) {\n return { success: false, error: `No fulltext attached to '${identifier}'` };\n }\n\n // Reorder paths based on preferredType\n if (preferredType && paths[preferredType]) {\n const ordered: { pdf?: string; markdown?: string } = {};\n ordered[preferredType] = paths[preferredType];\n for (const key of Object.keys(paths) as FulltextType[]) {\n if (key !== preferredType && paths[key]) {\n ordered[key] = paths[key];\n }\n }\n return { success: true, paths: ordered };\n }\n\n return { success: true, paths };\n}\n\n/**\n * Get fulltext file paths or content for a reference.\n *\n * @param library - The library containing the reference\n * @param options - Get options\n * @returns Result with file paths or content\n */\nexport async function fulltextGet(\n library: ILibrary,\n options: FulltextGetOptions\n): Promise<FulltextGetResult> {\n const { identifier, type, preferredType, stdout, idType = \"id\", fulltextDirectory } = options;\n\n // Find reference\n const item = await library.find(identifier, { idType });\n if (!item) {\n return { success: false, error: `Reference '${identifier}' not found` };\n }\n\n // Get attachments metadata\n const attachments = (item as CslItem).custom?.attachments as Attachments | undefined;\n\n // Stdout mode with specific type\n if (stdout && type) {\n return handleStdoutMode(attachments, type, identifier, fulltextDirectory);\n }\n\n // Path mode - find all fulltext files\n const fulltextFiles = findFulltextFiles(attachments);\n if (fulltextFiles.length === 0) {\n return { success: false, error: `No fulltext attached to '${identifier}'` };\n }\n\n // If specific type requested, filter to that type\n if (type) {\n return getSingleTypePath(attachments, type, identifier, fulltextDirectory);\n }\n\n // Return all fulltext paths\n if (!attachments) {\n return { success: false, error: `No fulltext attached to '${identifier}'` };\n }\n\n return getAllFulltextPaths(\n attachments,\n fulltextFiles,\n fulltextDirectory,\n identifier,\n preferredType\n );\n}\n","/**\n * arXiv OA discovery client.\n * Generates PDF download URLs for arXiv articles.\n *\n * URL pattern: https://arxiv.org/pdf/{id}.pdf\n * No API call needed — arXiv is always open access.\n */\n/** Strip common prefixes from arXiv IDs */\nfunction normalizeArxivId(id) {\n return id.replace(/^arXiv:/i, \"\");\n}\n/**\n * Check arXiv availability for an article.\n * Since all arXiv articles are freely available, this simply\n * generates the PDF URL from the arXiv ID.\n *\n * @param arxivId - arXiv identifier (e.g., \"2401.12345\", \"hep-ph/9901234\")\n * @returns Array with a single PDF OALocation, or null if no ID\n */\nexport function checkArxiv(arxivId) {\n if (!arxivId)\n return null;\n const id = normalizeArxivId(arxivId);\n return [\n {\n source: \"arxiv\",\n url: `https://arxiv.org/pdf/${id}.pdf`,\n urlType: \"pdf\",\n version: \"submitted\",\n },\n ];\n}\n//# sourceMappingURL=arxiv.js.map","/**\n * CORE API OA discovery client.\n * Checks Open Access availability via the CORE API.\n *\n * API: https://api.core.ac.uk/v3/search/works?q=doi:\"{doi}\"\n * Auth: Bearer token (API key, free registration)\n * Rate limit: 10 req/sec\n */\nconst CORE_API_BASE = \"https://api.core.ac.uk/v3\";\n/**\n * Check CORE API for Open Access availability of an article.\n *\n * @param doi - The article's DOI\n * @param apiKey - CORE API key (required; returns null if empty)\n * @returns Array of OALocations if found, null if not found or no key\n * @throws On rate limit (429) or network errors\n */\nexport async function checkCore(doi, apiKey) {\n if (!doi)\n return null;\n if (!apiKey)\n return null;\n const url = `${CORE_API_BASE}/search/works?q=doi:\"${doi}\"&limit=1`;\n const response = await fetch(url, {\n headers: {\n Authorization: `Bearer ${apiKey}`,\n },\n });\n if (!response.ok) {\n if (response.status === 429) {\n throw new Error(\"CORE API rate limit exceeded\");\n }\n throw new Error(`CORE API error: HTTP ${response.status} ${response.statusText}`);\n }\n const data = (await response.json());\n if (!data.totalHits || !data.results || data.results.length === 0) {\n return null;\n }\n const firstResult = data.results[0];\n if (!firstResult)\n return null;\n // Prefer downloadUrl (direct PDF from CORE)\n if (firstResult.downloadUrl) {\n return [\n {\n source: \"core\",\n url: firstResult.downloadUrl,\n urlType: \"pdf\",\n version: \"accepted\",\n },\n ];\n }\n // Fall back to sourceFulltextUrls (repository links)\n if (firstResult.sourceFulltextUrls && firstResult.sourceFulltextUrls.length > 0) {\n const repoUrl = firstResult.sourceFulltextUrls[0];\n if (repoUrl) {\n return [\n {\n source: \"core\",\n url: repoUrl,\n urlType: \"repository\",\n version: \"accepted\",\n },\n ];\n }\n }\n return null;\n}\n//# sourceMappingURL=core.js.map","/**\n * PMC OA discovery client.\n * Checks PubMed Central availability and generates download URLs.\n *\n * PDF: https://www.ncbi.nlm.nih.gov/pmc/articles/PMC{id}/pdf/\n * XML: https://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?db=pmc&id={pmcid}&rettype=xml\n * PMID→PMCID: https://eutils.ncbi.nlm.nih.gov/entrez/eutils/elink.fcgi?dbfrom=pubmed&db=pmc&id={pmid}&retmode=json\n */\nconst EUTILS_BASE = \"https://eutils.ncbi.nlm.nih.gov/entrez/eutils\";\n/** Strip \"PMC\" prefix from PMCID, returning just the numeric part */\nfunction stripPmcPrefix(pmcid) {\n return pmcid.replace(/^PMC/i, \"\");\n}\n/** Ensure PMCID has the \"PMC\" prefix */\nfunction ensurePmcPrefix(pmcid) {\n return pmcid.startsWith(\"PMC\") ? pmcid : `PMC${pmcid}`;\n}\n/**\n * Generate PMC download URLs from a known PMCID.\n */\nexport function getPmcUrls(pmcid) {\n const numericId = stripPmcPrefix(pmcid);\n const fullPmcid = ensurePmcPrefix(pmcid);\n return [\n {\n source: \"pmc\",\n url: `https://www.ncbi.nlm.nih.gov/pmc/articles/${fullPmcid}/pdf/`,\n urlType: \"pdf\",\n version: \"published\",\n },\n {\n source: \"pmc\",\n url: `${EUTILS_BASE}/efetch.fcgi?db=pmc&id=${numericId}&rettype=xml`,\n urlType: \"xml\",\n version: \"published\",\n },\n ];\n}\n/**\n * Look up PMCID from PMID via E-utilities elink API.\n * @returns PMCID string or null if not in PMC\n */\nasync function lookupPmcid(pmid, options) {\n let url = `${EUTILS_BASE}/elink.fcgi?dbfrom=pubmed&db=pmc&id=${pmid}&retmode=json`;\n if (options?.apiKey) {\n url += `&api_key=${options.apiKey}`;\n }\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error(`PMC elink API error: HTTP ${response.status}`);\n }\n const data = (await response.json());\n const linksets = data.linksets;\n if (!linksets || linksets.length === 0)\n return null;\n const firstLinkset = linksets[0];\n if (!firstLinkset?.linksetdbs)\n return null;\n const pmcLink = firstLinkset.linksetdbs.find((db) => db.dbto === \"pmc\");\n if (!pmcLink?.links || pmcLink.links.length === 0)\n return null;\n const pmcNumericId = pmcLink.links[0];\n return pmcNumericId ? `PMC${pmcNumericId}` : null;\n}\n/**\n * Check PMC availability for an article.\n * If PMCID is known, generates URLs directly.\n * If only PMID is known, looks up PMCID via E-utilities elink.\n */\nexport async function checkPmc(ids, options) {\n // If PMCID is already known, generate URLs directly\n if (ids.pmcid) {\n return getPmcUrls(ids.pmcid);\n }\n // If only PMID is known, look up PMCID\n if (ids.pmid) {\n const pmcid = await lookupPmcid(ids.pmid, options);\n if (!pmcid)\n return null;\n return getPmcUrls(pmcid);\n }\n // No identifiers provided\n return null;\n}\n//# sourceMappingURL=pmc.js.map","/**\n * Unpaywall OA discovery client.\n * Checks Open Access availability via the Unpaywall API.\n *\n * API: https://api.unpaywall.org/v2/{doi}?email={email}\n * Rate limit: 100,000 requests/day (no per-second limit documented)\n */\nconst UNPAYWALL_BASE_URL = \"https://api.unpaywall.org/v2\";\n/** Map Unpaywall version strings to our OALocation version format */\nfunction mapVersion(version) {\n switch (version) {\n case \"publishedVersion\":\n return \"published\";\n case \"acceptedVersion\":\n return \"accepted\";\n case \"submittedVersion\":\n return \"submitted\";\n default:\n return \"published\";\n }\n}\n/** Convert an Unpaywall location to our OALocation format */\nfunction toOALocation(loc) {\n const hasPdf = loc.url_for_pdf != null;\n const url = hasPdf ? loc.url_for_pdf : loc.url_for_landing_page;\n if (!url)\n return null;\n const result = {\n source: \"unpaywall\",\n url,\n urlType: hasPdf ? \"pdf\" : \"html\",\n version: mapVersion(loc.version),\n };\n if (loc.license) {\n result.license = loc.license;\n }\n return result;\n}\n/**\n * Check Unpaywall for Open Access availability of an article.\n *\n * @param doi - The article's DOI\n * @param email - Email address required by Unpaywall API (free, no registration)\n * @returns Array of OALocations if OA, null if closed/not found\n * @throws On rate limit (429) or network errors\n */\nexport async function checkUnpaywall(doi, email) {\n if (!doi)\n return null;\n if (!email) {\n throw new Error(\"Unpaywall email is required for API access\");\n }\n const url = `${UNPAYWALL_BASE_URL}/${doi}?email=${encodeURIComponent(email)}`;\n const response = await fetch(url);\n if (!response.ok) {\n if (response.status === 404)\n return null;\n if (response.status === 429) {\n throw new Error(\"Unpaywall rate limit exceeded\");\n }\n throw new Error(`Unpaywall API error: HTTP ${response.status} ${response.statusText}`);\n }\n const data = (await response.json());\n if (!data.is_oa || !data.oa_locations || data.oa_locations.length === 0) {\n return null;\n }\n const locations = [];\n for (const loc of data.oa_locations) {\n const oaLoc = toOALocation(loc);\n if (oaLoc)\n locations.push(oaLoc);\n }\n return locations.length > 0 ? locations : null;\n}\n//# sourceMappingURL=unpaywall.js.map","/**\n * OA Discovery Aggregator.\n * Combines results from multiple OA discovery sources.\n */\nimport { checkArxiv } from \"./arxiv.js\";\nimport { checkCore } from \"./core.js\";\nimport { checkPmc } from \"./pmc.js\";\nimport { checkUnpaywall } from \"./unpaywall.js\";\n/** Default source order when preferSources is empty or not specified */\nconst DEFAULT_SOURCE_ORDER = [\"pmc\", \"arxiv\", \"unpaywall\", \"core\"];\nasync function checkPmcSource(article) {\n if (!article.pmid && !article.pmcid)\n return undefined;\n const ids = {};\n if (article.pmid)\n ids.pmid = article.pmid;\n if (article.pmcid)\n ids.pmcid = article.pmcid;\n return await checkPmc(ids);\n}\nfunction checkArxivSource(article) {\n if (!article.arxivId)\n return undefined;\n return checkArxiv(article.arxivId);\n}\nasync function checkUnpaywallSource(article, config) {\n if (!config.unpaywallEmail || !article.doi)\n return undefined;\n return await checkUnpaywall(article.doi, config.unpaywallEmail);\n}\nasync function checkCoreSource(article, config) {\n if (!config.coreApiKey || !article.doi)\n return undefined;\n return await checkCore(article.doi, config.coreApiKey);\n}\n/** Map of source name to its checker function. */\nconst sourceCheckers = {\n pmc: checkPmcSource,\n arxiv: checkArxivSource,\n unpaywall: checkUnpaywallSource,\n core: checkCoreSource,\n};\n/** Determine OA status from collected locations and errors. */\nfunction determineOAStatus(locations, errors, sourcesChecked) {\n if (locations.length > 0)\n return \"open\";\n if (errors.length > 0 && errors.length >= sourcesChecked)\n return \"unknown\";\n return \"closed\";\n}\n/**\n * Discover OA availability for an article across all configured sources.\n * Checks sources in the order specified by config.preferSources, falling back\n * to the default order. Individual source errors are caught and reported\n * without failing the whole discovery.\n */\nexport async function discoverOA(article, config) {\n const locations = [];\n const errors = [];\n let sourcesChecked = 0;\n const sourceOrder = config.preferSources.length > 0 ? config.preferSources : DEFAULT_SOURCE_ORDER;\n for (const source of sourceOrder) {\n const checker = sourceCheckers[source];\n if (!checker)\n continue;\n const result = await runSourceChecker(checker, article, config);\n if (result.skipped)\n continue;\n sourcesChecked++;\n if (result.error) {\n errors.push({ source, error: result.error });\n }\n else if (result.locations) {\n locations.push(...result.locations);\n }\n }\n const oaStatus = determineOAStatus(locations, errors, sourcesChecked);\n return { oaStatus, locations, errors };\n}\n/** Run a single source checker with error handling. */\nasync function runSourceChecker(checker, article, config) {\n try {\n const result = await checker(article, config);\n if (result === undefined)\n return { skipped: true };\n return { skipped: false, locations: result ?? [] };\n }\n catch (err) {\n return { skipped: false, error: String(err) };\n }\n}\n//# sourceMappingURL=index.js.map","/**\n * PDF downloader with retry and error handling.\n */\nimport { mkdir, writeFile } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\n/** HTTP status codes that should not be retried */\nconst NON_RETRYABLE_STATUSES = new Set([400, 401, 403, 404, 405, 410]);\n/** Content types accepted as valid PDF responses */\nconst VALID_CONTENT_TYPES = [\"application/pdf\", \"application/octet-stream\"];\nconst USER_AGENT = \"search-hub/0.8.0 (https://github.com/ncukondo/search-hub)\";\nfunction isValidPdfContentType(contentType) {\n if (!contentType)\n return false;\n const base = (contentType.split(\";\")[0] ?? \"\").trim().toLowerCase();\n return VALID_CONTENT_TYPES.includes(base);\n}\nfunction sleep(ms) {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\nasync function attemptDownload(url, destPath) {\n const response = await fetch(url, {\n headers: { \"User-Agent\": USER_AGENT },\n });\n if (!response.ok) {\n const error = `HTTP ${response.status} ${response.statusText}`;\n if (NON_RETRYABLE_STATUSES.has(response.status)) {\n return { kind: \"fail\", result: { success: false, error } };\n }\n return { kind: \"retry\", error };\n }\n const contentType = response.headers.get(\"content-type\");\n if (!isValidPdfContentType(contentType)) {\n return {\n kind: \"fail\",\n result: {\n success: false,\n error: `Unexpected Content-Type: ${contentType ?? \"none\"}`,\n },\n };\n }\n const buffer = await response.arrayBuffer();\n await mkdir(dirname(destPath), { recursive: true });\n await writeFile(destPath, Buffer.from(buffer));\n return { kind: \"success\", result: { success: true, size: buffer.byteLength } };\n}\n/**\n * Download a PDF from a URL to a local file path.\n * Retries on network errors and 429 responses with exponential backoff.\n * Does not retry on 403/404 or other client errors.\n */\nexport async function downloadPdf(url, destPath, options) {\n const retries = options?.retries ?? 3;\n const retryDelay = options?.retryDelay ?? 1000;\n let lastError;\n for (let attempt = 1; attempt <= retries; attempt++) {\n try {\n const outcome = await attemptDownload(url, destPath);\n if (outcome.kind === \"success\" || outcome.kind === \"fail\") {\n return outcome.result;\n }\n lastError = outcome.error;\n }\n catch (err) {\n lastError = err instanceof Error ? err.message : String(err);\n }\n if (attempt < retries) {\n await sleep(retryDelay * attempt);\n }\n }\n return { success: false, error: lastError ?? \"Download failed\" };\n}\n//# sourceMappingURL=downloader.js.map","/**\n * PMC XML downloader via E-utilities.\n */\nimport { mkdir, writeFile } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\nconst PMC_EFETCH_URL = \"https://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi\";\n/** Content types accepted as valid XML responses */\nconst VALID_XML_TYPES = [\"text/xml\", \"application/xml\"];\nconst USER_AGENT = \"search-hub/0.8.0 (https://github.com/ncukondo/search-hub)\";\nfunction isValidXmlContentType(contentType) {\n if (!contentType)\n return false;\n const base = (contentType.split(\";\")[0] ?? \"\").trim().toLowerCase();\n return VALID_XML_TYPES.includes(base);\n}\n/** Strip \"PMC\" prefix if present, returning numeric ID */\nfunction normalizePmcid(pmcid) {\n return pmcid.replace(/^PMC/i, \"\");\n}\n/**\n * Download PMC XML for a given PMCID via E-utilities efetch.\n */\nexport async function downloadPmcXml(pmcid, destPath) {\n const numericId = normalizePmcid(pmcid);\n const url = `${PMC_EFETCH_URL}?db=pmc&id=${numericId}&rettype=xml`;\n try {\n const response = await fetch(url, {\n headers: { \"User-Agent\": USER_AGENT },\n });\n if (!response.ok) {\n return {\n success: false,\n error: `HTTP ${response.status} ${response.statusText}`,\n };\n }\n const contentType = response.headers.get(\"content-type\");\n if (!isValidXmlContentType(contentType)) {\n return {\n success: false,\n error: `Unexpected Content-Type: ${contentType ?? \"none\"} (expected XML)`,\n };\n }\n const text = await response.text();\n await mkdir(dirname(destPath), { recursive: true });\n await writeFile(destPath, text, \"utf-8\");\n return { success: true, size: Buffer.byteLength(text) };\n }\n catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n}\n//# sourceMappingURL=pmc-xml.js.map","'use strict';\n\nconst nameStartChar = ':A-Za-z_\\\\u00C0-\\\\u00D6\\\\u00D8-\\\\u00F6\\\\u00F8-\\\\u02FF\\\\u0370-\\\\u037D\\\\u037F-\\\\u1FFF\\\\u200C-\\\\u200D\\\\u2070-\\\\u218F\\\\u2C00-\\\\u2FEF\\\\u3001-\\\\uD7FF\\\\uF900-\\\\uFDCF\\\\uFDF0-\\\\uFFFD';\nconst nameChar = nameStartChar + '\\\\-.\\\\d\\\\u00B7\\\\u0300-\\\\u036F\\\\u203F-\\\\u2040';\nexport const nameRegexp = '[' + nameStartChar + '][' + nameChar + ']*';\nconst regexName = new RegExp('^' + nameRegexp + '$');\n\nexport function getAllMatches(string, regex) {\n const matches = [];\n let match = regex.exec(string);\n while (match) {\n const allmatches = [];\n allmatches.startIndex = regex.lastIndex - match[0].length;\n const len = match.length;\n for (let index = 0; index < len; index++) {\n allmatches.push(match[index]);\n }\n matches.push(allmatches);\n match = regex.exec(string);\n }\n return matches;\n}\n\nexport const isName = function(string) {\n const match = regexName.exec(string);\n return !(match === null || typeof match === 'undefined');\n}\n\nexport function isExist(v) {\n return typeof v !== 'undefined';\n}\n\nexport function isEmptyObject(obj) {\n return Object.keys(obj).length === 0;\n}\n\n/**\n * Copy all the properties of a into b.\n * @param {*} target\n * @param {*} a\n */\nexport function merge(target, a, arrayMode) {\n if (a) {\n const keys = Object.keys(a); // will return an array of own properties\n const len = keys.length; //don't make it inline\n for (let i = 0; i < len; i++) {\n if (arrayMode === 'strict') {\n target[keys[i]] = [ a[keys[i]] ];\n } else {\n target[keys[i]] = a[keys[i]];\n }\n }\n }\n}\n/* exports.merge =function (b,a){\n return Object.assign(b,a);\n} */\n\nexport function getValue(v) {\n if (exports.isExist(v)) {\n return v;\n } else {\n return '';\n }\n}\n\n// const fakeCall = function(a) {return a;};\n// const fakeCallNoReturn = function() {};","'use strict';\n\nimport {getAllMatches, isName} from './util.js';\n\nconst defaultOptions = {\n allowBooleanAttributes: false, //A tag can have attributes without any value\n unpairedTags: []\n};\n\n//const tagsPattern = new RegExp(\"<\\\\/?([\\\\w:\\\\-_\\.]+)\\\\s*\\/?>\",\"g\");\nexport function validate(xmlData, options) {\n options = Object.assign({}, defaultOptions, options);\n\n //xmlData = xmlData.replace(/(\\r\\n|\\n|\\r)/gm,\"\");//make it single line\n //xmlData = xmlData.replace(/(^\\s*<\\?xml.*?\\?>)/g,\"\");//Remove XML starting tag\n //xmlData = xmlData.replace(/(<!DOCTYPE[\\s\\w\\\"\\.\\/\\-\\:]+(\\[.*\\])*\\s*>)/g,\"\");//Remove DOCTYPE\n const tags = [];\n let tagFound = false;\n\n //indicates that the root tag has been closed (aka. depth 0 has been reached)\n let reachedRoot = false;\n\n if (xmlData[0] === '\\ufeff') {\n // check for byte order mark (BOM)\n xmlData = xmlData.substr(1);\n }\n \n for (let i = 0; i < xmlData.length; i++) {\n\n if (xmlData[i] === '<' && xmlData[i+1] === '?') {\n i+=2;\n i = readPI(xmlData,i);\n if (i.err) return i;\n }else if (xmlData[i] === '<') {\n //starting of tag\n //read until you reach to '>' avoiding any '>' in attribute value\n let tagStartPos = i;\n i++;\n \n if (xmlData[i] === '!') {\n i = readCommentAndCDATA(xmlData, i);\n continue;\n } else {\n let closingTag = false;\n if (xmlData[i] === '/') {\n //closing tag\n closingTag = true;\n i++;\n }\n //read tagname\n let tagName = '';\n for (; i < xmlData.length &&\n xmlData[i] !== '>' &&\n xmlData[i] !== ' ' &&\n xmlData[i] !== '\\t' &&\n xmlData[i] !== '\\n' &&\n xmlData[i] !== '\\r'; i++\n ) {\n tagName += xmlData[i];\n }\n tagName = tagName.trim();\n //console.log(tagName);\n\n if (tagName[tagName.length - 1] === '/') {\n //self closing tag without attributes\n tagName = tagName.substring(0, tagName.length - 1);\n //continue;\n i--;\n }\n if (!validateTagName(tagName)) {\n let msg;\n if (tagName.trim().length === 0) {\n msg = \"Invalid space after '<'.\";\n } else {\n msg = \"Tag '\"+tagName+\"' is an invalid name.\";\n }\n return getErrorObject('InvalidTag', msg, getLineNumberForPosition(xmlData, i));\n }\n\n const result = readAttributeStr(xmlData, i);\n if (result === false) {\n return getErrorObject('InvalidAttr', \"Attributes for '\"+tagName+\"' have open quote.\", getLineNumberForPosition(xmlData, i));\n }\n let attrStr = result.value;\n i = result.index;\n\n if (attrStr[attrStr.length - 1] === '/') {\n //self closing tag\n const attrStrStart = i - attrStr.length;\n attrStr = attrStr.substring(0, attrStr.length - 1);\n const isValid = validateAttributeString(attrStr, options);\n if (isValid === true) {\n tagFound = true;\n //continue; //text may presents after self closing tag\n } else {\n //the result from the nested function returns the position of the error within the attribute\n //in order to get the 'true' error line, we need to calculate the position where the attribute begins (i - attrStr.length) and then add the position within the attribute\n //this gives us the absolute index in the entire xml, which we can use to find the line at last\n return getErrorObject(isValid.err.code, isValid.err.msg, getLineNumberForPosition(xmlData, attrStrStart + isValid.err.line));\n }\n } else if (closingTag) {\n if (!result.tagClosed) {\n return getErrorObject('InvalidTag', \"Closing tag '\"+tagName+\"' doesn't have proper closing.\", getLineNumberForPosition(xmlData, i));\n } else if (attrStr.trim().length > 0) {\n return getErrorObject('InvalidTag', \"Closing tag '\"+tagName+\"' can't have attributes or invalid starting.\", getLineNumberForPosition(xmlData, tagStartPos));\n } else if (tags.length === 0) {\n return getErrorObject('InvalidTag', \"Closing tag '\"+tagName+\"' has not been opened.\", getLineNumberForPosition(xmlData, tagStartPos));\n } else {\n const otg = tags.pop();\n if (tagName !== otg.tagName) {\n let openPos = getLineNumberForPosition(xmlData, otg.tagStartPos);\n return getErrorObject('InvalidTag',\n \"Expected closing tag '\"+otg.tagName+\"' (opened in line \"+openPos.line+\", col \"+openPos.col+\") instead of closing tag '\"+tagName+\"'.\",\n getLineNumberForPosition(xmlData, tagStartPos));\n }\n\n //when there are no more tags, we reached the root level.\n if (tags.length == 0) {\n reachedRoot = true;\n }\n }\n } else {\n const isValid = validateAttributeString(attrStr, options);\n if (isValid !== true) {\n //the result from the nested function returns the position of the error within the attribute\n //in order to get the 'true' error line, we need to calculate the position where the attribute begins (i - attrStr.length) and then add the position within the attribute\n //this gives us the absolute index in the entire xml, which we can use to find the line at last\n return getErrorObject(isValid.err.code, isValid.err.msg, getLineNumberForPosition(xmlData, i - attrStr.length + isValid.err.line));\n }\n\n //if the root level has been reached before ...\n if (reachedRoot === true) {\n return getErrorObject('InvalidXml', 'Multiple possible root nodes found.', getLineNumberForPosition(xmlData, i));\n } else if(options.unpairedTags.indexOf(tagName) !== -1){\n //don't push into stack\n } else {\n tags.push({tagName, tagStartPos});\n }\n tagFound = true;\n }\n\n //skip tag text value\n //It may include comments and CDATA value\n for (i++; i < xmlData.length; i++) {\n if (xmlData[i] === '<') {\n if (xmlData[i + 1] === '!') {\n //comment or CADATA\n i++;\n i = readCommentAndCDATA(xmlData, i);\n continue;\n } else if (xmlData[i+1] === '?') {\n i = readPI(xmlData, ++i);\n if (i.err) return i;\n } else{\n break;\n }\n } else if (xmlData[i] === '&') {\n const afterAmp = validateAmpersand(xmlData, i);\n if (afterAmp == -1)\n return getErrorObject('InvalidChar', \"char '&' is not expected.\", getLineNumberForPosition(xmlData, i));\n i = afterAmp;\n }else{\n if (reachedRoot === true && !isWhiteSpace(xmlData[i])) {\n return getErrorObject('InvalidXml', \"Extra text at the end\", getLineNumberForPosition(xmlData, i));\n }\n }\n } //end of reading tag text value\n if (xmlData[i] === '<') {\n i--;\n }\n }\n } else {\n if ( isWhiteSpace(xmlData[i])) {\n continue;\n }\n return getErrorObject('InvalidChar', \"char '\"+xmlData[i]+\"' is not expected.\", getLineNumberForPosition(xmlData, i));\n }\n }\n\n if (!tagFound) {\n return getErrorObject('InvalidXml', 'Start tag expected.', 1);\n }else if (tags.length == 1) {\n return getErrorObject('InvalidTag', \"Unclosed tag '\"+tags[0].tagName+\"'.\", getLineNumberForPosition(xmlData, tags[0].tagStartPos));\n }else if (tags.length > 0) {\n return getErrorObject('InvalidXml', \"Invalid '\"+\n JSON.stringify(tags.map(t => t.tagName), null, 4).replace(/\\r?\\n/g, '')+\n \"' found.\", {line: 1, col: 1});\n }\n\n return true;\n};\n\nfunction isWhiteSpace(char){\n return char === ' ' || char === '\\t' || char === '\\n' || char === '\\r';\n}\n/**\n * Read Processing insstructions and skip\n * @param {*} xmlData\n * @param {*} i\n */\nfunction readPI(xmlData, i) {\n const start = i;\n for (; i < xmlData.length; i++) {\n if (xmlData[i] == '?' || xmlData[i] == ' ') {\n //tagname\n const tagname = xmlData.substr(start, i - start);\n if (i > 5 && tagname === 'xml') {\n return getErrorObject('InvalidXml', 'XML declaration allowed only at the start of the document.', getLineNumberForPosition(xmlData, i));\n } else if (xmlData[i] == '?' && xmlData[i + 1] == '>') {\n //check if valid attribut string\n i++;\n break;\n } else {\n continue;\n }\n }\n }\n return i;\n}\n\nfunction readCommentAndCDATA(xmlData, i) {\n if (xmlData.length > i + 5 && xmlData[i + 1] === '-' && xmlData[i + 2] === '-') {\n //comment\n for (i += 3; i < xmlData.length; i++) {\n if (xmlData[i] === '-' && xmlData[i + 1] === '-' && xmlData[i + 2] === '>') {\n i += 2;\n break;\n }\n }\n } else if (\n xmlData.length > i + 8 &&\n xmlData[i + 1] === 'D' &&\n xmlData[i + 2] === 'O' &&\n xmlData[i + 3] === 'C' &&\n xmlData[i + 4] === 'T' &&\n xmlData[i + 5] === 'Y' &&\n xmlData[i + 6] === 'P' &&\n xmlData[i + 7] === 'E'\n ) {\n let angleBracketsCount = 1;\n for (i += 8; i < xmlData.length; i++) {\n if (xmlData[i] === '<') {\n angleBracketsCount++;\n } else if (xmlData[i] === '>') {\n angleBracketsCount--;\n if (angleBracketsCount === 0) {\n break;\n }\n }\n }\n } else if (\n xmlData.length > i + 9 &&\n xmlData[i + 1] === '[' &&\n xmlData[i + 2] === 'C' &&\n xmlData[i + 3] === 'D' &&\n xmlData[i + 4] === 'A' &&\n xmlData[i + 5] === 'T' &&\n xmlData[i + 6] === 'A' &&\n xmlData[i + 7] === '['\n ) {\n for (i += 8; i < xmlData.length; i++) {\n if (xmlData[i] === ']' && xmlData[i + 1] === ']' && xmlData[i + 2] === '>') {\n i += 2;\n break;\n }\n }\n }\n\n return i;\n}\n\nconst doubleQuote = '\"';\nconst singleQuote = \"'\";\n\n/**\n * Keep reading xmlData until '<' is found outside the attribute value.\n * @param {string} xmlData\n * @param {number} i\n */\nfunction readAttributeStr(xmlData, i) {\n let attrStr = '';\n let startChar = '';\n let tagClosed = false;\n for (; i < xmlData.length; i++) {\n if (xmlData[i] === doubleQuote || xmlData[i] === singleQuote) {\n if (startChar === '') {\n startChar = xmlData[i];\n } else if (startChar !== xmlData[i]) {\n //if vaue is enclosed with double quote then single quotes are allowed inside the value and vice versa\n } else {\n startChar = '';\n }\n } else if (xmlData[i] === '>') {\n if (startChar === '') {\n tagClosed = true;\n break;\n }\n }\n attrStr += xmlData[i];\n }\n if (startChar !== '') {\n return false;\n }\n\n return {\n value: attrStr,\n index: i,\n tagClosed: tagClosed\n };\n}\n\n/**\n * Select all the attributes whether valid or invalid.\n */\nconst validAttrStrRegxp = new RegExp('(\\\\s*)([^\\\\s=]+)(\\\\s*=)?(\\\\s*([\\'\"])(([\\\\s\\\\S])*?)\\\\5)?', 'g');\n\n//attr, =\"sd\", a=\"amit's\", a=\"sd\"b=\"saf\", ab cd=\"\"\n\nfunction validateAttributeString(attrStr, options) {\n //console.log(\"start:\"+attrStr+\":end\");\n\n //if(attrStr.trim().length === 0) return true; //empty string\n\n const matches = getAllMatches(attrStr, validAttrStrRegxp);\n const attrNames = {};\n\n for (let i = 0; i < matches.length; i++) {\n if (matches[i][1].length === 0) {\n //nospace before attribute name: a=\"sd\"b=\"saf\"\n return getErrorObject('InvalidAttr', \"Attribute '\"+matches[i][2]+\"' has no space in starting.\", getPositionFromMatch(matches[i]))\n } else if (matches[i][3] !== undefined && matches[i][4] === undefined) {\n return getErrorObject('InvalidAttr', \"Attribute '\"+matches[i][2]+\"' is without value.\", getPositionFromMatch(matches[i]));\n } else if (matches[i][3] === undefined && !options.allowBooleanAttributes) {\n //independent attribute: ab\n return getErrorObject('InvalidAttr', \"boolean attribute '\"+matches[i][2]+\"' is not allowed.\", getPositionFromMatch(matches[i]));\n }\n /* else if(matches[i][6] === undefined){//attribute without value: ab=\n return { err: { code:\"InvalidAttr\",msg:\"attribute \" + matches[i][2] + \" has no value assigned.\"}};\n } */\n const attrName = matches[i][2];\n if (!validateAttrName(attrName)) {\n return getErrorObject('InvalidAttr', \"Attribute '\"+attrName+\"' is an invalid name.\", getPositionFromMatch(matches[i]));\n }\n if (!attrNames.hasOwnProperty(attrName)) {\n //check for duplicate attribute.\n attrNames[attrName] = 1;\n } else {\n return getErrorObject('InvalidAttr', \"Attribute '\"+attrName+\"' is repeated.\", getPositionFromMatch(matches[i]));\n }\n }\n\n return true;\n}\n\nfunction validateNumberAmpersand(xmlData, i) {\n let re = /\\d/;\n if (xmlData[i] === 'x') {\n i++;\n re = /[\\da-fA-F]/;\n }\n for (; i < xmlData.length; i++) {\n if (xmlData[i] === ';')\n return i;\n if (!xmlData[i].match(re))\n break;\n }\n return -1;\n}\n\nfunction validateAmpersand(xmlData, i) {\n // https://www.w3.org/TR/xml/#dt-charref\n i++;\n if (xmlData[i] === ';')\n return -1;\n if (xmlData[i] === '#') {\n i++;\n return validateNumberAmpersand(xmlData, i);\n }\n let count = 0;\n for (; i < xmlData.length; i++, count++) {\n if (xmlData[i].match(/\\w/) && count < 20)\n continue;\n if (xmlData[i] === ';')\n break;\n return -1;\n }\n return i;\n}\n\nfunction getErrorObject(code, message, lineNumber) {\n return {\n err: {\n code: code,\n msg: message,\n line: lineNumber.line || lineNumber,\n col: lineNumber.col,\n },\n };\n}\n\nfunction validateAttrName(attrName) {\n return isName(attrName);\n}\n\n// const startsWithXML = /^xml/i;\n\nfunction validateTagName(tagname) {\n return isName(tagname) /* && !tagname.match(startsWithXML) */;\n}\n\n//this function returns the line number for the character at the given index\nfunction getLineNumberForPosition(xmlData, index) {\n const lines = xmlData.substring(0, index).split(/\\r?\\n/);\n return {\n line: lines.length,\n\n // column number is last line's length + 1, because column numbering starts at 1:\n col: lines[lines.length - 1].length + 1\n };\n}\n\n//this function returns the position of the first character of match within attrStr\nfunction getPositionFromMatch(match) {\n return match.startIndex + match[1].length;\n}\n","\nexport const defaultOptions = {\n preserveOrder: false,\n attributeNamePrefix: '@_',\n attributesGroupName: false,\n textNodeName: '#text',\n ignoreAttributes: true,\n removeNSPrefix: false, // remove NS from tag name or attribute name if true\n allowBooleanAttributes: false, //a tag can have attributes without any value\n //ignoreRootElement : false,\n parseTagValue: true,\n parseAttributeValue: false,\n trimValues: true, //Trim string values of tag and attributes\n cdataPropName: false,\n numberParseOptions: {\n hex: true,\n leadingZeros: true,\n eNotation: true\n },\n tagValueProcessor: function(tagName, val) {\n return val;\n },\n attributeValueProcessor: function(attrName, val) {\n return val;\n },\n stopNodes: [], //nested tags will not be parsed even for errors\n alwaysCreateTextNode: false,\n isArray: () => false,\n commentPropName: false,\n unpairedTags: [],\n processEntities: true,\n htmlEntities: false,\n ignoreDeclaration: false,\n ignorePiTags: false,\n transformTagName: false,\n transformAttributeName: false,\n updateTag: function(tagName, jPath, attrs){\n return tagName\n },\n // skipEmptyListItem: false\n captureMetaData: false,\n};\n \nexport const buildOptions = function(options) {\n return Object.assign({}, defaultOptions, options);\n};\n","'use strict';\n\nlet METADATA_SYMBOL;\n\nif (typeof Symbol !== \"function\") {\n METADATA_SYMBOL = \"@@xmlMetadata\";\n} else {\n METADATA_SYMBOL = Symbol(\"XML Node Metadata\");\n}\n\nexport default class XmlNode{\n constructor(tagname) {\n this.tagname = tagname;\n this.child = []; //nested tags, text, cdata, comments in order\n this[\":@\"] = {}; //attributes map\n }\n add(key,val){\n // this.child.push( {name : key, val: val, isCdata: isCdata });\n if(key === \"__proto__\") key = \"#__proto__\";\n this.child.push( {[key]: val });\n }\n addChild(node, startIndex) {\n if(node.tagname === \"__proto__\") node.tagname = \"#__proto__\";\n if(node[\":@\"] && Object.keys(node[\":@\"]).length > 0){\n this.child.push( { [node.tagname]: node.child, [\":@\"]: node[\":@\"] });\n }else{\n this.child.push( { [node.tagname]: node.child });\n }\n // if requested, add the startIndex\n if (startIndex !== undefined) {\n // Note: for now we just overwrite the metadata. If we had more complex metadata,\n // we might need to do an object append here: metadata = { ...metadata, startIndex }\n this.child[this.child.length - 1][METADATA_SYMBOL] = { startIndex };\n }\n }\n /** symbol used for metadata */\n static getMetaDataSymbol() {\n return METADATA_SYMBOL;\n }\n}\n","import {isName} from '../util.js';\n\nexport default class DocTypeReader{\n constructor(processEntities){\n this.suppressValidationErr = !processEntities;\n }\n \n readDocType(xmlData, i){\n \n const entities = {};\n if( xmlData[i + 3] === 'O' &&\n xmlData[i + 4] === 'C' &&\n xmlData[i + 5] === 'T' &&\n xmlData[i + 6] === 'Y' &&\n xmlData[i + 7] === 'P' &&\n xmlData[i + 8] === 'E')\n { \n i = i+9;\n let angleBracketsCount = 1;\n let hasBody = false, comment = false;\n let exp = \"\";\n for(;i<xmlData.length;i++){\n if (xmlData[i] === '<' && !comment) { //Determine the tag type\n if( hasBody && hasSeq(xmlData, \"!ENTITY\",i)){\n i += 7; \n let entityName, val;\n [entityName, val,i] = this.readEntityExp(xmlData,i+1,this.suppressValidationErr);\n if(val.indexOf(\"&\") === -1){ //Parameter entities are not supported\n const escaped = entityName.replace(/[.\\-+*:]/g, '\\\\.');\n entities[ entityName ] = {\n regx : RegExp( `&${escaped};`,\"g\"),\n val: val\n };\n }\n }\n else if( hasBody && hasSeq(xmlData, \"!ELEMENT\",i)) {\n i += 8;//Not supported\n const {index} = this.readElementExp(xmlData,i+1);\n i = index;\n }else if( hasBody && hasSeq(xmlData, \"!ATTLIST\",i)){\n i += 8;//Not supported\n // const {index} = this.readAttlistExp(xmlData,i+1);\n // i = index;\n }else if( hasBody && hasSeq(xmlData, \"!NOTATION\",i)) {\n i += 9;//Not supported\n const {index} = this.readNotationExp(xmlData,i+1,this.suppressValidationErr);\n i = index;\n }else if( hasSeq(xmlData, \"!--\",i) ) comment = true;\n else throw new Error(`Invalid DOCTYPE`);\n\n angleBracketsCount++;\n exp = \"\";\n } else if (xmlData[i] === '>') { //Read tag content\n if(comment){\n if( xmlData[i - 1] === \"-\" && xmlData[i - 2] === \"-\"){\n comment = false;\n angleBracketsCount--;\n }\n }else{\n angleBracketsCount--;\n }\n if (angleBracketsCount === 0) {\n break;\n }\n }else if( xmlData[i] === '['){\n hasBody = true;\n }else{\n exp += xmlData[i];\n }\n }\n if(angleBracketsCount !== 0){\n throw new Error(`Unclosed DOCTYPE`);\n }\n }else{\n throw new Error(`Invalid Tag instead of DOCTYPE`);\n }\n return {entities, i};\n }\n readEntityExp(xmlData, i) { \n //External entities are not supported\n // <!ENTITY ext SYSTEM \"http://normal-website.com\" >\n\n //Parameter entities are not supported\n // <!ENTITY entityname \"&anotherElement;\">\n\n //Internal entities are supported\n // <!ENTITY entityname \"replacement text\">\n\n // Skip leading whitespace after <!ENTITY\n i = skipWhitespace(xmlData, i);\n\n // Read entity name\n let entityName = \"\";\n while (i < xmlData.length && !/\\s/.test(xmlData[i]) && xmlData[i] !== '\"' && xmlData[i] !== \"'\") {\n entityName += xmlData[i];\n i++;\n }\n validateEntityName(entityName);\n\n // Skip whitespace after entity name\n i = skipWhitespace(xmlData, i);\n\n // Check for unsupported constructs (external entities or parameter entities)\n if(!this.suppressValidationErr){\n if (xmlData.substring(i, i + 6).toUpperCase() === \"SYSTEM\") {\n throw new Error(\"External entities are not supported\");\n }else if (xmlData[i] === \"%\") {\n throw new Error(\"Parameter entities are not supported\");\n }\n }\n\n // Read entity value (internal entity)\n let entityValue = \"\";\n [i, entityValue] = this.readIdentifierVal(xmlData, i, \"entity\");\n i--;\n return [entityName, entityValue, i ];\n }\n\n readNotationExp(xmlData, i) {\n // Skip leading whitespace after <!NOTATION\n i = skipWhitespace(xmlData, i);\n\n // Read notation name\n let notationName = \"\";\n while (i < xmlData.length && !/\\s/.test(xmlData[i])) {\n notationName += xmlData[i];\n i++;\n }\n !this.suppressValidationErr && validateEntityName(notationName);\n\n // Skip whitespace after notation name\n i = skipWhitespace(xmlData, i);\n\n // Check identifier type (SYSTEM or PUBLIC)\n const identifierType = xmlData.substring(i, i + 6).toUpperCase();\n if (!this.suppressValidationErr && identifierType !== \"SYSTEM\" && identifierType !== \"PUBLIC\") {\n throw new Error(`Expected SYSTEM or PUBLIC, found \"${identifierType}\"`);\n }\n i += identifierType.length;\n\n // Skip whitespace after identifier type\n i = skipWhitespace(xmlData, i);\n\n // Read public identifier (if PUBLIC)\n let publicIdentifier = null;\n let systemIdentifier = null;\n\n if (identifierType === \"PUBLIC\") {\n [i, publicIdentifier ] = this.readIdentifierVal(xmlData, i, \"publicIdentifier\");\n\n // Skip whitespace after public identifier\n i = skipWhitespace(xmlData, i);\n\n // Optionally read system identifier\n if (xmlData[i] === '\"' || xmlData[i] === \"'\") {\n [i, systemIdentifier ] = this.readIdentifierVal(xmlData, i,\"systemIdentifier\");\n }\n } else if (identifierType === \"SYSTEM\") {\n // Read system identifier (mandatory for SYSTEM)\n [i, systemIdentifier ] = this.readIdentifierVal(xmlData, i, \"systemIdentifier\");\n\n if (!this.suppressValidationErr && !systemIdentifier) {\n throw new Error(\"Missing mandatory system identifier for SYSTEM notation\");\n }\n }\n \n return {notationName, publicIdentifier, systemIdentifier, index: --i};\n }\n\n readIdentifierVal(xmlData, i, type) {\n let identifierVal = \"\";\n const startChar = xmlData[i];\n if (startChar !== '\"' && startChar !== \"'\") {\n throw new Error(`Expected quoted string, found \"${startChar}\"`);\n }\n i++;\n\n while (i < xmlData.length && xmlData[i] !== startChar) {\n identifierVal += xmlData[i];\n i++;\n }\n\n if (xmlData[i] !== startChar) {\n throw new Error(`Unterminated ${type} value`);\n }\n i++;\n return [i, identifierVal];\n }\n\n readElementExp(xmlData, i) {\n // <!ELEMENT br EMPTY>\n // <!ELEMENT div ANY>\n // <!ELEMENT title (#PCDATA)>\n // <!ELEMENT book (title, author+)>\n // <!ELEMENT name (content-model)>\n \n // Skip leading whitespace after <!ELEMENT\n i = skipWhitespace(xmlData, i);\n\n // Read element name\n let elementName = \"\";\n while (i < xmlData.length && !/\\s/.test(xmlData[i])) {\n elementName += xmlData[i];\n i++;\n }\n\n // Validate element name\n if (!this.suppressValidationErr && !isName(elementName)) {\n throw new Error(`Invalid element name: \"${elementName}\"`);\n }\n\n // Skip whitespace after element name\n i = skipWhitespace(xmlData, i);\n let contentModel = \"\";\n // Expect '(' to start content model\n if(xmlData[i] === \"E\" && hasSeq(xmlData, \"MPTY\",i)) i+=4;\n else if(xmlData[i] === \"A\" && hasSeq(xmlData, \"NY\",i)) i+=2;\n else if (xmlData[i] === \"(\") {\n i++; // Move past '('\n\n // Read content model\n while (i < xmlData.length && xmlData[i] !== \")\") {\n contentModel += xmlData[i];\n i++;\n }\n if (xmlData[i] !== \")\") {\n throw new Error(\"Unterminated content model\");\n }\n\n }else if(!this.suppressValidationErr){\n throw new Error(`Invalid Element Expression, found \"${xmlData[i]}\"`);\n }\n \n return {\n elementName,\n contentModel: contentModel.trim(),\n index: i\n };\n }\n\n readAttlistExp(xmlData, i) {\n // Skip leading whitespace after <!ATTLIST\n i = skipWhitespace(xmlData, i);\n\n // Read element name\n let elementName = \"\";\n while (i < xmlData.length && !/\\s/.test(xmlData[i])) {\n elementName += xmlData[i];\n i++;\n }\n\n // Validate element name\n validateEntityName(elementName)\n\n // Skip whitespace after element name\n i = skipWhitespace(xmlData, i);\n\n // Read attribute name\n let attributeName = \"\";\n while (i < xmlData.length && !/\\s/.test(xmlData[i])) {\n attributeName += xmlData[i];\n i++;\n }\n\n // Validate attribute name\n if (!validateEntityName(attributeName)) {\n throw new Error(`Invalid attribute name: \"${attributeName}\"`);\n }\n\n // Skip whitespace after attribute name\n i = skipWhitespace(xmlData, i);\n\n // Read attribute type\n let attributeType = \"\";\n if (xmlData.substring(i, i + 8).toUpperCase() === \"NOTATION\") {\n attributeType = \"NOTATION\";\n i += 8; // Move past \"NOTATION\"\n\n // Skip whitespace after \"NOTATION\"\n i = skipWhitespace(xmlData, i);\n\n // Expect '(' to start the list of notations\n if (xmlData[i] !== \"(\") {\n throw new Error(`Expected '(', found \"${xmlData[i]}\"`);\n }\n i++; // Move past '('\n\n // Read the list of allowed notations\n let allowedNotations = [];\n while (i < xmlData.length && xmlData[i] !== \")\") {\n let notation = \"\";\n while (i < xmlData.length && xmlData[i] !== \"|\" && xmlData[i] !== \")\") {\n notation += xmlData[i];\n i++;\n }\n\n // Validate notation name\n notation = notation.trim();\n if (!validateEntityName(notation)) {\n throw new Error(`Invalid notation name: \"${notation}\"`);\n }\n\n allowedNotations.push(notation);\n\n // Skip '|' separator or exit loop\n if (xmlData[i] === \"|\") {\n i++; // Move past '|'\n i = skipWhitespace(xmlData, i); // Skip optional whitespace after '|'\n }\n }\n\n if (xmlData[i] !== \")\") {\n throw new Error(\"Unterminated list of notations\");\n }\n i++; // Move past ')'\n\n // Store the allowed notations as part of the attribute type\n attributeType += \" (\" + allowedNotations.join(\"|\") + \")\";\n } else {\n // Handle simple types (e.g., CDATA, ID, IDREF, etc.)\n while (i < xmlData.length && !/\\s/.test(xmlData[i])) {\n attributeType += xmlData[i];\n i++;\n }\n\n // Validate simple attribute type\n const validTypes = [\"CDATA\", \"ID\", \"IDREF\", \"IDREFS\", \"ENTITY\", \"ENTITIES\", \"NMTOKEN\", \"NMTOKENS\"];\n if (!this.suppressValidationErr && !validTypes.includes(attributeType.toUpperCase())) {\n throw new Error(`Invalid attribute type: \"${attributeType}\"`);\n }\n }\n\n // Skip whitespace after attribute type\n i = skipWhitespace(xmlData, i);\n\n // Read default value\n let defaultValue = \"\";\n if (xmlData.substring(i, i + 8).toUpperCase() === \"#REQUIRED\") {\n defaultValue = \"#REQUIRED\";\n i += 8;\n } else if (xmlData.substring(i, i + 7).toUpperCase() === \"#IMPLIED\") {\n defaultValue = \"#IMPLIED\";\n i += 7;\n } else {\n [i, defaultValue] = this.readIdentifierVal(xmlData, i, \"ATTLIST\");\n }\n\n return {\n elementName,\n attributeName,\n attributeType,\n defaultValue,\n index: i\n }\n }\n}\n\n\n\nconst skipWhitespace = (data, index) => {\n while (index < data.length && /\\s/.test(data[index])) {\n index++;\n }\n return index;\n};\n\n\n\nfunction hasSeq(data, seq,i){\n for(let j=0;j<seq.length;j++){\n if(seq[j]!==data[i+j+1]) return false;\n }\n return true;\n}\n\nfunction validateEntityName(name){\n if (isName(name))\n\t return name;\n else\n throw new Error(`Invalid entity name ${name}`);\n}\n","const hexRegex = /^[-+]?0x[a-fA-F0-9]+$/;\nconst numRegex = /^([\\-\\+])?(0*)([0-9]*(\\.[0-9]*)?)$/;\n// const octRegex = /^0x[a-z0-9]+/;\n// const binRegex = /0x[a-z0-9]+/;\n\n \nconst consider = {\n hex : true,\n // oct: false,\n leadingZeros: true,\n decimalPoint: \"\\.\",\n eNotation: true,\n //skipLike: /regex/\n};\n\nexport default function toNumber(str, options = {}){\n options = Object.assign({}, consider, options );\n if(!str || typeof str !== \"string\" ) return str;\n \n let trimmedStr = str.trim();\n \n if(options.skipLike !== undefined && options.skipLike.test(trimmedStr)) return str;\n else if(str===\"0\") return 0;\n else if (options.hex && hexRegex.test(trimmedStr)) {\n return parse_int(trimmedStr, 16);\n // }else if (options.oct && octRegex.test(str)) {\n // return Number.parseInt(val, 8);\n }else if (trimmedStr.includes('e') || trimmedStr.includes('E')) { //eNotation\n return resolveEnotation(str,trimmedStr,options);\n // }else if (options.parseBin && binRegex.test(str)) {\n // return Number.parseInt(val, 2);\n }else{\n //separate negative sign, leading zeros, and rest number\n const match = numRegex.exec(trimmedStr);\n // +00.123 => [ , '+', '00', '.123', ..\n if(match){\n const sign = match[1] || \"\";\n const leadingZeros = match[2];\n let numTrimmedByZeros = trimZeros(match[3]); //complete num without leading zeros\n const decimalAdjacentToLeadingZeros = sign ? // 0., -00., 000.\n str[leadingZeros.length+1] === \".\" \n : str[leadingZeros.length] === \".\";\n\n //trim ending zeros for floating number\n if(!options.leadingZeros //leading zeros are not allowed\n && (leadingZeros.length > 1 \n || (leadingZeros.length === 1 && !decimalAdjacentToLeadingZeros))){\n // 00, 00.3, +03.24, 03, 03.24\n return str;\n }\n else{//no leading zeros or leading zeros are allowed\n const num = Number(trimmedStr);\n const parsedStr = String(num);\n\n if( num === 0) return num;\n if(parsedStr.search(/[eE]/) !== -1){ //given number is long and parsed to eNotation\n if(options.eNotation) return num;\n else return str;\n }else if(trimmedStr.indexOf(\".\") !== -1){ //floating number\n if(parsedStr === \"0\") return num; //0.0\n else if(parsedStr === numTrimmedByZeros) return num; //0.456. 0.79000\n else if( parsedStr === `${sign}${numTrimmedByZeros}`) return num;\n else return str;\n }\n \n let n = leadingZeros? numTrimmedByZeros : trimmedStr;\n if(leadingZeros){\n // -009 => -9\n return (n === parsedStr) || (sign+n === parsedStr) ? num : str\n }else {\n // +9\n return (n === parsedStr) || (n === sign+parsedStr) ? num : str\n }\n }\n }else{ //non-numeric string\n return str;\n }\n }\n}\n\nconst eNotationRegx = /^([-+])?(0*)(\\d*(\\.\\d*)?[eE][-\\+]?\\d+)$/;\nfunction resolveEnotation(str,trimmedStr,options){\n if(!options.eNotation) return str;\n const notation = trimmedStr.match(eNotationRegx); \n if(notation){\n let sign = notation[1] || \"\";\n const eChar = notation[3].indexOf(\"e\") === -1 ? \"E\" : \"e\";\n const leadingZeros = notation[2];\n const eAdjacentToLeadingZeros = sign ? // 0E.\n str[leadingZeros.length+1] === eChar \n : str[leadingZeros.length] === eChar;\n\n if(leadingZeros.length > 1 && eAdjacentToLeadingZeros) return str;\n else if(leadingZeros.length === 1 \n && (notation[3].startsWith(`.${eChar}`) || notation[3][0] === eChar)){\n return Number(trimmedStr);\n }else if(options.leadingZeros && !eAdjacentToLeadingZeros){ //accept with leading zeros\n //remove leading 0s\n trimmedStr = (notation[1] || \"\") + notation[3];\n return Number(trimmedStr);\n }else return str;\n }else{\n return str;\n }\n}\n\n/**\n * \n * @param {string} numStr without leading zeros\n * @returns \n */\nfunction trimZeros(numStr){\n if(numStr && numStr.indexOf(\".\") !== -1){//float\n numStr = numStr.replace(/0+$/, \"\"); //remove ending zeros\n if(numStr === \".\") numStr = \"0\";\n else if(numStr[0] === \".\") numStr = \"0\"+numStr;\n else if(numStr[numStr.length-1] === \".\") numStr = numStr.substring(0,numStr.length-1);\n return numStr;\n }\n return numStr;\n}\n\nfunction parse_int(numStr, base){\n //polyfill\n if(parseInt) return parseInt(numStr, base);\n else if(Number.parseInt) return Number.parseInt(numStr, base);\n else if(window && window.parseInt) return window.parseInt(numStr, base);\n else throw new Error(\"parseInt, Number.parseInt, window.parseInt are not supported\")\n}","export default function getIgnoreAttributesFn(ignoreAttributes) {\n if (typeof ignoreAttributes === 'function') {\n return ignoreAttributes\n }\n if (Array.isArray(ignoreAttributes)) {\n return (attrName) => {\n for (const pattern of ignoreAttributes) {\n if (typeof pattern === 'string' && attrName === pattern) {\n return true\n }\n if (pattern instanceof RegExp && pattern.test(attrName)) {\n return true\n }\n }\n }\n }\n return () => false\n}","'use strict';\n///@ts-check\n\nimport {getAllMatches, isExist} from '../util.js';\nimport xmlNode from './xmlNode.js';\nimport DocTypeReader from './DocTypeReader.js';\nimport toNumber from \"strnum\";\nimport getIgnoreAttributesFn from \"../ignoreAttributes.js\";\n\n// const regx =\n// '<((!\\\\[CDATA\\\\[([\\\\s\\\\S]*?)(]]>))|((NAME:)?(NAME))([^>]*)>|((\\\\/)(NAME)\\\\s*>))([^<]*)'\n// .replace(/NAME/g, util.nameRegexp);\n\n//const tagsRegx = new RegExp(\"<(\\\\/?[\\\\w:\\\\-\\._]+)([^>]*)>(\\\\s*\"+cdataRegx+\")*([^<]+)?\",\"g\");\n//const tagsRegx = new RegExp(\"<(\\\\/?)((\\\\w*:)?([\\\\w:\\\\-\\._]+))([^>]*)>([^<]*)(\"+cdataRegx+\"([^<]*))*([^<]+)?\",\"g\");\n\nexport default class OrderedObjParser{\n constructor(options){\n this.options = options;\n this.currentNode = null;\n this.tagsNodeStack = [];\n this.docTypeEntities = {};\n this.lastEntities = {\n \"apos\" : { regex: /&(apos|#39|#x27);/g, val : \"'\"},\n \"gt\" : { regex: /&(gt|#62|#x3E);/g, val : \">\"},\n \"lt\" : { regex: /&(lt|#60|#x3C);/g, val : \"<\"},\n \"quot\" : { regex: /&(quot|#34|#x22);/g, val : \"\\\"\"},\n };\n this.ampEntity = { regex: /&(amp|#38|#x26);/g, val : \"&\"};\n this.htmlEntities = {\n \"space\": { regex: /&(nbsp|#160);/g, val: \" \" },\n // \"lt\" : { regex: /&(lt|#60);/g, val: \"<\" },\n // \"gt\" : { regex: /&(gt|#62);/g, val: \">\" },\n // \"amp\" : { regex: /&(amp|#38);/g, val: \"&\" },\n // \"quot\" : { regex: /&(quot|#34);/g, val: \"\\\"\" },\n // \"apos\" : { regex: /&(apos|#39);/g, val: \"'\" },\n \"cent\" : { regex: /&(cent|#162);/g, val: \"¢\" },\n \"pound\" : { regex: /&(pound|#163);/g, val: \"£\" },\n \"yen\" : { regex: /&(yen|#165);/g, val: \"¥\" },\n \"euro\" : { regex: /&(euro|#8364);/g, val: \"€\" },\n \"copyright\" : { regex: /&(copy|#169);/g, val: \"©\" },\n \"reg\" : { regex: /&(reg|#174);/g, val: \"®\" },\n \"inr\" : { regex: /&(inr|#8377);/g, val: \"₹\" },\n \"num_dec\": { regex: /&#([0-9]{1,7});/g, val : (_, str) => fromCodePoint(str, 10, \"&#\") },\n \"num_hex\": { regex: /&#x([0-9a-fA-F]{1,6});/g, val : (_, str) => fromCodePoint(str, 16, \"&#x\") },\n };\n this.addExternalEntities = addExternalEntities;\n this.parseXml = parseXml;\n this.parseTextData = parseTextData;\n this.resolveNameSpace = resolveNameSpace;\n this.buildAttributesMap = buildAttributesMap;\n this.isItStopNode = isItStopNode;\n this.replaceEntitiesValue = replaceEntitiesValue;\n this.readStopNodeData = readStopNodeData;\n this.saveTextToParentTag = saveTextToParentTag;\n this.addChild = addChild;\n this.ignoreAttributesFn = getIgnoreAttributesFn(this.options.ignoreAttributes)\n\n if(this.options.stopNodes && this.options.stopNodes.length > 0){\n this.stopNodesExact = new Set();\n this.stopNodesWildcard = new Set();\n for(let i = 0; i < this.options.stopNodes.length; i++){\n const stopNodeExp = this.options.stopNodes[i];\n if(typeof stopNodeExp !== 'string') continue;\n if(stopNodeExp.startsWith(\"*.\")){\n this.stopNodesWildcard.add(stopNodeExp.substring(2));\n }else{\n this.stopNodesExact.add(stopNodeExp);\n }\n }\n }\n }\n\n}\n\nfunction addExternalEntities(externalEntities){\n const entKeys = Object.keys(externalEntities);\n for (let i = 0; i < entKeys.length; i++) {\n const ent = entKeys[i];\n const escaped = ent.replace(/[.\\-+*:]/g, '\\\\.');\n this.lastEntities[ent] = {\n regex: new RegExp(\"&\"+escaped+\";\",\"g\"),\n val : externalEntities[ent]\n }\n }\n}\n\n/**\n * @param {string} val\n * @param {string} tagName\n * @param {string} jPath\n * @param {boolean} dontTrim\n * @param {boolean} hasAttributes\n * @param {boolean} isLeafNode\n * @param {boolean} escapeEntities\n */\nfunction parseTextData(val, tagName, jPath, dontTrim, hasAttributes, isLeafNode, escapeEntities) {\n if (val !== undefined) {\n if (this.options.trimValues && !dontTrim) {\n val = val.trim();\n }\n if(val.length > 0){\n if(!escapeEntities) val = this.replaceEntitiesValue(val);\n \n const newval = this.options.tagValueProcessor(tagName, val, jPath, hasAttributes, isLeafNode);\n if(newval === null || newval === undefined){\n //don't parse\n return val;\n }else if(typeof newval !== typeof val || newval !== val){\n //overwrite\n return newval;\n }else if(this.options.trimValues){\n return parseValue(val, this.options.parseTagValue, this.options.numberParseOptions);\n }else{\n const trimmedVal = val.trim();\n if(trimmedVal === val){\n return parseValue(val, this.options.parseTagValue, this.options.numberParseOptions);\n }else{\n return val;\n }\n }\n }\n }\n}\n\nfunction resolveNameSpace(tagname) {\n if (this.options.removeNSPrefix) {\n const tags = tagname.split(':');\n const prefix = tagname.charAt(0) === '/' ? '/' : '';\n if (tags[0] === 'xmlns') {\n return '';\n }\n if (tags.length === 2) {\n tagname = prefix + tags[1];\n }\n }\n return tagname;\n}\n\n//TODO: change regex to capture NS\n//const attrsRegx = new RegExp(\"([\\\\w\\\\-\\\\.\\\\:]+)\\\\s*=\\\\s*(['\\\"])((.|\\n)*?)\\\\2\",\"gm\");\nconst attrsRegx = new RegExp('([^\\\\s=]+)\\\\s*(=\\\\s*([\\'\"])([\\\\s\\\\S]*?)\\\\3)?', 'gm');\n\nfunction buildAttributesMap(attrStr, jPath) {\n if (this.options.ignoreAttributes !== true && typeof attrStr === 'string') {\n // attrStr = attrStr.replace(/\\r?\\n/g, ' ');\n //attrStr = attrStr || attrStr.trim();\n\n const matches = getAllMatches(attrStr, attrsRegx);\n const len = matches.length; //don't make it inline\n const attrs = {};\n for (let i = 0; i < len; i++) {\n const attrName = this.resolveNameSpace(matches[i][1]);\n if (this.ignoreAttributesFn(attrName, jPath)) {\n continue\n }\n let oldVal = matches[i][4];\n let aName = this.options.attributeNamePrefix + attrName;\n if (attrName.length) {\n if (this.options.transformAttributeName) {\n aName = this.options.transformAttributeName(aName);\n }\n if(aName === \"__proto__\") aName = \"#__proto__\";\n if (oldVal !== undefined) {\n if (this.options.trimValues) {\n oldVal = oldVal.trim();\n }\n oldVal = this.replaceEntitiesValue(oldVal);\n const newVal = this.options.attributeValueProcessor(attrName, oldVal, jPath);\n if(newVal === null || newVal === undefined){\n //don't parse\n attrs[aName] = oldVal;\n }else if(typeof newVal !== typeof oldVal || newVal !== oldVal){\n //overwrite\n attrs[aName] = newVal;\n }else{\n //parse\n attrs[aName] = parseValue(\n oldVal,\n this.options.parseAttributeValue,\n this.options.numberParseOptions\n );\n }\n } else if (this.options.allowBooleanAttributes) {\n attrs[aName] = true;\n }\n }\n }\n if (!Object.keys(attrs).length) {\n return;\n }\n if (this.options.attributesGroupName) {\n const attrCollection = {};\n attrCollection[this.options.attributesGroupName] = attrs;\n return attrCollection;\n }\n return attrs\n }\n}\n\nconst parseXml = function(xmlData) {\n xmlData = xmlData.replace(/\\r\\n?/g, \"\\n\"); //TODO: remove this line\n const xmlObj = new xmlNode('!xml');\n let currentNode = xmlObj;\n let textData = \"\";\n let jPath = \"\";\n const docTypeReader = new DocTypeReader(this.options.processEntities);\n for(let i=0; i< xmlData.length; i++){//for each char in XML data\n const ch = xmlData[i];\n if(ch === '<'){\n // const nextIndex = i+1;\n // const _2ndChar = xmlData[nextIndex];\n if( xmlData[i+1] === '/') {//Closing Tag\n const closeIndex = findClosingIndex(xmlData, \">\", i, \"Closing Tag is not closed.\")\n let tagName = xmlData.substring(i+2,closeIndex).trim();\n\n if(this.options.removeNSPrefix){\n const colonIndex = tagName.indexOf(\":\");\n if(colonIndex !== -1){\n tagName = tagName.substr(colonIndex+1);\n }\n }\n\n if(this.options.transformTagName) {\n tagName = this.options.transformTagName(tagName);\n }\n\n if(currentNode){\n textData = this.saveTextToParentTag(textData, currentNode, jPath);\n }\n\n //check if last tag of nested tag was unpaired tag\n const lastTagName = jPath.substring(jPath.lastIndexOf(\".\")+1);\n if(tagName && this.options.unpairedTags.indexOf(tagName) !== -1 ){\n throw new Error(`Unpaired tag can not be used as closing tag: </${tagName}>`);\n }\n let propIndex = 0\n if(lastTagName && this.options.unpairedTags.indexOf(lastTagName) !== -1 ){\n propIndex = jPath.lastIndexOf('.', jPath.lastIndexOf('.')-1)\n this.tagsNodeStack.pop();\n }else{\n propIndex = jPath.lastIndexOf(\".\");\n }\n jPath = jPath.substring(0, propIndex);\n\n currentNode = this.tagsNodeStack.pop();//avoid recursion, set the parent tag scope\n textData = \"\";\n i = closeIndex;\n } else if( xmlData[i+1] === '?') {\n\n let tagData = readTagExp(xmlData,i, false, \"?>\");\n if(!tagData) throw new Error(\"Pi Tag is not closed.\");\n\n textData = this.saveTextToParentTag(textData, currentNode, jPath);\n if( (this.options.ignoreDeclaration && tagData.tagName === \"?xml\") || this.options.ignorePiTags){\n //do nothing\n }else{\n \n const childNode = new xmlNode(tagData.tagName);\n childNode.add(this.options.textNodeName, \"\");\n \n if(tagData.tagName !== tagData.tagExp && tagData.attrExpPresent){\n childNode[\":@\"] = this.buildAttributesMap(tagData.tagExp, jPath);\n }\n this.addChild(currentNode, childNode, jPath, i);\n }\n\n\n i = tagData.closeIndex + 1;\n } else if(xmlData.substr(i + 1, 3) === '!--') {\n const endIndex = findClosingIndex(xmlData, \"-->\", i+4, \"Comment is not closed.\")\n if(this.options.commentPropName){\n const comment = xmlData.substring(i + 4, endIndex - 2);\n\n textData = this.saveTextToParentTag(textData, currentNode, jPath);\n\n currentNode.add(this.options.commentPropName, [ { [this.options.textNodeName] : comment } ]);\n }\n i = endIndex;\n } else if( xmlData.substr(i + 1, 2) === '!D') {\n const result = docTypeReader.readDocType(xmlData, i);\n this.docTypeEntities = result.entities;\n i = result.i;\n }else if(xmlData.substr(i + 1, 2) === '![') {\n const closeIndex = findClosingIndex(xmlData, \"]]>\", i, \"CDATA is not closed.\") - 2;\n const tagExp = xmlData.substring(i + 9,closeIndex);\n\n textData = this.saveTextToParentTag(textData, currentNode, jPath);\n\n let val = this.parseTextData(tagExp, currentNode.tagname, jPath, true, false, true, true);\n if(val == undefined) val = \"\";\n\n //cdata should be set even if it is 0 length string\n if(this.options.cdataPropName){\n currentNode.add(this.options.cdataPropName, [ { [this.options.textNodeName] : tagExp } ]);\n }else{\n currentNode.add(this.options.textNodeName, val);\n }\n \n i = closeIndex + 2;\n }else {//Opening tag\n let result = readTagExp(xmlData,i, this.options.removeNSPrefix);\n let tagName= result.tagName;\n const rawTagName = result.rawTagName;\n let tagExp = result.tagExp;\n let attrExpPresent = result.attrExpPresent;\n let closeIndex = result.closeIndex;\n\n if (this.options.transformTagName) {\n //console.log(tagExp, tagName)\n const newTagName = this.options.transformTagName(tagName);\n if(tagExp === tagName) {\n tagExp = newTagName\n }\n tagName = newTagName;\n }\n \n //save text as child node\n if (currentNode && textData) {\n if(currentNode.tagname !== '!xml'){\n //when nested tag is found\n textData = this.saveTextToParentTag(textData, currentNode, jPath, false);\n }\n }\n\n //check if last tag was unpaired tag\n const lastTag = currentNode;\n if(lastTag && this.options.unpairedTags.indexOf(lastTag.tagname) !== -1 ){\n currentNode = this.tagsNodeStack.pop();\n jPath = jPath.substring(0, jPath.lastIndexOf(\".\"));\n }\n if(tagName !== xmlObj.tagname){\n jPath += jPath ? \".\" + tagName : tagName;\n }\n const startIndex = i;\n if (this.isItStopNode(this.stopNodesExact, this.stopNodesWildcard, jPath, tagName)) {\n let tagContent = \"\";\n //self-closing tag\n if(tagExp.length > 0 && tagExp.lastIndexOf(\"/\") === tagExp.length - 1){\n if(tagName[tagName.length - 1] === \"/\"){ //remove trailing '/'\n tagName = tagName.substr(0, tagName.length - 1);\n jPath = jPath.substr(0, jPath.length - 1);\n tagExp = tagName;\n }else{\n tagExp = tagExp.substr(0, tagExp.length - 1);\n }\n i = result.closeIndex;\n }\n //unpaired tag\n else if(this.options.unpairedTags.indexOf(tagName) !== -1){\n \n i = result.closeIndex;\n }\n //normal tag\n else{\n //read until closing tag is found\n const result = this.readStopNodeData(xmlData, rawTagName, closeIndex + 1);\n if(!result) throw new Error(`Unexpected end of ${rawTagName}`);\n i = result.i;\n tagContent = result.tagContent;\n }\n\n const childNode = new xmlNode(tagName);\n\n if(tagName !== tagExp && attrExpPresent){\n childNode[\":@\"] = this.buildAttributesMap(tagExp, jPath\n );\n }\n if(tagContent) {\n tagContent = this.parseTextData(tagContent, tagName, jPath, true, attrExpPresent, true, true);\n }\n \n jPath = jPath.substr(0, jPath.lastIndexOf(\".\"));\n childNode.add(this.options.textNodeName, tagContent);\n \n this.addChild(currentNode, childNode, jPath, startIndex);\n }else{\n //selfClosing tag\n if(tagExp.length > 0 && tagExp.lastIndexOf(\"/\") === tagExp.length - 1){\n if(tagName[tagName.length - 1] === \"/\"){ //remove trailing '/'\n tagName = tagName.substr(0, tagName.length - 1);\n jPath = jPath.substr(0, jPath.length - 1);\n tagExp = tagName;\n }else{\n tagExp = tagExp.substr(0, tagExp.length - 1);\n }\n \n if(this.options.transformTagName) {\n const newTagName = this.options.transformTagName(tagName);\n if(tagExp === tagName) {\n tagExp = newTagName\n }\n tagName = newTagName;\n }\n\n const childNode = new xmlNode(tagName);\n if(tagName !== tagExp && attrExpPresent){\n childNode[\":@\"] = this.buildAttributesMap(tagExp, jPath);\n }\n this.addChild(currentNode, childNode, jPath, startIndex);\n jPath = jPath.substr(0, jPath.lastIndexOf(\".\"));\n }\n //opening tag\n else{\n const childNode = new xmlNode( tagName);\n this.tagsNodeStack.push(currentNode);\n \n if(tagName !== tagExp && attrExpPresent){\n childNode[\":@\"] = this.buildAttributesMap(tagExp, jPath);\n }\n this.addChild(currentNode, childNode, jPath, startIndex);\n currentNode = childNode;\n }\n textData = \"\";\n i = closeIndex;\n }\n }\n }else{\n textData += xmlData[i];\n }\n }\n return xmlObj.child;\n}\n\nfunction addChild(currentNode, childNode, jPath, startIndex){\n // unset startIndex if not requested\n if (!this.options.captureMetaData) startIndex = undefined;\n const result = this.options.updateTag(childNode.tagname, jPath, childNode[\":@\"])\n if(result === false){\n //do nothing\n } else if(typeof result === \"string\"){\n childNode.tagname = result\n currentNode.addChild(childNode, startIndex);\n }else{\n currentNode.addChild(childNode, startIndex);\n }\n}\n\nconst replaceEntitiesValue = function(val){\n\n if(this.options.processEntities){\n for(let entityName in this.docTypeEntities){\n const entity = this.docTypeEntities[entityName];\n val = val.replace( entity.regx, entity.val);\n }\n for(let entityName in this.lastEntities){\n const entity = this.lastEntities[entityName];\n val = val.replace( entity.regex, entity.val);\n }\n if(this.options.htmlEntities){\n for(let entityName in this.htmlEntities){\n const entity = this.htmlEntities[entityName];\n val = val.replace( entity.regex, entity.val);\n }\n }\n val = val.replace( this.ampEntity.regex, this.ampEntity.val);\n }\n return val;\n}\nfunction saveTextToParentTag(textData, currentNode, jPath, isLeafNode) {\n if (textData) { //store previously collected data as textNode\n if(isLeafNode === undefined) isLeafNode = currentNode.child.length === 0\n \n textData = this.parseTextData(textData,\n currentNode.tagname,\n jPath,\n false,\n currentNode[\":@\"] ? Object.keys(currentNode[\":@\"]).length !== 0 : false,\n isLeafNode);\n\n if (textData !== undefined && textData !== \"\")\n currentNode.add(this.options.textNodeName, textData);\n textData = \"\";\n }\n return textData;\n}\n\n//TODO: use jPath to simplify the logic\n/**\n * @param {Set} stopNodesExact\n * @param {Set} stopNodesWildcard\n * @param {string} jPath\n * @param {string} currentTagName\n */\nfunction isItStopNode(stopNodesExact, stopNodesWildcard, jPath, currentTagName){\n if(stopNodesWildcard && stopNodesWildcard.has(currentTagName)) return true;\n if(stopNodesExact && stopNodesExact.has(jPath)) return true;\n return false;\n}\n\n/**\n * Returns the tag Expression and where it is ending handling single-double quotes situation\n * @param {string} xmlData \n * @param {number} i starting index\n * @returns \n */\nfunction tagExpWithClosingIndex(xmlData, i, closingChar = \">\"){\n let attrBoundary;\n let tagExp = \"\";\n for (let index = i; index < xmlData.length; index++) {\n let ch = xmlData[index];\n if (attrBoundary) {\n if (ch === attrBoundary) attrBoundary = \"\";//reset\n } else if (ch === '\"' || ch === \"'\") {\n attrBoundary = ch;\n } else if (ch === closingChar[0]) {\n if(closingChar[1]){\n if(xmlData[index + 1] === closingChar[1]){\n return {\n data: tagExp,\n index: index\n }\n }\n }else{\n return {\n data: tagExp,\n index: index\n }\n }\n } else if (ch === '\\t') {\n ch = \" \"\n }\n tagExp += ch;\n }\n}\n\nfunction findClosingIndex(xmlData, str, i, errMsg){\n const closingIndex = xmlData.indexOf(str, i);\n if(closingIndex === -1){\n throw new Error(errMsg)\n }else{\n return closingIndex + str.length - 1;\n }\n}\n\nfunction readTagExp(xmlData,i, removeNSPrefix, closingChar = \">\"){\n const result = tagExpWithClosingIndex(xmlData, i+1, closingChar);\n if(!result) return;\n let tagExp = result.data;\n const closeIndex = result.index;\n const separatorIndex = tagExp.search(/\\s/);\n let tagName = tagExp;\n let attrExpPresent = true;\n if(separatorIndex !== -1){//separate tag name and attributes expression\n tagName = tagExp.substring(0, separatorIndex);\n tagExp = tagExp.substring(separatorIndex + 1).trimStart();\n }\n\n const rawTagName = tagName;\n if(removeNSPrefix){\n const colonIndex = tagName.indexOf(\":\");\n if(colonIndex !== -1){\n tagName = tagName.substr(colonIndex+1);\n attrExpPresent = tagName !== result.data.substr(colonIndex + 1);\n }\n }\n\n return {\n tagName: tagName,\n tagExp: tagExp,\n closeIndex: closeIndex,\n attrExpPresent: attrExpPresent,\n rawTagName: rawTagName,\n }\n}\n/**\n * find paired tag for a stop node\n * @param {string} xmlData \n * @param {string} tagName \n * @param {number} i \n */\nfunction readStopNodeData(xmlData, tagName, i){\n const startIndex = i;\n // Starting at 1 since we already have an open tag\n let openTagCount = 1;\n\n for (; i < xmlData.length; i++) {\n if( xmlData[i] === \"<\"){ \n if (xmlData[i+1] === \"/\") {//close tag\n const closeIndex = findClosingIndex(xmlData, \">\", i, `${tagName} is not closed`);\n let closeTagName = xmlData.substring(i+2,closeIndex).trim();\n if(closeTagName === tagName){\n openTagCount--;\n if (openTagCount === 0) {\n return {\n tagContent: xmlData.substring(startIndex, i),\n i : closeIndex\n }\n }\n }\n i=closeIndex;\n } else if(xmlData[i+1] === '?') { \n const closeIndex = findClosingIndex(xmlData, \"?>\", i+1, \"StopNode is not closed.\")\n i=closeIndex;\n } else if(xmlData.substr(i + 1, 3) === '!--') { \n const closeIndex = findClosingIndex(xmlData, \"-->\", i+3, \"StopNode is not closed.\")\n i=closeIndex;\n } else if(xmlData.substr(i + 1, 2) === '![') { \n const closeIndex = findClosingIndex(xmlData, \"]]>\", i, \"StopNode is not closed.\") - 2;\n i=closeIndex;\n } else {\n const tagData = readTagExp(xmlData, i, '>')\n\n if (tagData) {\n const openTagName = tagData && tagData.tagName;\n if (openTagName === tagName && tagData.tagExp[tagData.tagExp.length-1] !== \"/\") {\n openTagCount++;\n }\n i=tagData.closeIndex;\n }\n }\n }\n }//end for loop\n}\n\nfunction parseValue(val, shouldParse, options) {\n if (shouldParse && typeof val === 'string') {\n //console.log(options)\n const newval = val.trim();\n if(newval === 'true' ) return true;\n else if(newval === 'false' ) return false;\n else return toNumber(val, options);\n } else {\n if (isExist(val)) {\n return val;\n } else {\n return '';\n }\n }\n}\n\nfunction fromCodePoint(str, base, prefix){\n const codePoint = Number.parseInt(str, base);\n\n if (codePoint >= 0 && codePoint <= 0x10FFFF) {\n return String.fromCodePoint(codePoint);\n } else {\n return prefix +str + \";\";\n }\n}","'use strict';\n\nimport XmlNode from './xmlNode.js';\n\nconst METADATA_SYMBOL = XmlNode.getMetaDataSymbol();\n\n/**\n * \n * @param {array} node \n * @param {any} options \n * @returns \n */\nexport default function prettify(node, options){\n return compress( node, options);\n}\n\n/**\n * \n * @param {array} arr \n * @param {object} options \n * @param {string} jPath \n * @returns object\n */\nfunction compress(arr, options, jPath){\n let text;\n const compressedObj = {};\n for (let i = 0; i < arr.length; i++) {\n const tagObj = arr[i];\n const property = propName(tagObj);\n let newJpath = \"\";\n if(jPath === undefined) newJpath = property;\n else newJpath = jPath + \".\" + property;\n\n if(property === options.textNodeName){\n if(text === undefined) text = tagObj[property];\n else text += \"\" + tagObj[property];\n }else if(property === undefined){\n continue;\n }else if(tagObj[property]){\n \n let val = compress(tagObj[property], options, newJpath);\n const isLeaf = isLeafTag(val, options);\n if (tagObj[METADATA_SYMBOL] !== undefined) {\n val[METADATA_SYMBOL] = tagObj[METADATA_SYMBOL]; // copy over metadata\n }\n\n if(tagObj[\":@\"]){\n assignAttributes( val, tagObj[\":@\"], newJpath, options);\n }else if(Object.keys(val).length === 1 && val[options.textNodeName] !== undefined && !options.alwaysCreateTextNode){\n val = val[options.textNodeName];\n }else if(Object.keys(val).length === 0){\n if(options.alwaysCreateTextNode) val[options.textNodeName] = \"\";\n else val = \"\";\n }\n\n if(compressedObj[property] !== undefined && compressedObj.hasOwnProperty(property)) {\n if(!Array.isArray(compressedObj[property])) {\n compressedObj[property] = [ compressedObj[property] ];\n }\n compressedObj[property].push(val);\n }else{\n //TODO: if a node is not an array, then check if it should be an array\n //also determine if it is a leaf node\n if (options.isArray(property, newJpath, isLeaf )) {\n compressedObj[property] = [val];\n }else{\n compressedObj[property] = val;\n }\n }\n }\n \n }\n // if(text && text.length > 0) compressedObj[options.textNodeName] = text;\n if(typeof text === \"string\"){\n if(text.length > 0) compressedObj[options.textNodeName] = text;\n }else if(text !== undefined) compressedObj[options.textNodeName] = text;\n return compressedObj;\n}\n\nfunction propName(obj){\n const keys = Object.keys(obj);\n for (let i = 0; i < keys.length; i++) {\n const key = keys[i];\n if(key !== \":@\") return key;\n }\n}\n\nfunction assignAttributes(obj, attrMap, jpath, options){\n if (attrMap) {\n const keys = Object.keys(attrMap);\n const len = keys.length; //don't make it inline\n for (let i = 0; i < len; i++) {\n const atrrName = keys[i];\n if (options.isArray(atrrName, jpath + \".\" + atrrName, true, true)) {\n obj[atrrName] = [ attrMap[atrrName] ];\n } else {\n obj[atrrName] = attrMap[atrrName];\n }\n }\n }\n}\n\nfunction isLeafTag(obj, options){\n const { textNodeName } = options;\n const propCount = Object.keys(obj).length;\n \n if (propCount === 0) {\n return true;\n }\n\n if (\n propCount === 1 &&\n (obj[textNodeName] || typeof obj[textNodeName] === \"boolean\" || obj[textNodeName] === 0)\n ) {\n return true;\n }\n\n return false;\n}\n","import { buildOptions} from './OptionsBuilder.js';\nimport OrderedObjParser from './OrderedObjParser.js';\nimport prettify from './node2json.js';\nimport {validate} from \"../validator.js\";\nimport XmlNode from './xmlNode.js';\n\nexport default class XMLParser{\n \n constructor(options){\n this.externalEntities = {};\n this.options = buildOptions(options);\n \n }\n /**\n * Parse XML dats to JS object \n * @param {string|Uint8Array} xmlData \n * @param {boolean|Object} validationOption \n */\n parse(xmlData,validationOption){\n if(typeof xmlData !== \"string\" && xmlData.toString){\n xmlData = xmlData.toString();\n }else if(typeof xmlData !== \"string\"){\n throw new Error(\"XML data is accepted in String or Bytes[] form.\")\n }\n \n if( validationOption){\n if(validationOption === true) validationOption = {}; //validate with default options\n \n const result = validate(xmlData, validationOption);\n if (result !== true) {\n throw Error( `${result.err.msg}:${result.err.line}:${result.err.col}` )\n }\n }\n const orderedObjParser = new OrderedObjParser(this.options);\n orderedObjParser.addExternalEntities(this.externalEntities);\n const orderedResult = orderedObjParser.parseXml(xmlData);\n if(this.options.preserveOrder || orderedResult === undefined) return orderedResult;\n else return prettify(orderedResult, this.options);\n }\n\n /**\n * Add Entity which is not by default supported by this library\n * @param {string} key \n * @param {string} value \n */\n addEntity(key, value){\n if(value.indexOf(\"&\") !== -1){\n throw new Error(\"Entity value can't have '&'\")\n }else if(key.indexOf(\"&\") !== -1 || key.indexOf(\";\") !== -1){\n throw new Error(\"An entity must be set without '&' and ';'. Eg. use '#xD' for '&#xD;'\")\n }else if(value === \"&\"){\n throw new Error(\"An entity with value '&' is not permitted\");\n }else{\n this.externalEntities[key] = value;\n }\n }\n\n /**\n * Returns a Symbol that can be used to access the metadata\n * property on a node.\n * \n * If Symbol is not available in the environment, an ordinary property is used\n * and the name of the property is here returned.\n * \n * The XMLMetaData property is only present when `captureMetaData`\n * is true in the options.\n */\n static getMetaDataSymbol() {\n return XmlNode.getMetaDataSymbol();\n }\n}\n","/**\n * JATS XML parser for PMC articles.\n *\n * Parses JATS (Journal Article Tag Suite) XML into an intermediate\n * representation for Markdown conversion.\n *\n * Uses fast-xml-parser with `preserveOrder: true` to maintain document order\n * of interleaved elements (e.g. text, citations, formatting).\n */\nimport { XMLParser } from \"fast-xml-parser\";\nconst parser = new XMLParser({\n ignoreAttributes: false,\n attributeNamePrefix: \"@_\",\n textNodeName: \"#text\",\n trimValues: false,\n preserveOrder: true,\n processEntities: true,\n htmlEntities: true,\n});\n// ─── Navigation Helpers ──────────────────────────────────────────────\n/** Get the tag name of an ordered node (the first key that isn't \":@\" or \"#text\"). */\nfunction getTagName(node) {\n for (const key of Object.keys(node)) {\n if (key !== \":@\" && key !== \"#text\")\n return key;\n }\n return undefined;\n}\n/** Get the children array of an element node. */\nfunction getChildren(node) {\n const tag = getTagName(node);\n if (!tag)\n return [];\n const children = node[tag];\n return Array.isArray(children) ? children : [];\n}\n/** Get attributes of an element node. */\nfunction getAttr(node, attrName) {\n const attrs = node[\":@\"];\n if (!attrs)\n return undefined;\n const val = attrs[`@_${attrName}`];\n return val != null ? String(val) : undefined;\n}\n/** Get all attributes of an element node (strips @_ prefix for consistency with getAttr). */\nfunction getAttrs(node) {\n const attrs = node[\":@\"];\n if (!attrs)\n return {};\n const result = {};\n for (const [key, value] of Object.entries(attrs)) {\n if (key.startsWith(\"@_\")) {\n result[key.slice(2)] = String(value);\n }\n }\n return result;\n}\n/** Find the first child element with the given tag name. */\nfunction findChild(children, tagName) {\n for (const child of children) {\n if (tagName in child) {\n const childArr = child[tagName];\n return {\n node: child,\n children: Array.isArray(childArr) ? childArr : [],\n attrs: getAttrs(child),\n };\n }\n }\n return undefined;\n}\n/** Find all child elements with the given tag name. */\nfunction findChildren(children, tagName) {\n const results = [];\n for (const child of children) {\n if (tagName in child) {\n const childArr = child[tagName];\n results.push({\n node: child,\n children: Array.isArray(childArr) ? childArr : [],\n attrs: getAttrs(child),\n });\n }\n }\n return results;\n}\n/** Get text content from a #text node. */\nfunction getTextContent(child) {\n if (\"#text\" in child) {\n const val = child[\"#text\"];\n return val != null ? String(val) : undefined;\n }\n return undefined;\n}\n/**\n * Find the <article> element, handling optional <pmc-articleset> wrapper\n * that appears in efetch responses.\n */\nfunction findArticle(parsed) {\n const direct = findChild(parsed, \"article\");\n if (direct)\n return direct;\n const wrapper = findChild(parsed, \"pmc-articleset\");\n if (wrapper)\n return findChild(wrapper.children, \"article\");\n return undefined;\n}\n// ─── Text Extraction ─────────────────────────────────────────────────\n/** Tags whose text content should be followed by a space when adjacent to other content. */\nconst SPACE_AFTER_TAGS = new Set([\"surname\", \"given-names\", \"name\", \"string-name\"]);\n/**\n * Extract plain text from a node that may contain nested elements.\n * Recursively collects all text content from preserveOrder nodes.\n *\n * When extracting text from inline container elements (e.g. `<name>`,\n * `<string-name>`), inserts a space between adjacent child elements\n * that would otherwise concatenate without whitespace (e.g.\n * `<surname>McGuire</surname><given-names>N</given-names>` → `McGuire N`).\n */\nfunction extractAllText(node) {\n if (node == null)\n return \"\";\n if (typeof node === \"string\")\n return node;\n if (typeof node === \"number\")\n return String(node);\n if (Array.isArray(node)) {\n return joinChildTexts(node);\n }\n if (typeof node === \"object\") {\n const obj = node;\n // Text node\n const text = getTextContent(obj);\n if (text != null)\n return text;\n // Element node — recurse into children\n const tag = getTagName(obj);\n if (tag) {\n const children = obj[tag];\n if (Array.isArray(children)) {\n return joinChildTexts(children);\n }\n }\n }\n return \"\";\n}\n/**\n * Join extracted text from an array of child nodes, inserting spaces\n * between adjacent inline elements where no whitespace separator exists.\n */\nfunction joinChildTexts(children) {\n const parts = [];\n for (const child of children) {\n const text = extractAllText(child);\n if (!text)\n continue;\n const tag = getTagName(child);\n // If this is a space-after tag and there's previous content that doesn't\n // end with whitespace or punctuation, insert a space before this text.\n if (tag && SPACE_AFTER_TAGS.has(tag) && parts.length > 0) {\n const prev = parts.at(-1);\n if (prev && !/[\\s,;.:()\\-/]$/.test(prev)) {\n parts.push(\" \");\n }\n }\n parts.push(text);\n // If this is a space-after tag, check if a space is needed after.\n // We handle this by peeking: space will be inserted before the next\n // element if needed (handled above). But we also need to handle\n // the case where the next sibling is a text node starting without space.\n // That's already handled since text nodes include their own whitespace.\n }\n return parts.join(\"\");\n}\n// ─── Metadata Parsing ────────────────────────────────────────────────\n/** Extract DOI, PMCID, and PMID from article-id elements. */\nfunction parseArticleIds(metaChildren) {\n const articleIds = findChildren(metaChildren, \"article-id\");\n const result = {};\n for (const idEntry of articleIds) {\n const idType = idEntry.attrs[\"pub-id-type\"];\n const idText = extractAllText(idEntry.children);\n if (idType === \"doi\")\n result.doi = idText;\n if (idType === \"pmc\" || idType === \"pmcid\") {\n result.pmcid = idText.replace(/^PMC/, \"\");\n }\n if (idType === \"pmid\")\n result.pmid = idText;\n }\n return result;\n}\n/** Extract authors from contrib-group. */\nfunction parseAuthors(metaChildren) {\n const authors = [];\n const contribGroup = findChild(metaChildren, \"contrib-group\");\n if (!contribGroup)\n return authors;\n const contribs = findChildren(contribGroup.children, \"contrib\");\n for (const contrib of contribs) {\n if (contrib.attrs[\"contrib-type\"] !== \"author\")\n continue;\n const nameNode = findChild(contrib.children, \"name\");\n if (!nameNode)\n continue;\n const surnameNode = findChild(nameNode.children, \"surname\");\n const givenNamesNode = findChild(nameNode.children, \"given-names\");\n const author = {\n surname: surnameNode ? extractAllText(surnameNode.children) : \"\",\n };\n const givenNames = givenNamesNode ? extractAllText(givenNamesNode.children) : \"\";\n if (givenNames) {\n author.givenNames = givenNames;\n }\n authors.push(author);\n }\n return authors;\n}\n/** Extract abstract text, handling both structured and simple formats. */\nfunction parseAbstract(metaChildren) {\n const abstractNode = findChild(metaChildren, \"abstract\");\n if (!abstractNode)\n return undefined;\n // Structured abstract with <sec> elements\n const sections = findChildren(abstractNode.children, \"sec\");\n if (sections.length > 0) {\n return parseStructuredAbstract(sections);\n }\n // Simple abstract with <p>\n const paragraphs = findChildren(abstractNode.children, \"p\");\n if (paragraphs.length > 0) {\n return paragraphs.map((p) => extractAllText(p.children)).join(\"\\n\\n\");\n }\n const text = extractAllText(abstractNode.children);\n return text || undefined;\n}\n/** Parse a structured abstract with <sec> elements. */\nfunction parseStructuredAbstract(sections) {\n const parts = [];\n for (const sec of sections) {\n const secTitleNode = findChild(sec.children, \"title\");\n const secTitle = secTitleNode ? extractAllText(secTitleNode.children) : \"\";\n const secPs = findChildren(sec.children, \"p\");\n const text = secPs.map((p) => extractAllText(p.children)).join(\" \");\n parts.push(secTitle ? `${secTitle}: ${text}` : text);\n }\n return parts.join(\"\\n\\n\");\n}\n/** Extract a date from a pub-date node. */\nfunction extractDateFromNode(pd) {\n const yearNode = findChild(pd.children, \"year\");\n if (!yearNode)\n return undefined;\n const year = extractAllText(yearNode.children);\n const monthNode = findChild(pd.children, \"month\");\n const dayNode = findChild(pd.children, \"day\");\n const date = { year };\n if (monthNode)\n date.month = extractAllText(monthNode.children);\n if (dayNode)\n date.day = extractAllText(dayNode.children);\n return date;\n}\n/**\n * Extract publication date with priority: epub > ppub > collection > any other.\n * Falls back to first available date if none match priority.\n */\nfunction parsePublicationDate(metaChildren) {\n const pubDates = findChildren(metaChildren, \"pub-date\");\n const datePriority = { epub: 0, ppub: 1, collection: 2 };\n let bestPriority = Number.POSITIVE_INFINITY;\n let publicationDate;\n for (const pd of pubDates) {\n const dateType = pd.attrs[\"pub-type\"] ?? pd.attrs[\"date-type\"] ?? \"\";\n const priority = datePriority[dateType] ?? 3;\n if (priority < bestPriority) {\n bestPriority = priority;\n publicationDate = extractDateFromNode(pd);\n }\n }\n // If no prioritized date found, take first available\n if (!publicationDate && pubDates.length > 0) {\n const pd = pubDates.at(0);\n if (pd) {\n publicationDate = extractDateFromNode(pd);\n }\n }\n return publicationDate;\n}\n/** Extract license information from permissions. */\nfunction parseLicense(metaChildren) {\n const permissions = findChild(metaChildren, \"permissions\");\n if (!permissions)\n return undefined;\n const licenseNode = findChild(permissions.children, \"license\");\n if (!licenseNode)\n return undefined;\n // Prefer @xlink:href (standardized URL) over <license-p> (free-text)\n const href = licenseNode.attrs[\"xlink:href\"];\n if (href)\n return href;\n const licenseP = findChild(licenseNode.children, \"license-p\");\n if (licenseP)\n return extractAllText(licenseP.children).trim();\n return undefined;\n}\n/** Extract keywords from all kwd-group elements. */\nfunction parseKeywords(metaChildren) {\n const kwdGroups = findChildren(metaChildren, \"kwd-group\");\n const keywords = [];\n for (const kwdGroup of kwdGroups) {\n const kwds = findChildren(kwdGroup.children, \"kwd\");\n for (const kwd of kwds) {\n const text = extractAllText(kwd.children).trim();\n if (text)\n keywords.push(text);\n }\n }\n return keywords;\n}\n/** Extract volume, issue, and pages from article meta. */\nfunction parseVolumeAndPages(metaChildren) {\n const volumeNode = findChild(metaChildren, \"volume\");\n const volume = volumeNode ? extractAllText(volumeNode.children) : undefined;\n const issueNode = findChild(metaChildren, \"issue\");\n const issue = issueNode ? extractAllText(issueNode.children) : undefined;\n let pages;\n const fpageNode = findChild(metaChildren, \"fpage\");\n const lpageNode = findChild(metaChildren, \"lpage\");\n if (fpageNode) {\n const fp = extractAllText(fpageNode.children);\n const lp = lpageNode ? extractAllText(lpageNode.children) : \"\";\n pages = lp ? `${fp}-${lp}` : fp;\n }\n else {\n const elocationNode = findChild(metaChildren, \"elocation-id\");\n if (elocationNode)\n pages = extractAllText(elocationNode.children);\n }\n const result = {};\n if (volume !== undefined)\n result.volume = volume;\n if (issue !== undefined)\n result.issue = issue;\n if (pages !== undefined)\n result.pages = pages;\n return result;\n}\n/** Extract journal name from front matter journal-meta. */\nfunction parseJournalName(frontChildren) {\n const journalMeta = findChild(frontChildren, \"journal-meta\");\n if (!journalMeta)\n return undefined;\n const titleGroup = findChild(journalMeta.children, \"journal-title-group\");\n if (titleGroup) {\n const jTitle = findChild(titleGroup.children, \"journal-title\");\n if (jTitle)\n return extractAllText(jTitle.children);\n }\n const jTitle = findChild(journalMeta.children, \"journal-title\");\n if (jTitle)\n return extractAllText(jTitle.children);\n return undefined;\n}\n/** Extract article title from title-group. */\nfunction parseArticleTitle(metaChildren) {\n const titleGroup = findChild(metaChildren, \"title-group\");\n const articleTitle = titleGroup ? findChild(titleGroup.children, \"article-title\") : undefined;\n return articleTitle ? extractAllText(articleTitle.children) : \"\";\n}\n/** Assemble optional metadata fields into a JatsMetadata result. */\nfunction assembleMetadata(base, fields) {\n const result = { ...base };\n if (fields.doi)\n result.doi = fields.doi;\n if (fields.pmcid)\n result.pmcid = fields.pmcid;\n if (fields.pmid)\n result.pmid = fields.pmid;\n if (fields.journal)\n result.journal = fields.journal;\n if (fields.publicationDate)\n result.publicationDate = fields.publicationDate;\n if (fields.volume)\n result.volume = fields.volume;\n if (fields.issue)\n result.issue = fields.issue;\n if (fields.pages)\n result.pages = fields.pages;\n if (fields.keywords.length > 0)\n result.keywords = fields.keywords;\n if (fields.articleType)\n result.articleType = fields.articleType;\n if (fields.license)\n result.license = fields.license;\n if (fields.abstract)\n result.abstract = fields.abstract;\n return result;\n}\n/**\n * Parse JATS XML front matter to extract article metadata.\n */\nexport function parseJatsMetadata(xml) {\n const parsed = parser.parse(xml);\n const article = findArticle(parsed);\n if (!article)\n return { title: \"\", authors: [] };\n const front = findChild(article.children, \"front\");\n if (!front)\n return { title: \"\", authors: [] };\n const articleMeta = findChild(front.children, \"article-meta\");\n if (!articleMeta)\n return { title: \"\", authors: [] };\n const metaChildren = articleMeta.children;\n const journal = parseJournalName(front.children);\n const publicationDate = parsePublicationDate(metaChildren);\n const articleType = article.attrs[\"article-type\"] || undefined;\n const license = parseLicense(metaChildren);\n const abstract = parseAbstract(metaChildren);\n return assembleMetadata({ title: parseArticleTitle(metaChildren), authors: parseAuthors(metaChildren) }, {\n ...parseArticleIds(metaChildren),\n ...(journal !== undefined ? { journal } : {}),\n ...(publicationDate !== undefined ? { publicationDate } : {}),\n ...parseVolumeAndPages(metaChildren),\n keywords: parseKeywords(metaChildren),\n ...(articleType !== undefined ? { articleType } : {}),\n ...(license !== undefined ? { license } : {}),\n ...(abstract !== undefined ? { abstract } : {}),\n });\n}\n// ─── Inline Content Parsing ──────────────────────────────────────────\n/** Handle <inline-formula> tag. */\nfunction handleInlineFormula(innerChildren) {\n // Try to find <tex-math> directly or inside <alternatives>\n let texMath = findChild(innerChildren, \"tex-math\");\n if (!texMath) {\n const alternatives = findChild(innerChildren, \"alternatives\");\n if (alternatives) {\n texMath = findChild(alternatives.children, \"tex-math\");\n }\n }\n const tex = texMath ? extractAllText(texMath.children) : undefined;\n const text = tex || extractAllText(innerChildren);\n const entry = {\n type: \"inline-formula\",\n text,\n };\n if (tex)\n entry.tex = tex;\n return entry;\n}\n/** Handle <ext-link> tag. */\nfunction handleExtLink(child, innerChildren) {\n const href = getAttr(child, \"xlink:href\");\n if (href) {\n return { type: \"link\", url: href, children: parseInlineContent(innerChildren) };\n }\n const linkText = extractAllText(innerChildren);\n if (linkText)\n return { type: \"text\", text: linkText };\n return null;\n}\n/** Handle <uri> tag. */\nfunction handleUri(child, innerChildren) {\n const href = getAttr(child, \"xlink:href\");\n const textContent = extractAllText(innerChildren);\n const url = href || textContent;\n if (url) {\n return { type: \"link\", url, children: parseInlineContent(innerChildren) };\n }\n return null;\n}\n/** Handle <xref> tag. */\nfunction handleXref(child, innerChildren) {\n const refType = getAttr(child, \"ref-type\");\n if (refType === \"bibr\") {\n return {\n type: \"citation\",\n refId: getAttr(child, \"rid\") ?? \"\",\n text: extractAllText(innerChildren),\n };\n }\n const xrefText = extractAllText(innerChildren);\n if (xrefText)\n return { type: \"text\", text: xrefText };\n return null;\n}\n/** Map of tag names to their inline content handlers. */\nconst inlineTagHandlers = {\n bold: (_child, innerChildren) => ({\n type: \"bold\",\n children: parseInlineContent(innerChildren),\n }),\n italic: (_child, innerChildren) => ({\n type: \"italic\",\n children: parseInlineContent(innerChildren),\n }),\n sup: (_child, innerChildren) => ({\n type: \"superscript\",\n text: extractAllText(innerChildren),\n }),\n sub: (_child, innerChildren) => ({\n type: \"subscript\",\n text: extractAllText(innerChildren),\n }),\n \"inline-formula\": (_child, innerChildren) => handleInlineFormula(innerChildren),\n monospace: (_child, innerChildren) => ({\n type: \"code\",\n text: extractAllText(innerChildren),\n }),\n \"ext-link\": (child, innerChildren) => handleExtLink(child, innerChildren),\n uri: (child, innerChildren) => handleUri(child, innerChildren),\n underline: (_child, innerChildren) => {\n const passText = extractAllText(innerChildren);\n return passText ? { type: \"text\", text: passText } : null;\n },\n sc: (_child, innerChildren) => {\n const passText = extractAllText(innerChildren);\n return passText ? { type: \"text\", text: passText } : null;\n },\n xref: (child, innerChildren) => handleXref(child, innerChildren),\n};\n/** Process a single inline child node into an InlineContent, or return null. */\nfunction processInlineChild(child) {\n // Text node\n const text = getTextContent(child);\n if (text != null) {\n return text ? { type: \"text\", text } : null;\n }\n const tag = getTagName(child);\n if (!tag)\n return null;\n const innerChildren = getChildren(child);\n const handler = inlineTagHandlers[tag];\n if (handler)\n return handler(child, innerChildren);\n // Unknown inline element -- extract text\n const unknownText = extractAllText(innerChildren);\n return unknownText ? { type: \"text\", text: unknownText } : null;\n}\n/**\n * Parse inline content from a paragraph's children array.\n * Iterates in document order to preserve interleaving of text, citations,\n * and formatting elements.\n */\nfunction parseInlineContent(children) {\n const result = [];\n for (const child of children) {\n const content = processInlineChild(child);\n if (content)\n result.push(content);\n }\n return result;\n}\n// ─── Block Content Parsing ───────────────────────────────────────────\n/**\n * Parse a <list> element into a BlockElement.\n */\nfunction parseList(listNode) {\n const listType = getAttr(listNode, \"list-type\");\n const ordered = listType === \"order\";\n const listChildren = getChildren(listNode);\n const listItems = findChildren(listChildren, \"list-item\");\n const items = [];\n for (const item of listItems) {\n const pNodes = findChildren(item.children, \"p\");\n const content = pNodes.flatMap((p) => parseInlineContent(p.children));\n items.push(content);\n }\n return { type: \"list\", ordered, items };\n}\n/**\n * Parse a table row into an array of cell text content.\n */\nfunction parseTableRow(trChildren) {\n const cells = [];\n for (const child of trChildren) {\n const tag = getTagName(child);\n if (tag === \"th\" || tag === \"td\") {\n const cellChildren = getChildren(child);\n // Check if cell contains multiple <p> elements\n const paragraphs = findChildren(cellChildren, \"p\");\n if (paragraphs.length > 1) {\n cells.push(paragraphs.map((p) => extractAllText(p.children)).join(\"<br>\"));\n }\n else {\n cells.push(extractAllText(cellChildren));\n }\n }\n }\n return cells;\n}\n/**\n * Parse an already-parsed table-wrap node.\n */\nfunction parseTableWrap(tableWrapNode) {\n const children = getChildren(tableWrapNode);\n // Caption\n const labelNode = findChild(children, \"label\");\n const label = labelNode ? extractAllText(labelNode.children) : \"\";\n const captionNode = findChild(children, \"caption\");\n const captionText = captionNode ? extractAllText(captionNode.children) : \"\";\n const captionStr = [label, captionText].filter(Boolean).join(\". \");\n const tableNode = findChild(children, \"table\");\n const result = {\n headers: [],\n rows: [],\n };\n if (captionStr)\n result.caption = captionStr;\n if (!tableNode)\n return result;\n // Headers from thead\n const thead = findChild(tableNode.children, \"thead\");\n if (thead) {\n const headRows = findChildren(thead.children, \"tr\");\n if (headRows.length > 0) {\n result.headers.push(...parseTableRow(headRows[0]?.children ?? []));\n }\n }\n // Body rows\n const tbody = findChild(tableNode.children, \"tbody\");\n if (tbody) {\n const bodyRows = findChildren(tbody.children, \"tr\");\n for (const row of bodyRows) {\n result.rows.push(parseTableRow(row.children));\n }\n }\n return result;\n}\n/**\n * Parse a <table-wrap> element into a table block.\n * Exported for standalone use and used internally by parseBlockContent.\n */\nexport function parseJatsTable(xml) {\n const parsed = parser.parse(xml);\n const tableWrap = findChild(parsed, \"table-wrap\");\n if (tableWrap) {\n return parseTableWrap(tableWrap.node);\n }\n // Fallback: if not wrapped, try to find table directly\n return { headers: [], rows: [] };\n}\n/**\n * Parse a <boxed-text> element into a boxed-text block.\n * Extracts optional title and recursively parses inner block content.\n */\nfunction parseBoxedText(node) {\n const children = getChildren(node);\n const titleNode = findChild(children, \"title\");\n const title = titleNode ? extractAllText(titleNode.children) : undefined;\n const content = parseBlockContent(children);\n const block = { type: \"boxed-text\", content };\n if (title)\n block.title = title;\n return block;\n}\n/**\n * Parse a <def-list> element into a def-list block.\n * Extracts optional title and <def-item> pairs with <term> and <def>.\n */\nfunction parseDefList(node) {\n const children = getChildren(node);\n const titleNode = findChild(children, \"title\");\n const title = titleNode ? extractAllText(titleNode.children) : undefined;\n const defItems = findChildren(children, \"def-item\");\n const items = [];\n for (const item of defItems) {\n const termNode = findChild(item.children, \"term\");\n const defNode = findChild(item.children, \"def\");\n const term = termNode ? extractAllText(termNode.children) : \"\";\n const definition = defNode ? extractAllText(defNode.children) : \"\";\n items.push({ term, definition });\n }\n const block = { type: \"def-list\", items };\n if (title)\n block.title = title;\n return block;\n}\n/**\n * Parse a <disp-formula> element into a formula block.\n * Extracts TeX content from <tex-math> preferentially (inside <alternatives> or direct),\n * falls back to extractAllText for plain text.\n */\nfunction parseDispFormula(node) {\n const children = getChildren(node);\n const id = getAttr(node, \"id\");\n const labelNode = findChild(children, \"label\");\n const label = labelNode ? extractAllText(labelNode.children) : undefined;\n // Try <alternatives> wrapper first\n const alternatives = findChild(children, \"alternatives\");\n const searchChildren = alternatives ? alternatives.children : children;\n const texMath = findChild(searchChildren, \"tex-math\");\n const block = { type: \"formula\" };\n if (id)\n block.id = id;\n if (label)\n block.label = label;\n if (texMath) {\n block.tex = extractAllText(texMath.children);\n }\n else {\n // Fall back to plain text extraction (skip label)\n const textChildren = children.filter((c) => !(\"label\" in c));\n const text = extractAllText(textChildren).trim();\n if (text)\n block.text = text;\n }\n return block;\n}\n/** Tags that represent block-level elements when nested inside <p>. */\nconst BLOCK_TAGS = new Set([\"table-wrap\", \"fig\", \"disp-quote\", \"boxed-text\"]);\n/**\n * Parse a <disp-quote> element into a blockquote block.\n * Extracts <p> children and concatenates their inline content.\n */\nfunction parseDispQuote(node) {\n const children = getChildren(node);\n const paragraphs = findChildren(children, \"p\");\n const content = [];\n for (let i = 0; i < paragraphs.length; i++) {\n if (i > 0)\n content.push({ type: \"text\", text: \"\\n\\n\" });\n const para = paragraphs[i];\n if (para)\n content.push(...parseInlineContent(para.children));\n }\n // If no <p> children, extract inline content directly\n if (paragraphs.length === 0) {\n content.push(...parseInlineContent(children));\n }\n return { type: \"blockquote\", content };\n}\n/**\n * Parse a <table-wrap> node into a table block element.\n */\nfunction parseTableBlock(node) {\n const tableResult = parseTableWrap(node);\n const tableBlock = {\n type: \"table\",\n headers: tableResult.headers,\n rows: tableResult.rows,\n };\n if (tableResult.caption)\n tableBlock.caption = tableResult.caption;\n return tableBlock;\n}\n/**\n * Parse a <fig> node into a figure block element.\n */\nfunction parseFigBlock(node) {\n const innerChildren = getChildren(node);\n const figBlock = { type: \"figure\" };\n const figId = getAttr(node, \"id\");\n if (figId)\n figBlock.id = figId;\n const figLabel = findChild(innerChildren, \"label\");\n if (figLabel) {\n const labelText = extractAllText(figLabel.children);\n if (labelText)\n figBlock.label = labelText;\n }\n const figCaption = findChild(innerChildren, \"caption\");\n if (figCaption) {\n const captionText = extractAllText(figCaption.children);\n if (captionText)\n figBlock.caption = captionText;\n }\n return figBlock;\n}\n/**\n * Parse a <p> element, splitting it if it contains nested block elements\n * (table-wrap, fig, disp-quote). Returns one or more block elements.\n */\nfunction parseParagraph(pChildren) {\n // Check if <p> contains any nested block elements\n const hasNestedBlocks = pChildren.some((child) => {\n const tag = getTagName(child);\n return tag != null && BLOCK_TAGS.has(tag);\n });\n if (!hasNestedBlocks) {\n return [{ type: \"paragraph\", content: parseInlineContent(pChildren) }];\n }\n // Split into inline runs and block elements\n const blocks = [];\n let inlineBuffer = [];\n const flushInline = () => {\n if (inlineBuffer.length > 0) {\n const content = parseInlineContent(inlineBuffer);\n // Skip whitespace-only paragraphs created by XML formatting\n const hasNonWhitespace = content.some((c) => c.type !== \"text\" || c.text.trim() !== \"\");\n if (content.length > 0 && hasNonWhitespace) {\n blocks.push({ type: \"paragraph\", content });\n }\n inlineBuffer = [];\n }\n };\n for (const child of pChildren) {\n const tag = getTagName(child);\n if (tag === \"table-wrap\") {\n flushInline();\n blocks.push(parseTableBlock(child));\n }\n else if (tag === \"fig\") {\n flushInline();\n blocks.push(parseFigBlock(child));\n }\n else if (tag === \"disp-quote\") {\n flushInline();\n blocks.push(parseDispQuote(child));\n }\n else if (tag === \"boxed-text\") {\n flushInline();\n blocks.push(parseBoxedText(child));\n }\n else {\n inlineBuffer.push(child);\n }\n }\n flushInline();\n return blocks;\n}\n/** Parse a <supplementary-material> element into a paragraph block. */\nfunction parseSupplementaryMaterial(child) {\n const innerChildren = getChildren(child);\n const labelNode = findChild(innerChildren, \"label\");\n const captionNode = findChild(innerChildren, \"caption\");\n const labelText = labelNode ? extractAllText(labelNode.children) : \"\";\n const captionText = captionNode ? extractAllText(captionNode.children) : \"\";\n const text = [labelText, captionText].filter(Boolean).join(\": \");\n if (text) {\n return { type: \"paragraph\", content: [{ type: \"text\", text }] };\n }\n return null;\n}\n/** Map of tag names to their block content handlers. */\nconst blockTagHandlers = {\n p: (child) => parseParagraph(getChildren(child)),\n list: (child) => parseList(child),\n \"table-wrap\": (child) => parseTableBlock(child),\n fig: (child) => parseFigBlock(child),\n \"disp-quote\": (child) => parseDispQuote(child),\n \"boxed-text\": (child) => parseBoxedText(child),\n \"def-list\": (child) => parseDefList(child),\n \"disp-formula\": (child) => parseDispFormula(child),\n preformat: (child) => ({ type: \"preformat\", text: extractAllText(getChildren(child)) }),\n \"supplementary-material\": (child) => parseSupplementaryMaterial(child),\n};\n/**\n * Parse block-level content from a section's children.\n * Iterates in document order to preserve ordering of paragraphs, lists,\n * tables, figures, and blockquotes.\n */\nfunction parseBlockContent(sectionChildren) {\n const blocks = [];\n for (const child of sectionChildren) {\n const tag = getTagName(child);\n if (!tag)\n continue;\n const handler = blockTagHandlers[tag];\n if (!handler)\n continue;\n const result = handler(child);\n if (result == null)\n continue;\n if (Array.isArray(result)) {\n blocks.push(...result);\n }\n else {\n blocks.push(result);\n }\n }\n return blocks;\n}\n// ─── Section Parsing ─────────────────────────────────────────────────\n/**\n * Parse a <sec> element into a JatsSection, recursively handling subsections.\n */\nfunction parseSection(secChildren, level) {\n const titleNode = findChild(secChildren, \"title\");\n const title = titleNode ? extractAllText(titleNode.children) : \"\";\n const content = parseBlockContent(secChildren);\n // Nested sections\n const subsections = [];\n const nestedSecs = findChildren(secChildren, \"sec\");\n for (const sub of nestedSecs) {\n subsections.push(parseSection(sub.children, level + 1));\n }\n return { title, level, content, subsections };\n}\n/**\n * Parse JATS XML body to extract sections and content.\n */\nexport function parseJatsBody(xml) {\n const parsed = parser.parse(xml);\n const article = findArticle(parsed);\n if (!article)\n return [];\n const body = findChild(article.children, \"body\");\n if (!body)\n return [];\n const sections = [];\n const secs = findChildren(body.children, \"sec\");\n if (secs.length > 0) {\n for (const sec of secs) {\n sections.push(parseSection(sec.children, 2));\n }\n }\n else {\n // Body has paragraphs without sections\n const content = parseBlockContent(body.children);\n if (content.length > 0) {\n sections.push({ title: \"\", level: 2, content, subsections: [] });\n }\n }\n return sections;\n}\n// ─── Reference Parsing ───────────────────────────────────────────────\n/** Extract authors from a <person-group> element. */\nfunction extractCitationAuthors(children) {\n const personGroup = findChild(children, \"person-group\");\n if (!personGroup)\n return undefined;\n const names = findChildren(personGroup.children, \"name\");\n const authorParts = [];\n for (const name of names) {\n const surname = findChild(name.children, \"surname\");\n const givenNames = findChild(name.children, \"given-names\");\n const surnameText = surname ? extractAllText(surname.children) : \"\";\n const givenText = givenNames ? extractAllText(givenNames.children) : \"\";\n if (surnameText && givenText) {\n authorParts.push(`${surnameText} ${givenText}`);\n }\n else if (surnameText) {\n authorParts.push(surnameText);\n }\n }\n return authorParts.length > 0 ? authorParts.join(\", \") : undefined;\n}\n/** Format year, volume, and pages into a citation string part. */\nfunction formatYearVolumePage(children) {\n const year = findChild(children, \"year\");\n if (!year)\n return undefined;\n let yearStr = extractAllText(year.children);\n const volume = findChild(children, \"volume\");\n if (volume) {\n yearStr += `;${extractAllText(volume.children)}`;\n }\n const fpage = findChild(children, \"fpage\");\n if (fpage) {\n const fpageText = extractAllText(fpage.children);\n const lpage = findChild(children, \"lpage\");\n const lpageText = lpage ? extractAllText(lpage.children) : \"\";\n yearStr += `:${fpageText}${lpageText ? `-${lpageText}` : \"\"}`;\n }\n return yearStr;\n}\n/**\n * Format a structured <element-citation> into a readable reference string.\n * Produces: \"Author1, Author2. Title. Source. Year;Volume:FirstPage-LastPage.\"\n */\nfunction formatElementCitation(children) {\n const parts = [];\n const authorsStr = extractCitationAuthors(children);\n if (authorsStr)\n parts.push(authorsStr);\n // Article title\n const articleTitle = findChild(children, \"article-title\");\n if (articleTitle) {\n parts.push(extractAllText(articleTitle.children));\n }\n // Source (journal name)\n const source = findChild(children, \"source\");\n if (source) {\n parts.push(extractAllText(source.children));\n }\n // Year, volume, pages\n const yearVolumePage = formatYearVolumePage(children);\n if (yearVolumePage)\n parts.push(yearVolumePage);\n return `${parts.join(\". \")}.`;\n}\n/**\n * Extract text from a <mixed-citation>'s children, deduplicating any\n * <pub-id> content that also appears as inline text.\n *\n * Some publishers include the DOI/PMID both as a text node and inside\n * a <pub-id> element, causing duplication like \"10.1234/x 10.1234/x\".\n */\nfunction extractMixedCitationText(children) {\n // Collect pub-id values\n const pubIds = findChildren(children, \"pub-id\");\n const pubIdValues = pubIds.map((p) => extractAllText(p.children).trim()).filter(Boolean);\n if (pubIdValues.length === 0) {\n return extractAllText(children).trim();\n }\n // Extract full text\n const fullText = extractAllText(children).trim();\n // For each pub-id value, if it appears more than once, remove extra occurrences\n let result = fullText;\n for (const val of pubIdValues) {\n // Escape regex special characters\n const escaped = val.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n const matches = result.match(new RegExp(escaped, \"g\"));\n if (matches && matches.length > 1) {\n // Remove the first occurrence (typically the inline text), keep the last (pub-id element)\n result = result.replace(val, \"\");\n // Clean up any leftover extra whitespace\n result = result.replace(/\\s{2,}/g, \" \").trim();\n }\n }\n return result;\n}\n/**\n * Extract structured pub-id values (DOI, PMID, PMCID) from children nodes.\n */\nfunction extractPubIds(children) {\n const pubIds = findChildren(children, \"pub-id\");\n const result = {};\n for (const p of pubIds) {\n const idType = p.attrs[\"pub-id-type\"];\n const value = extractAllText(p.children).trim();\n if (!value)\n continue;\n if (idType === \"doi\")\n result.doi = value;\n if (idType === \"pmid\")\n result.pmid = value;\n if (idType === \"pmc\" || idType === \"pmcid\") {\n result.pmcid = value.replace(/^PMC/, \"\");\n }\n }\n return result;\n}\n/**\n * Strip extracted pub-id values from reference text to avoid duplication\n * when pub-ids are rendered separately as links.\n */\nfunction stripPubIdValues(text, pubIds) {\n let result = text;\n const values = [pubIds.doi, pubIds.pmid, pubIds.pmcid].filter(Boolean);\n for (const val of values) {\n // Strip common label prefixes (e.g. \"doi: \", \"PMID: \", \"DOI:\", \"pmid:\") followed by the value\n const escaped = val.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n result = result.replace(new RegExp(`(?:doi|PMID|pmid|PMC|pmc)[:\\\\s]*${escaped}`, \"gi\"), \"\");\n // Also strip the bare value itself\n result = result.replace(new RegExp(escaped, \"g\"), \"\");\n }\n // Also strip PMC-prefixed form of pmcid\n if (pubIds.pmcid) {\n const pmcFull = `PMC${pubIds.pmcid}`;\n const escaped = pmcFull.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n result = result.replace(new RegExp(`(?:pmc|pmcid)[:\\\\s]*${escaped}`, \"gi\"), \"\");\n result = result.replace(new RegExp(escaped, \"g\"), \"\");\n }\n // Clean up trailing/leading whitespace and extra spaces\n result = result.replace(/\\s{2,}/g, \" \").trim();\n // Clean up trailing period after stripped content (e.g. \"Title. .\" -> \"Title.\")\n result = result.replace(/\\.\\s*\\.$/, \".\");\n return result;\n}\n/** Parse a single <ref> element into a JatsReference, or return null if invalid. */\nfunction parseSingleReference(ref) {\n const id = getAttr(ref.node, \"id\") ?? \"\";\n // Determine the search scope: if <citation-alternatives> exists, search within it;\n // otherwise search direct children of <ref>\n const citationAlternatives = findChild(ref.children, \"citation-alternatives\");\n const searchChildren = citationAlternatives ? citationAlternatives.children : ref.children;\n // Try mixed-citation first (already formatted), then element-citation (structured)\n const mixedCitation = findChild(searchChildren, \"mixed-citation\");\n if (mixedCitation) {\n const rawText = extractMixedCitationText(mixedCitation.children);\n const pubIds = extractPubIds(mixedCitation.children);\n const text = stripPubIdValues(rawText, pubIds);\n if (id && text)\n return { id, text, ...pubIds };\n return null;\n }\n const elementCitation = findChild(searchChildren, \"element-citation\");\n if (elementCitation) {\n const rawText = formatElementCitation(elementCitation.children);\n const pubIds = extractPubIds(elementCitation.children);\n const text = stripPubIdValues(rawText, pubIds);\n if (id && text)\n return { id, text, ...pubIds };\n return null;\n }\n // Fallback: extract all text from ref, skipping <label>\n const childrenWithoutLabel = ref.children.filter((c) => !(\"label\" in c));\n const text = extractAllText(childrenWithoutLabel).trim();\n if (id && text)\n return { id, text };\n return null;\n}\n/**\n * Parse JATS XML back matter to extract references.\n */\nexport function parseJatsReferences(xml) {\n const parsed = parser.parse(xml);\n const article = findArticle(parsed);\n if (!article)\n return [];\n const back = findChild(article.children, \"back\");\n if (!back)\n return [];\n const refList = findChild(back.children, \"ref-list\");\n if (!refList)\n return [];\n const refs = findChildren(refList.children, \"ref\");\n const references = [];\n for (const ref of refs) {\n const reference = parseSingleReference(ref);\n if (reference)\n references.push(reference);\n }\n return references;\n}\n/** Parse acknowledgments from <ack> element. */\nfunction parseAcknowledgments(backChildren) {\n const ack = findChild(backChildren, \"ack\");\n if (!ack)\n return undefined;\n const paragraphs = findChildren(ack.children, \"p\");\n if (paragraphs.length > 0) {\n return paragraphs.map((p) => extractAllText(p.children)).join(\"\\n\\n\");\n }\n return undefined;\n}\n/** Parse appendices from <app-group>/<app> elements. */\nfunction parseAppendices(backChildren) {\n const appGroup = findChild(backChildren, \"app-group\");\n if (!appGroup)\n return undefined;\n const apps = findChildren(appGroup.children, \"app\");\n if (apps.length === 0)\n return undefined;\n return apps.map((app) => parseSection(app.children, 2));\n}\n/** Parse a single footnote element into a JatsFootnote. */\nfunction parseSingleFootnote(fn) {\n const parts = [];\n // Include <title> if present\n const titleNode = findChild(fn.children, \"title\");\n if (titleNode) {\n const titleText = extractAllText(titleNode.children).trim();\n if (titleText)\n parts.push(titleText);\n }\n // Extract text from each <p> separately and join with space\n const paragraphs = findChildren(fn.children, \"p\");\n for (const p of paragraphs) {\n const pText = extractAllText(p.children).trim();\n if (pText)\n parts.push(pText);\n }\n return {\n id: getAttr(fn.node, \"id\") ?? \"\",\n text: parts.join(\" \"),\n };\n}\n/** Parse footnotes from <fn-group>/<fn> elements. */\nfunction parseFootnotes(backChildren) {\n const fnGroup = findChild(backChildren, \"fn-group\");\n if (!fnGroup)\n return undefined;\n const fns = findChildren(fnGroup.children, \"fn\");\n if (fns.length === 0)\n return undefined;\n return fns.map(parseSingleFootnote);\n}\n/** Parse a single notes element into BackMatterNote entries. */\nfunction parseSingleNotesElement(note) {\n const notes = [];\n // Check if this <notes> contains <sec> or nested <notes> children\n const secs = findChildren(note.children, \"sec\");\n const nestedNotes = findChildren(note.children, \"notes\");\n const subItems = secs.length > 0 ? secs : nestedNotes;\n if (subItems.length > 0) {\n for (const sub of subItems) {\n const subTitleNode = findChild(sub.children, \"title\");\n const subTitle = subTitleNode ? extractAllText(subTitleNode.children) : \"\";\n const subParagraphs = findChildren(sub.children, \"p\");\n const subText = subParagraphs.map((p) => extractAllText(p.children)).join(\"\\n\\n\");\n if (subTitle || subText) {\n notes.push({ title: subTitle, text: subText });\n }\n }\n return notes;\n }\n const titleNode = findChild(note.children, \"title\");\n const title = titleNode ? extractAllText(titleNode.children) : \"\";\n const paragraphs = findChildren(note.children, \"p\");\n const text = paragraphs.map((p) => extractAllText(p.children)).join(\"\\n\\n\");\n if (title || text) {\n notes.push({ title, text });\n }\n return notes;\n}\n/** Parse notes from <notes> elements (author contributions, funding, etc.). */\nfunction parseNotes(backChildren) {\n const notesElements = findChildren(backChildren, \"notes\");\n if (notesElements.length === 0)\n return undefined;\n const notes = [];\n for (const note of notesElements) {\n notes.push(...parseSingleNotesElement(note));\n }\n return notes.length > 0 ? notes : undefined;\n}\n/** Parse glossary elements into BackMatterNote entries. */\nfunction parseGlossary(backChildren) {\n const glossaryElements = findChildren(backChildren, \"glossary\");\n const notes = [];\n for (const glossary of glossaryElements) {\n const titleNode = findChild(glossary.children, \"title\");\n const title = titleNode ? extractAllText(titleNode.children) : \"Glossary\";\n const defList = findChild(glossary.children, \"def-list\");\n if (!defList)\n continue;\n const defItems = findChildren(defList.children, \"def-item\");\n const lines = [];\n for (const item of defItems) {\n const termNode = findChild(item.children, \"term\");\n const defNode = findChild(item.children, \"def\");\n const term = termNode ? extractAllText(termNode.children) : \"\";\n const definition = defNode ? extractAllText(defNode.children) : \"\";\n lines.push(`${term}: ${definition}`);\n }\n notes.push({ title, text: lines.join(\"\\n\") });\n }\n return notes;\n}\n/** Parse <floats-group> into block elements. */\nfunction parseFloatsGroup(articleChildren) {\n const floatsGroup = findChild(articleChildren, \"floats-group\");\n if (!floatsGroup)\n return undefined;\n const blocks = [];\n for (const child of floatsGroup.children) {\n const tag = getTagName(child);\n if (tag === \"fig\") {\n blocks.push(parseFigBlock(child));\n }\n else if (tag === \"table-wrap\") {\n blocks.push(parseTableBlock(child));\n }\n }\n return blocks.length > 0 ? blocks : undefined;\n}\n/**\n * Parse JATS XML back matter sections (ack, app-group, fn-group)\n * and top-level floats-group.\n */\nexport function parseJatsBackMatter(xml) {\n const parsed = parser.parse(xml);\n const article = findArticle(parsed);\n if (!article)\n return {};\n const result = {};\n // Parse <back> children\n const back = findChild(article.children, \"back\");\n if (back) {\n const ack = parseAcknowledgments(back.children);\n if (ack)\n result.acknowledgments = ack;\n const app = parseAppendices(back.children);\n if (app)\n result.appendices = app;\n const fn = parseFootnotes(back.children);\n if (fn)\n result.footnotes = fn;\n const notes = parseNotes(back.children);\n const glossaryNotes = parseGlossary(back.children);\n if (notes || glossaryNotes.length > 0) {\n result.notes = [...(notes ?? []), ...glossaryNotes];\n }\n }\n // Floats-group: <floats-group> (sibling of <body> and <back>)\n const floats = parseFloatsGroup(article.children);\n if (floats)\n result.floats = floats;\n return result;\n}\n//# sourceMappingURL=jats-parser.js.map","/**\n * Markdown writer for JATS XML conversion.\n *\n * Converts the intermediate JatsDocument representation to Markdown text.\n */\n/**\n * Format an author's name in abbreviated form (e.g., \"Smith J\").\n */\nfunction formatAuthor(author) {\n if (!author.givenNames)\n return author.surname;\n const initials = author.givenNames\n .split(/[\\s.]+/)\n .filter(Boolean)\n .map((n) => n[0])\n .join(\"\");\n return `${author.surname} ${initials}`;\n}\n/**\n * Render inline content to Markdown string.\n */\nfunction renderInline(content) {\n return content\n .map((node) => {\n switch (node.type) {\n case \"text\":\n return node.text;\n case \"bold\":\n return `**${renderInline(node.children)}**`;\n case \"italic\":\n return `*${renderInline(node.children)}*`;\n case \"superscript\":\n return `^${node.text}^`;\n case \"subscript\":\n return `~${node.text}~`;\n case \"citation\":\n return node.text;\n case \"code\":\n return `\\`${node.text}\\``;\n case \"inline-formula\":\n return node.tex ? `$${node.tex}$` : node.text;\n case \"link\": {\n const linkText = renderInline(node.children);\n if (linkText === node.url)\n return node.url;\n return `[${linkText}](${node.url})`;\n }\n }\n })\n .join(\"\");\n}\n/**\n * Render a table block to Markdown.\n */\nfunction renderTable(block) {\n const lines = [];\n if (block.caption) {\n lines.push(`*${block.caption}*`);\n lines.push(\"\");\n }\n if (block.headers.length > 0) {\n lines.push(`| ${block.headers.join(\" | \")} |`);\n lines.push(`| ${block.headers.map(() => \"---\").join(\" | \")} |`);\n }\n else if (block.rows.length > 0) {\n const colCount = block.rows[0]?.length ?? 0;\n lines.push(`| ${Array.from({ length: colCount }, () => \"\").join(\" | \")} |`);\n lines.push(`| ${Array.from({ length: colCount }, () => \"---\").join(\" | \")} |`);\n }\n for (const row of block.rows) {\n lines.push(`| ${row.join(\" | \")} |`);\n }\n return lines.join(\"\\n\");\n}\n/**\n * Render a formula block to Markdown.\n */\nfunction renderFormula(block) {\n const lines = [];\n if (block.tex) {\n lines.push(`$$${block.tex}$$`);\n }\n else if (block.text) {\n lines.push(\"```\");\n lines.push(block.text);\n lines.push(\"```\");\n }\n if (block.label) {\n lines.push(block.label);\n }\n return lines.join(\"\\n\");\n}\n/**\n * Render a definition list block to Markdown.\n */\nfunction renderDefList(block) {\n const lines = [];\n if (block.title) {\n lines.push(`**${block.title}**`);\n lines.push(\"\");\n }\n for (const item of block.items) {\n lines.push(`**${item.term}**: ${item.definition}`);\n }\n return lines.join(\"\\n\");\n}\n/**\n * Render a boxed-text block to Markdown.\n */\nfunction renderBoxedText(block) {\n const lines = [];\n if (block.title) {\n lines.push(`> **${block.title}**`);\n lines.push(\">\");\n }\n for (const inner of block.content) {\n const rendered = renderBlock(inner);\n for (const line of rendered.split(\"\\n\")) {\n lines.push(line === \"\" ? \">\" : `> ${line}`);\n }\n }\n return lines.join(\"\\n\");\n}\n/**\n * Render a block element to Markdown lines.\n */\nfunction renderBlock(block) {\n switch (block.type) {\n case \"paragraph\":\n return renderInline(block.content);\n case \"blockquote\": {\n const text = renderInline(block.content);\n return text\n .split(\"\\n\")\n .map((line) => (line === \"\" ? \">\" : `> ${line}`))\n .join(\"\\n\");\n }\n case \"list\": {\n return block.items\n .map((item, i) => {\n const prefix = block.ordered ? `${i + 1}. ` : \"- \";\n return `${prefix}${renderInline(item)}`;\n })\n .join(\"\\n\");\n }\n case \"table\":\n return renderTable(block);\n case \"figure\": {\n const label = block.label ?? \"Figure\";\n const altText = block.caption ? `${label}. ${block.caption}` : label;\n return `![${altText}]()`;\n }\n case \"preformat\":\n return `\\`\\`\\`\\n${block.text}\\n\\`\\`\\``;\n case \"formula\":\n return renderFormula(block);\n case \"def-list\":\n return renderDefList(block);\n case \"boxed-text\":\n return renderBoxedText(block);\n }\n}\n/**\n * Render a section and its subsections to Markdown.\n */\nfunction renderSection(section) {\n const lines = [];\n const heading = \"#\".repeat(section.level);\n if (section.title.trim()) {\n lines.push(`${heading} ${section.title}`);\n lines.push(\"\");\n }\n for (const block of section.content) {\n lines.push(renderBlock(block));\n lines.push(\"\");\n }\n for (const sub of section.subsections) {\n lines.push(renderSection(sub));\n }\n return lines.join(\"\\n\");\n}\n/**\n * Render references section.\n */\nfunction formatRefPubIds(ref) {\n const links = [];\n if (ref.doi) {\n links.push(`[doi:${ref.doi}](https://doi.org/${ref.doi})`);\n }\n if (ref.pmid) {\n links.push(`[pmid:${ref.pmid}](https://pubmed.ncbi.nlm.nih.gov/${ref.pmid}/)`);\n }\n if (ref.pmcid) {\n links.push(`[pmcid:PMC${ref.pmcid}](https://www.ncbi.nlm.nih.gov/pmc/articles/PMC${ref.pmcid}/)`);\n }\n return links.join(\" \");\n}\nfunction renderReferences(references) {\n if (references.length === 0)\n return \"\";\n const lines = [\"## References\", \"\"];\n references.forEach((ref, i) => {\n const pubIdLinks = formatRefPubIds(ref);\n const line = pubIdLinks ? `${i + 1}. ${ref.text} ${pubIdLinks}` : `${i + 1}. ${ref.text}`;\n lines.push(line);\n });\n lines.push(\"\");\n return lines.join(\"\\n\");\n}\n/**\n * Render footnotes section.\n */\nfunction renderFootnotes(footnotes) {\n if (footnotes.length === 0)\n return \"\";\n const lines = [\"## Footnotes\", \"\"];\n footnotes.forEach((fn, i) => {\n lines.push(`${i + 1}. ${fn.text}`);\n });\n lines.push(\"\");\n return lines.join(\"\\n\");\n}\n/**\n * Render floats (figures and tables) section.\n */\nfunction renderFloats(floats) {\n if (floats.length === 0)\n return \"\";\n const lines = [\"## Figures and Tables\", \"\"];\n for (const block of floats) {\n lines.push(renderBlock(block));\n lines.push(\"\");\n }\n return lines.join(\"\\n\");\n}\n/**\n * Format a publication date as a string (e.g., \"2024\", \"2024-01\", \"2024-01-15\").\n */\nfunction formatPublicationDate(date) {\n let dateStr = date.year;\n if (date.month) {\n dateStr += `-${date.month.padStart(2, \"0\")}`;\n if (date.day)\n dateStr += `-${date.day.padStart(2, \"0\")}`;\n }\n return dateStr;\n}\n/**\n * Format a citation string from volume, issue, and pages.\n */\nfunction formatCitation(meta) {\n if (meta.volume && meta.issue) {\n let citation = `Vol. ${meta.volume}(${meta.issue})`;\n if (meta.pages)\n citation += `, pp. ${meta.pages}`;\n return citation;\n }\n const parts = [];\n if (meta.volume)\n parts.push(`Vol. ${meta.volume}`);\n if (meta.issue)\n parts.push(`(${meta.issue})`);\n if (meta.pages)\n parts.push(`pp. ${meta.pages}`);\n return parts.join(\", \");\n}\n/**\n * Render document metadata (authors, DOI, journal, etc.) to Markdown lines.\n */\nfunction renderMetadata(doc) {\n const lines = [];\n const meta = doc.metadata;\n // Title\n lines.push(`# ${meta.title}`);\n lines.push(\"\");\n // Track position after title to detect if any metadata fields were added\n const posAfterTitle = lines.length;\n // Authors\n if (meta.authors.length > 0) {\n const authorStr = meta.authors.map(formatAuthor).join(\", \");\n lines.push(`**Authors**: ${authorStr}`);\n }\n if (meta.doi)\n lines.push(`**DOI**: ${meta.doi}`);\n if (meta.pmcid)\n lines.push(`**PMC**: PMC${meta.pmcid}`);\n if (meta.pmid)\n lines.push(`**PMID**: ${meta.pmid}`);\n if (meta.journal)\n lines.push(`**Journal**: ${meta.journal}`);\n if (meta.publicationDate) {\n lines.push(`**Published**: ${formatPublicationDate(meta.publicationDate)}`);\n }\n if (meta.volume || meta.issue || meta.pages) {\n lines.push(`**Citation**: ${formatCitation(meta)}`);\n }\n if (meta.articleType)\n lines.push(`**Article Type**: ${meta.articleType}`);\n if (meta.keywords && meta.keywords.length > 0) {\n lines.push(`**Keywords**: ${meta.keywords.join(\", \")}`);\n }\n if (meta.license)\n lines.push(`**License**: ${meta.license}`);\n if (lines.length > posAfterTitle) {\n lines.push(\"\");\n }\n // Abstract\n if (meta.abstract) {\n lines.push(\"## Abstract\");\n lines.push(\"\");\n lines.push(meta.abstract);\n lines.push(\"\");\n }\n return lines;\n}\n/**\n * Render trailing sections (acknowledgments, notes, references, appendices,\n * footnotes, floats) to Markdown lines.\n */\nfunction renderTrailingSections(doc) {\n const lines = [];\n // Acknowledgments (before References)\n if (doc.acknowledgments) {\n lines.push(\"## Acknowledgments\");\n lines.push(\"\");\n lines.push(doc.acknowledgments);\n lines.push(\"\");\n }\n // Notes (between Acknowledgments and References)\n if (doc.notes && doc.notes.length > 0) {\n for (const note of doc.notes) {\n lines.push(`## ${note.title}`);\n lines.push(\"\");\n lines.push(note.text);\n lines.push(\"\");\n }\n }\n // References\n if (doc.references.length > 0) {\n lines.push(renderReferences(doc.references));\n }\n // Appendices (after References)\n if (doc.appendices && doc.appendices.length > 0) {\n for (const appendix of doc.appendices) {\n lines.push(renderSection(appendix));\n }\n }\n // Footnotes\n if (doc.footnotes && doc.footnotes.length > 0) {\n lines.push(renderFootnotes(doc.footnotes));\n }\n // Floats (Figures and Tables from floats-group)\n if (doc.floats && doc.floats.length > 0) {\n lines.push(renderFloats(doc.floats));\n }\n return lines;\n}\n/**\n * Convert a parsed JATS document to Markdown string.\n */\nexport function writeMarkdown(doc) {\n const lines = [];\n lines.push(...renderMetadata(doc));\n // Sections\n for (const section of doc.sections) {\n lines.push(renderSection(section));\n }\n lines.push(...renderTrailingSections(doc));\n return `${lines.join(\"\\n\").trimEnd()}\\n`;\n}\n//# sourceMappingURL=markdown-writer.js.map","/**\n * Conversion orchestrator for PMC XML to Markdown.\n *\n * Ties together the JATS parser and Markdown writer with file I/O.\n */\nimport { readFile, stat, writeFile } from \"node:fs/promises\";\nimport { parseJatsBackMatter, parseJatsBody, parseJatsMetadata, parseJatsReferences, } from \"./jats-parser.js\";\nimport { writeMarkdown } from \"./markdown-writer.js\";\n/**\n * Convert a PMC JATS XML file to Markdown.\n *\n * Reads the XML, parses it into a JatsDocument, writes Markdown,\n * and optionally updates meta.json.\n */\nexport async function convertPmcXmlToMarkdown(xmlPath, mdPath, metaPath) {\n try {\n const xml = await readFile(xmlPath, \"utf-8\");\n // Parse\n const metadata = parseJatsMetadata(xml);\n const sections = parseJatsBody(xml);\n const references = parseJatsReferences(xml);\n const backMatter = parseJatsBackMatter(xml);\n const doc = { metadata, sections, references };\n if (backMatter.acknowledgments)\n doc.acknowledgments = backMatter.acknowledgments;\n if (backMatter.appendices)\n doc.appendices = backMatter.appendices;\n if (backMatter.footnotes)\n doc.footnotes = backMatter.footnotes;\n if (backMatter.floats)\n doc.floats = backMatter.floats;\n if (backMatter.notes)\n doc.notes = backMatter.notes;\n // Write Markdown\n const md = writeMarkdown(doc);\n await writeFile(mdPath, md, \"utf-8\");\n // Update meta.json if path provided and file exists\n if (metaPath) {\n try {\n await stat(metaPath);\n const metaRaw = await readFile(metaPath, \"utf-8\");\n const meta = JSON.parse(metaRaw);\n const mdStat = await stat(mdPath);\n meta.files.markdown = {\n filename: \"fulltext.md\",\n source: \"conversion\",\n retrievedAt: new Date().toISOString(),\n size: mdStat.size,\n convertedFrom: \"fulltext.xml\",\n };\n await writeFile(metaPath, `${JSON.stringify(meta, null, 2)}\\n`, \"utf-8\");\n }\n catch {\n // meta.json doesn't exist or can't be read, skip update\n }\n }\n const result = { success: true };\n result.title = metadata.title;\n result.sections = sections.length;\n result.references = references.length;\n return result;\n }\n catch (err) {\n const result = { success: false };\n result.error = err instanceof Error ? err.message : String(err);\n return result;\n }\n}\n//# sourceMappingURL=index.js.map","/**\n * Fulltext OA discovery operation.\n *\n * Discovers open access availability for a reference by checking\n * multiple sources (Unpaywall, PMC, arXiv, CORE).\n */\n\nimport {\n type DiscoveryArticle,\n type DiscoveryConfig,\n type OALocation,\n type OAStatus,\n discoverOA,\n} from \"@ncukondo/academic-fulltext\";\nimport type { FulltextConfig } from \"../../../config/schema.js\";\nimport type { IdentifierType } from \"../../../core/library-interface.js\";\nimport type { ILibrary } from \"../../../core/library-interface.js\";\n\nexport interface FulltextDiscoverOptions {\n /** Reference identifier (id or uuid) */\n identifier: string;\n /** Identifier type: 'id' (default), 'uuid', 'doi', 'pmid', or 'isbn' */\n idType?: IdentifierType | undefined;\n /** Fulltext configuration */\n fulltextConfig: FulltextConfig;\n}\n\nexport interface FulltextDiscoverResult {\n success: boolean;\n error?: string;\n /** The reference ID used for display */\n referenceId?: string;\n /** OA status */\n oaStatus?: OAStatus;\n /** Discovered OA locations */\n locations?: OALocation[];\n /** Source-level errors (non-fatal) */\n errors?: Array<{ source: string; error: string }>;\n}\n\nexport async function fulltextDiscover(\n library: ILibrary,\n options: FulltextDiscoverOptions\n): Promise<FulltextDiscoverResult> {\n const { identifier, idType = \"id\", fulltextConfig } = options;\n\n // Resolve reference\n const item = await library.find(identifier, { idType });\n if (!item) {\n return { success: false, error: `Reference '${identifier}' not found` };\n }\n\n // Extract identifiers\n const doi = item.DOI;\n const pmid = item.PMID;\n const pmcid = item.PMCID;\n\n if (!doi && !pmid) {\n return {\n success: false,\n error: `No DOI or PMID found for ${identifier}. Cannot discover OA sources.`,\n };\n }\n\n // Build article object for discovery\n const article: DiscoveryArticle = {};\n if (doi) article.doi = doi;\n if (pmid) article.pmid = pmid;\n if (pmcid) article.pmcid = pmcid;\n\n // Build discovery config\n const config: DiscoveryConfig = {\n unpaywallEmail: fulltextConfig.sources.unpaywallEmail ?? \"\",\n coreApiKey: fulltextConfig.sources.coreApiKey ?? \"\",\n preferSources: fulltextConfig.preferSources,\n };\n\n const result = await discoverOA(article, config);\n\n const discoverResult: FulltextDiscoverResult = {\n success: true,\n referenceId: item.id,\n oaStatus: result.oaStatus,\n locations: result.locations,\n };\n if (result.errors.length > 0) {\n discoverResult.errors = result.errors;\n }\n return discoverResult;\n}\n","/**\n * Fulltext fetch operation.\n *\n * Discovers OA sources, downloads full-text files (PDF, PMC XML),\n * converts XML to Markdown, and attaches them to references.\n */\n\nimport { mkdtemp, rm } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport {\n type DiscoveryArticle,\n type DiscoveryConfig,\n type OALocation,\n convertPmcXmlToMarkdown,\n discoverOA,\n downloadPdf,\n downloadPmcXml,\n} from \"@ncukondo/academic-fulltext\";\nimport type { FulltextConfig, FulltextSource } from \"../../../config/schema.js\";\nimport type { CslItem } from \"../../../core/csl-json/types.js\";\nimport type { ILibrary, IdentifierType } from \"../../../core/library-interface.js\";\nimport { fulltextAttach } from \"./attach.js\";\nimport { fulltextGet } from \"./get.js\";\n\nexport interface FulltextFetchOptions {\n /** Reference identifier (id or uuid) */\n identifier: string;\n /** Identifier type: 'id' (default), 'uuid', 'doi', 'pmid', or 'isbn' */\n idType?: IdentifierType | undefined;\n /** Fulltext configuration */\n fulltextConfig: FulltextConfig;\n /** Directory for fulltext attachments */\n fulltextDirectory: string;\n /** Preferred source to fetch from */\n source?: FulltextSource | undefined;\n /** Force overwrite existing fulltext */\n force?: boolean | undefined;\n}\n\nexport interface FulltextFetchResult {\n success: boolean;\n error?: string;\n /** The reference ID used for display */\n referenceId?: string;\n /** Which source was used */\n source?: string;\n /** Which file types were attached */\n attachedFiles?: string[];\n}\n\ninterface AttachContext {\n library: ILibrary;\n identifier: string;\n idType: IdentifierType;\n fulltextDirectory: string;\n force: boolean;\n}\n\nfunction buildDiscoveryArticle(item: CslItem): DiscoveryArticle {\n const article: DiscoveryArticle = {};\n if (item.DOI) article.doi = item.DOI;\n if (item.PMID) article.pmid = item.PMID;\n if (item.PMCID) article.pmcid = item.PMCID;\n return article;\n}\n\nfunction buildDiscoveryConfig(fulltextConfig: FulltextConfig): DiscoveryConfig {\n return {\n unpaywallEmail: fulltextConfig.sources.unpaywallEmail ?? \"\",\n coreApiKey: fulltextConfig.sources.coreApiKey ?? \"\",\n preferSources: fulltextConfig.preferSources,\n };\n}\n\nasync function tryDownloadPdf(\n locations: OALocation[],\n tempDir: string,\n ctx: AttachContext\n): Promise<{ attached: boolean; source: string }> {\n const pdfLocation = locations.find((loc) => loc.urlType === \"pdf\");\n if (!pdfLocation) return { attached: false, source: \"\" };\n\n const pdfPath = join(tempDir, \"fulltext.pdf\");\n const pdfResult = await downloadPdf(pdfLocation.url, pdfPath);\n if (!pdfResult.success) return { attached: false, source: pdfLocation.source };\n\n const attachResult = await fulltextAttach(ctx.library, {\n identifier: ctx.identifier,\n idType: ctx.idType,\n filePath: pdfPath,\n type: \"pdf\",\n force: ctx.force,\n move: true,\n fulltextDirectory: ctx.fulltextDirectory,\n });\n\n return { attached: attachResult.success, source: pdfLocation.source };\n}\n\nasync function tryDownloadPmcXmlAndConvert(\n pmcid: string,\n tempDir: string,\n ctx: AttachContext\n): Promise<boolean> {\n const xmlPath = join(tempDir, \"fulltext.xml\");\n const xmlResult = await downloadPmcXml(pmcid, xmlPath);\n if (!xmlResult.success) return false;\n\n const mdPath = join(tempDir, \"fulltext.md\");\n const convertResult = await convertPmcXmlToMarkdown(xmlPath, mdPath);\n if (!convertResult.success) return false;\n\n const attachResult = await fulltextAttach(ctx.library, {\n identifier: ctx.identifier,\n idType: ctx.idType,\n filePath: mdPath,\n type: \"markdown\",\n force: ctx.force,\n move: true,\n fulltextDirectory: ctx.fulltextDirectory,\n });\n\n return attachResult.success;\n}\n\nasync function checkExistingFulltext(\n library: ILibrary,\n identifier: string,\n idType: IdentifierType,\n fulltextDirectory: string\n): Promise<boolean> {\n const existing = await fulltextGet(library, { identifier, idType, fulltextDirectory });\n return existing.success && existing.paths !== undefined;\n}\n\nexport async function fulltextFetch(\n library: ILibrary,\n options: FulltextFetchOptions\n): Promise<FulltextFetchResult> {\n const { identifier, idType = \"id\", fulltextConfig, fulltextDirectory, source, force } = options;\n\n const item = await library.find(identifier, { idType });\n if (!item) {\n return { success: false, error: `Reference '${identifier}' not found` };\n }\n\n if (!item.DOI && !item.PMID) {\n return {\n success: false,\n error: `No DOI or PMID found for ${identifier}. Cannot discover OA sources.`,\n };\n }\n\n if (!force && (await checkExistingFulltext(library, identifier, idType, fulltextDirectory))) {\n return {\n success: false,\n error: `Fulltext already attached to ${identifier}. Use --force to overwrite.`,\n };\n }\n\n const discovery = await discoverOA(\n buildDiscoveryArticle(item),\n buildDiscoveryConfig(fulltextConfig)\n );\n\n let locations = discovery.locations;\n if (source) {\n locations = locations.filter((loc) => loc.source === source);\n }\n\n if (locations.length === 0) {\n return { success: false, error: `No OA sources found for ${identifier}` };\n }\n\n const tempDir = await mkdtemp(join(tmpdir(), \"ref-fulltext-\"));\n const ctx: AttachContext = {\n library,\n identifier,\n idType,\n fulltextDirectory,\n force: force ?? false,\n };\n\n try {\n return await downloadAndAttach(locations, item.PMCID, tempDir, ctx, item.id, identifier);\n } finally {\n await rm(tempDir, { recursive: true, force: true }).catch(() => {});\n }\n}\n\nasync function downloadAndAttach(\n locations: OALocation[],\n pmcid: string | undefined,\n tempDir: string,\n ctx: AttachContext,\n referenceId: string,\n identifier: string\n): Promise<FulltextFetchResult> {\n const attachedFiles: string[] = [];\n let usedSource = \"\";\n\n const pdfResult = await tryDownloadPdf(locations, tempDir, ctx);\n if (pdfResult.attached) {\n attachedFiles.push(\"pdf\");\n usedSource = pdfResult.source;\n }\n\n if (pmcid) {\n const mdAttached = await tryDownloadPmcXmlAndConvert(pmcid, tempDir, ctx);\n if (mdAttached) {\n attachedFiles.push(\"markdown\");\n if (!usedSource) usedSource = \"pmc\";\n }\n }\n\n if (attachedFiles.length === 0) {\n const pdfLocation = locations.find((loc) => loc.urlType === \"pdf\");\n if (pdfLocation) {\n return {\n success: false,\n error: `Failed to download from ${pdfLocation.source}: download failed`,\n };\n }\n return { success: false, error: `Failed to download fulltext for ${identifier}` };\n }\n\n return {\n success: true,\n referenceId,\n source: usedSource,\n attachedFiles,\n };\n}\n","/**\n * Fulltext convert operation.\n *\n * Converts an attached PMC JATS XML file to Markdown.\n */\n\nimport { access } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { convertPmcXmlToMarkdown } from \"@ncukondo/academic-fulltext\";\nimport type { CslItem } from \"../../../core/csl-json/types.js\";\nimport type { ILibrary, IdentifierType } from \"../../../core/library-interface.js\";\nimport type { Attachments } from \"../../attachments/types.js\";\nimport { fulltextAttach } from \"./attach.js\";\n\nexport interface FulltextConvertOptions {\n /** Reference identifier (id or uuid) */\n identifier: string;\n /** Identifier type: 'id' (default), 'uuid', 'doi', 'pmid', or 'isbn' */\n idType?: IdentifierType | undefined;\n /** Directory for fulltext attachments */\n fulltextDirectory: string;\n}\n\nexport interface FulltextConvertResult {\n success: boolean;\n error?: string;\n /** The converted markdown filename */\n filename?: string;\n}\n\nfunction findXmlFile(item: CslItem): string | undefined {\n const attachments = item.custom?.attachments as Attachments | undefined;\n if (!attachments?.files) return undefined;\n\n const xmlFile = attachments.files.find(\n (f) => f.role === \"fulltext\" && f.filename.endsWith(\".xml\")\n );\n return xmlFile?.filename;\n}\n\nfunction getXmlPath(item: CslItem, xmlFilename: string, fulltextDirectory: string): string {\n const attachments = item.custom?.attachments as Attachments | undefined;\n const directory = attachments?.directory ?? \"\";\n return join(fulltextDirectory, directory, xmlFilename);\n}\n\nexport async function fulltextConvert(\n library: ILibrary,\n options: FulltextConvertOptions\n): Promise<FulltextConvertResult> {\n const { identifier, idType = \"id\", fulltextDirectory } = options;\n\n const item = await library.find(identifier, { idType });\n if (!item) {\n return { success: false, error: `Reference '${identifier}' not found` };\n }\n\n const xmlFilename = findXmlFile(item as CslItem);\n if (!xmlFilename) {\n return { success: false, error: `No PMC XML file attached to '${identifier}'` };\n }\n\n const xmlPath = getXmlPath(item as CslItem, xmlFilename, fulltextDirectory);\n\n // Verify file exists on disk\n try {\n await access(xmlPath);\n } catch {\n return { success: false, error: `XML file not found on disk: ${xmlPath}` };\n }\n\n // Convert to temp file then attach\n const mdPath = xmlPath.replace(/\\.xml$/, \".md\");\n const convertResult = await convertPmcXmlToMarkdown(xmlPath, mdPath);\n if (!convertResult.success) {\n return {\n success: false,\n error: `Failed to convert PMC XML to Markdown: ${convertResult.error ?? \"unknown error\"}`,\n };\n }\n\n const attachResult = await fulltextAttach(library, {\n identifier,\n idType,\n filePath: mdPath,\n type: \"markdown\",\n force: true,\n move: true,\n fulltextDirectory,\n });\n\n if (!attachResult.success) {\n return { success: false, error: attachResult.error ?? \"Attach failed\" };\n }\n\n return {\n success: true,\n filename: attachResult.filename ?? \"fulltext.md\",\n };\n}\n","import type { CslItem } from \"../../core/csl-json/types.js\";\n\n/**\n * Extract first author name with initial\n * Returns \"Family G\" or \"Family\" if no given name\n */\nfunction formatFirstAuthor(item: CslItem): string {\n if (!item.author || item.author.length === 0) {\n return \"Unknown\";\n }\n\n const firstAuthor = item.author[0];\n if (!firstAuthor) {\n return \"Unknown\";\n }\n\n const family = firstAuthor.family || \"Unknown\";\n const givenInitial = firstAuthor.given ? firstAuthor.given[0] : \"\";\n\n if (givenInitial) {\n return `${family} ${givenInitial}`;\n }\n return family;\n}\n\n/**\n * Check if item has multiple authors\n */\nfunction hasMultipleAuthors(item: CslItem): boolean {\n return (item.author?.length || 0) > 1;\n}\n\n/**\n * Extract year from CSL-JSON issued field\n */\nfunction extractYear(item: CslItem): string {\n if (item.issued?.[\"date-parts\"]?.[0]?.[0]) {\n return String(item.issued[\"date-parts\"][0][0]);\n }\n return \"n.d.\";\n}\n\n/**\n * Get journal abbreviation (prefer short title)\n */\nfunction getJournalAbbrev(item: CslItem): string {\n const containerTitleShort = (item as Record<string, unknown>)[\"container-title-short\"];\n if (typeof containerTitleShort === \"string\") {\n return containerTitleShort;\n }\n return item[\"container-title\"] || \"\";\n}\n\n/**\n * Format volume/issue/pages section\n * Returns formats like: \"10(2):123-145\", \"10:123-145\", \"10(2)\", \"10\", or \"\"\n */\nfunction formatVolumeIssuePage(item: CslItem): string {\n const volume = item.volume;\n const issue = item.issue;\n const page = item.page;\n\n if (!volume && !issue && !page) {\n return \"\";\n }\n\n let result = \"\";\n\n if (volume) {\n result += volume;\n if (issue) {\n result += `(${issue})`;\n }\n if (page) {\n result += `:${page}`;\n }\n } else if (page) {\n result += page;\n }\n\n return result;\n}\n\n/**\n * Get identifier (PMID > DOI > URL priority)\n */\nfunction getIdentifier(item: CslItem): string {\n if (item.PMID) {\n return `PMID:${item.PMID}`;\n }\n if (item.DOI) {\n return `DOI:${item.DOI}`;\n }\n if (item.URL) {\n return item.URL;\n }\n return \"\";\n}\n\n/**\n * Format a single bibliography entry\n */\nfunction formatBibliographyEntry(item: CslItem): string {\n const parts: string[] = [];\n\n // Author\n const author = formatFirstAuthor(item);\n const etAl = hasMultipleAuthors(item) ? \" et al\" : \"\";\n parts.push(`${author}${etAl}.`);\n\n // Journal\n const journal = getJournalAbbrev(item);\n if (journal) {\n parts.push(`${journal}.`);\n }\n\n // Year and volume/issue/pages\n const year = extractYear(item);\n const volumeIssuePage = formatVolumeIssuePage(item);\n\n if (volumeIssuePage) {\n parts.push(`${year};${volumeIssuePage}.`);\n } else {\n parts.push(`${year}.`);\n }\n\n // Identifier\n const identifier = getIdentifier(item);\n if (identifier) {\n parts.push(`${identifier}.`);\n }\n\n // Title\n if (item.title) {\n parts.push(`${item.title}.`);\n }\n\n return parts.join(\" \");\n}\n\n/**\n * Get first author family name only (for in-text citations)\n */\nfunction getFirstAuthorFamilyName(item: CslItem): string {\n if (!item.author || item.author.length === 0) {\n return \"Unknown\";\n }\n\n const firstAuthor = item.author[0];\n if (!firstAuthor) {\n return \"Unknown\";\n }\n\n return firstAuthor.family || \"Unknown\";\n}\n\n/**\n * Format a single in-text citation (without parentheses)\n * Returns \"Family et al, YYYY\" or \"Family, YYYY\"\n */\nfunction formatInTextEntry(item: CslItem): string {\n const author = getFirstAuthorFamilyName(item);\n const etAl = hasMultipleAuthors(item) ? \" et al\" : \"\";\n const year = extractYear(item);\n\n return `${author}${etAl}, ${year}`;\n}\n\n/**\n * Format CSL-JSON items as simplified AMA-like bibliography entries.\n *\n * Format: FirstAuthor [et al]. JournalAbbrev. YYYY;volume(issue):pages. PMID:xxxxx [or DOI:xxxxx]. Title.\n *\n * Multiple items are separated by double newlines.\n *\n * @param items - Array of CSL-JSON items\n * @returns Formatted bibliography entries separated by double newlines\n */\nexport function formatBibliography(items: CslItem[]): string {\n if (items.length === 0) {\n return \"\";\n }\n\n return items.map(formatBibliographyEntry).join(\"\\n\\n\");\n}\n\n/**\n * Format CSL-JSON items as simplified in-text citations.\n *\n * Format: (FirstAuthor et al, YYYY)\n *\n * Multiple items are separated by semicolons and enclosed in parentheses.\n *\n * @param items - Array of CSL-JSON items\n * @returns Formatted in-text citation(s) enclosed in parentheses\n */\nexport function formatInText(items: CslItem[]): string {\n if (items.length === 0) {\n return \"\";\n }\n\n const citations = items.map(formatInTextEntry).join(\"; \");\n return `(${citations})`;\n}\n","import { Cite, plugins } from \"@citation-js/core\";\nimport \"@citation-js/plugin-csl\";\nimport type { CslItem } from \"../../core/csl-json/types.js\";\nimport { formatBibliography, formatInText } from \"./citation-fallback.js\";\n\n/**\n * Options for CSL citation formatting\n */\nexport type CitationFormatOptions = {\n /**\n * CSL style name (e.g., 'apa', 'vancouver', 'chicago')\n * @default 'apa'\n */\n style?: string;\n\n /**\n * Custom CSL style XML content.\n * When provided, this XML is registered and used instead of built-in styles.\n */\n styleXml?: string;\n\n /**\n * Output format: text, html, or rtf\n * @default 'text'\n */\n format?: \"text\" | \"html\" | \"rtf\";\n\n /**\n * Locale code (e.g., 'en-US', 'en-GB')\n * @default 'en-US'\n */\n locale?: string;\n};\n\n/**\n * Register a custom CSL style with citation-js.\n * Returns the style name to use for formatting.\n * @throws Error if CSL XML is invalid or malformed\n */\nfunction registerCustomStyle(styleName: string, styleXml: string): string {\n // Basic XML validation\n if (!styleXml.includes(\"<style\") || !styleXml.includes(\"</style>\")) {\n throw new Error(\n \"Invalid CSL file: Missing <style> element. The file may be malformed or not a valid CSL style.\"\n );\n }\n\n // Check for required CSL sections\n const hasCitation = styleXml.includes(\"<citation\") || styleXml.includes(\"<citation>\");\n const hasBibliography = styleXml.includes(\"<bibliography\") || styleXml.includes(\"<bibliography>\");\n if (!hasCitation && !hasBibliography) {\n throw new Error(\n \"Invalid CSL file: Missing <citation> or <bibliography> section. \" +\n \"A valid CSL style must define at least one of these sections.\"\n );\n }\n\n try {\n const config = plugins.config.get(\"@csl\");\n config.templates.add(styleName, styleXml);\n return styleName;\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to register CSL style '${styleName}': ${message}`);\n }\n}\n\n/**\n * Format CSL-JSON items as bibliography using CSL processor.\n * Falls back to simplified format if CSL processing fails.\n *\n * @param items - Array of CSL-JSON items\n * @param options - Formatting options\n * @returns Formatted bibliography entries\n */\nexport function formatBibliographyCSL(items: CslItem[], options: CitationFormatOptions): string {\n // Handle empty array\n if (items.length === 0) {\n return \"\";\n }\n\n // Set defaults\n let style = options.style || \"apa\";\n const format = options.format || \"text\";\n const locale = options.locale || \"en-US\";\n\n // Register custom style if XML is provided\n if (options.styleXml) {\n style = registerCustomStyle(style, options.styleXml);\n }\n\n try {\n // Create Cite instance with CSL-JSON data\n const cite = new Cite(items);\n\n // Format as bibliography\n const result = cite.format(\"bibliography\", {\n format,\n template: style,\n lang: locale,\n });\n\n return result;\n } catch (error) {\n // Fall back to simplified format on any error\n const errorMessage = error instanceof Error ? error.message : String(error);\n process.stderr.write(\n `Warning: CSL processing failed (style: ${style}), falling back to simplified format: ${errorMessage}\\n`\n );\n return formatBibliography(items);\n }\n}\n\n/**\n * Format CSL-JSON items as in-text citations using CSL processor.\n * Falls back to simplified format if CSL processing fails.\n *\n * @param items - Array of CSL-JSON items\n * @param options - Formatting options\n * @returns Formatted in-text citation(s)\n */\nexport function formatInTextCSL(items: CslItem[], options: CitationFormatOptions): string {\n // Handle empty array\n if (items.length === 0) {\n return \"\";\n }\n\n // Set defaults\n let style = options.style || \"apa\";\n const format = options.format || \"text\";\n const locale = options.locale || \"en-US\";\n\n // Register custom style if XML is provided\n if (options.styleXml) {\n style = registerCustomStyle(style, options.styleXml);\n }\n\n try {\n // Create Cite instance with CSL-JSON data\n const cite = new Cite(items);\n\n // Format as in-text citation\n const result = cite.format(\"citation\", {\n format,\n template: style,\n lang: locale,\n });\n\n return result;\n } catch (error) {\n // Fall back to simplified format on any error\n const errorMessage = error instanceof Error ? error.message : String(error);\n process.stderr.write(\n `Warning: CSL processing failed (style: ${style}), falling back to simplified format: ${errorMessage}\\n`\n );\n return formatInText(items);\n }\n}\n","/**\n * Reference sorter\n */\n\nimport type { CslItem } from \"../../core/csl-json/types.js\";\nimport type { SortField, SortOrder } from \"./types.js\";\n\n/**\n * Extract created_at timestamp from item, returns epoch (0) if missing\n */\nfunction getCreatedAt(item: CslItem): number {\n const createdAt = item.custom?.created_at;\n if (!createdAt) return 0;\n return new Date(createdAt).getTime();\n}\n\n/**\n * Extract updated timestamp from item, falls back to created_at\n */\nfunction getUpdatedAt(item: CslItem): number {\n const timestamp = item.custom?.timestamp;\n if (timestamp) return new Date(timestamp).getTime();\n return getCreatedAt(item);\n}\n\n/**\n * Extract published date as comparable number\n * Returns 0 (epoch) if missing\n */\nfunction getPublishedDate(item: CslItem): number {\n const dateParts = item.issued?.[\"date-parts\"]?.[0];\n if (!dateParts || dateParts.length === 0) return 0;\n\n const year = dateParts[0] ?? 0;\n const month = dateParts[1] ?? 1;\n const day = dateParts[2] ?? 1;\n\n return new Date(year, month - 1, day).getTime();\n}\n\n/**\n * Extract first author's sortable name\n * Returns \"Anonymous\" if no author\n */\nfunction getAuthorName(item: CslItem): string {\n const firstAuthor = item.author?.[0];\n if (!firstAuthor) return \"Anonymous\";\n\n return firstAuthor.family ?? firstAuthor.literal ?? \"Anonymous\";\n}\n\n/**\n * Extract title, returns empty string if missing\n */\nfunction getTitle(item: CslItem): string {\n return item.title ?? \"\";\n}\n\n/**\n * Get sort value for a given field\n */\nfunction getSortValue(item: CslItem, field: SortField): number | string {\n switch (field) {\n case \"created\":\n return getCreatedAt(item);\n case \"updated\":\n return getUpdatedAt(item);\n case \"published\":\n return getPublishedDate(item);\n case \"author\":\n return getAuthorName(item).toLowerCase();\n case \"title\":\n return getTitle(item).toLowerCase();\n }\n}\n\n/**\n * Compare function for sorting\n */\nfunction compareValues(a: number | string, b: number | string, order: SortOrder): number {\n const multiplier = order === \"desc\" ? -1 : 1;\n\n if (typeof a === \"number\" && typeof b === \"number\") {\n return (a - b) * multiplier;\n }\n\n const strA = String(a);\n const strB = String(b);\n return strA.localeCompare(strB) * multiplier;\n}\n\n/**\n * Sort references by the specified field and order.\n * Uses secondary sort: created (desc), then id (asc) for stability.\n *\n * @param items - References to sort\n * @param sort - Sort field\n * @param order - Sort order\n * @returns Sorted references (new array, does not mutate input)\n */\nexport function sortReferences(items: CslItem[], sort: SortField, order: SortOrder): CslItem[] {\n return [...items].sort((a, b) => {\n // Primary sort\n const aValue = getSortValue(a, sort);\n const bValue = getSortValue(b, sort);\n const primaryCompare = compareValues(aValue, bValue, order);\n\n if (primaryCompare !== 0) return primaryCompare;\n\n // Secondary sort: created (desc)\n const aCreated = getCreatedAt(a);\n const bCreated = getCreatedAt(b);\n const createdCompare = bCreated - aCreated; // desc\n\n if (createdCompare !== 0) return createdCompare;\n\n // Tertiary sort: id (asc) for stability\n return a.id.localeCompare(b.id);\n });\n}\n","/**\n * Pagination applier\n */\n\nexport interface PaginateOptions {\n limit?: number;\n offset?: number;\n}\n\nexport interface PaginateResult<T> {\n items: T[];\n nextOffset: number | null;\n}\n\n/**\n * Apply pagination to an array of items.\n *\n * @param items - Items to paginate\n * @param options - Pagination options (limit=0 or undefined means unlimited)\n * @returns Paginated items with nextOffset (null if no more items)\n */\nexport function paginate<T>(items: T[], options: PaginateOptions): PaginateResult<T> {\n const offset = options.offset ?? 0;\n const limit = options.limit ?? 0;\n\n // Validate inputs\n if (limit < 0) {\n throw new Error(\"limit must be non-negative\");\n }\n if (offset < 0) {\n throw new Error(\"offset must be non-negative\");\n }\n\n const isUnlimited = limit === 0;\n\n // Apply offset\n const afterOffset = items.slice(offset);\n\n // Apply limit (0 means unlimited)\n const paginatedItems = isUnlimited ? afterOffset : afterOffset.slice(0, limit);\n\n // Calculate nextOffset\n let nextOffset: number | null = null;\n if (!isUnlimited && paginatedItems.length > 0) {\n const nextPosition = offset + paginatedItems.length;\n if (nextPosition < items.length) {\n nextOffset = nextPosition;\n }\n }\n\n return {\n items: paginatedItems,\n nextOffset,\n };\n}\n","/**\n * CSL Style Management\n *\n * Handles resolution and loading of CSL (Citation Style Language) style files.\n *\n * Style Resolution Order:\n * 1. --csl-file <path> (exact file path)\n * 2. Built-in style matching --style <name>\n * 3. Search in csl_directory paths (in array order)\n * 4. Default style from config (default_style)\n * 5. \"apa\" (hardcoded default)\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\n\n/**\n * Built-in styles available in @citation-js/plugin-csl\n * These can be used directly without loading external files\n */\nexport const BUILTIN_STYLES = [\"apa\", \"vancouver\", \"harvard\"] as const;\n\nexport type BuiltinStyleName = (typeof BUILTIN_STYLES)[number];\n\n/**\n * Check if a style name is a built-in style\n */\nexport function isBuiltinStyle(styleName: string): styleName is BuiltinStyleName {\n return BUILTIN_STYLES.includes(styleName as BuiltinStyleName);\n}\n\nexport interface StyleResolutionOptions {\n /**\n * Exact path to CSL file (from --csl-file option)\n * Takes highest priority\n */\n cslFile?: string;\n\n /**\n * Style name to resolve (from --style option)\n */\n style?: string;\n\n /**\n * Directory or directories to search for custom CSL files\n * (from csl_directory config)\n * Can be a single string or array of strings\n */\n cslDirectory?: string | string[];\n\n /**\n * Default style to use if specified style not found\n * (from default_style config)\n */\n defaultStyle?: string;\n}\n\nexport interface StyleResolution {\n /**\n * Type of resolution: \"builtin\" for citation-js built-in styles,\n * \"custom\" for external CSL files\n */\n type: \"builtin\" | \"custom\";\n\n /**\n * The resolved style name (for built-in) or identifier (for custom)\n */\n styleName: string;\n\n /**\n * CSL XML content (only for custom styles)\n */\n styleXml?: string;\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 * Load CSL style file content from the given path\n *\n * @param stylePath - Path to the CSL style file\n * @returns Content of the CSL style file (XML string)\n * @throws Error if file cannot be read\n */\nexport function loadCSLStyleFile(stylePath: string): string {\n return fs.readFileSync(stylePath, \"utf-8\");\n}\n\n/**\n * Resolve the style based on resolution options\n *\n * Resolution order:\n * 1. cslFile (exact path) - throws if doesn't exist\n * 2. Built-in style matching style name\n * 3. Search in csl_directory paths (in order)\n * 4. Default style (defaultStyle) - if built-in\n * 5. \"apa\" (hardcoded fallback)\n *\n * @param options - Style resolution options\n * @returns StyleResolution with type, styleName, and optional styleXml\n * @throws Error if cslFile is specified but doesn't exist\n */\nexport function resolveStyle(options: StyleResolutionOptions): StyleResolution {\n const { cslFile, style, cslDirectory, defaultStyle } = options;\n\n // 1. If cslFile is specified, use it (highest priority)\n if (cslFile) {\n if (!fs.existsSync(cslFile)) {\n throw new Error(`CSL file '${cslFile}' not found`);\n }\n const styleXml = loadCSLStyleFile(cslFile);\n const styleName = path.basename(cslFile, \".csl\");\n return {\n type: \"custom\",\n styleName,\n styleXml,\n };\n }\n\n // Determine which style name to try\n const styleToResolve = style || defaultStyle || \"apa\";\n\n // 2. Check if it's a built-in style\n if (isBuiltinStyle(styleToResolve)) {\n return {\n type: \"builtin\",\n styleName: styleToResolve,\n };\n }\n\n // 3. Search in csl_directory paths\n if (cslDirectory) {\n const directories = Array.isArray(cslDirectory) ? cslDirectory : [cslDirectory];\n\n for (const dir of directories) {\n const expandedDir = expandTilde(dir);\n const stylePath = path.join(expandedDir, `${styleToResolve}.csl`);\n\n if (fs.existsSync(stylePath)) {\n const styleXml = loadCSLStyleFile(stylePath);\n return {\n type: \"custom\",\n styleName: styleToResolve,\n styleXml,\n };\n }\n }\n }\n\n // 4. Fall back to default style if it's built-in\n if (defaultStyle && isBuiltinStyle(defaultStyle)) {\n return {\n type: \"builtin\",\n styleName: defaultStyle,\n };\n }\n\n // 5. Fall back to apa (hardcoded default)\n return {\n type: \"builtin\",\n styleName: \"apa\",\n };\n}\n","import { rmdir, unlink } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type { CslItem } from \"../../core/csl-json/types.js\";\nimport type { ILibrary, IdentifierType } from \"../../core/library-interface.js\";\nimport type { Attachments } from \"../attachments/types.js\";\nimport type { FulltextType } from \"../fulltext/index.js\";\nimport { extensionToFormat, findFulltextFiles } from \"./fulltext-adapter/index.js\";\n\n/**\n * Options for removeReference operation\n */\nexport interface RemoveOperationOptions {\n /** Reference ID or UUID */\n identifier: string;\n /** Identifier type: 'id' (default), 'uuid', 'doi', 'pmid', or 'isbn' */\n idType?: IdentifierType;\n /** Directory containing fulltext files (required if deleteFulltext is true) */\n fulltextDirectory?: string;\n /** Whether to delete associated fulltext files */\n deleteFulltext?: boolean;\n}\n\n/**\n * Result of removeReference operation\n */\nexport interface RemoveResult {\n /** Whether the reference was removed */\n removed: boolean;\n /** The removed item (if found and removal succeeded) */\n removedItem?: CslItem;\n /** Fulltext types that were deleted (only when deleteFulltext=true) */\n deletedFulltextTypes?: FulltextType[];\n}\n\n/**\n * Get fulltext attachment types from a CSL item.\n */\nexport function getFulltextAttachmentTypes(item: CslItem): FulltextType[] {\n const types: FulltextType[] = [];\n\n // Check attachments structure\n const attachments = item.custom?.attachments as Attachments | undefined;\n const fulltextFiles = findFulltextFiles(attachments);\n for (const file of fulltextFiles) {\n const ext = file.filename.split(\".\").pop()?.toLowerCase();\n const format = ext ? extensionToFormat(ext) : undefined;\n if (format && !types.includes(format)) {\n types.push(format);\n }\n }\n\n return types;\n}\n\n/**\n * Delete fulltext files associated with an item.\n */\nasync function deleteFulltextFiles(item: CslItem, fulltextDirectory: string): Promise<void> {\n const filesToDelete: string[] = [];\n\n // Check attachments structure\n const attachments = item.custom?.attachments as Attachments | undefined;\n if (attachments?.directory) {\n const fulltextFiles = findFulltextFiles(attachments);\n for (const file of fulltextFiles) {\n filesToDelete.push(join(fulltextDirectory, attachments.directory, file.filename));\n }\n }\n\n // Delete individual files\n for (const filePath of filesToDelete) {\n try {\n await unlink(filePath);\n } catch {\n // Ignore errors (file might not exist)\n }\n }\n\n // Try to remove the attachments directory if it's now empty\n if (attachments?.directory) {\n try {\n const dirPath = join(fulltextDirectory, attachments.directory);\n await rmdir(dirPath); // Only removes if empty\n } catch {\n // Ignore - directory might not be empty or not exist\n }\n }\n}\n\n/**\n * Remove a reference from the library.\n *\n * @param library - The library to remove from\n * @param options - Remove options including identifier and lookup method\n * @returns Result indicating success and the removed item\n */\nexport async function removeReference(\n library: ILibrary,\n options: RemoveOperationOptions\n): Promise<RemoveResult> {\n const { identifier, idType = \"id\", fulltextDirectory, deleteFulltext = false } = options;\n\n const result = await library.remove(identifier, { idType });\n\n if (!result.removed || !result.removedItem) {\n return { removed: false };\n }\n\n // Delete fulltext files if requested\n let deletedFulltextTypes: FulltextType[] | undefined;\n if (deleteFulltext && fulltextDirectory) {\n deletedFulltextTypes = getFulltextAttachmentTypes(result.removedItem);\n if (deletedFulltextTypes.length > 0) {\n await deleteFulltextFiles(result.removedItem, fulltextDirectory);\n }\n }\n\n await library.save();\n\n return {\n removed: true,\n removedItem: result.removedItem,\n ...(deletedFulltextTypes && deletedFulltextTypes.length > 0 && { deletedFulltextTypes }),\n };\n}\n","/**\n * Response cache for PMID and DOI metadata\n *\n * In-memory cache with TTL to avoid redundant API calls.\n * - Per ADR-001: No persistent cache files on disk\n * - Cache is warm during interactive sessions (server mode)\n * - CLI invocations start fresh\n */\n\nimport type { CslItem } from \"../../core/csl-json/types.js\";\n\n/** Default TTL: 1 hour */\nconst DEFAULT_TTL_MS = 60 * 60 * 1000;\n\n/**\n * Cache configuration\n */\nexport interface CacheConfig {\n /** Time-to-live in milliseconds (default: 1 hour) */\n ttlMs?: number;\n}\n\n/**\n * Cache entry with timestamp and TTL\n */\ninterface CacheEntry {\n item: CslItem;\n cachedAt: number;\n ttlMs: number;\n}\n\n/** PMID cache: Map<pmid, CacheEntry> */\nconst pmidCache = new Map<string, CacheEntry>();\n\n/** DOI cache: Map<doi, CacheEntry> */\nconst doiCache = new Map<string, CacheEntry>();\n\n/** ISBN cache: Map<isbn, CacheEntry> */\nconst isbnCache = new Map<string, CacheEntry>();\n\n/**\n * Check if a cache entry is still valid\n */\nfunction isEntryValid(entry: CacheEntry): boolean {\n const now = Date.now();\n return now - entry.cachedAt < entry.ttlMs;\n}\n\n/**\n * Get item from cache if valid\n */\nfunction getFromCache(cache: Map<string, CacheEntry>, key: string): CslItem | undefined {\n const entry = cache.get(key);\n if (!entry) {\n return undefined;\n }\n if (!isEntryValid(entry)) {\n cache.delete(key);\n return undefined;\n }\n return entry.item;\n}\n\n/**\n * Store item in cache\n */\nfunction storeInCache(\n cache: Map<string, CacheEntry>,\n key: string,\n item: CslItem,\n config?: CacheConfig\n): void {\n const ttlMs = config?.ttlMs ?? DEFAULT_TTL_MS;\n cache.set(key, {\n item,\n cachedAt: Date.now(),\n ttlMs,\n });\n}\n\n/**\n * Get cached PMID result\n */\nexport function getPmidFromCache(pmid: string): CslItem | undefined {\n return getFromCache(pmidCache, pmid);\n}\n\n/**\n * Cache PMID result\n */\nexport function cachePmidResult(pmid: string, item: CslItem, config?: CacheConfig): void {\n storeInCache(pmidCache, pmid, item, config);\n}\n\n/**\n * Get cached DOI result\n */\nexport function getDoiFromCache(doi: string): CslItem | undefined {\n return getFromCache(doiCache, doi);\n}\n\n/**\n * Cache DOI result\n */\nexport function cacheDoiResult(doi: string, item: CslItem, config?: CacheConfig): void {\n storeInCache(doiCache, doi, item, config);\n}\n\n/**\n * Get cached ISBN result\n */\nexport function getIsbnFromCache(isbn: string): CslItem | undefined {\n return getFromCache(isbnCache, isbn);\n}\n\n/**\n * Cache ISBN result\n */\nexport function cacheIsbnResult(isbn: string, item: CslItem, config?: CacheConfig): void {\n storeInCache(isbnCache, isbn, item, config);\n}\n\n/**\n * Reset all caches (for test isolation)\n */\nexport function resetCache(): void {\n pmidCache.clear();\n doiCache.clear();\n isbnCache.clear();\n}\n","/**\n * DOI normalizer module\n *\n * Normalizes DOI identifiers by:\n * - Removing URL prefixes (doi.org, dx.doi.org)\n * - Trimming whitespace\n */\n\n/**\n * URL prefixes to remove from DOI\n */\nconst DOI_URL_PREFIXES = [\n \"https://doi.org/\",\n \"http://doi.org/\",\n \"https://dx.doi.org/\",\n \"http://dx.doi.org/\",\n];\n\n/**\n * Normalize a DOI identifier\n *\n * @param doi - DOI string, possibly with URL prefix\n * @returns Normalized DOI (10.xxx/xxx format)\n */\nexport function normalizeDoi(doi: string): string {\n // Trim whitespace\n const trimmed = doi.trim();\n\n if (!trimmed) {\n return \"\";\n }\n\n // Check for URL prefixes (case-insensitive)\n const lowerInput = trimmed.toLowerCase();\n\n for (const prefix of DOI_URL_PREFIXES) {\n if (lowerInput.startsWith(prefix.toLowerCase())) {\n // Remove the prefix while preserving the original case of the DOI\n return trimmed.slice(prefix.length);\n }\n }\n\n // No prefix found, return as-is\n return trimmed;\n}\n\n/**\n * Normalizes a PMID by removing the optional \"PMID:\" prefix and trimming whitespace.\n *\n * Supported formats:\n * - \"12345678\" -> \"12345678\"\n * - \"PMID:12345678\" -> \"12345678\"\n * - \"pmid:12345678\" -> \"12345678\"\n * - \"PMID: 12345678\" -> \"12345678\" (space after colon)\n *\n * @param pmid - The PMID string to normalize\n * @returns The normalized PMID (digits only) or empty string if invalid\n */\nexport function normalizePmid(pmid: string): string {\n // Trim whitespace\n const trimmed = pmid.trim();\n\n if (!trimmed) {\n return \"\";\n }\n\n // Remove \"PMID:\" prefix (case-insensitive, optional whitespace after colon)\n const normalized = trimmed.replace(/^pmid:\\s*/i, \"\");\n\n return normalized.trim();\n}\n\n/**\n * Normalizes an ISBN by removing the \"ISBN:\" prefix, hyphens, spaces, and uppercasing X.\n *\n * Supported formats:\n * - \"ISBN:978-4-00-000000-0\" -> \"9784000000000\"\n * - \"isbn:4-00-000000-0\" -> \"4000000000\"\n * - \"ISBN: 978 4 00 000000 0\" -> \"9784000000000\"\n * - \"ISBN:400000000x\" -> \"400000000X\" (uppercase X)\n *\n * @param isbn - The ISBN string to normalize\n * @returns The normalized ISBN (digits only, X uppercase at end for ISBN-10) or empty string if invalid\n */\nexport function normalizeIsbn(isbn: string): string {\n // Trim whitespace\n const trimmed = isbn.trim();\n\n if (!trimmed) {\n return \"\";\n }\n\n // Check for ISBN: prefix (case-insensitive)\n if (!/^isbn:/i.test(trimmed)) {\n return \"\";\n }\n\n // Remove \"ISBN:\" prefix (case-insensitive, optional whitespace after colon)\n let normalized = trimmed.replace(/^isbn:\\s*/i, \"\");\n\n // Remove hyphens and spaces\n normalized = normalized.replace(/[-\\s]/g, \"\");\n\n // Uppercase X (for ISBN-10 check digit)\n normalized = normalized.toUpperCase();\n\n return normalized;\n}\n","/**\n * Format detection module for multi-format import\n *\n * Detects input format based on:\n * - File extension (.json, .bib, .ris)\n * - Content patterns (JSON, BibTeX, RIS)\n * - Identifier patterns (PMID, DOI)\n * - Multiple whitespace-separated identifiers\n */\n\nimport { normalizeIsbn, normalizePmid } from \"./normalizer.js\";\n\n/**\n * Supported input formats\n */\nexport type InputFormat =\n | \"json\"\n | \"bibtex\"\n | \"ris\"\n | \"nbib\"\n | \"pmid\"\n | \"doi\"\n | \"isbn\"\n | \"identifiers\"\n | \"unknown\";\n\n/**\n * Extension to format mapping\n */\nconst EXTENSION_MAP: Record<string, InputFormat> = {\n \".json\": \"json\",\n \".bib\": \"bibtex\",\n \".ris\": \"ris\",\n \".nbib\": \"nbib\",\n};\n\n/**\n * DOI URL prefixes to strip\n */\nconst DOI_URL_PREFIXES = [\n \"https://doi.org/\",\n \"http://doi.org/\",\n \"https://dx.doi.org/\",\n \"http://dx.doi.org/\",\n];\n\n/**\n * Detect the format of the given input\n *\n * @param input - File path, identifier, or empty string for stdin\n * @param content - Optional content to analyze (for stdin or unknown extension)\n * @returns Detected format\n */\nexport function detectFormat(input: string, content?: string): InputFormat {\n // 1. Try extension-based detection first\n const extFormat = detectByExtension(input);\n if (extFormat !== \"unknown\") {\n return extFormat;\n }\n\n // 2. If content provided, try content-based detection\n if (content !== undefined) {\n const contentFormat = detectByContent(content);\n if (contentFormat !== \"unknown\") {\n return contentFormat;\n }\n }\n\n // 3. Try identifier detection on input string\n if (input.length > 0) {\n const identifierFormat = detectIdentifier(input);\n if (identifierFormat !== \"unknown\") {\n return identifierFormat;\n }\n }\n\n return \"unknown\";\n}\n\n/**\n * Detect format based on file extension\n */\nexport function detectByExtension(input: string): InputFormat {\n if (!input) return \"unknown\";\n\n // Extract extension (last dot and onwards)\n const dotIndex = input.lastIndexOf(\".\");\n if (dotIndex === -1 || dotIndex === input.length - 1) {\n return \"unknown\";\n }\n\n const ext = input.slice(dotIndex).toLowerCase();\n return EXTENSION_MAP[ext] ?? \"unknown\";\n}\n\n/**\n * Detect format based on content patterns\n */\nexport function detectByContent(content: string): InputFormat {\n const trimmed = content.trim();\n if (!trimmed) return \"unknown\";\n\n // JSON: starts with [ or {\n if (trimmed.startsWith(\"[\") || trimmed.startsWith(\"{\")) {\n return \"json\";\n }\n\n // BibTeX: starts with @\n if (trimmed.startsWith(\"@\")) {\n return \"bibtex\";\n }\n\n // RIS: starts with TY - (tag format)\n if (trimmed.startsWith(\"TY -\")) {\n return \"ris\";\n }\n\n // NBIB (PubMed MEDLINE): starts with PMID-\n if (trimmed.startsWith(\"PMID-\")) {\n return \"nbib\";\n }\n\n // Check if content is multiple identifiers\n return detectIdentifier(trimmed);\n}\n\n/**\n * Detect if input is an identifier (PMID, DOI, ISBN) or multiple identifiers\n */\nfunction detectIdentifier(input: string): InputFormat {\n // Split by whitespace\n const parts = input.split(/\\s+/).filter((p) => p.length > 0);\n\n if (parts.length === 0) {\n return \"unknown\";\n }\n\n // Check each part\n const formats: (\"pmid\" | \"doi\" | \"isbn\")[] = [];\n for (const part of parts) {\n const format = detectSingleIdentifier(part);\n if (format === \"unknown\") {\n // If any part is not a valid identifier, return unknown\n return \"unknown\";\n }\n formats.push(format);\n }\n\n // Single identifier returns its specific format\n if (formats.length === 1) {\n // formats[0] is guaranteed to exist when length === 1\n return formats[0] as \"pmid\" | \"doi\" | \"isbn\";\n }\n\n // Multiple valid identifiers\n return \"identifiers\";\n}\n\n/**\n * Detect if a single string is a PMID, DOI, or ISBN\n */\nexport function detectSingleIdentifier(input: string): \"pmid\" | \"doi\" | \"isbn\" | \"unknown\" {\n // DOI: starts with 10. or is a DOI URL\n if (isDoi(input)) {\n return \"doi\";\n }\n\n // ISBN: requires ISBN: prefix\n if (isIsbn(input)) {\n return \"isbn\";\n }\n\n // PMID: numeric only (must be after ISBN check to avoid conflicts)\n if (isPmid(input)) {\n return \"pmid\";\n }\n\n return \"unknown\";\n}\n\n/**\n * Check if string is a valid DOI\n */\nexport function isDoi(input: string): boolean {\n // Check DOI URL formats\n for (const prefix of DOI_URL_PREFIXES) {\n if (input.toLowerCase().startsWith(prefix.toLowerCase())) {\n const remainder = input.slice(prefix.length);\n return isDoiFormat(remainder);\n }\n }\n\n // Check standard DOI format (10.xxx/xxx)\n return isDoiFormat(input);\n}\n\n/**\n * Check if string is a valid DOI format (10.xxx/xxx)\n */\nfunction isDoiFormat(input: string): boolean {\n // DOI starts with 10. followed by registrant code and suffix\n // Pattern: 10.{registrant}/{suffix}\n if (!input.startsWith(\"10.\")) {\n return false;\n }\n\n // Must have content after 10.\n if (input.length <= 3) {\n return false;\n }\n\n // Must have a slash after registrant code\n const slashIndex = input.indexOf(\"/\");\n if (slashIndex === -1 || slashIndex <= 3) {\n return false;\n }\n\n return true;\n}\n\n/**\n * Check if string is a valid PMID (numeric only)\n */\nexport function isPmid(input: string): boolean {\n if (!input || input.length === 0) {\n return false;\n }\n\n // Normalize input (removes PMID: prefix if present)\n const normalized = normalizePmid(input);\n\n if (!normalized) {\n return false;\n }\n\n // PMID is all digits\n return /^\\d+$/.test(normalized);\n}\n\n/**\n * Check if string is a valid ISBN (requires ISBN: prefix)\n *\n * ISBN must have ISBN: prefix and be either:\n * - ISBN-13: 13 digits\n * - ISBN-10: 10 digits (last may be X)\n */\nexport function isIsbn(input: string): boolean {\n if (!input || input.length === 0) {\n return false;\n }\n\n // Normalize input (removes ISBN: prefix if present, hyphens, spaces)\n const normalized = normalizeIsbn(input);\n\n if (!normalized) {\n return false;\n }\n\n // Check length: ISBN-10 (10 chars) or ISBN-13 (13 chars)\n if (normalized.length !== 10 && normalized.length !== 13) {\n return false;\n }\n\n // ISBN-10: 9 digits + (digit or X)\n if (normalized.length === 10) {\n // First 9 must be digits, last can be digit or X\n if (!/^\\d{9}[\\dX]$/.test(normalized)) {\n return false;\n }\n return true;\n }\n\n // ISBN-13: all digits\n if (!/^\\d{13}$/.test(normalized)) {\n return false;\n }\n\n return true;\n}\n","/**\n * Rate limiter module for API calls\n *\n * Uses factory + lazy initialization singleton pattern:\n * - RateLimiter class: Delay-based rate limiting with configurable requests/second\n * - getRateLimiter(api, config): Returns singleton per API type\n * - resetRateLimiters(): Clears singletons for test isolation\n */\n\n/**\n * API types supported by the rate limiter\n */\nexport type ApiType = \"pubmed\" | \"crossref\" | \"isbn\";\n\n/**\n * Configuration for rate limiter\n */\nexport interface RateLimiterConfig {\n pubmedApiKey?: string;\n}\n\n/**\n * Rate limiter interface\n */\nexport interface RateLimiter {\n readonly requestsPerSecond: number;\n readonly intervalMs: number;\n readonly lastRequestTime: number;\n acquire(): Promise<void>;\n}\n\n/**\n * Rate limit settings per API type\n */\nconst RATE_LIMITS = {\n pubmed: {\n withoutApiKey: 3, // 3 req/sec\n withApiKey: 10, // 10 req/sec\n },\n crossref: 50, // 50 req/sec\n isbn: 10, // 10 req/sec (conservative for Google Books API daily limit)\n} as const;\n\n/**\n * Internal rate limiter implementation\n */\nclass RateLimiterImpl implements RateLimiter {\n readonly requestsPerSecond: number;\n readonly intervalMs: number;\n private _lastRequestTime = 0;\n private _pending: Promise<void> = Promise.resolve();\n\n constructor(requestsPerSecond: number) {\n this.requestsPerSecond = requestsPerSecond;\n this.intervalMs = 1000 / requestsPerSecond;\n }\n\n get lastRequestTime(): number {\n return this._lastRequestTime;\n }\n\n async acquire(): Promise<void> {\n // Chain onto pending promise to ensure sequential processing\n this._pending = this._pending.then(() => this._acquireInternal());\n return this._pending;\n }\n\n private async _acquireInternal(): Promise<void> {\n const now = Date.now();\n const elapsed = now - this._lastRequestTime;\n const waitTime = Math.max(0, this.intervalMs - elapsed);\n\n if (waitTime > 0 && this._lastRequestTime > 0) {\n await this._delay(waitTime);\n }\n\n this._lastRequestTime = Date.now();\n }\n\n private _delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n}\n\n/**\n * Singleton storage for rate limiters by API type\n */\nconst limiters = new Map<ApiType, RateLimiter>();\n\n/**\n * Create a new rate limiter instance\n */\nexport function createRateLimiter(options: {\n requestsPerSecond: number;\n}): RateLimiter {\n return new RateLimiterImpl(options.requestsPerSecond);\n}\n\n/**\n * Get singleton rate limiter for the specified API type\n *\n * Note: Configuration is only used on first call. Subsequent calls\n * return the existing singleton regardless of config changes.\n */\nexport function getRateLimiter(api: ApiType, config: RateLimiterConfig): RateLimiter {\n const existing = limiters.get(api);\n if (existing) {\n return existing;\n }\n\n const requestsPerSecond = getRequestsPerSecond(api, config);\n const limiter = createRateLimiter({ requestsPerSecond });\n limiters.set(api, limiter);\n\n return limiter;\n}\n\n/**\n * Determine requests per second based on API type and configuration\n */\nfunction getRequestsPerSecond(api: ApiType, config: RateLimiterConfig): number {\n switch (api) {\n case \"pubmed\":\n return config.pubmedApiKey ? RATE_LIMITS.pubmed.withApiKey : RATE_LIMITS.pubmed.withoutApiKey;\n case \"crossref\":\n return RATE_LIMITS.crossref;\n case \"isbn\":\n return RATE_LIMITS.isbn;\n }\n}\n\n/**\n * Reset all rate limiter singletons (for test isolation)\n */\nexport function resetRateLimiters(): void {\n limiters.clear();\n}\n","/**\n * Fetcher module for PMID and DOI metadata retrieval\n *\n * - PMID: Uses PMC Citation Exporter API (returns CSL-JSON directly)\n * - DOI: Uses citation-js plugin-doi (Cite.async)\n */\n\nimport { Cite } from \"@citation-js/core\";\nimport \"@citation-js/plugin-doi\";\nimport \"@citation-js/plugin-isbn\";\nimport { type CslItem, CslItemSchema } from \"../../core/csl-json/types.js\";\nimport { getRateLimiter } from \"./rate-limiter.js\";\n\n/** PMC Citation Exporter API base URL */\nconst PMC_API_BASE = \"https://pmc.ncbi.nlm.nih.gov/api/ctxp/v1/pubmed/\";\n\n/** Default timeout for API requests (10 seconds) */\nconst DEFAULT_TIMEOUT_MS = 10000;\n\n/** DOI pattern for validation */\nconst DOI_PATTERN = /^10\\.\\d{4,}(?:\\.\\d+)*\\/\\S+$/;\n\n/**\n * PubMed configuration for API requests\n */\nexport interface PubmedConfig {\n email?: string;\n apiKey?: string;\n}\n\n/**\n * Categorized failure reasons for JSON output\n */\nexport type FailureReason =\n | \"not_found\"\n | \"fetch_error\"\n | \"parse_error\"\n | \"validation_error\"\n | \"unknown\";\n\n/**\n * Result of fetching a single identifier\n */\nexport type FetchResult =\n | { success: true; item: CslItem }\n | { success: false; error: string; reason: FailureReason };\n\n/**\n * Result of fetching a PMID (includes pmid for tracking)\n */\nexport type PmidFetchResult =\n | { pmid: string; success: true; item: CslItem }\n | { pmid: string; success: false; error: string; reason: FailureReason };\n\n/**\n * Results of fetching multiple PMIDs\n */\nexport type FetchResults = PmidFetchResult[];\n\n/**\n * Build PMC API URL with query parameters\n */\nfunction buildPmcUrl(pmids: string[], config: PubmedConfig): string {\n const url = new URL(PMC_API_BASE);\n url.searchParams.set(\"format\", \"csl\");\n\n // Add each PMID as separate id parameter\n for (const pmid of pmids) {\n url.searchParams.append(\"id\", pmid);\n }\n\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\n return url.toString();\n}\n\n/**\n * Extract PMID from CSL-JSON item id field\n * PMC API returns id like \"pmid:12345678\"\n */\nfunction extractPmidFromId(id: string | undefined): string | undefined {\n if (!id) return undefined;\n const match = id.match(/^pmid:(\\d+)$/);\n return match?.[1];\n}\n\n/**\n * Fetch metadata for multiple PMIDs from PMC Citation Exporter API\n *\n * Uses batch API endpoint: /api/ctxp/v1/pubmed/?format=csl&id=1&id=2\n */\n\n/**\n * Parse raw API items and build maps of found items and validation errors\n */\nfunction parseRawItems(rawItems: unknown[]): {\n foundItems: Map<string, CslItem>;\n validationErrors: Map<string, string>;\n} {\n const foundItems = new Map<string, CslItem>();\n const validationErrors = new Map<string, string>();\n\n for (const rawItem of rawItems) {\n const parseResult = CslItemSchema.safeParse(rawItem);\n if (parseResult.success) {\n const pmid = extractPmidFromId(parseResult.data.id);\n if (pmid) {\n foundItems.set(pmid, parseResult.data);\n }\n } else {\n // Try to extract pmid even from invalid data for error reporting\n const maybeId = (rawItem as { id?: string })?.id;\n const pmid = extractPmidFromId(maybeId);\n if (pmid) {\n validationErrors.set(pmid, parseResult.error.message);\n }\n }\n }\n\n return { foundItems, validationErrors };\n}\n\n/**\n * Build fetch result for a single PMID\n */\nfunction buildPmidResult(\n pmid: string,\n foundItems: Map<string, CslItem>,\n validationErrors: Map<string, string>\n): PmidFetchResult {\n const item = foundItems.get(pmid);\n if (item) {\n return { pmid, success: true as const, item };\n }\n const validationError = validationErrors.get(pmid);\n if (validationError) {\n return {\n pmid,\n success: false as const,\n error: `Invalid CSL-JSON data: ${validationError}`,\n reason: \"validation_error\",\n };\n }\n return {\n pmid,\n success: false as const,\n error: `PMID ${pmid} not found`,\n reason: \"not_found\",\n };\n}\n\nexport async function fetchPmids(pmids: string[], config: PubmedConfig): Promise<FetchResults> {\n // Return empty array for empty input\n if (pmids.length === 0) {\n return [];\n }\n\n // Apply rate limiting\n const rateLimiterConfig = config.apiKey ? { pubmedApiKey: config.apiKey } : {};\n const rateLimiter = getRateLimiter(\"pubmed\", rateLimiterConfig);\n await rateLimiter.acquire();\n\n const url = buildPmcUrl(pmids, config);\n\n try {\n const response = await fetch(url, {\n method: \"GET\",\n signal: AbortSignal.timeout(DEFAULT_TIMEOUT_MS),\n });\n\n if (!response.ok) {\n // Return error for all PMIDs\n const errorMsg = `HTTP ${response.status}: ${response.statusText}`;\n return pmids.map((pmid) => ({\n pmid,\n success: false as const,\n error: errorMsg,\n reason: \"fetch_error\",\n }));\n }\n\n const data = await response.json();\n\n // Normalize response to array\n const rawItems: unknown[] = Array.isArray(data) ? data : [data];\n\n // Parse raw items and build results\n const { foundItems, validationErrors } = parseRawItems(rawItems);\n\n // Build results for each requested PMID\n return pmids.map((pmid) => buildPmidResult(pmid, foundItems, validationErrors));\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n return pmids.map((pmid) => ({\n pmid,\n success: false as const,\n error: errorMsg,\n reason: \"fetch_error\",\n }));\n }\n}\n\n/**\n * Fetch metadata for a DOI using citation-js\n *\n * Uses @citation-js/plugin-doi for content negotiation\n */\nexport async function fetchDoi(doi: string): Promise<FetchResult> {\n // Validate DOI format\n if (!DOI_PATTERN.test(doi)) {\n return {\n success: false,\n error: `Invalid DOI format: ${doi}`,\n reason: \"validation_error\",\n };\n }\n\n // Apply rate limiting (crossref)\n const rateLimiter = getRateLimiter(\"crossref\", {});\n await rateLimiter.acquire();\n\n try {\n // Use citation-js Cite.async for DOI resolution\n const cite = await Cite.async(doi);\n const rawItems = cite.get({ format: \"real\", type: \"json\" });\n\n if (!rawItems || !Array.isArray(rawItems) || rawItems.length === 0) {\n return {\n success: false,\n error: `No data returned for DOI ${doi}`,\n reason: \"not_found\",\n };\n }\n\n // Validate using zod schema\n const parseResult = CslItemSchema.safeParse(rawItems[0]);\n if (!parseResult.success) {\n return {\n success: false,\n error: `Invalid CSL-JSON data for DOI ${doi}: ${parseResult.error.message}`,\n reason: \"validation_error\",\n };\n }\n\n return { success: true, item: parseResult.data };\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n return {\n success: false,\n error: errorMsg,\n reason: \"fetch_error\",\n };\n }\n}\n\n/** ISBN-10 pattern: 9 digits + (digit or X) */\nconst ISBN10_PATTERN = /^\\d{9}[\\dX]$/;\n\n/** ISBN-13 pattern: 13 digits */\nconst ISBN13_PATTERN = /^\\d{13}$/;\n\n/**\n * Fetch metadata for an ISBN using Google Books API via citation-js\n *\n * @param isbn - Normalized ISBN (10 or 13 digits, no hyphens)\n * @returns FetchResult with CSL-JSON item or error\n */\nexport async function fetchIsbn(isbn: string): Promise<FetchResult> {\n // Validate ISBN format\n if (!ISBN10_PATTERN.test(isbn) && !ISBN13_PATTERN.test(isbn)) {\n return {\n success: false,\n error: `Invalid ISBN format: ${isbn}`,\n reason: \"validation_error\",\n };\n }\n\n // Apply rate limiting (google books - daily limit so we use a generic limiter)\n const rateLimiter = getRateLimiter(\"isbn\", {});\n await rateLimiter.acquire();\n\n try {\n // Use citation-js Cite.async for ISBN resolution\n const cite = await Cite.async(isbn);\n const rawItems = cite.get({ format: \"real\", type: \"json\" });\n\n if (!rawItems || !Array.isArray(rawItems) || rawItems.length === 0) {\n return {\n success: false,\n error: `No data returned for ISBN ${isbn}`,\n reason: \"not_found\",\n };\n }\n\n // Validate using zod schema\n const parseResult = CslItemSchema.safeParse(rawItems[0]);\n if (!parseResult.success) {\n return {\n success: false,\n error: `Invalid CSL-JSON data for ISBN ${isbn}: ${parseResult.error.message}`,\n reason: \"validation_error\",\n };\n }\n\n return { success: true, item: parseResult.data };\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n return {\n success: false,\n error: errorMsg,\n reason: \"fetch_error\",\n };\n }\n}\n","/**\n * Parser module for BibTeX and RIS formats\n *\n * Uses citation-js plugins for parsing:\n * - @citation-js/plugin-bibtex for BibTeX\n * - @citation-js/plugin-ris for RIS\n */\n\nimport { Cite } from \"@citation-js/core\";\nimport \"@citation-js/plugin-bibtex\";\nimport \"@citation-js/plugin-ris\";\nimport type { CslItem } from \"../../core/csl-json/types.js\";\n\n/**\n * Result of a parse operation\n */\nexport type ParseResult = {\n success: boolean;\n items: CslItem[];\n error?: string;\n};\n\n/**\n * Parse BibTeX content to CSL-JSON\n *\n * @param content - BibTeX content string\n * @returns Parse result with CSL-JSON items\n */\nexport function parseBibtex(content: string): ParseResult {\n return parseWithCitationJs(content, \"bibtex\");\n}\n\n/**\n * Parse RIS content to CSL-JSON\n *\n * @param content - RIS content string\n * @returns Parse result with CSL-JSON items\n */\nexport function parseRis(content: string): ParseResult {\n return parseWithCitationJs(content, \"ris\");\n}\n\n/**\n * NBIB to RIS tag mapping\n *\n * Maps PubMed MEDLINE tags to RIS equivalents\n */\nconst NBIB_TO_RIS_TAG_MAP: Record<string, string> = {\n PMID: \"AN\", // PubMed ID -> Accession Number\n TI: \"TI\", // Title -> Title\n FAU: \"AU\", // Full Author -> Author\n AU: \"AU\", // Author -> Author (short form, use FAU when available)\n JT: \"JO\", // Journal Title -> Journal Name\n TA: \"JA\", // Title Abbreviation -> Journal Abbreviation\n AB: \"AB\", // Abstract -> Abstract\n VI: \"VL\", // Volume -> Volume\n IP: \"IS\", // Issue/Part -> Issue Number\n PG: \"SP\", // Pagination -> Start Page (includes range)\n DP: \"PY\", // Date of Publication -> Publication Year\n LA: \"LA\", // Language -> Language\n MH: \"KW\", // MeSH Headings -> Keywords\n OT: \"KW\", // Other Terms -> Keywords\n AD: \"AD\", // Affiliation/Address -> Author Address\n IS: \"SN\", // ISSN -> Serial Number\n PT: \"TY\", // Publication Type -> Type of Reference\n};\n\n/**\n * Publication type mapping from NBIB to RIS\n */\nconst NBIB_PUBLICATION_TYPE_MAP: Record<string, string> = {\n \"Journal Article\": \"JOUR\",\n Review: \"JOUR\",\n Book: \"BOOK\",\n \"Book Chapter\": \"CHAP\",\n \"Conference Paper\": \"CPAPER\",\n Thesis: \"THES\",\n Report: \"RPRT\",\n};\n\n/**\n * Parse a single NBIB entry into tag-value pairs\n */\nfunction parseNbibEntry(entry: string): Array<{ tag: string; value: string }> {\n const result: Array<{ tag: string; value: string }> = [];\n const lines = entry.split(\"\\n\");\n\n let currentTag = \"\";\n let currentValue = \"\";\n\n for (const line of lines) {\n // Check if line starts with a tag (2-4 uppercase letters followed by space(s) and dash)\n const tagMatch = line.match(/^([A-Z]{2,4})\\s*-\\s*(.*)$/);\n\n if (tagMatch) {\n // Save previous tag-value pair\n if (currentTag) {\n result.push({ tag: currentTag, value: currentValue.trim() });\n }\n currentTag = tagMatch[1] ?? \"\";\n currentValue = tagMatch[2] ?? \"\";\n } else if (currentTag && line.match(/^\\s+/)) {\n // Continuation line (starts with whitespace)\n currentValue += ` ${line.trim()}`;\n }\n }\n\n // Save the last tag-value pair\n if (currentTag) {\n result.push({ tag: currentTag, value: currentValue.trim() });\n }\n\n return result;\n}\n\n/**\n * Convert a single NBIB tag-value pair to RIS line\n * @returns RIS line or null if tag should be skipped\n */\nfunction convertNbibTagToRisLine(\n tag: string,\n value: string\n): { line: string; isType?: boolean } | null {\n // Handle DOI specially (AID tag with [doi] suffix)\n if (tag === \"AID\" && value.includes(\"[doi]\")) {\n const doi = value.replace(/\\s*\\[doi\\].*$/, \"\").trim();\n return { line: `DO - ${doi}` };\n }\n\n // Handle PII specially (AID tag with [pii] suffix)\n if (tag === \"AID\" && value.includes(\"[pii]\")) {\n const pii = value.replace(/\\s*\\[pii\\].*$/, \"\").trim();\n return { line: `C1 - ${pii}` }; // C1 = Custom Field 1\n }\n\n // Get mapped RIS tag\n const risTag = NBIB_TO_RIS_TAG_MAP[tag];\n if (!risTag) {\n return null; // Skip unmapped tags\n }\n\n // Handle publication year (extract year only)\n if (risTag === \"PY\") {\n const yearMatch = value.match(/^(\\d{4})/);\n return yearMatch ? { line: `PY - ${yearMatch[1]}` } : null;\n }\n\n // Handle publication type\n if (risTag === \"TY\") {\n const risType = NBIB_PUBLICATION_TYPE_MAP[value] || \"JOUR\";\n return { line: `TY - ${risType}`, isType: true };\n }\n\n return { line: `${risTag} - ${value}` };\n}\n\n/**\n * Convert a single NBIB entry to RIS format\n */\nfunction convertSingleNbibEntryToRis(entry: string): string {\n const parsed = parseNbibEntry(entry);\n\n if (parsed.length === 0) {\n return \"\";\n }\n\n const risLines: string[] = [];\n let hasType = false;\n\n for (const { tag, value } of parsed) {\n const converted = convertNbibTagToRisLine(tag, value);\n if (!converted) {\n continue;\n }\n\n if (converted.isType) {\n risLines.unshift(converted.line); // TY must be first\n hasType = true;\n } else {\n risLines.push(converted.line);\n }\n }\n\n // Add default type if not present\n if (!hasType) {\n risLines.unshift(\"TY - JOUR\");\n }\n\n // Add end record tag\n risLines.push(\"ER -\");\n\n return risLines.join(\"\\n\");\n}\n\n/**\n * Convert NBIB (PubMed MEDLINE) format to RIS format\n *\n * @param content - NBIB content string\n * @returns RIS format string\n */\nexport function convertNbibToRis(content: string): string {\n const trimmed = content.trim();\n\n if (!trimmed) {\n return \"\";\n }\n\n // Split into entries by blank lines (PMID- starts each entry)\n const entries = trimmed.split(/\\n\\s*\\n/).filter((e) => e.trim());\n\n const risEntries = entries.map((entry) => convertSingleNbibEntryToRis(entry)).filter(Boolean);\n\n return risEntries.join(\"\\n\\n\");\n}\n\n/**\n * Parse NBIB (PubMed MEDLINE) content to CSL-JSON\n *\n * Converts NBIB to RIS format first, then parses with citation-js\n *\n * @param content - NBIB content string\n * @returns Parse result with CSL-JSON items\n */\nexport function parseNbib(content: string): ParseResult {\n const trimmed = content.trim();\n\n // Handle empty input\n if (!trimmed) {\n return { success: true, items: [] };\n }\n\n // Convert NBIB to RIS\n const risContent = convertNbibToRis(trimmed);\n\n if (!risContent) {\n return {\n success: false,\n items: [],\n error: \"Failed to convert NBIB to RIS: No valid entries found\",\n };\n }\n\n // Parse the RIS content\n return parseRis(risContent);\n}\n\n/**\n * Parse content using citation-js\n */\nfunction parseWithCitationJs(content: string, format: string): ParseResult {\n const trimmed = content.trim();\n\n // Handle empty input\n if (!trimmed) {\n return { success: true, items: [] };\n }\n\n try {\n // Parse with citation-js (auto-detection works well for bibtex/ris)\n const cite = new Cite(trimmed);\n\n // Get CSL-JSON output\n const items = cite.get({ format: \"real\", type: \"json\" }) as CslItem[];\n\n // Handle case where parsing produces no results\n if (!items || items.length === 0) {\n // Check if input looks like valid format but has no entries\n if (isEmptyFormat(trimmed, format)) {\n return { success: true, items: [] };\n }\n\n return {\n success: false,\n items: [],\n error: `No valid ${format.toUpperCase()} entries found`,\n };\n }\n\n return { success: true, items };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n\n // Check if this is truly empty content (comments only for bibtex)\n if (isEmptyFormat(trimmed, format)) {\n return { success: true, items: [] };\n }\n\n return {\n success: false,\n items: [],\n error: `Failed to parse ${format.toUpperCase()}: ${errorMessage}`,\n };\n }\n}\n\n/**\n * Check if content is \"empty\" for the given format\n * (e.g., only comments for BibTeX)\n */\nfunction isEmptyFormat(content: string, format: string): boolean {\n if (format === \"bibtex\") {\n // BibTeX comments start with %\n const lines = content.split(\"\\n\");\n return lines.every((line) => {\n const trimmed = line.trim();\n return trimmed === \"\" || trimmed.startsWith(\"%\");\n });\n }\n\n return false;\n}\n","/**\n * Importer orchestration module\n *\n * Coordinates format detection, parsing, and fetching to import references\n * from various input formats.\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport type { CslItem } from \"../../core/csl-json/types.js\";\nimport { CslItemSchema } from \"../../core/csl-json/types.js\";\nimport {\n cacheDoiResult,\n cacheIsbnResult,\n cachePmidResult,\n getDoiFromCache,\n getIsbnFromCache,\n getPmidFromCache,\n} from \"./cache.js\";\nimport { detectByContent, detectByExtension, isDoi, isIsbn, isPmid } from \"./detector.js\";\nimport type { InputFormat } from \"./detector.js\";\nimport { fetchDoi, fetchIsbn, fetchPmids } from \"./fetcher.js\";\nimport type { FailureReason, PubmedConfig } from \"./fetcher.js\";\nimport { normalizeDoi, normalizeIsbn, normalizePmid } from \"./normalizer.js\";\nimport { parseBibtex, parseNbib, parseRis } from \"./parser.js\";\n\n// Re-export FailureReason for external use\nexport type { FailureReason } from \"./fetcher.js\";\n\n/**\n * Result of importing a single item\n */\nexport type ImportItemResult =\n | { success: true; item: CslItem; source: string }\n | { success: false; error: string; source: string; reason: FailureReason };\n\n/**\n * Result of an import operation\n */\nexport interface ImportResult {\n results: ImportItemResult[];\n}\n\n/**\n * Options for import operations\n */\nexport interface ImportOptions {\n pubmedConfig?: PubmedConfig;\n}\n\n/**\n * Classified identifiers\n */\ninterface ClassifiedIdentifiers {\n pmids: string[];\n dois: string[];\n isbns: string[];\n unknowns: string[];\n}\n\n/**\n * Classify identifiers into PMIDs, DOIs, and unknowns\n */\nfunction classifyIdentifiers(identifiers: string[]): ClassifiedIdentifiers {\n const pmids: string[] = [];\n const dois: string[] = [];\n const isbns: string[] = [];\n const unknowns: string[] = [];\n\n for (const id of identifiers) {\n if (isPmid(id)) {\n pmids.push(normalizePmid(id));\n } else if (isDoi(id)) {\n dois.push(normalizeDoi(id));\n } else if (isIsbn(id)) {\n isbns.push(normalizeIsbn(id));\n } else {\n unknowns.push(id);\n }\n }\n\n return { pmids, dois, isbns, unknowns };\n}\n\n/**\n * Build error results for unknown identifiers\n */\nfunction buildUnknownResults(unknowns: string[]): ImportItemResult[] {\n return unknowns.map((unknown) => ({\n success: false as const,\n error: `Cannot interpret '${unknown}' as identifier (not a valid PMID or DOI)`,\n source: unknown,\n reason: \"validation_error\" as const,\n }));\n}\n\n/**\n * Clear the id from a fetched item to force regeneration using author-year format\n * Identifiers (PMID, DOI, ISBN) from APIs may have non-standard IDs that should not be used\n */\nfunction clearItemId(item: CslItem): CslItem {\n const { id: _ignored, ...rest } = item;\n return { ...rest, id: \"\" };\n}\n\n/**\n * Fetch PMIDs with cache support\n */\nasync function fetchPmidsWithCache(\n pmids: string[],\n pubmedConfig: PubmedConfig\n): Promise<ImportItemResult[]> {\n const results: ImportItemResult[] = [];\n const pmidsToFetch: string[] = [];\n\n // Check cache first\n for (const pmid of pmids) {\n const cached = getPmidFromCache(pmid);\n if (cached) {\n results.push({ success: true, item: clearItemId(cached), source: pmid });\n } else {\n pmidsToFetch.push(pmid);\n }\n }\n\n // Fetch uncached PMIDs\n if (pmidsToFetch.length > 0) {\n const fetchResults = await fetchPmids(pmidsToFetch, pubmedConfig);\n for (const fetchResult of fetchResults) {\n if (fetchResult.success) {\n cachePmidResult(fetchResult.pmid, fetchResult.item);\n results.push({\n success: true,\n item: clearItemId(fetchResult.item),\n source: fetchResult.pmid,\n });\n } else {\n results.push({\n success: false,\n error: fetchResult.error,\n source: fetchResult.pmid,\n reason: fetchResult.reason,\n });\n }\n }\n }\n\n return results;\n}\n\n/**\n * Fetch DOIs with cache support\n */\nasync function fetchDoisWithCache(dois: string[]): Promise<ImportItemResult[]> {\n const results: ImportItemResult[] = [];\n\n for (const doi of dois) {\n const cached = getDoiFromCache(doi);\n if (cached) {\n results.push({ success: true, item: clearItemId(cached), source: doi });\n continue;\n }\n\n const fetchResult = await fetchDoi(doi);\n if (fetchResult.success) {\n cacheDoiResult(doi, fetchResult.item);\n results.push({ success: true, item: clearItemId(fetchResult.item), source: doi });\n } else {\n results.push({\n success: false,\n error: fetchResult.error,\n source: doi,\n reason: fetchResult.reason,\n });\n }\n }\n\n return results;\n}\n\n/**\n * Fetch ISBNs with caching\n */\nasync function fetchIsbnsWithCache(isbns: string[]): Promise<ImportItemResult[]> {\n const results: ImportItemResult[] = [];\n\n for (const isbn of isbns) {\n const cached = getIsbnFromCache(isbn);\n if (cached) {\n results.push({ success: true, item: clearItemId(cached), source: isbn });\n continue;\n }\n\n const fetchResult = await fetchIsbn(isbn);\n if (fetchResult.success) {\n cacheIsbnResult(isbn, fetchResult.item);\n results.push({ success: true, item: clearItemId(fetchResult.item), source: isbn });\n } else {\n results.push({\n success: false,\n error: fetchResult.error,\n source: isbn,\n reason: fetchResult.reason,\n });\n }\n }\n\n return results;\n}\n\n/**\n * Parse JSON content and return import result\n */\nfunction parseJsonContent(content: string): ImportResult {\n try {\n const parsed = JSON.parse(content);\n const items: unknown[] = Array.isArray(parsed) ? parsed : [parsed];\n\n if (items.length === 0) {\n return { results: [] };\n }\n\n const results: ImportItemResult[] = [];\n for (const item of items) {\n const parseResult = CslItemSchema.safeParse(item);\n if (parseResult.success) {\n results.push({ success: true, item: parseResult.data, source: \"json\" });\n } else {\n results.push({\n success: false,\n error: `Invalid CSL-JSON: ${parseResult.error.message}`,\n source: \"json\",\n reason: \"validation_error\",\n });\n }\n }\n return { results };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n results: [\n {\n success: false,\n error: `Failed to parse JSON: ${message}`,\n source: \"json\",\n reason: \"parse_error\",\n },\n ],\n };\n }\n}\n\n/**\n * Parse BibTeX content and return import result\n */\nfunction parseBibtexContent(content: string): ImportResult {\n const parseResult = parseBibtex(content);\n\n if (!parseResult.success) {\n return {\n results: [\n {\n success: false,\n error: parseResult.error ?? \"Failed to parse BibTeX\",\n source: \"bibtex\",\n reason: \"parse_error\",\n },\n ],\n };\n }\n\n if (parseResult.items.length === 0) {\n return { results: [] };\n }\n\n return {\n results: parseResult.items.map((item) => ({\n success: true as const,\n item,\n source: \"bibtex\",\n })),\n };\n}\n\n/**\n * Parse RIS content and return import result\n */\nfunction parseRisContent(content: string): ImportResult {\n const parseResult = parseRis(content);\n\n if (!parseResult.success) {\n return {\n results: [\n {\n success: false,\n error: parseResult.error ?? \"Failed to parse RIS\",\n source: \"ris\",\n reason: \"parse_error\",\n },\n ],\n };\n }\n\n if (parseResult.items.length === 0) {\n return { results: [] };\n }\n\n return {\n results: parseResult.items.map((item) => ({\n success: true as const,\n item,\n source: \"ris\",\n })),\n };\n}\n\n/**\n * Parse NBIB content and return import result\n */\nfunction parseNbibContent(content: string): ImportResult {\n const parseResult = parseNbib(content);\n\n if (!parseResult.success) {\n return {\n results: [\n {\n success: false,\n error: parseResult.error ?? \"Failed to parse NBIB\",\n source: \"nbib\",\n reason: \"parse_error\",\n },\n ],\n };\n }\n\n if (parseResult.items.length === 0) {\n return { results: [] };\n }\n\n return {\n results: parseResult.items.map((item) => ({\n success: true as const,\n item,\n source: \"nbib\",\n })),\n };\n}\n\n/**\n * Import references from content string\n *\n * @param content - The content to parse\n * @param format - The format of the content (or \"auto\" for detection)\n * @param options - Import options\n * @returns Import result with parsed items\n */\nexport async function importFromContent(\n content: string,\n format: InputFormat | \"auto\",\n _options: ImportOptions\n): Promise<ImportResult> {\n // Determine the actual format\n let actualFormat: InputFormat;\n if (format === \"auto\") {\n actualFormat = detectByContent(content);\n if (actualFormat === \"unknown\") {\n return {\n results: [\n {\n success: false,\n error: \"Cannot detect input format. Use --format to specify explicitly.\",\n source: \"content\",\n reason: \"validation_error\",\n },\n ],\n };\n }\n } else {\n actualFormat = format;\n }\n\n // Parse based on format\n switch (actualFormat) {\n case \"json\":\n return parseJsonContent(content);\n case \"bibtex\":\n return parseBibtexContent(content);\n case \"ris\":\n return parseRisContent(content);\n case \"nbib\":\n return parseNbibContent(content);\n default:\n return {\n results: [\n {\n success: false,\n error: `Unsupported format for content parsing: ${actualFormat}`,\n source: \"content\",\n reason: \"validation_error\",\n },\n ],\n };\n }\n}\n\n/**\n * Import references from identifier strings (PMID or DOI)\n *\n * @param identifiers - Array of identifier strings\n * @param options - Import options (requires pubmedConfig for PMID fetching)\n * @returns Import result with fetched items\n */\nexport async function importFromIdentifiers(\n identifiers: string[],\n options: ImportOptions\n): Promise<ImportResult> {\n if (identifiers.length === 0) {\n return { results: [] };\n }\n\n // Classify identifiers\n const { pmids, dois, isbns, unknowns } = classifyIdentifiers(identifiers);\n\n // Collect results\n const results: ImportItemResult[] = [];\n\n // Add errors for unknown identifiers\n results.push(...buildUnknownResults(unknowns));\n\n // Fetch PMIDs with cache\n const pmidResults = await fetchPmidsWithCache(pmids, options.pubmedConfig ?? {});\n results.push(...pmidResults);\n\n // Fetch DOIs with cache\n const doiResults = await fetchDoisWithCache(dois);\n results.push(...doiResults);\n\n // Fetch ISBNs with cache\n const isbnResults = await fetchIsbnsWithCache(isbns);\n results.push(...isbnResults);\n\n return { results };\n}\n\n/**\n * Options for importFromInputs\n */\nexport interface ImportInputsOptions extends ImportOptions {\n /** Explicit format specification (default: auto) */\n format?: InputFormat | \"auto\";\n /** Content from stdin (if provided, processed before file/identifier inputs) */\n stdinContent?: string;\n}\n\n/**\n * Unified entry point for importing references from file paths or identifiers\n *\n * Classifies inputs as files or identifiers:\n * - If path exists as file → read and parse\n * - If path does not exist → interpret as identifier (PMID/DOI)\n *\n * @param inputs - Array of file paths or identifier strings\n * @param options - Import options including format specification\n * @returns Import result with all parsed/fetched items\n */\n\n/**\n * Check if input looks like a file path (has file-like extension)\n */\nfunction looksLikeFilePath(input: string): boolean {\n const fileExtensions = [\".json\", \".bib\", \".ris\", \".txt\", \".xml\", \".yaml\", \".yml\"];\n const lowerInput = input.toLowerCase();\n return fileExtensions.some((ext) => lowerInput.endsWith(ext));\n}\n\n/**\n * Process a single file input\n */\nasync function processFile(\n filePath: string,\n options: ImportInputsOptions\n): Promise<ImportItemResult[]> {\n try {\n const content = readFileSync(filePath, \"utf-8\");\n\n // Determine format\n let format: InputFormat | \"auto\";\n if (options.format && options.format !== \"auto\") {\n format = options.format;\n } else {\n // Try extension first\n const extFormat = detectByExtension(filePath);\n format = extFormat !== \"unknown\" ? extFormat : \"auto\";\n }\n\n const result = await importFromContent(content, format, options);\n\n // Update source to be the file path\n return result.results.map((r) => ({\n ...r,\n source: filePath,\n }));\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return [\n {\n success: false,\n error: `Failed to read file: ${message}`,\n source: filePath,\n reason: \"fetch_error\",\n },\n ];\n }\n}\n\n/**\n * Process identifier inputs (PMID/DOI)\n */\nasync function processIdentifiers(\n inputs: string[],\n options: ImportInputsOptions\n): Promise<ImportItemResult[]> {\n const results: ImportItemResult[] = [];\n const validIdentifiers: string[] = [];\n\n // Separate valid identifiers from invalid inputs\n for (const input of inputs) {\n // Check if it's a valid identifier\n const isValidPmid = isPmid(input);\n const isValidDoi = isDoi(input);\n const isValidIsbn = isIsbn(input);\n\n if (isValidPmid || isValidDoi || isValidIsbn) {\n validIdentifiers.push(input);\n } else {\n // Not a valid identifier\n const hint = looksLikeFilePath(input)\n ? \" Hint: If this is a file path, check that the file exists.\"\n : \"\";\n results.push({\n success: false,\n error: `Cannot interpret '${input}' as identifier (not a valid PMID, DOI, or ISBN).${hint}`,\n source: input,\n reason: \"validation_error\",\n });\n }\n }\n\n // Fetch valid identifiers\n if (validIdentifiers.length > 0) {\n const fetchResult = await importFromIdentifiers(validIdentifiers, options);\n results.push(...fetchResult.results);\n }\n\n return results;\n}\n\nexport async function importFromInputs(\n inputs: string[],\n options: ImportInputsOptions\n): Promise<ImportResult> {\n const allResults: ImportItemResult[] = [];\n\n // Process stdinContent if provided\n if (options.stdinContent?.trim()) {\n const stdinResults = await processStdinContent(options.stdinContent, options);\n allResults.push(...stdinResults);\n }\n\n // Process file/identifier inputs\n if (inputs.length > 0) {\n const identifiersToFetch: string[] = [];\n\n // Process each input\n for (const input of inputs) {\n if (existsSync(input)) {\n // Input is an existing file\n const fileResults = await processFile(input, options);\n allResults.push(...fileResults);\n } else {\n // Input does not exist as file - treat as potential identifier\n identifiersToFetch.push(input);\n }\n }\n\n // Process identifiers\n if (identifiersToFetch.length > 0) {\n const identifierResults = await processIdentifiers(identifiersToFetch, options);\n allResults.push(...identifierResults);\n }\n }\n\n return { results: allResults };\n}\n\n/**\n * Process stdin content based on format detection\n * - For file formats (json/bibtex/ris): parse directly\n * - For identifier formats (pmid/doi) or auto with identifiers: split and process\n */\nasync function processStdinContent(\n content: string,\n options: ImportInputsOptions\n): Promise<ImportItemResult[]> {\n const format = options.format || \"auto\";\n\n // If explicit file format specified, parse as content\n if (format === \"json\" || format === \"bibtex\" || format === \"ris\" || format === \"nbib\") {\n const result = await importFromContent(content, format, options);\n return result.results.map((r) => ({\n ...r,\n source: r.source === \"content\" ? \"stdin\" : r.source,\n }));\n }\n\n // If explicit identifier format, split and process\n if (format === \"pmid\" || format === \"doi\" || format === \"isbn\") {\n const identifiers = content.split(/\\s+/).filter((s) => s.length > 0);\n return processIdentifiers(identifiers, options);\n }\n\n // Auto-detect format from content\n const detectedFormat = detectByContent(content);\n\n if (\n detectedFormat === \"json\" ||\n detectedFormat === \"bibtex\" ||\n detectedFormat === \"ris\" ||\n detectedFormat === \"nbib\"\n ) {\n // File format detected - parse as content\n const result = await importFromContent(content, detectedFormat, options);\n return result.results.map((r) => ({\n ...r,\n source: r.source === \"content\" ? \"stdin\" : r.source,\n }));\n }\n\n // Not a file format - treat as whitespace-separated identifiers\n const identifiers = content.split(/\\s+/).filter((s) => s.length > 0);\n if (identifiers.length === 0) {\n return [];\n }\n\n return processIdentifiers(identifiers, options);\n}\n","import type { CslItem } from \"../../core/csl-json/types.js\";\nimport { generateId } from \"../../core/identifier/generator.js\";\nimport type { ILibrary } from \"../../core/library-interface.js\";\nimport { detectDuplicate } from \"../duplicate/detector.js\";\nimport type { InputFormat } from \"../import/detector.js\";\nimport type { PubmedConfig } from \"../import/fetcher.js\";\nimport {\n type ImportInputsOptions,\n type ImportItemResult,\n importFromInputs,\n} from \"../import/importer.js\";\n\n// Re-export FailureReason for external use\nexport type { FailureReason } from \"../import/importer.js\";\n\n/**\n * Options for adding references\n */\nexport interface AddReferencesOptions {\n /** Skip duplicate detection */\n force?: boolean;\n /** Explicit input format (default: auto) */\n format?: InputFormat | \"auto\";\n /** PubMed API configuration */\n pubmedConfig?: PubmedConfig;\n /** Content from stdin (if provided, processed before file/identifier inputs) */\n stdinContent?: string;\n}\n\n/**\n * Information about a successfully added reference\n */\nexport interface AddedItem {\n source: string;\n id: string;\n uuid: string;\n title: string;\n /** True if the original ID from source file was changed due to collision */\n idChanged?: boolean;\n /** Original ID from source file before collision resolution */\n originalId?: string;\n}\n\n/**\n * Information about a failed import\n */\nexport interface FailedItem {\n source: string;\n error: string;\n reason: import(\"../import/importer.js\").FailureReason;\n}\n\n/**\n * Information about a skipped duplicate\n */\nexport interface SkippedItem {\n source: string;\n existingId: string;\n duplicateType: import(\"../duplicate/types.js\").DuplicateType;\n}\n\n/**\n * Result of addReferences operation\n */\nexport interface AddReferencesResult {\n added: AddedItem[];\n failed: FailedItem[];\n skipped: SkippedItem[];\n}\n\n/**\n * Add references to a library from various input sources.\n *\n * This function orchestrates:\n * 1. Import from inputs (files or identifiers)\n * 2. Duplicate detection (unless force=true)\n * 3. ID collision resolution\n * 4. Library save\n *\n * @param inputs - File paths or identifiers (PMID, DOI)\n * @param library - Target library\n * @param options - Add options\n * @returns Result with added, failed, and skipped items\n */\nexport async function addReferences(\n inputs: string[],\n library: ILibrary,\n options: AddReferencesOptions\n): Promise<AddReferencesResult> {\n const added: AddedItem[] = [];\n const failed: FailedItem[] = [];\n const skipped: SkippedItem[] = [];\n\n // 1. Import from inputs\n const importOptions = buildImportOptions(options);\n const importResult = await importFromInputs(inputs, importOptions);\n\n // Get existing items for duplicate/collision checks (getAll now returns CslItem[] directly)\n const existingItems = await library.getAll();\n\n // Track IDs we've added in this batch (for collision detection within batch)\n const addedIds = new Set<string>();\n\n // 2. Process each import result\n for (const result of importResult.results) {\n const processed = await processImportResult(\n result,\n existingItems,\n addedIds,\n options.force ?? false,\n library\n );\n\n if (processed.type === \"failed\") {\n failed.push(processed.item);\n } else if (processed.type === \"skipped\") {\n skipped.push(processed.item);\n } else {\n added.push(processed.item);\n }\n }\n\n // 3. Save library if any items were added\n if (added.length > 0) {\n await library.save();\n }\n\n return { added, failed, skipped };\n}\n\n/**\n * Build import options from add options\n */\nfunction buildImportOptions(options: AddReferencesOptions): ImportInputsOptions {\n const importOptions: ImportInputsOptions = {};\n if (options.format !== undefined) {\n importOptions.format = options.format;\n }\n if (options.pubmedConfig !== undefined) {\n importOptions.pubmedConfig = options.pubmedConfig;\n }\n if (options.stdinContent !== undefined) {\n importOptions.stdinContent = options.stdinContent;\n }\n return importOptions;\n}\n\ntype ProcessResult =\n | { type: \"added\"; item: AddedItem }\n | { type: \"failed\"; item: FailedItem }\n | { type: \"skipped\"; item: SkippedItem };\n\n/**\n * Process a single import result\n */\nasync function processImportResult(\n result: ImportItemResult,\n existingItems: CslItem[],\n addedIds: Set<string>,\n force: boolean,\n library: ILibrary\n): Promise<ProcessResult> {\n if (!result.success) {\n return {\n type: \"failed\",\n item: { source: result.source, error: result.error, reason: result.reason },\n };\n }\n\n const item = result.item;\n\n // Check for duplicates (unless force=true)\n if (!force) {\n const duplicateResult = detectDuplicate(item, existingItems);\n const existingMatch = duplicateResult.matches[0];\n if (existingMatch) {\n return {\n type: \"skipped\",\n item: {\n source: result.source,\n existingId: existingMatch.existing.id ?? \"\",\n duplicateType: existingMatch.type,\n },\n };\n }\n }\n\n // Resolve ID collision\n // Prioritize original ID from source file; generate ID only if not present\n const allExistingIds = new Set([...existingItems.map((i) => i.id), ...addedIds]);\n const originalId = item.id?.trim() || \"\";\n const hasOriginalId = originalId.length > 0;\n const baseId = hasOriginalId ? originalId : generateId(item);\n const { id, changed } = resolveIdCollision(baseId, allExistingIds);\n\n const finalItem: CslItem = { ...item, id };\n\n // Add to library\n const addedToLibrary = await library.add(finalItem);\n addedIds.add(id);\n\n // Build result (uuid comes from the library-added item which has ensured UUID)\n const uuid = addedToLibrary.custom?.uuid ?? \"\";\n const addedItem: AddedItem = {\n source: result.source,\n id,\n uuid,\n title: typeof finalItem.title === \"string\" ? finalItem.title : \"\",\n };\n\n // Report idChanged only when original ID from source was changed due to collision\n // Generated ID collisions are internal and not reported\n if (hasOriginalId && changed) {\n addedItem.idChanged = true;\n addedItem.originalId = originalId;\n }\n\n return { type: \"added\", item: addedItem };\n}\n\n/**\n * Generate an alphabetic suffix for ID collision resolution.\n * 0 -> 'a', 1 -> 'b', ..., 25 -> 'z', 26 -> 'aa', etc.\n */\nfunction generateSuffix(index: number): string {\n const alphabet = \"abcdefghijklmnopqrstuvwxyz\";\n let suffix = \"\";\n let n = index;\n\n do {\n suffix = alphabet[n % 26] + suffix;\n n = Math.floor(n / 26) - 1;\n } while (n >= 0);\n\n return suffix;\n}\n\n/**\n * Resolve ID collision by appending alphabetic suffix.\n */\nfunction resolveIdCollision(\n baseId: string,\n existingIds: Set<string>\n): { id: string; changed: boolean } {\n if (!existingIds.has(baseId)) {\n return { id: baseId, changed: false };\n }\n\n // Find next available suffix\n let index = 0;\n let newId: string;\n\n do {\n const suffix = generateSuffix(index);\n newId = `${baseId}${suffix}`;\n index++;\n } while (existingIds.has(newId));\n\n return { id: newId, changed: true };\n}\n","import { Hono } from \"hono\";\nimport type { Config } from \"../../config/schema.js\";\nimport type { Library } from \"../../core/library.js\";\nimport type { InputFormat } from \"../../features/import/detector.js\";\nimport type { PubmedConfig } from \"../../features/import/fetcher.js\";\nimport { type AddReferencesOptions, addReferences } from \"../../features/operations/add.js\";\n\n/**\n * Build PubmedConfig from config, filtering out undefined values\n * to satisfy exactOptionalPropertyTypes requirements.\n */\nfunction buildPubmedConfig(config: Config): PubmedConfig {\n const pubmedConfig: PubmedConfig = {};\n if (config.pubmed.email !== undefined) {\n pubmedConfig.email = config.pubmed.email;\n }\n if (config.pubmed.apiKey !== undefined) {\n pubmedConfig.apiKey = config.pubmed.apiKey;\n }\n return pubmedConfig;\n}\n\n/**\n * Create add route for importing references.\n * @param library - Library instance to use for operations\n * @param config - Configuration with PubMed settings\n * @returns Hono app with add route\n */\nexport function createAddRoute(library: Library, config: Config) {\n const route = new Hono();\n\n // POST / - Add references from inputs\n route.post(\"/\", async (c) => {\n // Parse request body\n let body: unknown;\n try {\n body = await c.req.json();\n } catch {\n return c.json({ error: \"Invalid JSON\" }, 400);\n }\n\n // Validate inputs\n if (!body || typeof body !== \"object\") {\n return c.json({ error: \"Request body must be an object\" }, 400);\n }\n\n const { inputs, options } = body as {\n inputs?: unknown;\n options?: { force?: boolean; format?: string };\n };\n\n if (!inputs || !Array.isArray(inputs) || inputs.length === 0) {\n return c.json({ error: \"inputs must be a non-empty array of strings\" }, 400);\n }\n\n // Ensure all inputs are strings\n if (!inputs.every((input) => typeof input === \"string\")) {\n return c.json({ error: \"All inputs must be strings\" }, 400);\n }\n\n // Build options\n const addOptions: AddReferencesOptions = {\n force: options?.force ?? false,\n pubmedConfig: buildPubmedConfig(config),\n };\n\n if (options?.format) {\n addOptions.format = options.format as InputFormat | \"auto\";\n }\n\n // Call addReferences\n const result = await addReferences(inputs as string[], library, addOptions);\n\n return c.json(result);\n });\n\n return route;\n}\n","import { isBuiltinStyle, resolveStyle } from \"../../config/csl-styles.js\";\nimport type { CslItem } from \"../../core/csl-json/types.js\";\nimport type { ILibrary, IdentifierType } from \"../../core/library-interface.js\";\nimport {\n formatBibliography,\n formatBibliographyCSL,\n formatInText,\n formatInTextCSL,\n} from \"../format/index.js\";\n\n/**\n * Options for citeReferences operation\n */\nexport interface CiteOperationOptions {\n /** Reference IDs or UUIDs to cite */\n identifiers: string[];\n /** Identifier type: 'id' (default), 'uuid', 'doi', 'pmid', or 'isbn' */\n idType?: IdentifierType;\n /** CSL style name or path to CSL file */\n style?: string;\n /** Path to custom CSL file */\n cslFile?: string;\n /** Default style from config (used when style is not specified) */\n defaultStyle?: string;\n /** Directory or directories to search for custom CSL files */\n cslDirectory?: string | string[];\n /** Locale for citation formatting (default: \"en-US\") */\n locale?: string;\n /** Output format (default: \"text\") */\n format?: \"text\" | \"html\" | \"rtf\";\n /** If true, generate in-text citation instead of bibliography */\n inText?: boolean;\n}\n\n/**\n * Result for a single citation\n */\nexport type CiteItemResult =\n | { success: true; identifier: string; citation: string }\n | { success: false; identifier: string; error: string };\n\n/**\n * Result of citeReferences operation\n */\nexport interface CiteResult {\n /** Results for each identifier */\n results: CiteItemResult[];\n}\n\ninterface FormatOptions {\n style?: string | undefined;\n styleXml?: string | undefined;\n locale?: string | undefined;\n format?: \"text\" | \"html\" | \"rtf\" | undefined;\n}\n\n/**\n * Check if fallback formatter should be used.\n */\nfunction shouldUseFallback(style: string | undefined, hasCustomXml: boolean): boolean {\n if (hasCustomXml) {\n return false;\n }\n if (style && !isBuiltinStyle(style)) {\n return true;\n }\n return false;\n}\n\n/**\n * Format a single item as citation.\n */\nfunction formatCitation(item: CslItem, inText: boolean, options: FormatOptions): string {\n const useFallback = shouldUseFallback(options.style, !!options.styleXml);\n const style = options.style ?? \"apa\";\n const locale = options.locale ?? \"en-US\";\n const format = options.format ?? \"text\";\n const styleXml = options.styleXml;\n\n if (useFallback) {\n return inText ? formatInText([item]) : formatBibliography([item]);\n }\n\n const formatOptions = { style, locale, format, ...(styleXml && { styleXml }) };\n return inText\n ? formatInTextCSL([item], formatOptions)\n : formatBibliographyCSL([item], formatOptions);\n}\n\n/**\n * Generate citation for a single identifier.\n */\nasync function generateCitationForIdentifier(\n library: ILibrary,\n identifier: string,\n idType: IdentifierType,\n inText: boolean,\n options: FormatOptions\n): Promise<CiteItemResult> {\n const item = await library.find(identifier, { idType });\n\n if (!item) {\n const lookupType = idType === \"uuid\" ? \"UUID\" : idType.toUpperCase();\n return {\n success: false,\n identifier,\n error: `Reference with ${lookupType} '${identifier}' not found`,\n };\n }\n\n const citation = formatCitation(item, inText, options);\n\n return {\n success: true,\n identifier,\n citation,\n };\n}\n\n/**\n * Generate citations for references.\n *\n * @param library - The library to cite from\n * @param options - Citation options including identifiers and style settings\n * @returns Results array with citation or error for each identifier\n */\nexport async function citeReferences(\n library: ILibrary,\n options: CiteOperationOptions\n): Promise<CiteResult> {\n const {\n identifiers,\n idType = \"id\",\n inText = false,\n style,\n cslFile,\n defaultStyle,\n cslDirectory,\n locale,\n format,\n } = options;\n const results: CiteItemResult[] = [];\n\n // Resolve style using the full resolution chain:\n // 1. cslFile (exact path)\n // 2. style (if built-in)\n // 3. Search in cslDirectory\n // 4. defaultStyle (if built-in or found in cslDirectory)\n // 5. Fallback to 'apa'\n const resolution = resolveStyle({\n ...(cslFile !== undefined && { cslFile }),\n ...(style !== undefined && { style }),\n ...(defaultStyle !== undefined && { defaultStyle }),\n ...(cslDirectory !== undefined && { cslDirectory }),\n });\n\n for (const identifier of identifiers) {\n const result = await generateCitationForIdentifier(library, identifier, idType, inText, {\n style: resolution.styleName,\n styleXml: resolution.styleXml,\n locale,\n format,\n });\n results.push(result);\n }\n\n return { results };\n}\n","import { Hono } from \"hono\";\nimport { z } from \"zod\";\nimport type { Library } from \"../../core/library.js\";\nimport {\n type CiteOperationOptions,\n type CiteResult,\n citeReferences,\n} from \"../../features/operations/cite.js\";\n\n/**\n * Zod schema for cite request body\n */\nconst CiteRequestSchema = z.object({\n identifiers: z.array(z.string()).min(1, \"identifiers must be a non-empty array\"),\n idType: z.enum([\"id\", \"uuid\", \"doi\", \"pmid\", \"isbn\"]).optional(),\n inText: z.boolean().optional(),\n style: z.string().optional(),\n cslFile: z.string().optional(),\n locale: z.string().optional(),\n format: z.enum([\"text\", \"html\"]).optional(),\n});\n\ntype CiteRequestBody = z.infer<typeof CiteRequestSchema>;\n\n/**\n * Build cite operation options from validated request body.\n */\nfunction buildCiteOptions(body: CiteRequestBody): CiteOperationOptions {\n return {\n identifiers: body.identifiers,\n ...(body.idType !== undefined && { idType: body.idType }),\n ...(body.inText !== undefined && { inText: body.inText }),\n ...(body.style !== undefined && { style: body.style }),\n ...(body.cslFile !== undefined && { cslFile: body.cslFile }),\n ...(body.locale !== undefined && { locale: body.locale }),\n ...(body.format !== undefined && { format: body.format }),\n };\n}\n\n/**\n * Create cite route for generating citations.\n * @param library - Library instance to use for operations\n * @returns Hono app with cite route\n */\nexport function createCiteRoute(library: Library) {\n const route = new Hono();\n\n // POST / - Generate citations for identifiers\n route.post(\"/\", async (c) => {\n // Parse request body\n let rawBody: unknown;\n try {\n rawBody = await c.req.json();\n } catch {\n return c.json({ error: \"Invalid JSON\" }, 400);\n }\n\n // Validate with zod schema\n const parseResult = CiteRequestSchema.safeParse(rawBody);\n if (!parseResult.success) {\n const errorMessage = parseResult.error.issues[0]?.message ?? \"Invalid request body\";\n return c.json({ error: errorMessage }, 400);\n }\n\n // Call citeReferences operation\n const result: CiteResult = await citeReferences(library, buildCiteOptions(parseResult.data));\n\n return c.json(result);\n });\n\n return route;\n}\n","import { Hono } from \"hono\";\n\n/**\n * Health check route.\n * Returns a simple status to verify the server is running.\n */\nexport const healthRoute = new Hono();\n\nhealthRoute.get(\"/\", (c) => {\n return c.json({ status: \"ok\" });\n});\n","import type { CslItem } from \"../../core/csl-json/types.js\";\nimport type { ILibrary } from \"../../core/library-interface.js\";\nimport {\n type PaginationOptions,\n type SortField,\n type SortOptions,\n type SortOrder,\n paginate,\n sortReferences,\n} from \"../pagination/index.js\";\n\n/**\n * Options for listReferences operation\n */\nexport interface ListOptions extends PaginationOptions, SortOptions {}\n\n/**\n * Result of listReferences operation\n */\nexport interface ListResult {\n /** Raw CslItem array */\n items: CslItem[];\n /** Total count before pagination */\n total: number;\n /** Applied limit (0 if unlimited) */\n limit: number;\n /** Applied offset */\n offset: number;\n /** Next page offset, null if no more results */\n nextOffset: number | null;\n}\n\n/**\n * List all references from the library.\n *\n * @param library - The library to list references from\n * @param options - Pagination and sorting options\n * @returns Raw CslItem[] with pagination metadata\n */\nexport async function listReferences(library: ILibrary, options: ListOptions): Promise<ListResult> {\n const sort: SortField = options.sort ?? \"updated\";\n const order: SortOrder = options.order ?? \"desc\";\n const limit = options.limit ?? 0;\n const offset = options.offset ?? 0;\n\n // Get all items\n const allItems = await library.getAll();\n const total = allItems.length;\n\n // Sort\n const sorted = sortReferences(allItems, sort, order);\n\n // Paginate\n const { items: paginatedItems, nextOffset } = paginate(sorted, { limit, offset });\n\n return {\n items: paginatedItems,\n total,\n limit,\n offset,\n nextOffset,\n };\n}\n","import { Hono } from \"hono\";\nimport { z } from \"zod\";\nimport type { Library } from \"../../core/library.js\";\nimport { type ListOptions, listReferences } from \"../../features/operations/list.js\";\nimport { sortFieldSchema, sortOrderSchema } from \"../../features/pagination/index.js\";\nimport { pickDefined } from \"../../utils/object.js\";\n\n/**\n * Request body schema for list endpoint\n */\nconst listRequestBodySchema = z.object({\n sort: sortFieldSchema.optional(),\n order: sortOrderSchema.optional(),\n limit: z.number().int().min(0).optional(),\n offset: z.number().int().min(0).optional(),\n});\n\n/**\n * Request body type for list endpoint\n */\nexport type ListRequestBody = z.infer<typeof listRequestBodySchema>;\n\n/**\n * Creates list route for HTTP server\n */\nexport function createListRoute(library: Library) {\n const route = new Hono();\n\n // POST / - List all references\n route.post(\"/\", async (c) => {\n // Parse request body\n let body: unknown;\n try {\n body = await c.req.json();\n } catch {\n return c.json({ error: \"Invalid JSON\" }, 400);\n }\n\n // Validate body with zod\n const parseResult = listRequestBodySchema.safeParse(body);\n if (!parseResult.success) {\n const errorMessage = parseResult.error.issues[0]?.message ?? \"Invalid request body\";\n return c.json({ error: errorMessage }, 400);\n }\n\n const requestBody = parseResult.data;\n\n // Build options for listReferences\n const options: ListOptions = pickDefined(requestBody, [\n \"sort\",\n \"order\",\n \"limit\",\n \"offset\",\n ] as const);\n\n // Call listReferences operation - always returns raw CslItem[]\n const result = await listReferences(library, options);\n\n return c.json(result);\n });\n\n return route;\n}\n","import type { CslItem } from \"../../core/csl-json/types.js\";\nimport type { ILibrary, IdentifierType } from \"../../core/library-interface.js\";\n\n/**\n * Options for updateReference operation\n */\nexport interface UpdateOperationOptions {\n /** Reference ID or UUID */\n identifier: string;\n /** Identifier type: 'id' (default), 'uuid', 'doi', 'pmid', or 'isbn' */\n idType?: IdentifierType;\n /** Partial updates to apply to the reference */\n updates: Partial<CslItem>;\n /** How to handle ID collision: 'fail' (default) or 'suffix' */\n onIdCollision?: \"fail\" | \"suffix\";\n}\n\n/**\n * Result of updateReference operation\n */\nexport interface UpdateOperationResult {\n /** Whether the update was successful */\n updated: boolean;\n /** The updated item (if successful) */\n item?: CslItem;\n /** The original item before update (when item is available) */\n oldItem?: CslItem;\n /** Error type when update failed (only when updated=false) */\n errorType?: \"not_found\" | \"id_collision\";\n /** True if the ID was changed due to collision resolution */\n idChanged?: boolean;\n /** The new ID after collision resolution (only when idChanged=true) */\n newId?: string;\n}\n\n/**\n * Update a reference in the library.\n *\n * @param library - The library to update\n * @param options - Update options including identifier, updates, and collision handling\n * @returns Result indicating success and the updated item\n */\nexport async function updateReference(\n library: ILibrary,\n options: UpdateOperationOptions\n): Promise<UpdateOperationResult> {\n const { identifier, idType = \"id\", updates, onIdCollision = \"fail\" } = options;\n\n // Update the reference using unified update() method\n const updateResult = await library.update(identifier, updates, { idType, onIdCollision });\n\n if (!updateResult.updated) {\n const result: UpdateOperationResult = { updated: false };\n if (updateResult.errorType) {\n result.errorType = updateResult.errorType;\n }\n if (updateResult.item) {\n result.item = updateResult.item;\n }\n if (updateResult.idChanged && updateResult.newId) {\n result.idChanged = true;\n result.newId = updateResult.newId;\n }\n return result;\n }\n\n // Save the library\n await library.save();\n\n // Build result from UpdateResult (item is now included)\n const result: UpdateOperationResult = { updated: true };\n\n if (updateResult.item) {\n result.item = updateResult.item;\n }\n\n if (updateResult.oldItem) {\n result.oldItem = updateResult.oldItem;\n }\n\n if (updateResult.idChanged && updateResult.newId) {\n result.idChanged = true;\n result.newId = updateResult.newId;\n }\n\n return result;\n}\n","import { Hono } from \"hono\";\nimport type { Config, FulltextSource } from \"../../config/schema.js\";\nimport type { Library } from \"../../core/library.js\";\nimport {\n fulltextConvert,\n fulltextDiscover,\n fulltextFetch,\n} from \"../../features/operations/fulltext/index.js\";\nimport { removeReference } from \"../../features/operations/remove.js\";\nimport { updateReference } from \"../../features/operations/update.js\";\n\n/**\n * Create references CRUD route with the given library.\n * @param library - Library instance to use for operations\n * @param config - Configuration for fulltext operations\n * @returns Hono app with references routes\n */\nexport function createReferencesRoute(library: Library, config?: Config) {\n const route = new Hono();\n\n // GET / - Get all references (getAll now returns Promise<CslItem[]>)\n route.get(\"/\", async (c) => {\n const items = await library.getAll();\n return c.json(items);\n });\n\n // GET /uuid/:uuid - Get reference by UUID\n route.get(\"/uuid/:uuid\", async (c) => {\n const uuid = c.req.param(\"uuid\");\n const item = await library.find(uuid, { idType: \"uuid\" });\n\n if (!item) {\n return c.json({ error: \"Reference not found\" }, 404);\n }\n\n return c.json(item);\n });\n\n // GET /id/:id - Get reference by citation ID\n route.get(\"/id/:id\", async (c) => {\n const id = c.req.param(\"id\");\n const item = await library.find(id);\n\n if (!item) {\n return c.json({ error: \"Reference not found\" }, 404);\n }\n\n return c.json(item);\n });\n\n // POST / - Create new reference\n route.post(\"/\", async (c) => {\n try {\n const body = await c.req.json();\n\n // Create and add reference (library.add handles validation and returns the added item)\n const addedItem = await library.add(body);\n\n return c.json(addedItem, 201);\n } catch (error) {\n return c.json(\n {\n error: \"Invalid request body\",\n details: error instanceof Error ? error.message : String(error),\n },\n 400\n );\n }\n });\n\n // PUT /uuid/:uuid - Update reference by UUID\n // Request body: { updates: Partial<CslItem>, onIdCollision?: \"fail\" | \"suffix\" }\n route.put(\"/uuid/:uuid\", async (c) => {\n const uuid = c.req.param(\"uuid\");\n\n let body: unknown;\n try {\n body = await c.req.json();\n } catch {\n return c.json({ error: \"Invalid JSON\" }, 400);\n }\n\n if (!body || typeof body !== \"object\") {\n return c.json({ error: \"Request body must be an object\" }, 400);\n }\n\n const { updates, onIdCollision } = body as {\n updates?: Partial<import(\"../../core/csl-json/types.js\").CslItem>;\n onIdCollision?: \"fail\" | \"suffix\";\n };\n\n if (!updates || typeof updates !== \"object\") {\n return c.json({ error: \"Request body must contain 'updates' object\" }, 400);\n }\n\n // Use updateReference operation\n const result = await updateReference(library, {\n identifier: uuid,\n idType: \"uuid\",\n updates,\n onIdCollision: onIdCollision ?? \"suffix\",\n });\n\n // Return operation result with appropriate status code\n if (!result.updated) {\n const status = result.errorType === \"id_collision\" ? 409 : 404;\n return c.json(result, status);\n }\n\n return c.json(result);\n });\n\n // PUT /id/:id - Update reference by citation ID\n // Request body: { updates: Partial<CslItem>, onIdCollision?: \"fail\" | \"suffix\" }\n route.put(\"/id/:id\", async (c) => {\n const id = c.req.param(\"id\");\n\n let body: unknown;\n try {\n body = await c.req.json();\n } catch {\n return c.json({ error: \"Invalid JSON\" }, 400);\n }\n\n if (!body || typeof body !== \"object\") {\n return c.json({ error: \"Request body must be an object\" }, 400);\n }\n\n const { updates, onIdCollision } = body as {\n updates?: Partial<import(\"../../core/csl-json/types.js\").CslItem>;\n onIdCollision?: \"fail\" | \"suffix\";\n };\n\n if (!updates || typeof updates !== \"object\") {\n return c.json({ error: \"Request body must contain 'updates' object\" }, 400);\n }\n\n // Use updateReference operation with idType: 'id'\n const result = await updateReference(library, {\n identifier: id,\n updates,\n onIdCollision: onIdCollision ?? \"suffix\",\n });\n\n // Return operation result with appropriate status code\n if (!result.updated) {\n const status = result.errorType === \"id_collision\" ? 409 : 404;\n return c.json(result, status);\n }\n\n return c.json(result);\n });\n\n // DELETE /uuid/:uuid - Delete reference by UUID\n route.delete(\"/uuid/:uuid\", async (c) => {\n const uuid = c.req.param(\"uuid\");\n\n // Use removeReference operation\n const result = await removeReference(library, {\n identifier: uuid,\n idType: \"uuid\",\n });\n\n // Return operation result with appropriate status code\n if (!result.removed) {\n return c.json(result, 404);\n }\n\n return c.json(result);\n });\n\n // DELETE /id/:id - Delete reference by citation ID\n route.delete(\"/id/:id\", async (c) => {\n const id = c.req.param(\"id\");\n\n // Use removeReference operation\n const result = await removeReference(library, {\n identifier: id,\n });\n\n // Return operation result with appropriate status code\n if (!result.removed) {\n return c.json(result, 404);\n }\n\n return c.json(result);\n });\n\n // Fulltext retrieval routes (require config)\n if (config) {\n // GET /uuid/:uuid/fulltext/discover\n route.get(\"/uuid/:uuid/fulltext/discover\", async (c) => {\n const uuid = c.req.param(\"uuid\");\n const result = await fulltextDiscover(library, {\n identifier: uuid,\n idType: \"uuid\",\n fulltextConfig: config.fulltext,\n });\n\n if (!result.success) {\n return c.json({ error: result.error }, 400);\n }\n\n return c.json(result);\n });\n\n // POST /uuid/:uuid/fulltext/fetch\n route.post(\"/uuid/:uuid/fulltext/fetch\", async (c) => {\n const uuid = c.req.param(\"uuid\");\n let body: { source?: string; force?: boolean } = {};\n try {\n body = await c.req.json();\n } catch {\n // No body is OK - use defaults\n }\n\n const result = await fulltextFetch(library, {\n identifier: uuid,\n idType: \"uuid\",\n fulltextConfig: config.fulltext,\n fulltextDirectory: config.attachments.directory,\n source: body.source as FulltextSource | undefined,\n force: body.force,\n });\n\n if (!result.success) {\n return c.json({ error: result.error }, 400);\n }\n\n return c.json(result);\n });\n\n // POST /uuid/:uuid/fulltext/convert\n route.post(\"/uuid/:uuid/fulltext/convert\", async (c) => {\n const uuid = c.req.param(\"uuid\");\n const result = await fulltextConvert(library, {\n identifier: uuid,\n idType: \"uuid\",\n fulltextDirectory: config.attachments.directory,\n });\n\n if (!result.success) {\n return c.json({ error: result.error }, 400);\n }\n\n return c.json(result);\n });\n }\n\n return route;\n}\n","import type { CslItem } from \"../../core/csl-json/types.js\";\nimport type { ILibrary } from \"../../core/library-interface.js\";\nimport {\n type PaginationOptions,\n type SearchSortField,\n type SortField,\n type SortOrder,\n paginate,\n sortReferences,\n} from \"../pagination/index.js\";\nimport { search } from \"../search/matcher.js\";\nimport { sortResults as sortByRelevance } from \"../search/sorter.js\";\nimport { tokenize } from \"../search/tokenizer.js\";\n\n/**\n * Sort options for search (includes relevance)\n */\nexport interface SearchSortOptions {\n sort?: SearchSortField;\n order?: SortOrder;\n}\n\n/**\n * Options for searchReferences operation\n */\nexport interface SearchOperationOptions extends PaginationOptions, SearchSortOptions {\n /** Search query string */\n query: string;\n}\n\n/**\n * Result of searchReferences operation\n */\nexport interface SearchResult {\n /** Raw CslItem array */\n items: CslItem[];\n /** Total count before pagination */\n total: number;\n /** Applied limit (0 if unlimited) */\n limit: number;\n /** Applied offset */\n offset: number;\n /** Next page offset, null if no more results */\n nextOffset: number | null;\n}\n\n/**\n * Search references in the library and return raw CslItem[] results.\n *\n * @param library - The library to search in\n * @param options - Search query and pagination options\n * @returns Raw CslItem[] with pagination metadata\n */\nexport async function searchReferences(\n library: ILibrary,\n options: SearchOperationOptions\n): Promise<SearchResult> {\n const query = options.query;\n const sort: SearchSortField = options.sort ?? \"updated\";\n const order: SortOrder = options.order ?? \"desc\";\n const limit = options.limit ?? 0;\n const offset = options.offset ?? 0;\n\n // Get all references\n const allItems = await library.getAll();\n\n // Search and get matched items\n let matchedItems: CslItem[];\n if (!query.trim()) {\n matchedItems = allItems;\n } else {\n // Tokenize and search\n const tokens = tokenize(query).tokens;\n const results = search(allItems, tokens);\n\n // If sorting by relevance, use the search sorter\n if (sort === \"relevance\") {\n const sorted = sortByRelevance(results);\n matchedItems =\n order === \"desc\"\n ? sorted.map((r) => r.reference)\n : sorted.map((r) => r.reference).reverse();\n } else {\n matchedItems = results.map((r) => r.reference);\n }\n }\n\n const total = matchedItems.length;\n\n // Sort (unless already sorted by relevance)\n let sorted: CslItem[];\n if (sort === \"relevance\") {\n sorted = matchedItems;\n } else {\n sorted = sortReferences(matchedItems, sort as SortField, order);\n }\n\n // Paginate\n const { items: paginatedItems, nextOffset } = paginate(sorted, { limit, offset });\n\n return {\n items: paginatedItems,\n total,\n limit,\n offset,\n nextOffset,\n };\n}\n","import { Hono } from \"hono\";\nimport { z } from \"zod\";\nimport type { Library } from \"../../core/library.js\";\nimport { type SearchOperationOptions, searchReferences } from \"../../features/operations/search.js\";\nimport { searchSortFieldSchema, sortOrderSchema } from \"../../features/pagination/index.js\";\nimport { pickDefined } from \"../../utils/object.js\";\n\n/**\n * Request body schema for search endpoint\n */\nconst searchRequestBodySchema = z.object({\n query: z.string(),\n sort: searchSortFieldSchema.optional(),\n order: sortOrderSchema.optional(),\n limit: z.number().int().min(0).optional(),\n offset: z.number().int().min(0).optional(),\n});\n\n/**\n * Request body type for search endpoint\n */\nexport type SearchRequestBody = z.infer<typeof searchRequestBodySchema>;\n\n/**\n * Creates search route for HTTP server\n */\nexport function createSearchRoute(library: Library) {\n const route = new Hono();\n\n // POST / - Search references\n route.post(\"/\", async (c) => {\n // Parse request body\n let body: unknown;\n try {\n body = await c.req.json();\n } catch {\n return c.json({ error: \"Invalid JSON\" }, 400);\n }\n\n // Validate body with zod\n const parseResult = searchRequestBodySchema.safeParse(body);\n if (!parseResult.success) {\n const errorMessage = parseResult.error.issues[0]?.message ?? \"Invalid request body\";\n return c.json({ error: errorMessage }, 400);\n }\n\n const requestBody = parseResult.data;\n\n // Build options for searchReferences\n const options: SearchOperationOptions = {\n query: requestBody.query,\n ...pickDefined(requestBody, [\"sort\", \"order\", \"limit\", \"offset\"] as const),\n };\n\n // Call searchReferences operation - always returns raw CslItem[]\n const result = await searchReferences(library, options);\n\n return c.json(result);\n });\n\n return route;\n}\n","import { Hono } from \"hono\";\nimport type { Config } from \"../config/schema.js\";\nimport { Library } from \"../core/library.js\";\nimport { FileWatcher } from \"../features/file-watcher/file-watcher.js\";\nimport { createAddRoute } from \"./routes/add.js\";\nimport { createCiteRoute } from \"./routes/cite.js\";\nimport { healthRoute } from \"./routes/health.js\";\nimport { createListRoute } from \"./routes/list.js\";\nimport { createReferencesRoute } from \"./routes/references.js\";\nimport { createSearchRoute } from \"./routes/search.js\";\n\n/**\n * Result of starting a server with file watcher.\n */\nexport interface ServerWithFileWatcherResult {\n /** The Hono application */\n app: Hono;\n /** The library instance */\n library: Library;\n /** The file watcher instance */\n fileWatcher: FileWatcher;\n /** Dispose function to clean up resources */\n dispose: () => Promise<void>;\n}\n\n/**\n * Create the main Hono server application.\n * @param library - Library instance for the references API\n * @param config - Configuration for the server\n * @returns Hono application\n */\nexport function createServer(library: Library, config: Config) {\n const app = new Hono();\n\n // Health check route\n app.route(\"/health\", healthRoute);\n\n // References API routes\n const referencesRoute = createReferencesRoute(library, config);\n app.route(\"/api/references\", referencesRoute);\n\n // Add references route\n const addRoute = createAddRoute(library, config);\n app.route(\"/api/add\", addRoute);\n\n // Cite route\n const citeRoute = createCiteRoute(library);\n app.route(\"/api/cite\", citeRoute);\n\n // List route\n const listRoute = createListRoute(library);\n app.route(\"/api/list\", listRoute);\n\n // Search route\n const searchRoute = createSearchRoute(library);\n app.route(\"/api/search\", searchRoute);\n\n return app;\n}\n\n/**\n * Start a server with file watcher for automatic library reload.\n * Uses the same pattern as MCP server file monitoring.\n * @param libraryPath - Path to the library file\n * @param config - Configuration for the server\n * @returns Server with file watcher result\n */\nexport async function startServerWithFileWatcher(\n libraryPath: string,\n config: Config\n): Promise<ServerWithFileWatcherResult> {\n // Load library\n const library = await Library.load(libraryPath);\n\n // Create the Hono app\n const app = createServer(library, config);\n\n // Create and start file watcher\n const fileWatcher = new FileWatcher(libraryPath, {\n debounceMs: config.watch.debounceMs,\n maxRetries: config.watch.maxRetries,\n retryDelayMs: config.watch.retryIntervalMs,\n pollIntervalMs: config.watch.pollIntervalMs,\n });\n\n // Listen for file changes\n // Library.reload() handles self-write detection via hash comparison\n fileWatcher.on(\"change\", () => {\n library.reload().catch((error) => {\n // Log error but don't crash - library continues with previous state\n console.error(\"Failed to reload library:\", error);\n });\n });\n\n await fileWatcher.start();\n\n // Create dispose function\n const dispose = async (): Promise<void> => {\n fileWatcher.close();\n };\n\n return {\n app,\n library,\n fileWatcher,\n dispose,\n };\n}\n"],"names":["path","fs","USER_AGENT","defaultOptions","METADATA_SYMBOL","xmlNode","result","jTitle","text","formatCitation","convertResult","cite","DOI_URL_PREFIXES","identifiers","search","sorted","sortByRelevance"],"mappings":"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","x_google_ignoreList":[9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28]}