UNPKG

vditor

Version:

♏ 易于使用的 Markdown 编辑器,为适配不同的应用场景而生

149 lines (140 loc) 6.16 kB
import {Constants} from "../constants"; import {addScript, addScriptSync} from "../util/addScript"; import {addStyle} from "../util/addStyle"; import {code160to32} from "../util/code160to32"; import {mathRenderAdapter} from "./adapterRender"; declare const katex: { renderToString(math: string, option: { displayMode: boolean; output: string; macros: object; }): string; }; declare global { interface Window { MathJax: any; } } export const mathRender = (element: (HTMLElement | Document) = document, options?: { cdn?: string, math?: IMath }) => { const mathElements = mathRenderAdapter.getElements(element); if (mathElements.length === 0) { return; } const defaultOptions = { cdn: Constants.CDN, math: { engine: "KaTeX", inlineDigit: false, macros: {}, }, }; if (options && options.math) { options.math = Object.assign({}, defaultOptions.math, options.math); } options = Object.assign({}, defaultOptions, options); if (options.math.engine === "KaTeX") { addStyle(`${options.cdn}/dist/js/katex/katex.min.css?v=0.16.9`, "vditorKatexStyle"); addScript(`${options.cdn}/dist/js/katex/katex.min.js?v=0.16.9`, "vditorKatexScript").then(() => { addScript(`${options.cdn}/dist/js/katex/mhchem.min.js?v=0.16.9`, "vditorKatexChemScript").then(() => { mathElements.forEach((mathElement) => { if (mathElement.parentElement.classList.contains("vditor-wysiwyg__pre") || mathElement.parentElement.classList.contains("vditor-ir__marker--pre")) { return; } if (mathElement.getAttribute("data-math")) { return; } const math = code160to32(mathRenderAdapter.getCode(mathElement)); mathElement.setAttribute("data-math", math); try { mathElement.innerHTML = katex.renderToString(math, { displayMode: mathElement.tagName === "DIV", output: "html", macros: options.math.macros, }); } catch (e) { mathElement.innerHTML = e.message; mathElement.className = "language-math vditor-reset--error"; } mathElement.addEventListener("copy", (event: ClipboardEvent) => { event.stopPropagation(); event.preventDefault(); const vditorMathElement = (event.currentTarget as HTMLElement).closest(".language-math"); event.clipboardData.setData("text/html", vditorMathElement.innerHTML); event.clipboardData.setData("text/plain", vditorMathElement.getAttribute("data-math")); }); }); }); }); } else if (options.math.engine === "MathJax") { const chainAsync = (fns: any) => { if (fns.length === 0) { return; } let curr = 0; const last = fns[fns.length - 1]; const next = () => { const fn = fns[curr++]; fn === last ? fn() : fn(next); }; next(); }; if (!window.MathJax) { window.MathJax = { loader: { paths: {mathjax: `${options.cdn}/dist/js/mathjax`}, }, startup: { typeset: false, }, tex: { macros: options.math.macros, }, }; // https://github.com/Vanessa219/vditor/issues/1453 Object.assign(window.MathJax, options.math.mathJaxOptions); } // 循环加载会抛异常 addScriptSync(`${options.cdn}/dist/js/mathjax/tex-svg-full.js`, "protyleMathJaxScript"); const renderMath = (mathElement: Element, next?: () => void) => { const math = code160to32(mathElement.textContent).trim(); const mathOptions = window.MathJax.getMetricsFor(mathElement); mathOptions.display = mathElement.tagName === "DIV"; window.MathJax.tex2svgPromise(math, mathOptions).then((node: Element) => { mathElement.innerHTML = ""; mathElement.setAttribute("data-math", math); mathElement.append(node); window.MathJax.startup.document.clear(); window.MathJax.startup.document.updateDocument(); const errorTextElement = node.querySelector('[data-mml-node="merror"]'); if (errorTextElement && errorTextElement.textContent.trim() !== "") { mathElement.innerHTML = errorTextElement.textContent.trim(); mathElement.className = "vditor-reset--error"; } if (next) { next(); } }); }; window.MathJax.startup.promise.then(() => { const chains: any[] = []; for (let i = 0; i < mathElements.length; i++) { const mathElement = mathElements[i]; if (!mathElement.parentElement.classList.contains("vditor-wysiwyg__pre") && !mathElement.parentElement.classList.contains("vditor-ir__marker--pre") && !mathElement.getAttribute("data-math") && code160to32(mathElement.textContent).trim()) { chains.push((next: () => void) => { if (i === mathElements.length - 1) { renderMath(mathElement); } else { renderMath(mathElement, next); } }); } } chainAsync(chains); }); } };