@luckydraw/cumulus 0.5.1
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/README.md +148 -0
- package/dist/cli/cumulus.d.ts +3 -0
- package/dist/cli/cumulus.d.ts.map +1 -0
- package/dist/cli/cumulus.js +233 -0
- package/dist/cli/cumulus.js.map +1 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +43 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/config.d.ts +86 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +241 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/content-detector.d.ts +46 -0
- package/dist/lib/content-detector.d.ts.map +1 -0
- package/dist/lib/content-detector.js +359 -0
- package/dist/lib/content-detector.js.map +1 -0
- package/dist/lib/content-store.d.ts +255 -0
- package/dist/lib/content-store.d.ts.map +1 -0
- package/dist/lib/content-store.js +955 -0
- package/dist/lib/content-store.js.map +1 -0
- package/dist/lib/context-budget.d.ts +83 -0
- package/dist/lib/context-budget.d.ts.map +1 -0
- package/dist/lib/context-budget.js +101 -0
- package/dist/lib/context-budget.js.map +1 -0
- package/dist/lib/embeddings.d.ts +64 -0
- package/dist/lib/embeddings.d.ts.map +1 -0
- package/dist/lib/embeddings.js +176 -0
- package/dist/lib/embeddings.js.map +1 -0
- package/dist/lib/history.d.ts +120 -0
- package/dist/lib/history.d.ts.map +1 -0
- package/dist/lib/history.js +205 -0
- package/dist/lib/history.js.map +1 -0
- package/dist/lib/image-utils.d.ts +41 -0
- package/dist/lib/image-utils.d.ts.map +1 -0
- package/dist/lib/image-utils.js +288 -0
- package/dist/lib/image-utils.js.map +1 -0
- package/dist/lib/migrate.d.ts +35 -0
- package/dist/lib/migrate.d.ts.map +1 -0
- package/dist/lib/migrate.js +196 -0
- package/dist/lib/migrate.js.map +1 -0
- package/dist/lib/retriever.d.ts +56 -0
- package/dist/lib/retriever.d.ts.map +1 -0
- package/dist/lib/retriever.js +644 -0
- package/dist/lib/retriever.js.map +1 -0
- package/dist/lib/revert.d.ts +23 -0
- package/dist/lib/revert.d.ts.map +1 -0
- package/dist/lib/revert.js +75 -0
- package/dist/lib/revert.js.map +1 -0
- package/dist/lib/session.d.ts +65 -0
- package/dist/lib/session.d.ts.map +1 -0
- package/dist/lib/session.js +289 -0
- package/dist/lib/session.js.map +1 -0
- package/dist/lib/snapshots.d.ts +39 -0
- package/dist/lib/snapshots.d.ts.map +1 -0
- package/dist/lib/snapshots.js +99 -0
- package/dist/lib/snapshots.js.map +1 -0
- package/dist/lib/stream-processor.d.ts +149 -0
- package/dist/lib/stream-processor.d.ts.map +1 -0
- package/dist/lib/stream-processor.js +389 -0
- package/dist/lib/stream-processor.js.map +1 -0
- package/dist/lib/summarizer.d.ts +67 -0
- package/dist/lib/summarizer.d.ts.map +1 -0
- package/dist/lib/summarizer.js +213 -0
- package/dist/lib/summarizer.js.map +1 -0
- package/dist/mcp/index.d.ts +3 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +16 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/proxy.d.ts +19 -0
- package/dist/mcp/proxy.d.ts.map +1 -0
- package/dist/mcp/proxy.js +120 -0
- package/dist/mcp/proxy.js.map +1 -0
- package/dist/mcp/server.d.ts +6 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +29 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/shared-server.d.ts +21 -0
- package/dist/mcp/shared-server.d.ts.map +1 -0
- package/dist/mcp/shared-server.js +210 -0
- package/dist/mcp/shared-server.js.map +1 -0
- package/dist/mcp/tool-handler.d.ts +20 -0
- package/dist/mcp/tool-handler.d.ts.map +1 -0
- package/dist/mcp/tool-handler.js +1405 -0
- package/dist/mcp/tool-handler.js.map +1 -0
- package/dist/tui/components/App.d.ts +11 -0
- package/dist/tui/components/App.d.ts.map +1 -0
- package/dist/tui/components/App.js +607 -0
- package/dist/tui/components/App.js.map +1 -0
- package/dist/tui/components/DebugContextView.d.ts +13 -0
- package/dist/tui/components/DebugContextView.d.ts.map +1 -0
- package/dist/tui/components/DebugContextView.js +78 -0
- package/dist/tui/components/DebugContextView.js.map +1 -0
- package/dist/tui/components/IncludeMenu.d.ts +12 -0
- package/dist/tui/components/IncludeMenu.d.ts.map +1 -0
- package/dist/tui/components/IncludeMenu.js +127 -0
- package/dist/tui/components/IncludeMenu.js.map +1 -0
- package/dist/tui/components/InputArea.d.ts +27 -0
- package/dist/tui/components/InputArea.d.ts.map +1 -0
- package/dist/tui/components/InputArea.js +366 -0
- package/dist/tui/components/InputArea.js.map +1 -0
- package/dist/tui/components/MarkdownText.d.ts +38 -0
- package/dist/tui/components/MarkdownText.d.ts.map +1 -0
- package/dist/tui/components/MarkdownText.js +234 -0
- package/dist/tui/components/MarkdownText.js.map +1 -0
- package/dist/tui/components/MessageBubble.d.ts +11 -0
- package/dist/tui/components/MessageBubble.d.ts.map +1 -0
- package/dist/tui/components/MessageBubble.js +16 -0
- package/dist/tui/components/MessageBubble.js.map +1 -0
- package/dist/tui/components/MessageHistory.d.ts +11 -0
- package/dist/tui/components/MessageHistory.d.ts.map +1 -0
- package/dist/tui/components/MessageHistory.js +12 -0
- package/dist/tui/components/MessageHistory.js.map +1 -0
- package/dist/tui/components/RevertMenu.d.ts +17 -0
- package/dist/tui/components/RevertMenu.d.ts.map +1 -0
- package/dist/tui/components/RevertMenu.js +144 -0
- package/dist/tui/components/RevertMenu.js.map +1 -0
- package/dist/tui/components/StatusBar.d.ts +14 -0
- package/dist/tui/components/StatusBar.d.ts.map +1 -0
- package/dist/tui/components/StatusBar.js +13 -0
- package/dist/tui/components/StatusBar.js.map +1 -0
- package/dist/tui/components/StreamingResponse.d.ts +15 -0
- package/dist/tui/components/StreamingResponse.d.ts.map +1 -0
- package/dist/tui/components/StreamingResponse.js +52 -0
- package/dist/tui/components/StreamingResponse.js.map +1 -0
- package/dist/tui/hooks/useAppState.d.ts +147 -0
- package/dist/tui/hooks/useAppState.d.ts.map +1 -0
- package/dist/tui/hooks/useAppState.js +110 -0
- package/dist/tui/hooks/useAppState.js.map +1 -0
- package/dist/tui/hooks/useClaudeProcess.d.ts +19 -0
- package/dist/tui/hooks/useClaudeProcess.d.ts.map +1 -0
- package/dist/tui/hooks/useClaudeProcess.js +185 -0
- package/dist/tui/hooks/useClaudeProcess.js.map +1 -0
- package/dist/tui/index.d.ts +10 -0
- package/dist/tui/index.d.ts.map +1 -0
- package/dist/tui/index.js +11 -0
- package/dist/tui/index.js.map +1 -0
- package/dist/tui/utils/streamParser.d.ts +31 -0
- package/dist/tui/utils/streamParser.d.ts.map +1 -0
- package/dist/tui/utils/streamParser.js +63 -0
- package/dist/tui/utils/streamParser.js.map +1 -0
- package/package.json +94 -0
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Unified text input component.
|
|
4
|
+
* Normal mode: type to input buffer, Enter submits
|
|
5
|
+
* Processing mode: same input buffer with full editing, Enter interrupts Claude
|
|
6
|
+
* Supports Ctrl+V for clipboard image paste, Shift+Return for newlines,
|
|
7
|
+
* and correct multi-line paste handling.
|
|
8
|
+
*
|
|
9
|
+
* Uses refs for buffer/cursor to ensure synchronous correctness when multiple
|
|
10
|
+
* useInput calls fire within the same React batch (e.g. during paste).
|
|
11
|
+
*/
|
|
12
|
+
import { Box, Text, useInput, useStdout } from 'ink';
|
|
13
|
+
import { useState, useCallback, useMemo, useEffect, useRef } from 'react';
|
|
14
|
+
import { readClipboardImage } from '../../lib/image-utils.js';
|
|
15
|
+
/**
|
|
16
|
+
* Find the start of the previous word from the given position.
|
|
17
|
+
* Skips trailing whitespace, then skips the word characters.
|
|
18
|
+
*/
|
|
19
|
+
function findPrevWordBoundary(text, pos) {
|
|
20
|
+
let i = pos;
|
|
21
|
+
// Skip whitespace before cursor
|
|
22
|
+
while (i > 0 && text[i - 1] === ' ')
|
|
23
|
+
i--;
|
|
24
|
+
// Skip word characters
|
|
25
|
+
while (i > 0 && text[i - 1] !== ' ')
|
|
26
|
+
i--;
|
|
27
|
+
return i;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Build the list of visual rows from the input buffer, accounting for both
|
|
31
|
+
* explicit newlines and terminal soft-wrapping.
|
|
32
|
+
*/
|
|
33
|
+
function buildVisualRows(text, effectiveWidth) {
|
|
34
|
+
const logicalLines = text.split('\n');
|
|
35
|
+
const rows = [];
|
|
36
|
+
let flatOffset = 0;
|
|
37
|
+
for (let i = 0; i < logicalLines.length; i++) {
|
|
38
|
+
const line = logicalLines[i];
|
|
39
|
+
const wrapped = wrapLine(line, effectiveWidth);
|
|
40
|
+
for (const chunk of wrapped) {
|
|
41
|
+
rows.push({ text: chunk, flatStart: flatOffset, width: chunk.length });
|
|
42
|
+
flatOffset += chunk.length;
|
|
43
|
+
}
|
|
44
|
+
// Account for the '\n' between logical lines
|
|
45
|
+
if (i < logicalLines.length - 1) {
|
|
46
|
+
flatOffset += 1; // the newline character
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return rows;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Find which visual row the cursor is on, and the column within that row.
|
|
53
|
+
*/
|
|
54
|
+
function cursorToVisualRowCol(rows, cursorPos) {
|
|
55
|
+
for (let i = 0; i < rows.length; i++) {
|
|
56
|
+
const row = rows[i];
|
|
57
|
+
const rowEnd = row.flatStart + row.width;
|
|
58
|
+
const isLast = i === rows.length - 1;
|
|
59
|
+
// Cursor belongs to this row if it's within [flatStart, flatStart+width)
|
|
60
|
+
// or at the end of the last row (inclusive)
|
|
61
|
+
if (cursorPos >= row.flatStart && (isLast ? cursorPos <= rowEnd : cursorPos < rowEnd)) {
|
|
62
|
+
return { rowIdx: i, col: cursorPos - row.flatStart };
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
// Fallback: end of last row
|
|
66
|
+
const last = rows[rows.length - 1];
|
|
67
|
+
return { rowIdx: rows.length - 1, col: last.width };
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Convert a visual row index and column back to a flat cursor position.
|
|
71
|
+
*/
|
|
72
|
+
function visualRowColToFlat(rows, rowIdx, col) {
|
|
73
|
+
const row = rows[rowIdx];
|
|
74
|
+
return row.flatStart + Math.min(col, row.width);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Split a logical line into visual rows based on the available terminal width.
|
|
78
|
+
* Returns an array of substrings, each fitting within `width` columns.
|
|
79
|
+
*/
|
|
80
|
+
function wrapLine(line, width) {
|
|
81
|
+
if (width <= 0 || line.length <= width)
|
|
82
|
+
return [line];
|
|
83
|
+
const rows = [];
|
|
84
|
+
for (let i = 0; i < line.length; i += width) {
|
|
85
|
+
rows.push(line.slice(i, i + width));
|
|
86
|
+
}
|
|
87
|
+
if (rows.length === 0)
|
|
88
|
+
rows.push('');
|
|
89
|
+
return rows;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Find the end of the next word from the given position.
|
|
93
|
+
* Skips leading whitespace, then skips the word characters.
|
|
94
|
+
*/
|
|
95
|
+
function findNextWordBoundary(text, pos) {
|
|
96
|
+
let i = pos;
|
|
97
|
+
// Skip word characters
|
|
98
|
+
while (i < text.length && text[i] !== ' ')
|
|
99
|
+
i++;
|
|
100
|
+
// Skip whitespace after word
|
|
101
|
+
while (i < text.length && text[i] === ' ')
|
|
102
|
+
i++;
|
|
103
|
+
return i;
|
|
104
|
+
}
|
|
105
|
+
export function InputArea({ isProcessing, onSubmit, onInterjection, isOverlayActive = false, contentBasePath, commands = [], }) {
|
|
106
|
+
const { stdout } = useStdout();
|
|
107
|
+
const terminalWidth = stdout?.columns || 80;
|
|
108
|
+
const prefixWidth = 2; // '> ' or ' '
|
|
109
|
+
const effectiveWidth = terminalWidth - prefixWidth;
|
|
110
|
+
const [inputBuffer, setInputBuffer] = useState('');
|
|
111
|
+
const [cursorPos, setCursorPos] = useState(0);
|
|
112
|
+
const [attachedImages, setAttachedImages] = useState([]);
|
|
113
|
+
const [pasteInProgress, setPasteInProgress] = useState(false);
|
|
114
|
+
const [commandMenuIndex, setCommandMenuIndex] = useState(0);
|
|
115
|
+
// Refs for synchronous state access within batched useInput calls (paste).
|
|
116
|
+
// Without these, multiple useInput calls in the same tick all see the same
|
|
117
|
+
// stale cursorPos/inputBuffer from the last render closure.
|
|
118
|
+
const bufferRef = useRef('');
|
|
119
|
+
const cursorRef = useRef(0);
|
|
120
|
+
// Batch counter: counts how many useInput calls fire in the current synchronous
|
|
121
|
+
// tick. If > 1, we're in a paste and treat Return as newline, not submit.
|
|
122
|
+
const batchCountRef = useRef(0);
|
|
123
|
+
// Ref for attached images (needed in handler without stale closure)
|
|
124
|
+
const imagesRef = useRef([]);
|
|
125
|
+
useEffect(() => {
|
|
126
|
+
imagesRef.current = attachedImages;
|
|
127
|
+
}, [attachedImages]);
|
|
128
|
+
const isCommandMode = inputBuffer.startsWith('/') && !isProcessing && commands.length > 0;
|
|
129
|
+
const filteredCommands = useMemo(() => {
|
|
130
|
+
if (!isCommandMode)
|
|
131
|
+
return [];
|
|
132
|
+
const prefix = inputBuffer.toLowerCase();
|
|
133
|
+
return commands.filter(cmd => cmd.name.toLowerCase().startsWith(prefix));
|
|
134
|
+
}, [isCommandMode, inputBuffer, commands]);
|
|
135
|
+
// Reset menu index when input changes
|
|
136
|
+
useEffect(() => {
|
|
137
|
+
setCommandMenuIndex(0);
|
|
138
|
+
}, [inputBuffer]);
|
|
139
|
+
const handleInput = useCallback((input, key) => {
|
|
140
|
+
// --- Paste detection via batch counting ---
|
|
141
|
+
// All useInput calls from a single stdin data event (paste) fire synchronously.
|
|
142
|
+
// The first call schedules a microtask to reset the counter after the sync block.
|
|
143
|
+
batchCountRef.current++;
|
|
144
|
+
if (batchCountRef.current === 1) {
|
|
145
|
+
Promise.resolve().then(() => {
|
|
146
|
+
batchCountRef.current = 0;
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
const isPasting = batchCountRef.current > 1;
|
|
150
|
+
// Read current state from refs (always up-to-date, even mid-batch)
|
|
151
|
+
const buf = bufferRef.current;
|
|
152
|
+
const cur = cursorRef.current;
|
|
153
|
+
// Helper: update buffer + cursor synchronously (via refs) and schedule React state update
|
|
154
|
+
const updateBufferAndCursor = (newBuf, newCur) => {
|
|
155
|
+
bufferRef.current = newBuf;
|
|
156
|
+
cursorRef.current = newCur;
|
|
157
|
+
setInputBuffer(newBuf);
|
|
158
|
+
setCursorPos(newCur);
|
|
159
|
+
};
|
|
160
|
+
const insertText = (text) => {
|
|
161
|
+
updateBufferAndCursor(buf.slice(0, cur) + text + buf.slice(cur), cur + text.length);
|
|
162
|
+
};
|
|
163
|
+
// Handle Ctrl+V / Cmd+V for clipboard image paste (only in normal mode)
|
|
164
|
+
if ((key.ctrl || key.meta) && input === 'v' && !isProcessing && contentBasePath) {
|
|
165
|
+
if (pasteInProgress)
|
|
166
|
+
return;
|
|
167
|
+
setPasteInProgress(true);
|
|
168
|
+
readClipboardImage(contentBasePath)
|
|
169
|
+
.then(image => {
|
|
170
|
+
if (image) {
|
|
171
|
+
setAttachedImages(prev => [...prev, image]);
|
|
172
|
+
}
|
|
173
|
+
// If no image found, clipboard text is handled by the terminal naturally
|
|
174
|
+
})
|
|
175
|
+
.catch(err => {
|
|
176
|
+
console.error('[InputArea] Clipboard image read failed:', err);
|
|
177
|
+
})
|
|
178
|
+
.finally(() => {
|
|
179
|
+
setPasteInProgress(false);
|
|
180
|
+
});
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
// Escape: clear input when in command mode
|
|
184
|
+
if (key.escape) {
|
|
185
|
+
// Compute command mode from ref for freshness
|
|
186
|
+
const isCmd = bufferRef.current.startsWith('/') && !isProcessing && commands.length > 0;
|
|
187
|
+
if (isCmd) {
|
|
188
|
+
updateBufferAndCursor('', 0);
|
|
189
|
+
}
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
// Up/Down arrows: navigate command menu when in command mode, or move cursor between visual rows
|
|
193
|
+
if (key.upArrow) {
|
|
194
|
+
const isCmd = buf.startsWith('/') && !isProcessing && commands.length > 0;
|
|
195
|
+
const cmds = isCmd
|
|
196
|
+
? commands.filter(c => c.name.toLowerCase().startsWith(buf.toLowerCase()))
|
|
197
|
+
: [];
|
|
198
|
+
if (isCmd && cmds.length > 0) {
|
|
199
|
+
setCommandMenuIndex(prev => (prev <= 0 ? cmds.length - 1 : prev - 1));
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
const rows = buildVisualRows(buf, effectiveWidth);
|
|
203
|
+
const { rowIdx, col } = cursorToVisualRowCol(rows, cur);
|
|
204
|
+
if (rowIdx > 0) {
|
|
205
|
+
const newCur = visualRowColToFlat(rows, rowIdx - 1, col);
|
|
206
|
+
cursorRef.current = newCur;
|
|
207
|
+
setCursorPos(newCur);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
if (key.downArrow) {
|
|
213
|
+
const isCmd = buf.startsWith('/') && !isProcessing && commands.length > 0;
|
|
214
|
+
const cmds = isCmd
|
|
215
|
+
? commands.filter(c => c.name.toLowerCase().startsWith(buf.toLowerCase()))
|
|
216
|
+
: [];
|
|
217
|
+
if (isCmd && cmds.length > 0) {
|
|
218
|
+
setCommandMenuIndex(prev => (prev >= cmds.length - 1 ? 0 : prev + 1));
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
const rows = buildVisualRows(buf, effectiveWidth);
|
|
222
|
+
const { rowIdx, col } = cursorToVisualRowCol(rows, cur);
|
|
223
|
+
if (rowIdx < rows.length - 1) {
|
|
224
|
+
const newCur = visualRowColToFlat(rows, rowIdx + 1, col);
|
|
225
|
+
cursorRef.current = newCur;
|
|
226
|
+
setCursorPos(newCur);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
if (key.return) {
|
|
232
|
+
// During paste or with Shift held: insert newline instead of submitting
|
|
233
|
+
if (isPasting || key.shift) {
|
|
234
|
+
insertText('\n');
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
if (isProcessing) {
|
|
238
|
+
// Interjection mode: interrupt with buffered text
|
|
239
|
+
if (buf.trim()) {
|
|
240
|
+
onInterjection(buf);
|
|
241
|
+
updateBufferAndCursor('', 0);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
else {
|
|
245
|
+
const isCmd = buf.startsWith('/') && !isProcessing && commands.length > 0;
|
|
246
|
+
const cmds = isCmd
|
|
247
|
+
? commands.filter(c => c.name.toLowerCase().startsWith(buf.toLowerCase()))
|
|
248
|
+
: [];
|
|
249
|
+
if (isCmd && cmds.length > 0) {
|
|
250
|
+
// Command mode: submit the selected command
|
|
251
|
+
const selected = cmds[commandMenuIndex];
|
|
252
|
+
if (selected) {
|
|
253
|
+
onSubmit(selected.name);
|
|
254
|
+
updateBufferAndCursor('', 0);
|
|
255
|
+
setAttachedImages([]);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
else if (cur > 0 && buf[cur - 1] === '\\') {
|
|
259
|
+
// Line continuation: replace trailing backslash with newline
|
|
260
|
+
const newBuf = buf.slice(0, cur - 1) + '\n' + buf.slice(cur);
|
|
261
|
+
updateBufferAndCursor(newBuf, cur); // cursor stays at same position (backslash removed, newline added)
|
|
262
|
+
}
|
|
263
|
+
else {
|
|
264
|
+
// Normal mode: submit input
|
|
265
|
+
const text = buf.trim();
|
|
266
|
+
if (text) {
|
|
267
|
+
const imgs = imagesRef.current;
|
|
268
|
+
onSubmit(text, imgs.length > 0 ? imgs : undefined);
|
|
269
|
+
updateBufferAndCursor('', 0);
|
|
270
|
+
setAttachedImages([]);
|
|
271
|
+
imagesRef.current = [];
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
// Arrow keys for cursor movement
|
|
278
|
+
if (key.leftArrow) {
|
|
279
|
+
if (key.meta) {
|
|
280
|
+
// Option+Left: move to previous word boundary
|
|
281
|
+
const newCur = findPrevWordBoundary(buf, cur);
|
|
282
|
+
cursorRef.current = newCur;
|
|
283
|
+
setCursorPos(newCur);
|
|
284
|
+
}
|
|
285
|
+
else {
|
|
286
|
+
const newCur = Math.max(0, cur - 1);
|
|
287
|
+
cursorRef.current = newCur;
|
|
288
|
+
setCursorPos(newCur);
|
|
289
|
+
}
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
if (key.rightArrow) {
|
|
293
|
+
if (key.meta) {
|
|
294
|
+
// Option+Right: move to next word boundary
|
|
295
|
+
const newCur = findNextWordBoundary(buf, cur);
|
|
296
|
+
cursorRef.current = newCur;
|
|
297
|
+
setCursorPos(newCur);
|
|
298
|
+
}
|
|
299
|
+
else {
|
|
300
|
+
const newCur = Math.min(buf.length, cur + 1);
|
|
301
|
+
cursorRef.current = newCur;
|
|
302
|
+
setCursorPos(newCur);
|
|
303
|
+
}
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
// Readline-style word navigation (ESC+b / ESC+f)
|
|
307
|
+
// Some terminals send these instead of modified arrow keys for Option+Arrow
|
|
308
|
+
if (key.meta && input === 'b') {
|
|
309
|
+
const newCur = findPrevWordBoundary(buf, cur);
|
|
310
|
+
cursorRef.current = newCur;
|
|
311
|
+
setCursorPos(newCur);
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
if (key.meta && input === 'f') {
|
|
315
|
+
const newCur = findNextWordBoundary(buf, cur);
|
|
316
|
+
cursorRef.current = newCur;
|
|
317
|
+
setCursorPos(newCur);
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
if (key.backspace || key.delete) {
|
|
321
|
+
if (key.meta) {
|
|
322
|
+
// Option+Backspace: delete previous word
|
|
323
|
+
const boundary = findPrevWordBoundary(buf, cur);
|
|
324
|
+
updateBufferAndCursor(buf.slice(0, boundary) + buf.slice(cur), boundary);
|
|
325
|
+
}
|
|
326
|
+
else if (cur > 0) {
|
|
327
|
+
updateBufferAndCursor(buf.slice(0, cur - 1) + buf.slice(cur), cur - 1);
|
|
328
|
+
}
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
// Regular character input
|
|
332
|
+
if (input && !key.return) {
|
|
333
|
+
insertText(input);
|
|
334
|
+
}
|
|
335
|
+
}, [
|
|
336
|
+
isProcessing,
|
|
337
|
+
pasteInProgress,
|
|
338
|
+
contentBasePath,
|
|
339
|
+
commands,
|
|
340
|
+
commandMenuIndex,
|
|
341
|
+
effectiveWidth,
|
|
342
|
+
onSubmit,
|
|
343
|
+
onInterjection,
|
|
344
|
+
]);
|
|
345
|
+
useInput(handleInput, { isActive: !isOverlayActive });
|
|
346
|
+
// Hide input when overlay is active
|
|
347
|
+
if (isOverlayActive) {
|
|
348
|
+
return _jsx(_Fragment, {});
|
|
349
|
+
}
|
|
350
|
+
// Build visual rows from logical lines, accounting for terminal soft-wrapping.
|
|
351
|
+
const rows = buildVisualRows(inputBuffer, effectiveWidth);
|
|
352
|
+
const { rowIdx: cursorRowIdx, col: cursorVisualCol } = cursorToVisualRowCol(rows, cursorPos);
|
|
353
|
+
// Annotate each row with prefix and cursor info for rendering
|
|
354
|
+
const prefix = isProcessing ? '! ' : '> ';
|
|
355
|
+
const prefixColor = isProcessing ? 'yellow' : 'cyan';
|
|
356
|
+
const visualRows = rows.map((row, idx) => ({
|
|
357
|
+
text: row.text,
|
|
358
|
+
prefix: idx === 0 ? prefix : ' ',
|
|
359
|
+
hasCursor: idx === cursorRowIdx,
|
|
360
|
+
cursorCol: idx === cursorRowIdx ? cursorVisualCol : 0,
|
|
361
|
+
}));
|
|
362
|
+
return (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [isCommandMode && filteredCommands.length > 0 && (_jsx(Box, { flexDirection: "column", borderStyle: "single", borderColor: "cyan", paddingX: 1, children: filteredCommands.map((cmd, i) => (_jsxs(Box, { children: [i === commandMenuIndex ? _jsx(Text, { color: "cyan", children: "> " }) : _jsx(Text, { children: " " }), _jsx(Text, { bold: true, children: cmd.name }), _jsxs(Text, { color: "gray", children: [" ", cmd.description] })] }, cmd.name))) })), attachedImages.length > 0 && (_jsx(Box, { children: attachedImages.map((img, i) => (_jsxs(Text, { color: "yellow", children: [i > 0 ? ' ' : '', "[IMG:", ' ', img.originalPath === 'clipboard'
|
|
363
|
+
? `clipboard-${i + 1}`
|
|
364
|
+
: img.originalPath.split('/').pop(), "]"] }, i))) })), visualRows.map((row, rowIdx) => (_jsxs(Box, { children: [_jsx(Text, { color: prefixColor, children: row.prefix }), row.hasCursor ? (_jsxs(_Fragment, { children: [_jsx(Text, { children: row.text.slice(0, row.cursorCol) }), _jsx(Text, { inverse: true, children: row.cursorCol < row.text.length ? row.text[row.cursorCol] : ' ' }), row.cursorCol < row.text.length && _jsx(Text, { children: row.text.slice(row.cursorCol + 1) })] })) : (_jsx(Text, { children: row.text }))] }, rowIdx)))] }));
|
|
365
|
+
}
|
|
366
|
+
//# sourceMappingURL=InputArea.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InputArea.js","sourceRoot":"","sources":["../../../src/tui/components/InputArea.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Markdown text rendering for terminal.
|
|
3
|
+
* Handles headings, tables, lists, code blocks, blockquotes, horizontal rules,
|
|
4
|
+
* and inline formatting (bold, inline code).
|
|
5
|
+
*/
|
|
6
|
+
import React from 'react';
|
|
7
|
+
type Block = {
|
|
8
|
+
type: 'codeblock';
|
|
9
|
+
content: string;
|
|
10
|
+
language?: string;
|
|
11
|
+
} | {
|
|
12
|
+
type: 'table';
|
|
13
|
+
headers: string[];
|
|
14
|
+
rows: string[][];
|
|
15
|
+
} | {
|
|
16
|
+
type: 'heading';
|
|
17
|
+
level: number;
|
|
18
|
+
content: string;
|
|
19
|
+
} | {
|
|
20
|
+
type: 'list';
|
|
21
|
+
ordered: boolean;
|
|
22
|
+
items: string[];
|
|
23
|
+
} | {
|
|
24
|
+
type: 'hr';
|
|
25
|
+
} | {
|
|
26
|
+
type: 'blockquote';
|
|
27
|
+
lines: string[];
|
|
28
|
+
} | {
|
|
29
|
+
type: 'paragraph';
|
|
30
|
+
content: string;
|
|
31
|
+
};
|
|
32
|
+
export declare function parseBlocks(content: string): Block[];
|
|
33
|
+
export interface MarkdownTextProps {
|
|
34
|
+
content: string;
|
|
35
|
+
}
|
|
36
|
+
export declare function MarkdownText({ content }: MarkdownTextProps): React.ReactElement;
|
|
37
|
+
export {};
|
|
38
|
+
//# sourceMappingURL=MarkdownText.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MarkdownText.d.ts","sourceRoot":"","sources":["../../../src/tui/components/MarkdownText.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,MAAM,OAAO,CAAC;AAS1B,KAAK,KAAK,GACN;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GACzD;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,EAAE,CAAA;CAAE,GACtD;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACnD;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,GACnD;IAAE,IAAI,EAAE,IAAI,CAAA;CAAE,GACd;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,GACvC;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AA0D3C,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,KAAK,EAAE,CA4HpD;AAoCD,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,YAAY,CAAC,EAAE,OAAO,EAAE,EAAE,iBAAiB,GAAG,KAAK,CAAC,YAAY,CAgH/E"}
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Markdown text rendering for terminal.
|
|
4
|
+
* Handles headings, tables, lists, code blocks, blockquotes, horizontal rules,
|
|
5
|
+
* and inline formatting (bold, inline code).
|
|
6
|
+
*/
|
|
7
|
+
import { Box, Text } from 'ink';
|
|
8
|
+
// ─── Inline Parser ──────────────────────────────────────────────────────────
|
|
9
|
+
function parseInline(text) {
|
|
10
|
+
const segments = [];
|
|
11
|
+
let remaining = text;
|
|
12
|
+
while (remaining.length > 0) {
|
|
13
|
+
const inlineCodeMatch = remaining.match(/^`([^`]+)`/);
|
|
14
|
+
if (inlineCodeMatch) {
|
|
15
|
+
segments.push({ type: 'code', content: inlineCodeMatch[1] });
|
|
16
|
+
remaining = remaining.slice(inlineCodeMatch[0].length);
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
19
|
+
const boldMatch = remaining.match(/^\*\*([^*]+)\*\*/);
|
|
20
|
+
if (boldMatch) {
|
|
21
|
+
segments.push({ type: 'bold', content: boldMatch[1] });
|
|
22
|
+
remaining = remaining.slice(boldMatch[0].length);
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
const nextSpecial = remaining.search(/`|\*\*/);
|
|
26
|
+
if (nextSpecial === -1) {
|
|
27
|
+
segments.push({ type: 'text', content: remaining });
|
|
28
|
+
break;
|
|
29
|
+
}
|
|
30
|
+
else if (nextSpecial === 0) {
|
|
31
|
+
segments.push({ type: 'text', content: remaining[0] });
|
|
32
|
+
remaining = remaining.slice(1);
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
segments.push({ type: 'text', content: remaining.slice(0, nextSpecial) });
|
|
36
|
+
remaining = remaining.slice(nextSpecial);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return segments;
|
|
40
|
+
}
|
|
41
|
+
// ─── Block Parser ───────────────────────────────────────────────────────────
|
|
42
|
+
function isTableSeparator(line) {
|
|
43
|
+
const trimmed = line.trim();
|
|
44
|
+
if (!trimmed.includes('-'))
|
|
45
|
+
return false;
|
|
46
|
+
let inner = trimmed;
|
|
47
|
+
if (inner.startsWith('|'))
|
|
48
|
+
inner = inner.slice(1);
|
|
49
|
+
if (inner.endsWith('|'))
|
|
50
|
+
inner = inner.slice(0, -1);
|
|
51
|
+
const cells = inner.split('|');
|
|
52
|
+
return cells.length > 0 && cells.every(cell => /^\s*:?-{1,}:?\s*$/.test(cell));
|
|
53
|
+
}
|
|
54
|
+
function parseTableRow(line) {
|
|
55
|
+
let trimmed = line.trim();
|
|
56
|
+
if (trimmed.startsWith('|'))
|
|
57
|
+
trimmed = trimmed.slice(1);
|
|
58
|
+
if (trimmed.endsWith('|'))
|
|
59
|
+
trimmed = trimmed.slice(0, -1);
|
|
60
|
+
return trimmed.split('|').map(cell => cell.trim());
|
|
61
|
+
}
|
|
62
|
+
export function parseBlocks(content) {
|
|
63
|
+
const lines = content.split('\n');
|
|
64
|
+
const blocks = [];
|
|
65
|
+
let i = 0;
|
|
66
|
+
while (i < lines.length) {
|
|
67
|
+
const line = lines[i];
|
|
68
|
+
// Code block
|
|
69
|
+
if (line.trimStart().startsWith('```')) {
|
|
70
|
+
const language = line.trimStart().slice(3).trim();
|
|
71
|
+
const codeLines = [];
|
|
72
|
+
i++;
|
|
73
|
+
while (i < lines.length && !lines[i].trimStart().startsWith('```')) {
|
|
74
|
+
codeLines.push(lines[i]);
|
|
75
|
+
i++;
|
|
76
|
+
}
|
|
77
|
+
blocks.push({
|
|
78
|
+
type: 'codeblock',
|
|
79
|
+
content: codeLines.join('\n'),
|
|
80
|
+
language: language || undefined,
|
|
81
|
+
});
|
|
82
|
+
if (i < lines.length)
|
|
83
|
+
i++; // skip closing ```
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
// Empty line
|
|
87
|
+
if (line.trim() === '') {
|
|
88
|
+
i++;
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
// Heading
|
|
92
|
+
const headingMatch = line.match(/^(#{1,6})\s+(.*)/);
|
|
93
|
+
if (headingMatch) {
|
|
94
|
+
blocks.push({
|
|
95
|
+
type: 'heading',
|
|
96
|
+
level: headingMatch[1].length,
|
|
97
|
+
content: headingMatch[2],
|
|
98
|
+
});
|
|
99
|
+
i++;
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
// Horizontal rule: ---, ***, ___ (3+ chars, nothing else on the line)
|
|
103
|
+
if (/^(\*{3,}|-{3,}|_{3,})\s*$/.test(line.trim())) {
|
|
104
|
+
// Make sure this isn't a table separator (check if surrounded by table rows)
|
|
105
|
+
const prevIsTable = i > 0 && lines[i - 1].includes('|');
|
|
106
|
+
const nextIsTable = i + 1 < lines.length && lines[i + 1].includes('|');
|
|
107
|
+
if (!prevIsTable || !nextIsTable) {
|
|
108
|
+
blocks.push({ type: 'hr' });
|
|
109
|
+
i++;
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
// Table: line with pipes and next line is separator
|
|
114
|
+
if (line.includes('|') && i + 1 < lines.length && isTableSeparator(lines[i + 1])) {
|
|
115
|
+
const headers = parseTableRow(line);
|
|
116
|
+
i += 2; // skip header + separator
|
|
117
|
+
const rows = [];
|
|
118
|
+
while (i < lines.length && lines[i].includes('|') && lines[i].trim() !== '') {
|
|
119
|
+
rows.push(parseTableRow(lines[i]));
|
|
120
|
+
i++;
|
|
121
|
+
}
|
|
122
|
+
blocks.push({ type: 'table', headers, rows });
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
// Unordered list
|
|
126
|
+
if (/^\s*[-*+]\s/.test(line)) {
|
|
127
|
+
const items = [];
|
|
128
|
+
while (i < lines.length && /^\s*[-*+]\s/.test(lines[i])) {
|
|
129
|
+
items.push(lines[i].replace(/^\s*[-*+]\s+/, ''));
|
|
130
|
+
i++;
|
|
131
|
+
}
|
|
132
|
+
blocks.push({ type: 'list', ordered: false, items });
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
// Ordered list
|
|
136
|
+
if (/^\s*\d+[.)]\s/.test(line)) {
|
|
137
|
+
const items = [];
|
|
138
|
+
while (i < lines.length && /^\s*\d+[.)]\s/.test(lines[i])) {
|
|
139
|
+
items.push(lines[i].replace(/^\s*\d+[.)]\s+/, ''));
|
|
140
|
+
i++;
|
|
141
|
+
}
|
|
142
|
+
blocks.push({ type: 'list', ordered: true, items });
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
// Blockquote
|
|
146
|
+
if (line.startsWith('>')) {
|
|
147
|
+
const bqLines = [];
|
|
148
|
+
while (i < lines.length && lines[i].startsWith('>')) {
|
|
149
|
+
bqLines.push(lines[i].replace(/^>\s?/, ''));
|
|
150
|
+
i++;
|
|
151
|
+
}
|
|
152
|
+
blocks.push({ type: 'blockquote', lines: bqLines });
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
// Paragraph: collect lines until empty line or recognized block start
|
|
156
|
+
const paraLines = [];
|
|
157
|
+
while (i < lines.length &&
|
|
158
|
+
lines[i].trim() !== '' &&
|
|
159
|
+
!lines[i].trimStart().startsWith('```') &&
|
|
160
|
+
!/^#{1,6}\s/.test(lines[i]) &&
|
|
161
|
+
!/^(\*{3,}|-{3,}|_{3,})\s*$/.test(lines[i].trim()) &&
|
|
162
|
+
!(lines[i].includes('|') && i + 1 < lines.length && isTableSeparator(lines[i + 1])) &&
|
|
163
|
+
!/^\s*[-*+]\s/.test(lines[i]) &&
|
|
164
|
+
!/^\s*\d+[.)]\s/.test(lines[i]) &&
|
|
165
|
+
!lines[i].startsWith('>')) {
|
|
166
|
+
paraLines.push(lines[i]);
|
|
167
|
+
i++;
|
|
168
|
+
}
|
|
169
|
+
if (paraLines.length > 0) {
|
|
170
|
+
blocks.push({ type: 'paragraph', content: paraLines.join('\n') });
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return blocks;
|
|
174
|
+
}
|
|
175
|
+
// ─── Render Helpers ─────────────────────────────────────────────────────────
|
|
176
|
+
function InlineText({ text }) {
|
|
177
|
+
const segments = parseInline(text);
|
|
178
|
+
return (_jsx(Text, { children: segments.map((seg, i) => {
|
|
179
|
+
switch (seg.type) {
|
|
180
|
+
case 'bold':
|
|
181
|
+
return (_jsx(Text, { bold: true, children: seg.content }, i));
|
|
182
|
+
case 'code':
|
|
183
|
+
return (_jsx(Text, { color: "yellow", children: seg.content }, i));
|
|
184
|
+
default:
|
|
185
|
+
return _jsx(Text, { children: seg.content }, i);
|
|
186
|
+
}
|
|
187
|
+
}) }));
|
|
188
|
+
}
|
|
189
|
+
function stripInlineMarkers(text) {
|
|
190
|
+
return text.replace(/\*\*([^*]+)\*\*/g, '$1').replace(/`([^`]+)`/g, '$1');
|
|
191
|
+
}
|
|
192
|
+
export function MarkdownText({ content }) {
|
|
193
|
+
const blocks = parseBlocks(content);
|
|
194
|
+
return (_jsx(Box, { flexDirection: "column", children: blocks.map((block, i) => {
|
|
195
|
+
switch (block.type) {
|
|
196
|
+
case 'codeblock':
|
|
197
|
+
return (_jsxs(Box, { flexDirection: "column", marginY: 1, children: [_jsxs(Text, { color: "gray", children: ['```', block.language] }), _jsx(Text, { color: "green", children: block.content }), _jsx(Text, { color: "gray", children: '```' })] }, i));
|
|
198
|
+
case 'heading': {
|
|
199
|
+
const colorMap = { 1: 'white', 2: 'cyan', 3: 'blue' };
|
|
200
|
+
const color = colorMap[block.level] || 'white';
|
|
201
|
+
return (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { bold: true, color: color, children: ['#'.repeat(block.level), " ", block.content] }) }, i));
|
|
202
|
+
}
|
|
203
|
+
case 'hr':
|
|
204
|
+
return (_jsx(Box, { marginY: 1, children: _jsx(Text, { color: "gray", children: '─'.repeat(40) }) }, i));
|
|
205
|
+
case 'table': {
|
|
206
|
+
const { headers, rows } = block;
|
|
207
|
+
const colCount = headers.length;
|
|
208
|
+
// Calculate column widths from plain text content
|
|
209
|
+
const colWidths = Array.from({ length: colCount }, (_, c) => {
|
|
210
|
+
const headerWidth = stripInlineMarkers(headers[c] || '').length;
|
|
211
|
+
const maxRowWidth = rows.reduce((max, row) => Math.max(max, stripInlineMarkers(row[c] || '').length), 0);
|
|
212
|
+
return Math.max(headerWidth, maxRowWidth);
|
|
213
|
+
});
|
|
214
|
+
const pad = (s, w) => s + ' '.repeat(Math.max(0, w - s.length));
|
|
215
|
+
const topBorder = '┌' + colWidths.map(w => '─'.repeat(w + 2)).join('┬') + '┐';
|
|
216
|
+
const midBorder = '├' + colWidths.map(w => '─'.repeat(w + 2)).join('┼') + '┤';
|
|
217
|
+
const botBorder = '└' + colWidths.map(w => '─'.repeat(w + 2)).join('┴') + '┘';
|
|
218
|
+
const formatRow = (cells) => '│' +
|
|
219
|
+
Array.from({ length: colCount }, (_, c) => ' ' + pad(stripInlineMarkers(cells[c] || ''), colWidths[c]) + ' ').join('│') +
|
|
220
|
+
'│';
|
|
221
|
+
return (_jsxs(Box, { flexDirection: "column", marginY: 1, children: [_jsx(Text, { color: "gray", children: topBorder }), _jsx(Text, { bold: true, children: formatRow(headers) }), _jsx(Text, { color: "gray", children: midBorder }), rows.map((row, r) => (_jsx(Text, { children: formatRow(row) }, r))), _jsx(Text, { color: "gray", children: botBorder })] }, i));
|
|
222
|
+
}
|
|
223
|
+
case 'list':
|
|
224
|
+
return (_jsx(Box, { flexDirection: "column", children: block.items.map((item, j) => (_jsxs(Box, { children: [_jsx(Text, { children: block.ordered ? ` ${j + 1}. ` : ' • ' }), _jsx(InlineText, { text: item })] }, j))) }, i));
|
|
225
|
+
case 'blockquote':
|
|
226
|
+
return (_jsx(Box, { flexDirection: "column", marginY: 1, children: block.lines.map((line, j) => (_jsxs(Box, { children: [_jsx(Text, { color: "gray", children: ' │ ' }), _jsx(InlineText, { text: line })] }, j))) }, i));
|
|
227
|
+
case 'paragraph':
|
|
228
|
+
return _jsx(InlineText, { text: block.content }, i);
|
|
229
|
+
default:
|
|
230
|
+
return null;
|
|
231
|
+
}
|
|
232
|
+
}) }));
|
|
233
|
+
}
|
|
234
|
+
//# sourceMappingURL=MarkdownText.js.map
|