Zum Inhalt springen
Navigation
Erzählung

Verstehen

Sechs Abschnitte darüber, warum die Sprache so gebaut ist — und was die Entscheidungen kosten.

01Was Stencil istEine Vorlage, die man bedienen kann, statt sie zu bearbeiten.

Eine Marke braucht dasselbe Motiv hundertmal: anderer Text, anderes Bild, andere Farbe, gleiche Handschrift. Der übliche Weg dafür ist ein Design-Werkzeug, in dem jemand eine Datei dupliziert und Kästen verschiebt. Das Ergebnis ist jedes Mal ein neues Original — und nach dreißig Kopien weiß niemand mehr, welches das richtige war.

Ein Stencil dreht das um. Die Vorlage ist Daten: ein Baum aus Element-Knoten, Text-Bindungen, Verzweigungen, Schleifen und Aufrufen registrierter Bausteine. Was daran variabel sein soll, ist ausdrücklich benannt — als Regler. Wer den Post macht, dreht an Reglern; die Vorlage bleibt eine.

Der Interpreter heißt die Press. Sie bekommt drei Dinge — den Baum, den Zustand der Regler und den Kontext (Format, Maße, Marke, Zeit) — und gibt Ebenen aus fertigem Markup zurück. Sie tut das an jeder Stelle gleich: im Editor, in der Render-App, im PNG-Export, im MCP-Aufruf eines Agenten.

Ein Beispiel, das es wirklich gibt. Der erste Konsument der Sprache ist der Static-Post-Baukasten im trybe Studio. Dort liegen heute 57 Vorlagen als Stencil — keine davon ist noch Code. Ein zweiter Konsument (E-Mail) hätte andere Primitives und andere Ebenen, aber dieselbe Grammatik: Die Sprache kennt weder Marke noch Optik.

02Warum geschlossen — und warum ohne ParserDer Quelltext IST der Baum.

Die meisten Template-Sprachen sind Text: {{ user.name | upper }}. Damit beginnt jede Ausführung mit einer Übersetzungsstufe — jemand muss den Text lesen, zerlegen und zu einem Baum machen. Genau dort sitzen die klassischen Fehlerklassen: Fehler mit Zeile und Spalte, Escaping-Regeln, Sonderzeichen, und im schlimmsten Fall ein Ausdruck, der beim Auswerten mehr darf als er sollte.

Ein Stencil überspringt diese Stufe. Es ist schon der Baum:

{ "$": "text", "value": { "$": "state", "path": "slots.head" } }
Der Diskriminator $ sagt, was für ein Ding das ist. Mehr Syntax gibt es nicht.

Der Preis dafür ist ehrlich zu nennen: Ein Stencil ist unhandlich zu tippen. Niemand schreibt so eine Vorlage von Hand gern — und genau deshalb gibt es den Spielplatz, den Compiler aus HTML und die Skill, die aus einer gestalteten Vorlage einen Baum macht. Der Gewinn steht auf der anderen Seite: Es gibt keine Syntaxfehler, weil es keine Syntax gibt. Was JSON ist, ist form-korrekt; ob es gültig ist, beantwortet ein Validator mit dem exakten Pfad zur Stelle.

Geschlossen heißt: Es gibt keinen Ausführungspfad. Kein eval, keine freien Ausdrücke, kein rohes HTML aus dem Zustand. Gerechnet wird ausschließlich mit benannten Helfern aus einer Registry (45 Stück, jeder mit eigener Seite), Markup entsteht nur aus Element-Knoten und registrierten Bausteinen. Was nicht in der Registry steht, existiert nicht — es rendert nichts und fällt an der Schreibkante auf.

Das ist eine Sicherheitsaussage, keine Stilfrage. Eine fremde Marke darf eigene Vorlagen mitbringen, und unser Editor führt sie aus. Wäre die Sprache offen, wäre jede Fork-Vorlage ein Skript im Browser fremder Leute. Weil sie geschlossen ist, ist die Handler-Injektion nicht etwa gefiltert, sondern nicht deklarierbar: Ein Attribut, dessen Name mit on beginnt, kommt in der Grammatik nicht vor.

03Die drei Zusicherungen — und was sie kostenSie terminiert. Sie wirft nie. Sie ist deterministisch.

Sie terminiert immer

Es gibt keine allgemeine Rekursion und keine Schleife mit Bedingung. each läuft über eine endliche Liste aus dem Zustand; die einzige Erzeugung einer Liste ohne Vorlage (range) ist gedeckelt; die Einbettung eines Stencils in ein anderes ist auf 8 Glieder begrenzt und schneidet Zyklen an der Kette; die Verschachtelung endet bei 40. Ein Fork-Stencil kann den Editor also nicht anhalten — nicht, weil wir einen Timeout haben, sondern weil die Sprache das Konstrukt nicht kennt.

Kosten: Rekursive Strukturen — ein Baum unbekannter Tiefe, eine verschachtelte Gliederung — lassen sich nicht ausdrücken. Wer sie braucht, braucht eine andere Sprache.

Sie wirft nie

Ein unbekannter Knoten, ein unbekannter Helfer, ein kaputter Pfad, eine Zahl jenseits jeder Vernunft: Die Press rendert an dieser Stelle nichts und macht weiter. Das ist bewusst asymmetrisch zum Gate: Der Validator ist streng und benennt jeden Befund mit Pfad, die Press ist defensiv. Ein kaputtes Dokument darf keinen Editor abschießen.

Kosten: Stille. Ein Tippfehler in einem Argument gibt kein Signal, sondern ein leeres Stück Bild. Genau dagegen sind die Deklarationen gewachsen, die in der Referenz stehen — geschlossene Wertemengen an Argumenten, Inhalts-Deklarationen an Primitives: Jede von ihnen macht aus einem stummen Ausgang einen lauten Befund an der Schreibkante. Das ist eine bezahlte Lehre, keine Vorsichtsmaßnahme.

Sie ist deterministisch

Gleicher Baum, gleicher Zustand, gleicher Kontext ⇒ dasselbe Byte. Keine Zufallszahl, keine Uhr (die Zeit ist eine Kontext-Größe, kein Zugriff), keine Iterationsreihenfolge, die vom Zufall abhängt. Deshalb kann eine Testreihe aus eingefrorenen Ausgaben („Goldens") überhaupt ein Schiedsrichter sein: Was sich bewegt, hat jemand bewegt.

Kosten: Jede Verhaltensänderung ist eine Versions-Entscheidung. Die Press trägt deshalb eine Kennung (s1.p22.899c6d64), die aus der Grammatik, der Flächen-Deklaration und einer handgepflegten Revision entsteht. Zwei Prozesse mit verschiedenen Kennungen dürfen dasselbe Dokument nicht rendern — sonst sähen Vorschau und Export leise unterschiedlich aus.

04Der Regler ist der eigentliche GegenstandEine Vorlage ohne Regler ist ein Bild.

Das Layout ist der sichtbare Teil und der einfachere. Der Engpass sind die Regler: Sie entscheiden, was eine Vorlage kann. Der Inspector zeichnet sie, der Überlauf-Hinweis sitzt an ihnen, die Herkunfts-Spur bildet jeden Knoten auf sie zurück, und ein Agent bedient die Vorlage ausschließlich über sie.

Ein Regler entsteht, indem ein Literal im Baum durch einen Verweis ersetzt wird:

"Sommer-Sale"          ⇒   { "$": "state", "path": "slots.head" }
"104"  (font-size)     ⇒   { "$": "state", "path": "kopfGroesse" }, unit: "px"
Der Wert verschwindet nicht — er zieht in den Zustand um und wird dort zur Vorgabe.

Die Mechanik daran ist trivial und lässt sich automatisieren. Die Entscheidung ist es nicht: Welcher Text soll einstellbar sein, wie heißt er, in welche Gruppe gehört er, welche Grenzen sind sinnvoll? Das kann kein Compiler ableiten, weil es keine Eigenschaft des HTML ist, sondern eine Aussage über die Absicht. Deshalb macht der Spielplatz alles außer diesem einen Schritt — und für diesen einen klickt ein Mensch.

05Was die Sprache nicht kannDie interessanteren Grenzen sind die gewollten.

  • Nicht responsiv. Ein Stencil sitzt auf einer Fläche, deren Maße feststehen. Es gibt keine Breakpoints, keine Medienabfragen, keinen Fluss. Der anchor-Knoten sieht danach aus, ist es aber nicht: Er löst gegen die bekannte Größe auf und schreibt eine gerechnete Zahl ins Markup. Für ein zweites Format schreibt man kein zweites Layout — man verankert anders.
  • Nicht Turing-vollständig, und das ist der Preis der ersten Zusicherung. Keine Rekursion, keine bedingte Schleife, keine Variablen, die man setzt. Wer rechnen will, ruft einen der benannten Helfer.
  • Kein Fließtext über Seiten. Ein Stencil weiß nicht, was passiert, wenn der Text nicht passt — es gibt keinen Umbruch auf die nächste Seite, keine Spalten, die sich füllen. Für fließende Dokumente (Artikel, Guides, PDFs mit unbekannter Länge) haben wir eine zweite Sprache; die Grenze ist bewusst gezogen und nicht bedauerlich. Was Stencil stattdessen tut: Es schätzt vor dem Rendern, ob der Text passt, und sagt es am Regler.
  • Keine eigenen Bausteine im Dokument. Was ein Primitive zeichnet, ist Code des Konsumenten. Ein Stencil kann Bausteine benutzen und andere Stencils einbetten — aber es kann keinen neuen Baustein definieren. Optik-Bausteine gehören dem Design-System, nicht dem einzelnen Dokument.
  • Kein Zugriff nach außen. Keine Netzaufrufe, kein Dateisystem, keine Uhr. Was von außen kommt, stellt der Kontext — und der wird gereicht, nicht geholt.

06Wie diese Seite gebaut istWeil die Antwort Teil der Aussage ist.

Die Referenz ist nicht geschrieben. Sie entsteht beim Bauen dieser Seite aus dem laufenden Sprach-Kern: die Knoten- und Wert-Felder aus dem JSON-Schema, die Helfer und Primitives samt Beschreibung und Argumenten aus der Registry, Vokabulare und Grenzwerte aus der Grammatik — demselben Objekt, das im Manifest zur serverseitigen Validierung reist. Auch die ROUTEN sind erzeugt: Ein neuer Helfer bekommt eine Seite, ohne dass jemand eine Zeile in dieser App schreibt.

Von Hand steht hier die Erzählung — diese sechs Abschnitte, die Sätze unter den Knotenarten, die getippten Beispiele (sie sind an jedem Eintrag als solche ausgewiesen) und die Beschriftung einer Grenzwert-Zeile. Das ist die Trennung, um die es geht: Prosa über Daten lügt irgendwann. Also darf Prosa nur das behaupten, was ein Mensch verantwortet, und alles Zählbare kommt aus der Quelle.

Der Spielplatz rendert mit renderPage() aus @trybe/static-post-templates — derselben Funktion wie Editor, Render-App und Export — und prüft mit validateDefinition(), derselben Prüfung wie die Schreibkante des Backends. Er ist kein Nachbau; es gibt in dieser App keinen zweiten Interpreter. Dieselbe Press rechnet auch die Ausgabe jedes Beispiels in der Referenz aus.

Die Gegenprobe, die diese Behauptung wert ist. Einen Helfer in packages/stencil/src/pure-helpers.ts ergänzen, die Seite neu bauen — und es gibt eine Route mehr, mit seiner Seite darauf. Wer das nicht nachstellt, glaubt einer Prosa-Aussage über Daten. Genau davon handelt der Abschnitt; im Gate der Seite steht diese Gegenprobe als Test (der „Zahn").