style: improved syntax highlighting functionality and code loading
This commit is contained in:
parent
e11633310c
commit
bac3bad8db
@ -98,10 +98,6 @@
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
}
|
||||
|
||||
p code,
|
||||
li code {
|
||||
background: var(--color-background-mute);
|
||||
|
||||
@ -13,7 +13,7 @@ import {
|
||||
} from 'shiki'
|
||||
|
||||
interface SyntaxHighlighterContextType {
|
||||
codeToHtml: (code: string, language: string) => string
|
||||
codeToHtml: (code: string, language: string) => Promise<string>
|
||||
}
|
||||
|
||||
const SyntaxHighlighterContext = createContext<SyntaxHighlighterContextType | undefined>(undefined)
|
||||
@ -34,11 +34,10 @@ export const SyntaxHighlighterProvider: React.FC<PropsWithChildren> = ({ childre
|
||||
useEffect(() => {
|
||||
const initMermaid = async () => {
|
||||
if (!window.mermaid) {
|
||||
await loadScript('https://unpkg.com/mermaid@10.9.1/dist/mermaid.min.js')
|
||||
await loadScript('https://unpkg.com/mermaid@11.4.0/dist/mermaid.min.js')
|
||||
window.mermaid.initialize({
|
||||
startOnLoad: true,
|
||||
theme: theme === ThemeMode.dark ? 'dark' : 'default',
|
||||
securityLevel: 'loose'
|
||||
theme: theme === ThemeMode.dark ? 'dark' : 'default'
|
||||
})
|
||||
window.mermaid.contentLoaded()
|
||||
}
|
||||
@ -49,31 +48,49 @@ export const SyntaxHighlighterProvider: React.FC<PropsWithChildren> = ({ childre
|
||||
|
||||
useEffect(() => {
|
||||
const initHighlighter = async () => {
|
||||
const commonLanguages = ['javascript', 'typescript', 'python', 'java', 'markdown']
|
||||
|
||||
const hl = await createHighlighter({
|
||||
themes: Object.keys(bundledThemes),
|
||||
langs: Object.keys(bundledLanguages)
|
||||
themes: [highlighterTheme],
|
||||
langs: commonLanguages
|
||||
})
|
||||
|
||||
setHighlighter(hl)
|
||||
|
||||
window.requestIdleCallback(
|
||||
() => {
|
||||
hl.loadTheme(...(Object.keys(bundledThemes) as BundledTheme[]))
|
||||
hl.loadLanguage(...(Object.keys(bundledLanguages) as BundledLanguage[]))
|
||||
},
|
||||
{ timeout: 2000 }
|
||||
)
|
||||
}
|
||||
|
||||
initHighlighter()
|
||||
}, [])
|
||||
}, [highlighterTheme, theme])
|
||||
|
||||
const codeToHtml = (code: string, language: string) => {
|
||||
const codeToHtml = async (code: string, language: string) => {
|
||||
if (!highlighter) return ''
|
||||
|
||||
return highlighter.codeToHtml(code, {
|
||||
lang: language,
|
||||
theme: highlighterTheme,
|
||||
transformers: [
|
||||
{
|
||||
preprocess(code) {
|
||||
if (code.endsWith('\n')) code = code.slice(0, -1)
|
||||
return code
|
||||
}
|
||||
try {
|
||||
if (!highlighter.getLoadedLanguages().includes(language as BundledLanguage)) {
|
||||
if (language in bundledLanguages) {
|
||||
await highlighter.loadLanguage(language as BundledLanguage)
|
||||
console.log(`Loaded language: ${language}`)
|
||||
} else {
|
||||
console.warn(`Language '${language}' is not supported`)
|
||||
return `<pre><code>${code}</code></pre>`
|
||||
}
|
||||
]
|
||||
})
|
||||
}
|
||||
|
||||
return highlighter.codeToHtml(code, {
|
||||
lang: language,
|
||||
theme: highlighterTheme
|
||||
})
|
||||
} catch (error) {
|
||||
console.warn(`Error highlighting code for language '${language}':`, error)
|
||||
return `<pre><code>${code}</code></pre>`
|
||||
}
|
||||
}
|
||||
|
||||
return <SyntaxHighlighterContext.Provider value={{ codeToHtml }}>{children}</SyntaxHighlighterContext.Provider>
|
||||
|
||||
@ -2,7 +2,7 @@ import { CheckOutlined } from '@ant-design/icons'
|
||||
import CopyIcon from '@renderer/components/Icons/CopyIcon'
|
||||
import { useSyntaxHighlighter } from '@renderer/context/SyntaxHighlighterProvider'
|
||||
import { useSettings } from '@renderer/hooks/useSettings'
|
||||
import React, { memo, useState } from 'react'
|
||||
import React, { memo, useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
|
||||
@ -20,10 +20,16 @@ const CodeBlock: React.FC<CodeBlockProps> = ({ children, className }) => {
|
||||
const showFooterCopyButton = children && children.length > 500
|
||||
const { codeShowLineNumbers, fontSize } = useSettings()
|
||||
const language = match?.[1] ?? 'text'
|
||||
|
||||
const [html, setHtml] = useState<string>('')
|
||||
const { codeToHtml } = useSyntaxHighlighter()
|
||||
|
||||
const html = codeToHtml(children, language)
|
||||
useEffect(() => {
|
||||
const loadHighlightedCode = async () => {
|
||||
const highlightedHtml = await codeToHtml(children, language)
|
||||
setHtml(highlightedHtml)
|
||||
}
|
||||
loadHighlightedCode()
|
||||
}, [children, language, codeToHtml])
|
||||
|
||||
if (language === 'mermaid') {
|
||||
return <Mermaid chart={children} />
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user