import ReactMarkdown, { PluggableList, ReactMarkdownOptions, } from 'react-markdown'; import remarkGfm from 'remark-gfm'; import rehypeRaw from 'rehype-raw'; import rehypeSanitize from 'rehype-sanitize'; import React, { useMemo } from 'react'; import { useComposedCssClasses } from '../hooks/useComposedCssClasses'; // The Remark and Rehype plugins to use in conjunction with ReactMarkdown. const unifiedPlugins: { remark?: PluggableList, rehype: PluggableList } = { remark: [ remarkGfm, //renders Github-Flavored Markdown ], rehype: [ rehypeRaw, //to support HTML embedded in markdown rehypeSanitize, //to sanitize HTML content ], }; /** * The CSS class interface for the Markdown component. * * @internal */ export interface MarkdownCssClasses { container?: string, link?: string } const builtInCssClasses: MarkdownCssClasses = { link: 'cursor-pointer', }; interface MarkdownProps { /** Stringified markdown. */ content: string, /** CSS classes for customizing the component styling. */ customCssClasses?: MarkdownCssClasses, /** A callback which is called when a link is clicked. */ onLinkClick?: (href?: string) => void } /** * Renders Github-Flavored Markdown from the Knowledge Graph. This Markdown can include * arbitrary HTML. Any HTML will be sanitized according to Rehype's default Schema. * * @remarks * A link click will send a CHAT_LINK_CLICK analytics event * * @internal */ export function Markdown({ content, customCssClasses, onLinkClick, }: MarkdownProps) { const cssClasses = useComposedCssClasses(builtInCssClasses, customCssClasses); const components: ReactMarkdownOptions['components'] = useMemo(() => { const createClickHandlerFn = (href?: string) => () => { onLinkClick?.(href); }; return { a: ({ node: _, children, ...props }) => { return ( {children} ); }, }; }, [ cssClasses, onLinkClick, ]); return ( ); }