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