import ReactMarkdown from "react-markdown"; import "katex/dist/katex.min.css"; import RemarkMath from "remark-math"; import RemarkBreaks from "remark-breaks"; import RehypeKatex from "rehype-katex"; import RemarkGfm from "remark-gfm"; import RehypeHighlight from "rehype-highlight"; import { useRef, useState, RefObject, useEffect } from "react"; import { copyToClipboard } from "../utils"; export function PreCode(props: { children: any }) { const ref = useRef<HTMLPreElement>(null); return ( <pre ref={ref}> <span className="copy-code-button" onClick={() => { if (ref.current) { const code = ref.current.innerText; copyToClipboard(code); } }} ></span> {props.children} </pre> ); } const useLazyLoad = (ref: RefObject<Element>): boolean => { const [isIntersecting, setIntersecting] = useState<boolean>(false); useEffect(() => { const observer = new IntersectionObserver(([entry]) => { if (entry.isIntersecting) { setIntersecting(true); observer.disconnect(); } }); if (ref.current) { observer.observe(ref.current); } return () => { observer.disconnect(); }; }, [ref]); return isIntersecting; }; export function Markdown(props: { content: string }) { return ( <ReactMarkdown remarkPlugins={[RemarkMath, RemarkGfm, RemarkBreaks]} rehypePlugins={[ RehypeKatex, [ RehypeHighlight, { detect: false, ignoreMissing: true, }, ], ]} components={{ pre: PreCode, }} linkTarget={'_blank'} > {props.content} </ReactMarkdown> ); }