【问题标题】:Render math in node.js template with KaTeX使用 KaTeX 在 node.js 模板中渲染数学
【发布时间】:2016-07-04 09:44:09
【问题描述】:

我想在node.js 的乳胶模式页面中呈现数学。我看过MathJaXKaTeX

我用

渲染我的页面
router.get('/math', function (req, res) {
  res.render('math');
});

那么我怎样才能确保此页面上的数学呈现为数学?

我可以使用

const katex = require('katex');
const math = katex.renderToString("c = \\pm\\sqrt{a^2 + b^2}", { displayMode: true });

然后在模板中设置变量

router.get('/math', function (req, res) {
  res.render('math', { math: math });
});

但我宁愿直接在模板中编写所有数学运算,而不是在 javascript 代码中专门设置每个变量。

编辑

我正在从模板中获取 html

router.get('/math', function (req, res) {
  res.render('math', function (err, html) {
    html = html.replace(/\$\$(.*?)\$\$/g, function (outer, inner) {
      return katex.renderToString(inner, { displayMode: true });
    });

    res.send(html);
  });
});

这是一个好方法吗?或者我可以在使用res.send()之前省略调用res.render()吗?

当我使用时

html = html.replace(/\$\$(.*?)\$\$/g, function (outer, inner) {
  return katex.renderToString(inner, { displayMode: true });
}).replace(/\$(.*?)\$/g, function (outer, inner) {
  return katex.renderToString(inner);
});

服务器出现故障,我收到错误ParseError: KaTeX parse error: Expected 'EOF', got '$' at position 1: $_

【问题讨论】:

  • 作为对这个问题和答案的补充,使用/\$\$(.*?)\$\$/g 不匹配换行符(因为. 不匹配换行符)。我建议使用/\$\$([^\$]*?)\$\$/g,这样可以更好地匹配客户端行为。 ????

标签: javascript node.js math mathjax katex


【解决方案1】:

KaTeX 核心并不关心文本输入的来源。识别 TeX 源 sn-ps 不是其目标的一部分。有一个名为 auto-render 的贡献扩展,它作为 KaTeX 代码库的一部分进行维护。它将识别页面中的 TeX 输入,并将其替换为 KaTeX 呈现的 HTML。但它在 DOM 树上运行客户端,而不是在 HTML 标记文本上运行服务器端。

所以我建议你在这里滚动你自己的代码。我猜你不应该需要任何 DOM 解析。相反,我会尝试提出一些合适的正则表达式来描述数学块,然后用它们的renderToString 类比替换它们。类似的东西

html = html.replace(/\$\$(.*?)\$\$/g, function(outer, inner) {
    return katex.renderToString(inner, { displayMode: true });
}).replace(/\\\[(.*?)\\\]/g, function(outer, innner) {
    return katex.renderToString(inner, { displayMode: true });
}).replace(/\\\((.*?)\\\)/g, function(outer, innner) {
    return katex.renderToString(inner, { displayMode: false });
});

根据您的用例,您可能希望将此替换应用于您的输入模板、您提供给模板的参数或您从渲染模板中获得的结果。在所有这三种情况下,您都应该尝试在某个时候将 HTML 文本的相关部分作为单个字符串处理。在某些情况下,这可能涉及缓冲基于流的模板输出。由于您没有说明您为模板和应用服务器使用的框架,因此我无法提供更多详细信息。

请注意,上述内容赋予 TeX 比 HTML 更高的优先级:$$a<p>b$$ 之类的输入被解释为 TeX 输入 a < p > b。这与客户端渲染(如自动渲染器)形成对比,在客户端渲染中,上述内容将被视为两段,它们都不包含完整的 TeX 输入片段,以及在哪里实现a < p > b 渲染必须将< 编码为<。如果您控制所有输入,则给予 TeX 优先级可能是您想要的。但是,如果您接受用户提供的输入,则此行为可能会导致某些内容清理程序或 Wiki 标记格式化代码出现意外。因此,如果您打算按照这些方式做任何事情,请确保您知道自己想要什么行为,并让您的客户意识到这一点。

如果您想实现与 TeX 的更高兼容性,您可以尝试支持其他顶级环境。例如,您可以包括

html = html.replace(/\\begin\{align\*\}(.*?)\\end\{align\*\}/g, function(outer, inner) {
    return katex.renderToString("\\begin{aligned}" + inner + "\\end{aligned}", { displayMode: true });
})

利用aligned 环境已实现而align* 环境尚未实现这一事实。


回应您的编辑:

res.render 与回调的组合以及该回调中的res.send 对我来说看起来不错。如果您自己调用模板渲染,则可以避免调用 res.render,但是否需要由您决定。

在不知道输入的情况下很难确定错误消息的原因。似乎您可能有一些以双 $$ 开头但仅以单个 $ 结尾的输入,因此第一个正则表达式无法匹配,而第二个正则表达式在其匹配的字符串中包含一个额外的 $

【讨论】:

  • 谢谢!我正在使用车把。我正在使用res.render('math') 渲染我的模板,那么是否可以从该模板中获取内容并通过您的代码 sn-p 运行并将其放回去?
  • 如果在使用.replace(/\$\$(.*?)\$\$/g, function(outer, innner) { 后使用.replace(/\$(.*?)\$/g, function(outer, innner) {,我会收到服务器错误。只有一个 $ 有什么问题?
  • @Jamgreen:你在使用 Express 吗?它确实描述了res.render。什么版本?无论如何,您可能不想调用res.render,而是直接调用模板引擎,然后使用res.end 发送结果。单个 $ 作为分隔符可能会很棘手,因为 a) 它们可能出现在常规文本中,b) 它们也可能出现在 LaTeX 代码中,例如在 x > x_0\text{ for all $x$ in $X$} 这样的结构中。但不应该出现错误,因此如果您需要更多帮助,可能需要提供错误消息。
  • .replace 在普通 JS 中会是什么样子?它给我的内心是没有定义的......
【解决方案2】:
/\\\((.*?)\\\)/g

在许多情况下不起作用,因为会发生以下情况:

多个公式被识别为一个,导致错误。

为了防止这种情况,请使用

/\\\(((.)*?(?=\\\)))?\\\)/

例子

html = html.replace(/\\\(((.)*?(?=\\\)))?\\\)/g, function(a, b) {
  return katex.renderToString(b, { displayMode: false });
}).replace(/\\\[((.)*?(?=\\\]))?\\\]/g, function(a, b) {
  return katex.renderToString(b, { displayMode: true });
}) ...

但是,仍然存在一些警告,例如未正确渲染的内容。另一种方法可能是https://joa.sh/posts/2015-09-14-prerender-mathjax.html(这是我要尝试的下一个方法......)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-03-19
    • 2018-06-09
    • 2017-02-17
    • 2012-12-16
    • 1970-01-01
    • 1970-01-01
    • 2015-10-21
    相关资源
    最近更新 更多