WKHTMLTOPDF und Chartist
Eine PDF-Datei aus einem guten HTML-Template zu generieren ist mit WKHTMLTOPDF nicht wirklich schwierig. Werden zudem aber Diagramme mit JavaScript in dieses Template gerendert, wird die Angelegenheit schon etwas kniffliger. Ein kleiner Guide für das Zusammenspiel zwischen WKHTMLTOPDF und Chartist.
In unserem Beispiel wurde chartist.js als Bibliothek für die Diagramme verwendet. Dem Internet zufolge ist die Kombination beider Komponenten möglich, da Chartist die Bilder als SVG ausgibt. Dies braucht allerdings zusätzliche Konfiguration, anderenfalls wird das Template einfach ohne Diagramme ausgegeben.
Voraussetzungen schaffen
Damit Chartist seinen Dienst ordnungsgemäß verrichten kann, wird eine globale Funktion bind
benötigt. Für diese bauen wir uns einen Workaround:
Function.prototype.bind = Function.prototype.bind || function (thisp) { var fn = this; return function () { return fn.apply(thisp, arguments); }; };
Dieses Snippet sollte vor Chartist inkludiert werden.
Größen justieren
Als nächstes muss sichergestellt werden, dass Chartist die Größen der generierten SVGs mit festen Werten angibt. Das SVG braucht dafür verpflichtend width
und height
Attribute und Styles gleichermaßen.
Falls Chartist dies nicht schon automatisch vorgibt, muss es in den Diagramm-Optionen angepasst werden. Um wirklich sicher zu gehen, können dieselben Attribute auch dem Umgebenden Tag zugeteilt werden.
<svg width="100" heigth="100" style="width: 100px; height: 100px;">...</svg>
WKHTML einrichten
Zuletzt muss WKHTMLTOPDF mitgeteilt werden, dass wir JavaScript ausführen. Denn auf diese Scripts muss gewartet werden!
wkhtmltopdf --javascript-delay 1000 --no-stop-slow-scripts $url $filename
Mit --javascript-delay 1000
warten wir eine zusätzliche Sekunde auf das ausführen von JavaScript Code und mit --no-stop-slow-scripts
sind wir auf der sicheren Seite, wenn doch mal ein Script etwas länger benötigt. Hier muss eventuell getestet werden, wie lange auf ein Skript gewartet wird, denn die Werte sich von dem ausführenden Rechner, den Klienten (der es abruft) und der Masse des JavaScripts abhängig.
Alternatives Warten
Dieser Ansatz ist bisher nicht getestet, sondern nur eine Idee!
Statt auf das JavaScript direkt zu warten, könnte man auch auf ein Kommando reagieren. Die Dokumentation von WKHTML enthält ein Flag --window-status <windowStatus>
, das es erlaubt, auf eine Statusänderung des JavaScript-Window zu lauschen.
wkhtmltopdf --window-status 'work-is-done' $url $filename
Würde also warten, bis
<script type="text/javascript"> window.status = 'work-is-done'; </script>
eingetreten ist, bevor die Seite in das PDF übertragen wird. So könnte man direkt auf ein onComplete
-Event reagieren und bräuchte keine statischen Wartezeiten.