(options: {
text: string
cursorPosition: number
onChange: (value: InputValue) => void
onPasteImage?: () => void
onPasteImagePath?: (imagePath: string) => void
onPasteFilePath?: (filePath: string, isDirectory: boolean) => void
onPasteLongText?: (text: string) => void
cwd?: string
})
| 117 | * Only when NO eventText is provided do we read from the clipboard. |
| 118 | */ |
| 119 | export function createPasteHandler(options: { |
| 120 | text: string |
| 121 | cursorPosition: number |
| 122 | onChange: (value: InputValue) => void |
| 123 | onPasteImage?: () => void |
| 124 | onPasteImagePath?: (imagePath: string) => void |
| 125 | onPasteFilePath?: (filePath: string, isDirectory: boolean) => void |
| 126 | onPasteLongText?: (text: string) => void |
| 127 | cwd?: string |
| 128 | }): (eventText?: string) => void { |
| 129 | const { |
| 130 | text, |
| 131 | cursorPosition, |
| 132 | onChange, |
| 133 | onPasteImage, |
| 134 | onPasteImagePath, |
| 135 | onPasteFilePath, |
| 136 | onPasteLongText, |
| 137 | cwd, |
| 138 | } = options |
| 139 | return (eventText) => { |
| 140 | // Strip ANSI escape sequences from pasted text — terminal paste events |
| 141 | // (bracketed paste) may include ANSI sequences from the source content. |
| 142 | if (eventText) { |
| 143 | eventText = Bun.stripANSI(eventText) |
| 144 | } |
| 145 | |
| 146 | // If we have direct input text from the paste event (e.g., from terminal paste), |
| 147 | // check if it looks like an image filename and if we can get the full path from clipboard |
| 148 | if (eventText && onPasteImagePath) { |
| 149 | // The terminal often only passes the filename when pasting a file copied from Finder. |
| 150 | // Check if this looks like just a filename (no path separators) that's an image. |
| 151 | const looksLikeImageFilename = |
| 152 | isImageFile(eventText) && |
| 153 | !eventText.includes('/') && |
| 154 | !eventText.includes('\\') |
| 155 | |
| 156 | if (looksLikeImageFilename) { |
| 157 | // Try to get the full path from the clipboard's file URL |
| 158 | const clipboardFilePath = readClipboardImageFilePath() |
| 159 | // Verify the clipboard path's basename matches exactly (not just endsWith) |
| 160 | if ( |
| 161 | clipboardFilePath && |
| 162 | path.basename(clipboardFilePath) === eventText |
| 163 | ) { |
| 164 | // The clipboard has the full path to the same file - use it! |
| 165 | onPasteImagePath(clipboardFilePath) |
| 166 | return |
| 167 | } |
| 168 | } |
| 169 | |
| 170 | // Check if eventText is a full path to an image file |
| 171 | if (cwd) { |
| 172 | const imagePath = getImageFilePathFromText(eventText, cwd) |
| 173 | if (imagePath) { |
| 174 | onPasteImagePath(imagePath) |
| 175 | return |
| 176 | } |
no test coverage detected