·  阅读

在html页面渲染MathJax公式,可以选择 MathJaxV2 MathJaxV3 ,V2更适合通过cdn引用,本地化比较麻烦,也不能直接把cdn.js复制下来放在本地,因为里面还引了其他资源(字体等),会导致这些资源引用失败。

V3可以资源放在本地,还可以根据项目的需要,下载单独的包,比如 tex-chtml 及字体库。

 <script>
      window.MathJax = {
        chtml: {
          matchFontHeight: true,
          fontURL: "./formula/woff-v2", // 字体
          adaptiveCSS: true,
          scale: 0.8,
          minScale: .7,                  
        options: {
          renderActions: {
            addMenu: [],
    </script>
    <script type="text/javascript" src="./formula/tex-chtml.js" id="MathJax-script" ></script> //Mathjax tex-chtml

网页渲染Mathjax公式,只要花时间耐心看Mathjax的文档,基本没有问题,有问题网上也能找到比较多参考答案。

这里要说的是后端要用mkhtmltox将html转成pdf时,发现公式渲染不出来的问题。

我们采用的是上面所说V3的方式渲染公式,在浏览器看相应的html公式是可以渲染的,但是转出来的pdf却失败。

渲染失败:

渲染成功应该是这样

问题出现了,前端如何排查呢?这里先说一下排查方法。

  • 先去下载安装windows版本的wkhtmltox
  • <安装路径>\bin\wkhtmltopdf --debug-javascript <要转换的html路径>.html <生成的pdf保存路径>.pdf
  • --debug-javascript 显示 javascript 调试输出,这是wkhtmltopdf的全局可配置选项. 根据情况可能还需要用到--window-status <> --enable-local-file-access 等,更多选项请看

    通过--debug-javascript后出现的日志,发现出现了语法报错原因是wkhtmltopdf 使用的WebKit 引擎版本比较低(wkhtmltopdf 这个工具也不怎么维护了,感觉WebKit 升级遥遥无期),无法解析tex-chtml.js里面的es6语法,同时不支持tex-chtml.js里使用到的localStorage。

    首先考虑了再引入polyfill解决es6的编译问题,不支持localStorage就在tex-chtml.js里面写个localStorage,一番折腾下来,终于不报错了。

    但是公式还是渲染失败,由于wkhtmltopdf 显示的调试信息太少了,无法继续深入研究。

    转而考虑通过V2的cdn引入,Mathjax2官网里面的cdn在国内经常无法访问,wkhtmltopdf报cdn加载失败。

    转而求其次,寻找国内大厂cdn,很多国内大厂的cdn源都能找到mathjax2,但是mathjax2里面引用的其他cdn都不全,公式编译还是失败。

    最后staticfile Cdn库里的MathJax2 cdn是可用的,后端生成的pdf终于可以渲染出公式了。

    感谢Staticfile CDN,感谢七牛云,感谢掘金。

    最后终于渲染成功!

    <script type="text/javascript">
      var el = document.createElement("script"); // 不要使用const等es6语法
      el.setAttribute("id", "MathJax-script");
      el.src =
        "https://cdn.staticfile.org/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML";
      document.body.appendChild(el);
      if (el.readyState) {
        el.onreadystatechange = function () {
          if (el.readyState === "complete" || el.readyState === "loaded") {
            el.onreadystatechange = null;
            mathjaxConfig();
      } else {
        //非IE
        el.onload = function () {
          mathjaxConfig();
      function mathjaxConfig() {
        if (window.MathJax) {
          window.MathJax.Hub.Config({
            extensions: ["tex2jax.js"],
            jax: ["input/TeX", "output/HTML-CSS"],
            tex2jax: {
              inlineMath: [["\\(", "\\)"]],
              displayMath: [
                ["$$", "$$"],
                ["\\[", "\\]"],
              processEscapes: true,
            "HTML-CSS": {
              availableFonts: ["TeX"],
              preferredFont: "TeX",
              minScaleAdjust: 100,
          window.MathJax.Hub.Queue([
            "Typeset",
            MathJax.Hub,
            document.getElementById("wrapper"),
            // MathJax把公式都渲染完成后,触发
            function () {
            // 这里是为了配合wkhtmltopdf转换选项--window-status onloadready使用,
            // 加载完html后,等window-status值为onloadready时wkhtmltopdf才会开始转换
              window.status = "onloadready"; 
    </script>
    

    至于很多的细节,比如一开始pdf渲染出来的公式字体很小等问题,就不一一赘述了。归结起来,这些都是通过花时间阅读MathJax2文档调整各种配置,实现出满意的渲染效果。

    分类:
    前端
    标签: