将MathJax渲染成PDF

5

我已经花费了数日时间,试图在客户端上将MathJax渲染为PDF(使用几个库,如jsPDF等)用于开源项目Writing。 我尝试了许多不同的选项,但都没有成功。

这里是一个代码示例,展示了我最新尝试的问题,基于这个答案

  MathJax.Hub.Config({ tex2jax: {inlineMath: [["$","$"],["\\(","\\)"]]} });

document.getElementById("getPdf").addEventListener("click", getPdf);

function getPdf() {
  var svg = document.getElementById('main').innerHTML;
  if (svg)
    svg = svg.replace(/\r?\n|\r/g, '').trim();

  var canvas = document.createElement('canvas');
  var context = canvas.getContext('2d');

  context.clearRect(0, 0, canvas.width, canvas.height);
  canvg(canvas, svg);

  var imgData = canvas.toDataURL('image/png');

  var doc = new jsPDF('p', 'pt', 'a4');
  doc.addImage(imgData, 'PNG', 40, 40, 75, 75);
  doc.save('test.pdf');
}  
<script src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_HTML-full"></script>
<script src="https://cdn.rawgit.com/canvg/canvg/master/canvg.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.2.61/jspdf.min.js"></script>

<p id="main">
When $a \ne 0$, there are two solutions to \(ax^2 + bx + c = 0\) and they are
$$x = {-b \pm \sqrt{b^2-4ac} \over 2a}.$$
</p>

<button id="getPdf">Get PDF</button>

问题:

如何在客户端上将HTML + MathJax内容渲染成PDF?


注意:cdn.mathjax.org即将到达其生命周期的尽头,请参见https://www.mathjax.org/cdn-shutting-down/。 - Peter Krautzberger
1个回答

1
我的简短回答是:不要这样做。 长的回答是,你可以让它工作,但结果会比提供一个打印样式表并让用户将输出保存为PDF要差。首先,你会创建一个只有一个(可能非常巨大)PNG的PDF;这对于打印来说是很糟糕的。
你代码的主要问题是canvg只能处理SVG内容,而不能处理任意网页内容,所以你需要使用其他工具。
但通常在canvas元素中注入HTML内容会有限制(出于安全原因)。
最后,你需要强制MathJax的AssistiveMML扩展关闭,以避免重复内容。
下面是一个片段,但由于上述安全原因,在SO上失败了;你可以在codepen上尝试它。

MathJax.Hub.Queue(function (){
  var canvas = document.getElementById("canvas");
  var main = document.getElementById("main");
  rasterizeHTML.drawHTML(main.outerHTML,canvas);

})
document.getElementById("getPdf").addEventListener("click", getPdf);

function getPdf() {
  var imgData = canvas.toDataURL('image/png');

  var doc = new jsPDF('p', 'pt', 'a4');
  doc.addImage(imgData, 'PNG', 40, 40, 400, 200);
  doc.save('test.pdf');
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.2.61/jspdf.min.js"></script>
<script type="text/x-mathjax-config">
  MathJax.Hub.Config({
    extensions: ["tex2jax.js"],
  "AssistiveMML": {
    disabled: true
  },
  SVG: {
    addMMLclasses: true,
    useGlobalCache: false
  },
  });
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-AMS_SVG-full"></script>
<script   src="https://cdnjs.cloudflare.com/ajax/libs/rasterizehtml/1.2.4/rasterizeHTML.allinone.js"></script>
<p id="main">
When \(a \ne 0\), there are two solutions to \(ax^2 + bx + c = 0\) and they are
$$x = {-b \pm \sqrt{b^2-4ac} \over 2a}.$$
</p>
<h1>As canvas</h1>
    <canvas id="canvas" width="400" height="200"></canvas>

<button id="getPdf">Get PDF</button>


另外还有一件事:我并不想将整个内容渲染成一个大的PNG图像。实际上,我希望保留文本的格式,并且只将MathJax部分渲染为PNG或SVG格式,然后可以使用jsPDF或类似的库将其保存为PDF文件。 - Basj
2
最后一件事:如果我们从大局来看,我并不完全同意“不要这样做”。应该有一个解决方案:我想在这个页面上让用户在左侧编写Markdown和数学公式。应该可以将其导出为PDF。我的意思是,从用户的角度来看,用户应该能够导出为PDF :) 所以我必须找到如何做到这一点... ;) - Basj
白底带线条的渲染表示配置未被捕获。我注意到了一个尾随逗号并进行了修复;请查看是否有所帮助,或在现代浏览器中尝试本地副本。 - Peter Krautzberger
我不知道是否有一个解决方案会有用。据我所知,目前没有客户端解决方案。虽然我可以想象一个Web API,它可以访问内置的“打印为PDF”,但并不是所有浏览器都有这样的功能,所以这似乎是一个不太可能的建议(尤其是一些浏览器提供“另存为PDF”按钮,例如Safari)。我怀疑一个触发打印对话框的按钮(使用打印样式表)在可用性方面可能已经足够了。 - Peter Krautzberger
想象一下,这个工具只是一个LaTeX+markdown在线编辑器。用户希望能够导出为PDF,并且即使更改浏览器也能获得一致的结果。我愿意花时间来解决这个问题,并做出开源贡献。您认为我应该调查哪种解决方案,以便能够拥有一致的MathJax-> PDF(而不是一个大的PNG或SVG)?提前感谢。 - Basj
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接