花卷实验室 · A2UI for Streaming AI

给流式 AI
加点儿界面感

来自花卷实验室——与 markdown 共存不冲突的 结构化组件 DSL。保留 markdown 单行可渲染能力,无侵害地扩展组件与主题; 混合渲染的同时保留高度设计的样式效果,降低模型输出的样式心智负担, 也大幅减少 token 消耗。

  • 意图事件交互
  • 组件白名单
  • 业务定制组件与主题
  • 标准 skill 约束 AI 输出
  • 花卷主题工具
HOT RECAP
林晚
盛夏夜名场面
48小时刷屏2026.07
01 DATA 先看数据
主榜最高
8位
在榜时长
11h+
48 小时
06/30到达
长沙起飞
07/01爆点
手怎么了 词条登榜
↑ 一段 zone-DSL 的真实渲染
装上 skill,你就不用再翻文档了 AI 会替你 输出 DSL · 接入平台 · 加组件 · 定制主题
POSITIONING

一种 A2UI 协议。

广义上,ZoneDSL 属于 A2UI(Agent-to-UI)这一类协议——让 agent / 模型的输出,直接变成结构化、可渲染的界面。它要解决的核心问题,和「让 AI 吐出结构化 UI」这件事是一致的:agent 产出 → 解析 → 组件树 → 界面

A2UI / WHAT

agent
产出即界面

A2UI 的本质是把模型输出映射成 UI。ZoneDSL 里,AI 只需吐出一段带 ::组件 的文本流,前端解析成组件树并渲染成卡片、图表、时间线。

A2UI / HOW

文本优先
而非协议优先

同类方案多走结构化 JSON / 协议下发。ZoneDSL 选了另一条路:文本优先、与 markdown 共生,最小侵入地扩展组件与主题,更贴合 AI 天然的文本输出习惯,也更省 token。

A2UI / EDGE

为流式
而生

面向 AI 流式吐字做了 streamingSafe 保护,属性未闭合前不更新——这正是把 A2UI 落到真实流式对话场景时最容易被忽略、却最关键的一环。

JSON / JSONL 协议 vs ZoneDSL · 五个关键维度
维度 结构化 JSON / JSONL 协议 ZoneDSL(文本优先)
Token 消耗 高——键名/引号/括号占 30-50% 字符 低——只写值,组件名用 :: 前缀标记
Schema 约束 硬——键漏一个 / 类型错一个,整段解析失败 软——未知组件静默丢弃,不闭合的属性跳过,组件始终在场
流式渲染 不友好——JSON 必须闭合才能 parse,中途都是无效状态 行级渐进——一行完整就渲染一行,streamingSafe 兜底半截值
与 markdown 共存 需要额外字段包装 markdown 段(如 {type:"md",content:"..."}) 原生共存——markdown 段照常写,zone 组件用 :: 顶格/围栏穿插
模型心智负担 需记住嵌套 schema、字段名、必填/选填、类型规则 只需记住组件名与几个属性,写法接近自然缩进的伪代码

结构化协议的强项是严格性,适合内部服务间调用;ZoneDSL 的强项是宽容性流式友好,适合直面用户的 AI 输出场景——两者互补,不是替代。

CAPABILITY

markdown 美化 + 结构化扩展。

对话式 AI 吐出的 markdown 又硬又干,缺卡片、缺图表、缺主题气质。 ZoneDSL 在 markdown 之上叠了一层可扩展的结构化 DSL, 加上一套可定制的主题作用域——同一份内容,切主题即变身。

01 / DSL

80+ 组件
5 层分组

primitive 原语 · structure 结构 · interactive 交互 · chart 图表 · preset 业务预设。从 text/tag 到 magazine-cover / era-timeline / data-board——一行 DSL 出成品卡。

02 / THEME

12 套主题
杂志系 + 接管系

杂志系 7 套作用于 zone 组件(editorial/literary/serious/ data/serene/warm/luxe)。markdown 接管系 5 套(purple/sky/ pop/sage/note)让普通 markdown 也整体变杂志视觉——不写组件也能出效果。

03 / STREAMING

流式
渲染保护

针对 AI 流式吐字场景做了 streamingSafe 保护: parser 只在属性完整闭合时更新 attrs,避免 bg=a → bg=accent 半截值导致视觉闪烁。组件始终在场, 细节逐帧稳定加入。

EXAMPLE

写 DSL,渲染页面 / 卡片。

左边是一段 ZoneDSL 源码,右边是它的渲染效果。 AI 只需要输出这样的文本流,前端自动解析成组件树。

ZoneDSL Source
// 一段科普问答:咖啡因怎么起效
::kicker "SCIENCE / 咖啡因 101"

::text size=hero "为什么
一杯咖啡
能让你**清醒**?"
::callout "咖啡因不是提供能量,它是「借了 4 小时的清醒」——通过阻断腺苷受体,让大脑以为自己还不困。" ::display "≈45 分钟" desc="血药浓度峰值到达时间" ::numbered-list "起效三步" item "入胃 15 分钟:小肠开始吸收咖啡因" item "血脑屏障:分子小,直接进大脑" item "占位腺苷受体:困意的化学信号被拦截" ::tip "半衰期约 5 小时——下午 3 点后喝,晚上就别想睡了。"
SCIENCE / 咖啡因 101
为什么
一杯咖啡
能让你清醒?
咖啡因不是提供能量,它是「借了 4 小时的清醒」——通过阻断腺苷受体,让大脑以为自己还不困。
≈45分钟
血药浓度峰值到达时间
起效三步
1入胃 15 分钟:小肠开始吸收咖啡因
2血脑屏障:分子小,直接进大脑
3占位腺苷受体:困意的化学信号被拦截
半衰期约 5 小时——下午 3 点后喝,晚上就别想睡了。
ZoneDSL Source
// 杂志式复盘 · 单日多小节
::magazine-cover tag="HOT RECAP" date="2026.07"
  title="演唱会\n**48 小时刷屏**"
  subtitle="从开票到收官"
  bg=light

::chapter "01" title="先看数据" category="DATA"

::data-board cols=2
  item "主榜最高" value="8 位"
  item "在榜时长" value="11h+"

::era-timeline "48 小时"
  item "D0" label="开票"
    desc="3 秒售罄,词条冲上热议"
  item "D1" label="爆点"
    desc="现场返场惊喜,视频过亿播放"
HOT RECAP
演唱会
48 小时刷屏
从开票到收官2026.07
01 DATA 先看数据
主榜最高
8 位
在榜时长
11h+
48 小时
D0开票
3 秒售罄,词条冲上热议
D1爆点
现场返场惊喜,视频过亿播放
ZoneDSL Source
// 前端候选人能力评估
::kicker "CANDIDATE / 一面结果"

::text size=title "L5 前端 · 综合评分"

::radar "六维评估"
  axis "工程" score=88
  axis "框架" score=76
  axis "性能" score=82
  axis "审美" score=92
  axis "协作" score=78
  axis "深度" score=70

::labeled-list "面试官备注"
  item "审美是最亮眼的加分项" label="92"
  item "深度略薄,可考虑二面加压" label="70"
  item "工程能力扎实,能独立带项目" label="88"

::callout "建议:通过一面,二面重点考察系统设计与深度。"
CANDIDATE / 一面结果
L5 前端 · 综合评分
六维评估
面试官备注
92审美是最亮眼的加分项
70深度略薄,可考虑二面加压
88工程能力扎实,能独立带项目
建议:通过一面,二面重点考察系统设计与深度。
ZoneDSL Source
// 综艺《花儿与少年》第 8 季 · 一个梳理
::magazine-cover tag="COMEDY VARIETY"
  title="**盛夏夜**\n姐姐们出发了"
  subtitle="南美三国 · 影后阵容"

::chapter "01" title="数据先声" category="HEAT"

::data-board cols=4
  item "热议" value="19"
  item "主榜" value="5"
  item "文娱" value="21"
  item "在榜" value="11h+"

::chapter "02" title="四位嘉宾" category="CAST"

::person-grid cols=2
  ::person-card name="大姐 林晚"
    desc="香港资深演员"
    avatar="https://..."
  ::person-card name="二姐 苏念"
    desc="天后级歌手"
    avatar="https://..."
  ::person-card name="三姐 周屿"
    desc="港片女神"
    avatar="https://..."
  ::person-card name="四姐 陈默"
    desc="金马影后"
    avatar="https://..."

::chapter "03" title="名场面" category="SCENES"

::scene-card icon="🎤" title="苏念开口就是华语乐坛"
  desc="车上即兴清唱《默》,弹幕全在刷鸡皮疙瘩。"
  tags="名场面,K 歌"

::scene-card icon="😂" title="陈默秒变段子手"
  desc="高原反应下依然抛梗不停,4 小时热议第 8 位。"
  tags="综艺感,爆点"
COMEDY VARIETY
盛夏夜
姐姐们出发了
南美三国 · 影后阵容
01 HEAT 数据先声
热议
19
主榜
5
文娱
21
在榜
11h+
02 CAST 四位嘉宾
大姐 林晚
香港资深演员
二姐 苏念
天后级歌手
三姐 周屿
港片女神
四姐 陈默
金马影后
03 SCENES 名场面
🎤
苏念开口就是华语乐坛
车上即兴清唱《默》,弹幕全在刷鸡皮疙瘩。
名场面K 歌
😂
陈默秒变段子手
高原反应下依然抛梗不停,4 小时热议第 8 位。
综艺感爆点
ZoneDSL Source
// 两款笔记本选购对比
::kicker "BUYING GUIDE / 2026"

::text size=title "14 寸轻办公,选谁?"

::compare
  a name="Air 14" tag="轻薄"
  b name="Pro 14" tag="性能"
  row label="重量" a="1.24kg" b="1.55kg"
  row label="续航" a="18h" b="22h"
  row label="价格" a="¥7999" b="¥13999"

::callout "结论:通勤 + 写文档选 Air;视频剪辑 + 编译大项目选 Pro。"
BUYING GUIDE / 2026
14 寸轻办公,选谁?
Air 14
轻薄
VS
Pro 14
性能
1.24kg重量1.55kg
18h续航22h
¥7999价格¥13999
结论:通勤 + 写文档选 Air;视频剪辑 + 编译大项目选 Pro。
ZoneDSL Source · 纯 markdown
// 不写任何 zone 组件,只顶格声明主题
::theme note

# 秋日随笔

*十月三日,晴,微风*

推开窗,秋阳斜进书桌,把昨夜没写完的稿纸镀了一层暖色。
茶凉了两次,想法始终没落地。

## 三件小事

- 楼下的桂花开了,风一吹整条街都是甜的
- 图书馆借了本《人类群星闪耀时》,一口气读了三章
- 傍晚跑了 5 公里,汗透了衣服却心情很好

> 「秋天是慢下来的季节。」

## 明天想做

1. 把稿子改完,发给编辑
2. 去菜市场买一次真正的新鲜青菜
3. 早睡

秋日随笔

十月三日,晴,微风

推开窗,秋阳斜进书桌,把昨夜没写完的稿纸镀了一层暖色。茶凉了两次,想法始终没落地。

三件小事

  • 楼下的桂花开了,风一吹整条街都是甜的
  • 图书馆借了本《人类群星闪耀时》,一口气读了三章
  • 傍晚跑了 5 公里,汗透了衣服却心情很好
「秋天是慢下来的季节。」

明天想做

  1. 把稿子改完,发给编辑
  2. 去菜市场买一次真正的新鲜青菜
  3. 早睡
ZoneDSL Source · 用户可点
// 一段可交互的追问 + 反馈场景
::callout "AI: 上面梳理完了,还想深入哪个方向?"

::checkbox-group "我感兴趣的角度"
  checkbox "数据背后的原因"
  checkbox "人物关系脉络"
  checkbox "横向对比历史"

::radio-group "回答长度偏好"
  radio "简短要点(≤ 200 字)" checked=true
  radio "完整长文(≥ 800 字)"

::row align=center
  ::button "追问看点"
    intent=followup
    value="这个话题最出圈的三个瞬间"
  ::button "换个话题"
    variant=outline
    intent=send-message
    value="聊点别的"

::quiz "顺手做个小调查"
  option "我是路人,来看热闹"
  option "我是原生粉丝"
  option "我做内容 / 数据研究"
AI: 上面梳理完了,还想深入哪个方向?
我感兴趣的角度
回答长度偏好
顺手做个小调查
↳ 事件冒泡到 onZoneAction(intent, value)
点击上面任意按钮 / 选项,这里会显示派发到业务侧的 intent + value
CROSS PLATFORM

DSL 一份,组件库多套。

当前实现是 ZoneDSL 语法体系的第一个落地。同一份 DSL 也可以在其他平台上构建自己的组件库——DSL 是接口,组件是实现,两者解耦。

CURRENT

当前实现
WeChat Mini Program

当前发布。基于 towxml + 自研 zone-DSL parser + zone-node WeChat 组件。已在真实 AI Chat 小程序生产环境使用。

ROADMAP

Web 版
H5 / React / Vue

规划中。同一份 DSL parser 可复用,只需替换组件层 为 React/Vue 组件。适合浏览器端 AI 助手、内容 CMS、报表工具。

ROADMAP

跨端 / 客户端
RN / Flutter / iOS

可复刻。DSL 是纯文本约定,任何平台都能实现自己的 renderer。花卷实验室后续会陆续放出参考实现,社区也欢迎贡献。

IN PRODUCTION

已有
真实商业产品
上线运行

从「事件复盘 / 议题解码 / 人物八卦 / 数据报告 / 科普长文」 到「多轮流式播放 / 多主题横向对比」——20+ demo 会话真实覆盖, 经受生产环境的流式响应、复杂布局与多主题一致性的实际考验。

快速上手

ZoneDSL 的核心使用者是 AI——业务只需要让 agent 会输出、 前端能渲染即可。四步走通: 让 AI 学会 skill(必做) → 安装到项目 → 修引用路径 → 实现分发器(可选)。

Note · 当前落地平台
当前 Beta 阶段以微信小程序为例讲解接入(towxml 集成、 zone-node 组件、分包目录结构)。ZoneDSL 的 parser 是平台无关的纯 JS (无 DOM 依赖),将来会补上 Web / React Native / Flutter 等端的参考实现, DSL 与组件规范保持一致。

核心链路

ZoneDSL 的工作流水线本质上是四步:

  1. AI 后端流式吐出一段 markdown + zone-DSL 混排文本
  2. 前端 agentChat 页把 content 拿到,交给 buildAst()
  3. towxml/index.js 里的 extractZoneBlocks() 先拆出 zone 块, markdown 走 towxml 原有解析,zone 块交给 zone-dsl/toWxNodes.js 转成组件节点树
  4. 页面渲染层遇到 item.isZone 派发给统一的 <zone-node> 组件, wxml 里 60+ 个 wx:elif 分支各自渲染成对应 zone 组件
TL;DR
你只需要产出 DSL 文本,剩下的解析、组件派发、主题作用域、 流式安全全部由 ZoneDSL 引擎在小程序端搞定。

Hello ZoneDSL

最短的一个 zone 组件:

::text "你好, ZoneDSL"

渲染出来就是一段正文文字。::<组件名> 就是 ZoneDSL 的核心语法。

纯 markdown 用法

ZoneDSL 不排斥 markdown——你完全可以只写 markdown,ZoneDSL 引擎会照常 把它交给 towxml(此处以小程序平台为例) 渲染,得到跟你熟悉的 markdown 一样的结果:

# 一级标题

正文段落,可以用 **加粗**、*斜体*、==高亮==、`inline code`。

- 列表项 1
- 列表项 2

| 表头 | 数值 |
| --- | --- |
| A | 1 |

加入 zone 组件

markdown 里穿插 :: 组件(前后各空一行),得到杂志式结构化输出:

# 今日热议三看点

今天有三条线索都值得看。

::magazine-cover tag="HOT SPOTS · 07.03"
  title="今日三焦点"
  bg=light

## 焦点一: 盛夏夜

正文段落...

::numbered-list "看点在哪"
  item "四姐气场碰撞"
  item "南美世界杯氛围"
规则
顶格 :: 前后必须各留一行空行,让 towxml 识别 zone 块边界。子项用 2 空格缩进,不能用 Tab 或 4 空格。

切换主题

ZoneDSL 内置 12 套主题——7 套杂志系作用于 zone 组件, 5 套 markdown 接管系让纯 markdown 也整体变杂志视觉。

不写 ::theme 就是默认 editorial 暖橙风。要切主题:

::theme purple

# 我的备忘录

正文段落——现在整块内容会变成紫底黄胶囊白卡片的杂志视觉。

可用主题:editorial / literary / serious / data / serene / warm / luxe / purple / sky / pop / sage / note。详见 组件全览 · 12 主题

1. 让 AI 学会输出 ZoneDSL 必做

ZoneDSL 的核心使用者是 AI——你的用户几乎不需要手写 DSL,而是让 AI 后端(Claude / GPT / 自研 agent)在流式输出里自动生成。所以第一件事是让 AI 学会

推荐加载 zonedsl skill——一份 20KB 结构化提示词,写清楚了「什么时候用 / 怎么写 / 避坑清单 / 6 个模板 / 62 个组件目录」。agent 加载后会按规范输出,不用逐句 few-shot。

📦
zonedsl-skill.zip
v2.9.0 · SKILL.md + 5 CATALOG · Claude Code / Codex / OpenClaw / Agent SDK 兼容
解压后含 zonedsl/SKILL.md + CATALOG-{PRIMITIVE,STRUCTURE,INTERACTIVE,CHART,PRESET}.md, 放到 Claude Code 的 ~/.claude/skills/ 目录即可自动被 agent 发现和调用。
下载 skill →

方式 A · Claude Code(推荐)

# 下载并解压到 skills 目录
curl -O https://<你的域名>/assets/zonedsl-skill.zip
unzip zonedsl-skill.zip -d ~/.claude/skills/

# 目录结构:
~/.claude/skills/zonedsl/
├── SKILL.md              # agent 加载时读的主文件
├── CATALOG-PRIMITIVE.md  # 按需查的组件字典
├── CATALOG-STRUCTURE.md
├── CATALOG-INTERACTIVE.md
├── CATALOG-CHART.md
└── CATALOG-PRESET.md

# Claude Code 会自动识别 skill,当用户对话触发 description 条件时激活

方式 B · Agent SDK / 自定义 agent

不用 Claude Code 的话,把 SKILL.md 内容作为 system prompt / 工具说明加载即可——skill 本质是结构化提示词,兼容任何 markdown 的 agent 框架。

// OpenAI Function Calling / Anthropic Tool Use 都可以直接注入
const systemPrompt = fs.readFileSync('./skills/zonedsl/SKILL.md', 'utf-8')
const response = await anthropic.messages.create({
  system: systemPrompt,
  // ...
})
生产建议
Agent 侧只加载 SKILL.md(20 KB)就够了。5 个 CATALOG 是**按需引用**的组件字典, 放在同目录 agent 需要写具体组件时会自己去查。用 skill + 12 主题 + 意图白名单, AI 输出 zone-DSL 就像输出 markdown 一样自然。

2. 安装到你的项目

AI 学会输出后,前端需要能渲染。ZoneDSL 已拆成 npm 包:@zonedsl/core(parser) + @zonedsl/web(Web 渲染器) + @zonedsl/wechat(小程序运行时,生产验证) + @zonedsl/skill(AI 规范)。

装上开发者 skill,你不用翻文档,AI 就能替你把接入和二次开发都做了。 装完直接说「帮我把 zonedsl 接入我这个小程序」/「我要加个新组件叫 xxx」/「我要在 Web 端复刻一份」,AI 会自动查 4 处登记规范、层归属、主题变量、intent 白名单——你只用负责决策和 review 代码。

🛠️
zonedsl-dev-skill.zip
v2.9.0 · 接入 / 扩展 / 跨平台 · Claude Code / Codex / OpenClaw / Cursor / Copilot 兼容
让 AI 直接帮你接入、加组件、跨平台适配——你不用翻文档。 装到 Claude Code / Cursor / 自研 agent 后,平常向 AI 提问「加个新组件叫 xxx」/「接入到 X 平台」, AI 会自动查 4 处登记流程、层归属、主题变量、intent 白名单,直接产出规范代码。
下载 dev skill →

Web 安装(v1 已就绪)

npm i @zonedsl/core @zonedsl/web,或直接 <script src> 引 UMD:

<!-- CDN -->
<script src="https://unpkg.com/@zonedsl/core/dist/parser.umd.js"></script>
<script src="https://unpkg.com/@zonedsl/web/dist/zonedsl-web.umd.js"></script>
<div id="out"></div>
<script>
  ZonePlayground.mount(document.getElementById('out'), '::callout "Hello"')
</script>

流式渲染传 { streaming: true },骨架传 { skeleton: true }。注册自定义组件用 ZonePlayground.register('my-comp', fn)(parser 零改动,见 协议 §10)。

WeChat 小程序

@zonedsl/wechat(zone-node 派发组件 + towxml + 12 主题,生产验证):

// index.json
{
  "usingComponents": {
    "towxml": "@zonedsl/wechat/towxml/towxml",
    "zone-node": "@zonedsl/wechat/zone-node/index"
  }
}
// index.js
const { toAst } = require('@zonedsl/wechat')
const ast = toAst(content, { streamingSafe: true })
// <towxml nodes="{{ast}}" bindzoneaction="onZoneAction" />

3. 实现 zone-action 分发器

DSL 里 ::button intent=xxx value=yyy 点击会触发 intent,业务方在分发器里实现具体跳转(平台无关,详见 @zonedsl/core/INTENTS.md):

// Web
handleZoneAction(intent, value) {
  switch (intent) {
    case 'search': location.href = `/search?q=${value}`; break
    case 'copy': navigator.clipboard.writeText(value); break
    case 'followup': /* 填输入框 */ break
    // ... 其他 intent 按你项目实现
  }
}
// WeChat: onZoneAction(e) { const {intent,value}=e.detail; ... }
备注
intent 是一种点击意图机制,以下 8 个是常用示例(followup / send-message / search / open-topic / open-tab / open-url / copy / share),宿主可自行扩展平台专属 intent(如电商 open-cart)。详见 @zonedsl/core/INTENTS.md。未识别的 intent 静默降级为纯样式按钮,不会报错。

语法参考

ZoneDSL 一共只有 4 个语法要素:组件声明、属性、子节点、行内高亮。 本页把它们全部列清楚,同时说明和 markdown 的混排方式。

组件声明

顶格两个冒号加组件名,一行一个:

::text "这是一段文字"
::divider
::magazine-cover title="标题"

组件名会在@zonedsl/wechat/toWxNodes.jsCOMPONENT_REGISTRY 里查找;查不到默认静默丢弃, 不会渲染出「未支持」占位。

属性 attrs

组件名后面跟属性,格式 key=value,值有引号和裸值两种:

// 引号包裹的字符串
::magazine-cover title="两天刷屏" subtitle="48 小时高光时刻"

// 裸值(单词/数字,无空格)
::grid cols=3 gap=md

// flag 属性(无 = 号,值为 true)
::radio "选项 A" selected
值内引号转义
属性值里如果要出现英文双引号,用 \" 转义,或者用中文引号 「」 「」代替。
换行用 \n(在模板字符串里写 \\n)。

子节点

2 空格缩进表示子节点:

::numbered-list "看点在哪"
  item "四姐气场碰撞"
  item "南美世界杯氛围"
  item "新老代际对话"

::data-board cols=4
  item "主榜最高" value="8位"
  item "在榜时长" value="11h+"

子关键字白名单:item / row / field / series / option / step / radio。 不在白名单里的裸词会被当纯文本处理。

main 快捷值

组件名紧跟一个字符串,等价于 main="..."(约定就是主标题/主内容):

// 这两种写法等价:
::card "Q4 核心指标"
::card main="Q4 核心指标"
⚠️ 别重复写
写了 main 就别再写 title:::card "Q4" title="Q4 核心" 是重复。 引号紧跟组件名就是 main,大部分组件会自动把 main 用作 title。

markdown 与 zone 混排

ZoneDSL 支持三种混排:

A · 纯 markdown

如果只需要标题+段落+列表,直接写 markdown。zone-DSL 引擎照常识别。

B · 顶格 :: 混排(推荐 95% 场景)

markdown 正文中穿插顶格 ::,前后各留一行空行:

# 今日热点

三条线索都值得看。

::magazine-cover tag="HOT SPOTS" title="今日三焦点"

## 焦点一: 盛夏夜

正文继续...

C · 围栏 ```zone

```zone ... ``` 显式围出一段 zone,parser 只处理围栏内的部分:

```zone
::magazine-cover
  tag="HOT RECAP" title="**48小时刷屏**"

::chapter "01" title="先看数据"
::data-board cols=2
  item "主榜最高" value="8位"
  item "在榜时长" value="11h+"
```

markdown 段落继续,不会被 zone 影响。
两种边界的等价性

B · 顶格 :: 混排C · ```zone 围栏 在渲染结果上完全等价 —— parser 会把两种边界都替换成同一个 zone-dsl-placeholder 占位,再统一走 zone-DSL 引擎。

选哪种取决于场景:AI 流式吐字用 B(无围栏,吐一行渲一行体验最好); 正式文档 / Web / 长内容 用 C(边界最清晰,不怕缩进错位)。

B vs C · 什么时候用哪个

B · 顶格 ::C · ```zone 围栏
边界隐式(空行止)显式(围栏字符)
AI 流式吐字✅ 首选 —— 吐一行渲一行需吐完首行 ```zone
长内容 / Web混排时得小心空行✅ 首选 —— 边界最稳
主题声明用顶格 ::theme xxx可用围栏 meta:```zone theme=xxx
嵌套 markdownzone 段前后各留空行围栏外的 markdown 完全隔离

围栏 meta 传主题(可选)

用围栏时可以直接在开栏行写 theme=xxx,parser 会把它当作块首 ::theme 处理:

```zone theme=literary
::magazine-cover title="梅雨季"
::chapter ...
```

等价于:

```zone
::theme literary
::magazine-cover title="梅雨季"
::chapter ...
```

行内高亮(title/subtitle 通用)

ZoneDSL 在标题/副标题里支持三档行内高亮,和 markdown 语法一致:

语法视觉用途
**text** 亮金黄块 + 深炭字 主强调,视觉重量拉满
~~text~~ 橙色字 + 底部半高浅金橙块 次强调,马克笔效果
==text== title:深炭字 + 橙下划线
subtitle:橙色加粗字
轻强调

主题声明

三种入口都可以,一个 zone 块只需要写一次:

// 入口 A:magazine-cover 属性
::magazine-cover theme=literary title="..."

// 入口 B:顶格伪组件(推荐用于 markdown 接管系主题)
::theme purple

// 入口 C:围栏 meta
```zone theme=data
::chapter ...
```

三种声明等价,优先级 A > C > B。不写就是默认 editorial

意图与交互

ZoneDSL 有一套意图白名单让 AI 输出的按钮 / 表单能真的触发业务动作,而不是只做视觉。核心是 ::button intent=xxx value=yyy 和其它交互组件 (checkbox / radio / quiz / select),用户点击时事件逐级冒泡到宿主的 onZoneAction 分发器。

11 个意图白名单

AI 只能从这 11 个 intent 里选,业务方在 onZoneAction 里挑选性实现——未实现 intent 静默降级为纯样式按钮,不会误触:

分组Intent做什么value 示例
会话操作followup把 value 作为新问题追问 AI"这个话题最出圈的三个瞬间"
send-message发一条消息到会话"聊点别的"
内容跳转search跳搜索页 / 联想"示例关键词"
open-topic打开话题页"示例话题"
open-tab切换主 tab"home"
open-url打开链接(宿主校验白名单)"https://example.com"
通用操作copy复制文本到剪贴板"要复制的内容"
share拉起分享面板分享内容 / URL
暂未列入(宿主自管)login拉起登录流程
open-my打开"我"页 / 个人中心

完整规范见 @zonedsl/core/INTENTS.md。平台专属 intent(如电商 open-cart)由宿主自管,不进通用白名单。

事件冒泡链

用户点击一个组件后,事件按下面的路径逐级传上去,最终到达业务方的分发器:

// 组件层                → 消息层                → 页面层
zone-node.onButtonAction   →  message-item.onZoneAction  →  agentChat/index.js.onZoneAction(e)

// 到达页面层时 e.detail 结构固定为:
{
  intent: 'followup',      // 白名单里的 intent
  value:  '具体参数',       // intent 的 payload
  source: 'button',          // 触发组件类型
  ext:    { ... }              // 可选扩展字段(如 checkbox-group 的 items 数组)
}

业务侧分发器模板

onZoneAction(e) {
  const { intent, value, source } = e.detail
  switch (intent) {
    case 'followup':
      // 把 value 塞进输入框,自动发一条追问
      this.sendFollowup(value)
      break
    case 'search':
      wx.navigateTo({ url: `/pages/search/index?q=${encodeURIComponent(value)}` })
      break
    case 'copy':
      wx.setClipboardData({ data: value })
      break
    default:
      // 未实现的 intent 静默忽略(不会报错,组件降级为纯样式)
      console.log('[zone] unhandled intent', intent, value)
  }
}

其它交互组件

除了 ::button intent=...,还有一批完全独立于 intent 的交互组件——它们的 state 由 zone-node 内部维护,不需要业务侧处理:

  • ::tabs / ::accordion —— 展开/收起,组件内部 state
  • ::checkbox / ::checkbox-group —— 多选,change 事件可冒泡
  • ::radio / ::radio-group —— 单选,同组互斥
  • ::select / ::textarea —— 表单输入
  • ::quiz —— 单选题,点击选项高亮

需要把 checkbox/radio 的结果发给业务,再套一个 ::button intent=followup value="...",由用户点确认按钮触发。

常见错误

  1. 顶格 :: 前后不留空行 —— towxml 用空行作为 zone 块的边界,紧贴段落会解析错乱
  2. 子项用 Tab 或 4 空格缩进 —— parser 按缩进层级识别子节点,必须用 2 空格
  3. 属性值里嵌英文双引号 —— 用 \" 转义或改中文引号
  4. attrs 里直接按回车 —— parser 按行 tokenize,attrs 内真实换行会截断组件,用 \\n 表示换行
  5. 写不存在的组件名 —— 默认静默丢弃,不会报错,但你的组件不会出现。请参考 组件全览
  6. 网格深嵌套 3 层以上 —— row/col/grid 深嵌小程序会卡顿,建议 2 层内

组件全览

全部 62 个组件,按 5 层组织。每个都带**语法示例 + 微缩预览 + 属性说明**。 底部有 12 主题声明语法专章。

Note
组件预览仅供示意——本页微缩效果由 web CSS 复刻实现,与小程序端实际渲染的 视觉细节(圆角、间距、字重、动效等)会略有差异。以实际渲染效果为准

1 · primitive 原语层 18 个

无状态、无场景的最小视觉单元。任何主题都能用。

::text文本v1.0
::text "这是一段正文" ::text size=hero "大字标题" ::text size=title align=center "章节标题"
大字标题
章节标题
这是一段正文
main 文本内容 · size xs/sm/base/lg/xl/hero/title,默认 base · align left/center,默认 left
::tag标签v1.0
::tag "热议" ::tag color=success "稳定"
热议 稳定
main 标签文字 · color accent/primary/success/warning/danger/info/neutral
::divider分隔线v1.0
::divider ::divider thick=true
default
thick=true
thick 是否粗线 · gap 上下间距
::badge徽标v1.0
::badge "NEW" ::badge color=success "1"
NEW 1
main 徽标文字 · color 颜色语义
::pill胶囊v1.0
::pill "限时优惠" ::pill color=warning "待处理"
限时优惠 待处理
main 文字 · color 颜色语义
::icon图标v1.0
::icon "🔥" ::icon size=lg "✨"
🔥
main emoji 或图标名 · size sm/md/lg
::avatar头像v1.0
::avatar avatar="https://..." size="lg" ::avatar avatar="https://..." ::avatar name="丁" size="sm"
name 名字首字 fallback · avatar 图片 URL · size xs/sm/md/lg/xl
::quote引用块v1.0
::quote "衣裳润润的,书页软软的" cite="江南随笔"
衣裳润润的,书页软软的
— 江南随笔
main 引用文字 · cite 出处
::kicker小标签v1.0
::kicker "TODAY · 2026.07" ::kicker align=center "STREAMING · LIVE"
TODAY · 2026.07
STREAMING · LIVE
main 顶部小标签文字 · align 对齐方式
::trend趋势胶囊v1.0
::trend "↑18%" dir=up ::trend "↓3%" dir=down
↑ 18% ↓ 3%
main 趋势文字 · dir up/down/flat
::tip提示v1.0
::tip "💡 早上晒 15 分钟太阳"
💡 早上晒 15 分钟太阳
main 提示文字(通常以 emoji 开头)
::callout重点卡片v1.0
::callout title="核心发现" "阳光能显著降低皮质醇水平。"
核心发现
阳光能显著降低皮质醇水平。
main 正文 · title 顶部小标签 · type info/accent/success/warning/danger
::display巨字数据v1.0
::display align=center "4258.77" desc="美元 / 盎司"
4258.77
美元 / 盎司
main 主数字 · desc 描述 · align 对齐
::progress进度条v1.0
::progress value=72 label="完成度"
完成度72%
value 0-100 · label 左侧文字 · color 填充色
::alert警示条v1.0
::alert type=success "操作成功" ::alert type=warning "请注意"
操作成功
请注意
main 文字 · type info/success/warn/danger
::metric指标数字v1.0
::metric "1240 万" desc="Q4 总营收" trend="↑18.5%" color=accent
1240 万
Q4 总营收
↑18.5%
main 数值 · desc 描述 · trend 趋势 · color 数值染色
::image图片v1.0
::image url="https://..." caption="江南梅雨"
图片占位
url 图片地址 · caption 图注 · mode 显示模式
::spacer留白v2.3
::spacer h=md ::spacer h=48 // 别名 ::gap
h = xs / sm / md / lg / xl 或 rpx 值
h xs/sm/md/lg/xl(8/16/32/60/96 rpx) 或精确 rpx 值(h=24) · 别名 ::gap

2 · structure 结构层 16 个

通用容器与布局。任何主题都能用。

::card卡片容器v1.0
::card "Q4 核心指标" ::metric "1240 万" desc="营收"
Q4 核心指标
卡片内嵌任意子组件
main 卡片标题 · variant default/outline/highlight/ghost/elevated
::section章节容器v1.0
::section "渠道拆解" ::text "..."
渠道拆解
章节正文内容
main 章节标题
::row / ::col行列布局v1.0
::row ::col span=6 ::metric "A" ::col span=6 ::metric "B"
列 A · span=6
列 B · span=6
col.span 6-12,配合父级 row 布局 · align center(v2.9,让子组件在容器内居中)
::center居中容器v2.9
::center ::radar "六维评估" axis "工程" score=88
居中的组件
宽度 100% · 内容居中
零参数容器,双向 flex 居中,宽度 100%。适合让 chart / hero 标题 / 空态提示自然居中,不用套 section/card。
::grid网格布局v1.0
::grid cols=3 gap=md ::metric "A" ::metric "B" ::metric "C"
A
B
C
cols 1-4,默认 2 · gap xs/sm/md/lg
::list无序列表v1.0
::list "看点在哪" item "四姐气场碰撞" item "南美世界杯氛围"
看点在哪
四姐气场碰撞
南美世界杯氛围
main 列表标题 · item 子项
::numbered-list编号列表v1.5
::numbered-list "步骤" item "分析内容" item "选择组件" item "填充数据"
步骤
1分析内容
2选择组件
3填充数据
别名 ::ol · 数字圆点自动编号
::labeled-list左标签列表v1.5
::labeled-list "关键指标" item "营收" label="Q4" item "净利" label="YOY"
关键指标
Q4营收
YOY净利
item 支持 label(左) + main(右)
::table表格v1.0
::table field "渠道" field "占比" row cells=电商,45% row cells=私域,30%
渠道占比
电商45%
私域30%
field 表头字段 · row.cells 单元格逗号分隔
::timeline时间线v1.0
::timeline item "到达长沙" when="06/30 08:40" tag="到达" item "手怎么了 词条登榜" when="07/01 23:19" tag="爆点" highlight item "表演我猜杀你" when="07/02 07:54" tag="名场面"
06/30 08:40到达
到达长沙
07/01 23:19爆点
手怎么了 词条登榜
07/02 07:54名场面
表演我猜杀你
item 支持 when(时间) / tag(小标签) / highlight
::gallery图片集v1.0
::gallery cols=3 ::image url="..." ::image url="..."
cols 1-3 · 子项为 image
::hscroll横滑容器v1.0
::hscroll "标题" ::card "A" ::card "B"
卡片 A
卡片 B
卡片 C
别名 ::scroller · 横向滚动展示
::swiper轮播v1.0
::swiper autoplay=true ::image url="..." ::image url="..."
Slide 1
别名 ::carousel · autoplay / dots / circular
::chapter杂志分栏v1.0
::chapter "01" title="先看数据" category="DATA"
01
DATA
先看数据
main 编号 · title 标题 · subtitle 副标 · category 类别(有则走 magazine 变体) · variant default/magazine
::divider-fancy装饰分隔线v1.5
::divider-fancy "看点操作" ::divider-fancy "章节" prefix="▸"
// 看点操作
别名 ::section-mark · main 文字 · prefix 前缀符号(默认 //)
::form表单容器v1.0
::form "用户信息" ::textarea placeholder="..." ::radio-group
用户信息
性别
留言
表单包裹容器 · 子组件为 textarea/radio-group/checkbox-group/select/button 等

3 · interactive 交互层 13 个

可点击、可切换、可提交。zone-node data 里维护 state。

::tabs标签页v1.0
::tabs item "概览" item "明细" item "图表"
概览
明细
图表
item 子项
::accordion折叠面板v1.0
::accordion item "什么是 ZoneDSL?" desc="一种 DSL..."
什么是 ZoneDSL?
如何使用?
item 支持 label/desc
::checkbox复选框v1.0
::checkbox "同意条款" checked
同意条款
main 文字 · checked 初始选中
::checkbox-group多选组v2.8
::checkbox-group "兴趣爱好" checkbox "阅读" checked checkbox "运动" checkbox "音乐" checked
兴趣爱好
阅读 运动 音乐
同组多选 + 标题 · 子 checkbox 支持 checked
::radio单选按钮v1.0
::radio "男" selected
main 文字 · selected 初始选中
::radio-group单选组v1.0
::radio-group "性别" radio "男" selected radio "女"
性别
同组单选互斥 · 子 radio 支持 selected
::select下拉选择v1.0
::select "城市" options=北京,上海,广州
北京
main 默认值/占位 · options 逗号分隔 · 使用小程序原生 picker
::textarea多行输入v1.0
::textarea placeholder="请输入..."
请输入...
placeholder 占位符 · maxlength 最大长度
::quiz选择题v1.0
::quiz "你觉得哪个正确?" option "A. 选项 1" option "B. 选项 2" option "C. 选项 3"
你觉得哪个正确?
A选项 1
B选项 2
C选项 3
main 题目 · option 子项 · answer 正确答案索引
::button按钮v1.0 · v2.0 intent
::button "追问看点" variant=primary intent=followup value="还有哪些看点?"
main 按钮文字 · variant primary/outline/ghost/danger/success · intent 11 白名单意图 · value intent 参数 · size sm/md/lg
::steps / ::step步骤引导v1.0
::steps layout=horizontal step "登录" step "检索" step "导出"
1
登录
2
检索
3
导出
layout horizontal/vertical · step 支持 label/desc
::stairs阶梯v1.0
::stairs step "起步阶段" step "发展阶段" step "成熟阶段"
01起步
02发展
03成熟
阶段感更强的编号列表,标注每步 label
::mechanism机制说明v1.0
::mechanism "降压机制" step "感知光照" step "分泌激素"
感知光照
分泌激素
血压下降
用于流程解释,step 按顺序连接

4 · chart 图表层 8 个

基于 echarts,数据以逗号分隔字符串传入,前端自动构建 option。

::line折线图v1.0
::line "营收趋势" labels=Q1,Q2,Q3,Q4 data=820,1050,1180,1240 unit=
labels / data 逗号分隔 · area 面积图 · smooth 平滑 · unit 单位
::bar柱状图v1.0
::bar "周销量" labels=iPhone,Mac,iPad,Watch data=12000,8500,6200,4300
labels / data · horizontal 横向柱状
::pie饼图v1.0
::pie "占比" labels=电商,私域,线下 data=45,30,25 donut
donut 环形 · unit % · labels / data
::sparkline迷你走势v1.0
::sparkline data=10,15,8,20,25,18,30
紧凑走势,不带坐标轴 · 常嵌在 metric 里
::radar雷达图v1.0
::radar "能力评估" indicator=销售,营销,产品,技术 data=80,70,90,85
indicator 维度 · data
::ring环形进度v1.0
::ring value=72 title="完成度"
value 0-100 · title 中心文字 · desc 底部说明
::rank排行榜v1.0
::rank "TOP 4" item "iPhone" value=3200 item "Mac" value=2100 item "iPad" value=1400 item "Watch" value=860
TOP 4
1
iPhone3200
2
Mac2100
3
iPad1400
4
Watch860
别名 ::ranking · 前 3 自动金银铜色
::compare对比v1.0
::compare a="Vision Pro" b="Quest 3" a-value=3499 b-value=499
$3499
Vision Pro
$499
Quest 3
两方对比 · a/b 标签 · a-value/b-value 数值

5 · preset 业务预设 18 个

强场景绑定的成品卡——一行 DSL 出效果。杂志内容首选。

::magazine-cover杂志封面头v1.5
::magazine-cover tag="HOT RECAP" title="林晚\n**盛夏夜名场面**" subtitle="48小时刷屏" stats="19 条热议,11h+ 最长" bg=light
HOT RECAP · 2026.07.01
林晚
盛夏夜名场面
48小时刷屏
别名 ::cover · tag/date · title(行内高亮+\n) · subtitle · footnote · badge · stats 逗号分隔 · bg light(默认,v2.8) / accent / warm / dark · theme 主题声明入口
::city-card城市行程卡v1.5
::city-card num="01" country="意大利" city="米兰" en="MILANO" date="6.19 — 6.21" color=purple
CITY 01 · 意大利
米兰
MILANO
别名 ::itinerary-card · color purple/red/green/blue/pink/accent · item 支持 tag/desc · tags 底部话题
::person-grid人物阵容v1.5
::person-grid cols=2 ::person-card name="林晚" ::person-card name="苏念"
林晚
苏念
cols 1-4 · 子项为 person-card
::person-card人物卡v1.5
::person-card name="林晚" desc="香港资深演员" avatar="https://..."
林晚
香港资深演员
别名 ::person · name(必填) · desc · avatar · 无 avatar 时首字 fallback
::scene-card名场面卡v1.5
::scene-card icon="😂" title="手怎么了" desc="7 月 1 日晚上榜" rank="峰值 6"
😂名场面 · 峰值 6
手怎么了
7 月 1 日晚上榜第 13 位
别名 ::moment-card · icon emoji · title/desc · badge(顶部) · rank(峰值) · tags
::glyph-compare字词对比v1.5
::glyph-compare "名字两张脸" item "䔍" label="古字" item "甯" label="艺名"
古字
本名·古字
艺名
通用字
别名 ::character-compare · 单外框 + 顶部 tab · item 支持 label/desc
::statement声明卡v1.5
::statement title="一个美丽的误会" author="苏念" time="2026.06.25" ::text "..."
一个美丽的误会
「钧甯」二字,藏着父母对我人生的深深寄望...
苏念 · 2026.06.25
title · author · time · source · 内嵌 text 段落
::editorial-hero编辑体大标v1.5
::editorial-hero kicker="THE WEEK" title="这不是一个人的\n**是一群人的化学反应**" bg=warm
THE WEEK
一群人的
化学反应
4 大名场面 · 6 成互动梗
kicker · title(行内高亮+\n) · subtitle · stats · bg accent/warm/dark · align
::editorial-pullquote大字引言v1.5
::editorial-pullquote "衣裳润润的,书页软软的。" cite="江南随笔"
" 衣裳润润的,书页软软的。 "
— 江南随笔
米色底 + 橙左条 + 衬线大字 · cite 出处
::editorial-summaryTL;DR 摘要v1.5
::editorial-summary title="TL;DR" "金价短期承压,4200 为关键支撑。"
TL;DR
金价短期承压,4200 为关键支撑。
title 顶部小标 · main 摘要正文
::editorial-stat编辑体数字v1.5
::editorial-stat "10M+" desc="全球活跃用户" trend="↑34%"
10M+
全球活跃用户
↑34%
main 巨字 · desc · trend
::editorial-image编辑体图片v1.5
::editorial-image url="https://..." caption="创新引领未来"
— 创新引领未来
url · caption · search(点击搜索关键词)
::fact-bar深色事实条v1.5
::fact-bar item "场地" value="麦迪逊广场" item "宾客" value="约 1100 人"
场地
麦迪逊
宾客
1100 人
深炭底 + 横向键值对 · item 支持 label/value
::data-board数据面板v1.5
::data-board cols=2 item "主榜最高" value="8 位" item "在榜时长" value="11h+"
热议
8 位
主榜最高
时长
11h+
在榜时长
cols 1-4 · layout grid(默认) / row(label 左 value 右,适合超 8 字符值)
::step-block米色步骤块v1.5
::step-block item "分析内容" label="Step 1" item "选择组件" label="Step 2"
STEP 1 分析内容
STEP 2 选择组件
别名 ::steps-block · 米色底 + 左 label 右描述 · literary 主题主用
::icon-gridemoji 网格v1.5
::icon-grid cols=4 item "晒太阳" icon="☀️" item "睡眠" icon="🌙"
☀️
晒太阳
🌙
睡眠
🫁
深呼吸
🏃
运动
别名 ::tip-grid · cols 1-4 · item 支持 icon/desc
::era-timeline历史时间条v2.1
::era-timeline "极端年份" item "1954" label="百年一遇" item "1998" label="二度梅" item "2020" label="超长梅"
1954
百年一遇
长江超警戒
1998
二度梅
29 省受灾
2020
超长梅
60 天不停
别名 ::history-strip · layout ≤3 张自动 grid · 4+ 张自动 scroll(可显式覆盖)
::media-card图片+叠加标题v2.1
::media-card url="https://..." tag="TOP STORY" title="盛夏夜 开录" overlay=gradient
TOP STORY
盛夏夜 北京开录
7 月 3 日 · 首都机场
url · tag(左上小胶囊) · title/subtitle · height · align top/center/bottom · overlay gradient/solid/none

主题声明语法

三种入口等价,一个 zone 块只需要声明一次。优先级 A > C > B。不写就走默认 editorial

入口 A · magazine-cover 属性(推荐 95% 场景)

杂志封面自带 theme 属性,整块内容继承该主题:

::magazine-cover theme=literary title="梅雨季" ::chapter ... // 自动继承 literary ::text ...

入口 B · 顶格 ::theme(无封面时)

::theme 是伪组件,只影响主题,不会渲染任何 UI:

::theme purple # 备忘便签 正文段落,可以用 **加粗** 强调重点。
markdown 接管系必用 B
purple/sky/pop/sage/note 5 套接管系主题不写 zone 组件,只用 markdown。因为没有 magazine-cover 挂载点,必须走 ::theme 顶格声明。

入口 C · 围栏 meta

整段都是 zone 组件时,把主题放在围栏 meta 上:

```zone theme=data ::chapter ... ::line ... ```

CSS 变量定制

ZoneDSL 所有主题基于同一套 CSS 变量。业务方可以在自己的小程序里 override 这些变量实现品牌色定制——不用改核心代码。

变量用途
--mz-bg页底
--mz-panel内容卡底(纯白通常)
--mz-panel-soft次级卡底
--mz-ink主字
--mz-ink-soft次字
--mz-ink-mute弱字
--mz-line / --mz-line-strong分隔线
--mz-accent主强调色(品牌色核心)
--mz-accent-warm强调块底色
--mz-accent-soft浅强调
--mz-accent-tint微染背景
--mz-gradient-warm封面/hero 渐变
--mz-font主题级默认字体族(v2.2)
--mz-title-tracking主标题字距(v2.2)

业务定制例子——把整站换成品牌粉色:

/* 业务侧 wxss */ .brand-magenta .zone-block { --mz-accent: #E91E63; --mz-accent-warm: #F06292; --mz-accent-soft: #FCE4EC; --mz-bg: #FDF7F9; --mz-gradient-warm: linear-gradient(135deg, #E91E63 0%, #F06292 100%); }

12 主题一览

杂志系 7 套作用于 zone 组件(.zn-*)。markdown 接管系 5 套(v2.8+)让普通 markdown 元素(.h2w__*)也整体切换视觉。

顶部主题切换器可以实时预览——切一次,整站配色/字体/氛围就跟着变。

AI 输出策略
默认不写 ::theme——让内容走默认 editorial。只在用户明确要求特定风格或内容气质冲突时才显式声明主题。
GALLERY

示例画廊

每个例子都是「一段真实 DSL 源码 + 用 web CSS 复现的微缩效果」——直接对照看, 效果最终会由小程序端 zone-node 组件精准渲染。

流式输出 · 实时对照

左:AI 逐字吐字 · 右:同步渲染
点击 ▶ 播放,看组件如何随字流逐渐浮现
SKILL OUTPUT

按 zonedsl skill 输出的完整复盘

用户提问「梳理下 ::ZoneDSL发布这件事」,AI 按 zonedsl skill 规范一次性输出下面这段 DSL。 左边是原始文本流(AI 就吐这个),右边是小程序端 zone-node 组件树的最终渲染。 注意:走的是默认 editorial 主题,不用手动声明,视觉自动一致。

AI 输出 · 纯文本流
::magazine-cover
  tag="LAUNCH RECAP · 2026.07"
  title="::ZoneDSL\n**正式发布 Beta**"
  subtitle="来自花卷实验室的 markdown 增强方案"
  stats="62 组件,12 主题,1 分包"

::chapter "01" title="它解决了什么" category="WHY"

::callout "小程序里 AI 输出的 markdown 又硬又干,缺卡片、缺图表、缺主题气质。ZoneDSL 是无侵害的扩展 —— 与 markdown 共存,一行 DSL 就能出杂志级的视觉。"

::chapter "02" title="三个数字" category="DATA"

::data-board cols=3
  item "组件总数" value="62" desc="5 层分组"
  item "主题套数" value="12" desc="杂志系 7 + 接管系 5"
  item "skill 数量" value="1" desc="AI 输出约束规范"

::chapter "03" title="关键节点" category="WHEN"

::era-timeline "三个版本"
  item "v2.0" label="意图交互"
    desc="button 组件支持 11 类 intent 白名单"
  item "v2.5" label="多主题"
    desc="7 套杂志主题作用于 zone 组件"
  item "v2.8" label="接管系"
    desc="5 套 markdown 主题,不写组件也能出效果"

::chapter "04" title="你能拿去做什么" category="HOW"

::numbered-list "三步接入"
  item "安装 @zonedsl/web(Web) 或 @zonedsl/wechat(小程序)"
  item "在渲染消息处调用 towxml,option 传 streamingSafe=true"
  item "配置 zonedsl skill 到 AI 侧,约束输出走 DSL"
小程序端渲染
LAUNCH RECAP · 2026.07
::ZoneDSL
正式发布 Beta
来自花卷实验室的 markdown 增强方案
62组件 12主题 1分包
01 WHY 它解决了什么
小程序里 AI 输出的 markdown 又硬又干,缺卡片、缺图表、缺主题气质。ZoneDSL 是无侵害的扩展 —— 与 markdown 共存,一行 DSL 就能出杂志级的视觉。
02 DATA 三个数字
组件总数
62
5 层分组
主题套数
12
杂志系 7 + 接管系 5
skill 数量
1
AI 输出约束
03 WHEN 关键节点
三个版本
v2.0意图交互
button 组件支持 11 类 intent 白名单
v2.5多主题
7 套杂志主题作用于 zone 组件
v2.8接管系
5 套 markdown 主题,不写组件也能出效果
04 HOW 你能拿去做什么
三步接入
1安装 @zonedsl/web(Web) 或 @zonedsl/wechat(小程序)
2在渲染消息处调用 towxml,option 传 streamingSafe=true
3配置 zonedsl skill 到 AI 侧,约束输出走 DSL
MARKDOWN · SKILL NOT TRIGGERED

纯 markdown · 接管系主题

用户问「::ZoneDSL 是什么?」这类短问答,按 skill 规则**不该**触发 zone 组件(< 400 字、单点问答)。 但 markdown 本身也可以通过顶格 ::theme purple 声明主题, 整段 markdown 视觉就变成杂志感 —— 不写任何 zone 组件也能出效果。

AI 输出 · 纯 markdown + 接管系主题
::theme purple

# ::ZoneDSL 是什么?

**::ZoneDSL**是来自*花卷实验室*的
markdown 增强方案 —— 与 markdown 完全共存,
在其之上叠一层结构化组件扩展。

## 三个特点

- **共存不冲突**:markdown 语法照常渲染,DSL 只是补齐组件层
- **减 token**:一行 DSL = 一张卡,比逐字描述省 3-5 倍
- **减心智**:标准 skill 约束 AI 输出,不用记复杂语法

> 你可以理解成:markdown 的超集,只是加了几十个「一行成卡」的组件。
小程序端渲染 · purple 接管系

::ZoneDSL 是什么?

::ZoneDSL是来自花卷实验室的 markdown 增强方案 —— 与 markdown 完全共存, 在其之上叠一层结构化组件扩展。

三个特点

  • 共存不冲突:markdown 语法照常渲染,DSL 只是补齐组件层
  • 减 token:一行 DSL = 一张卡,比逐字描述省 3-5 倍
  • 减心智:标准 skill 约束 AI 输出,不用记复杂语法
你可以理解成:markdown 的超集,只是加了几十个「一行成卡」的组件。
MIXED · MARKDOWN + ZONE

混合渲染 · markdown 与 zone 并存

用户问「详细讲讲 zone-node 组件怎么工作」—— skill 触发,但内容以叙述为主、 结构化点缀。skill 允许 markdown 段落 + zone 组件穿插 —— 前者管叙事、 后者管数据/流程/时间点。这就是 ZoneDSL 「无侵害扩展」的核心场景。

AI 输出 · markdown 段落 + zone 组件穿插
# zone-node 组件是怎么工作的

**zone-node** 是 zone-DSL 的**统一派发组件** ——
不管你写的是 `::text` 还是 `::magazine-cover`,
最终都会被 towxml 解析成同一个 `<zone-node>` 节点,
再由内部的 60+ 个 `wx:elif` 分支按 tag 派发到对应模板。

::callout "三个关键设计:virtualHost 让 host 透明、styleIsolation 跨作用域命中、addGlobalClass 让主题类落到子组件。三合一让 zone-node 变成一个视觉上完全消失的容器。"

## 数据流

从 AI 吐字到最终渲染,整个链路只有三步:

::data-board cols=3
  item "Parse" value="~2ms" desc="DSL → AST"
  item "Transform" value="~1ms" desc="AST → nodes"
  item "Render" value="~8ms" desc="nodes → DOM"

## 为什么不冲突

- markdown 的 `# 标题``**加粗**``- 列表` 照常走
- zone 语法用 `::` 前缀,和 markdown 的语法字符完全分开
- parser 先扫 zone 块占位,再让 towxml 处理剩下的纯 markdown
小程序端渲染 · 默认 editorial 主题

zone-node 组件是怎么工作的

zone-node 是 zone-DSL 的统一派发组件 —— 不管你写的是 ::text 还是 ::magazine-cover, 最终都会被 towxml 解析成同一个 <zone-node> 节点, 再由内部的 60+ 个 wx:elif 分支按 tag 派发到对应模板。

三个关键设计:virtualHost 让 host 透明、styleIsolation 跨作用域命中、addGlobalClass 让主题类落到子组件。三合一让 zone-node 变成一个视觉上完全消失的容器。

数据流

从 AI 吐字到最终渲染,整个链路只有三步:

Parse
2ms
DSL → AST
Transform
1ms
AST → nodes
Render
8ms
nodes → DOM

为什么不冲突

  • markdown 的 # 标题**加粗**- 列表 照常走
  • zone 语法用 :: 前缀,和 markdown 的语法字符完全分开
  • parser 先扫 zone 块占位,再让 towxml 处理剩下的纯 markdown
FENCE · 边界语法

Zone 围栏 · 两种边界

Zone 块跟 markdown 段落穿插时,parser 需要知道「哪里是 zone、哪里是 markdown」。 提供两种等价语法:```zone 围栏(web 惯例,显式) 和 :: 顶格 连续行(小程序 AI 常用,隐式)。上下两段渲染完全一致 —— 用哪种取决于场景。

两种等价写法 · 上围栏 / 下无围栏
// A · 围栏版 ``` zone ... ```(显式边界,推荐 web / 长内容)
## 今日看点

```zone
::callout "围栏内组件与外面的 markdown 完全隔离"

::data-board cols=2
  item "围栏语法" value="显式"
  item "适用" value="web / 长内容"
```

markdown 段落继续,不会被 zone 影响。

// ===================================================

// B · 无围栏版 :: 顶格连续行,遇空行止(隐式,推荐流式)
## 今日看点

::callout "顶格 :: 开始的连续行会自动被识别为 zone 块"

::data-board cols=2
  item "无围栏" value="隐式"
  item "适用" value="AI 流式吐字"

markdown 段落继续,不会被 zone 影响。
两种写法 · 同一渲染结果

今日看点

围栏内组件与外面的 markdown 完全隔离
围栏语法
显式
边界最清晰
适用
web · 长内容
正式文档友好

markdown 段落继续,不会被 zone 影响。

今日看点

顶格 :: 开始的连续行会自动被识别为 zone 块
无围栏
隐式
::顶格
适用
AI 流式
吐字友好

markdown 段落继续,不会被 zone 影响。

EXAMPLE 01 · MAGAZINE COVER

杂志封面 · 复盘头图

一行 DSL 生成一张完整杂志式封面卡:tag / title(含高亮) / subtitle / stats。 ::magazine-cover 是 preset 层的招牌组件。

DSL
::magazine-cover
  tag="HOT RECAP · 2026.07"
  title="林晚\n**盛夏夜名场面**"
  subtitle="48 小时刷屏,4 大场面轮番出圈"
  stats="19 条热议,5 条冲主榜,11h+ 最长在榜"
  bg=light
HOT RECAP · 2026.07
林晚
盛夏夜名场面
48 小时刷屏,4 大场面轮番出圈
19条热议 5条冲主榜 11h+最长在榜
EXAMPLE 02 · CHAPTER + DATA BOARD

杂志分栏 + 数据面板

::chaptercategory 属性自动走 magazine 变体 (深炭 tab)。搭配 ::data-board 展示关键数字。

DSL
::chapter "01" title="先看数据"
  category="DATA"

::data-board cols=2
  item "主榜最高" value="8 位"
  item "在榜时长" value="11h+"
  item "文娱榜记录" value="21 条"
  item "互动占比" value="63%"
01 / DATA
先看数据
主榜最高
8 位
在榜时长
11h+
文娱榜记录
21 条
互动占比
63%
EXAMPLE 03 · ERA TIMELINE

横向历史时间条

::era-timeline 展示极端年份 / 品牌大事记 / 版本演进。 ≤3 张自动 grid 2 列铺满,4+ 张横滑——布局自适应,不用写死。

DSL
::era-timeline "梅雨极端年份"
  item "1954"
    label="百年一遇"
    desc="长江流域超警戒水位"
  item "1998"
    label="二度梅+洪水"
    desc="千亿损失,29 省受灾"
  item "2020"
    label="超长梅"
    desc="60 天不停歇"
1954
百年一遇
长江流域超警戒水位
1998
二度梅+洪水
千亿损失,29 省受灾
2020
超长梅
60 天不停歇
EXAMPLE 04 · PURPLE THEME

markdown 接管 · purple 主题

不写任何 zone 组件——只在首行加 ::theme purple, 然后用普通 markdown。整块内容自动变成紫底 + 黄胶囊 + 白卡片的杂志视觉。

DSL + Markdown
::theme purple

# 备忘便签

正文段落,可以用 **加粗** 强调重点。
h1/h2 自动变成黄色胶囊,段落自动变白卡片。

备忘便签

正文段落,可以用 加粗 强调重点。h1/h2 自动变成黄色胶囊,段落自动变白卡片。

EXAMPLE 05 · SKY THEME

markdown 接管 · sky 主题

同样一段 markdown,换个主题声明就是完全不同的视觉气质。sky 主题走简报风: 蓝底 + 白胶囊 H1 + 深蓝卡片段落 + 黄胶囊内联高亮。

DSL + Markdown
::theme sky

# 每日简报

大模型正在 **调用工具、浏览网页、
执行多步任务**——这意味着新形态。

每日简报

大模型正在 调用工具、浏览网页、执行多步任务——这意味着新形态。

EXAMPLE 06 · INTERACTIVE

交互层 · checkbox-group + button

多选组 + 意图按钮。::button intent=xxx 会触发页面上的 onZoneAction,你可以把它连到搜索/跳转/复制等业务能力。

DSL
::checkbox-group "兴趣爱好"
  checkbox "阅读" checked
  checkbox "运动"
  checkbox "音乐" checked

::row
  ::button "追问更多"
    variant=primary
    intent=followup
    value="还有哪些没聊到?"
  ::button "搜相关"
    intent=search
    value="热议"
兴趣爱好
阅读 运动 音乐
DSL / Markdown 源码
实时预览
左侧写点 DSL,这里立刻渲染。