需求
- markdown支持数学公式
- 流式期间也要支持
解决
1.前置条件
npm install markdown-it markdown-it-highlightjs katex highlight.js vue-katex
// markdown-it是markdown解析插件 markdown-it-highlightjs是高亮 但是需要引入highlight.js样式
// vue-katex 数学公式展示 katex也是需要样式
2.代码实现
//记得把样式也一起引入进来
import VueKatex from "vue-katex";
import "katex/dist/katex.min.css";
Vue.use(VueKatex, {
globalOptions: {
//定义好界定符,好让它能够找到渲染的latex公式块
delimiters: [
{ left: "$$", right: "$$", display: true },
{ left: "$", right: "$", display: false },
{ left: "\\(", right: "\\)", display: false },
{ left: "\\[", right: "\\]", display: true },
],
throwOnError:false
//... Define globally applied KaTeX options here
},
});
<template>
<div>
<div v-katex:auto v-html="renderMdText(text)" class="mdTextBox"></div>
</div>
</template>
<script>
import MarkdownIt from "markdown-it";
import MarkdownItHighlightjs from "markdown-it-highlightjs";
import "highlight.js/styles/a11y-dark.css";
export default {
data() {
return {
text: "\\( a^2 - 2ab + b^2 = (a - b)^2 \\)",
markdownRender: new MarkdownIt({
html: true,
linkify: true,
typographer: true,
}).use(MarkdownItHighlightjs),
};
},
updated() {
let that = this;
this.$nextTick(() => {
// 获取页面上的pre和code标签
const codeBlocks = document.querySelectorAll("pre code");
codeBlocks.forEach((block) => {
let newDiv;
// 获取code标签
const preElement = block;
// 获取code标签的父元素
const parentElement = preElement.parentNode;
// 获取parentElement下的第一个div元素
const firstDiv = parentElement.querySelector("div");
// 检查是否找到了div元素
if (!firstDiv) {
// 创建一个div
newDiv = document.createElement("div");
// 给div添加文字内容
newDiv.innerText = "复制代码";
// 给div设置class样式
newDiv.setAttribute("class", "copyButton");
// 把div插入到code标签前面
parentElement.insertBefore(newDiv, preElement);
// 给div添加点击事件
newDiv.onclick = function () {
const textArea = document.createElement("textarea");
textArea.value = preElement.innerText;
document.body.appendChild(textArea);
textArea.select();
document.execCommand("copy");
document.body.removeChild(textArea);
that.$message.success('复制成功');
};
}
});
});
},
methods: {
renderMdText(text) {
//生成html
return this.markdownRender.render(text);
},
},
};
</script>
<style lang="less" scoped>
</style>
以上会有问题 \[或者(这种适配太低了 npm install katex 页面引入样式和katex markdown-it还是要有的
renderMdText(text) {
// markdown转html
text = this.markdownRender.render(text);
text = this.renderMath(text);
return text;
},
// markdown转latex
renderMath(html) {
// 匹配 $$...$$, \[...\], \(...\), and $...$
const regex =
/(\$\$([\s\S]+?)\$\$)|(\[([\s\S]+?)\])|(\(([\s\S]+?)\))|(\$([^\$]+?)\$)/g;
return html.replace(regex, (match, p1, p2, p3, p4, p5, p6, p7, p8) => {
let latex;
if (p2) {
// $$...$$
latex = p2;
} else if (p4) {
// \[...\]
latex = p4;
} else if (p6) {
// \(...\)
latex = p6;
} else if (p8) {
// $...$
latex = p8;
}
if (latex) {
try {
return `${katex.renderToString(latex, {
throwOnError: false,
})}`;
} catch (e) {
console.error("KaTeX rendering error:", e);
return match;
}
}
return match; // Return original match if no LaTeX was found
});
},
原来的vue-katex不用了 原来是自动渲染 匹配现在改为手动匹配 更精确