Rho Cheatsheet

One-page syntax quick reference — all 15 capabilities, minimal examples. Print it / pin to wall / embed in IDE auto-complete. Detailed docs in each capability page.


Static visual blocks (5)

Callout

> [!INFO]      | [!WARN]    | [!ZEN]      ← Rho native
> [!NOTE]      | [!TIP]     | [!IMPORTANT]
> [!WARNING]   | [!CAUTION]                ← GFM compatible
> body

Details →

Layout grid + cards

```layout grid cols=N            ← N: 1-6
:::card accent=COLOR              ← blue/red/green/yellow/purple/gray
content
:::
```

Details →

Annotate

```annotate
body text here
---
START-END|COLOR|LABEL              ← 0-based half-open, Unicode codepoint
4-9|red|adjective
10-15|blue|noun
```

Details →

Timeline

```timeline
:::event date=DATE title=TITLE accent=COLOR
body
:::
```

Details →

STL syntax highlight

```stl
[Source] -> [Target] ::mod(key=value, key=value)
# comment
```

Details →


Interactive blocks (4)

Tabs

```tabs default=TITLE
:::tab title=TITLE
content
:::
```

Details →

Stepper

```stepper linear=true|false
:::step title=TITLE optional=true|false disabled=true|false
content
:::
```

Details →

```modal trigger="text" width=SIZE
content
```

SIZE: small / medium / large / full Details →

Interact (controls + template)

```interact namespace NAMESPACE
slider name min max initial step
input name "default"
select name "opt1" "opt2" "opt3"
toggle name <true|false>
button name "label" value
timer name min max step <loop|once|pause|pingpong>
computed name = expression
template <stl|vega-lite|svg>:
  body with {expr} placeholders
```

Details →


Computed + animation (3)

Computed

computed varName = expression

See mini DSL below. Details →

Timer

timer name min max step mode

mode: loop / once / pause / pingpong Details →

SVG scenes

template svg:
<svg viewBox="0 0 100 100">
  <element attr="{expr}" />
</svg>

Allowed: rect / circle / line / path / text / g / defs / animate Forbidden: script / foreignObject / on* / external href Details →

Vega-Lite live chart

template vega-lite:
{
  "data": {"sequence": {"start": 0, "stop": 10, "step": 0.1, "as": "x"}},
  "transform": [{"calculate": "sin({freq} * datum.x)", "as": "y"}],
  "mark": "line",
  "encoding": {"x": {"field": "x"}, "y": {"field": "y", "type": "quantitative"}}
}
  • Numeric fields: {var} (no quotes)
  • String fields: "{var}" (with quotes) Details →

Composition (2)

Shared state (namespace)

\```interact namespace finance
slider rate 0 0.15 0.05 0.01
\```

\```interact namespace finance
template stl: [Rate] -> [{rate}]      ← reuses finance namespace
\```

Details →

Nested DSL

Any structural container (callout / layout / tabs / stepper / modal / timeline) can hold any DSL block — including other containers + interact. Don't nest: tabs in tabs / stepper in stepper / interact in interact (use namespace instead). Details →


Mini DSL (inside {} placeholders)

Arithmetic / comparison / logical

+  -  *  /  %  **
==  !=  <  >  <=  >=
&&  ||  !
cond ? a : b               ← Ternary (replaces if/else)

Functions

abs sign min max
pow sqrt exp log log2 log10
sin cos tan asin acos atan atan2
floor ceil round trunc
length upper lower substring
parseFloat parseInt toString

Constants

pi   = 3.14159...
e    = 2.71828...

Format spec

{x:.2f}       2 decimals
{x:.0f}       integer
{x:.3e}       scientific
{x:%}         percent (auto ×100)
{x:>10.2f}    right-align width 10 + 2 decimals
{{   }}       literal { }

Forbidden (not JavaScript):

Math.X    Number.X    eval    Function
if/else statements    for/while    function definitions
fetch / DOM / window / async

Details →


6-color palette (callout / layout card / annotate / timeline event)

blue    red    green    yellow    purple    gray

Plain-text fallback

Every Rho DSL degrades in non-Rho readers as:

  • Callout → standard blockquote + [!TYPE] literal
  • Others → code block / ::: literals + inner markdown renders normally

Test: push .md to GitHub web — all content should be readable. Details →


Common pitfall reminders

slider param order: name min max initial step (min ≤ initial ≤ max)
input always returns string — use parseFloat for math
namespace is case-sensitive + per-page scope
share across blocks → namespace; don't redeclare
mini DSL isn't JS: use sin(x), not Math.sin
fenced code nesting: outer/inner backtick counts must differ
SVG: always set viewBox

Details →


See also