Referencia de sintaxis Spintax

Referencia completa del marcado de plantillas spintax.

Enumeraciones { }

Selecciona aleatoriamente una opción de la lista.

{option1|option2|option3}

Ejemplos

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

Reglas

  • Delimitadores: { y }
  • Separador: |
  • Soporta anidamiento a profundidad arbitraria
  • Las opciones vacías son válidas (producen cadena vacía)
  • La resolución va desde la expresión más interna hacia afuera

Permutaciones [ ]

Selecciona N elementos, los mezcla y los une con separadores.

Permutaciones simples

Todos los elementos incluidos, separados por espacios:

[1|2|3|4]

Ejemplos de salida: 1 4 3 2, 2 3 4 1, 3 2 4 1

Con separador

Separador uniforme especificado en < > al inicio:

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

Ejemplos de salida: 2, 1, 4, 3 · 4, 3, 2, 1

Importante: Sin espacio entre [ y <separador>.

Separadores por elemento

Cada opción puede tener su propio separador definido con <sep> antes del | precedente. El separador viaja con su elemento durante la mezcla.

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

Ejemplos de salida: 1, 3, 2 and 4 · 3, 1, 2 and 4

Espaciado automático: Los separadores de palabras como <and> o <or> se rellenan automáticamente con espacios: <and> produce  and . Los separadores de puntuación (<,>) no se rellenan.

Permutaciones con combinaciones

Cantidad mínima/máxima de elementos y separadores configurables:

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

Ejemplos de salida: apple, plum and orange · apple and apricot · orange

Parámetros de configuración

ParámetroPor defectoDescripción
minsizetotal de todosNúmero mínimo de elementos a seleccionar
maxsizetotal de todosNúmero máximo de elementos a seleccionar
sep" " (espacio)Separador entre elementos no finales
lastsepigual que sepSeparador antes del último elemento

Reglas de permutación

  • Delimitadores: [ y ]
  • El bloque de configuración <...> debe ir inmediatamente después de [
  • Los parámetros de configuración se separan con punto y coma
  • Los valores de cadena en la configuración van entre comillas: sep=", "
  • Las enumeraciones y permutaciones pueden anidarse dentro de las opciones
  • Los elementos HTML pueden ser opciones
  • sep une todo salvo el par final, lastsep une ese par: con dos elementos solo aparece lastsep, con uno ninguno de los dos

Variables %var%

Define una variable reutilizable que se sustituye allí donde aparece. Dos directivas la declaran, y la elección no es cosmética: #set es una macro — su valor se sustituye de nuevo en cada referencia, así que el spintax que contiene se vuelve a resolver; #def sortea el valor una vez por renderizado y entrega ese único resultado a todas las referencias. (Un renderizado es una salida; la misma semilla la reproduce.) Mientras el valor sea texto plano ambas son idénticas; la diferencia aparece en cuanto el valor contiene una elección.

#set %VARIABLE_NAME% = value or spintax structure

#def %VARIABLE_NAME% = value or spintax structure

Ejemplos

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

Reglas de variables

  • #set y #def deben empezar al principio de una línea
  • Los nombres de variables van entre %: %name%
  • Los nombres son alfanuméricos + guion bajo, y las referencias no distinguen mayúsculas: %Tone% y %tone% son una misma variable
  • Los valores pueden contener cualquier sintaxis spintax (enumeraciones, permutaciones, otras variables)
  • #set es una macro: se expande al referenciarla, no al definirla, y su valor — incluido el spintax que contenga — se sustituye de nuevo y se vuelve a sortear en cada referencia
  • #def resuelve su valor una vez por renderizado y mantiene ese resultado en todas partes. Eso es lo que mantiene concordadas las repeticiones: un sustantivo y las formas construidas a partir de él, un número que alimenta un bloque {plural}, cualquier frase cuyas repeticiones deban coincidir palabra por palabra
  • #def hace que una variable sea consistente consigo misma; no correlaciona dos variables. #def %Noun% y #def %NounGen% son dos sorteos independientes y pueden caer en palabras distintas — las formas que deben concordar tienen que venir de un solo sorteo: una raíz en #def a la que referencia cada forma, o sinónimos que se declinan igual con la terminación escrita fuera de la definición
  • Un nombre se define una vez. Una segunda definición del mismo nombre se reporta como definition.duplicate-name y el renderizado continúa igualmente: entre dos directivas iguales gana la última, y cuando un #set y un #def comparten nombre gana el #def, viniera primero el que viniera
  • Una referencia sin definición se imprime a sí misma: %missing% permanece en la salida en vez de desaparecer
  • Ninguna de las dos directivas cruza un #include: la plantilla incluida no ve las locales del padre, y las suyas no se filtran hacia arriba. Una forma ya sorteada llega al hijo solo como variable de ejecución
  • Las líneas #set y #def se eliminan de la salida
  • Profundizar: consulta la guía de variables (ámbitos y la trampa del re-sorteo) y la sinonimización gramaticalmente segura (familias de casos)

Ámbitos de las variables

Un host puede aportar variables desde más de un sitio. Cuando el mismo nombre existe en varios, gana el más fuerte:

  1. Variables de ejecución (las más fuertes) — lo que el host pasa a la llamada de renderizado: context en @spintax/core, atributos del shortcode en el plugin de WordPress: [spintax slug="greeting" name="Alice"]
  2. Variables locales — definidas con #set o #def dentro de la plantilla
  3. Variables globales (las más débiles) — valores por defecto de todo el host, como la página de ajustes del plugin

Condicionales {?VAR?then|else}

Los condicionales son una construcción propia del lenguaje: nada parecido existía en el prototipo GTW. Mientras {a|b} elige uno al azar ignorando variables, {?VAR?then|else} elige según si %VAR% tiene un valor.

Úsalo para elecciones impulsadas por valor: mostrar una línea de plan gratuito solo cuando exista, renderizar un bloque de funciones pro solo cuando el usuario tenga un plan de pago, ocultar un CTA que no aplica.

El pre-paso corre antes de la expansión de %var% y antes del selector aleatorio de ramas, así que una rama falsy se descarta por completo — nada en su interior se evalúa.

Formas

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

La regla es deliberadamente más simple que en JavaScript — truthy = al menos un carácter no-espacio:

Valor de %VAR%¿Truthy?
no declaradafalsy
cadena vacíafalsy
solo espaciosfalsy
"0", "false"truthy (no vacías)
cualquier otro texto o HTMLtruthy

Reglas de los condicionales

  • Los nombres de variable siguen la misma regex que %var% (sin distinguir mayúsculas)
  • El prefijo ! invierte la comprobación: {?!VAR?ausente}
  • El primer | de profundidad 0 separa then de else; los siguientes quedan literales en else
  • Los condicionales anidados se evalúan de fuera hacia dentro — las ramas falsy hacen short-circuit
  • La lógica compuesta (&&, ||, comparaciones) no está soportada — calcula una variable guardia en el ensamblador
  • Las formas malformadas ({??yes}, {?VAR}) nunca lanzan — el playground las marca como advertencias
  • Profundizar: consulta la guía de spintax condicional con ejemplos y anti-patrones

Plurales {plural %n%: idioma|idiomas}

Elige la forma gramaticalmente correcta de una palabra según un número. El contador va antes de los dos puntos y las formas después, separadas por |.

La forma la decide la locale del render, no la plantilla, así que cuántas formas debes aportar depende de esa locale: el inglés necesita dos, el ruso tres.

{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

Formas por locale

La locale se compara por su subetiqueta de idioma, así que ru-RU y ru se comportan igual:

LocaleFormasSe elige por
ru, uk, be, sr, hr, bs31 · 2–4 · 5 en adelante
todas las demás, incl. en2exactamente 1 · el resto

Si el número de formas no coincide, el motor informa plural.arity y deja el bloque visible con llaves de ancho completo: un plural incorrecto nunca sale en silencio.

Reglas de los plurales

  • La apertura es literal, incluido el espacio: {plural . {plural: x} y {pluralN: x} no son bloques plurales
  • Los dos puntos son obligatorios: separan el contador de las formas
  • El contador es una referencia %Var% o un entero literal; las variables del contador se sustituyen antes de elegir la forma
  • Los números negativos se toman en valor absoluto; el 0 recibe la forma «el resto»
  • Una variable contador debe ser #def, no #set: #set es una macro, así que un valor como {1|4|9} sigue siendo spintax sin resolver cuando se decide el plural y el bloque se renderiza vacío. El playground lo marca como plural.count-macro
  • Un contador no numérico o indefinido borra el bloque en lugar de adivinar
  • Profundizar: consulta la guía de plurales con las reglas rusas de tres formas y ejemplos resueltos

Includes #include

Inserta otra plantilla en la posición de la directiva. #include es la única construcción que el motor no puede resolver por sí solo: no guarda plantillas, así que el host aporta un resolver que convierte una referencia en texto de plantilla. Donde no hay resolver instalado — el playground y el servidor MCP de este sitio, ambos a propósito — la directiva es inerte y permanece en la salida como texto literal.

#include "hero-text"

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

Reglas de include

  • La directiva debe ocupar la línea entera. El espacio inicial no molesta; el texto después de la referencia sí — Texto #include "hero" queda literal
  • La referencia va entre comillas dobles; con comillas simples o sin comillas ya no es la directiva
  • La resolución es cosa del host: el plugin de WordPress resuelve por slug o ID numérico, un host JavaScript pasa un includeResolver
  • Sin resolver, la línea queda literal en la salida; si el resolver no tiene esa plantilla, la línea se elimina — un destino desconocido te cuesta el bloque en silencio
  • Las plantillas incluidas pueden contener sus propias variables y spintax, y sus propios #include
  • Las inclusiones se resuelven después de que se hayan elegido las enumeraciones y permutaciones del padre, así que una inclusión dentro de la rama ganadora se incrusta — una dentro de una rama descartada nunca ocurre
  • Las cadenas funcionan (una plantilla incluye otra que incluye otra); una plantilla que se incluye a sí misma, directamente o en ciclo, se corta en la primera repetición — sin error y sin diagnóstico
  • Las plantillas hijas heredan variables globales y de ejecución, pero no las locales #set / #def del padre, y las suyas no se filtran hacia arriba
  • Una inclusión no puede ser el valor de una definición: #def %x% = #include "y" se rechaza como def.include-in-value
  • Antes de renderizar, validate() señala un destino desconocido solo si el host pasa la lista de referencias conocidas; extract() devuelve las referencias que necesita la plantilla, que es como el host las precarga
  • Profundizar: consulta la guía de composición de plantillas, el patrón de ensamblador que usan la mayoría de los pipelines

Comentarios /#...#/

El texto entre marcadores de comentario se elimina de la salida antes de cualquier otro procesamiento.

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

Reglas de comentarios

  • Delimitador de inicio: /#
  • Delimitador de fin: #/
  • Pueden abarcar múltiples líneas
  • No pueden anidarse
  • Se eliminan antes de cualquier otro procesamiento

Anidamiento

Todos los elementos de sintaxis pueden anidarse entre sí a profundidad arbitraria:

{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-procesamiento

El motor aplica corrección automática de texto después de la generación:

  1. Protege URLs, correos electrónicos, dominios, decimales y abreviaturas de la capitalización
  2. Elimina espacios y tabulaciones duplicados
  3. Elimina espacios antes de signos de puntuación (, . ! ?)
  4. Añade espacio después de signos de puntuación donde falta
  5. Capitaliza la primera letra de la salida (omitiendo etiquetas HTML)
  6. Capitaliza después de signos de puntuación de fin de oración
  7. Capitaliza después de etiquetas HTML de nivel de bloque
  8. Capitaliza después de saltos de línea
  9. Restaura los marcadores protegidos

Resumen de sintaxis

CaracterísticaSintaxisComportamiento
Enumeración{a|b|c}Elige una opción aleatoria
Permutación[a|b|c]Elige N, mezcla, une
Separador[<sep> a|b|c]Permutación con separador uniforme
Sep por elemento[<, > a|b <x>|c]Permutación con separadores personalizados
Combinaciones[<config> a|b|c]Permutación con cuenta mín/máx
Variable#set %var% = {a|b}Se sustituye de nuevo en cada referencia — el spintax que contiene se vuelve a resolver
Variable (una vez)#def %var% = {a|b}Un solo sorteo por renderizado, mantenido en todas partes — así concuerdan las formas y las terminaciones
Condicional{?VAR?then|else}then si truthy; else si falsy
Plural{plural %n%: idioma|idiomas}Concuerda la forma de la palabra con el número, por locale
Include#include "slug"Inserta otra plantilla — la referencia la resuelve el host
Comentario/#...#/Se elimina de la salida

El lenguaje superó a su prototipo, Generating The Web (GTW): las plantillas escritas para GTW siguen funcionando sin cambios.