Référence de syntaxe Spintax

Référence complète du balisage de modèles spintax.

Énumérations { }

Sélectionne aléatoirement une option dans la liste.

{option1|option2|option3}

Exemples

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

Règles

  • Délimiteurs : { et }
  • Séparateur : |
  • Prend en charge l'imbrication à profondeur arbitraire
  • Les options vides sont valides (produisent une chaîne vide)
  • La résolution va de l'expression la plus interne vers l'extérieur

Permutations [ ]

Sélectionne N éléments, les mélange et les joint avec des séparateurs.

Permutations simples

Tous les éléments inclus, séparés par des espaces :

[1|2|3|4]

Exemples de sortie : 1 4 3 2, 2 3 4 1, 3 2 4 1

Avec séparateur

Séparateur uniforme spécifié dans < > au début :

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

Exemples de sortie : 2, 1, 4, 3 · 4, 3, 2, 1

Important : Pas d'espace entre [ et <séparateur>.

Séparateurs par élément

Chaque option peut avoir son propre séparateur défini avec <sep> avant le | précédent. Le séparateur voyage avec son élément lors du mélange.

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

Exemples de sortie : 1, 3, 2 and 4 · 3, 1, 2 and 4

Espacement automatique : Les séparateurs textuels comme <and> ou <or> sont automatiquement entourés d'espaces : <and> produit  and . Les séparateurs de ponctuation (<,>) ne sont pas complétés.

Permutations avec combinaisons

Nombre minimum/maximum d'éléments et séparateurs configurables :

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

Exemples de sortie : apple, plum and orange · apple and apricot · orange

Paramètres de configuration

ParamètrePar défautDescription
minsizetotal de tousNombre minimum d'éléments à sélectionner
maxsizetotal de tousNombre maximum d'éléments à sélectionner
sep" " (espace)Séparateur entre les éléments non finaux
lastsepidentique à sepSéparateur avant le dernier élément

Règles de permutation

  • Délimiteurs : [ et ]
  • Le bloc de configuration <...> doit suivre immédiatement [
  • Les paramètres de configuration sont séparés par des points-virgules
  • Les valeurs de chaîne dans la configuration sont entre guillemets : sep=", "
  • Les énumérations et permutations peuvent être imbriquées dans les options
  • Les éléments HTML peuvent être des options
  • sep joint tout ce qui précède la dernière paire, lastsep joint cette paire : avec deux éléments seul lastsep apparaît, avec un seul aucun des deux

Variables %var%

Définit une variable réutilisable, substituée partout où elle apparaît. Deux directives la déclarent, et le choix n’est pas cosmétique : #set est une macro — sa valeur est resubstituée à chaque référence, donc le spintax qu’elle contient est rejoué ; #def tire la valeur une seule fois par rendu et remet ce résultat unique à toutes les références. (Un rendu est une sortie ; la même graine la reproduit.) Tant que la valeur est un texte simple, les deux sont identiques ; la différence apparaît dès que la valeur contient un choix.

#set %VARIABLE_NAME% = value or spintax structure

#def %VARIABLE_NAME% = value or spintax structure

Exemples

#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.

Règles des variables

  • #set et #def doivent commencer en début de ligne
  • Les noms de variables sont entourés de % : %name%
  • Les noms sont alphanumériques + tiret bas, et les références sont insensibles à la casse : %Tone% et %tone% sont une seule variable
  • Les valeurs peuvent contenir n’importe quelle syntaxe spintax (énumérations, permutations, autres variables)
  • #set est une macro : elle est développée à la référence, pas à la définition, et sa valeur — y compris le spintax qu’elle contient — est resubstituée et rejouée à chaque référence
  • #def résout sa valeur une seule fois par rendu et conserve ce résultat partout. C’est ce qui garde les répétitions accordées : un nom et les formes qui en dérivent, un compte alimentant un bloc {plural}, toute phrase dont les répétitions doivent correspondre mot pour mot
  • #def rend une variable cohérente avec elle-même ; il ne corrèle pas deux variables. #def %Noun% et #def %NounGen% sont deux tirages indépendants et peuvent tomber sur des mots différents — les formes qui doivent s’accorder doivent venir d’un seul tirage : un radical en #def référencé par chaque forme, ou des synonymes qui se déclinent pareil avec la terminaison écrite hors de la définition
  • Un nom se définit une fois. Une seconde définition du même nom est signalée comme definition.duplicate-name et le rendu se poursuit malgré tout : entre deux directives identiques, la dernière l’emporte ; et quand un #set et un #def partagent un nom, c’est le #def qui l’emporte, quel que soit celui qui vient en premier
  • Une référence sans définition s’imprime elle-même : %missing% reste dans la sortie au lieu de disparaître
  • Aucune des deux directives ne franchit un #include : le modèle inclus ne voit pas les locales du parent, et les siennes ne remontent pas. Une forme déjà tirée n’atteint l’enfant que comme variable d’exécution
  • Les lignes #set et #def sont retirées de la sortie
  • Approfondir : voir le guide des variables (portées et piège du re-tirage) et la synonymisation grammaticalement sûre (familles de cas)

Portées des variables

Un hôte peut fournir des variables depuis plusieurs endroits. Quand le même nom existe dans plusieurs, le plus fort l’emporte :

  1. Variables d’exécution (les plus fortes) — ce que l’hôte passe à l’appel de rendu : context dans @spintax/core, attributs du shortcode dans l’extension WordPress : [spintax slug="greeting" name="Alice"]
  2. Variables locales — définies avec #set ou #def dans le modèle
  3. Variables globales (les plus faibles) — valeurs par défaut à l’échelle de l’hôte, comme la page de réglages de l’extension

Conditionnels {?VAR?then|else}

Les conditionnels sont une construction propre au langage : rien de tel n'existait dans le prototype GTW. Là où {a|b} est un tirage aléatoire uniforme qui ignore les variables, {?VAR?then|else} choisit selon que %VAR% ait une valeur ou non.

Utilisez-le pour des choix dictés par la valeur : afficher une ligne sur l'offre gratuite uniquement si elle existe, rendre un bloc fonctionnalités pro uniquement lorsque l'utilisateur a un forfait payant, masquer un CTA qui ne s'applique pas.

Le pré-traitement s'exécute avant l'expansion de %var% et avant le sélecteur de branche aléatoire, donc une branche fausse est entièrement écartée — rien à l'intérieur n'est évalué.

Formes

{?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 et falsy

La règle est volontairement plus simple qu'en JavaScript — truthy = au moins un caractère non-espace :

Valeur de %VAR%Truthy ?
non déclaréefalsy
chaîne videfalsy
uniquement des espacesfalsy
"0", "false"truthy (non vides)
tout autre texte ou HTMLtruthy

Règles des conditionnels

  • Les noms de variables suivent la même regex que %var% (insensibles à la casse)
  • Le préfixe ! inverse la vérification : {?!VAR?absent}
  • Le premier | de profondeur 0 sépare then et else ; les suivants restent littéraux dans else
  • Les conditionnels imbriqués s'évaluent de l'extérieur — les branches fausses court-circuitent
  • La logique composée (&&, ||, comparaisons) n'est pas supportée — pré-calculez une variable garde dans l'assembleur
  • Les formes malformées ({??yes}, {?VAR}) ne lèvent jamais d'exception — le playground les signale comme avertissements
  • Approfondir : voir le guide spintax conditionnel avec exemples et anti-patterns

Pluriels {plural %n%: langue|langues}

Choisit la forme grammaticalement correcte d'un mot en fonction d'un nombre. Le compteur précède les deux-points, les formes suivent, séparées par |.

La forme est choisie par la locale du rendu, pas par le modèle : le nombre de formes à fournir dépend donc de cette locale. L'anglais en demande deux, le russe trois.

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

{plural %n%: form1|form2|form3}    ← 3-form locale (ru, uk, sr…)
#def %LangCount% = 5
supports %LangCount% {plural %LangCount%: language|languages}
← supports 5 languages

Formes par locale

La locale est comparée sur sa sous-balise de langue : ru-RU et ru se comportent donc à l'identique.

LocaleFormesChoisie selon
ru, uk, be, sr, hr, bs31 · 2–4 · 5 et plus
toutes les autres, dont en2exactement 1 · tout le reste

Si le nombre de formes ne correspond pas, le moteur signale plural.arity et laisse le bloc visible avec des accolades pleine chasse : un pluriel faux ne part jamais en silence.

Règles des pluriels

  • L'ouverture est littérale, espace compris : {plural . {plural: x} et {pluralN: x} ne sont pas des blocs pluriels
  • Les deux-points sont obligatoires : ils séparent le compteur des formes
  • Le compteur est une référence %Var% ou un entier littéral ; les variables du compteur sont substituées avant le choix de la forme
  • Les nombres négatifs sont pris en valeur absolue ; 0 reçoit la forme « tout le reste »
  • Une variable compteur doit être #def, pas #set : #set est une macro, donc une valeur comme {1|4|9} est encore du spintax non résolu au moment du choix, et le bloc se rend vide. Le playground le signale par plural.count-macro
  • Un compteur non numérique ou indéfini efface le bloc au lieu de deviner
  • Approfondir : voir le guide des pluriels pour les règles russes à trois formes et des exemples détaillés

Includes #include

Insère un autre modèle à la position de la directive. #include est la seule construction que le moteur ne peut pas assurer seul : il ne stocke aucun modèle, c’est donc l’hôte qui fournit un resolver transformant une référence en texte de modèle. Là où aucun resolver n’est installé — le playground et le serveur MCP de ce site, les deux volontairement — la directive est inerte et reste dans la sortie comme du texte littéral.

#include "hero-text"

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

Règles d'inclusion

  • La directive doit occuper toute la ligne. Une indentation ne gêne pas ; du texte après la référence, si — Texte #include "hero" reste littéral
  • La référence est entre guillemets doubles ; avec des apostrophes ou sans guillemets, ce n’est plus la directive
  • La résolution appartient à l’hôte : l’extension WordPress résout par slug ou ID numérique, un hôte JavaScript passe un includeResolver
  • Sans resolver, la ligne reste littérale dans la sortie ; si le resolver n’a pas ce modèle, la ligne est supprimée — une cible inconnue vous coûte le bloc en silence
  • Les modèles inclus peuvent contenir leurs propres variables et spintax, et leurs propres #include
  • Les inclusions sont résolues après le tirage des énumérations et permutations du parent : une inclusion dans la branche gagnante est intégrée — une inclusion dans une branche écartée n’a jamais lieu
  • Les chaînes fonctionnent (un modèle en inclut un autre qui en inclut un troisième) ; un modèle qui s’inclut lui-même, directement ou en cycle, est coupé à la première répétition — sans erreur ni diagnostic
  • Les modèles enfants héritent des variables globales et d’exécution mais pas des locales #set / #def du parent, et les leurs ne remontent pas
  • Une inclusion ne peut pas être la valeur d’une définition : #def %x% = #include "y" est rejeté comme def.include-in-value
  • Avant le rendu, validate() ne signale une cible inconnue que si l’hôte fournit la liste des références connues ; extract() renvoie les références dont le modèle a besoin, ce qui permet à l’hôte de les précharger
  • Approfondir : voir le guide de composition de modèles, le motif d’assembleur qu’utilisent la plupart des pipelines

Commentaires /#...#/

Le texte entre les marqueurs de commentaire est supprimé de la sortie avant tout autre traitement.

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

Règles des commentaires

  • Délimiteur de début : /#
  • Délimiteur de fin : #/
  • Peuvent s'étendre sur plusieurs lignes
  • Ne peuvent pas être imbriqués
  • Supprimés avant tout autre traitement

Imbrication

Tous les éléments de syntaxe peuvent être imbriqués les uns dans les autres à profondeur arbitraire :

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

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

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

Post-traitement

Le moteur applique une correction automatique du texte après la génération :

  1. Protège les URLs, e-mails, domaines, décimales et abréviations de la capitalisation
  2. Supprime les espaces et tabulations en double
  3. Supprime les espaces avant la ponctuation (, . ! ?)
  4. Ajoute un espace après la ponctuation si manquant
  5. Met en majuscule la première lettre de la sortie (en ignorant les balises HTML)
  6. Met en majuscule après la ponctuation de fin de phrase
  7. Met en majuscule après les balises HTML de niveau bloc
  8. Met en majuscule après les sauts de ligne
  9. Restaure les marqueurs protégés

Résumé de la syntaxe

FonctionnalitéSyntaxeComportement
Énumération{a|b|c}Choisit une option aléatoire
Permutation[a|b|c]Choisit N, mélange, joint
Séparateur[<sep> a|b|c]Permutation avec séparateur uniforme
Sep par élément[<, > a|b <x>|c]Permutation avec séparateurs personnalisés
Combinaisons[<config> a|b|c]Permutation avec nombre min/max
Variable#set %var% = {a|b}Resubstituée à chaque référence — le spintax qu’elle contient est rejoué
Variable (une fois)#def %var% = {a|b}Un seul tirage par rendu, conservé partout — c’est ainsi que formes et terminaisons s’accordent
Conditionnel{?VAR?then|else}then si vrai ; else si faux
Pluriel{plural %n%: langue|langues}Accorde la forme du mot avec le nombre, selon la locale
Include#include "slug"Intègre un autre modèle — la référence est résolue par l’hôte
Commentaire/#...#/Supprimé de la sortie

Le langage a dépassé son prototype, Generating The Web (GTW) : les modèles écrits pour GTW fonctionnent toujours sans modification.