components/message.tsx
Rama main · réplica de lectura del repositorio original.
'use client'
import { useMemo } from 'react'
import { math } from '@streamdown/math'
import {
defaultRehypePlugins,
Streamdown,
type StreamdownProps
} from 'streamdown'
import { normalizeDraftFences } from '@/lib/draft/draft'
import { mergeStreamdownSpecRenderer } from '@/lib/render/streamdown-spec'
import type { SearchResultItem } from '@/lib/types'
import { cn } from '@/lib/utils'
import { processCitations } from '@/lib/utils/citation'
import { CitationProvider } from './citation-context'
import { Citing } from './custom-link'
import 'katex/dist/katex.min.css'
const rehypePlugins = Object.values(defaultRehypePlugins)
const customComponents = {
a: Citing
}
export function MarkdownMessage({
message,
className,
citationMaps,
drafts = true
}: {
message: string
className?: string
citationMaps?: Record<string, Record<number, SearchResultItem>>
/** False inside the draft panel, where a draft fence is an example to show. */
drafts?: boolean
}) {
// Process citations to replace [number](#toolCallId) with [number](actual-url)
const processedMessage = processCitations(
drafts ? normalizeDraftFences(message || '') : message || '',
citationMaps || {}
)
const streamdownProps = useMemo<Partial<StreamdownProps>>(
() => ({
mode: 'streaming' as const,
plugins: mergeStreamdownSpecRenderer({ math }, { drafts })
}),
[drafts]
)
return (
<CitationProvider citationMaps={citationMaps}>
<div
className={cn(
'prose-sm prose-neutral prose-a:text-accent-foreground/50',
className
)}
>
<Streamdown
{...streamdownProps}
rehypePlugins={rehypePlugins}
components={customComponents}
>
{processedMessage}
</Streamdown>
</div>
</CitationProvider>
)
}