fix(tui): preserved bare png filename pastes

Require bracketed image-path paste detection to see an explicit local path separator or file URI before routing .png-like text to image attachment handling.\n\nFixes #3253
This commit is contained in:
roboomp
2026-06-22 10:46:24 +00:00
parent 320261fca9
commit fe9ffc7912
3 changed files with 36 additions and 1 deletions
@@ -64,6 +64,9 @@ const BRACKETED_PASTE_END = "\x1b[201~";
const BRACKETED_IMAGE_PATH_REGEX = /\.(?:png|jpe?g|gif|webp)$/i;
const BRACKETED_IMAGE_PATH_BOUNDARY_REGEX = /\.(?:png|jpe?g|gif|webp)(?=$|["']?\s)/gi;
const SHELL_ESCAPED_PATH_CHAR_REGEX = /\\([\\\s'"()[\]{}&;<>|?*!$`])/g;
const URI_SCHEME_REGEX = /^[a-z][a-z0-9+.-]*:/i;
const FILE_URI_REGEX = /^file:\/\//i;
const WINDOWS_DRIVE_PATH_REGEX = /^[a-z]:[\\/]/i;
/** Max gap (ms) between two spaces for the later one to count as OS key auto-repeat rather than a
* deliberate press. OS auto-repeat is fast; a deliberate tap (even a fast one) is slower. */
@@ -118,6 +121,12 @@ function normalizePastedImagePath(path: string): string {
return unquoted.replace(SHELL_ESCAPED_PATH_CHAR_REGEX, "$1");
}
function isExplicitPastedImagePath(path: string): boolean {
if (WINDOWS_DRIVE_PATH_REGEX.test(path) || FILE_URI_REGEX.test(path)) return true;
if (URI_SCHEME_REGEX.test(path)) return false;
return path.includes("/") || path.includes("\\");
}
export function extractBracketedImagePastePaths(data: string): string[] | undefined {
if (!data.startsWith(BRACKETED_PASTE_START)) return undefined;
const endIndex = data.indexOf(BRACKETED_PASTE_END, BRACKETED_PASTE_START.length);
@@ -139,7 +148,7 @@ export function extractBracketedImagePastePaths(data: string): string[] | undefi
if (boundaryEnd === undefined) continue;
const path = normalizePastedImagePath(pasted.slice(segmentStart, boundaryEnd));
if (!path || !BRACKETED_IMAGE_PATH_REGEX.test(path)) return undefined;
if (!path || !BRACKETED_IMAGE_PATH_REGEX.test(path) || !isExplicitPastedImagePath(path)) return undefined;
paths.push(path);
segmentStart = boundaryEnd;