feat: add Mermaid render

This commit is contained in:
kangfenmao 2024-07-23 17:59:53 +08:00
parent 764aadd234
commit 4036c36753
6 changed files with 46 additions and 2 deletions

View File

@ -7,7 +7,7 @@
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP --> <!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
<meta <meta
http-equiv="Content-Security-Policy" http-equiv="Content-Security-Policy"
content="default-src 'self'; connect-src *; script-src 'self'; worker-src 'self' blob:; style-src 'self' 'unsafe-inline' *; font-src 'self' *; img-src 'self' data:" /> content="default-src 'self'; connect-src *; script-src 'self' *; worker-src 'self' blob:; style-src 'self' 'unsafe-inline' *; font-src 'self' *; img-src 'self' data:" />
</head> </head>
<body theme-mode="dark"> <body theme-mode="dark">

View File

@ -9,5 +9,6 @@ declare global {
message: MessageInstance message: MessageInstance
modal: HookAPI modal: HookAPI
keyv: KeyvStorage keyv: KeyvStorage
mermaid: any
} }
} }

View File

@ -1,7 +1,7 @@
import localforage from 'localforage' import localforage from 'localforage'
import KeyvStorage from '@kangfenmao/keyv-storage' import KeyvStorage from '@kangfenmao/keyv-storage'
import * as Sentry from '@sentry/electron/renderer' import * as Sentry from '@sentry/electron/renderer'
import { isProduction } from './utils' import { isProduction, loadScript } from './utils'
async function initSentry() { async function initSentry() {
if (await isProduction()) { if (await isProduction()) {
@ -21,6 +21,15 @@ async function initSentry() {
} }
} }
async function initMermaid() {
await loadScript('https://unpkg.com/mermaid@10.9.1/dist/mermaid.min.js')
window.mermaid.initialize({
startOnLoad: true,
theme: 'dark',
securityLevel: 'loose'
})
}
function init() { function init() {
localforage.config({ localforage.config({
driver: localforage.INDEXEDDB, driver: localforage.INDEXEDDB,
@ -34,6 +43,7 @@ function init() {
window.keyv.init() window.keyv.init()
initSentry() initSentry()
initMermaid()
} }
init() init()

View File

@ -4,6 +4,7 @@ import { atomDark } from 'react-syntax-highlighter/dist/esm/styles/prism'
import styled from 'styled-components' import styled from 'styled-components'
import { CopyOutlined } from '@ant-design/icons' import { CopyOutlined } from '@ant-design/icons'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import Mermaid from './Mermaid'
interface CodeBlockProps { interface CodeBlockProps {
children: string children: string
@ -21,6 +22,10 @@ const CodeBlock: React.FC<CodeBlockProps> = ({ children, className, ...rest }) =
window.message.success({ content: t('message.copied'), key: 'copy-code' }) window.message.success({ content: t('message.copied'), key: 'copy-code' })
} }
if (match && match[1] === 'mermaid') {
return <Mermaid chart={children} />
}
return match ? ( return match ? (
<div> <div>
<CodeHeader> <CodeHeader>

View File

@ -0,0 +1,15 @@
import React, { useEffect } from 'react'
interface Props {
chart: string
}
const Mermaid: React.FC<Props> = ({ chart }) => {
useEffect(() => {
window?.mermaid?.contentLoaded()
}, [])
return <div className="mermaid">{chart}</div>
}
export default Mermaid

View File

@ -207,3 +207,16 @@ export function estimateHistoryTokenCount(assistant: Assistant, msgs: Message[])
export const isValidProxyUrl = (url: string) => { export const isValidProxyUrl = (url: string) => {
return url.includes('://') return url.includes('://')
} }
export function loadScript(url: string) {
return new Promise((resolve, reject) => {
const script = document.createElement('script')
script.type = 'text/javascript'
script.src = url
script.onload = resolve
script.onerror = reject
document.head.appendChild(script)
})
}