# Formulaires pour les modèles Typst

Donnez un formulaire à vos propres fonctions Typst, pour que les personnes qui rédigent un rapport voient des champs avec libellé en mode Visuel plutôt que la syntaxe d'un appel de fonction.

Un modèle Typst fournit souvent ses propres fonctions : une page de couverture, un encadré d'information, un bloc de validation. Celui qui rédige le rapport les appelle, comme dans `#info-box(title: "Supply risk", tone: "risk")[...]`. Si vous maintenez le modèle, vous pouvez décrire une seule fois les arguments de chaque fonction. Le mode Visuel affiche alors chaque appel de cette fonction sous forme de formulaire : des champs avec libellé, une liste pour les choix fixes, un interrupteur pour oui ou non. Modifier un champ réécrit uniquement cet argument dans le fichier `.typ`, de sorte que le rapport reste un source Typst ordinaire qui compile de la même façon.

## Ce que voit le lecteur

Un appel sur ses propres lignes devient une **carte**. L'en-tête de la carte affiche le nom du formulaire et, si vous en choisissez un, un court résumé comme le titre de l'encadré. Chaque argument a une ligne avec son libellé et un contrôle.

Un appel à l'intérieur d'une phrase, comme `#badge("review")`, devient une **pastille** dans la ligne de texte. Cliquer sur la pastille ouvre les mêmes champs dans une petite fenêtre contextuelle.

Les champs de texte et de balisage s'enregistrent quand vous appuyez sur Enter (⌘ Enter ou Ctrl Enter dans un champ multiligne) ou quand vous quittez le champ. Esc remet l'ancienne valeur. Les listes et les interrupteurs s'enregistrent aussitôt. Chaque modification est une étape d'annulation.

Placer le curseur dans un appel affiche son source, comme n'importe quel autre élément du mode Visuel. **Modifier dans le source** sur la carte fait la même chose.

## Où déclarer les formulaires

Il y a deux endroits, avec le même format :

- **Dans un paquet.** Ajoutez une section `[tool.oleafly]` au `typst.toml` du paquet. Typst réserve les sections `[tool.*]` à d'autres outils, donc le paquet s'installe et compile toujours partout. Cela fonctionne pour les paquets `@local` et pour les paquets `@preview` de Typst Universe.
- **Dans le projet.** Pour les modèles gardés sous forme de fichiers `.typ` simples dans le projet, créez `oleafly-forms.toml` à la racine du projet. Chaque formulaire nomme aussi le fichier qui définit la fonction, avec `module`.

Un formulaire de paquet :

```toml
[tool.oleafly]
schema = 1

[[tool.oleafly.forms]]
function = "info-box"
label = "Info box"
summary = "title"

  [[tool.oleafly.forms.fields]]
  arg = "title"
  kind = "text"
  label = "Heading"
  placeholder = "Short heading"
  required = true

  [[tool.oleafly.forms.fields]]
  arg = "tone"
  kind = "choice"
  label = "Tone"
  default = "note"
  options = [{ value = "note", label = "Note" }, { value = "risk", label = "Risk" }, "neutral"]

  [[tool.oleafly.forms.fields]]
  arg = 0
  kind = "content"
  label = "Text"
```

Un formulaire de projet, dans `oleafly-forms.toml` :

```toml
[tool.oleafly]
schema = 1

[[tool.oleafly.forms]]
module = "template/memo.typ"
function = "memo-header"
label = "Memo header"
fields = [
  { arg = "to", kind = "text", label = "To" },
  { arg = "subject", kind = "text", label = "Subject" },
]
```

## Les clés

`schema = 1` est obligatoire. Un fichier qui n'en a pas, ou qui a un autre nombre, est ignoré.

Chaque entrée `[[tool.oleafly.forms]]` a :

| Clé | Obligatoire | Signification |
| --- | --- | --- |
| `function` | Oui | Le nom de la fonction, sous forme d'un seul identifiant Typst. Les traits d'union sont acceptés. |
| `module` | Dans `oleafly-forms.toml` seulement | Le fichier du projet qui définit la fonction, relatif à la racine du projet, avec `/` entre les dossiers. |
| `label` | Non | Le nom du formulaire sur les cartes et les pastilles. Par défaut, le nom de la fonction. |
| `summary` | Non | L'argument dont la valeur apparaît à côté du libellé, écrit comme le `arg` d'un champ. |
| `fields` | Oui | Un ou plusieurs champs. |

Chaque champ a :

| Clé | Obligatoire | Signification |
| --- | --- | --- |
| `arg` | Oui | Un nom pour un argument nommé (`"title"`), ou un nombre pour un argument positionnel (`0` est le premier). Un bloc `[...]` final compte comme un argument positionnel après ceux entre parenthèses. |
| `kind` | Oui | `text`, `content`, `choice`, `number` ou `toggle`. |
| `label` | Oui | Le libellé du champ. |
| `help` | Non | Une courte note sous le champ. |
| `placeholder` | Non | Texte gris dans un champ vide. |
| `required` | Non | `true` marque un champ vide comme manquant et masque son bouton **Effacer**. Oleafly n'ajoute jamais l'argument de lui-même. |
| `default` | Non | La valeur que votre fonction utilise quand l'argument est omis. Elle est affichée, jamais écrite. |

Les types et leurs clés supplémentaires :

- `text` écrit une chaîne Typst. Ajoutez `multiline = true` pour une zone plus grande.
- `content` modifie du balisage Typst et l'écrit sous forme de bloc `[...]`. Un argument de type chaîne reste une chaîne.
- `choice` a besoin de `options` : une liste de chaînes, ou des tables `{ value, label }` quand le libellé diffère de la valeur. Les valeurs sont écrites comme des chaînes.
- `number` accepte `integer`, `min`, `max` et `step`. Les nombres n'ont pas d'unités.
- `toggle` écrit `true` ou `false`.

## Quels appels reçoivent un formulaire

Oleafly suit les lignes `#import` et `#let` du rapport, au niveau supérieur du fichier :

- `#import "@local/acme-report:0.1.0" as acme` fait de `#acme.info-box(...)` un formulaire.
- `#import "@local/acme-report:0.1.0": info-box, status-badge as badge` fait de `#info-box(...)` et de `#badge(...)` des formulaires.
- `#import "@local/acme-report:0.1.0": *` donne un formulaire à chaque fonction pour laquelle le paquet en déclare un.
- `#import "template/memo.typ": memo-header` correspond à un formulaire de projet dont le `module` est `template/memo.typ`. Les chemins sont lus depuis le dossier du rapport, ou depuis la racine du projet quand ils commencent par `/`.

La version du paquet doit correspondre exactement. Un `#let` de même nom, plus loin dans le fichier, remplace le formulaire à partir de ce point. Les appels atteints via un autre fichier qui réimporte le paquet gardent leur texte source.

Une fonction nommée comme un élément Typst que le mode Visuel dessine déjà, comme `table` ou `figure`, garde l'apparence intégrée quand elle est appelée par son nom seul. `#acme.table(...)` ou un import renommé obtient quand même le formulaire.

## Champs affichés en lecture seule

Certains arguments ne peuvent pas être modifiés sans risque depuis un formulaire. Leur ligne affiche le source avec la raison, et **Modifier dans le source** y saute :

- **Calculé dans le source :** la valeur est une expression, comme `title: data.title`.
- **Écrit comme un autre type de valeur :** par exemple un nombre là où le formulaire attend du texte.
- **Ne fait pas partie des choix :** une valeur que vos `options` ne listent pas.
- **Défini par un argument étalé :** un appel avec `..args` transmet des valeurs que le formulaire ne voit pas, donc tous les champs sont en lecture seule.

Quand un champ ne peut pas être ajouté à l'endroit où il irait, par exemple un argument positionnel après un argument manquant, le formulaire le dit et propose **Ajouter dans le source**.

## Erreurs dans une définition

Ouvrez `oleafly-forms.toml`, ou le `typst.toml` d'un paquet intégré au projet, dans Oleafly, et chaque problème s'affiche comme un repère sur sa ligne : un type inconnu, un libellé manquant, un formulaire en double, un `module` hors du projet. Un formulaire cassé est laissé de côté et les autres continuent de fonctionner. Un fichier de plus de 256 Ko n'est pas lu.

## Partager des modèles

Oleafly lit les formulaires des paquets dans les mêmes dossiers que le compilateur. Un collaborateur qui n'a pas le paquet `@local` voit du source simple et aucune erreur. Pour partager les formulaires avec tous les membres d'un projet, ouvrez la boîte de dialogue **Paquets Typst**, activez **Utiliser les paquets du dossier du projet** et choisissez **Intégrer les paquets au projet**. Le paquet, et ses formulaires, voyagent alors dans le dossier `typst-packages` du projet (voir [Projets Typst](/docs/typst/)).
