vue3 在渲染md中的数学公式

常规的md转数学公式插件无法解决此问题

问题: 在渲染过程中 \t 被转义 导致渲染出错

**方案为:将\t 转义为\t **

依赖的插件及版本

    "katex": "^0.16.15",
    "markdown-it": "^14.1.0",
    "markdown-it-katex": "^2.0.3",
    "markdown-it-latex": "^0.2.0",
    "markdown-it-mathjax": "^2.0.0",
    "markdown-it-multimd-table": "^4.2.3",
    "markdown-it-texmath": "^1.0.0",
    "mathjax": "^3.2.2",
    "vue-markdown": "^2.2.4",

utils 文件

mathjax.js

window.MathJax = {
    tex: {
        inlineMath: [
            ["$", "$"],
            ["\\(", "\\)"],
            ["\(", "\)"],
            ["\\[", "\\]"],
        ], // 行内公式选择符
        displayMath: [
            ["$$", "$$"],
            ["\\[", "\\]"],
            ['?', '?'],
        ], // 段内公式选择符
    },
    startup: {
        ready() {
            MathJax.startup.defaultReady();
        },
    },
};

引入代码

在html中引入
<script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js"></script>

vue文件中

import MarkdownIt from 'markdown-it';
import markdownItMathjax from 'markdown-it-mathjax';
import mk from 'markdown-it-katex';
import mkl from 'markdown-it-latex';

import 'katex/dist/katex.min.css';
import 'github-markdown-css';

如果是vue3+ts项目 则需要在声明文件,定义全局变量,要不然会有提示信息

// 声明文件,定义全局变量
/* eslint-disable */
declare interface Window {
	nextLoading: boolean;
	MathJax: any;  // 这里先使用any类型占位,如果知道MathJax确切结构可替换为更准确类型
}

举例
image

方法调用

const preprocessLaTeX = (content: string) => {
	if (typeof content !== 'string') return content;
	return content
		.replace(/\\\[(.*?)\\\]/gs, (_, equation) => `$$${equation}$$`)
		.replace(/\\\((.*?)\\\)/gs, (_, equation) => `$$${equation}$$`)
		.replace(/(^|[^\\])\$(.+?)\$/gs, (_, prefix, equation) => `${prefix}$${equation}$`)
		.replace(/\t/g, '\\t');
};

const md = new MarkdownIt({
	html: true,
	linkify: true,
	typographer: true,
});
md.use(markdownItMathjax);
md.use(mk, {
	throwOnError: false,
});
md.use(mkl);


const renderMd = (text: string) => {
	window.MathJax.startup.defaultReady();
	text = preprocessLaTeX(text);
	return md.render(text);
};

renderMd中传入的是需要 渲染到md中的文本

注意事项

就不需要在main.ts中引入

方案二

需要的依赖
package.json

   "katex": "^0.16.15",
    "markdown-it": "^14.1.0",
    "markdown-it-katex": "^2.0.3",
    "markdown-it-latex": "^0.2.0",
    "markdown-it-mathjax": "^2.0.0",
    "markdown-it-multimd-table": "^4.2.3",
    "markdown-it-texmath": "^1.0.0",
    "mathjax": "^3.2.2",

image

index.html

<script>
		window.MathJax = {
			tex: {
				inlineMath: [
					["$", "$"],
					["\\(", "\\)"],
					["\(", "\)"],
					["\\[", "\\]"],
				], // 行内公式选择符
				displayMath: [
					["$$", "$$"],
					["\\[", "\\]"],
					['?', '?'],
				], // 段内公式选择符
			},
			startup: {
				ready() {
					MathJax.startup.defaultReady();
				},
			},
		};
	</script>
	
	
	<script id="MathJax-script" async src="/utils/tex-svg.js"></script>

public/utils/tex-svg.js
tex-svg.js

src/types/global.d.ts

// 声明文件,定义全局变量
/* eslint-disable */
declare interface Window {
	nextLoading: boolean;
	MathJax: any;  // 这里先使用any类型占位,如果知道MathJax确切结构可替换为更准确类型
}

页面中引入

import MarkdownIt from 'markdown-it';
import markdownItMultimdTable from 'markdown-it-multimd-table';
import markdownItMathjax from 'markdown-it-mathjax';
import mk from 'markdown-it-katex';
import mkl from 'markdown-it-latex';
import 'katex/dist/katex.min.css';
import 'github-markdown-css';

使用示例

// ======================================md 渲染
<div class="text markdown-body" v-html="renderMd(item.text, index)"></div>
// ======================================md 解析

const preprocessLaTeX = (content: string) => {
	if (typeof content !== 'string') return content;
	return (
		content
			// .replace(/\\text\{([^}]+)\}/g, function (match, p1) {
			// 	return '$ \\' + match + ' $';
			// })
			.replace(/\\\[(.*?)\\\]/gs, (_, equation) => `$$${equation}$$`)
			.replace(/\\\((.*?)\\\)/gs, (_, equation) => `$$${equation}$$`)
			.replace(/(^|[^\\])\$(.+?)\$/gs, (_, prefix, equation) => `${prefix}$${equation}$`)
			.replace(/\text\{([^}]+)\}/g, '($1)')
			.replace(/\times/g, '\\times')
	);
};

onMounted(() => {
	// window.MathJax.startup.defaultReady();
	// window.MathJax.typesetPromise()
});

const md = new MarkdownIt({
	html: true,
	linkify: true, // 自动识别链接
	typographer: true, // 启用一些语言学的替换和格式
	// html: false, // 禁用 HTML 标签
	xhtmlOut: false, // 不使用 '/' 来闭合单标签
	breaks: true, // 将连续的两个换行转换为 `<br>` 标签
});
md.use(markdownItMultimdTable);
md.use(markdownItMathjax);
md.use(mk, {
	throwOnError: false,
});
md.use(mkl);

const defaultRender =
	md.renderer.rules.link_open ||
	function (tokens, idx, options, env, self) {
		return self.renderToken(tokens, idx, options);
	};

md.renderer.rules.link_open = function (tokens, idx, options, env, self) {
	// If you are sure other plugins can't add `target` - drop check below
	var aIndex = tokens[idx].attrIndex('target');
	if (aIndex < 0) {
		tokens[idx].attrPush(['target', '_blank']); // add new attribute
	} else {
		tokens[idx].attrs[aIndex][1] = '_blank'; // replace value of existing attr
	}
	// pass token to default renderer.
	return defaultRender(tokens, idx, options, env, self);
};

const renderMd = (text: string, index: number) => {
	window.MathJax.startup.defaultReady();
	text = preprocessLaTeX(text);
	return md.render(text);
};

// =====================================
posted @ 2025-01-03 16:42  混名汪小星  阅读(1152)  评论(2)    收藏  举报