Commit a9e7f87d authored by tyyin lan's avatar tyyin lan

fix(首页): 写作编辑器功能无法携带格式

parent ecbc18b2
<script setup lang="ts">
import { computed, nextTick, ref, useTemplateRef, watchEffect } from 'vue'
import { Marked } from 'marked'
import { markedHighlight } from 'marked-highlight'
import 'katex/dist/katex.min.css'
import { throttle, debounce } from 'lodash-es'
import DOMPurify from 'dompurify'
import hljs from 'highlight.js'
// import 'highlight.js/styles/panda-syntax-light.css'
import 'highlight.js/styles/atom-one-dark.min.css'
import './style/github-markdown.css'
import markedKatex, { MarkedKatexOptions } from 'marked-katex-extension'
import { copyToClip } from '@/utils/copy'
import { useI18n } from 'vue-i18n'
import { createMarkedInst } from './utils/markdown-parser'
interface Props {
rawTextContent: string
......@@ -27,62 +23,10 @@ const props = withDefaults(defineProps<Props>(), {
darkTheme: true,
})
const katexOptions: MarkedKatexOptions = {
throwOnError: false,
displayMode: true,
nonStandard: true,
output: 'html',
}
const markdownRenderContainerRef = useTemplateRef<HTMLDivElement>('markdownRenderContainerRef')
const { t } = useI18n()
const marked = new Marked()
.use({ gfm: true, async: true, breaks: true })
.use(
markedHighlight({
emptyLangClass: 'hljs',
langPrefix: 'hljs code-container-wrapper language-',
highlight(code, lang, _info) {
const language = hljs.getLanguage(lang) ? lang : 'plaintext'
// return hljs.highlight(code, { language }).value
const str = hljs.highlight(code, { language }).value
// return `<div class="code-render-container"><div class="code-operation-bar-container"><span class="language">${language}</span><span><span class="code-copy-btn iconfont icon-fuzhi"></span><span class="fold-btn iconfont icon-left"></span></span></div><pre class="code-render-inner"><code>${str}</code></pre></div>`
return (
'<div class="code-render-container">' +
'<div class="code-operation-bar-container">' +
`<span class="language">${language}</span><span><span class="code-copy-btn iconfont icon-fuzhi"></span><span class="fold-btn iconfont icon-left"></span></span>` +
'</div>' +
`<div class="code-render-wrapper"><pre class="code-render-inner"><code>${str}</code></pre></div>` +
'</div>'
)
},
}),
)
.use(markedKatex(katexOptions))
.use({
hooks: {
preprocess(markdown: string) {
/**
* 1. 将 \(...\) 和 \\(...\\) 转为 $...$ 以支持行内公式
* 2. 将 \[...\] 和 \\[...\\] 转为 $$...$$ 以支持块级公式
*/
const katexTextReplace = markdown
.replace(/\\\\\(|\\\\\)|\\\(|\\\)/g, '$')
.replace(/\\\\\[|\\\\\]|\\\[|\\\]/g, '$$$$')
return katexTextReplace
},
postprocess(html: string) {
return DOMPurify.sanitize(html)
},
},
})
const markedInst = createMarkedInst()
let btnEventController = new AbortController()
const renderTextContent = ref('')
......@@ -96,7 +40,7 @@ const articleContainerStyle = computed(() => {
const textContentParser = throttle(
(text: string) => {
;(marked.parse(text) as Promise<string>).then((res) => {
;(markedInst.parse(text) as Promise<string>).then((res) => {
renderTextContent.value = res
})
},
......
import { Marked } from 'marked'
import { markedHighlight } from 'marked-highlight'
import DOMPurify from 'dompurify'
import hljs from 'highlight.js'
import markedKatex, { type MarkedKatexOptions } from 'marked-katex-extension'
const katexOptions: MarkedKatexOptions = {
throwOnError: false,
displayMode: true,
nonStandard: true,
output: 'html',
}
export function createMarkedInst() {
return new Marked()
.use({ gfm: true, async: true, breaks: true })
.use(
markedHighlight({
emptyLangClass: 'hljs',
langPrefix: 'hljs code-container-wrapper language-',
highlight(code, lang, _info) {
const language = hljs.getLanguage(lang) ? lang : 'plaintext'
// return hljs.highlight(code, { language }).value
const str = hljs.highlight(code, { language }).value
// return `<div class="code-render-container"><div class="code-operation-bar-container"><span class="language">${language}</span><span><span class="code-copy-btn iconfont icon-fuzhi"></span><span class="fold-btn iconfont icon-left"></span></span></div><pre class="code-render-inner"><code>${str}</code></pre></div>`
return (
'<div class="code-render-container">' +
'<div class="code-operation-bar-container">' +
`<span class="language">${language}</span><span><span class="code-copy-btn iconfont icon-fuzhi"></span><span class="fold-btn iconfont icon-left"></span></span>` +
'</div>' +
`<div class="code-render-wrapper"><pre class="code-render-inner"><code>${str}</code></pre></div>` +
'</div>'
)
},
}),
)
.use(markedKatex(katexOptions))
.use({
hooks: {
preprocess(markdown: string) {
/**
* 1. 将 \(...\) 和 \\(...\\) 转为 $...$ 以支持行内公式
* 2. 将 \[...\] 和 \\[...\\] 转为 $$...$$ 以支持块级公式
*/
const katexTextReplace = markdown
.replace(/\\\\\(|\\\\\)|\\\(|\\\)/g, '$')
.replace(/\\\\\[|\\\\\]|\\\[|\\\]/g, '$$$$')
return katexTextReplace
},
postprocess(html: string) {
return DOMPurify.sanitize(html)
},
},
})
}
export function markdownParser(markdown: string) {
return createMarkedInst().parse(markdown)
}
......@@ -17,6 +17,7 @@ import { NAvatar, NEllipsis } from 'naive-ui'
import type { SelectRenderLabel, SelectRenderTag } from 'naive-ui'
import RichTextInputBox from './rich-text-input-box/index.vue'
import type { WorkModeType } from '@/views/home/components/rich-text-input-box/types/index'
import { markdownParser } from '@/components/markdown-render/utils/markdown-parser'
interface Props {
currentSessionId: string
......@@ -240,7 +241,7 @@ function questionSubmit(question: string) {
}
},
onend: () => {
setTimeout(() => {
setTimeout(async () => {
emit('updateSpecifyMessageItem', currentLatestMessageItemKeyMap.value.get('assistant')!, {
isAnswerLoading: false,
})
......@@ -250,7 +251,7 @@ function questionSubmit(question: string) {
if (editorModeEnable.value) {
editorDrawerConfig.value = {
isShow: true,
content: messageContent,
content: await markdownParser(messageContent),
}
}
}, 100)
......
......@@ -45,16 +45,17 @@ class TemplateInputPromptBlot extends Embed {
// 'min-w-full',
// 'left-0',
// 'right-0',
'focus:outline-none',
'px-[6px]',
// 'text-[#0057ff]',
'whitespace-pre-wrap',
'break-all',
// 'outline-none',
)
inputContainerEl.style.left = '0'
inputContainerEl.style.right = '0'
inputContainerEl.style.color = '#000dff'
inputContainerEl.style.outlineStyle = 'none'
inputContainerEl.textContent = ''
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment