# CHAPITRE 18 — Annoter un template avec des slots

Le slot est l'unité de base du module. Ce chapitre vous montre comment transformer un HTML statique en HTML annoté, prêt à être édité par le client. Il s'agit de l'opération la plus fréquente dans votre travail d'intégrateur.

### <span style="color: rgb(35, 111, 161);">Le principe en deux phrases</span>

1. Vous écrivez votre HTML normalement, comme vous le feriez sans le module.
2. <span style="white-space: pre-wrap;">Aux endroits que vous voulez rendre éditables, vous remplacez le contenu en dur par un token </span>`<span class="editor-theme-code">{{slot:...}}</span>`.

C'est tout. Le module se charge du reste : détection automatique, persistance, rendu, interface d'édition.

### <span style="color: rgb(35, 111, 161);">Premier exemple complet</span>

##### **Avant — page non éditable**

```
<section class="hero">
    <h1>Bienvenue chez Keatic</h1>
    <p>Votre partenaire numérique de confiance depuis 2010.</p>
    <a href="/contact" class="btn">Nous contacter</a>
</section>
```

##### **Après — page éditable via le Studio**

```
<section class="hero">
    <h1>{{slot:hero_title|type=text|default=Bienvenue chez Keatic|label=Titre du hero|group=hero}}</h1>
    <p>{{slot:hero_lead|type=textarea|default=Votre partenaire numérique de confiance depuis 2010.|label=Accroche|group=hero}}</p>
    <a href="{{slot:hero_cta_url|type=url|default=/contact|label=URL du bouton|group=hero}}" class="btn">
        {{slot:hero_cta_label|type=text|default=Nous contacter|label=Libellé du bouton|group=hero}}
    </a>
</section>
```

<p class="callout success">**Résultat —**<span style="white-space: pre-wrap;"> Le client voit dans le Studio un panneau « Hero » comportant quatre champs (titre, accroche, URL du bouton, libellé du bouton). Aucun HTML à modifier de son côté.</span></p>

### <span style="color: rgb(35, 111, 161);">Anatomie d'un token de slot</span>

```
{{slot:<identifiant>|type=<type>|attribut1=valeur1|attribut2=valeur2}}
```

<table id="bkmrk-%C3%89l%C3%A9mentobligatoirede" style="width: 100%; border-collapse: collapse; margin: 1rem 0px; font-size: 0.95em;"><colgroup><col></col><col></col><col></col></colgroup><tbody><tr style="background: rgb(25, 5, 45); color: rgb(254, 252, 232);"><th class="align-left" style="padding: 0.6rem 1rem; text-align: left; border: 1px solid rgb(25, 5, 45);">Élément

</th><th class="align-left" style="padding: 0.6rem 1rem; text-align: left; border: 1px solid rgb(25, 5, 45);">Obligatoire

</th><th class="align-left" style="padding: 0.6rem 1rem; text-align: left; border: 1px solid rgb(25, 5, 45);">Description

</th></tr><tr><td style="padding: 0.5rem 1rem; border: 1px solid rgb(229, 231, 235);">`<span class="editor-theme-code">{{slot:</span>`

</td><td style="padding: 0.5rem 1rem; border: 1px solid rgb(229, 231, 235);">Oui

</td><td style="padding: 0.5rem 1rem; border: 1px solid rgb(229, 231, 235);">Préfixe fixe qui déclare un slot.

</td></tr><tr style="background: rgb(250, 245, 255);"><td style="padding: 0.5rem 1rem; border: 1px solid rgb(229, 231, 235);">Identifiant

</td><td style="padding: 0.5rem 1rem; border: 1px solid rgb(229, 231, 235);">Oui

</td><td style="padding: 0.5rem 1rem; border: 1px solid rgb(229, 231, 235);">Unique par page. Caractères acceptés : minuscules, chiffres, tiret bas. 64 caractères maximum.

</td></tr><tr><td style="padding: 0.5rem 1rem; border: 1px solid rgb(229, 231, 235);">`<span class="editor-theme-code">type=</span>`

</td><td style="padding: 0.5rem 1rem; border: 1px solid rgb(229, 231, 235);">Oui

</td><td style="padding: 0.5rem 1rem; border: 1px solid rgb(229, 231, 235);">text, textarea, richtext, image, url, number, select, bool, icon, color.

</td></tr><tr style="background: rgb(250, 245, 255);"><td style="padding: 0.5rem 1rem; border: 1px solid rgb(229, 231, 235);">`<span class="editor-theme-code">default=</span>`

</td><td style="padding: 0.5rem 1rem; border: 1px solid rgb(229, 231, 235);">Recommandé

</td><td style="padding: 0.5rem 1rem; border: 1px solid rgb(229, 231, 235);">Valeur de repli si le slot n'est pas encore édité.

</td></tr><tr><td style="padding: 0.5rem 1rem; border: 1px solid rgb(229, 231, 235);">`<span class="editor-theme-code">label=</span>`

</td><td style="padding: 0.5rem 1rem; border: 1px solid rgb(229, 231, 235);">Recommandé

</td><td style="padding: 0.5rem 1rem; border: 1px solid rgb(229, 231, 235);">Libellé affiché à l'éditeur dans le Studio.

</td></tr><tr style="background: rgb(250, 245, 255);"><td style="padding: 0.5rem 1rem; border: 1px solid rgb(229, 231, 235);">`<span class="editor-theme-code">group=</span>`

</td><td style="padding: 0.5rem 1rem; border: 1px solid rgb(229, 231, 235);">Facultatif

</td><td style="padding: 0.5rem 1rem; border: 1px solid rgb(229, 231, 235);">Regroupe les slots dans une section de l'interface.

</td></tr><tr><td style="padding: 0.5rem 1rem; border: 1px solid rgb(229, 231, 235);">`<span class="editor-theme-code">help=</span>`

</td><td style="padding: 0.5rem 1rem; border: 1px solid rgb(229, 231, 235);">Facultatif

</td><td style="padding: 0.5rem 1rem; border: 1px solid rgb(229, 231, 235);">Aide affichée sous le champ.

</td></tr><tr style="background: rgb(250, 245, 255);"><td style="padding: 0.5rem 1rem; border: 1px solid rgb(229, 231, 235);">`<span class="editor-theme-code">maxlength=</span>`

</td><td style="padding: 0.5rem 1rem; border: 1px solid rgb(229, 231, 235);">Facultatif

</td><td style="padding: 0.5rem 1rem; border: 1px solid rgb(229, 231, 235);">Limite de caractères pour text et textarea.

</td></tr><tr><td style="padding: 0.5rem 1rem; border: 1px solid rgb(229, 231, 235);">`<span class="editor-theme-code">options=</span>`

</td><td style="padding: 0.5rem 1rem; border: 1px solid rgb(229, 231, 235);">Si type=select

</td><td style="padding: 0.5rem 1rem; border: 1px solid rgb(229, 231, 235);">Liste CSV des valeurs possibles.

</td></tr></tbody></table>

**Conseil —**<span style="white-space: pre-wrap;"> La grammaire complète est détaillée au Chapitre 19.</span>

### <span style="color: rgb(35, 111, 161);">Où placer un slot</span>

Un slot peut être placé à de nombreux endroits dans votre HTML.

##### **Dans le contenu d'une balise (cas le plus fréquent)**

```
<h1>{{slot:title|type=text|default=Bienvenue}}</h1>
```

##### **Dans un attribut HTML**

```
<img src="{{slot:hero_image|type=image|default=/medias/hero.jpg}}" alt="...">
<a href="{{slot:cta_url|type=url|default=/contact}}">...</a>
<section style="background-color:{{slot:bg_color|type=color|default=#19052d}}">
```

##### **Dans une chaîne de classes CSS**

```
<i class="fa-solid {{slot:hero_icon|type=text|default=fa-rocket}}"></i>
```

<p class="callout warning">**À ne pas faire —**<span style="white-space: pre-wrap;"> Ne placez pas un slot dans un commentaire HTML, dans un bloc </span>`<span class="editor-theme-code"><script></span>`, ou dans du JSON intégré. Le scanner détecte tous les tokens et peut générer des slots fantômes.</p>

### <span style="color: rgb(35, 111, 161);">Convention de nommage des identifiants</span>

L'identifiant est libre, mais une convention claire facilite la maintenance.

##### **Schéma recommandé**

`<span class="editor-theme-code"><section>_<champ></span>`<span style="white-space: pre-wrap;"> ou </span>`<span class="editor-theme-code"><page>_<section>_<champ></span>`

<table id="bkmrk-bon%C3%80-%C3%A9viterhero_titl" style="width: 100%; border-collapse: collapse; margin: 1rem 0px; font-size: 0.95em;"><colgroup><col></col><col></col></colgroup><tbody><tr style="background: rgb(25, 5, 45); color: rgb(254, 252, 232);"><th class="align-left" style="padding: 0.6rem 1rem; text-align: left; border: 1px solid rgb(25, 5, 45);">Bon

</th><th class="align-left" style="padding: 0.6rem 1rem; text-align: left; border: 1px solid rgb(25, 5, 45);">À éviter

</th></tr><tr><td style="padding: 0.5rem 1rem; border: 1px solid rgb(229, 231, 235);">`<span class="editor-theme-code">hero_title</span>`

</td><td style="padding: 0.5rem 1rem; border: 1px solid rgb(229, 231, 235);">`<span class="editor-theme-code">title</span>`

<span style="white-space: pre-wrap;"> (trop générique, risque de collision)</span>

</td></tr><tr style="background: rgb(250, 245, 255);"><td style="padding: 0.5rem 1rem; border: 1px solid rgb(229, 231, 235);">`<span class="editor-theme-code">features_grid_card_3_label</span>`

</td><td style="padding: 0.5rem 1rem; border: 1px solid rgb(229, 231, 235);">`<span class="editor-theme-code">truc3</span>`

<span style="white-space: pre-wrap;"> (incompréhensible)</span>

</td></tr><tr><td style="padding: 0.5rem 1rem; border: 1px solid rgb(229, 231, 235);">`<span class="editor-theme-code">footer_copyright</span>`

</td><td style="padding: 0.5rem 1rem; border: 1px solid rgb(229, 231, 235);">`<span class="editor-theme-code">FooterCopyright</span>`

<span style="white-space: pre-wrap;"> (les majuscules sont rejetées par le scanner)</span>

</td></tr></tbody></table>

<p class="callout info">**Recommandé —**<span style="white-space: pre-wrap;"> Si votre site comporte cinq sections (hero, features, stats, testimonials, footer), préfixez tous vos slots par leur section. Le client retrouvera ainsi plus rapidement ce qu'il cherche dans le Studio.</span></p>

### <span style="color: rgb(35, 111, 161);">Utiliser le groupe pour structurer l'interface</span>

<span style="white-space: pre-wrap;">L'attribut </span>`<span class="editor-theme-code">group</span>`<span style="white-space: pre-wrap;"> détermine sous quelle section le slot apparaît dans le panneau « Contenu de la page » du Studio.</span>

```
{{slot:hero_title|type=text|group=hero|...}}
{{slot:hero_lead|type=textarea|group=hero|...}}
{{slot:hero_image|type=image|group=hero|...}}

{{slot:features_card_1_title|type=text|group=features|...}}
{{slot:features_card_2_title|type=text|group=features|...}}
{{slot:features_card_3_title|type=text|group=features|...}}

{{slot:footer_copyright|type=text|group=footer|...}}
```

Dans le Studio, ces slots seront regroupés visuellement sous trois sections : Hero, Features et Footer.

### <span style="color: rgb(35, 111, 161);">Le rescan après ajout</span>

<span style="white-space: pre-wrap;">Ajouter un slot dans un fichier </span>`<span class="editor-theme-code">tpl.php</span>`<span style="white-space: pre-wrap;"> ne suffit pas : le module doit le détecter et l'enregistrer en base. Pour cela, lancez un rescan.</span>

##### **Méthode A — Via l'interface Studio**

1. Outils → InfraSStudio → Contenu des pages.
2. Sélectionnez votre site.
3. <span style="white-space: pre-wrap;">Cliquez sur </span>**Rescanner**<span style="white-space: pre-wrap;"> en haut.</span>
4. <span style="white-space: pre-wrap;">Le module parcourt tous les fichiers </span>`<span class="editor-theme-code">tpl.php</span>`<span style="white-space: pre-wrap;"> et synchronise les slots.</span>

##### **Méthode B — En ligne de commande**

```
php htdocs/custom/infrasstudio/scripts/rescan_slots.php <ref-du-site> --entity=<N>
```

Sortie typique :

```
Rescanning website #1 — monsite (entity 2)
Pages scanned   : 22
Slots added     : 3
Slots updated   : 40
Slots orphaned  : 0
```

**Mode de validation —**<span style="white-space: pre-wrap;"> Ajoutez l'option </span>`<span class="editor-theme-code">--lint</span>`<span style="white-space: pre-wrap;"> pour détecter les erreurs de syntaxe avant de les valider :</span>  
`<span class="editor-theme-code">php rescan_slots.php <ref> --lint</span>`  
Le code de sortie est 0 en l'absence d'erreur, 1 en présence d'avertissements, 2 en cas d'erreurs. Cette commande peut être intégrée dans un crochet de pré-commit.

### <span style="color: rgb(35, 111, 161);">Slots orphelins</span>

<span style="white-space: pre-wrap;">Lorsque vous supprimez un slot d'un fichier </span>`<span class="editor-theme-code">tpl.php</span>`, son enregistrement en base passe au statut « orphelin ». Le module le conserve pendant 30 jours avant de le supprimer automatiquement (via une tâche planifiée).

Cette politique présente un avantage : si vous restaurez le slot dans le HTML pendant cette période, sa valeur précédente est récupérée.

<p class="callout info">**Note —**<span style="white-space: pre-wrap;"> Pour forcer la purge immédiate des slots orphelins :</span>  
`<span class="editor-theme-code">php rescan_slots.php <ref> --purge-orphans</span>`</p>

### <span style="color: rgb(35, 111, 161);">Liste de contrôle d'annotation</span>

**Avant de livrer une page annotée :**

- <span style="white-space: pre-wrap;">Chaque slot possède un </span>`<span class="editor-theme-code">type</span>`<span style="white-space: pre-wrap;"> explicite.</span>
- <span style="white-space: pre-wrap;">Chaque slot possède une valeur </span>`<span class="editor-theme-code">default</span>`, garantissant la lisibilité de la page si la base venait à se vider.
- <span style="white-space: pre-wrap;">Chaque slot possède un </span>`<span class="editor-theme-code">label</span>`<span style="white-space: pre-wrap;"> en français clair, destiné à l'éditeur.</span>
- <span style="white-space: pre-wrap;">Les slots sont regroupés par section avec </span>`<span class="editor-theme-code">group</span>`.
- <span style="white-space: pre-wrap;">Les identifiants suivent la convention </span>`<span class="editor-theme-code"><section>_<champ></span>`.
- Le rescan a été lancé sans avertissement ni erreur.
- Vous avez ouvert la page dans le Studio et vérifié la présence de tous les slots.

Le chapitre suivant détaille la grammaire complète des slots, avec tous les types et leurs comportements.