vue+markdown+latex公式
·
1.下载包
npm i github-markdown-css highlight.js marked marked-highlight mathjax --s

我本地node版本22.14.0
2.新建MathJax.js
在markdown.vue中引用
let isMathjaxConfig = false;
const initMathjaxConfig = () => {
if (!window.MathJax) {
return;
}
window.MathJax = {
tex: {
inlineMath: [
["$", "$"],
["\\(", "\\)"],
], // ⾏内公式选择符
displayMath: [
["$$", "$$"],
["\\[", "\\]"],
], // 段内公式选择符
},
options: {
skipHtmlTags: [
"script",
"noscript",
"style",
"textarea",
"pre",
"code",
"a",
], // 避开某些标签
ignoreHtmlClass: "tex2jax_ignore",
processHtmlClass: "tex2jax_process",
},
};
isMathjaxConfig = true;
};
const TypeSet = async function (elementId) {
if (!window.MathJax) {
return;
}
window.MathJax.startup.promise = window.MathJax.startup.promise
.then(() => {
return window.MathJax.typesetPromise();
})
.catch((err) => console.log("Typeset failed: " + err.message));
return window.MathJax.startup.promise;
};
export default {
isMathjaxConfig,
initMathjaxConfig,
TypeSet,
};
3.markdown.vue文件
<template>
<div v-html="htmlContent" class="markdown-body"></div>
</template>
<script>
import {defineComponent, nextTick, onMounted, ref, watch} from 'vue';
import {Marked} from 'marked';
import {markedHighlight} from 'marked-highlight';
import hljs from 'highlight.js';
import 'highlight.js/styles/github.css';
import 'github-markdown-css/github-markdown-light.css';
import mathJax from "@/util/MathJax.js";
import "mathjax/es5/tex-svg"; // 使用 tex-svg.js
let doCopy = function (e) {
const code = this.parentNode.parentNode.querySelector('code');
navigator.clipboard
.writeText(code.innerText)
.then(() => {
alert('复制成功');
})
.catch((error) => {
alert('复制失败');
});
}
export default defineComponent({
name: 'DynamicMarkdown',
props: {
value: {
type: String,
required: true,
},
},
setup(props) {
const htmlContent = ref('');
// 初始化 marked 实例
const marked = new Marked(
markedHighlight({
async: false,
langPrefix: 'language-',
emptyLangClass: 'no-lang',
highlight: (code, language) => {
// 代码高亮自动识别语言的关键就在这里
return hljs.highlightAuto(code, [language]).value;
},
})
);
// 增强代码块功能
const enhanceCodeBlock = (content) => {
return content.replace(/<pre><code/g, '<pre><div class="enhance"><div class="copyCode">复制</div></div><code');
};
// 复制功能绑定
const bindCopyFunction = (el) => {
const codeBlocks = el.querySelectorAll('pre');
codeBlocks.forEach((codeBlock) => {
const enhance = codeBlock.querySelector('.enhance');
if (enhance) {
const copyCode = enhance.querySelector('.copyCode');
if (copyCode) {
copyCode.removeEventListener('click', doCopy);
copyCode.addEventListener('click', doCopy);
}
}
});
};
// 解析 Markdown 内容
const parseMarkdown = () => {
htmlContent.value = props.value
// 这里是关键,很多人就折在这了,时序上一定是先转公式,再取出来转Markdown,最后转代码
nextTick(()=>{
// 先转公式
if (mathJax) {
if (mathJax.isMathjaxConfig) {
mathJax.initMathjaxConfig()
}
mathJax.TypeSet()
}
nextTick(()=>{
htmlContent.value=document.querySelector('.markdown-body').innerHTML
htmlContent.value = enhanceCodeBlock(marked.parse(htmlContent.value));
nextTick(() => {
const el = document.querySelector('.markdown-body');
if (el) {
bindCopyFunction(el);
}
});
})
})
};
// 监听 value 变化
watch(
() => props.value,
(newValue, oldValue) => {
if (newValue) {
parseMarkdown();
}
},
{immediate: true}
);
onMounted(() => {
if (props.value) {
parseMarkdown();
}
});
return {
htmlContent,
};
},
});
</script>
<style >
</style>
4.引用markdown.vue
新建demo.vue
<template>
<MarkDown :value="content"></MarkDown>
</template>
<script setup>
import { ref, onMounted } from 'vue';
import MarkDown from './MarkDown.vue'
const content = ref('')
// md文档导入
const mdModules = import.meta.glob('./提交示例.md', { as: 'raw' })
onMounted(async () => {
content.value = await mdModules['./提交示例.md']()
})
</script>
5.效果图

更多推荐

所有评论(0)