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.

Kommentar hinterlassen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.