# Formulare für Typst-Vorlagen

Geben Sie Ihren eigenen Typst-Funktionen ein Formular, damit Personen, die einen Bericht ausfüllen, im visuellen Modus beschriftete Felder statt der Syntax eines Funktionsaufrufs sehen.

Eine Typst-Vorlage bringt oft eigene Funktionen mit: eine Titelseite, eine Infobox, einen Freigabeblock. Wer den Bericht schreibt, ruft sie auf, etwa mit `#info-box(title: "Supply risk", tone: "risk")[...]`. Wenn Sie die Vorlage pflegen, können Sie die Argumente jeder Funktion einmal beschreiben. Der visuelle Modus zeigt dann jeden Aufruf dieser Funktion als Formular: beschriftete Felder, eine Liste für feste Auswahlmöglichkeiten, einen Schalter für Ja oder Nein. Das Bearbeiten eines Feldes schreibt nur dieses eine Argument in der `.typ`-Datei um, sodass der Bericht gewöhnlicher Typst-Quelltext bleibt, der auf dieselbe Weise kompiliert.

## Was die Leserin oder der Leser sieht

Ein Aufruf auf eigenen Zeilen wird zu einer **Karte**. Die Kopfzeile der Karte zeigt den Namen des Formulars und, wenn Sie eine wählen, eine kurze Zusammenfassung, etwa den Titel der Box. Jedes Argument bekommt eine Zeile mit seiner Beschriftung und einem Bedienelement.

Ein Aufruf innerhalb eines Satzes, etwa `#badge("review")`, wird zu einem **Chip** in der Textzeile. Ein Klick auf den Chip öffnet dieselben Felder in einem kleinen Popover.

Textfelder und Auszeichnungsfelder speichern, wenn Sie Enter drücken (⌘ Enter oder Ctrl Enter in einem mehrzeiligen Feld) oder das Feld verlassen. Esc stellt den alten Wert wieder her. Listen und Schalter speichern sofort. Jede Änderung ist ein Rückgängig-Schritt.

Setzen Sie den Cursor in einen Aufruf, erscheint sein Quelltext, wie bei jedem anderen Element des visuellen Modus. **Im Quelltext bearbeiten** auf der Karte bewirkt dasselbe.

## Wo Formulare deklariert werden

Es gibt zwei Orte, mit demselben Format:

- **In einem Paket.** Fügen Sie der `typst.toml` des Pakets einen Abschnitt `[tool.oleafly]` hinzu. Typst hält die Abschnitte `[tool.*]` für andere Werkzeuge frei, sodass das Paket weiterhin überall installiert und kompiliert. Das funktioniert für `@local`-Pakete und für `@preview`-Pakete aus Typst Universe.
- **Im Projekt.** Für Vorlagen, die als gewöhnliche `.typ`-Dateien im Projekt liegen, legen Sie `oleafly-forms.toml` im Projektstamm an. Jedes Formular nennt zusätzlich mit `module` die Datei, die die Funktion definiert.

Ein Paketformular:

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

Ein Projektformular in `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" },
]
```

## Die Schlüssel

`schema = 1` ist erforderlich. Eine Datei ohne diese Angabe oder mit einer anderen Zahl wird ignoriert.

Jeder Eintrag `[[tool.oleafly.forms]]` hat:

| Schlüssel | Erforderlich | Bedeutung |
| --- | --- | --- |
| `function` | Ja | Der Name der Funktion als ein Typst-Bezeichner. Bindestriche sind erlaubt. |
| `module` | Nur in `oleafly-forms.toml` | Die Projektdatei, die die Funktion definiert, relativ zum Projektstamm, mit `/` zwischen den Ordnern. |
| `label` | Nein | Der Name des Formulars auf Karten und Chips. Voreinstellung ist der Name der Funktion. |
| `summary` | Nein | Das Argument, dessen Wert neben der Beschriftung erscheint, geschrieben wie das `arg` eines Feldes. |
| `fields` | Ja | Ein oder mehrere Felder. |

Jedes Feld hat:

| Schlüssel | Erforderlich | Bedeutung |
| --- | --- | --- |
| `arg` | Ja | Ein Name für ein benanntes Argument (`"title"`) oder eine Zahl für ein Positionsargument (`0` ist das erste). Ein nachgestellter `[...]`-Block zählt als Positionsargument nach denen in den Klammern. |
| `kind` | Ja | `text`, `content`, `choice`, `number` oder `toggle`. |
| `label` | Ja | Die Beschriftung des Feldes. |
| `help` | Nein | Ein kurzer Hinweis unter dem Feld. |
| `placeholder` | Nein | Grauer Text in einem leeren Feld. |
| `required` | Nein | `true` markiert ein leeres Feld als fehlend und blendet seine Schaltfläche **Leeren** aus. Oleafly fügt das Argument nie von selbst hinzu. |
| `default` | Nein | Der Wert, den Ihre Funktion verwendet, wenn das Argument fehlt. Er wird angezeigt, aber nie geschrieben. |

Arten und ihre zusätzlichen Schlüssel:

- `text` schreibt einen Typst-String. Fügen Sie `multiline = true` für ein größeres Feld hinzu.
- `content` bearbeitet Typst-Auszeichnung und schreibt sie als `[...]`-Block. Ein String-Argument bleibt ein String.
- `choice` braucht `options`: eine Liste von Strings oder `{ value, label }`-Tabellen, wenn die Beschriftung vom Wert abweicht. Werte werden als Strings geschrieben.
- `number` akzeptiert `integer`, `min`, `max` und `step`. Zahlen haben keine Einheiten.
- `toggle` schreibt `true` oder `false`.

## Welche Aufrufe ein Formular bekommen

Oleafly folgt den eigenen Zeilen `#import` und `#let` des Berichts auf oberster Ebene der Datei:

- `#import "@local/acme-report:0.1.0" as acme` macht `#acme.info-box(...)` zu einem Formular.
- `#import "@local/acme-report:0.1.0": info-box, status-badge as badge` macht `#info-box(...)` und `#badge(...)` zu Formularen.
- `#import "@local/acme-report:0.1.0": *` macht für jede Funktion, die das Paket deklariert, ein Formular.
- `#import "template/memo.typ": memo-header` passt zu einem Projektformular, dessen `module` `template/memo.typ` ist. Pfade werden vom Ordner des Berichts aus gelesen oder vom Projektstamm, wenn sie mit `/` beginnen.

Die Paketversion muss genau übereinstimmen. Ein `#let` mit demselben Namen weiter unten in der Datei ersetzt das Formular ab dieser Stelle. Aufrufe, die über eine andere Datei erreicht werden, die das Paket erneut importiert, behalten ihren Quelltext.

Eine Funktion, die wie ein Typst-Element heißt, das der visuelle Modus bereits zeichnet, etwa `table` oder `figure`, behält bei Aufruf unter ihrem bloßen Namen die eingebaute Darstellung. `#acme.table(...)` oder ein umbenannter Import bekommt weiterhin das Formular.

## Schreibgeschützt angezeigte Felder

Manche Argumente lassen sich nicht sicher über ein Formular bearbeiten. Ihre Zeile zeigt den Quelltext mit dem Grund, und **Im Quelltext bearbeiten** springt dorthin:

- **Im Quelltext berechnet:** Der Wert ist ein Ausdruck, etwa `title: data.title`.
- **Als anderer Werttyp geschrieben:** zum Beispiel eine Zahl, wo das Formular Text erwartet.
- **Nicht in der Auswahl:** ein Wert, den Ihre `options` nicht auflisten.
- **Durch ein Spread-Argument gesetzt:** Ein Aufruf mit `..args` übergibt Werte, die das Formular nicht sehen kann, daher ist jedes Feld schreibgeschützt.

Lässt sich ein Feld dort, wo es stehen würde, nicht hinzufügen, etwa ein Positionsargument nach einem fehlenden, sagt das Formular das und bietet **Im Quelltext hinzufügen** an.

## Fehler in einer Definition

Öffnen Sie `oleafly-forms.toml` oder die `typst.toml` eines ins Projekt kopierten Pakets in Oleafly, und jedes Problem erscheint als Markierung in seiner Zeile: eine unbekannte Art, eine fehlende Beschriftung, ein doppeltes Formular, ein `module` außerhalb des Projekts. Ein fehlerhaftes Formular wird weggelassen, und die anderen funktionieren weiter. Eine Datei, die größer als 256 KB ist, wird nicht gelesen.

## Vorlagen teilen

Oleafly liest Paketformulare aus denselben Ordnern, die der Compiler verwendet. Wer mitarbeitet und das `@local`-Paket nicht hat, sieht schlichten Quelltext und keine Fehler. Um Formulare mit allen im Projekt zu teilen, öffnen Sie den Dialog **Typst-Pakete**, schalten **Pakete aus dem Projektordner verwenden** ein und wählen **Pakete ins Projekt kopieren**. Das Paket und seine Formulare reisen dann im Ordner `typst-packages` des Projekts mit (siehe [Typst-Projekte](/docs/typst/)).
