Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
P
poc-fe
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
poc
poc-fe
Commits
a9e7f87d
Commit
a9e7f87d
authored
May 19, 2025
by
tyyin lan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix(首页): 写作编辑器功能无法携带格式
parent
ecbc18b2
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
72 additions
and
62 deletions
+72
-62
markdown-render.vue
src/components/markdown-render/markdown-render.vue
+3
-59
markdown-parser.ts
src/components/markdown-render/utils/markdown-parser.ts
+64
-0
footer-operation.vue
src/views/home/components/footer-operation.vue
+3
-2
template-input-prompt.ts
...ents/rich-text-input-box/formats/template-input-prompt.ts
+2
-1
No files found.
src/components/markdown-render/markdown-render.vue
View file @
a9e7f87d
<
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
)
=>
{
;(
marked
Inst
.
parse
(
text
)
as
Promise
<
string
>
).
then
((
res
)
=>
{
renderTextContent
.
value
=
res
})
},
...
...
src/components/markdown-render/utils/markdown-parser.ts
0 → 100644
View file @
a9e7f87d
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
)
}
src/views/home/components/footer-operation.vue
View file @
a9e7f87d
...
...
@@ -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
)
...
...
src/views/home/components/rich-text-input-box/formats/template-input-prompt.ts
View file @
a9e7f87d
...
...
@@ -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
=
''
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment