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) - 常数:
pie
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
- Interact controls — 控件声明
- Computed — 派生值(避免 template 里写复杂表达式)
- Interact + Vega-Lite chart — chart template
- SVG scenes — svg template
- Shared state (namespace)
- Plain-text fallback principle