<template>
<div ref="mathContainer" class="math-container">
<slot></slot>
</div>
</template>
<script>
export default {
name: 'MathJaxRenderer',
props: {
content: {
type: String,
default: '',
},
options: {
type: Object,
default: () => ({}),
},
},
data() {
return {
mathContainer: null,
};
},
watch: {
content: {
handler(newContent) {
if (this.mathContainer && newContent) {
this.mathContainer.innerHTML = newContent;
this.renderMathJax();
}
},
immediate: true,
},
},
methods: {
refreshMathJax() {
if (!this.mathContainer) {
this.mathContainer = this.$refs.mathContainer;
}
this.renderMathJax();
return new Promise((resolve) => {
this.$nextTick(() => {
resolve();
});
});
},
configureMathJax() {
window.MathJax = {
tex: {
inlineMath: [
['\\(', '\\)'],
['$', '$'],
],
displayMath: [
['$$', '$$'],
['\\[', '\\]'],
],
packages: [
'base',
'ams',
'noerrors',
'noundefined',
'newcommand',
'boldsymbol',
'cancel',
'color',
'enclose',
'mhchem',
'physics',
],
macros: {
'\\mathbb': '\\mathbf',
'\\R': '\\mathbb{R}',
'\\N': '\\mathbb{N}',
'\\Z': '\\mathbb{Z}',
'\\Q': '\\mathbb{Q}',
'\\C': '\\mathbb{C}',
'\\lim': '\\lim\\limits',
'\\sum': '\\sum\\limits',
'\\int': '\\int\\limits',
'\\iint': '\\iint\\limits',
'\\iiint': '\\iiint\\limits',
'\\prod': '\\prod\\limits',
'\\frac': '\\frac',
'\\sqrt': '\\sqrt',
'\\sin': '\\sin',
'\\cos': '\\cos',
'\\tan': '\\tan',
'\\cot': '\\cot',
'\\sec': '\\sec',
'\\csc': '\\csc',
'\\arcsin': '\\arcsin',
'\\arccos': '\\arccos',
'\\arctan': '\\arctan',
'\\sinh': '\\sinh',
'\\cosh': '\\cosh',
'\\tanh': '\\tanh',
'\\infty': '\\infty',
'\\partial': '\\partial',
'\\nabla': '\\nabla',
'\\pi': '\\pi',
'\\epsilon': '\\epsilon',
'\\delta': '\\delta',
'\\Delta': '\\Delta',
'\\begin{matrix}': '\\begin{matrix}',
'\\end{matrix}': '\\end{matrix}',
'\\begin{pmatrix}': '\\begin{pmatrix}',
'\\end{pmatrix}': '\\end{pmatrix}',
'\\begin{bmatrix}': '\\begin{bmatrix}',
'\\end{bmatrix}': '\\end{bmatrix}',
'\\begin{align}': '\\begin{align}',
'\\end{align}': '\\end{align}',
'\\begin{aligned}': '\\begin{aligned}',
'\\end{aligned}': '\\end{aligned}',
'\\to': '\\to',
'\\mapsto': '\\mapsto',
'\\Rightarrow': '\\Rightarrow',
'\\Leftarrow': '\\Leftarrow',
'\\Leftrightarrow': '\\Leftrightarrow',
},
processEscapes: true,
processEnvironments: true,
processRefs: true,
tags: 'ams',
},
options: {
enableMenu: false,
...this.options,
renderActions: {
addMenu: [0, '', ''],
checkLoading: [1000, () => '', ''],
},
ignoreHtmlClass: 'tex2jax_ignore',
processHtmlClass: 'tex2jax_process',
},
startup: {
pageReady: () => {
return window.MathJax.startup.defaultPageReady();
},
},
loader: {
load: [
'[tex]/color',
'[tex]/cancel',
'[tex]/enclose',
'[tex]/mhchem',
'[tex]/physics',
],
},
};
},
renderMathJax() {
if (window.MathJax && window.MathJax.typesetPromise) {
if (window.MathJax.typesetClear) {
window.MathJax.typesetClear([this.mathContainer]);
}
this.$nextTick(() => {
window.MathJax.typesetPromise([this.mathContainer])
.then(() => {
console.log('MathJax渲染完成');
})
.catch((err) => {
console.error('MathJax渲染错误:', err);
});
});
}
},
loadMathJax() {
return new Promise((resolve) => {
const script = document.createElement('script');
script.src =
'https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js';
script.async = true;
document.head.appendChild(script);
script.onload = (e) => {
if (window.MathJax && window.MathJax.typesetPromise) {
this.configureMathJax();
this.renderMathJax();
resolve();
} else {
setTimeout(checkMathJax, 100);
}
};
});
},
},
mounted() {
this.mathContainer = this.$refs.mathContainer;
this.loadMathJax();
},
updated() {
this.renderMathJax();
},
};
</script>
<style scoped>
.math-container {
font-family: 'Times New Roman', serif;
line-height: 1.6;
}
</style>