diff --git a/webui2/src/components/content/Markdown.tsx b/webui2/src/components/content/Markdown.tsx index 5ca0e1119d359b1b28d9dc07c9dbed798c5eef77..f062fffd6b5d475554770f9f354f91b4e5445d2d 100644 --- a/webui2/src/components/content/Markdown.tsx +++ b/webui2/src/components/content/Markdown.tsx @@ -1,3 +1,4 @@ +import { Link } from "@tanstack/react-router"; import { useMemo } from "react"; import ReactMarkdown from "react-markdown"; import rehypeAutolinkHeadings from "rehype-autolink-headings"; @@ -72,9 +73,8 @@ function isImagePath(path: string): boolean { // Renders a Markdown string with GitHub-flavoured extensions (tables, task // lists, strikethrough). Used in Timeline comments and code browser READMEs. export function Markdown({ content, className, repoContext }: MarkdownProps) { - // Rewrite relative URLs: - // - images → /gitraw/{repo}/{ref}/{path} (serves raw bytes) - // - links → /{repo}/blob/{ref}/{path} (code browser view) + // Rewrite image src to /gitraw for raw content serving. + // Links are handled by the custom `a` component below. const urlTransform = useMemo(() => { if (!repoContext) return undefined; const { repo, ref, basePath } = repoContext; @@ -84,10 +84,61 @@ export function Markdown({ content, className, repoContext }: MarkdownProps) { if (isImagePath(resolved)) { return `/gitraw/${repo}/${ref}/${resolved}`; } + // Non-image relative URLs are handled by the `a` component override, + // but urlTransform runs first, so we still need to return something. + // Return the resolved path prefixed so the `a` component can detect it. return `/${repo}/blob/${ref}/${resolved}`; }; }, [repoContext]); + const components = useMemo(() => { + if (!repoContext) return undefined; + const { repo, ref, basePath } = repoContext; + return { + a: ({ href, children, ...props }: React.AnchorHTMLAttributes) => { + if (!href) return {children}; + + // Anchor links stay as-is + if (href.startsWith("#")) + return ( + + {children} + + ); + + // Check if this is a relative URL that we should route client-side. + // After urlTransform, repo-local links look like /{repo}/blob/{ref}/{path} + const prefix = `/${repo}/blob/${ref}/`; + if (href.startsWith(prefix)) { + const path = href.slice(prefix.length); + return ( + + {children} + + ); + } + + // Also handle raw relative URLs that urlTransform didn't process + // (shouldn't happen but defensive) + if (isRelativeUrl(href)) { + const resolved = resolveRelativePath(basePath, href); + return ( + + {children} + + ); + } + + // External links — render as normal anchor + return ( + + {children} + + ); + }, + }; + }, [repoContext]); + return (
{content}