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
d75a3637
Commit
d75a3637
authored
Feb 26, 2025
by
nick zheng
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
chore: markdown渲染支持katex格式
parent
818694c5
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
124 additions
and
1 deletion
+124
-1
markdown-render.vue
src/components/markdown-render/markdown-render.vue
+1
-1
katex.ts
src/components/markdown-render/plugins/katex.ts
+123
-0
No files found.
src/components/markdown-render/markdown-render.vue
View file @
d75a3637
...
...
@@ -2,13 +2,13 @@
import
{
computed
,
ref
,
watchEffect
}
from
'vue'
import
{
Marked
}
from
'marked'
import
{
markedHighlight
}
from
'marked-highlight'
import
markedKatex
,
{
MarkedKatexOptions
}
from
'marked-katex-extension'
import
'katex/dist/katex.min.css'
import
{
throttle
}
from
'lodash-es'
import
DOMPurify
from
'dompurify'
import
hljs
from
'highlight.js'
import
'highlight.js/styles/panda-syntax-light.css'
import
'github-markdown-css'
import
markedKatex
,
{
MarkedKatexOptions
}
from
'./plugins/katex'
interface
Props
{
rawTextContent
:
string
...
...
src/components/markdown-render/plugins/katex.ts
0 → 100644
View file @
d75a3637
/**
* @file katex.ts
* @description markdown渲染插件,用于解析渲染katex数学公式, 依赖katex库, 请确保已经引入katex库
* @description 该插件支持公式行内公式$...$、\(...\)和块内公式$$...$$、\[...\]两种形式
*/
import
katex
,
{
KatexOptions
}
from
'katex'
import
{
MarkedExtension
,
TokenizerAndRendererExtension
,
Tokens
}
from
'marked'
export
interface
MarkedKatexOptions
extends
KatexOptions
{
nonStandard
?:
boolean
}
const
inlineRule
=
/^
(\${1,2})(?!\$)((?:\\
.|
[^\\\n])
*
?(?:\\
.|
[^\\\n\\
$
]))\1(?=[\s
?!
\\
.,:?!。,:
]
|$
)
/
const
inlineRuleNonStandard
=
/^
(\${1,2})(?!\$)((?:\\
.|
[^\\\n])
*
?(?:\\
.|
[^\\\n\\
$
]))\1
/
const
blockRule
=
/^
(?:(\${2})\n([\s\S]
+
?)\n\1
|
\\\[([\s\S]
+
?)\\\](?:\n
|$
))
/
export
default
function
(
options
:
MarkedKatexOptions
=
{}):
MarkedExtension
{
return
{
extensions
:
[
inlineKatex
(
options
,
createRenderer
(
options
,
false
)),
blockKatex
(
options
,
createRenderer
(
options
,
true
)),
],
}
}
function
createRenderer
(
options
:
MarkedKatexOptions
,
newlineAfter
:
boolean
)
{
return
(
token
:
Tokens
.
Generic
)
=>
{
return
katex
.
renderToString
(
token
.
text
,
{
...
options
,
displayMode
:
token
.
displayMode
})
+
(
newlineAfter
?
'
\
n'
:
''
)
}
}
function
inlineKatex
(
options
:
MarkedKatexOptions
,
renderer
:
(
token
:
Tokens
.
Generic
)
=>
string
,
):
TokenizerAndRendererExtension
{
const
nonStandard
=
options
&&
options
.
nonStandard
const
ruleReg
=
nonStandard
?
inlineRuleNonStandard
:
inlineRule
return
{
name
:
'inlineKatex'
,
level
:
'inline'
,
start
(
src
:
string
)
{
let
index
let
indexSrc
=
src
while
(
indexSrc
)
{
index
=
indexSrc
.
search
(
/
(?:\\\(
|
\$)
/
)
if
(
index
===
-
1
)
{
return
}
const
char
=
indexSrc
[
index
]
const
possibleKatex
=
indexSrc
.
substring
(
index
)
const
isParen
=
char
===
'
\
\'
&& indexSrc[index + 1] === '
(
'
const isDollar = char === '
$
'
const f = nonStandard ? true : index === 0 || indexSrc.charAt(index - 1).match(/
\
s/)
if (f) {
if (isDollar && possibleKatex.match(ruleReg)) {
return index
} else if (isParen && possibleKatex.match(/^
\\\
(((?:
\\
[^]|[^
\\\
n)])*?)
\\\
)/)) {
return index
}
}
indexSrc = indexSrc.substring(index + (isParen ? 2 : 1))
}
},
tokenizer(src: string) {
const dollarMatch = src.match(ruleReg)
if (dollarMatch) {
return {
type: '
inlineKatex
',
raw: dollarMatch[0],
text: dollarMatch[2].trim(),
displayMode: dollarMatch[1].length === 2,
}
}
// 匹配
\
(...
\
)包裹的内容
const parenMatch = src.match(/^
\\\
(((?:
\\
[^]|[^
\\\
n)])*?)
\\\
)/)
if (parenMatch) {
return {
type: '
inlineKatex
',
raw: parenMatch[0],
text: parenMatch[1].trim(),
displayMode: false,
}
}
},
renderer,
}
}
function blockKatex(
_options: KatexOptions,
renderer: (token: Tokens.Generic) => string,
): TokenizerAndRendererExtension {
return {
name: '
blockKatex
',
level: '
block
',
tokenizer(src: string) {
const match = src.match(blockRule)
if (match) {
// 处理 $$...$$
if (match[1]) {
return {
type: '
blockKatex
',
raw: match[0],
text: match[2].trim(),
displayMode: true,
}
} else {
// 处理
\
[...
\
]
return {
type: '
blockKatex
',
raw: match[0],
text: match[3].trim(),
displayMode: true,
}
}
}
return undefined
},
renderer,
}
}
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