diff --git a/apps/app/src/components/ui/markdown-local-file-link.ts b/apps/app/src/components/ui/markdown-local-file-link.ts index 86bf965f5..f50e4674d 100644 --- a/apps/app/src/components/ui/markdown-local-file-link.ts +++ b/apps/app/src/components/ui/markdown-local-file-link.ts @@ -269,6 +269,17 @@ function parseAbsoluteLocalFileHref( return parsed; } +// Shell-style home paths (`~`, `~/x`, `~user/x`) are not workspace-relative. +// The renderer has no home directory to expand them against, so leave them as +// plain links instead of joining the literal `~` onto the workspace root. +// Only a bare `~` or a first segment that starts with `~` and is followed by a +// `/` counts; a plain file name that happens to start with `~` (for example +// `~notes.md` or a `~$report.docx` lock file) is still a relative file. This +// runs on the *decoded* href, so `%7E/x` is covered too. +function isHomeRelativePath(path: string): boolean { + return /^~(?:[^/]*\/|$)/u.test(path); +} + // Apply scheme detection after file line suffix parsing so references such as // `Cargo.lock:14:33` and `foo.md:5` remain relative file links. const URI_SCHEME_PATTERN = /^[a-zA-Z][a-zA-Z0-9+.-]*:/u; @@ -297,6 +308,7 @@ export function resolveRelativeLocalFileHref({ parsedHref === null || parsedHref.path.length === 0 || parsedHref.path.startsWith("/") || + isHomeRelativePath(parsedHref.path) || parsedHref.path.startsWith("#") || parsedHref.path.startsWith("?") || URI_SCHEME_PATTERN.test(parsedHref.path)