
# Références de page

Les valeurs de `content` et de `props` d'un composant résolvent quatre familles de références au moment du rendu :

| Référence               | Résout vers                                                                                |
| ----------------------- | ------------------------------------------------------------------------------------------ |
| `$record.<champ>`       | Un champ de l'enregistrement courant de la source de données.                              |
| `$vars.<clé>`           | Une variable de portée page, déclarée dans le `vars` de la page.                           |
| `$currentUser.<chemin>` | Le contexte de session, par requête.                                                       |
| `$t:<clé>`              | Une clé de traduction, qui se rabat sur la clé elle-même quand aucune traduction n'existe. |

Une page rendue depuis du `markdown` expose en plus `$frontmatter.*`. Une cinquième référence, `$session.<champ>`, résout dans le navigateur plutôt qu'au rendu.

## Les paramètres de requête comme entrées de page

Le bloc `query` d'une page ouvre des paramètres de requête d'URL comme entrées de page, référençables par `$query.<nom>` partout où la substitution `$vars` s'applique. Chacun déclare une **liste blanche fermée** et une valeur par défaut.

| Propriété   | Description                                                                                                                              |
| ----------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `enum`      | Liste fermée des valeurs acceptées ; tout le reste se rabat sur `default`.                                                               |
| `default`   | Valeur employée quand l'URL omet le paramètre ou en fournit une hors `enum`.                                                             |
| `onUnknown` | Valeur vers laquelle résout une valeur d'URL inconnue, distinguée du cas où l'URL omet le paramètre. Doit elle-même figurer dans `enum`. |

```yaml
name: my-app
pages:
  - name: dashboard
    path: /dashboard
    query:
      period:
        default: 7d
        enum: [24h, 7d, 30d]
    components:
      - { type: text, content: 'Showing the last $query.period' }
```

`/dashboard` affiche `7d` ; `/dashboard?period=30d` affiche `30d`.

**Une valeur inconnue se rabat sur la valeur par défaut — la page ne répond jamais 400.** Une chaîne de requête est fournie par qui détient le lien, et un signet périmé n'est pas une condition d'erreur : une valeur non reconnue s'affiche donc exactement comme si le paramètre était absent. Borner l'ensemble accepté borne aussi l'espace des réponses à un rendu par valeur autorisée, et c'est ce qui garde la page cachable par valeur.

`default` doit faire partie de son propre `enum`, et chaque nom de propriété doit être en kebab-case minuscule ; les deux sont vérifiés au démarrage.

## Contraindre un segment de route

Le bloc `params` d'une page contraint un `:segment` à un ensemble fermé fourni par un point de lecture. Un segment hors de l'ensemble répond `404` plutôt que d'afficher une page vide — la même distinction que l'explorateur d'enregistrements fait entre « n'existe pas » et « est vide ».

| Propriété  | Description                                                                                             |
| ---------- | ------------------------------------------------------------------------------------------------------- |
| `system`   | Liaison à un point de lecture : `endpoint`, `rowsKey`, `param`, `idKey`, `totalKey`, `query`, `bindTo`. |
| `valueKey` | Clé de ligne portant chaque valeur de segment autorisée. Par défaut, l'`idKey` de l'enveloppe.          |

## Une fenêtre glissante relative

Un lecteur d'analytique veut des instants absolus, et `$query.period` substitue l'identifiant de préréglage `7d`, qui n'est pas un horodatage. Le bloc `window` d'une page referme cet écart : il déclare une liste fermée d'intervalles relatifs sélectionnés depuis l'URL, et résout celui qui est choisi en instants concrets au rendu.

| Propriété | Description                                                                                         |
| --------- | --------------------------------------------------------------------------------------------------- |
| `param`   | Clé de requête d'URL qui sélectionne la fenêtre. `period` par défaut.                               |
| `default` | Identifiant de préréglage employé quand l'URL omet le paramètre ou nomme un préréglage non déclaré. |
| `presets` | Les fenêtres sélectionnables, dans l'ordre du sélecteur. Au moins une est requise.                  |

```yaml
name: my-app
pages:
  - name: analytics
    path: /analytics
    window:
      param: period
      default: 7d
      presets:
        - { id: 24h, granularity: hour, label: last 24 hours }
        - { id: 7d }
        - { id: 30d }
    components:
      - type: text
        content: Measured over the $window.label.
```

Cinq références résolvent, une fois par rendu :

| Référence             | Valeur                                                                    |
| --------------------- | ------------------------------------------------------------------------- |
| `$window.start`       | Instant ISO d'ouverture de la fenêtre.                                    |
| `$window.end`         | Instant ISO de fermeture — le moment où la page a été rendue.             |
| `$window.granularity` | Largeur de seau pour une série temporelle : heure, jour, semaine ou mois. |
| `$window.label`       | La formule qui nomme la fenêtre dans le texte visible.                    |
| `$window.id`          | L'identifiant du préréglage actif, pour marquer un sélecteur.             |

Un identifiant de préréglage est un intervalle : un entier positif suivi de `h`, `d` ou `w`, comme `24h`, `7d`, `2w`. Les mois et les années sont absents parce qu'aucun des deux n'a de longueur fixe — « un mois avant le 31 mars » n'a pas de réponse unique défendable. La granularité et le libellé se déduisent de l'intervalle et peuvent chacun être surchargés par préréglage.

Elles résolvent **une seule fois** par rendu, contre un instant unique. Des panneaux qui liraient chacun l'horloge pour leur propre compte verraient leurs fenêtres diverger de la durée du rendu, et une page qui rapporte deux périodes à la fois vous invite à les comparer.

**Une valeur non reconnue se rabat sur la valeur par défaut et répond 200**, exactement comme `query`. Garder la liste fermée est aussi ce qui garde la page cachable : l'ensemble atteignable est d'un rendu par préréglage, et un rendu en cache porte à la fois le préréglage et un instant de fin arrondi à la minute, de sorte qu'un chiffre n'est jamais servi sous un horodatage auquel il n'a pas été mesuré.

`default` doit nommer l'un des préréglages déclarés, les identifiants doivent être uniques, et `param` ne peut pas masquer un nom de propriété `query` ; les trois sont vérifiés au démarrage.

## Portée à l'utilisateur courant

`$currentUser` résout par requête pendant le rendu serveur, et n'est jamais mis en cache d'un utilisateur à l'autre.

| Chemin                             | Valeur                                                                                                        |
| ---------------------------------- | ------------------------------------------------------------------------------------------------------------- |
| `$currentUser.id`                  | L'identifiant de l'utilisateur connecté.                                                                      |
| `$currentUser.email`               | Son adresse e-mail.                                                                                           |
| `$currentUser.role`                | Le nom de son rôle.                                                                                           |
| `$currentUser.isUnrestricted`      | `true` pour une administratrice globale, qui contourne la portée par affectation.                             |
| `$currentUser.assignments.<table>` | Les identifiants d'enregistrements auxquels l'utilisateur est affecté dans cette table. À associer avec `in`. |
| `$currentUser.activeAssignment`    | La portée active du sélecteur de locataire, ou rien.                                                          |

```yaml
name: my-app
tables:
  - name: projects
    fields:
      - { name: name, type: single-line-text }
pages:
  - name: Projects
    path: /projects
    components:
      - type: table
        dataSource:
          table: projects
          filter:
            - { field: id, operator: in, value: '$currentUser.assignments.projects' }
```

**Un filtre `$currentUser` rend la page authentifiée.** En résoudre un sans session répond `401 Unauthorized` — c'est distinct de la garde `access` de la page, qui redirige ou répond `404`. Une section de barre latérale qui rencontre la même condition est retirée silencieusement plutôt que de faire échouer la page.

## Texte lié à la session

`$session.<champ>` résout le champ de session **de l'appelant connecté lui-même** — `email`, `name`, `role` ou `id` — à l'intérieur du `content` d'un composant. C'est la contrepartie côté navigateur de `$currentUser`, et le lieu de résolution fait toute la différence : `$currentUser` est substitué côté serveur à chaque requête, `$session` une fois la page servie. C'est ce qui permet à une salutation liée à la session de vivre sur une page en cache statique sans que le cache porte jamais l'identité d'un lecteur jusqu'au suivant.

Un jeton qui ne résout rien — un appelant anonyme, ou un champ que le compte ne porte pas — devient la chaîne vide.

### Segments optionnels

Un jeton nu ne peut pas porter sa propre ponctuation. Une salutation écrite `Welcome, $session.name` est bien formée et fautive deux fois : le serveur n'a pas de session, donc les octets servis se lisent `Welcome,` avec une virgule en suspens pour tout lecteur sans JavaScript, et un appelant connecté dont le compte ne porte pas de nom d'affichage lit la même chose. La virgule appartient au nom, et la forme jeton n'a aucun moyen de le dire.

Enveloppez le littéral et son jeton entre crochets pour en faire une seule unité grammaticale :

```yaml
name: my-app
pages:
  - name: Dashboard
    path: /dashboard
    components:
      - type: text
        element: h1
        content: 'Welcome[, $session.name]'
```

Un appelant connecté avec un nom d'affichage lit `Welcome, Alice Johnson` ; un appelant anonyme, ou connecté sans nom d'affichage, lit `Welcome`.

Un segment est tout ou rien : chaque jeton qu'il contient doit résoudre vers une valeur non vide, sinon le segment entier disparaît — crochets, littéraux et tout le reste. Une unité à moitié résolue est précisément la ponctuation en suspens que le segment existe pour éviter. Les segments ne s'imbriquent pas, et l'un d'eux ne peut pas en contenir un autre.

**Des crochets ne forment un segment que si un jeton de session vit à l'intérieur.** Une phrase comme `Status [draft]` ne porte aucun jeton de session : elle s'affiche verbatim, crochets compris — les crochets sont de la prose ordinaire, et un texte qui n'a jamais demandé cette grammaire n'est pas touché par elle. Un jeton **hors** de tout crochet est lui aussi inchangé : il résout, ou il devient la chaîne vide.

Le serveur retire chaque segment optionnel et l'hydratation le rajoute. Ce sens est délibéré : un titre qui se lit `Welcome` puis s'allonge est lisible à chaque instant, là où un titre qui arrive vide et se remplit est un décalage de mise en page sur la première chose qu'un lecteur regarde.

## Pages connexes

- [Liaison de données](/fr/docs/pages-data-binding) — la `dataSource` qui produit `$record`.
- [Présentation des pages](/fr/docs/pages-overview) — `vars` et le reste du tableau des propriétés de page.
- [Langues](/fr/docs/languages) — les clés `$t:` et la façon dont une page résout sa langue.
- [Mises en page, barres latérales et accès](/fr/docs/pages-layouts-access) — la garde `access` et sa réponse différente.
