Passer au contenu principal
Version : 1.x

Modèles pour imprimantes thermiques

Les modèles thermiques utilisent un format XML qui produit à la fois un aperçu à l'écran et des commandes d'impression ESC/POS à partir du même modèle. Ils utilisent les mêmes balises {{variable}} que les modèles HTML pour la liaison de données.

Choisissez ce moteur si vous disposez d'une imprimante de reçus connectée via la Configuration de l'imprimante.

Éléments XML

Élément racine

Chaque modèle thermique commence par un <receipt> racine :

<receipt paper-width="48">
<!-- 48 characters = 80mm paper -->
<!-- 32 characters = 58mm paper -->
</receipt>

Texte et mise en forme

<text>Plain text</text>
<bold>Bold text</bold>
<underline>Underlined text</underline>
<invert>Inverted (white on black)</invert>

Alignement

<align mode="left">Left aligned</align>
<align mode="center">Centered</align>
<align mode="right">Right aligned</align>

Taille du texte

Mettez à l’échelle la largeur et la hauteur du texte indépendamment :

<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>

Mise en page tabulaire

Utilisez <row> et <col> pour des colonnes alignées :

<row>
<col width="24">Item name</col>
<col width="8" align="right">Qty</col>
<col width="16" align="right">Price</col>
</row>

Les largeurs de colonne sont exprimées en caractères. Utilisez width="*" pour une colonne flexible qui absorbe l’espace restant — cela permet aux modèles de fonctionner avec différentes largeurs de papier sans modification :

<row>
<col width="*">{{name}}</col>
<col width="12" align="right">{{line_total_display}}</col>
</row>

Séparateurs et espacement

<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/> (ou style="single") et style="double" impriment la règle native de l’imprimante. dashed et dotted impriment des séparateurs composés de caractères sur toute la largeur de colonne active — utile pour obtenir un séparateur visible qui reste présent dans une capture d’écran d’aperçu thermique.

Commandes d’imprimante

<cut /> <!-- Full paper cut -->
<cut mode="partial" /> <!-- Partial cut (leaves a tab) -->
<drawer /> <!-- Open cash drawer -->

Codes-barres et codes QR

<barcode type="code128" height="40">{{order.number}}</barcode>
<barcode type="qrcode" scale="3">{{fiscal.qr_payload}}</barcode>

Exemple : ticket simple de 80mm

<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>

Colonnes à largeur étoile

La fonctionnalité width="*" rend les modèles indépendants de la largeur du papier. Au lieu de définir en dur des largeurs de colonne pour un format de papier précis, utilisez * pour la colonne qui doit s’étirer :

<!-- 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>

Sur une imprimante 80mm (48 caractères), le nom de l’article obtient 38 caractères. Sur une imprimante 58mm (32 caractères), il obtient 22 caractères. Les colonnes fixes conservent la même taille dans les deux cas.

Aperçu du modèle

L’éditeur de modèle affiche un aperçu thermique en direct pendant la modification. L’aperçu affiche votre XML sous forme de HTML stylisé à chasse fixe, afin de simuler l’apparence du ticket sur papier. Les modifications se mettent à jour après un court délai (anti-rebond à 300ms).

Le même modèle produit à la fois l’aperçu et la sortie d’imprimante ESC/POS — il n’existe pas de modèle « impression » séparé. Les codes-barres et les codes QR sont affichés sous forme de SVG intégrés dans l’aperçu et sous forme de commandes ESC/POS natives (ou d’images matricielles) sur l’imprimante.

Conseils de rédaction et pièges à éviter

L’impression thermique comporte quelques pièges qui n’existent pas en HTML. Voici ceux que les auteurs rencontrent le plus souvent.

Encapsuler les titres stylisés dans <text> pour obtenir un saut de ligne

Conteneurs stylisés — <bold>, <size>, <underline>, <align>n’émettent pas de saut de ligne par eux-mêmes. Seuls <text> et les éléments de bloc (<line/>, <row>, <feed>) le font.

<!-- ❌ 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>

Les modèles de galerie 80mm fournis utilisent ce schéma pour chaque titre.

Évitez <size width="2"> dans les lignes étroites

Le texte en double largeur double le nombre effectif de caractères. Un titre qui tient sur une imprimante 80mm peut déborder sur une imprimante 80mm générique de 42 colonnes, et sur papier 58mm, il ne laisse que 16 caractères.

Pour les valeurs importantes (grands totaux, numéros de commande en cuisine), générez une ligne mise à l’échelle autonome plutôt que de l’encapsuler dans une disposition à plusieurs colonnes <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>

Utiliser width="*" pour des mises en page indépendantes de la largeur du papier

La colonne width="*" (étoile) absorbe la largeur restante après les colonnes à largeur fixe. Le même modèle s’affiche alors correctement sur les imprimantes 32 colonnes (58mm), 42 colonnes (80mm standard) et 48 colonnes (80mm large) sans modification :

<!-- Works on 58mm AND 80mm without changes -->
<row>
<col width="*">{{name}}</col>
<col width="10" align="right">{{line_total_display}}</col>
</row>

Si vous utilisez des largeurs numériques codées en dur, prévoyez-les pour 42, et non 48. Les lignes dont la somme atteint 48 passeront à la ligne sur les imprimantes 80mm courantes à 42 colonnes.

Titres stylisés centrés dans des blocs <align>

À l’intérieur de <align mode="center"> (ou right), un titre stylisé direct — <bold>, <size>, <underline>, <invert> placé directement à l’intérieur <align> — suivi d’une autre ligne, est automatiquement fermé sur sa propre ligne. Un nom de boutique centré et mis à l’échelle au-dessus d’une ligne d’adresse centrée s’imprime proprement même sans le <text> retour à la ligne.

En dehors d’un bloc d’alignement, conservez le <text> retour à la ligne.

Normalisation de la ponctuation ESC/POS

Lorsque le langage de l’imprimante est ESC/POS, l’encodeur normalise la ponctuation typographique en ASCII sûr avant l’écriture :

  • Tiret demi-cadratin, tiret cadratin, tiret numérique, signe moins Unicode → -
  • Guillemets typographiques → guillemets droits
  • Espace insécable → espace ordinaire

Ainsi Mon–Sat 9:00–18:00 et "open" s’impriment correctement, même sur les imprimantes sans police Unicode. Les imprimantes Star (star-line / star-prnt) préservent la typographie d’origine ; utilisez donc des caractères pris en charge par la police de l’imprimante.

Écritures non latines et de droite à gauche

Les imprimantes thermiques impriment le texte à l’aide d’une police et d’une page de code intégrées. L’arabe, l’hébreu, le persan, l’ourdou et les autres écritures non latines ne s’impriment donc correctement que si l’imprimante est configurée avec une page de code correspondante (par exemple CP864 / Windows-1256 pour l’arabe) — sinon, vous obtenez des blancs ou des caractères illisibles.

L’approche fiable pour ces écritures est Reçu entièrement rastérisé, qui rend l’ensemble du reçu sous forme d’image afin qu’il s’imprime exactement comme prévu, quelles que soient les polices intégrées de l’imprimante. Consultez Configuration de l’imprimante pour activer le mode raster.

Le matériel thermique nécessite un modèle thermique

Une imprimante thermique ne peut pas imprimer un modèle HTML pleine page — la tâche doit être rendue en commandes ESC/POS ou Star, ce que HTML ne peut pas exprimer. Utilisez un modèle thermique pour le matériel thermique ; pour du HTML pleine page A4/Letter, imprimez vers une imprimante système/PDF ou via PrintNode.

Logos et images

Utilisez <image> pour intégrer un logo :

<align mode="center">
<image src="data:image/png;base64,..." />
</align>

WCPOS rastérise les images côté client — décodage, aplatissement de la transparence en blanc, redimensionnement selon le budget de points de l’imprimante, conversion en monochrome (tramage Atkinson pour les logos, seuil pour les codes-barres) — puis envoie des commandes d’image ESC/POS ou Star.

  • Budgets de points : 384 points de large pour 58mm, 576 points de large pour 80mm.
  • Sources acceptées : URL de données data:image/png et data:image/jpeg, URL absolues http(s) et chemins relatifs à la racine de même origine. Les chemins relatifs au protocole //, les barres obliques inverses et les traversées .. encodées en pourcentage sont rejetés.
  • Format recommandé : PNG à contraste élevé avec un arrière-plan transparent ou blanc. JPEG fonctionne, mais les artefacts de compression peuvent s’imprimer sous forme de bruit.
  • SVG n'est pas encore pris en charge pour la sortie thermique brute.

Conseils

  • Partez d'un modèle de la galerie — les modèles thermiques de la galerie utilisent tous les motifs ci-dessus et sont validés sur de vraies imprimantes.
  • Testez les deux tailles de papier si vos boutiques utilisent des imprimantes différentes, ou utilisez des colonnes width="*".
  • Utilisez les champs _display pour les devises — ils sont déjà adaptés à la locale.
  • Restez simple — le thermique offre volontairement moins d'outils de mise en forme que le HTML. Appuyez-vous sur <row> + <col width="*"> et laissez l'imprimante faire le reste.