diff --git a/packages/tui/src/components/editor.ts b/packages/tui/src/components/editor.ts index dd6be631..73185a89 100644 --- a/packages/tui/src/components/editor.ts +++ b/packages/tui/src/components/editor.ts @@ -897,17 +897,21 @@ export class Editor implements Component, Focusable { return this.state.lines.join("\n"); } + private expandPasteMarkers(text: string): string { + let result = text; + for (const [pasteId, pasteContent] of this.pastes) { + const markerRegex = new RegExp(`\\[paste #${pasteId}( (\\+\\d+ lines|\\d+ chars))?\\]`, "g"); + result = result.replace(markerRegex, () => pasteContent); + } + return result; + } + /** * Get text with paste markers expanded to their actual content. * Use this when you need the full content (e.g., for external editor). */ getExpandedText(): string { - let result = this.state.lines.join("\n"); - for (const [pasteId, pasteContent] of this.pastes) { - const markerRegex = new RegExp(`\\[paste #${pasteId}( (\\+\\d+ lines|\\d+ chars))?\\]`, "g"); - result = result.replace(markerRegex, pasteContent); - } - return result; + return this.expandPasteMarkers(this.state.lines.join("\n")); } getLines(): string[] { @@ -1152,11 +1156,7 @@ export class Editor implements Component, Focusable { } private submitValue(): void { - let result = this.state.lines.join("\n").trim(); - for (const [pasteId, pasteContent] of this.pastes) { - const markerRegex = new RegExp(`\\[paste #${pasteId}( (\\+\\d+ lines|\\d+ chars))?\\]`, "g"); - result = result.replace(markerRegex, pasteContent); - } + const result = this.expandPasteMarkers(this.state.lines.join("\n")).trim(); this.state = { lines: [""], cursorLine: 0, cursorCol: 0 }; this.pastes.clear(); diff --git a/packages/tui/test/editor.test.ts b/packages/tui/test/editor.test.ts index 30fc3c66..600549f0 100644 --- a/packages/tui/test/editor.test.ts +++ b/packages/tui/test/editor.test.ts @@ -3388,5 +3388,53 @@ describe("Editor component", () => { ); } }); + + it("expands large pasted content literally in getExpandedText", () => { + const editor = new Editor(createTestTUI(), defaultEditorTheme); + const pastedText = [ + "line 1", + "line 2", + "line 3", + "line 4", + "line 5", + "line 6", + "line 7", + "line 8", + "line 9", + "line 10", + "tokens $1 $2 $& $$ $` $' end", + ].join("\n"); + + editor.handleInput(`\x1b[200~${pastedText}\x1b[201~`); + + assert.match(editor.getText(), /\[paste #\d+ \+\d+ lines\]/); + assert.strictEqual(editor.getExpandedText(), pastedText); + }); + + it("submits large pasted content literally", () => { + const editor = new Editor(createTestTUI(), defaultEditorTheme); + const pastedText = [ + "line 1", + "line 2", + "line 3", + "line 4", + "line 5", + "line 6", + "line 7", + "line 8", + "line 9", + "line 10", + "tokens $1 $2 $& $$ $` $' end", + ].join("\n"); + let submitted = ""; + editor.onSubmit = (text) => { + submitted = text; + }; + + editor.handleInput(`\x1b[200~${pastedText}\x1b[201~`); + editor.handleInput("\r"); + + assert.strictEqual(submitted, pastedText); + }); }); });