Spintax-Syntaxreferenz

Vollständige Referenz für Spintax-Vorlagen-Markup.

Enumerationen { }

Wählt zufällig eine Option aus der Liste.

{option1|option2|option3}

Beispiele

{blue|grey|clear}
{|free|paid} plan                 ← empty option = sometimes nothing
{Acme {Pro|Lite}}                ← nested enumerations
{order {|#42-A} confirmed}       ← nesting with empty option

Regeln

  • Begrenzer: { und }
  • Trennzeichen: |
  • Unterstützt Verschachtelung in beliebiger Tiefe
  • Leere Optionen sind gültig (erzeugen leere Zeichenkette)
  • Auflösung erfolgt vom innersten Ausdruck nach außen

Permutationen [ ]

Wählt N Elemente, mischt sie und verbindet sie mit Trennzeichen.

Einfache Permutationen

Alle Elemente einbezogen, durch Leerzeichen getrennt:

[1|2|3|4]

Ausgabebeispiele: 1 4 3 2, 2 3 4 1, 3 2 4 1

Mit Trennzeichen

Einheitliches Trennzeichen angegeben in < > am Anfang:

[<, > 1|2|3|4]

Ausgabebeispiele: 2, 1, 4, 3 · 4, 3, 2, 1

Wichtig: Kein Leerzeichen zwischen [ und <Trennzeichen>.

Trennzeichen pro Element

Jede Option kann ein eigenes Trennzeichen haben, definiert mit <sep> vor dem vorhergehenden |. Das Trennzeichen wandert beim Mischen mit seinem Element mit.

[<, > 1|2|3 < and >|4]

Ausgabebeispiele: 1, 3, 2 and 4 · 3, 1, 2 and 4

Auto-Abstände: Wort-Trennzeichen wie <and> oder <or> werden automatisch mit Leerzeichen ergänzt: <and> wird zu  and . Satzzeichen-Trennzeichen (<,>) werden nicht ergänzt. Zwei Ausnahmen: Ein Trennzeichen nur aus Han-, Hiragana-, Katakana-, Thai-, Lao-, Khmer- oder Myanmar-Schrift wird ohne Leerzeichen angefügt (<和> ergibt a和b), und unter der Locale ar werden die Konjunktionen و und ف an das folgende arabische Wort angehängt (الكازينو والبث), ebenso ו unter he.

Permutationen mit Kombinationen

Konfigurierbare minimale/maximale Elementanzahl und Trennzeichen:

[<minsize=1;maxsize=3;sep=", ";lastsep=" and "> apple|plum|orange|apricot]

Ausgabebeispiele: apple, plum and orange · apple and apricot · orange

Konfigurationsparameter

ParameterStandardBeschreibung
minsizeAnzahl allerMinimale Anzahl zu wählender Elemente
maxsizeAnzahl allerMaximale Anzahl zu wählender Elemente
sep" " (Leerzeichen)Trennzeichen zwischen nicht-letzten Elementen
lastsepwie sepTrennzeichen vor dem letzten Element

Permutationsregeln

  • Begrenzer: [ und ]
  • Konfigurationsblock <...> muss unmittelbar nach [ folgen
  • Konfigurationsparameter werden durch Semikolon getrennt
  • Zeichenkettenwerte in der Konfiguration stehen in Anführungszeichen: sep=", "
  • Enumerationen und Permutationen können innerhalb von Optionen verschachtelt werden
  • HTML-Elemente können Optionen sein
  • sep verbindet alles vor dem letzten Paar, lastsep das Paar selbst: bei zwei ausgewählten Elementen erscheint nur lastsep, bei einem keines von beiden

Variablen %var%

Definiert eine wiederverwendbare Variable, die überall dort eingesetzt wird, wo sie auftaucht. Zwei Direktiven deklarieren eine, und die Wahl ist nicht kosmetisch: #set ist ein Makro — sein Wert wird bei jeder Referenz erneut eingesetzt, enthaltenes Spintax also neu ausgewürfelt; #def würfelt den Wert einmal pro Rendering und gibt dieses eine Ergebnis an jede Referenz. (Ein Rendering ist eine Ausgabe; derselbe Seed reproduziert sie.) Solange der Wert reiner Text ist, sind beide identisch; der Unterschied zeigt sich in dem Moment, in dem der Wert eine Auswahl enthält.

#set %VARIABLE_NAME% = value or spintax structure

#def %VARIABLE_NAME% = value or spintax structure

Beispiele

#set %name% = John
#set %greeting% = {Hello|Hi|Hey}
#set %items% = [<minsize=2;maxsize=3;sep=", ";lastsep=" and "> apples|oranges|bananas]
Some text with %name% and %greeting%, also %items%.
And once more, %greeting% — a second reference.

/# %greeting% above may differ between the two references — #set re-rolls.
   #def picks once and keeps it: #/
#def %tone% = {friendly|warm|upbeat}
A %tone% intro, and a %tone% outro — always the same word.

Variablenregeln

  • #set und #def müssen am Zeilenanfang stehen
  • Variablennamen stehen zwischen %: %name%
  • Namen bestehen aus Buchstaben, Ziffern und Unterstrich, und Referenzen sind case-insensitiv: %Tone% und %tone% sind eine Variable
  • Werte dürfen beliebige Spintax-Syntax enthalten (Aufzählungen, Permutationen, andere Variablen)
  • #set ist ein Makro: es wird bei der Referenz expandiert, nicht bei der Definition, und sein Wert — samt enthaltenem Spintax — wird bei jeder Referenz erneut eingesetzt und neu ausgewürfelt
  • #def löst seinen Wert einmal pro Rendering auf und behält dieses Ergebnis überall. Genau das hält Wiederholungen kongruent: ein Substantiv und die daraus gebildeten Formen, eine Zahl für einen {plural}-Block, jede Phrase, deren Wiederholungen Wort für Wort übereinstimmen müssen
  • #def macht eine Variable mit sich selbst konsistent; es korreliert nicht zwei Variablen. #def %Noun% und #def %NounGen% sind zwei unabhängige Würfe und können auf verschiedene Wörter fallen — Formen, die übereinstimmen müssen, müssen aus einem Wurf stammen: ein #def-Stamm, auf den jede Form verweist, oder Synonyme, die gleich flektieren, mit der Endung außerhalb der Definition
  • Ein Name wird einmal definiert. Eine zweite Definition desselben Namens wird als definition.duplicate-name gemeldet, das Rendering läuft trotzdem weiter: zwischen zwei gleichen Direktiven gewinnt die spätere, und teilen sich #set und #def einen Namen, gewinnt #def — gleich welche zuerst kam
  • Eine Referenz ohne Definition gibt sich selbst aus: %missing% bleibt in der Ausgabe stehen, statt zu verschwinden
  • Keine der beiden Direktiven überquert ein #include: das eingebundene Template sieht die lokalen Variablen des Elterntemplates nicht, und seine eigenen dringen nicht nach oben. Eine ausgewürfelte Form erreicht das Kind nur als Laufzeitvariable
  • #set- und #def-Zeilen werden aus der Ausgabe entfernt
  • Vertiefung: siehe den Variablen-Leitfaden (Gültigkeitsbereiche und die Reroll-Falle) und die grammatiksichere Synonymisierung (Kasusfamilien)

Gültigkeitsbereiche von Variablen

Ein Host kann Variablen aus mehreren Quellen liefern. Existiert derselbe Name in mehreren, gewinnt die stärkste:

  1. Laufzeitvariablen (am stärksten) — das, was der Host an den Render-Aufruf übergibt: context in @spintax/core, Shortcode-Attribute im WordPress-Plugin: [spintax slug="greeting" name="Alice"]
  2. Lokale Variablen — mit #set oder #def im Template definiert
  3. Globale Variablen (am schwächsten) — hostweite Vorgaben, etwa die Einstellungsseite des Plugins

Bedingungen {?VAR?then|else}

Bedingungen sind eine eigene Konstruktion der Sprache — im GTW-Prototyp gab es nichts Vergleichbares. Während {a|b} eine gleichverteilte Zufallsauswahl ohne Bezug zu Variablen ist, wählt {?VAR?then|else} danach aus, ob %VAR% einen Wert hat.

Nutzen Sie es für wertgesteuerte Entscheidungen: eine Free-Tier-Zeile nur anzeigen, wenn ein Free-Tier existiert, einen Pro-Features-Block nur rendern, wenn der Nutzer auf einem kostenpflichtigen Plan ist, einen CTA verbergen, der nicht zutrifft.

Der Pre-Pass läuft vor der %var%-Expansion und vor dem zufälligen Zweig-Picker, sodass ein falsy-Zweig vollständig verworfen wird — nichts darin wird ausgewertet.

Formen

{?VAR?then}                ← truthy ⇒ then; falsy ⇒ empty
{?VAR?then|else}           ← truthy ⇒ then; falsy ⇒ else
{?!VAR?then|else}          ← inverted
{?HasFreeTier? — free tier available since %founded%|, trusted since %founded%}

Truthy und falsy

Die Regel ist bewusst einfacher als in JavaScript — truthy = mindestens ein Nicht-Leerraum-Zeichen:

Wert von %VAR%Truthy?
nicht deklariertfalsy
leerer Stringfalsy
nur Leerraumfalsy
"0", "false"truthy (nicht leer)
jeder andere Text oder HTMLtruthy

Bedingungs-Regeln

  • Variablennamen folgen derselben Regex wie %var% (unabhängig von Groß-/Kleinschreibung)
  • Das !-Präfix invertiert die Prüfung: {?!VAR?fehlt}
  • Das erste | auf Tiefe 0 trennt then von else; weitere bleiben literal im else-Zweig
  • Verschachtelte Bedingungen werden außen-zuerst ausgewertet — falsy-Zweige kurzschließen
  • Zusammengesetzte Logik (&&, ||, Vergleiche) wird nicht unterstützt — berechnen Sie eine Wächter-Variable im Assembler
  • Fehlerhafte Formen ({??yes}, {?VAR}) werfen niemals — das Playground markiert sie als Warnungen
  • Vertiefung: siehe den Conditional-Spintax-Leitfaden mit Beispielen und Anti-Pattern

Plurale {plural %n%: Sprache|Sprachen}

Wählt die grammatisch korrekte Wortform zu einer Zahl. Der Zähler steht vor dem Doppelpunkt, die Formen dahinter, getrennt durch |.

Die Form bestimmt die Render-Locale, nicht die Vorlage — wie viele Formen du liefern musst, hängt also von dieser Locale ab. Englisch braucht zwei, Russisch drei.

{plural %n%: form1|form2}          ← 2-form locale (en, de, es…)

{plural %n%: form1|form2|form3}    ← 3-form locale (ru, uk, sr…)

{plural %n%: zero|one|two|few|many|other}  ← 6-form locale (ar)
#def %LangCount% = 5
supports %LangCount% {plural %LangCount%: language|languages}
← supports 5 languages

Formen je Locale

Die Locale wird über ihr Sprach-Subtag abgeglichen, ru-RU und ru verhalten sich also gleich:

LocaleFormenAuswahl nach
ru, uk, be, sr, hr, bs31 · 2–4 · ab 5
ar60 · 1 · 2 · letzte zwei Ziffern 3–10 · letzte zwei Ziffern 11–99 · alles andere (100–102, 200–202…)
alle anderen, inkl. en2genau 1 · alles andere

Stimmt die Anzahl der Formen nicht, meldet die Engine plural.arity und lässt den Block mit Vollbreiten-Klammern sichtbar — ein falscher Plural geht nie stillschweigend live.

Plural-Regeln

  • Die Öffnung ist wörtlich, inklusive Leerzeichen: {plural . {plural: x} und {pluralN: x} sind keine Plural-Blöcke
  • Der Doppelpunkt ist Pflicht — er trennt Zähler und Formen
  • Der Zähler ist eine %Var%-Referenz oder eine ganzzahlige Konstante; Variablen im Zähler werden vor der Formwahl ersetzt
  • Negative Zahlen zählen im Betrag; 0 bekommt die Form „alles andere" (unter ar die erste, eigene)
  • Eine Zählervariable muss #def sein, nicht #set — #set ist ein Makro, ein Wert wie {1|4|9} ist bei der Formwahl also noch unaufgelöstes Spintax und der Block rendert leer. Das Playground meldet das als plural.count-macro
  • Ein nicht-numerischer oder undefinierter Zähler löscht den Block, statt zu raten
  • Vertiefung: siehe den Plural-Spintax-Leitfaden mit den russischen Dreiform-Regeln und ausgearbeiteten Beispielen

Includes #include

Bettet ein anderes Template an der Position der Direktive ein. #include ist die einzige Konstruktion, die die Engine nicht allein bedienen kann: sie hält keinen Template-Speicher, also liefert der Host einen Resolver, der eine Referenz in Template-Text verwandelt. Wo kein Resolver installiert ist — im Playground und im MCP-Server dieser Website, beides bewusst — ist die Direktive wirkungslos und bleibt als literaler Text in der Ausgabe.

#include "hero-text"

/# wrong: text before the directive on the same line leaves it literal #/
Intro: #include "hero-text"

Include-Regeln

  • Die Direktive muss die ganze Zeile einnehmen. Einrückung ist in Ordnung, Text nach der Referenz nicht — Text #include "hero" bleibt literal
  • Die Referenz steht in doppelten Anführungszeichen; mit einfachen oder ohne Anführungszeichen ist es keine Direktive mehr
  • Die Auflösung gehört dem Host: das WordPress-Plugin löst über Template-Slug oder numerische ID auf, ein JavaScript-Host übergibt einen includeResolver
  • Ohne Resolver bleibt die Zeile literal in der Ausgabe; kennt der Resolver das Template nicht, wird die Zeile stattdessen entfernt — ein unbekanntes Ziel kostet den Block lautlos
  • Eingebundene Templates können eigene Variablen und Spintax enthalten, und eigene #include
  • Includes werden aufgelöst, nachdem Aufzählungen und Permutationen des Elterntemplates gewürfelt wurden: ein Include im gewonnenen Zweig wird eingebettet — eines in einem verworfenen Zweig findet nie statt
  • Ketten funktionieren (ein Template bindet eines ein, das ein weiteres einbindet); ein Template, das sich selbst einbindet — direkt oder über einen Zyklus — wird bei der ersten Wiederholung abgeschnitten, ohne Fehler und ohne Diagnose
  • Kind-Templates erben globale und Laufzeitvariablen, aber nicht die lokalen #set / #def des Elterntemplates, und ihre eigenen dringen nicht nach oben
  • Ein Include kann nicht der Wert einer Definition sein: #def %x% = #include "y" wird als def.include-in-value abgelehnt
  • Vor dem Rendern meldet validate() ein unbekanntes Ziel nur, wenn der Host die Liste bekannter Referenzen übergibt; extract() liefert die Referenzen, die ein Template braucht — so lädt ein Host sie vorab
  • Vertiefung: siehe den Leitfaden zur Template-Komposition mit dem Assembler-Muster, das die meisten Pipelines stattdessen verwenden

Kommentare /#...#/

Text zwischen Kommentarmarkierungen wird vor jeder anderen Verarbeitung aus der Ausgabe entfernt.

/#
  This is a comment section.
  It can span multiple lines.
  It won't appear in output.
#/

Kommentarregeln

  • Start-Begrenzer: /#
  • End-Begrenzer: #/
  • Können sich über mehrere Zeilen erstrecken
  • Können nicht verschachtelt werden
  • Werden vor jeder anderen Verarbeitung entfernt
  • Das Gegenstück ist der Verbatim-Block /!...!/: Er behält seinen Text, statt ihn zu verwerfen

Verbatim-Block /!...!/

Text zwischen den Verbatim-Markern landet genau so in der Ausgabe, wie er geschrieben ist. Nichts darin ist Syntax, und die Nachbearbeitung rührt ihn nicht an. Verwenden Sie ihn für Text, der wie Spintax aussieht, aber keines ist: einen Markdown-Link, ein Makro, das ein anderes Tool expandiert, BBCode oder ein Spintax-Beispiel, das Sie zeigen statt rendern möchten.

Der Block ist neu in @spintax/core 0.14.0. Die anderen Engines ergänzen ihn, sobald sie ihn jeweils veröffentlichen.

Docs: /![Spintax](https://spintax.net)!/
→ Docs: [Spintax](https://spintax.net)

Write /!{Hello|Hi}!/ to get two variants.
→ Write {Hello|Hi} to get two variants.

Pull from /!#file[D:\kw.txt,1,S]!/ here.
→ Pull from #file[D:\kw.txt,1,S] here.

Verbatim-Regeln

  • Start-Begrenzer: /!; das erste !/ danach schließt den Block
  • Kann sich über mehrere Zeilen erstrecken, aber nicht verschachtelt werden
  • Innerhalb eines Blocks sind {, [, |, %var% und #set reiner Text
  • Funktioniert in einem #set- oder #def-Wert, sodass sich ein Block wiederverwenden lässt
  • Die Nachbearbeitung läuft wie gewohnt um den Block herum, verändert den Text darin aber nie, schreibt ihn nicht groß und kürzt ihn nicht
  • Ein leerer Block /!!/ wird entfernt
  • Was von /# und /! zuerst kommt, gewinnt: Ein Kommentar kann ein /! verbergen, und ein Block kann ein /# bewahren
  • Ein /! ohne Abschluss ist reiner Text, und der Validator warnt mit verbatim.unclosed
  • Nur die Vorlage wird so gelesen: Ein /! im Wert einer Laufzeitvariable sind schlicht zwei Zeichen. Um nicht vertrauenswürdige Daten wörtlich zu halten, leiten Sie sie durch neutralize(). Die Funktion schützt | nicht, also halten Sie einen solchen Wert außerhalb von {…} und […], und es stoppt die Nachbearbeitung nicht: Für eine bytegenaue Ausgabe übergeben Sie zusätzlich postProcess: false

Verschachtelung

Alle Syntaxelemente können in beliebiger Tiefe ineinander verschachtelt werden:

{option1|[<, > sub1|sub2|sub3]|option3}

[<minsize=2;maxsize=3;sep=", ";lastsep=" and "> {red|blue} apples|{big|small} oranges|bananas]

#set %var% = {a|[b|c]}

Nachbearbeitung

Die Engine wendet nach der Generierung automatische Textkorrektur an:

  1. Schützt URLs (auch ein nacktes https://), E-Mails, Domains, Dezimalzahlen, Abkürzungen und Tokens, die mit einem Punkt beginnen (.NET, .gitignore, .xlsx), vor Großschreibung und Leerzeichenkorrektur
  2. Eliminiert doppelte Leerzeichen und Tabulatoren
  3. Entfernt Leerzeichen vor Satzzeichen (, . ! ?)
  4. Fügt Leerzeichen nach Satzzeichen ein, wo sie fehlen, aber nie zwischen einem Zeichen und dem Anführungszeichen oder der Klammer, die es schließt ("Really?", (etc.))
  5. Schreibt den ersten Buchstaben der Ausgabe groß (HTML-Tags überspringend)
  6. Großschreibung nach satzbeendenden Satzzeichen
  7. Großschreibung nach Block-Level-HTML-Tags
  8. Großschreibung nach Zeilenumbrüchen
  9. Stellt geschützte Platzhalter wieder her

Die Großschreibung folgt der Render-Locale: Unter tr und az beginnt ein Satz, der mit i anfängt, mit İ. Ein Verbatim-Block wird von allen Schritten übersprungen.

Syntaxübersicht

FunktionSyntaxVerhalten
Enumeration{a|b|c}Wählt eine zufällige Option
Permutation[a|b|c]Wählt N, mischt, verbindet
Trennzeichen[<sep> a|b|c]Permutation mit einheitlichem Trennzeichen
Sep pro Element[<, > a|b <x>|c]Permutation mit benutzerdefinierten Trennzeichen
Kombinationen[<config> a|b|c]Permutation mit Min/Max-Anzahl
Variable#set %var% = {a|b}Bei jeder Referenz erneut eingesetzt — enthaltenes Spintax wird neu ausgewürfelt
Variable (einmalig)#def %var% = {a|b}Ein Wurf pro Rendering, überall beibehalten — so bleiben Wortformen und Endungen kongruent
Bedingung{?VAR?then|else}then, wenn truthy; else, wenn falsy
Plural{plural %n%: Sprache|Sprachen}Gleicht die Wortform je nach Locale an die Zahl an
Include#include "slug"Bettet eine andere Vorlage ein — die Referenz löst der Host auf
Kommentar/#...#/Wird aus der Ausgabe entfernt
Verbatim/!...!/Wird genau wie geschrieben ausgegeben

Die Sprache ist ihrem Prototyp Generating The Web (GTW) entwachsen — für GTW geschriebene Vorlagen laufen weiterhin unverändert.