使用KaTeX在node.js模板中渲染数学

时间:2016-07-04 09:44:09

标签: javascript node.js math mathjax katex

我想在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.render()之前省略调用res.send()吗?

当我使用

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: $_

2 个答案:

答案 0 :(得分:1)

KaTeX核心并不关心文本输入的来源。识别TeX源代码片段不是其目标的一部分。有一个名为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渲染一个必须将<编码为&lt;。如果您控制所有输入,则可能会提供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,但是您可以自行决定是否需要这样做。

在不知道输入的情况下很难确定错误消息的原因。看起来好像你可能有一些输入以一个$$开头但仅以一个$结尾,因此第一个正则表达式无法匹配,第二个正则表达式包括另一个$ in它匹配的字符串。

答案 1 :(得分:0)

/\\\((.*?)\\\)/g

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

enter image description here

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

为防止这种情况,请使用

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

示例

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(这是我要尝试的下一个方法...)