# Anki-Kartenvorlagen, CSS und Medien wiederverwenden

Canonical page: https://ankiforge.dev/de/docs/templates/
Language: de
Description: Lade einen wiederverwendbaren Anki-Notiztyp aus einem Paket mit Kartenvorlagen, CSS und Medien – für normale oder Cloze-Karten mit Rust, Python oder Node.js.

Verwende dasselbe Anki-Kartendesign in mehreren Stapeln: Bewahre die Vorlagen, das CSS und die Medien eines Notiztyps in einem Verzeichnis auf und lade es für normale Karten oder Cloze-Karten. Die Beispiele verwenden Rust; Python und Node.js laden Pakete mit `NoteType.from_bundle` und `NoteType.fromBundle` (siehe [Python-API](https://ankiforge.dev/de/docs/python-api/#models-and-templates) und [Node-API](https://ankiforge.dev/de/docs/node-api/#immutable-models)).

Ein Vorlagenpaket umfasst eine wiederverwendbare Modelldeklaration, Vorlagentext, CSS und alle ausdrücklich deklarierten Medienabhängigkeiten. `NoteType::from_bundle(directory)` validiert das vollständige Paket und erstellt Snapshots mit eigenem Datenbesitz, bevor es denselben unveränderlichen `NoteType` zurückgibt, der auch bei der Definition im Code verwendet wird. Es verändert ein Projekt nicht teilweise.

## Das Paketbeispiel ausführen

```sh
cargo run --locked -p ankiforge --example docs_workflow -- target/docs-examples
```

Der Ablauf lädt das [Testpaket für einen eigenen Cloze-Typ](https://github.com/morehardy/anki-forge/blob/main/contracts/fixtures/template-bundle/custom-cloze/anki-template.yaml) und schreibt `target/docs-examples/template.apkg`. Seine Vorlage weist Karten dem Stapel **Languages::Cloze** zu. Eine Notiz erzeugt zwei Karten.

## Manifest und Vorlagenreferenzen

Die Manifestdatei heißt `anki-template.yaml`. Nur das neue Format wird akzeptiert:

```yaml
format_version: template-bundle-v2
note_type:
  key: language-cloze
  name: Language Cloze
  cloze_field: text
  fields:
    - key: text
      name: Sentence
      sort: true
      required: true
    - key: extra
      name: Extra
  templates:
    - key: cloze
      name: Cloze
      front_file: front.html
      back_file: back.html
      browser_front_file: browser-front.html
      target_deck: Languages::Cloze
css_file: style.css
```

`note_type.key`, Feldschlüssel und Vorlagenschlüssel sind erforderliche stabile Bezeichner. `name` ist optional und entspricht standardmäßig dem jeweiligen Schlüssel. `cloze_field` wählt ein Cloze-Modell; eine separate Typdeklaration ist nicht nötig. Ein Feld ohne `required: true` darf fehlen. Unbekannte Manifesteigenschaften werden zurückgewiesen.

Jede Vorlage verwendet **Feldschlüssel**, auch für Vorderseite, Rückseite und Kartenbrowser: `{{cloze:text}}`, `{{extra}}` und bedingte Abschnitte wie `{{#extra}}`. Anzeigenamen wie Sentence und Extra werden nach der Bindung für Anki erzeugt. Der Lader erhält ursprüngliche Dateipfade und Bytebereiche der Vorlagen in Fehlermeldungen.

## Ein Modell laden und wiederverwenden

```rust
fn bundle(output: &Path, template_directory: &Path) -> anyhow::Result<()> {
    let model = NoteType::from_bundle(template_directory)?;
    let mut project = Project::new("docs-languages")?;
    project.add(
        "capital",
        model
            .note()
            .field("text", "{{c1::Madrid}} is in {{c2::Spain}}.")
            .field("extra", "A city and its country."),
    )?;
    let built = project.build(BuildOptions::to(output.join("template.apkg")))?;
    verify(&built, 1, 2, 0)?;
    Ok(())
}
```

Für eine unabhängige Anwendung erwartet dieses vollständige Beispiel dasselbe Paket unter `fixtures/template-bundle`:

```rust
use ankiforge::{BuildOptions, NoteType, Project};

fn main() -> anyhow::Result<()> {
    let model = NoteType::from_bundle("fixtures/template-bundle")?;
    let mut project = Project::new("bundle-example")?;
    project.add("capital", model.note()
        .field("text", "{{c1::Madrid}} is in {{c2::Spain}}.")
        .field("extra", "A city and its country."))?;
    let output = project.build(BuildOptions::to("bundle-example.apkg"))?;
    assert_eq!(output.report().counts().cards, 2);
    Ok(())
}
```

Das zurückgegebene Modell ist vom Quellverzeichnis unabhängig. Du kannst es mit einem anderen Projekt teilen oder nach dem Entfernen dieses Verzeichnisses verwenden. Ein Ladefehler liefert kein unvollständiges Modell und räumt die nicht anderweitig gehaltenen Snapshots auf.

## Mediendateien und Budgets

Deklariere jede Datei, die direkt von Vorlagen, CSS oder Skripten verwendet wird, ausdrücklich. Jeder `assets`\-Eintrag verwendet einen zum Paket relativen Pfad und einen festen Exportnamen:

```yaml
assets:
  - path: assets/badge.png
    export_as: badge.png
  - path: assets/labels.woff
    export_as: labels.woff
```

Anschließend können Vorlagen `<img src="badge.png">` und CSS `url('labels.woff')` verwenden. Die Eigenschaft `css_file` gibt die CSS-Quelldatei an; Medien werden nicht aus beliebigem HTML, CSS oder JavaScript abgeleitet. Deklarierte Medien bleiben auch ohne erkannte statische Referenz im APKG. Exportnamen unterliegen denselben Regeln für portable Namen und Unicode-/Groß-/Kleinschreibungskonflikte wie [Media](https://ankiforge.dev/de/docs/media/). Der vollständige Exportname ist einschließlich Endung auf 255 UTF-8-Bytes begrenzt. Das JSON-Schema prüft Syntax und Zeichenanzahl; `NoteType::from_bundle` prüft zusätzlich Bytebudget, Dateiinhalte und Referenzen, bevor es ein validiertes Modell zurückgibt. Eine erfolgreiche Schemaprüfung allein garantiert kein erfolgreiches Laden.

Absolute Pfade, Pfadwechsel außerhalb des Pakets und symbolische Links auf Ziele außerhalb des Pakets werden zurückgewiesen. Das Manifest ist auf 256 KiB begrenzt; jede Vorlagen-/CSS-Textdatei auf 2 MiB und muss UTF-8 verwenden. Mediensnapshots verwenden das Standard-Medienbudget oder vom Aufrufer über `NoteType::from_bundle_with_limits` bereitgestellte `MediaLimits`. Sowohl vorab ermittelte Längen als auch tatsächlich gelesene Bytes werden geprüft.

Paketfehler erhalten Art und Code, Quellpfad, gegebenenfalls Byteposition und den zugrunde liegenden Schema-, E/A-, YAML-, UTF-8- oder Medienfehler. Der Modellabschluss validiert das Schema; das Hinzufügen von Notizen prüft separat Konflikte auf Projektebene. Siehe [Eigene Notiztypen](https://ankiforge.dev/de/docs/custom-notetypes/) und [Fehlersuche](https://ankiforge.dev/de/docs/troubleshooting/).
