Continuation lines
Prefix an indented line with ~ to append it to the line above instead of creating a child — added in Beast 0.2.6.
Beast is indentation-sensitive, so a physical newline normally starts a new sibling or child. A continuation line is any non-empty, non-// logical line whose first content character after its leading spaces is ~. The parser strips the ~ and one optional following space or tab, trims any additional leading whitespace, and appends the remainder to the previous logical line with a single separating space. The continuation line itself is discarded, has no children, and its indentation is otherwise ignored.
This keeps the merge independent of the surrounding tree. The merged content inherits the span of the original line for diagnostics and source maps; continuation lines do not produce separate TSRX nodes or extra indentation in generated output.
// ~ // comment is a comment continuation and is ignoreddiv(className='') ~ // comment p Still a child of the div, not of the comment line| Rule | Behavior |
|---|---|
| Position | The ~ must be the first non-space character. div ~ foo is not a continuation — it emits <div>~ foo</div>. |
| Stripping | One space or tab after ~ is removed. ~foo and ~ foo both yield foo. Extra leading whitespace is trimmed before the join. |
| Empty / comment | ~ followed by only whitespace, or by // after trimming, is a no-op and is dropped. |
| Join | Otherwise the trimmed payload is joined with exactly one space: Component(items={ + ~ 0, 1 -> Component(items={[ 0, 1 |
| Chaining | Multiple continuations chain onto the same predecessor. |
| Orphan | A continuation with no predecessor fails with BEAST1004_ORPHAN_CONTINUATION. |
Use continuation to split long component props, className, or array literals without creating children. Each ~ line continues the opening element or expression.
Button( ~ tone="primary" ~ disabled ~ onClick={() => save()} ~ ) Save// Long attribute and expression lists can be split without creating childrenComponent(items={[ ~ 0, 1, 2, 3 ~ ]} ~ ) // Equivalent to: Component(items={[ 0, 1, 2, 3 ]})section.hero(className="flex flex-col items-center justify-center min-h-screen px-6 py-12" ~ id="hero" ~ aria-label="Hero section") h1(className="text-4xl font-bold tracking-tight" ~ id="title") Welcome// → <section className="hero flex ..." id="hero" aria-label="Hero section">// <h1 id="title">Welcome</h1>Any template header can be continued — if, elseif, each, switch, try, and dotted components.
if isReady ~ && hasPermission p Ready each item in items ~ key item.id li #{item.label} switch status ~ // comment continuations are no-ops everywhere case "a" p A default p OtherText content and pipe literals can also be continued. p Hello, followed by ~ world becomes p Hello, world.
p Hello, ~ world// → <p>Hello, world</p>| Long literal text that ~ continues on the next physical line// → Long literal text that continues on the next physical lineA ~ line that is empty or a comment after the ~ is dropped and does not affect parent-child relationships.
div ~ p child// ~ with only whitespace → no effect Theme.Provider(value={theme}) ~ // comment p child// child remains child of Provider, not of the comment lineOrphan continuations and normal indentation rules still apply. The merged line keeps the predecessor span, so errors point at the original header.
~ orphan at top of file// → BEAST1004_ORPHAN_CONTINUATION: A continuation line starting with ~ must follow an indented parent line. div ~ foo// → not a continuation; emits <div>~ foo</div> because ~ is not first character| Code | When |
|---|---|
| BEAST1004_ORPHAN_CONTINUATION | First logical line (after imports/props/setup) starts with ~ |
| BEAST1003_TAB_INDENT | Any leading tab in indentation (unchanged) |
| (span) | Merged payload errors point at the predecessor line, not the ~ line |
Continuations are erased before code generation. Example BTSX with continuations and the TSRX Beast emits:
props { items }: { items: string[] }Card(items={[ ~ "a", ~ "b", ~ "c" ~ ]} ~ className="card" ~ id="main") Helloexport default function Card({ items }: { items: string[] }) @{ <Card items={[ "a", "b", "c" ]} className="card" id="main">Hello</Card>}