# Conditional spintax: {?VAR?then|else} Sometimes the choice between two phrasings is not a coin flip — it depends on a fact. The product has a free tier, or it doesn't. The merchant accepts cryptocurrency, or only fiat. Conditional spintax is the value-driven counterpart to `{a|b}` enum branches: instead of picking randomly, it picks based on whether a variable is truthy. ## The three forms Conditional syntax adds three tokens on top of the core spintax language. All three are evaluated **before** enums and permutations resolve — they are a pre-pass, not a runtime branch. | Form | Meaning | | --- | --- | | `{?VAR?then}` | Render `then` if `%VAR%` is truthy; render nothing otherwise. | | `{?VAR?then|else}` | Render `then` if truthy; render `else` if falsy. | | `{?!VAR?then[|else]}` | Inverted: render `then` when `%VAR%` is _falsy_. | The `!` prefix flips the check. There is no separate `{?VAR??else}` form — if you only want the falsy branch, write `{?!VAR?else}`. **Variable names follow the `%var%` rules.** They match `[A-Za-z_][A-Za-z0-9_]*` and are case-insensitive — `{?HasFreeTier?…}` and `{?hasfreetier?…}` read the same value. ## Truthy and falsy The truthy rule is deliberately simpler than JavaScript's. You should not have to remember coercion edge cases. | Value of `%VAR%` | Truthy? | | --- | --- | | not declared at all | falsy | | empty string `""` | falsy | | whitespace only (spaces, tabs, newlines) | falsy | | `"0"` | **truthy** (string zero is non-empty) | | `"false"` | **truthy** (still a non-empty string) | | `"x"`, `"

…

"`, raw spintax | truthy | That is the whole rule. **Truthy = at least one non-whitespace character.** If you ever need a JavaScript-flavoured truthiness, do that check in the assembler before passing the variable in. ### Truthiness reads the raw value The lookup is on the raw stored value of the variable. Nested `%var%` references inside that value are _not_ expanded for the truthy check — only later, when `expandVariables` runs as a separate stage. ``` #set %X% = %Other% {?X?yes|no} → "yes" ``` Even if `%Other%` would expand to an empty string, `%X%`'s raw value is the literal string `%Other%` — which is non-empty, hence truthy. To get value-aware truthiness, write `%X%` as a clean `'1'` or `''` directly. Compute the guard in the assembler before passing it in. ## The two-pass pipeline The engine processes a template in stages. Conditionals get **two evaluation passes**: ``` 1. strip comments 2. extract #set / #def directives 3. merge variables 4. apply conditionals ← pass 1 5. expand %var% references 6. apply conditionals ← pass 2 7. resolve enumerations 8. resolve permutations 9. post-process ``` **Pass 1** handles conditionals authored directly in the template body. It runs before variable expansion so a falsy branch is discarded without wasting cycles on its `%var%`s. **Pass 2** handles the case where a variable's value _itself_ contains a conditional: ``` #set %CTA% = {?HasBonus?Claim bonus|Deposit now} %CTA% /# pass 2 sees the conditional after expansion #/ ``` One clarification: pass 2 does not loop. If the chosen branch contains a fresh `%var%` reference, that reference is left literal — there is no third expansion pass. For most real templates this is fine; the guards used in conditional branches (`%HasCrypto%`, `%HasFiat%`) are typically the same ones already resolved in pass 1. ## Worked example: payment-methods section This is the case the syntax was designed for. A product page renders a "Payment methods" section. Some merchants accept crypto, some accept only fiat, some accept both, a few have no payment integration configured yet. The variable assembler computes two guards plus three pre-rendered HTML chunks: ``` %HasCrypto% "1" or "" %HasFiat% "1" or "" %CryptoSection% /# already-rendered

+