@ncukondo/reference-manager 0.21.0 → 0.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunks/{action-menu-CpkiDbRj.js → action-menu-B1DCdkkp.js} +4 -3
- package/dist/chunks/{action-menu-CpkiDbRj.js.map → action-menu-B1DCdkkp.js.map} +1 -1
- package/dist/chunks/{format-n2Es_y_u.js → format-CfTZqhUx.js} +2 -2
- package/dist/chunks/{format-n2Es_y_u.js.map → format-CfTZqhUx.js.map} +1 -1
- package/dist/chunks/{index-CScRH8g4.js → index-BK3hTiKR.js} +10 -9
- package/dist/chunks/{index-CScRH8g4.js.map → index-BK3hTiKR.js.map} +1 -1
- package/dist/chunks/{index-Bh6xryeS.js → index-BvIfOciH.js} +8 -5
- package/dist/chunks/index-BvIfOciH.js.map +1 -0
- package/dist/chunks/{index-DiF2ezv-.js → index-D7eiOplw.js} +3 -3
- package/dist/chunks/index-D7eiOplw.js.map +1 -0
- package/dist/chunks/{index-Cq83Elk8.js → index-DOvEusHb.js} +50 -25
- package/dist/chunks/index-DOvEusHb.js.map +1 -0
- package/dist/chunks/{reference-select-DlFG6N3o.js → reference-select-DTqhevya.js} +3 -3
- package/dist/chunks/{reference-select-DlFG6N3o.js.map → reference-select-DTqhevya.js.map} +1 -1
- package/dist/chunks/{style-select-1f5zHT8h.js → style-select-CXclvgJO.js} +3 -3
- package/dist/chunks/{style-select-1f5zHT8h.js.map → style-select-CXclvgJO.js.map} +1 -1
- package/dist/cli.js +1 -1
- package/dist/features/format/pretty.d.ts.map +1 -1
- package/dist/features/format/resource-indicators.d.ts +8 -0
- package/dist/features/format/resource-indicators.d.ts.map +1 -0
- package/dist/features/interactive/apps/runSearchFlow.d.ts +5 -0
- package/dist/features/interactive/apps/runSearchFlow.d.ts.map +1 -1
- package/dist/server.js +2 -2
- package/package.json +1 -1
- package/dist/chunks/index-Bh6xryeS.js.map +0 -1
- package/dist/chunks/index-Cq83Elk8.js.map +0 -1
- package/dist/chunks/index-DiF2ezv-.js.map +0 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { useApp, Box, render } from "ink";
|
|
2
2
|
import { useState, useEffect, createElement } from "react";
|
|
3
|
-
import { getActionChoices, OUTPUT_FORMAT_CHOICES, STYLE_CHOICES, isSideEffectAction, generateOutput } from "./action-menu-
|
|
4
|
-
import { S as SearchableMultiSelect, c as calculateEffectiveLimit, f as formatAuthors } from "./format-
|
|
5
|
-
import { S as Select, r as restoreStdinAfterInk } from "./index-
|
|
3
|
+
import { getActionChoices, OUTPUT_FORMAT_CHOICES, STYLE_CHOICES, isSideEffectAction, generateOutput } from "./action-menu-B1DCdkkp.js";
|
|
4
|
+
import { S as SearchableMultiSelect, c as calculateEffectiveLimit, f as formatAuthors } from "./format-CfTZqhUx.js";
|
|
5
|
+
import { S as Select, r as restoreStdinAfterInk, b as buildResourceIndicators } from "./index-DOvEusHb.js";
|
|
6
6
|
function SearchFlowApp({
|
|
7
7
|
choices,
|
|
8
8
|
filterFn,
|
|
@@ -197,11 +197,14 @@ function toChoice$1(item) {
|
|
|
197
197
|
const updatedDate = extractUpdatedDate$1(item);
|
|
198
198
|
const createdDate = extractCreatedDate$1(item);
|
|
199
199
|
const publishedDate = extractPublishedDate$1(item);
|
|
200
|
+
const indicators = buildResourceIndicators(item);
|
|
201
|
+
const metaStr = metaParts.join(" · ");
|
|
202
|
+
const meta = indicators ? `${indicators} ${metaStr}` : metaStr;
|
|
200
203
|
return {
|
|
201
204
|
id: item.id,
|
|
202
205
|
title: item.title ?? "(No title)",
|
|
203
206
|
subtitle: authors || "(No authors)",
|
|
204
|
-
meta
|
|
207
|
+
meta,
|
|
205
208
|
value: item,
|
|
206
209
|
...updatedDate && { updatedDate },
|
|
207
210
|
...createdDate && { createdDate },
|
|
@@ -466,4 +469,4 @@ export {
|
|
|
466
469
|
runCiteFlow,
|
|
467
470
|
runSearchFlow
|
|
468
471
|
};
|
|
469
|
-
//# sourceMappingURL=index-
|
|
472
|
+
//# sourceMappingURL=index-BvIfOciH.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-BvIfOciH.js","sources":["../../src/features/interactive/apps/SearchFlowApp.tsx","../../src/features/interactive/apps/runSearchFlow.ts","../../src/features/interactive/apps/CiteFlowApp.tsx","../../src/features/interactive/apps/runCiteFlow.ts"],"sourcesContent":["/**\n * SearchFlowApp - Single App for search -t flow\n *\n * Manages state transitions: search → action → (style/output-format if needed)\n * Following React Ink Single App Pattern (ADR-015)\n */\n\nimport { Box, useApp } from \"ink\";\nimport type React from \"react\";\nimport { createElement, useEffect, useState } from \"react\";\nimport type { CitationKeyFormat } from \"../../../config/schema.js\";\nimport type { CslItem } from \"../../../core/csl-json/types.js\";\nimport {\n type ActionMenuResult,\n type ActionType,\n OUTPUT_FORMAT_CHOICES,\n type OutputFormatType,\n STYLE_CHOICES,\n generateOutput,\n getActionChoices,\n isSideEffectAction,\n} from \"../action-menu.js\";\nimport {\n type Choice,\n SearchableMultiSelect,\n Select,\n type SortOption,\n} from \"../components/index.js\";\n\n/**\n * Flow states for the search flow\n */\ntype FlowState = \"search\" | \"action\" | \"style\" | \"output-format\" | \"exiting\";\n\n/**\n * Props for SearchFlowApp\n */\nexport interface SearchFlowAppProps {\n /** Choices for the search prompt */\n choices: Choice<CslItem>[];\n /** Filter function for search */\n filterFn: (query: string, choices: Choice<CslItem>[]) => Choice<CslItem>[];\n /** Number of visible items */\n visibleCount: number;\n /** Default sort option */\n defaultSort: SortOption;\n /** Default citation key format */\n defaultKeyFormat: CitationKeyFormat;\n /** Default citation style */\n defaultStyle: string;\n /** Callback when flow completes */\n onComplete: (result: ActionMenuResult) => void;\n /** Callback when flow is cancelled */\n onCancel: () => void;\n}\n\n/**\n * SearchFlowApp component\n *\n * Single App that manages search → action → style/output-format flow\n */\nexport function SearchFlowApp({\n choices,\n filterFn,\n visibleCount,\n defaultSort,\n defaultKeyFormat,\n defaultStyle,\n onComplete,\n onCancel,\n}: SearchFlowAppProps): React.ReactElement {\n const { exit } = useApp();\n const [state, setState] = useState<FlowState>(\"search\");\n const [selectedItems, setSelectedItems] = useState<CslItem[]>([]);\n const [pendingResult, setPendingResult] = useState<ActionMenuResult | null>(null);\n\n // Exit when entering \"exiting\" state (after rendering empty component)\n useEffect(() => {\n if (state === \"exiting\" && pendingResult) {\n exit();\n if (pendingResult.cancelled) {\n onCancel();\n } else {\n onComplete(pendingResult);\n }\n }\n }, [state, pendingResult, exit, onCancel, onComplete]);\n\n // Transition to exiting state with result\n const exitWith = (result: ActionMenuResult) => {\n setPendingResult(result);\n setState(\"exiting\");\n };\n\n // Handle search submission\n const handleSearchSubmit = (selected: Choice<CslItem>[]) => {\n if (selected.length === 0) {\n exitWith({ action: \"cancel\", output: \"\", cancelled: true });\n return;\n }\n setSelectedItems(selected.map((c) => c.value));\n setState(\"action\");\n };\n\n // Handle search cancel\n const handleSearchCancel = () => {\n exitWith({ action: \"cancel\", output: \"\", cancelled: true });\n };\n\n // Handle action selection\n const handleActionSelect = (action: ActionType) => {\n if (action === \"cancel\") {\n exitWith({ action: \"cancel\", output: \"\", cancelled: true });\n return;\n }\n\n // If cite-choose, go to style selection\n if (action === \"cite-choose\") {\n setState(\"style\");\n return;\n }\n\n // If output-format, go to output format submenu\n if (action === \"output-format\") {\n setState(\"output-format\");\n return;\n }\n\n // Handle side-effect actions\n if (isSideEffectAction(action)) {\n exitWith({ action, output: \"\", cancelled: false, selectedItems });\n return;\n }\n\n // Generate output and complete\n const output = generateOutput(action, selectedItems, {\n defaultKeyFormat,\n defaultStyle,\n });\n exitWith({ action, output, cancelled: false });\n };\n\n // Handle action cancel (go back to search)\n const handleActionCancel = () => {\n setState(\"search\");\n };\n\n // Handle style selection\n const handleStyleSelect = (style: string) => {\n const output = generateOutput(\"cite-choose\", selectedItems, {\n defaultKeyFormat,\n defaultStyle: style,\n });\n exitWith({ action: \"cite-choose\", output, cancelled: false });\n };\n\n // Handle style cancel (go back to action)\n const handleStyleCancel = () => {\n setState(\"action\");\n };\n\n // Handle output format selection\n const handleOutputFormatSelect = (format: OutputFormatType) => {\n if (format === \"cancel\") {\n setState(\"action\");\n return;\n }\n\n const output = generateOutput(format, selectedItems, {\n defaultKeyFormat,\n defaultStyle,\n });\n exitWith({ action: \"output-format\", output, cancelled: false });\n };\n\n // Handle output format cancel (go back to action)\n const handleOutputFormatCancel = () => {\n setState(\"action\");\n };\n\n // Render based on current state\n if (state === \"exiting\") {\n // Empty component - Ink will clear the previous content\n return createElement(Box);\n }\n\n if (state === \"search\") {\n return createElement(SearchableMultiSelect<CslItem>, {\n choices,\n filterFn,\n visibleCount,\n onSubmit: handleSearchSubmit,\n onCancel: handleSearchCancel,\n header: \"Search references\",\n placeholder: \"Type to search...\",\n defaultSort,\n });\n }\n\n if (state === \"action\") {\n const count = selectedItems.length;\n const refWord = count === 1 ? \"reference\" : \"references\";\n return createElement(Select<ActionType>, {\n key: \"action\",\n options: getActionChoices(count, { defaultKeyFormat }),\n message: `Action for ${count} selected ${refWord}:`,\n onSelect: handleActionSelect,\n onCancel: handleActionCancel,\n });\n }\n\n if (state === \"output-format\") {\n return createElement(Select<OutputFormatType>, {\n key: \"output-format\",\n options: OUTPUT_FORMAT_CHOICES,\n message: \"Select output format:\",\n onSelect: handleOutputFormatSelect,\n onCancel: handleOutputFormatCancel,\n });\n }\n\n // state === \"style\"\n return createElement(Select<string>, {\n key: \"style\",\n options: STYLE_CHOICES,\n message: \"Select citation style:\",\n onSelect: handleStyleSelect,\n onCancel: handleStyleCancel,\n });\n}\n","/**\n * Runner for SearchFlowApp\n *\n * Provides the public API for running the search flow.\n */\n\nimport { render } from \"ink\";\nimport { createElement } from \"react\";\nimport type { CitationKeyFormat } from \"../../../config/schema.js\";\nimport type { CslItem } from \"../../../core/csl-json/types.js\";\nimport { buildResourceIndicators } from \"../../format/resource-indicators.js\";\nimport type { SearchResult } from \"../../search/types.js\";\nimport type { ActionMenuResult } from \"../action-menu.js\";\nimport { restoreStdinAfterInk } from \"../alternate-screen.js\";\nimport { type Choice, type SortOption, calculateEffectiveLimit } from \"../components/index.js\";\nimport { formatAuthors } from \"../format.js\";\nimport { SearchFlowApp } from \"./SearchFlowApp.js\";\n\n/**\n * Configuration for the search flow\n */\nexport interface SearchFlowConfig {\n /** Maximum number of results to display */\n limit: number;\n /** Debounce delay in milliseconds (not used, kept for API compatibility) */\n debounceMs: number;\n /** Default citation key format */\n defaultKeyFormat?: CitationKeyFormat;\n /** Default citation style */\n defaultStyle?: string;\n}\n\n/**\n * Search function type for filtering references\n */\nexport type SearchFunction = (query: string) => SearchResult[];\n\n/**\n * Extract year from CSL item\n */\nfunction extractYear(item: CslItem): number | undefined {\n const dateParts = item.issued?.[\"date-parts\"];\n if (!dateParts || dateParts.length === 0) return undefined;\n const firstDatePart = dateParts[0];\n if (!firstDatePart || firstDatePart.length === 0) return undefined;\n return firstDatePart[0];\n}\n\n/**\n * Extract published date from CSL item\n */\nfunction extractPublishedDate(item: CslItem): Date | undefined {\n const dateParts = item.issued?.[\"date-parts\"];\n if (!dateParts || dateParts.length === 0) return undefined;\n const firstDatePart = dateParts[0];\n if (!firstDatePart || firstDatePart.length === 0) return undefined;\n const [year, month = 1, day = 1] = firstDatePart;\n if (year === undefined) return undefined;\n return new Date(year, month - 1, day);\n}\n\n/**\n * Extract updated date from CSL item (from custom.timestamp)\n */\nfunction extractUpdatedDate(item: CslItem): Date | undefined {\n const dateStr = item.custom?.timestamp;\n if (!dateStr || typeof dateStr !== \"string\") return undefined;\n const date = new Date(dateStr);\n return Number.isNaN(date.getTime()) ? undefined : date;\n}\n\n/**\n * Extract created date from CSL item (from custom.created_at)\n */\nfunction extractCreatedDate(item: CslItem): Date | undefined {\n const dateStr = item.custom?.created_at;\n if (!dateStr || typeof dateStr !== \"string\") return undefined;\n const date = new Date(dateStr);\n return Number.isNaN(date.getTime()) ? undefined : date;\n}\n\n/**\n * Format identifiers for meta line\n */\nfunction formatIdentifiers(item: CslItem): string {\n const parts: string[] = [];\n if (item.DOI) parts.push(`DOI: ${item.DOI}`);\n if (item.PMID) parts.push(`PMID: ${item.PMID}`);\n if (item.PMCID) parts.push(`PMCID: ${item.PMCID}`);\n if (item.ISBN) parts.push(`ISBN: ${item.ISBN}`);\n return parts.join(\" · \");\n}\n\n/**\n * Format item type for display\n */\nfunction formatType(type: string): string {\n const typeMap: Record<string, string> = {\n \"article-journal\": \"Journal article\",\n \"article-magazine\": \"Magazine article\",\n \"article-newspaper\": \"Newspaper article\",\n book: \"Book\",\n chapter: \"Book chapter\",\n \"paper-conference\": \"Conference paper\",\n thesis: \"Thesis\",\n report: \"Report\",\n webpage: \"Web page\",\n };\n return typeMap[type] ?? type;\n}\n\n/**\n * Convert CslItem to Choice for SearchableMultiSelect\n */\nexport function toChoice(item: CslItem): Choice<CslItem> {\n const authors = formatAuthors(item.author);\n const year = extractYear(item);\n const identifiers = formatIdentifiers(item);\n const itemType = formatType(item.type);\n\n // Build meta line: Year · Type · Identifiers\n const metaParts: string[] = [];\n if (year) metaParts.push(String(year));\n metaParts.push(itemType);\n if (identifiers) metaParts.push(identifiers);\n\n const updatedDate = extractUpdatedDate(item);\n const createdDate = extractCreatedDate(item);\n const publishedDate = extractPublishedDate(item);\n\n // Prepend resource indicators to meta if present\n const indicators = buildResourceIndicators(item);\n const metaStr = metaParts.join(\" · \");\n const meta = indicators ? `${indicators} ${metaStr}` : metaStr;\n\n return {\n id: item.id,\n title: item.title ?? \"(No title)\",\n subtitle: authors || \"(No authors)\",\n meta,\n value: item,\n ...(updatedDate && { updatedDate }),\n ...(createdDate && { createdDate }),\n ...(publishedDate && { publishedDate }),\n };\n}\n\n/**\n * Run the search flow (search → action → style if needed)\n *\n * This is the main entry point for the `search -t` command.\n */\nexport async function runSearchFlow(\n allReferences: CslItem[],\n searchFn: SearchFunction,\n config: SearchFlowConfig\n): Promise<ActionMenuResult> {\n // Convert references to choices\n const choices = allReferences.map(toChoice);\n\n // Calculate effective visible count\n const effectiveLimit = calculateEffectiveLimit(config.limit);\n\n // Create filter function using the provided search function\n const filterFn = (query: string, choices: Choice<CslItem>[]): Choice<CslItem>[] => {\n if (!query.trim()) return choices;\n\n const results = searchFn(query);\n return results.map((r) => toChoice(r.reference));\n };\n\n // Default sort option\n const defaultSort: SortOption = \"updated-desc\";\n\n // Create a promise to capture the result\n return new Promise<ActionMenuResult>((resolve) => {\n let flowResult: ActionMenuResult = {\n action: \"cancel\",\n output: \"\",\n cancelled: true,\n };\n\n const handleComplete = (result: ActionMenuResult): void => {\n flowResult = result;\n };\n\n const handleCancel = (): void => {\n flowResult = {\n action: \"cancel\",\n output: \"\",\n cancelled: true,\n };\n };\n\n // Render the Ink app (single render for entire flow)\n const { waitUntilExit } = render(\n createElement(SearchFlowApp, {\n choices,\n filterFn,\n visibleCount: effectiveLimit,\n defaultSort,\n defaultKeyFormat: config.defaultKeyFormat ?? \"pandoc\",\n defaultStyle: config.defaultStyle ?? \"apa\",\n onComplete: handleComplete,\n onCancel: handleCancel,\n })\n );\n\n // Wait for the app to exit, then resolve\n waitUntilExit()\n .then(() => {\n restoreStdinAfterInk();\n resolve(flowResult);\n })\n .catch(() => {\n restoreStdinAfterInk();\n resolve({\n action: \"cancel\",\n output: \"\",\n cancelled: true,\n });\n });\n });\n}\n","/**\n * CiteFlowApp - Single App for cite command flow\n *\n * Implements the Single App Pattern (ADR-015) for the cite command.\n * Manages state transitions: reference selection → style selection → exiting\n */\n\nimport { Box, useApp } from \"ink\";\nimport type React from \"react\";\nimport { createElement, useEffect, useState } from \"react\";\nimport type { CslItem } from \"../../../core/csl-json/types.js\";\nimport { SearchableMultiSelect } from \"../components/SearchableMultiSelect.js\";\nimport { Select, type SelectOption } from \"../components/Select.js\";\nimport type { Choice, SortOption } from \"../components/index.js\";\n\n// Flow states\ntype FlowState = \"search\" | \"style\" | \"exiting\";\n\n/**\n * Result from the cite flow\n */\nexport interface CiteFlowResult {\n /** Selected reference IDs */\n identifiers: string[];\n /** Selected style (if style selection was shown) */\n style?: string;\n /** Whether the flow was cancelled */\n cancelled: boolean;\n}\n\n/**\n * Props for CiteFlowApp\n */\nexport interface CiteFlowAppProps {\n /** All reference choices */\n choices: Choice<CslItem>[];\n /** Filter function for search */\n filterFn: (query: string, choices: Choice<CslItem>[]) => Choice<CslItem>[];\n /** Number of visible items */\n visibleCount: number;\n /** Default sort option */\n defaultSort: SortOption;\n /** Style options for style selection */\n styleOptions: SelectOption<string>[];\n /** Whether to show style selection (false if style already specified) */\n showStyleSelect: boolean;\n /** Callback when flow completes */\n onComplete: (result: CiteFlowResult) => void;\n /** Callback when flow is cancelled */\n onCancel: () => void;\n}\n\n/**\n * CiteFlowApp component\n *\n * Single Ink app that handles the entire cite flow:\n * 1. Reference selection (SearchableMultiSelect)\n * 2. Style selection (Select) - optional\n * 3. Exit\n */\nexport function CiteFlowApp({\n choices,\n filterFn,\n visibleCount,\n defaultSort,\n styleOptions,\n showStyleSelect,\n onComplete,\n onCancel,\n}: CiteFlowAppProps): React.ReactElement {\n const { exit } = useApp();\n const [state, setState] = useState<FlowState>(\"search\");\n const [selectedItems, setSelectedItems] = useState<CslItem[]>([]);\n const [pendingResult, setPendingResult] = useState<CiteFlowResult | null>(null);\n\n // Exit when entering \"exiting\" state\n useEffect(() => {\n if (state === \"exiting\" && pendingResult) {\n exit();\n if (pendingResult.cancelled) {\n onCancel();\n } else {\n onComplete(pendingResult);\n }\n }\n }, [state, pendingResult, exit, onCancel, onComplete]);\n\n // Transition to exiting state with result\n const exitWith = (result: CiteFlowResult) => {\n setPendingResult(result);\n setState(\"exiting\");\n };\n\n // Handle search submission\n const handleSearchSubmit = (selected: Choice<CslItem>[]) => {\n if (selected.length === 0) {\n exitWith({ identifiers: [], cancelled: true });\n return;\n }\n const items = selected.map((c) => c.value);\n setSelectedItems(items);\n\n if (showStyleSelect) {\n setState(\"style\");\n } else {\n // No style selection needed, complete immediately\n exitWith({\n identifiers: items.map((item) => item.id),\n cancelled: false,\n });\n }\n };\n\n // Handle search cancel\n const handleSearchCancel = () => {\n exitWith({ identifiers: [], cancelled: true });\n };\n\n // Handle style selection\n const handleStyleSelect = (style: string) => {\n exitWith({\n identifiers: selectedItems.map((item) => item.id),\n style,\n cancelled: false,\n });\n };\n\n // Handle style cancel (go back to search)\n const handleStyleCancel = () => {\n setState(\"search\");\n };\n\n // Render based on current state\n if (state === \"exiting\") {\n return createElement(Box);\n }\n\n if (state === \"search\") {\n return createElement(SearchableMultiSelect<CslItem>, {\n choices,\n filterFn,\n visibleCount,\n onSubmit: handleSearchSubmit,\n onCancel: handleSearchCancel,\n header: \"Select references to cite\",\n placeholder: \"Type to search...\",\n defaultSort,\n });\n }\n\n // state === \"style\"\n const count = selectedItems.length;\n const refWord = count === 1 ? \"reference\" : \"references\";\n return createElement(Select<string>, {\n options: styleOptions,\n message: `Select citation style for ${count} ${refWord}:`,\n onSelect: handleStyleSelect,\n onCancel: handleStyleCancel,\n });\n}\n","/**\n * Runner for CiteFlowApp\n *\n * Provides the public API for running the cite flow.\n */\n\nimport { render } from \"ink\";\nimport { createElement } from \"react\";\nimport type { CslItem } from \"../../../core/csl-json/types.js\";\nimport type { SearchResult } from \"../../search/types.js\";\nimport { restoreStdinAfterInk } from \"../alternate-screen.js\";\nimport {\n type Choice,\n type SelectOption,\n type SortOption,\n calculateEffectiveLimit,\n} from \"../components/index.js\";\nimport { formatAuthors } from \"../format.js\";\nimport { CiteFlowApp, type CiteFlowResult } from \"./CiteFlowApp.js\";\n\n/**\n * Configuration for the cite flow\n */\nexport interface CiteFlowConfig {\n /** Maximum number of results to display */\n limit: number;\n}\n\n/**\n * Search function type for filtering references\n */\nexport type SearchFunction = (query: string) => SearchResult[];\n\n/**\n * Extract year from CSL item\n */\nfunction extractYear(item: CslItem): number | undefined {\n const dateParts = item.issued?.[\"date-parts\"];\n if (!dateParts || dateParts.length === 0) return undefined;\n const firstDatePart = dateParts[0];\n if (!firstDatePart || firstDatePart.length === 0) return undefined;\n return firstDatePart[0];\n}\n\n/**\n * Extract published date from CSL item\n */\nfunction extractPublishedDate(item: CslItem): Date | undefined {\n const dateParts = item.issued?.[\"date-parts\"];\n if (!dateParts || dateParts.length === 0) return undefined;\n const firstDatePart = dateParts[0];\n if (!firstDatePart || firstDatePart.length === 0) return undefined;\n const [year, month = 1, day = 1] = firstDatePart;\n if (year === undefined) return undefined;\n return new Date(year, month - 1, day);\n}\n\n/**\n * Extract updated date from CSL item (from custom.timestamp)\n */\nfunction extractUpdatedDate(item: CslItem): Date | undefined {\n const dateStr = item.custom?.timestamp;\n if (!dateStr || typeof dateStr !== \"string\") return undefined;\n const date = new Date(dateStr);\n return Number.isNaN(date.getTime()) ? undefined : date;\n}\n\n/**\n * Extract created date from CSL item (from custom.created_at)\n */\nfunction extractCreatedDate(item: CslItem): Date | undefined {\n const dateStr = item.custom?.created_at;\n if (!dateStr || typeof dateStr !== \"string\") return undefined;\n const date = new Date(dateStr);\n return Number.isNaN(date.getTime()) ? undefined : date;\n}\n\n/**\n * Format identifiers for meta line\n */\nfunction formatIdentifiers(item: CslItem): string {\n const parts: string[] = [];\n if (item.DOI) parts.push(`DOI: ${item.DOI}`);\n if (item.PMID) parts.push(`PMID: ${item.PMID}`);\n if (item.PMCID) parts.push(`PMCID: ${item.PMCID}`);\n if (item.ISBN) parts.push(`ISBN: ${item.ISBN}`);\n return parts.join(\" · \");\n}\n\n/**\n * Format item type for display\n */\nfunction formatType(type: string): string {\n const typeMap: Record<string, string> = {\n \"article-journal\": \"Journal article\",\n \"article-magazine\": \"Magazine article\",\n \"article-newspaper\": \"Newspaper article\",\n book: \"Book\",\n chapter: \"Book chapter\",\n \"paper-conference\": \"Conference paper\",\n thesis: \"Thesis\",\n report: \"Report\",\n webpage: \"Web page\",\n };\n return typeMap[type] ?? type;\n}\n\n/**\n * Convert CslItem to Choice for SearchableMultiSelect\n */\nfunction toChoice(item: CslItem): Choice<CslItem> {\n const authors = formatAuthors(item.author);\n const year = extractYear(item);\n const identifiers = formatIdentifiers(item);\n const itemType = formatType(item.type);\n\n // Build meta line: Year · Type · Identifiers\n const metaParts: string[] = [];\n if (year) metaParts.push(String(year));\n metaParts.push(itemType);\n if (identifiers) metaParts.push(identifiers);\n\n const updatedDate = extractUpdatedDate(item);\n const createdDate = extractCreatedDate(item);\n const publishedDate = extractPublishedDate(item);\n\n return {\n id: item.id,\n title: item.title ?? \"(No title)\",\n subtitle: authors || \"(No authors)\",\n meta: metaParts.join(\" · \"),\n value: item,\n ...(updatedDate && { updatedDate }),\n ...(createdDate && { createdDate }),\n ...(publishedDate && { publishedDate }),\n };\n}\n\n/**\n * Options for running the cite flow\n */\nexport interface RunCiteFlowOptions {\n /** All references available for selection */\n allReferences: CslItem[];\n /** Search function for filtering */\n searchFn: SearchFunction;\n /** Flow configuration */\n config: CiteFlowConfig;\n /** Style options for style selection */\n styleOptions: SelectOption<string>[];\n /** Whether to show style selection */\n showStyleSelect: boolean;\n}\n\n/**\n * Run the cite flow (reference selection → style selection if needed)\n *\n * This is the main entry point for interactive cite command.\n */\nexport async function runCiteFlow(options: RunCiteFlowOptions): Promise<CiteFlowResult> {\n const { allReferences, searchFn, config, styleOptions, showStyleSelect } = options;\n\n // Convert references to choices\n const choices = allReferences.map(toChoice);\n\n // Calculate effective visible count\n const effectiveLimit = calculateEffectiveLimit(config.limit);\n\n // Create filter function using the provided search function\n const filterFn = (query: string, choices: Choice<CslItem>[]): Choice<CslItem>[] => {\n if (!query.trim()) return choices;\n\n const results = searchFn(query);\n return results.map((r) => toChoice(r.reference));\n };\n\n // Default sort option\n const defaultSort: SortOption = \"updated-desc\";\n\n // Create a promise to capture the result\n return new Promise<CiteFlowResult>((resolve) => {\n let flowResult: CiteFlowResult = {\n identifiers: [],\n cancelled: true,\n };\n\n const handleComplete = (result: CiteFlowResult): void => {\n flowResult = result;\n };\n\n const handleCancel = (): void => {\n flowResult = {\n identifiers: [],\n cancelled: true,\n };\n };\n\n // Render the Ink app (single render for entire flow)\n const { waitUntilExit } = render(\n createElement(CiteFlowApp, {\n choices,\n filterFn,\n visibleCount: effectiveLimit,\n defaultSort,\n styleOptions,\n showStyleSelect,\n onComplete: handleComplete,\n onCancel: handleCancel,\n })\n );\n\n // Wait for the app to exit, then resolve\n waitUntilExit()\n .then(() => {\n restoreStdinAfterInk();\n resolve(flowResult);\n })\n .catch(() => {\n restoreStdinAfterInk();\n resolve({\n identifiers: [],\n cancelled: true,\n });\n });\n });\n}\n"],"names":["extractYear","extractPublishedDate","extractUpdatedDate","extractCreatedDate","formatIdentifiers","formatType","toChoice","choices"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a } from "./index-
|
|
2
|
-
import { d, g, l, o, s } from "./index-
|
|
1
|
+
import { a } from "./index-BK3hTiKR.js";
|
|
2
|
+
import { d, g, l, o, s } from "./index-DOvEusHb.js";
|
|
3
3
|
export {
|
|
4
4
|
a as addAttachment,
|
|
5
5
|
d as detachAttachment,
|
|
@@ -8,4 +8,4 @@ export {
|
|
|
8
8
|
o as openAttachment,
|
|
9
9
|
s as syncAttachments
|
|
10
10
|
};
|
|
11
|
-
//# sourceMappingURL=index-
|
|
11
|
+
//# sourceMappingURL=index-D7eiOplw.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-D7eiOplw.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;"}
|
|
@@ -5,7 +5,7 @@ import { promises, readFileSync, existsSync, writeFileSync, mkdirSync } from "no
|
|
|
5
5
|
import * as os from "node:os";
|
|
6
6
|
import * as path from "node:path";
|
|
7
7
|
import path__default, { join, basename, dirname } from "node:path";
|
|
8
|
-
import { n as normalizePathForOutput, d as deleteDirectoryIfEmpty, p as parseFilename, i as isReservedRole, e as ensureDirectory, a as addAttachment, R as RESERVED_ROLES, g as generateFilename, b as findFulltextFiles, c as findFulltextFile, h as extensionToFormat, j as fulltextAttach, k as fulltextGet, l as fulltextDiscover, m as fulltextFetch, o as fulltextConvert, B as BUILTIN_STYLES,
|
|
8
|
+
import { n as normalizePathForOutput, d as deleteDirectoryIfEmpty, p as parseFilename, i as isReservedRole, e as ensureDirectory, a as addAttachment, R as RESERVED_ROLES, g as generateFilename, b as findFulltextFiles, c as findFulltextFile, h as extensionToFormat, j as fulltextAttach, k as fulltextGet, l as fulltextDiscover, m as fulltextFetch, o as fulltextConvert, q as getExtension, B as BUILTIN_STYLES, r as getFulltextAttachmentTypes, s as startServerWithFileWatcher } from "./index-BK3hTiKR.js";
|
|
9
9
|
import { readFile, unlink, stat, readdir, rename, mkdir } from "node:fs/promises";
|
|
10
10
|
import { o as openWithSystemApp, l as loadConfig, e as getDefaultCurrentDirConfigFilename, h as getDefaultUserConfigPath } from "./loader-BHvcats5.js";
|
|
11
11
|
import { spawn, spawnSync } from "node:child_process";
|
|
@@ -19,7 +19,7 @@ import "@citation-js/plugin-csl";
|
|
|
19
19
|
import { ZodOptional as ZodOptional$2, z } from "zod";
|
|
20
20
|
import { serve } from "@hono/node-server";
|
|
21
21
|
const name = "@ncukondo/reference-manager";
|
|
22
|
-
const version$1 = "0.
|
|
22
|
+
const version$1 = "0.22.0";
|
|
23
23
|
const description$1 = "A local reference management tool using CSL-JSON as the single source of truth";
|
|
24
24
|
const packageJson = {
|
|
25
25
|
name,
|
|
@@ -904,15 +904,15 @@ class OperationsLibrary {
|
|
|
904
904
|
}
|
|
905
905
|
// High-level operations
|
|
906
906
|
async search(options) {
|
|
907
|
-
const { searchReferences } = await import("./index-
|
|
907
|
+
const { searchReferences } = await import("./index-BK3hTiKR.js").then((n) => n.z);
|
|
908
908
|
return searchReferences(this.library, options);
|
|
909
909
|
}
|
|
910
910
|
async list(options) {
|
|
911
|
-
const { listReferences } = await import("./index-
|
|
911
|
+
const { listReferences } = await import("./index-BK3hTiKR.js").then((n) => n.y);
|
|
912
912
|
return listReferences(this.library, options ?? {});
|
|
913
913
|
}
|
|
914
914
|
async cite(options) {
|
|
915
|
-
const { citeReferences } = await import("./index-
|
|
915
|
+
const { citeReferences } = await import("./index-BK3hTiKR.js").then((n) => n.x);
|
|
916
916
|
const defaultStyle = options.defaultStyle ?? this.citationConfig?.defaultStyle;
|
|
917
917
|
const cslDirectory = options.cslDirectory ?? this.citationConfig?.cslDirectory;
|
|
918
918
|
const mergedOptions = {
|
|
@@ -923,32 +923,32 @@ class OperationsLibrary {
|
|
|
923
923
|
return citeReferences(this.library, mergedOptions);
|
|
924
924
|
}
|
|
925
925
|
async import(inputs, options) {
|
|
926
|
-
const { addReferences } = await import("./index-
|
|
926
|
+
const { addReferences } = await import("./index-BK3hTiKR.js").then((n) => n.w);
|
|
927
927
|
return addReferences(inputs, this.library, options ?? {});
|
|
928
928
|
}
|
|
929
929
|
// Attachment operations
|
|
930
930
|
async attachAdd(options) {
|
|
931
|
-
const { addAttachment: addAttachment2 } = await import("./index-
|
|
931
|
+
const { addAttachment: addAttachment2 } = await import("./index-D7eiOplw.js");
|
|
932
932
|
return addAttachment2(this.library, options);
|
|
933
933
|
}
|
|
934
934
|
async attachList(options) {
|
|
935
|
-
const { listAttachments: listAttachments2 } = await import("./index-
|
|
935
|
+
const { listAttachments: listAttachments2 } = await import("./index-D7eiOplw.js");
|
|
936
936
|
return listAttachments2(this.library, options);
|
|
937
937
|
}
|
|
938
938
|
async attachGet(options) {
|
|
939
|
-
const { getAttachment: getAttachment2 } = await import("./index-
|
|
939
|
+
const { getAttachment: getAttachment2 } = await import("./index-D7eiOplw.js");
|
|
940
940
|
return getAttachment2(this.library, options);
|
|
941
941
|
}
|
|
942
942
|
async attachDetach(options) {
|
|
943
|
-
const { detachAttachment: detachAttachment2 } = await import("./index-
|
|
943
|
+
const { detachAttachment: detachAttachment2 } = await import("./index-D7eiOplw.js");
|
|
944
944
|
return detachAttachment2(this.library, options);
|
|
945
945
|
}
|
|
946
946
|
async attachSync(options) {
|
|
947
|
-
const { syncAttachments: syncAttachments2 } = await import("./index-
|
|
947
|
+
const { syncAttachments: syncAttachments2 } = await import("./index-D7eiOplw.js");
|
|
948
948
|
return syncAttachments2(this.library, options);
|
|
949
949
|
}
|
|
950
950
|
async attachOpen(options) {
|
|
951
|
-
const { openAttachment: openAttachment2 } = await import("./index-
|
|
951
|
+
const { openAttachment: openAttachment2 } = await import("./index-D7eiOplw.js");
|
|
952
952
|
return openAttachment2(this.library, options);
|
|
953
953
|
}
|
|
954
954
|
}
|
|
@@ -1792,7 +1792,7 @@ function getAttachExitCode(result) {
|
|
|
1792
1792
|
}
|
|
1793
1793
|
async function executeInteractiveSelect$2(context, config2) {
|
|
1794
1794
|
const { withAlternateScreen: withAlternateScreen2 } = await Promise.resolve().then(() => alternateScreen);
|
|
1795
|
-
const { selectReferencesOrExit } = await import("./reference-select-
|
|
1795
|
+
const { selectReferencesOrExit } = await import("./reference-select-DTqhevya.js");
|
|
1796
1796
|
const allReferences = await context.library.getAll();
|
|
1797
1797
|
const identifiers = await withAlternateScreen2(
|
|
1798
1798
|
() => selectReferencesOrExit(allReferences, { multiSelect: false }, config2.cli.tui)
|
|
@@ -2340,8 +2340,8 @@ function getCiteExitCode(result) {
|
|
|
2340
2340
|
}
|
|
2341
2341
|
async function executeInteractiveCite(options, context, config2) {
|
|
2342
2342
|
const { withAlternateScreen: withAlternateScreen2 } = await Promise.resolve().then(() => alternateScreen);
|
|
2343
|
-
const { runCiteFlow } = await import("./index-
|
|
2344
|
-
const { buildStyleChoices, listCustomStyles } = await import("./style-select-
|
|
2343
|
+
const { runCiteFlow } = await import("./index-BvIfOciH.js");
|
|
2344
|
+
const { buildStyleChoices, listCustomStyles } = await import("./style-select-CXclvgJO.js");
|
|
2345
2345
|
const { search } = await import("./file-watcher-CrsNHUpz.js").then((n) => n.z);
|
|
2346
2346
|
const { tokenize } = await import("./file-watcher-CrsNHUpz.js").then((n) => n.y);
|
|
2347
2347
|
const { checkTTY } = await import("./tty-BMyaEOhX.js");
|
|
@@ -6923,7 +6923,7 @@ function formatEditOutput(result) {
|
|
|
6923
6923
|
}
|
|
6924
6924
|
async function executeInteractiveEdit(options, context, config2) {
|
|
6925
6925
|
const { withAlternateScreen: withAlternateScreen2 } = await Promise.resolve().then(() => alternateScreen);
|
|
6926
|
-
const { selectReferencesOrExit } = await import("./reference-select-
|
|
6926
|
+
const { selectReferencesOrExit } = await import("./reference-select-DTqhevya.js");
|
|
6927
6927
|
const allReferences = await context.library.getAll();
|
|
6928
6928
|
const identifiers = await withAlternateScreen2(
|
|
6929
6929
|
() => selectReferencesOrExit(allReferences, { multiSelect: true }, config2.cli.tui)
|
|
@@ -10460,7 +10460,7 @@ function getFulltextExitCode(result) {
|
|
|
10460
10460
|
}
|
|
10461
10461
|
async function executeInteractiveSelect$1(context, config2) {
|
|
10462
10462
|
const { withAlternateScreen: withAlternateScreen2 } = await Promise.resolve().then(() => alternateScreen);
|
|
10463
|
-
const { selectReferencesOrExit } = await import("./reference-select-
|
|
10463
|
+
const { selectReferencesOrExit } = await import("./reference-select-DTqhevya.js");
|
|
10464
10464
|
const allReferences = await context.library.getAll();
|
|
10465
10465
|
const identifiers = await withAlternateScreen2(
|
|
10466
10466
|
() => selectReferencesOrExit(allReferences, { multiSelect: false }, config2.cli.tui)
|
|
@@ -10792,6 +10792,26 @@ const fulltext = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProp
|
|
|
10792
10792
|
handleFulltextGetAction,
|
|
10793
10793
|
handleFulltextOpenAction
|
|
10794
10794
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
10795
|
+
function buildResourceIndicators(item) {
|
|
10796
|
+
const icons = [];
|
|
10797
|
+
const attachments = item.custom?.attachments;
|
|
10798
|
+
const fulltextFiles = findFulltextFiles(attachments);
|
|
10799
|
+
const hasFulltextPdf = fulltextFiles.some(
|
|
10800
|
+
(f) => extensionToFormat(getExtension(f.filename)) === "pdf"
|
|
10801
|
+
);
|
|
10802
|
+
if (hasFulltextPdf) icons.push("📄");
|
|
10803
|
+
const hasFulltextMd = fulltextFiles.some(
|
|
10804
|
+
(f) => extensionToFormat(getExtension(f.filename)) === "markdown"
|
|
10805
|
+
);
|
|
10806
|
+
if (hasFulltextMd) icons.push("📝");
|
|
10807
|
+
const allFiles = attachments?.files ?? [];
|
|
10808
|
+
const hasOtherAttachments = allFiles.length > fulltextFiles.length;
|
|
10809
|
+
if (hasOtherAttachments) icons.push("📎");
|
|
10810
|
+
if (item.URL) icons.push("🔗");
|
|
10811
|
+
const tags = item.custom?.tags;
|
|
10812
|
+
if (Array.isArray(tags) && tags.length > 0) icons.push("🏷");
|
|
10813
|
+
return icons.join("");
|
|
10814
|
+
}
|
|
10795
10815
|
function formatAuthor(author) {
|
|
10796
10816
|
const family = author.family || "";
|
|
10797
10817
|
const givenInitial = author.given ? `${author.given.charAt(0)}.` : "";
|
|
@@ -10824,6 +10844,10 @@ function formatSingleReference(item) {
|
|
|
10824
10844
|
}
|
|
10825
10845
|
const uuid2 = item.custom?.uuid || "(no uuid)";
|
|
10826
10846
|
lines.push(` UUID: ${uuid2}`);
|
|
10847
|
+
const indicators = buildResourceIndicators(item);
|
|
10848
|
+
if (indicators) {
|
|
10849
|
+
lines.push(` ${indicators}`);
|
|
10850
|
+
}
|
|
10827
10851
|
return lines.join("\n");
|
|
10828
10852
|
}
|
|
10829
10853
|
function formatPretty(items2) {
|
|
@@ -31730,7 +31754,7 @@ async function mcpStart(options) {
|
|
|
31730
31754
|
async function executeRemove(options, context) {
|
|
31731
31755
|
const { identifier, idType = "id", fulltextDirectory, deleteFulltext = false } = options;
|
|
31732
31756
|
if (context.mode === "local" && deleteFulltext && fulltextDirectory) {
|
|
31733
|
-
const { removeReference } = await import("./index-
|
|
31757
|
+
const { removeReference } = await import("./index-BK3hTiKR.js").then((n) => n.v);
|
|
31734
31758
|
return removeReference(context.library, {
|
|
31735
31759
|
identifier,
|
|
31736
31760
|
idType,
|
|
@@ -31785,7 +31809,7 @@ Continue?`;
|
|
|
31785
31809
|
}
|
|
31786
31810
|
async function executeInteractiveRemove(context, config2) {
|
|
31787
31811
|
const { withAlternateScreen: withAlternateScreen2 } = await Promise.resolve().then(() => alternateScreen);
|
|
31788
|
-
const { selectReferenceItemsOrExit } = await import("./reference-select-
|
|
31812
|
+
const { selectReferenceItemsOrExit } = await import("./reference-select-DTqhevya.js");
|
|
31789
31813
|
const allReferences = await context.library.getAll();
|
|
31790
31814
|
const selectedItems = await withAlternateScreen2(
|
|
31791
31815
|
() => selectReferenceItemsOrExit(allReferences, { multiSelect: false }, config2.cli.tui)
|
|
@@ -32010,7 +32034,7 @@ async function executeInteractiveSearch(options, context, config2) {
|
|
|
32010
32034
|
validateInteractiveOptions(options);
|
|
32011
32035
|
const { checkTTY } = await import("./tty-BMyaEOhX.js");
|
|
32012
32036
|
const { withAlternateScreen: withAlternateScreen2 } = await Promise.resolve().then(() => alternateScreen);
|
|
32013
|
-
const { runSearchFlow } = await import("./index-
|
|
32037
|
+
const { runSearchFlow } = await import("./index-BvIfOciH.js");
|
|
32014
32038
|
const { search } = await import("./file-watcher-CrsNHUpz.js").then((n) => n.z);
|
|
32015
32039
|
const { tokenize } = await import("./file-watcher-CrsNHUpz.js").then((n) => n.y);
|
|
32016
32040
|
checkTTY();
|
|
@@ -32029,7 +32053,7 @@ async function executeInteractiveSearch(options, context, config2) {
|
|
|
32029
32053
|
})
|
|
32030
32054
|
);
|
|
32031
32055
|
if (result.selectedItems && !result.cancelled) {
|
|
32032
|
-
const { isSideEffectAction } = await import("./action-menu-
|
|
32056
|
+
const { isSideEffectAction } = await import("./action-menu-B1DCdkkp.js");
|
|
32033
32057
|
if (isSideEffectAction(result.action)) {
|
|
32034
32058
|
await executeSideEffectAction(result.action, result.selectedItems, context, config2);
|
|
32035
32059
|
return { output: "", cancelled: false, action: result.action };
|
|
@@ -32432,7 +32456,7 @@ function formatUpdateOutput(result, identifier) {
|
|
|
32432
32456
|
}
|
|
32433
32457
|
async function executeInteractiveUpdate(context, config2) {
|
|
32434
32458
|
const { withAlternateScreen: withAlternateScreen2 } = await Promise.resolve().then(() => alternateScreen);
|
|
32435
|
-
const { selectReferencesOrExit } = await import("./reference-select-
|
|
32459
|
+
const { selectReferencesOrExit } = await import("./reference-select-DTqhevya.js");
|
|
32436
32460
|
const allReferences = await context.library.getAll();
|
|
32437
32461
|
const identifiers = await withAlternateScreen2(
|
|
32438
32462
|
() => selectReferencesOrExit(allReferences, { multiSelect: false }, config2.cli.tui)
|
|
@@ -32727,7 +32751,7 @@ function getUrlExitCode(result) {
|
|
|
32727
32751
|
}
|
|
32728
32752
|
async function executeInteractiveSelect(context, config2) {
|
|
32729
32753
|
const { withAlternateScreen: withAlternateScreen2 } = await Promise.resolve().then(() => alternateScreen);
|
|
32730
|
-
const { selectReferencesOrExit } = await import("./reference-select-
|
|
32754
|
+
const { selectReferencesOrExit } = await import("./reference-select-DTqhevya.js");
|
|
32731
32755
|
const allReferences = await context.library.getAll();
|
|
32732
32756
|
const identifiers = await withAlternateScreen2(
|
|
32733
32757
|
() => selectReferencesOrExit(allReferences, { multiSelect: false }, config2.cli.tui)
|
|
@@ -33230,7 +33254,7 @@ function shouldAutoFetch(cliFlag, configEnabled) {
|
|
|
33230
33254
|
return configEnabled;
|
|
33231
33255
|
}
|
|
33232
33256
|
async function performAutoFetch(addedItems, context, config2) {
|
|
33233
|
-
const { fulltextFetch: fulltextFetch2 } = await import("./index-
|
|
33257
|
+
const { fulltextFetch: fulltextFetch2 } = await import("./index-BK3hTiKR.js").then((n) => n.u);
|
|
33234
33258
|
const fetchResults = await autoFetchFulltext(addedItems, context, {
|
|
33235
33259
|
fulltextConfig: config2.fulltext,
|
|
33236
33260
|
fulltextDirectory: config2.attachments.directory,
|
|
@@ -33493,6 +33517,7 @@ async function main(argv) {
|
|
|
33493
33517
|
export {
|
|
33494
33518
|
Select as S,
|
|
33495
33519
|
stringify as a,
|
|
33520
|
+
buildResourceIndicators as b,
|
|
33496
33521
|
createProgram as c,
|
|
33497
33522
|
detachAttachment as d,
|
|
33498
33523
|
formatBibtex as f,
|
|
@@ -33504,4 +33529,4 @@ export {
|
|
|
33504
33529
|
restoreStdinAfterInk as r,
|
|
33505
33530
|
syncAttachments as s
|
|
33506
33531
|
};
|
|
33507
|
-
//# sourceMappingURL=index-
|
|
33532
|
+
//# sourceMappingURL=index-DOvEusHb.js.map
|