# Modèles HTML

Les modèles HTML utilisent une syntaxe sans logique de style Mustache avec des espaces réservés `{{variable}}`. Ils sont rendus côté client dans l’application POS, ce qui signifie qu’ils **fonctionnent hors ligne** — aucune connexion au serveur n’est nécessaire pour afficher ou imprimer un reçu.

C’est le moteur recommandé pour la plupart des utilisateurs.

## Syntaxe[​](#syntax "Lien direct vers Syntaxe")

### Variables[​](#variables "Lien direct vers Variables")

Insérez des données à l’aide de doubles accolades :

```
<h1>{{store.name}}</h1>

<p>Order #{{order.number}}</p>

<p>Total: {{totals.total_display}}</p>
```

Utilisez les variantes `_display` pour les valeurs monétaires préformatées (par exemple, `$12.50` au lieu de `12.5`). Consultez la [référence des données de reçu](/fr/receipts/receipt-data.md) pour connaître tous les champs disponibles.

### Sections (boucles et conditions)[​](#sections-loops-and-conditionals "Lien direct vers Sections (boucles et conditions)")

Utilisez `{{#section}}...{{/section}}` pour parcourir des tableaux en boucle ou afficher du contenu de manière conditionnelle :

```
{{#lines}}

<div class="line-item">

  <span>{{name}} × {{qty}}</span>

  <span>{{line_total_display}}</span>

</div>

{{/lines}}
```

### Sections inversées[​](#inverted-sections "Lien direct vers Sections inversées")

Utilisez `{{^section}}...{{/section}}` pour afficher le contenu lorsqu’une valeur est vide ou fausse :

```
{{#customer.id}}

  <p>Customer: {{customer.name}}</p>

{{/customer.id}}

{{^customer.id}}

  <p>Guest checkout</p>

{{/customer.id}}
```

### Libellés localisés[​](#localised-labels "Lien direct vers Libellés localisés")

Utilisez `{{i18n.key}}` pour les libellés traduisibles qui s’adaptent à la langue de la boutique :

```
<th>{{i18n.subtotal}}</th>

<td>{{totals.subtotal_display}}</td>
```

## Schémas courants[​](#common-patterns "Lien direct vers Schémas courants")

### En-tête de la boutique[​](#store-header "Lien direct vers En-tête de la boutique")

Le tableau `store.address_lines` est préformaté pour les reçus : parcourez-le avec une boucle au lieu d’assembler des champs d’adresse individuels.

```
<div style="text-align: center;">

  {{#store.logo}}<img src="{{store.logo}}" alt="{{store.name}}" style="max-width: 200px;" />{{/store.logo}}

  <h1 style="margin: 8px 0;">{{store.name}}</h1>

  {{#store.address_lines}}<div>{{.}}</div>{{/store.address_lines}}

  {{#store.phone}}<div>{{store.phone}}</div>{{/store.phone}}

  {{#store.tax_ids}}<div>{{#label}}{{label}} {{/label}}{{value}}</div>{{/store.tax_ids}}

</div>
```

### Lignes d’articles avec remises[​](#line-items-with-discounts "Lien direct vers Lignes d’articles avec remises")

Le champ `discounts` d’une ligne d’article correspond au montant de la remise sous forme de nombre positif, ou à `0` lorsqu’il n’y a pas de remise. Mustache traite `0` comme une valeur fausse ; `{{#discounts}}...{{/discounts}}` est donc la condition de garde appropriée.

```
{{#lines}}

<div class="line-item" style="display: flex; justify-content: space-between;">

  <div>

    <div>{{name}} × {{qty}}</div>

    {{#discounts}}

      <div style="font-size: 0.9em; color: #6b7280;">

        <s>{{unit_subtotal_display}}</s> {{unit_price_display}}

      </div>

    {{/discounts}}

  </div>

  <div>{{line_total_display}}</div>

</div>

{{/lines}}
```

### Récapitulatif des taxes[​](#tax-summary "Lien direct vers Récapitulatif des taxes")

```
{{#tax_summary}}

<div class="tax-line">

  <span>{{label}} ({{rate}}%)</span>

  <span>{{tax_amount_display}}</span>

</div>

{{/tax_summary}}
```

### Détails du paiement[​](#payment-details "Lien direct vers Détails du paiement")

```
{{#payments}}

<div class="payment" style="display: flex; justify-content: space-between;">

  <span>{{method_title}}</span>

  <span>{{amount_display}}</span>

</div>

{{#tendered}}

  <div style="display: flex; justify-content: space-between;">

    <span>{{i18n.tendered}}</span><span>{{tendered_display}}</span>

  </div>

  <div style="display: flex; justify-content: space-between;">

    <span>{{i18n.change}}</span><span>{{change_display}}</span>

  </div>

{{/tendered}}

{{/payments}}
```

### Codes-barres et codes QR[​](#barcodes-and-qr-codes "Lien direct vers Codes-barres et codes QR")

Utilisez le `<barcode>` élément — la même syntaxe que [modèles thermiques](/fr/receipts/thermal-templates.md). La valeur se place dans l’élément ; la symbologie est définie sur l’ `type` attribut. Le moteur de rendu remplace chaque élément par un SVG en ligne.

```
<!-- Code 128 barcode of the order number -->

<barcode type="code128" height="40">{{order.number}}</barcode>



<!-- QR code -->

<barcode type="qrcode" scale="3">{{order.payment_url}}</barcode>



<!-- EAN-13 -->

<barcode type="ean13">{{order.number}}</barcode>
```

L’attribut `type` doit être défini **littéralement** dans le modèle — il ne peut pas provenir d’un placeholder. Un `type` de `qr` ou `qrcode` s’affiche comme un code QR dans les modèles HTML comme dans les modèles thermiques.

Si le type de code-barres sélectionné ne peut pas encoder la valeur (par exemple des données EAN-13 non numériques ou de longueur incorrecte), l’aperçu affiche un bloc `Barcode error` ou `QR code error` avec la valeur d’origine, afin de corriger la valeur ou de passer à un type compatible.

Toutes les [symbologies bwip-js](https://github.com/metafloor/bwip-js/wiki/Supported-Barcode-Types) sont prises en charge — `code128`, `qrcode`, `ean13`, `ean8`, `upca`, `pdf417`, `datamatrix`, et bien d’autres.

## Mise en forme[​](#styling "Lien direct vers Mise en forme")

Les modèles sans logique sont nettoyés via WordPress `wp_kses_post` de WordPress avant le rendu, ce qui **supprime `<style>`, `<head>`, et les balises au niveau du document**. Utilisez des **styles en ligne** sur chaque élément :

```
<div style="font-family: monospace; font-size: 12px; max-width: 300px; margin: 0 auto;">

  <div style="text-align: center; margin-bottom: 16px;">

    <strong style="font-size: 16px;">{{store.name}}</strong>

  </div>

  <div style="display: flex; justify-content: space-between; font-weight: 700; border-top: 1px solid black; padding-top: 8px;">

    <span>{{i18n.total}}</span>

    <span>{{totals.total_display}}</span>

  </div>

</div>
```

La même restriction s’applique à `<script>`, `<link>`, ainsi qu’aux autres balises hors contenu — elles sont supprimées, donc ne vous appuyez pas sur du CSS ou du JavaScript externe.

Conçu pour le noir et blanc

Les reçus sont généralement imprimés sur des imprimantes thermiques ou laser noir et blanc. Concevez-les en conséquence — utilisez **la graisse de police, les espaces, le contraste typographique et les règles horizontales** pour établir la hiérarchie plutôt que des aplats de couleur. Les arrière-plans colorés et le texte gris disparaissent à l’impression en N\&B ou s’impriment sous forme de trames ternes.

Besoin d’un rendu de papier thermique sans imprimante thermique ?

Cliquez sur **Utiliser le modèle** sur la carte **Reçu étroit** dans la galerie — c’est une mise en page monospace de 72mm de large qui s’imprime proprement avec l’impression du navigateur, les imprimantes thermiques compatibles HTML (appareils Sunmi/Imin WebView) et le papier standard. Ne convient pas aux imprimantes thermiques ESC/POS brutes — utilisez les modèles XML **Reçu thermique simple** pour celles-ci.

## Bonnes pratiques[​](#best-practices "Lien direct vers Bonnes pratiques")

* **Utilisez les champs `_display`** pour toutes les valeurs monétaires — ils gèrent automatiquement le formatage adapté aux paramètres régionaux
* **Utilisez les libellés `{{i18n.*}}`** au lieu de coder le texte en dur, afin que les modèles fonctionnent dans toutes les langues
* **Utilisez des sections pour les affichages conditionnels** — enveloppez les champs facultatifs dans `{{#field}}...{{/field}}` afin qu’ils soient masqués lorsqu’ils sont vides
* **Commencez à partir d’un modèle de galerie** plutôt que de partir de zéro
* **Testez avec l’aperçu** dans l’éditeur de modèles avant l’activation
