@@ -81,7 +81,7 @@ export function findImagePathMentions(
8181 // Keep a lone trailing \r on CRLF out of the scan window.
8282 const contentEnd =
8383 lineEnd > lineStart && text [ lineEnd - 1 ] === "\r" ? lineEnd - 1 : lineEnd ;
84- scanImagePathLine ( text , lineStart , contentEnd , cwd , push ) ;
84+ scanImagePathLine ( text , lineStart , contentEnd , cwd , push , false ) ;
8585 if ( lineEnd === text . length ) break ;
8686 lineStart = lineEnd + 1 ;
8787 }
@@ -98,6 +98,7 @@ function scanImagePathLine(
9898 end : number ,
9999 cwd : string ,
100100 push : ( raw : string , path : string | undefined ) => void ,
101+ inQuotedProse : boolean ,
101102) : void {
102103 let i = start ;
103104 while ( i < end ) {
@@ -120,7 +121,7 @@ function scanImagePathLine(
120121 }
121122 // Balanced quotes around prose are not path wrappers. Search inside
122123 // so an absolute path can still be found, then resume after the closer.
123- scanImagePathLine ( text , i + 1 , close , cwd , push ) ;
124+ scanImagePathLine ( text , i + 1 , close , cwd , push , true ) ;
124125 i = close + 1 ;
125126 continue ;
126127 }
@@ -129,7 +130,12 @@ function scanImagePathLine(
129130 continue ;
130131 }
131132
132- if ( canStartUnquotedPath ( text , i , end ) ) {
133+ // Inside prose a candidate must open a new token, or the separator in
134+ // `notes/plan.png` mints a root-level `/plan.png` mention.
135+ if (
136+ canStartUnquotedPath ( text , i , end ) &&
137+ ( ! inQuotedProse || i === start || ! isTokenContinuation ( text [ i - 1 ] ) )
138+ ) {
133139 const match = UNQUOTED_AT . exec ( text . slice ( i , end ) ) ;
134140 if ( match ?. [ 0 ] !== undefined ) {
135141 const raw = trimTrailingPunctuation ( match [ 0 ] ) ;
@@ -151,6 +157,16 @@ function isWordChar(ch: string | undefined): boolean {
151157 ) ;
152158}
153159
160+ // Characters that can glue a `/` (or another path start) onto the token
161+ // before it: relative segments (`notes/plan.png`), URLs (`https://x.png`),
162+ // and shell-style quote concatenation (`'a'/b.png`).
163+ const TOKEN_CONTINUATION = "'\"`/\\:.~_-+@%" ;
164+
165+ function isTokenContinuation ( ch : string | undefined ) : boolean {
166+ if ( ch === undefined ) return false ;
167+ return isWordChar ( ch ) || TOKEN_CONTINUATION . includes ( ch ) ;
168+ }
169+
154170function looksLikeQuotedImagePath ( inner : string ) : boolean {
155171 if ( inner . startsWith ( "file://" ) ) return true ;
156172 if ( inner === "~" || inner . startsWith ( "~/" ) || inner . startsWith ( "~\\" ) )
0 commit comments