Referência de sintaxe Spintax

Referência completa para a marcação de templates spintax.

Enumerações { }

Seleciona aleatoriamente uma opção da lista.

{option1|option2|option3}

Exemplos

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

Regras

  • Delimitadores: { e }
  • Separador: |
  • Suporta aninhamento em profundidade arbitrária
  • Opções vazias são válidas (produzem string vazia)
  • A resolução vai da expressão mais interna para fora

Permutações [ ]

Seleciona N elementos, embaralha e junta com separadores.

Permutações simples

Todos os elementos incluídos, separados por espaços:

[1|2|3|4]

Exemplos de saída: 1 4 3 2, 2 3 4 1, 3 2 4 1

Com separador

Separador uniforme especificado em < > no início:

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

Exemplos de saída: 2, 1, 4, 3 · 4, 3, 2, 1

Importante: Sem espaço entre [ e <separador>.

Separadores por elemento

Cada opção pode ter seu próprio separador definido com <sep> antes do | anterior. O separador viaja com seu elemento durante a mistura.

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

Exemplos de saída: 1, 3, 2 and 4 · 3, 1, 2 and 4

Espaçamento automático: Separadores de palavras como <and> ou <or> são automaticamente preenchidos com espaços: <and> produz  and . Separadores de pontuação (<,>) não são preenchidos.

Permutações com combinações

Quantidade mínima/máxima de elementos e separadores configuráveis:

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

Exemplos de saída: apple, plum and orange · apple and apricot · orange

Parâmetros de configuração

ParâmetroPadrãoDescrição
minsizetotal de todosNúmero mínimo de elementos a selecionar
maxsizetotal de todosNúmero máximo de elementos a selecionar
sep" " (espaço)Separador entre itens não finais
lastsepigual a sepSeparador antes do último elemento

Regras de permutação

  • Delimitadores: [ e ]
  • O bloco de configuração <...> deve seguir imediatamente [
  • Os parâmetros de configuração são separados por ponto e vírgula
  • Valores de string na configuração estão entre aspas: sep=", "
  • Enumerações e permutações podem ser aninhadas dentro das opções
  • Elementos HTML podem ser opções
  • sep junta tudo antes do par final, lastsep junta esse par: com dois elementos aparece só lastsep, com um não aparece nenhum

Variáveis %var%

Define uma variável reutilizável, substituída onde quer que apareça. Duas diretivas a declaram, e a escolha não é cosmética: #set é uma macro — seu valor é substituído novamente a cada referência, então o spintax dentro dele é sorteado de novo; #def sorteia o valor uma vez por renderização e entrega esse único resultado a todas as referências. (Uma renderização é uma saída; a mesma semente a reproduz.) Enquanto o valor for texto simples as duas são idênticas; a diferença aparece no momento em que o valor contém uma escolha.

#set %VARIABLE_NAME% = value or spintax structure

#def %VARIABLE_NAME% = value or spintax structure

Exemplos

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

Regras de variáveis

  • #set e #def devem começar no início da linha
  • Nomes de variáveis ficam entre %: %name%
  • Os nomes são alfanuméricos + underscore, e as referências não diferenciam maiúsculas: %Tone% e %tone% são a mesma variável
  • Os valores podem conter qualquer sintaxe spintax (enumerações, permutações, outras variáveis)
  • #set é uma macro: expande na referência, não na definição, e seu valor — incluindo o spintax dentro dele — é substituído novamente e sorteado de novo a cada referência
  • #def resolve seu valor uma vez por renderização e mantém esse resultado em todos os lugares. É isso que mantém as repetições concordando: um substantivo e as formas construídas a partir dele, um número que alimenta um bloco {plural}, qualquer frase cujas repetições precisem coincidir palavra por palavra
  • #def torna uma variável consistente consigo mesma; não correlaciona duas variáveis. #def %Noun% e #def %NounGen% são dois sorteios independentes e podem cair em palavras diferentes — formas que precisam concordar têm de vir de um único sorteio: um radical em #def referenciado por cada forma, ou sinônimos que se flexionam igual com a terminação escrita fora da definição
  • Um nome é definido uma vez. Uma segunda definição do mesmo nome é reportada como definition.duplicate-name e a renderização segue mesmo assim: entre duas diretivas iguais vence a última, e quando um #set e um #def compartilham o nome vence o #def, venha qual vier primeiro
  • Uma referência sem definição imprime a si mesma: %missing% permanece na saída em vez de desaparecer
  • Nenhuma das diretivas atravessa um #include: o template incluído não vê as locais do pai, e as suas não vazam para cima. Uma forma já sorteada chega ao filho apenas como variável de runtime
  • As linhas #set e #def são removidas da saída
  • Aprofundar: veja o guia de variáveis (escopos e a pegadinha do re-sorteio) e a sinonimização gramaticalmente segura (famílias de casos)

Escopos de variáveis

Um host pode fornecer variáveis de mais de um lugar. Quando o mesmo nome existe em vários, vence o mais forte:

  1. Variáveis de runtime (as mais fortes) — o que o host passa para a chamada de renderização: context em @spintax/core, atributos do shortcode no plugin do WordPress: [spintax slug="greeting" name="Alice"]
  2. Variáveis locais — definidas com #set ou #def dentro do template
  3. Variáveis globais (as mais fracas) — padrões de todo o host, como a página de configurações do plugin

Condicionais {?VAR?then|else}

Os condicionais são uma construção própria da linguagem: nada parecido existia no protótipo GTW. Enquanto {a|b} é uma escolha aleatória uniforme que ignora variáveis, {?VAR?then|else} escolhe com base em %VAR% ter ou não um valor.

Use-o para escolhas orientadas por valor: mostrar uma linha de plano gratuito apenas quando existir, renderizar um bloco de recursos pro apenas quando o usuário estiver em um plano pago, ocultar um CTA não aplicável.

O pré-passo roda antes da expansão de %var% e antes do seletor aleatório de ramos, então um ramo falsy é totalmente descartado — nada em seu interior é avaliado.

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 e falsy

A regra é deliberadamente mais simples que em JavaScript — truthy = pelo menos um caractere não-espaço:

Valor de %VAR%Truthy?
não declaradafalsy
string vaziafalsy
somente espaços em brancofalsy
"0", "false"truthy (não vazias)
qualquer outro texto ou HTMLtruthy

Regras dos condicionais

  • Nomes de variáveis seguem a mesma regex que %var% (sem distinção de maiúsculas)
  • O prefixo ! inverte a verificação: {?!VAR?ausente}
  • O primeiro | de profundidade 0 separa then de else; os seguintes ficam literais em else
  • Condicionais aninhados são avaliados de fora para dentro — ramos falsy curto-circuitam
  • Lógica composta (&&, ||, comparações) não é suportada — pré-calcule uma variável guarda no assemblador
  • Formas malformadas ({??yes}, {?VAR}) nunca lançam — o playground as marca como avisos
  • Aprofundar: veja o guia de spintax condicional com exemplos e anti-padrões

Plurais {plural %n%: idioma|idiomas}

Escolhe a forma gramaticalmente correta de uma palavra conforme um número. O contador vem antes dos dois pontos e as formas depois, separadas por |.

A forma é escolhida pela locale do render, não pelo template — portanto quantas formas você precisa fornecer depende dessa locale. O inglês pede duas, o russo três.

{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

A locale é comparada pelo seu subtag de idioma, então ru-RU e ru se comportam igual:

LocaleFormasEscolhida por
ru, uk, be, sr, hr, bs31 · 2–4 · 5 em diante
todas as demais, incl. en2exatamente 1 · todo o resto

Se a quantidade de formas não bater, o motor reporta plural.arity e deixa o bloco visível com chaves de largura total — um plural errado nunca vai ao ar em silêncio.

Regras dos plurais

  • A abertura é literal, incluindo o espaço: {plural . {plural: x} e {pluralN: x} não são blocos plurais
  • Os dois pontos são obrigatórios — separam o contador das formas
  • O contador é uma referência %Var% ou um inteiro literal; variáveis no contador são substituídas antes da escolha da forma
  • Números negativos usam o valor absoluto; o 0 recebe a forma "todo o resto"
  • Uma variável contadora deve ser #def, não #set#set é uma macro, então um valor como {1|4|9} ainda é spintax não resolvido na hora de decidir o plural e o bloco renderiza vazio. O playground sinaliza isso como plural.count-macro
  • Um contador não numérico ou indefinido apaga o bloco em vez de adivinhar
  • Aprofundar: veja o guia de plurais com as regras russas de três formas e exemplos resolvidos

Includes #include

Incorpora outro template na posição da diretiva. #include é a única construção que o motor não resolve sozinho: ele não guarda templates, então o host fornece um resolver que transforma uma referência em texto de template. Onde nenhum resolver está instalado — o playground e o servidor MCP deste site, ambos de propósito — a diretiva fica inerte e permanece na saída como texto literal.

#include "hero-text"

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

Regras de include

  • A diretiva precisa ocupar a linha inteira. Recuo à esquerda tudo bem; texto depois da referência não — Texto #include "hero" fica literal
  • A referência vai entre aspas duplas; com aspas simples ou sem aspas já não é a diretiva
  • A resolução é do host: o plugin do WordPress resolve por slug ou ID numérico, um host JavaScript passa um includeResolver
  • Sem resolver, a linha fica literal na saída; se o resolver não tiver esse template, a linha é removida — um destino desconhecido custa o bloco silenciosamente
  • Templates incluídos podem conter suas próprias variáveis e spintax, e seus próprios #include
  • As inclusões são resolvidas depois que as enumerações e permutações do pai foram sorteadas: uma inclusão no ramo vencedor é incorporada — uma em ramo descartado nunca acontece
  • Cadeias funcionam (um template inclui outro que inclui um terceiro); um template que inclui a si mesmo, direto ou em ciclo, é cortado na primeira repetição — sem erro e sem diagnóstico
  • Templates filhos herdam variáveis globais e de runtime, mas não as locais #set / #def do pai, e as suas não vazam para cima
  • Uma inclusão não pode ser o valor de uma definição: #def %x% = #include "y" é rejeitado como def.include-in-value
  • Antes de renderizar, validate() aponta um destino desconhecido apenas quando o host passa a lista de referências conhecidas; extract() devolve as referências de que o template precisa, que é como o host as pré-carrega
  • Aprofundar: veja o guia de composição de templates, o padrão de assembler que a maioria dos pipelines usa no lugar

Comentários /#...#/

O texto entre marcadores de comentário é removido da saída antes de qualquer outro processamento.

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

Regras de comentários

  • Delimitador de início: /#
  • Delimitador de fim: #/
  • Podem abranger múltiplas linhas
  • Não podem ser aninhados
  • Removidos antes de qualquer outro processamento

Aninhamento

Todos os elementos de sintaxe podem ser aninhados uns dentro dos outros em profundidade arbitrária:

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

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

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

Pós-processamento

O motor aplica correção automática de texto após a geração:

  1. Protege URLs, emails, domínios, decimais e abreviações da capitalização
  2. Elimina espaços e tabulações duplicados
  3. Remove espaços antes da pontuação (, . ! ?)
  4. Adiciona espaço após pontuação onde falta
  5. Capitaliza a primeira letra da saída (pulando tags HTML)
  6. Capitaliza após pontuação de fim de frase
  7. Capitaliza após tags HTML de nível de bloco
  8. Capitaliza após quebras de linha
  9. Restaura os marcadores protegidos

Resumo da sintaxe

RecursoSintaxeComportamento
Enumeração{a|b|c}Escolhe uma opção aleatória
Permutação[a|b|c]Escolhe N, embaralha, junta
Separador[<sep> a|b|c]Permutação com separador uniforme
Sep por elemento[<, > a|b <x>|c]Permutação com separadores personalizados
Combinações[<config> a|b|c]Permutação com contagem mín/máx
Variável#set %var% = {a|b}Substituída novamente a cada referência — o spintax dentro dela é sorteado de novo
Variável (uma vez)#def %var% = {a|b}Um único sorteio por renderização, mantido em todos os lugares — assim as formas e as terminações concordam
Condicional{?VAR?then|else}then se truthy; else se falsy
Plural{plural %n%: idioma|idiomas}Concorda a forma da palavra com o número, por locale
Include#include "slug"Incorpora outro template — a referência é resolvida pelo host
Comentário/#...#/Removido da saída

A linguagem superou o seu protótipo, Generating The Web (GTW): os templates escritos para o GTW continuam a funcionar sem alterações.