I've spent days about how to render MathJax into PDF on client-side only (using several libraries like jsPDF, etc.) for the open source project Writing. I have tried many different options, without any success.
Here is a code showing the problem in my latest attempt, based on this answer.
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>
How to render HTML + MathJax content into PDF, on client-side only?
My short answer would be: don't do this.
The long answer is you can make this work but the result will be inferior to providing a print stylesheet and letting users save the output as PDF. For starters, you will create a PDF with a single (potentially huge) PNG in it; that will be terrible for printing.
The main problem with your code is that canvg can only handle SVG content, not arbitrary web content, so you need to use another tool.
But generally there are limitations for injecting HTML content in canvas elements (for security reasons).
Finally, you will need to force MathJax's AssistiveMML extension to be off to avoid duplicate content.
Below is a snippet but it fails on SO for the security reasons mentioned above; you can try it on codepen though.
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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With