Interact — text template

在 ```interact 块里用 template stl: 声明纯文本输出模板——把控件值嵌入 STL / 任意文本,实时显示给读者。 这是 Interact controls 的"输出端",最常见、最简单的 template 类型。


When to use

  • ✅ 轻量计算器(把 slider/input 值代入文本结果)
  • ✅ 配置预览("你选的设置 = ..." 实时回显)
  • ✅ STL 节点动态生成(拖滑块改某节点的 confidence / 描述)
  • ✅ 教学公式回显(输入 → 公式 → 结果)
  • ❌ 需要图表 → 用 Vega-Lite template
  • ❌ 需要动画 / SVG → 用 SVG template
  • ❌ 复杂 layout / 多 section → 拆成多个 interact 块或用 Layout

Basic syntax

\```interact
slider x 0 10 5 1
template stl:
[选中值] -> [{x}]
\```

template <type>: 声明 template 类型 + 冒号。冒号后的所有内容是 template 内容。{var} 是占位符。

渲染:slider 下方实时输出一行 STL:[选中值] -> [5]。拖 slider → 数字变。


Template types

类型 用途 文档
template stl: 输出 STL 语句 / 任意纯文本 本页
template vega-lite: 输出 live chart(Vega-Lite spec) Interact + Vega-Lite
template svg: 输出 SVG 场景 SVG scenes

"stl" template 类型名是历史遗留——它不只能输出 STL,能输出任意文本。模板里的 [A] -> [B] 只是文本,不会真的解析成 STL 节点(除非你后续把渲染结果喂进 STG)。


Placeholder 语法 {...}

template 里 { } 包围的是表达式,会被实时求值。

1. 直接引用变量

template stl:
[体重] -> [{weight}]
[姓名] -> [{name}]
[激活] -> [{enabled}]

2. 表达式

template stl:
[BMI] -> [{weight / (height * height)}]
[折扣价] -> [{price * (1 - discount)}]

mini DSL 支持的运算(详见 Computed):

  • 算术:+ - * / % **
  • 比较:== != < > <= >=
  • 逻辑:&& || !
  • 三元:cond ? a : b
  • 函数:pow(a, b) sqrt(x) abs(x) min(...) max(...) sin(x) cos(x) tan(x) log(x) exp(x) floor(x) ceil(x) round(x)
  • 常数:pi e

3. 格式化 :fmt

template stl:
[BMI] -> [{bmi:.1f}]                ← 1 位小数
[价格] -> [${price:.2f}]            ← 2 位小数(钱)
[百分比] -> [{(rate*100):.1f}%]      ← 转百分号
[科学] -> [{value:.3e}]             ← 科学记数
[整数] -> [{count:.0f}]             ← 0 位小数(强转 int)
[宽度] -> [{x:>10.2f}]              ← 右对齐 10 字符宽 + 2 位小数

格式化语法跟 Python f-string 类似:{value:[align][width][.precision][type]}

Type 含义 例
f float {x:.2f}
e 科学记数 {x:.3e}
d int (强转) {x:d}
s string {name:s}
% 百分号(自动 ×100) {rate:.1%}

4. 转义 {{ }}

如果 template 里要输出字面 { 或 },用双花括号转义:

template stl:
JSON 字面 = {{"key": "value"}}     ← 输出 {"key": "value"}

Examples

Example 1:纯回显

\```interact
slider x 0 100 50 1
template stl:
[当前值] -> [{x}]
\```

渲染:滑块 + 一行 "当前值 = 50",拖动实时变。

Example 2:多行 STL 输出 + 格式化

\```interact
slider weight 40 120 70 1
slider height 1.4 2.1 1.7 0.01
template stl:
[体重] -> [{weight} kg]
[身高] -> [{height:.2f} m]
[BMI] -> [{(weight / (height * height)):.1f}] ::mod(category="{(weight / (height * height)) < 18.5 ? "偏瘦" : (weight / (height * height)) < 24 ? "正常" : (weight / (height * height)) < 28 ? "超重" : "肥胖"}")
\```

渲染:3 行实时 STL 输出。第三行的 category 用三元嵌套显示 BMI 分类。重复表达式建议改用 computed 派生值。

Example 3:纯文本 template(不是 STL)

\```interact
input name "Alice"
slider age 1 100 30 1
select role "学生" "工程师" "教师" "其他"
template stl:
你好,{name}!

你是一位 {age} 岁的 **{role}**。

明年你将 {age + 1} 岁。
\```

渲染:自由文本 template(不限于 STL 形式)。"stl" 这个类型名其实是泛"纯文本"。

Example 4:配置预览

\```interact
input projectName "my-app"
select stack "Next.js" "Astro" "SvelteKit"
toggle typescript true
toggle eslint true
template stl:
**项目配置预览**:

\```bash
npx create-{stack:s} {projectName}{typescript ? " --typescript" : ""}{eslint ? " --eslint" : ""}
\```
\```

渲染:表单 → 一行命令实时拼接。toggle 配三元式按需追加 flag。


Plain-text fallback behavior

```interact 块在不支持的 reader 里显示为代码块。template 部分在 plain text 里保留 {var} 字面量——读者看到 template 的源码 + 控件声明,能完全理解原文档想表达什么。

\```interact
slider x 0 10 5 1
template stl:
[选中值] -> [{x}]
\```

→ Plain-text reader 看到上面这段(含 {x} placeholder),知道"这里 x 是动态值"。

Reader 渲染效果
Rho 完整交互 + template 实时求值
GitHub web 代码块({x} 字面量可见)
Obsidian 同上
VS Code 默认预览 同上
cat / less plain text

Common pitfalls

1. 引用未声明的变量

\```interact
slider x 0 10 5 1
template stl:
[结果] -> [{y}]      ← ❌ y 未声明
\```

→ template 输出 {y} 字面量或抛错。所有 template 引用的变量必须先用 slider/input/select/toggle/computed 声明。

2. 格式化指令错误

template stl:
[BMI] -> [{bmi:.1}]      ← ❌ 缺 type 字符(应是 .1f / .1e)
[BMI] -> [{bmi:.1f}]     ← ✅
[BMI] -> [{bmi:f}]       ← ⚠️ 默认 6 位小数,可能太多
[BMI] -> [{bmi:.1f}]     ← ✅ 1 位小数

format spec 必须带 type 字符(f / e / d / s / %)。

3. 表达式里嵌套未转义引号

template stl:
[标签] -> [{name == "Alice" ? "管理员" : "用户"}]    ← ❌ template 里的 " 跟外层冲突

→ template 里的 " 跟外层 STL 字符串语义冲突,行为未定义。 改进:用 mini DSL 单引号 '(如果支持),或预先在 computed 里算好,template 只引用 computed 名。

4. template 跟 callout / layout 嵌套深度过深

:::card
\```interact
slider x 0 10 5 1
template stl:
[选中] -> [{x}]
\```
:::

✅ 合法。但 callout / layout 内的 interact 块的高度会因 template 输出长度变化而变。控制 template 输出行数稳定或给容器固定 min-height。

5. template 输出含特殊 markdown 字符

template stl:
[选中] -> [{x}]      ← `[` `]` 在 markdown 是链接语法

实际通常没问题——Rho 渲染 template 输出时按 fenced code block 处理,不会触发 markdown 链接解析。但要小心 template 输出含 * _ 等可能被识别为 emphasis 的字符。

6. 用 stl template 想做 chart

template stl:
画一个柱状图:{...}      ← ❌ stl template 不渲染 chart

→ stl template 输出纯文本,没有图形渲染能力。要 chart 用 template vega-lite:(见 Interact + Vega-Lite)。

7. template 输出 markdown 但期待渲染

template stl:
**粗体** 和 *斜体*     ← ❌ 这些字符会作为字面文本输出,不渲染为粗体

→ template 默认输出纯文本,不再做 markdown 渲染。如果要 template 输出富文本,部分 reader 实现允许 template html: 或 template markdown:,但不通用——保持 plain text 最稳。


See also