Merge pull request #12 from devchat-ai/feat/prism

Feat/prism
This commit is contained in:
小石头 2024-01-05 16:24:26 +08:00 committed by GitHub
commit 5f88ce17ec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 166 additions and 91 deletions

View File

@ -135,6 +135,7 @@
"ncp": "^2.0.0", "ncp": "^2.0.0",
"node-fetch": "^3.3.1", "node-fetch": "^3.3.1",
"nonce": "^1.0.4", "nonce": "^1.0.4",
"prism-react-renderer": "^2.3.1",
"quote": "^0.4.0", "quote": "^0.4.0",
"react-i18next": "^13.5.0", "react-i18next": "^13.5.0",
"react-markdown": "^8.0.7", "react-markdown": "^8.0.7",

View File

@ -1,10 +1,10 @@
import { Accordion, Box, Button, Collapse, Group,Loader,Text } from "@mantine/core"; import { Accordion, Loader, Text } from "@mantine/core";
import { useDisclosure } from "@mantine/hooks"; import { useDisclosure } from "@mantine/hooks";
import React from "react"; import React from "react";
import SyntaxHighlighter from "react-syntax-highlighter"; import SyntaxHighlighter from "react-syntax-highlighter";
import LanguageCorner from "./LanguageCorner"; import { Highlight, themes } from "prism-react-renderer";
import { okaidia } from "react-syntax-highlighter/dist/esm/styles/prism"; import { okaidia } from "react-syntax-highlighter/dist/esm/styles/prism";
import { IconCheck, IconChevronDown, IconFileDiff, IconLoader } from "@tabler/icons-react"; import { IconCheck } from "@tabler/icons-react";
import { observer } from "mobx-react-lite"; import { observer } from "mobx-react-lite";
import { useMst } from "@/views/stores/RootStore"; import { useMst } from "@/views/stores/RootStore";
import { keyframes, css } from "@emotion/react"; import { keyframes, css } from "@emotion/react";
@ -22,8 +22,11 @@ const Step = observer((props:StepProps) => {
const [opened, { toggle }] = useDisclosure(false); const [opened, { toggle }] = useDisclosure(false);
// extract first line with # as button label // extract first line with # as button label
const lines = children.split('\n'); const lines = children.split("\n");
const title = lines.length>0&&lines[0].indexOf('#')>=0?lines[0].split('#')[1]:'Thinking...'; const title =
lines.length > 0 && lines[0].indexOf("#") >= 0
? lines[0].split("#")[1]
: "Thinking...";
const contents = lines.slice(1, lines.length - 1); const contents = lines.slice(1, lines.length - 1);
const spin = keyframes` const spin = keyframes`
@ -31,77 +34,99 @@ const Step = observer((props:StepProps) => {
100% { transform: rotate(360deg); } 100% { transform: rotate(360deg); }
`; `;
return <Accordion return (
<Accordion
variant="contained" variant="contained"
chevronPosition="right" chevronPosition="right"
sx={{ sx={{
marginTop: 5, marginTop: 5,
borderRadius: 5, borderRadius: 5,
backgroundColor: 'var(--vscode-menu-background)', backgroundColor: "var(--vscode-menu-background)",
}} }}
styles={{ styles={{
item: { item: {
borderColor: 'var(--vscode-menu-border)', borderColor: "var(--vscode-menu-border)",
backgroundColor: 'var(--vscode-menu-background)', backgroundColor: "var(--vscode-menu-background)",
'&[data-active]': { "&[data-active]": {
backgroundColor: 'var(--vscode-menu-background)', backgroundColor: "var(--vscode-menu-background)",
} },
}, },
control: { control: {
height: 30, height: 30,
borderRadius: 3, borderRadius: 3,
backgroundColor: 'var(--vscode-menu-background)', backgroundColor: "var(--vscode-menu-background)",
'&[aria-expanded="true"]': { '&[aria-expanded="true"]': {
borderBottomLeftRadius: 0, borderBottomLeftRadius: 0,
borderBottomRightRadius: 0, borderBottomRightRadius: 0,
}, },
'&:hover': { "&:hover": {
backgroundColor: 'var(--vscode-menu-background)', backgroundColor: "var(--vscode-menu-background)",
}, },
paddingLeft: '0.5rem', paddingLeft: "0.5rem",
paddingRight: '0.5rem', paddingRight: "0.5rem",
fontFamily: 'var(--vscode-editor-font-familyy)', fontFamily: "var(--vscode-editor-font-familyy)",
fontSize: 'var(--vscode-editor-font-size)', fontSize: "var(--vscode-editor-font-size)",
}, },
chevron: { chevron: {
color: 'var(--vscode-menu-foreground)', color: "var(--vscode-menu-foreground)",
}, },
icon: { icon: {
color: 'var(--vscode-menu-foreground)', color: "var(--vscode-menu-foreground)",
}, },
label: { label: {
color: 'var(--vscode-menu-foreground)', color: "var(--vscode-menu-foreground)",
}, },
panel: { panel: {
color: 'var(--vscode-menu-foreground)', color: "var(--vscode-menu-foreground)",
backgroundColor: 'var(--vscode-menu-background)', backgroundColor: "var(--vscode-menu-background)",
}, },
content: { content: {
borderRadius: 3, borderRadius: 3,
backgroundColor: 'var(--vscode-menu-background)', backgroundColor: "var(--vscode-menu-background)",
padding:'0.5rem' padding: "0.5rem",
} },
}} }}
> >
<Accordion.Item value={'step'+index} mah='200'> <Accordion.Item value={"step" + index} mah="200">
<Accordion.Control icon={ <Accordion.Control
status === "done" icon={
?<IconCheck size="1.125rem"/> status === "done" ? (
:<Loader size="xs" color="#ED6A45" speed={1} /> <IconCheck size="1.125rem" />
) : (
<Loader size="xs" color="#ED6A45" speed={1} />
)
} }
> >
<Text truncate='end' w={chat.chatPanelWidth-100}>{title}</Text> <Text truncate="end" w={chat.chatPanelWidth - 100}>
{title}
</Text>
</Accordion.Control> </Accordion.Control>
<Accordion.Panel> <Accordion.Panel>
<SyntaxHighlighter {...props} <Highlight code={children} theme={themes.okaidia} language="markdown">
language="markdown" {({ className, style, tokens, getLineProps, getTokenProps }) => (
style={okaidia} <pre
PreTag="div"> className={className}
{children} style={{
</SyntaxHighlighter> ...style,
borderRadius: "5px",
padding: "10px 15px",
}}
{...props}
>
{tokens.map((line, i) => (
<div {...getLineProps({ line, key: i })}>
{line.map((token, key) => (
<span {...getTokenProps({ token, key })} />
))}
</div>
))}
</pre>
)}
</Highlight>
</Accordion.Panel> </Accordion.Panel>
</Accordion.Item> </Accordion.Item>
</Accordion>; </Accordion>
);
}); });
export default Step; export default Step;

View File

@ -2,8 +2,7 @@ import { Button, Anchor, Stack, Group, Box, createStyles } from "@mantine/core";
import React, { useEffect, useMemo, useState } from "react"; import React, { useEffect, useMemo, useState } from "react";
import ReactMarkdown from "react-markdown"; import ReactMarkdown from "react-markdown";
import rehypeRaw from "rehype-raw"; import rehypeRaw from "rehype-raw";
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter"; import { Highlight, themes } from "prism-react-renderer";
import { okaidia } from "react-syntax-highlighter/dist/esm/styles/prism";
import CodeButtons from "./CodeButtons"; import CodeButtons from "./CodeButtons";
import Step from "./Step"; import Step from "./Step";
import LanguageCorner from "./LanguageCorner"; import LanguageCorner from "./LanguageCorner";
@ -355,7 +354,7 @@ Generate a professionally written and formatted release note in markdown with th
> >
<LanguageCorner language={lanugage} /> <LanguageCorner language={lanugage} />
<CodeButtons language={lanugage} code={value} /> <CodeButtons language={lanugage} code={value} />
<SyntaxHighlighter {/* <SyntaxHighlighter
{...props} {...props}
language={lanugage} language={lanugage}
customStyle={{ padding: "35px 10px 10px 10px" }} customStyle={{ padding: "35px 10px 10px 10px" }}
@ -364,7 +363,39 @@ Generate a professionally written and formatted release note in markdown with th
PreTag="div" PreTag="div"
> >
{value} {value}
</SyntaxHighlighter> </SyntaxHighlighter> */}
<Highlight
code={value}
theme={themes.okaidia}
language={lanugage}
>
{({
className,
style,
tokens,
getLineProps,
getTokenProps,
}) => (
<pre
className={className}
style={{
...style,
padding: "35px 10px 10px 10px",
borderRadius: "5px",
...props.style,
}}
{...props}
>
{tokens.map((line, i) => (
<div {...getLineProps({ line, key: i })}>
{line.map((token, key) => (
<span {...getTokenProps({ token, key })} />
))}
</div>
))}
</pre>
)}
</Highlight>
</div> </div>
) : ( ) : (
<code {...props} className={className}> <code {...props} className={className}>
@ -395,7 +426,7 @@ Generate a professionally written and formatted release note in markdown with th
styles={{ styles={{
root: { root: {
marginBottom: 10, marginBottom: 10,
} },
}} }}
onClick={() => { onClick={() => {
value === "get_devchat_key" && platform === "idea" value === "get_devchat_key" && platform === "idea"

View File

@ -2218,6 +2218,11 @@
resolved "https://registry.yarnpkg.com/@types/parse5/-/parse5-6.0.3.tgz#705bb349e789efa06f43f128cef51240753424cb" resolved "https://registry.yarnpkg.com/@types/parse5/-/parse5-6.0.3.tgz#705bb349e789efa06f43f128cef51240753424cb"
integrity sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g== integrity sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g==
"@types/prismjs@^1.26.0":
version "1.26.3"
resolved "https://registry.yarnpkg.com/@types/prismjs/-/prismjs-1.26.3.tgz#47fe8e784c2dee24fe636cab82e090d3da9b7dec"
integrity sha512-A0D0aTXvjlqJ5ZILMz3rNfDBOx9hHxLZYv2by47Sm/pqW35zzjusrZTryatjN/Rf8Us2gZrJD+KeHbUSTux1Cw==
"@types/prop-types@*", "@types/prop-types@^15.0.0": "@types/prop-types@*", "@types/prop-types@^15.0.0":
version "15.7.11" version "15.7.11"
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.11.tgz#2596fb352ee96a1379c657734d4b913a613ad563" resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.11.tgz#2596fb352ee96a1379c657734d4b913a613ad563"
@ -3256,6 +3261,11 @@ clsx@1.1.1:
resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.1.1.tgz#98b3134f9abbdf23b2663491ace13c5c03a73188" resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.1.1.tgz#98b3134f9abbdf23b2663491ace13c5c03a73188"
integrity sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA== integrity sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA==
clsx@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.1.0.tgz#e851283bcb5c80ee7608db18487433f7b23f77cb"
integrity sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg==
co@^4.6.0: co@^4.6.0:
version "4.6.0" version "4.6.0"
resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
@ -6874,6 +6884,14 @@ prism-react-renderer@^1.2.1:
resolved "https://registry.yarnpkg.com/prism-react-renderer/-/prism-react-renderer-1.3.5.tgz#786bb69aa6f73c32ba1ee813fbe17a0115435085" resolved "https://registry.yarnpkg.com/prism-react-renderer/-/prism-react-renderer-1.3.5.tgz#786bb69aa6f73c32ba1ee813fbe17a0115435085"
integrity sha512-IJ+MSwBWKG+SM3b2SUfdrhC+gu01QkV2KmRQgREThBfSQRoufqRfxfHUxpG1WcaFjP+kojcFyO9Qqtpgt3qLCg== integrity sha512-IJ+MSwBWKG+SM3b2SUfdrhC+gu01QkV2KmRQgREThBfSQRoufqRfxfHUxpG1WcaFjP+kojcFyO9Qqtpgt3qLCg==
prism-react-renderer@^2.3.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/prism-react-renderer/-/prism-react-renderer-2.3.1.tgz#e59e5450052ede17488f6bc85de1553f584ff8d5"
integrity sha512-Rdf+HzBLR7KYjzpJ1rSoxT9ioO85nZngQEoFIhL07XhtJHlCU3SOz0GJ6+qvMyQe0Se+BV3qpe6Yd/NmQF5Juw==
dependencies:
"@types/prismjs" "^1.26.0"
clsx "^2.0.0"
prismjs@^1.27.0: prismjs@^1.27.0:
version "1.29.0" version "1.29.0"
resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.29.0.tgz#f113555a8fa9b57c35e637bba27509dcf802dd12" resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.29.0.tgz#f113555a8fa9b57c35e637bba27509dcf802dd12"