Довідник синтаксису Spintax
Повний довідник із шаблонної розмітки spintax.
Переліки { }
Випадковим чином вибирає один варіант зі списку.
{option1|option2|option3}
Приклади
{blue|grey|clear}
{|free|paid} plan ← empty option = sometimes nothing
{Acme {Pro|Lite}} ← nested enumerations
{order {|#42-A} confirmed} ← nesting with empty option
Правила
- Обмежувачі:
{та} - Роздільник варіантів:
| - Підтримує вкладеність довільної глибини
- Порожні варіанти допустимі (дають порожній рядок)
- Розв’язання йде від найглибшого виразу назовні
Перестановки [ ]
Вибирає N елементів, перемішує їх і об’єднує з роздільниками.
Прості перестановки
Усі елементи включені, розділені пробілами:
[1|2|3|4]
Приклади результату: 1 4 3 2, 2 3 4 1, 3 2 4 1
З роздільником
Єдиний роздільник указується в < > на початку:
[<, > 1|2|3|4]
Приклади результату: 2, 1, 4, 3 · 4, 3, 2, 1
Важливо: Між [ та <роздільник> немає пробілу.
Роздільники для кожного елемента
Кожен варіант може мати власний роздільник, заданий через <sep> перед попереднім |. Роздільник переміщується разом зі своїм елементом під час перемішування.
[<, > 1|2|3 < and >|4]
Приклади результату: 1, 3, 2 and 4 · 3, 1, 2 and 4
Авто-пробіли: Словесні роздільники на кшталт <і> чи <або> автоматично доповнюються пробілами: <і> дає і . Розділові знаки (<,>) не доповнюються.
Перестановки з комбінаціями
Налаштовувана мін./макс. кількість елементів і роздільники:
[<minsize=1;maxsize=3;sep=", ";lastsep=" and "> apple|plum|orange|apricot]
Приклади результату: apple, plum and orange · apple and apricot · orange
Параметри конфігурації
| Параметр | Типово | Опис |
|---|---|---|
minsize | кількість усіх | Мінімальна кількість вибраних елементів |
maxsize | кількість усіх | Максимальна кількість вибраних елементів |
sep | " " (пробіл) | Роздільник між елементами (крім останнього) |
lastsep | як sep | Роздільник перед останнім елементом |
Правила перестановок
- Обмежувачі:
[та] - Блок конфігурації
<...>має йти одразу після[ - Параметри конфігурації розділяються крапкою з комою
- Рядкові значення в конфігурації беруться в лапки:
sep=", " - Переліки та перестановки можуть бути вкладені у варіанти
- HTML-елементи можуть бути варіантами
sepз'єднує все до останньої пари,lastsep— саму пару: за двох вибраних елементів з'являється лишеlastsep, за одного — жоден
Змінні %var%
Визначає змінну для багаторазового використання, яка підставляється всюди, де трапляється. Оголосити її можна двома директивами, і вибір не косметичний: #set — макрос, його значення підставляється заново при кожному посиланні, і spintax усередині перекидається; #def розкриває значення один раз за рендер і віддає цей єдиний результат усім посиланням. (Один рендер — це один вивід; той самий seed відтворює його.) Поки значення — простий текст, різниці немає; вона з’являється тієї миті, коли всередині з’являється вибір.
#set %VARIABLE_NAME% = value or spintax structure
#def %VARIABLE_NAME% = value or spintax structure
Приклади
#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.
Правила змінних
#setі#defмають починатися з початку рядка- Імена змінних беруться в
%:%name% - Імена складаються з букв, цифр і підкреслень, а посилання нечутливі до регістру:
%Tone%і%tone%— одна змінна - Значення можуть містити будь-який синтаксис spintax (переліки, перестановки, інші змінні)
#set— макрос: розкривається при посиланні, а не при визначенні, і його значення — разом зі spintax усередині — підставляється заново й перекидається при кожному посиланні#defрозкриває значення один раз за рендер і тримає результат скрізь. Саме цим тримаються повтори: іменник і побудовані від нього відмінкові форми, число для блоку{plural}, будь-яка фраза, що має повторюватися слово в слово#defробить змінну узгодженою із самою собою, але не пов’язує дві змінні.#def %Noun%і#def %NounGen%— два незалежні розкати, вони можуть випасти на різні слова: форми, що мають узгоджуватися, повинні йти з одного розкату — одна основа в#def, на яку посилається кожна відмінкова форма, або синоніми, що відмінюються однаково, із закінченням поза визначенням- Ім’я визначається один раз. Друге визначення того самого імені позначається як
definition.duplicate-name, але рендер усе одно триває: між двома однаковими директивами перемагає остання, а якщо ім’я ділять#setі#def, перемагає#def— байдуже, яка з них була першою - Посилання без визначення друкує саме себе:
%missing%залишається у виводі, а не зникає - Жодна з директив не переходить через
#include: включений шаблон не бачить локальних змінних батька, а його власні не витікають нагору. Розкатана форма потрапляє всередину лише як змінна часу виконання - Рядки
#setі#defвилучаються з результату - Докладно: див. посібник зі змінних — області видимості та підступ із перекидом, і граматично безпечну синонімізацію — відмінкові сім’ї
Області видимості змінних
Хост може подавати змінні з кількох місць. Якщо те саме ім’я є в кількох, перемагає найсильніше:
- Змінні часу виконання (найсильніші) — те, що хост передає у виклик рендера:
contextу@spintax/core, атрибути шорткоду в плагіні WordPress:[spintax slug="greeting" name="Alice"] - Локальні змінні — оголошені через
#setабо#defвсередині шаблону - Глобальні змінні (найслабші) — значення за замовчуванням на рівні хоста, наприклад сторінка налаштувань плагіна
Умови {?VAR?then|else}
Умовний синтаксис — власна конструкція мови: у прототипі GTW нічого подібного не було. Якщо {a|b} — це рівномірний випадковий вибір, який не дивиться на змінні, то {?VAR?then|else} вибирає за тим, чи має %VAR% значення.
Використовуйте для рішень за значенням: показувати рядок про безкоштовний тариф лише коли тариф є, рендерити блок про-можливостей лише коли користувач на платному тарифі, ховати CTA, який зараз не застосовний.
Попередній прохід відпрацьовує до розкриття %var% і до випадкового вибору гілок, тому falsy-гілка відкидається повністю — ніщо всередині неї не обчислюється.
Форми
{?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 та falsy
Правило простіше, ніж у JavaScript — truthy = хоча б один непробільний символ:
Значення %VAR% | Truthy? |
|---|---|
| не оголошена | falsy |
| порожній рядок | falsy |
| лише пробіли | falsy |
"0", "false" | truthy (непорожні рядки) |
| будь-який інший текст чи HTML | truthy |
Правила умов
- Імена змінних відповідають тому ж regex, що й
%var%(без урахування регістру) - Префікс
!інвертує перевірку:{?!VAR?немає даних} - Перший
|на нульовій глибині розділяєthenіelse; наступні|лишаються літералами вelse - Вкладені умови розкриваються outer-first — falsy-гілки короткозамикаються
- Складена логіка (
&&,||, порівняння) не підтримується — обчисліть guard-змінну в асемблері - Криві форми (
{??yes},{?VAR}) не падають — пісочниця позначає їх попередженнями - Докладно: див. гайд з умовного spintax із прикладами та анти-патернами
Плюрали {plural %n%: мова|мови|мов}
Підбирає граматично правильну форму слова під число. Лічильник іде до двокрапки, форми — після, через |.
Форму вибирає локаль рендера, а не шаблон, тому кількість форм залежить від локалі: українській потрібні три, англійській — дві.
{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
Форми за локалями
Локаль зіставляється за мовним субтегом, тож uk-UA та uk поводяться однаково:
| Локаль | Форм | Вибір за числом |
|---|---|---|
ru, uk, be, sr, hr, bs | 3 | 1 · 2–4 · 5 і більше |
усі інші, включно з en | 2 | рівно 1 · усе інше |
Якщо форм не стільки, скільки потрібно локалі, рушій віддає plural.arity і лишає блок видимим у повноширинних дужках — мовчки неправильна форма в продакшен не поїде.
Правила плюралів
- Відкривальна частина літеральна, разом із пробілом:
{plural.{plural: x}та{pluralN: x}плюралами не є - Двокрапка обов’язкова — вона відділяє лічильник від форм
- Лічильник — це посилання
%Var%або цілочисловий літерал; змінні в лічильнику підставляються до вибору форми - Від’ємні числа беруться за модулем;
0отримує форму «все інше» (українською — «мов») - Змінна-лічильник має бути
#def, а не#set—#setце макрос, тому значення на кшталт{1|4|9}на момент вибору форми все ще нерозв’язаний spintax, і блок відрендериться порожнім. У пісочниці цеplural.count-macro - Нечисловий чи невизначений лічильник стирає блок, а не вгадує форму
- Докладно: див. гайд із плюралів — правила трьох форм і розбори прикладів
Включення #include
Вбудовує інший шаблон у позицію директиви. #include — єдина конструкція, яку рушій не може забезпечити сам: сховища шаблонів він не має, тож резолвер, що перетворює посилання на текст шаблону, дає хост. Там, де резолвера не встановлено — у пісочниці та на MCP-сервері цього сайту, і те й інше навмисно, — директива інертна й лишається у виводі звичайним текстом.
#include "hero-text"
/# wrong: text before the directive on the same line leaves it literal #/
Intro: #include "hero-text"
Правила включень
- Директива має займати весь рядок. Відступ ліворуч припустимий, текст після посилання — ні:
Текст #include "hero"лишається літералом - Посилання береться в подвійні лапки; одинарні лапки або їх відсутність — це вже не директива
- Розв’язання посилання — справа хоста: плагін WordPress шукає за slug або числовим ID, JavaScript-хост передає
includeResolver - Без резолвера рядок лишається у виводі літералом; якщо в резолвера такого шаблону немає, рядок натомість видаляється — невідома ціль мовчки коштує вам цілого блоку
- Включені шаблони можуть містити власні змінні та spintax, а також власні
#include - Включення розв’язуються після того, як у батька розіграно переліки й перестановки: include у гілці, що виграла, вбудовується, а у відкинутій не стається взагалі
- Ланцюжки працюють (шаблон включає шаблон, який включає наступний); шаблон, що включає сам себе — прямо чи по циклу, — обривається на першому повторі, без помилки й без діагностики
- Дочірні шаблони успадковують глобальні змінні та змінні часу виконання, але не локальні
#set/#defбатька, і своїх нагору не віддають - Включення не може бути значенням визначення:
#def %x% = #include "y"відхиляється якdef.include-in-value - До рендера
validate()повідомляє про невідому ціль, лише якщо хост передав список відомих посилань;extract()повертає посилання, потрібні шаблону, — так хост їх передзавантажує - Докладно: див. посібник із композиції шаблонів — патерн асемблера, яким користується більшість конвеєрів
Коментарі /#...#/
Текст між маркерами коментарів видаляється з результату до будь-якої іншої обробки.
/#
This is a comment section.
It can span multiple lines.
It won't appear in output.
#/
Правила коментарів
- Відкривальний обмежувач:
/# - Закривальний обмежувач:
#/ - Може займати кілька рядків
- Вкладеність не підтримується
- Видаляються до початку будь-якої іншої обробки
Вкладеність
Усі елементи синтаксису можуть бути вкладені один в одного на довільну глибину:
{option1|[<, > sub1|sub2|sub3]|option3}
[<minsize=2;maxsize=3;sep=", ";lastsep=" and "> {red|blue} apples|{big|small} oranges|bananas]
#set %var% = {a|[b|c]}
Постобробка
Рушій автоматично коригує текст після генерації:
- Захист URL, email-адрес, доменів, десяткових чисел та абревіатур від зміни регістру
- Видалення повторюваних пробілів і табуляцій
- Видалення пробілів перед розділовими знаками (
,.!?) - Додавання пробілу після розділових знаків там, де його бракує
- Велика літера на початку результату (з пропуском HTML-тегів)
- Велика літера після знаків кінця речення
- Велика літера після блокових HTML-тегів
- Велика літера після переносів рядків
- Відновлення захищених заповнювачів
Зведення синтаксису
| Можливість | Синтаксис | Поведінка |
|---|---|---|
| Перелік | {a|b|c} | Вибрати один випадковий варіант |
| Перестановка | [a|b|c] | Вибрати N, перемішати, об’єднати |
| Роздільник | [<sep> a|b|c] | Перестановка з єдиним роздільником |
| Роздільник елемента | [<, > a|b <x>|c] | Перестановка з власними роздільниками |
| Комбінації | [<config> a|b|c] | Перестановка з мін./макс. кількістю |
| Змінна | #set %var% = {a|b} | Підставляється заново при кожному посиланні — spintax усередині перекидається |
| Змінна (раз за рендер) | #def %var% = {a|b} | Один розкат за рендер, результат тримається скрізь — так узгоджуються форми й закінчення |
| Умова | {?VAR?then|else} | then, якщо truthy; інакше else |
| Плюрал | {plural %n%: мова|мови|мов} | Узгоджує форму слова з числом за локаллю |
| Включення | #include "slug" | Вбудовування іншого шаблону — посилання розв’язує хост |
| Коментар | /#...#/ | Видаляється з результату |
Мова виросла зі свого прототипу — Generating The Web (GTW); шаблони, написані для GTW, і далі працюють без змін.