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âmetro | Padrão | Descrição |
|---|---|---|
minsize | total de todos | Número mínimo de elementos a selecionar |
maxsize | total de todos | Número máximo de elementos a selecionar |
sep | " " (espaço) | Separador entre itens não finais |
lastsep | igual a sep | Separador 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
sepjunta tudo antes do par final,lastsepjunta 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
#sete#defdevem 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#defresolve 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#deftorna 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#defreferenciado 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-namee a renderização segue mesmo assim: entre duas diretivas iguais vence a última, e quando um#sete um#defcompartilham 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
#sete#defsã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:
- Variáveis de runtime (as mais fortes) — o que o host passa para a chamada de renderização:
contextem@spintax/core, atributos do shortcode no plugin do WordPress:[spintax slug="greeting" name="Alice"] - Variáveis locais — definidas com
#setou#defdentro do template - 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 declarada | falsy |
| string vazia | falsy |
| somente espaços em branco | falsy |
"0", "false" | truthy (não vazias) |
| qualquer outro texto ou HTML | truthy |
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 separathendeelse; os seguintes ficam literais emelse - 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:
| Locale | Formas | Escolhida por |
|---|---|---|
ru, uk, be, sr, hr, bs | 3 | 1 · 2–4 · 5 em diante |
todas as demais, incl. en | 2 | exatamente 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
0recebe 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 comoplural.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/#defdo 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 comodef.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:
- Protege URLs, emails, domínios, decimais e abreviações da capitalização
- Elimina espaços e tabulações duplicados
- Remove espaços antes da pontuação (
,.!?) - Adiciona espaço após pontuação onde falta
- Capitaliza a primeira letra da saída (pulando tags HTML)
- Capitaliza após pontuação de fim de frase
- Capitaliza após tags HTML de nível de bloco
- Capitaliza após quebras de linha
- Restaura os marcadores protegidos
Resumo da sintaxe
| Recurso | Sintaxe | Comportamento |
|---|---|---|
| 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.