Replace react markdown with react remark for better performance when streaming

This commit is contained in:
Saoud Rizwan
2024-10-01 01:11:25 -04:00
parent 5fa3794610
commit c664403d4e
4 changed files with 133 additions and 1210 deletions

View File

@@ -0,0 +1,129 @@
import { memo, useEffect } from "react"
import { useRemark } from "react-remark"
import rehypeHighlight, { Options } from "rehype-highlight"
import styled from "styled-components"
import { visit } from "unist-util-visit"
import { useExtensionState } from "../../context/ExtensionStateContext"
import { CODE_BLOCK_BG_COLOR } from "./CodeBlock"
interface MarkdownBlockProps {
markdown?: string
}
const StyledMarkdown = styled.div`
pre {
background-color: ${CODE_BLOCK_BG_COLOR};
border-radius: 3px;
margin: 13x 0;
padding: 10px 10px;
max-width: calc(100vw - 20px);
overflow-x: scroll;
overflow-y: hidden;
}
pre > code {
.hljs-deletion {
background-color: var(--vscode-diffEditor-removedTextBackground);
display: inline-block;
width: 100%;
}
.hljs-addition {
background-color: var(--vscode-diffEditor-insertedTextBackground);
display: inline-block;
width: 100%;
}
}
code {
span.line:empty {
display: none;
}
word-wrap: break-word;
border-radius: 3px;
background-color: ${CODE_BLOCK_BG_COLOR};
font-size: var(--vscode-editor-font-size, var(--vscode-font-size, 12px));
font-family: var(--vscode-editor-font-family);
}
code:not(pre > code) {
font-family: var(--vscode-editor-font-family, monospace);
color: var(--vscode-textPreformat-foreground, #f78383);
background-color: var(--vscode-textCodeBlock-background, #1e1e1e);
padding: 0px 2px;
border-radius: 3px;
border: 1px solid var(--vscode-textSeparator-foreground, #424242);
white-space: pre-line;
word-break: break-word;
overflow-wrap: anywhere;
}
font-family: var(--vscode-font-family), system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen,
Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
font-size: var(--vscode-font-size, 13px);
p,
li,
ol,
ul {
line-height: 1.25;
}
`
const StyledPre = styled.pre<{ theme: any }>`
& .hljs {
color: var(--vscode-editor-foreground, #fff);
}
${(props) =>
Object.keys(props.theme)
.map((key, index) => {
return `
& ${key} {
color: ${props.theme[key]};
}
`
})
.join("")}
`
const MarkdownBlock = memo(({ markdown }: MarkdownBlockProps) => {
const { theme } = useExtensionState()
const [reactContent, setMarkdown] = useRemark({
remarkPlugins: [
() => {
return (tree) => {
visit(tree, "code", (node: any) => {
if (!node.lang) {
node.lang = "javascript"
} else if (node.lang.includes(".")) {
node.lang = node.lang.split(".").slice(-1)[0]
}
})
}
},
],
rehypePlugins: [
rehypeHighlight as any,
{
// languages: {},
} as Options,
],
rehypeReactOptions: {
components: {
pre: ({ node, ...preProps }: any) => <StyledPre {...preProps} theme={theme} />,
},
},
})
useEffect(() => {
setMarkdown(markdown || "")
}, [markdown, setMarkdown, theme])
return (
<div style={{}}>
<StyledMarkdown>{reactContent}</StyledMarkdown>
</div>
)
})
export default MarkdownBlock