diff --git a/web/app/components/base/markdown-with-directive/__tests__/index.spec.tsx b/web/app/components/base/markdown-with-directive/__tests__/index.spec.tsx index e71abd6620..d2b2d2a249 100644 --- a/web/app/components/base/markdown-with-directive/__tests__/index.spec.tsx +++ b/web/app/components/base/markdown-with-directive/__tests__/index.spec.tsx @@ -185,6 +185,15 @@ describe('markdown-with-directive', () => { }) expect(screen.getByText('Sanitized')).toBeInTheDocument() expectDecorativeIcon(container, 'https://example.com/safe.png') + sanitizeSpy.mockRestore() + }) + + it('should render markdown links without underline', () => { + render() + + const link = screen.getByRole('link', { name: 'Langfuse' }) + expect(link).toHaveClass('text-text-accent') + expect(link).toHaveStyle({ textDecoration: 'none' }) }) it('should render empty output and skip sanitizer when markdown is empty', () => { diff --git a/web/app/components/base/markdown-with-directive/index.tsx b/web/app/components/base/markdown-with-directive/index.tsx index 8da4cf7ede..e8feca39a3 100644 --- a/web/app/components/base/markdown-with-directive/index.tsx +++ b/web/app/components/base/markdown-with-directive/index.tsx @@ -1,5 +1,5 @@ 'use client' -import type { ReactNode } from 'react' +import type { AnchorHTMLAttributes, ClassAttributes, ReactNode } from 'react' import type { Components, StreamdownProps } from 'streamdown' import DOMPurify from 'dompurify' import remarkDirective from 'remark-directive' @@ -241,10 +241,25 @@ function directivePlugin() { } } -const directiveComponents = { +const directiveComponents: Components = { + a: (props) => { + const { children, href } = props as ClassAttributes & AnchorHTMLAttributes + + return ( + + {children} + + ) + }, withiconcardlist: WithIconCardListAdapter, withiconcarditem: WithIconCardItemAdapter, -} satisfies Components +} type MarkdownWithDirectiveProps = { markdown: string