目录python渲染linux 还需要安装python实时渲染代码js前端渲染katex和mathjax比较1. 兼容性MathJax 更胜一筹2. 纠错能力MathJax 更加智能3. 性能对比KaTeX 遥遥领先总结与选型建议katex公式渲染mathjax公式实时渲染mathjax公式渲染示例python渲染pip install playwright playwright install chromiumlinux 还需要安装sudo apt install libgbm1python实时渲染代码import time from playwright.sync_api import sync_playwright class MathJaxRenderer: def __init__(self): self.p sync_playwright().start() self.browser self.p.chromium.launch(headlessTrue) self.page self.browser.new_page() def close(self): self.browser.close() self.p.stop() def render(self, latex_string: str): html f !DOCTYPE html html head meta charsetUTF-8 script window.MathJax {{ tex: {{ inlineMath: [[$, $]], displayMath: [[$$, $$]] }} }}; /script script srchttps://cdn.jsdelivr.net/npm/mathjax3/es5/tex-chtml.js/script /head body div idformula$$ {latex_string} $$/div /body /html self.page.set_content(html) # 等待 MathJax 渲染完成 self.page.wait_for_function( window.MathJax MathJax.startup MathJax.startup.promise ) # 提取错误信息 result self.page.evaluate( () { const el document.querySelector(#formula); // MathJax v3 错误 const errorNode el.querySelector(mjx-merror); if (errorNode) { return { success: false, error: errorNode.textContent }; } // 备用旧版本 const err2 el.querySelector(.MathJax_Error); if (err2) { return { success: false, error: err2.textContent }; } return { success: true, error: null }; } ) return result # 测试 renderer MathJaxRenderer() starttime.time() print(renderer.render(r\frac{a}{b})) # {success: True, error: None} print(time1,time.time()-start) starttime.time() print(renderer.render(r\ln(e^{ab}}))) print(time2,time.time()-start) starttime.time() print(renderer.render(r\ln(e^{ab}}))) # {success: False, error: Missing } inserted} print(time3,time.time()-start) renderer.close()js前端渲染katex和mathjax比较兼容性和纠错能力这两个维度结论很清晰在兼容性广度和容错性上MathJax 全面优于 KaTeX。这两个库的侧重点完全不同具体对比如下1. 兼容性MathJax 更胜一筹更广的浏览器支持MathJax 兼容 IE 9 等老旧浏览器而 KaTeX 通常只支持较现代的浏览器。更全的输入/输出格式MathJax 支持LaTeX、MathML 和 AsciiMath输入输出支持HTML、SVG 和 MathMLKaTeX 主要聚焦于LaTeX输入和HTML输出。更完善的语法支持MathJax 几乎完整支持 LaTeX 语法KaTeX 仅支持核心语法不支持physics等扩展包。2. 纠错能力MathJax 更加智能KaTeX 是“严格模式”一旦语法不标准如括号不匹配它会直接报错停止渲染而 MathJax 会尽最大努力去理解和渲染有问题的公式给出最佳结果。3. 性能对比KaTeX 遥遥领先这是 KaTeX 的核心优势。它的设计目标就是快。在处理大量复杂公式时KaTeX 的渲染速度通常比 MathJax 快3-5 倍。总结与选型建议对比维度MathJaxKaTeX渲染速度较慢适合公式量少但复杂的场景极快适合公式密集型页面兼容性更优支持老旧浏览器和 MathML良好适合现代浏览器环境语法支持非常全面几乎完整 LaTeX 支持聚焦常用语法高级功能有限纠错与渲染更智能能尽力渲染有瑕疵的代码严格语法不标准时容易报错包体积较大 (~600KB)轻量 (~75KB gzipped)选择建议首选 MathJax如果你非常看重公式显示的准确性、兼容性和容错能力尤其是对于复杂的学术文档、LaTeX 功底不深、或需要兼容 MathML 格式时。选择 KaTeX如果你的核心目标是极致的页面加载性能和渲染速度如技术博客、在线教程且公式语法相对标准、不需要复杂的 LaTeX 功能。katex公式渲染mathjax公式实时渲染!DOCTYPE html html langzh-CN head meta charsetUTF-8 meta nameviewport contentwidthdevice-width, initial-scale1.0 titleLaTeX 公式实时渲染器/title script window.MathJax { tex: { inlineMath: [[$, $], [\\(, \\)]], displayMath: [[$$, $$], [\\[, \\]]], packages: {[]: [base, ams, newcommand]} }, options: { ignoreHtmlClass: tex2jax_ignore, processHtmlClass: tex2jax_process }, startup: { ready: () { console.log(MathJax 已就绪); MathJax.startup.defaultReady(); } } }; /script script srchttps://cdn.jsdelivr.net/npm/mathjax3/es5/tex-chtml.js/script style * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, sans-serif; max-width: 900px; margin: 30px auto; padding: 20px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); min-height: 100vh; } .container { background: white; border-radius: 20px; padding: 30px; box-shadow: 0 20px 60px rgba(0,0,0,0.3); } h1 { color: #333; margin-bottom: 10px; font-size: 2em; } .subtitle { color: #666; margin-bottom: 30px; font-size: 0.95em; } .editor-section { margin-bottom: 30px; } label { display: block; margin-bottom: 10px; color: #555; font-weight: 500; } textarea { width: 100%; min-height: 150px; padding: 15px; font-family: Consolas, Monaco, monospace; font-size: 14px; border: 2px solid #e0e0e0; border-radius: 10px; resize: vertical; transition: border-color 0.3s; } textarea:focus { outline: none; border-color: #667eea; } .toolbar { display: flex; gap: 10px; margin: 15px 0; flex-wrap: wrap; } button { background: #667eea; color: white; border: none; padding: 10px 20px; border-radius: 8px; cursor: pointer; font-size: 14px; font-weight: 500; transition: all 0.3s; } button:hover { background: #5a67d8; transform: translateY(-2px); box-shadow: 0 5px 15px rgba(102, 126, 234, 0.4); } button.secondary { background: #48bb78; } button.secondary:hover { background: #38a169; } button.warning { background: #ed8936; } button.warning:hover { background: #dd6b20; } .shortcut-btn { background: #e2e8f0; color: #4a5568; padding: 8px 12px; font-size: 13px; } .shortcut-btn:hover { background: #cbd5e0; transform: translateY(-1px); box-shadow: 0 2px 8px rgba(0,0,0,0.1); } .preview-section { margin-top: 30px; } .status-bar { display: flex; align-items: center; justify-content: space-between; margin-bottom: 15px; padding: 10px 15px; background: #f7fafc; border-radius: 10px; } .status-indicator { display: flex; align-items: center; gap: 10px; } .status-badge { padding: 4px 12px; border-radius: 20px; font-size: 0.85em; font-weight: 600; } .status-success { background: #c6f6d5; color: #22543d; } .status-error { background: #fed7d7; color: #742a2a; } .status-pending { background: #fefcbf; color: #744210; } .render-area { min-height: 200px; padding: 30px; background: #f7fafc; border-radius: 10px; border: 2px dashed #cbd5e0; display: flex; align-items: center; justify-content: center; font-size: 1.5em; overflow-x: auto; } .render-area:empty::before { content: ✨ 输入公式后点击渲染; color: #a0aec0; font-size: 1em; } .error-message { margin-top: 10px; padding: 12px; background: #fed7d7; border-left: 4px solid #e53e3e; border-radius: 8px; color: #742a2a; display: none; } .error-message.show { display: block; } .char-count { color: #718096; font-size: 0.9em; } .example-section { margin: 15px 0; } .example-buttons { display: flex; flex-wrap: wrap; gap: 8px; } /style /head body div classcontainer h1 LaTeX 公式实时渲染器/h1 div classsubtitle输入 LaTeX 代码实时查看渲染结果/div div classeditor-section label forlatexInput✏️ LaTeX 公式编辑器/label textarea idlatexInput placeholder输入 LaTeX 公式例如#10;E mc^2#10;x \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}#10;\int_0^\infty e^{-x^2} dx \frac{\sqrt{\pi}}{2} E mc^2/textarea div styledisplay: flex; justify-content: space-between; align-items: center; span classchar-count idcharCount0 字符/span div classtoolbar button onclickrenderFormula() idrenderBtn 渲染公式/button button onclickclearInput() classsecondary️ 清空/button button onclickcopyRendered() classwarning 复制代码/button /div /div div classexample-section label stylemargin-top: 15px; 快捷插入/label div classexample-buttons button onclickinsertAtCursor(\\frac{}{}) classshortcut-btn分数 \frac/button button onclickinsertAtCursor(\\sqrt{}) classshortcut-btn根号 \sqrt/button button onclickinsertAtCursor(\\int_{}^{}) classshortcut-btn积分 \int/button button onclickinsertAtCursor(\\sum_{}^{}) classshortcut-btn求和 \sum/button button onclickinsertAtCursor(\\alpha) classshortcut-btnα/button button onclickinsertAtCursor(\\beta) classshortcut-btnβ/button button onclickinsertAtCursor(\\pi) classshortcut-btnπ/button button onclickinsertAtCursor(\\infty) classshortcut-btn∞/button button onclickinsertAtCursor(\\pm) classshortcut-btn±/button button onclickinsertAtCursor(\\cdot) classshortcut-btn·/button /div /div /div div classpreview-section div classstatus-bar div classstatus-indicator span 渲染状态/span span classstatus-badge status-pending idstatusBadge等待输入/span /div span idrenderTime/span /div div classrender-area idrenderArea/div div classerror-message iderrorMessage/div /div /div script // 初始化 document.addEventListener(DOMContentLoaded, () { updateCharCount(); // 监听输入变化 document.getElementById(latexInput).addEventListener(input, updateCharCount); // 支持快捷键 CtrlEnter 渲染 document.getElementById(latexInput).addEventListener(keydown, (e) { if (e.ctrlKey e.key Enter) { renderFormula(); } }); }); function updateCharCount() { const input document.getElementById(latexInput); const count input.value.length; document.getElementById(charCount).textContent ${count} 字符; } async function renderFormula() { const input document.getElementById(latexInput).value.trim(); const renderArea document.getElementById(renderArea); const statusBadge document.getElementById(statusBadge); const errorMsg document.getElementById(errorMessage); const startTime performance.now(); if (!input) { statusBadge.textContent ⚠️ 请输入公式; statusBadge.className status-badge status-pending; renderArea.innerHTML ; return; } // 重置状态 statusBadge.textContent 渲染中...; statusBadge.className status-badge status-pending; errorMsg.classList.remove(show); try { // 预处理如果是纯公式自动包装为显示公式 let formulaToRender input; if (!input.includes($$) !input.includes(\\[)) { formulaToRender $$${input}$$; } renderArea.innerHTML formulaToRender; // 调用 MathJax 渲染 await MathJax.typesetPromise([renderArea]); // 检查渲染结果 const hasError renderArea.querySelector(.MathJax_ERROR, mjx-merror); const endTime performance.now(); const renderDuration ((endTime - startTime) / 1000).toFixed(2); if (hasError) { // 渲染失败 const errorText hasError.textContent || 公式语法错误; statusBadge.textContent ❌ 渲染失败; statusBadge.className status-badge status-error; errorMsg.textContent 错误详情${errorText}; errorMsg.classList.add(show); } else { // 渲染成功 statusBadge.textContent ✅ 渲染成功; statusBadge.className status-badge status-success; document.getElementById(renderTime).textContent ⏱️ ${renderDuration}秒; } } catch (error) { console.error(渲染异常:, error); statusBadge.textContent ❌ 渲染失败; statusBadge.className status-badge status-error; errorMsg.textContent 异常${error.message}; errorMsg.classList.add(show); } } function clearInput() { document.getElementById(latexInput).value ; document.getElementById(renderArea).innerHTML ; document.getElementById(statusBadge).textContent 等待输入; document.getElementById(statusBadge).className status-badge status-pending; document.getElementById(errorMessage).classList.remove(show); document.getElementById(renderTime).textContent ; updateCharCount(); } function copyRendered() { const input document.getElementById(latexInput); input.select(); document.execCommand(copy); // 临时提示 const btn event.target; const originalText btn.textContent; btn.textContent ✅ 已复制; setTimeout(() { btn.textContent originalText; }, 1500); } function insertAtCursor(text) { const textarea document.getElementById(latexInput); const start textarea.selectionStart; const end textarea.selectionEnd; const content textarea.value; textarea.value content.substring(0, start) text content.substring(end); textarea.selectionStart textarea.selectionEnd start text.length; textarea.focus(); updateCharCount(); } /script /body /htmlmathjax公式渲染示例!DOCTYPE html html langzh-CN head meta charsetUTF-8 meta nameviewport contentwidthdevice-width, initial-scale1.0 titleMathJax 数学公式渲染示例/title !-- 引入 MathJax 库 -- script srchttps://cdn.jsdelivr.net/npm/mathjax4.0.0-beta.6/tex-chtml.js idMathJax-script async/script style body { font-family: Segoe UI, Tahoma, Geneva, Verdana, sans-serif; max-width: 800px; margin: 50px auto; padding: 20px; background-color: #f5f5f5; } .card { background-color: white; border-radius: 10px; padding: 20px; margin-bottom: 20px; box-shadow: 0 2px 5px rgba(0,0,0,0.1); } h1 { color: #333; text-align: center; } h2 { color: #555; border-bottom: 2px solid #ddd; padding-bottom: 5px; } .formula-block { background-color: #f8f9fa; padding: 15px; border-radius: 5px; margin: 15px 0; font-size: 1.1em; } .code { background-color: #e9ecef; padding: 10px; border-radius: 5px; font-family: Courier New, monospace; font-size: 0.9em; overflow-x: auto; } /style /head body h1 MathJax 数学公式渲染示例/h1 !-- 示例1行内公式 -- div classcard h21️⃣ 行内公式 (Inline Math)/h2 p公式可以写在段落中间比如勾股定理$a^2 b^2 c^2$这是行内公式。/p p质能方程$E mc^2$揭示了质量和能量的关系。/p div classcode codelt;pgt;勾股定理$a^2 b^2 c^2$这是行内公式。lt;/pgt;/code /div /div !-- 示例2块级公式 -- div classcard h22️⃣ 块级公式 (Display Math)/h2 p下面是著名的求根公式它会单独成行并居中显示/p div classformula-block $$x \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}$$ /div p还有欧拉恒等式/p div classformula-block $$e^{i\pi} 1 0$$ /div div classcode code$$x \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}$$/code /div /div !-- 示例3分数和根号 -- div classcard h23️⃣ 分数和根号/h2 p分数$\frac{1}{2} \frac{1}{3} \frac{5}{6}$/p p根号$\sqrt{2} \approx 1.414$立方根$\sqrt[3]{8} 2$/p p嵌套公式$\frac{\sqrt{x1}}{\sqrt{x-1}}$/p /div !-- 示例4希腊字母和运算符 -- div classcard h24️⃣ 希腊字母和运算符/h2 p希腊字母$\alpha, \beta, \gamma, \delta, \epsilon, \pi, \theta, \sigma, \omega$/p p求和$\sum_{i1}^{n} i \frac{n(n1)}{2}$/p p积分$\int_{0}^{\infty} e^{-x} dx 1$/p p极限$\lim_{x \to 0} \frac{\sin x}{x} 1$/p /div !-- 示例5矩阵 -- div classcard h25️⃣ 矩阵/h2 p一个 $2 \times 2$ 矩阵/p div classformula-block $$A \begin{pmatrix} a b \\ c d \end{pmatrix}$$ /div p行列式$\det(A) ad - bc$/p /div !-- 示例6复杂公式 -- div classcard h26️⃣ 复杂公式示例/h2 p正态分布概率密度函数/p div classformula-block $$f(x) \frac{1}{\sigma\sqrt{2\pi}} e^{-\frac{(x-\mu)^2}{2\sigma^2}}$$ /div p泰勒展开式/p div classformula-block $$e^x \sum_{n0}^{\infty} \frac{x^n}{n!} 1 x \frac{x^2}{2!} \frac{x^3}{3!} \cdots$$ /div p傅里叶级数/p div classformula-block $$f(x) a_0 \sum_{n1}^{\infty} \left(a_n \cos\frac{n\pi x}{L} b_n \sin\frac{n\pi x}{L}\right)$$ /div /div !-- 示例7多行公式 -- div classcard h27️⃣ 多行对齐公式/h2 div classformula-block $$ \begin{aligned} (xy)^2 x^2 2xy y^2 \\ (x-y)^2 x^2 - 2xy y^2 \\ x^2 - y^2 (xy)(x-y) \end{aligned} $$ /div /div !-- 示例8你之前的例子 -- div classcard h28️⃣ 你提到的例子/h2 p原公式$x_0 x(t)$/p div classformula-block $$x_0 x(t)$$ /div p绝对值不等式$|a(t)| \le 1$/p div classformula-block $$|a(t)| \le 1$$ /div p区间表示$\in [3, 7]$/p div classformula-block $$\in [3, 7]$$ /div /div div classcard h2 使用说明/h2 ul listrong行内公式/strong使用 code$...$/code 或 code\(...\)/code/li listrong块级公式/strong使用 code$$...$$/code 或 code\[...\]/code/li listrong常用命令/strong分式 code\frac{}{}/code根号 code\sqrt{}/code求和 code\sum/code积分 code\int/code/li listrong上下标/strong上标 code^/code下标 code_/code/li /ul /div /body /html