Vorlagen für Thermodrucker
Thermovorlagen verwenden ein XML-Format, das aus derselben Vorlage sowohl eine Bildschirmvorschau als auch ESC/POS-Druckerbefehle erzeugt. Sie verwenden dieselben {{variable}}-Platzhalter wie HTML-Vorlagen für die Datenbindung.
Wählen Sie diese Engine, wenn ein Belegdrucker über die Druckereinrichtung verbunden ist.
XML-Elemente
Stammelement
Jede Thermovorlage beginnt mit einem <receipt> Stammelement:
<receipt paper-width="48">
<!-- 48 characters = 80mm paper -->
<!-- 32 characters = 58mm paper -->
</receipt>
Text und Formatierung
<text>Plain text</text>
<bold>Bold text</bold>
<underline>Underlined text</underline>
<invert>Inverted (white on black)</invert>
Ausrichtung
<align mode="left">Left aligned</align>
<align mode="center">Centered</align>
<align mode="right">Right aligned</align>
Textgröße
Textbreite und -höhe unabhängig skalieren:
<size width="2" height="2">Double-size text</size>
<size width="2" height="1">Wide text</size>
<size width="1" height="2">Tall text</size>
Tabellarisches Layout
Verwenden Sie <row> und <col> für ausgerichtete Spalten:
<row>
<col width="24">Item name</col>
<col width="8" align="right">Qty</col>
<col width="16" align="right">Price</col>
</row>
Spaltenbreiten werden in Zeichen angegeben. Verwenden Sie width="*" für eine flexible Spalte, die den verbleibenden Platz aufnimmt — so funktionieren Vorlagen ohne Anpassung mit unterschiedlichen Papierbreiten:
<row>
<col width="*">{{name}}</col>
<col width="12" align="right">{{line_total_display}}</col>
</row>
Trennlinien und Abstände
<line /> <!-- Default single rule -->
<line style="double" /> <!-- Printer-native double rule -->
<line style="dashed" /> <!-- Character dashes across the width -->
<line style="dotted" /> <!-- Character dots across the width -->
<feed lines="2" /> <!-- Blank lines -->
<line/> (oder style="single") und style="double" geben die native Trennlinie des Druckers aus. dashed und dotted geben zeichenbasierte Trennlinien über die aktive Spaltenbreite aus — nützlich, wenn Sie eine sichtbare Trennlinie wünschen, die in einem Screenshot der Thermovorschau erhalten bleibt.
Druckerbefehle
<cut /> <!-- Full paper cut -->
<cut mode="partial" /> <!-- Partial cut (leaves a tab) -->
<drawer /> <!-- Open cash drawer -->
Barcodes und QR-Codes
<barcode type="code128" height="40">{{order.number}}</barcode>
<barcode type="qrcode" scale="3">{{fiscal.qr_payload}}</barcode>
Beispiel: Einfacher 80mm-Beleg
<receipt paper-width="48">
<align mode="center">
<size width="2" height="2">{{store.name}}</size>
</align>
<feed lines="1" />
<align mode="center">
<text>{{store.address_1}}</text>
<text>{{store.city}} {{store.state}} {{store.postcode}}</text>
{{#store.phone}}<text>{{store.phone}}</text>{{/store.phone}}
</align>
<line />
<text>Order: #{{order.number}}</text>
<text>Date: {{order.created.datetime}}</text>
{{#cashier.name}}<text>Cashier: {{cashier.name}}</text>{{/cashier.name}}
<line />
<!-- Column headers -->
<row>
<col width="*"><bold>Item</bold></col>
<col width="4" align="right"><bold>Qty</bold></col>
<col width="12" align="right"><bold>Total</bold></col>
</row>
<line />
<!-- Line items -->
{{#lines}}
<row>
<col width="*">{{name}}</col>
<col width="4" align="right">{{qty}}</col>
<col width="12" align="right">{{line_total_display}}</col>
</row>
{{/lines}}
<line />
<!-- Totals -->
<row>
<col width="*">Subtotal</col>
<col width="16" align="right">{{totals.subtotal_display}}</col>
</row>
{{#totals.tax_total}}
<row>
<col width="*">Tax</col>
<col width="16" align="right">{{totals.tax_total_display}}</col>
</row>
{{/totals.tax_total}}
<row>
<col width="*"><bold>TOTAL</bold></col>
<col width="16" align="right"><bold>{{totals.total_display}}</bold></col>
</row>
<line />
{{#payments}}
<row>
<col width="*">{{method_title}}</col>
<col width="16" align="right">{{amount_display}}</col>
</row>
{{#tendered}}
<row>
<col width="*">Tendered</col>
<col width="16" align="right">{{tendered_display}}</col>
</row>
<row>
<col width="*">Change</col>
<col width="16" align="right">{{change_display}}</col>
</row>
{{/tendered}}
{{/payments}}
<feed lines="2" />
<align mode="center">
<text>Thank you for your purchase!</text>
</align>
<feed lines="3" />
<cut />
</receipt>
Spalten mit Sternbreite
Die Funktion width="*" macht Vorlagen unabhängig von der Papierbreite. Anstatt Spaltenbreiten für eine bestimmte Papiergröße fest zu codieren, verwenden Sie * für die Spalte, die sich strecken soll:
<!-- Works on 58mm (32 char) AND 80mm (48 char) printers -->
<row>
<col width="*">{{name}}</col>
<col width="10" align="right">{{line_total_display}}</col>
</row>
Auf einem 80mm-Drucker (48 Zeichen) erhält der Artikelname 38 Zeichen. Auf einem 58mm-Drucker (32 Zeichen) erhält er 22 Zeichen. Feste Spalten behalten auf beiden dieselbe Größe.
Vorlagenvorschau
Der Vorlageneditor zeigt beim Bearbeiten eine Live-Thermovorschau an. Die Vorschau rendert Ihr XML als formatiertes Monospace-HTML und simuliert, wie der Beleg auf Papier aussehen wird. Änderungen werden nach einer kurzen Verzögerung aktualisiert (mit 300ms Debounce).
Dieselbe Vorlage erzeugt sowohl die Vorschau als auch die ESC/POS-Druckerausgabe — es gibt keine separate „Druck“-Vorlage. Barcodes und QR-Codes werden in der Vorschau als Inline-SVGs und auf dem Drucker als native ESC/POS-Befehle (oder Rasterbilder) gerendert.
Tipps und Fallstricke beim Erstellen
Beim Thermodruck gibt es einige Stolperfallen, die es in HTML nicht gibt. Diese treten beim Erstellen am häufigsten auf.
Formatierte Überschriften für einen Zeilenumbruch in <text> einschließen
Formatierte Container — <bold>, <size>, <underline>, <align> — geben für sich allein keinen Zeilenumbruch aus. Nur <text> und Blockelemente (<line/>, <row>, <feed>) tun das.
<!-- ❌ Bug: the heading runs together with whatever follows -->
<bold>{{i18n.bill_to}}</bold>
{{customer.name}}
<!-- ✅ Fix: wrap the inner content in <text> -->
<bold><text>{{i18n.bill_to}}</text></bold>
<text>{{customer.name}}</text>
Die mitgelieferten 80mm-Galerievorlagen verwenden dieses Muster für jede Überschrift.
Vermeiden Sie <size width="2"> in schmalen Zeilen
Text mit doppelter Breite verdoppelt die effektive Zeichenanzahl. Eine Überschrift, die auf einen 80mm-Drucker passt, kann auf einem generischen 80mm-Drucker mit 42 Spalten überlaufen, und auf 58mm-Papier bleiben nur 16 Zeichen.
Für hervorgehobene Werte (große Gesamtsummen, Küchen-Bestellnummern) eine eigenständige skalierte Zeile ausgeben, statt sie in einer mehrspaltigen Zeile umbrechen zu lassen <row>:
<!-- For store names, prefer normal-width, double-height -->
<bold><size height="2"><text>{{store.name}}</text></size></bold>
<!-- For a bold total, put it on its own line above the row -->
<align mode="right">
<bold><size height="2"><text>{{totals.total_display}}</text></size></bold>
</align>
width="*" für papierbreitenunabhängige Layouts verwenden
Die Spalte width="*" (Stern) nimmt die verbleibende Breite auf, nachdem die Spalten mit fester Breite berücksichtigt wurden. Dieselbe Vorlage wird dadurch ohne Anpassung korrekt auf Druckern mit 32 Spalten (58mm), 42 Spalten (80mm Standard) und 48 Spalten (80mm breit) ausgegeben:
<!-- Works on 58mm AND 80mm without changes -->
<row>
<col width="*">{{name}}</col>
<col width="10" align="right">{{line_total_display}}</col>
</row>
Wenn fest codierte numerische Breiten verwendet werden, auf 42 auslegen, nicht auf 48. Zeilen mit einer Summe von 48 werden auf den gängigen 80mm-Druckern mit 42 Spalten umgebrochen.
Zentrierte formatierte Überschriften in <align>-Blöcken
Innerhalb von <align mode="center"> (oder right), eine direkt formatierte Überschrift — <bold>, <size>, <underline>, <invert> direkt darin platziert <align> — gefolgt von einer weiteren Zeile, wird automatisch in einer eigenen Zeile geschlossen. Ein zentrierter, skalierter Filialname über einer zentrierten Adresszeile wird sauber gedruckt, auch ohne den expliziten <text> Umbruch.
Außerhalb eines Ausrichtungsblocks behalten Sie das <text> Umbruch.
Normalisierung der ESC/POS-Interpunktion
Wenn die Druckersprache ESC/POS ist, normalisiert der Encoder typografische Zeichensetzung vor dem Schreiben zu sicherem ASCII:
- Halbgeviertstrich, Gedankenstrich, Ziffernstrich, Unicode-Minus →
- - Typografische Anführungszeichen → gerade Anführungszeichen
- Geschütztes Leerzeichen → reguläres Leerzeichen
So werden Mon–Sat 9:00–18:00 und "open" auch auf Druckern ohne Unicode-Schrift korrekt gedruckt. Star-Drucker (star-line / star-prnt) behalten die ursprüngliche Typografie bei; verwenden Sie daher Zeichen, die von der Schrift des Druckers unterstützt werden.
Logos und Bilder
Verwenden Sie <image> zum Einbetten eines Logos:
<align mode="center">
<image src="data:image/png;base64,..." />
</align>
WCPOS rastert Bilder auf dem Client — Dekodieren, Transparenz auf Weiß reduzieren, an das Punktbudget des Druckers anpassen, in Monochrom umwandeln (Atkinson-Dithering für Logos, Schwellenwert für Barcodes) — und sendet anschließend ESC/POS- oder Star-Bildbefehle.
- Punktbudgets: 384 Punkte Breite für 58mm, 576 Punkte Breite für 80mm.
- Akzeptierte Quellen: Daten-URLs vom Typ
data:image/pngunddata:image/jpeg, absolutehttp(s)URLs und gleichursprüngliche, root-relative Pfade. Protokollrelative//, Backslashes und prozentkodiertes..Traversal werden abgelehnt. - Empfohlenes Format: kontrastreiches PNG mit transparentem oder weißem Hintergrund. JPEG funktioniert, aber Kompressionsartefakte können als Störungen gedruckt werden.
- SVG wird noch nicht unterstützt für rohe Thermodruck-Ausgabe.
Tipps
- Mit einer Galerievorlage beginnen — die Thermodruck-Vorlagen in der Galerie verwenden alle oben genannten Muster und werden mit echten Druckern validiert.
- Testen Sie beide Papiergrößen, wenn Ihre Filialen unterschiedliche Drucker verwenden, oder bleiben Sie bei Spalten, die
width="*"verwenden. - Verwenden Sie Felder vom Typ
_displayfür Währungen — sie sind bereits locale-aware. - Einfach halten — Thermodruck bietet bewusst weniger Formatierungswerkzeuge als HTML. Setzen Sie auf
<row>+<col width="*">und lassen Sie den Drucker die Arbeit erledigen.