npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@macroui/dsl2ui

v5.0.6

Published

Dsl2UI — Zero-dependency streaming UI description & rendering framework for AI chat. Describe UI with a tiny DSL, stream over SSE, render to real DOM incrementally.

Readme

Dsl2UI - From Token to UI

English | 简体中文

Dsl2UI是全球首个 For AI & 零依赖的流式 UI 描述与渲染框架。后端用极简 DSL 描述组件,经 SSE 或 WebSocket 流式推送,前端增量解析、首个 Token 即开始渲染 —— 让 AI 使用极少的 Token 去输出更灵活、更具表现力的 UI。

npm version npm downloads License: MIT 零运行时依赖 bundle size

官网文档站 · 组件画廊演示 · DSL 完整参考 · 在线体验(StackBlitz)


目录


特性

  • 零运行时依赖 —— 前后端均为原生 API,不引入任何运行时 npm 包;产物自包含,gzip 后 ~86KB(ESM)。
  • 流式优先 —— 状态机增量解析,边收边渲染,首个字符到达即开始绘制 DOM。
  • 简洁 DSL —— [card tt:标题][p 内容][/card] 一行描述一个组件,AI 易生成、人易读。
  • 框架无关 —— 原生 JS 可用,另提供 React / Vue / Svelte / Web Component 官方适配器。
  • 插件化组件 —— renderer.register(type, fn) 注册,开箱即用 150+ 组件(卡片、表格、表单、图表、Markdown、代码高亮等)。
  • 事件安全 —— 事件处理器为命名引用(clk:/sub:),需预先 registerHandler 注册,禁止注入可执行代码。
  • 主题驱动 —— CSS 变量 + data-dsl2ui-theme 切换,内置 HSB 算法的 10 级色阶生成器。
  • SSR 友好 —— import 不依赖 window/document,可在 Next.js / Nuxt / SvelteKit 等服务端导入(渲染在客户端进行)。
  • 容错降级 —— 未注册组件渲染为 div.dsl2ui-unknown,渲染抛错生成 details.dsl2ui-error,单点错误不炸整页。
  • 资源防护 —— maxBuffer(1MB)与 maxDepth(100)防止恶意/超长输入耗尽资源。

安装

# npm
npm install @jboltai/dsl2ui

# pnpm
pnpm add @jboltai/dsl2ui

# yarn
yarn add @jboltai/dsl2ui

CDN(零构建)

<link rel="stylesheet" href="https://unpkg.com/@jboltai/dsl2ui/dist/dsl2ui.css">
<script src="https://unpkg.com/@jboltai/dsl2ui/dist/dsl2ui.umd.js"></script>
<!-- 挂载到 window.Dsl2UI 命名空间 -->

jsdelivr 同样可用:把 unpkg.com 换成 cdn.jsdelivr.net/npm


快速开始

引入样式(npm 项目)

import '@jboltai/dsl2ui/css';   // 必须显式引入一次(库样式合一)

三种渲染方式

1. 一次性渲染

import { Dsl2UI } from '@jboltai/dsl2ui';

const dsl2ui = new Dsl2UI({ container: '#app' });
dsl2ui.render('[h1 Hello Dsl2UI][p 这是一段文本]');

2. 流式渲染(feed() 逐步输入)

const dsl2ui = new Dsl2UI({ container: '#app' });
dsl2ui.startStream();
dsl2ui.feed('[card tt:');
dsl2ui.feed('流式卡片]');
dsl2ui.feed('[p 内容边到边渲染]');
dsl2ui.feed('[/card]');
dsl2ui.endStream();   // 刷出缓冲区

3. SSE 连接(服务端推流)

const dsl2ui = new Dsl2UI({
  container: '#chat',
  onEvent: (type, data) => {
    if (type === 'streamEnd') console.log('流结束');
  }
});
dsl2ui.connect('/api/chat', { prompt: '画一个登录卡片' });

SSE 协议约定:data: 行内为 JSON,取 dsl2ui 字段喂给解析器;[DONE] 标记流结束。

Node.js(服务端 Builder)

import { Dsl2UIBuilder } from '@jboltai/dsl2ui/builder';

const b = new Dsl2UIBuilder();
b.card({ tt: '标题' }).h2('内容').p('描述').end();
console.log(b.toString());  // [card tt:标题][h2 内容][p 描述][/card]

Builder 是纯逻辑模块,可在任意 Node 运行时(含 Edge / Serverless)使用,无需 DOM。


在框架中使用

Dsl2UI 提供官方框架适配器,让你用熟悉的声明式 API 渲染 DSL。适配器均 peer-depend 对应框架(不重复打包),并随 @jboltai/dsl2ui 自动引入样式。

| 包 | 适用 | 入口 | |------|------|------| | @jboltai/dsl2ui-react | React 16.8+ | <Dsl2UIView dsl={...} /> + useDsl2UIStream() | | @jboltai/dsl2ui-vue | Vue 3 | <Dsl2UIView :dsl="..." /> + useDsl2UIStream() | | @jboltai/dsl2ui-svelte | Svelte 3.46+ | use:dsl2ui={{ dsl }} action + <Dsl2UI /> | | @jboltai/dsl2ui-webc | 任意框架 / 无框架 | <dsl2ui-view dsl="..."></dsl2ui-view> 自定义元素 |

React

import { Dsl2UIView } from '@jboltai/dsl2ui-react';

export function App() {
  return <Dsl2UIView dsl="[card tt:你好][p 流式 UI][/card]" theme="default" />;
}

Vue 3

<script setup>
import { Dsl2UIView } from '@jboltai/dsl2ui-vue';
const dsl = '[card tt:你好][p 流式 UI][/card]';
</script>
<template><Dsl2UIView :dsl="dsl" /></template>

Svelte

<script>
  import { dsl2ui } from '@jboltai/dsl2ui-svelte';
</script>
<div use:dsl2ui={{ dsl: '[card tt:你好][p 流式 UI][/card]' }}></div>

Web Component(框架无关)

import defineDsl2uiElement from '@jboltai/dsl2ui-webc';
defineDsl2uiElement(); // 注册 <dsl2ui-view>
<dsl2ui-view dsl="[card tt:你好][p 流式 UI][/card]"></dsl2ui-view>

各适配器的流式 / SSE 用法见对应包 README。


架构

三层数据流

后端 Dsl2UIBuilder 生成 DSL  →  SSE 推送  →  前端 Dsl2UIParser 增量解析  →  Dsl2UIRenderer 渲染 DOM

核心模块

| 模块 | 职责 | |------|------| | core/parser.js | 基于状态机(TEXT / TAG_OPEN / TAG_CLOSE)的流式解析器,支持 feed() 增量与 parse() 一次性 | | core/renderer.js | 组件渲染引擎,slotStack 管理嵌套容器插槽,VARIANTS 白名单校验变体,深度上限 50 | | core/event-bus.js | 事件总线单例,registerHandler(name, fn) 注册,DSL 用 clk:/sub: 绑定 | | core/theme.js | CSS 变量驱动主题管理,data-dsl2ui-theme 切换 | | core/color-generator.js | 基于 HSB 算法的 10 级色板与主题 token 生成器 | | components/* | 按类型分文件的组件库,index.js 统一注册 | | server/dsl2ui-builder.js | 链式 API 生成 DSL,支持 toString()toChunks() 两种输出 | | server/sse-server.js | Node.js 原生 http 实现的 SSE 演示服务器 |


DSL 语法速查

[组件类型 属性:值 内容文本]           ; 自闭合
[card tt:标题][p 内容][/card]         ; 容器嵌套
ph:"含空格的值"                       ; 值含空格用双引号
v:"primary,sm"                        ; 多变体逗号分隔
stripe                                ; 布尔属性(只写 key)

常用属性简写

| 简写 | 含义 | 简写 | 含义 | |------|------|------|------| | tt | title | tx | text | | l | label | ph | placeholder | | u | url | s | src / source | | n | name | v | value / variant | | act| action | mtd| method | | clk| onclick 处理器名 | sub| onsubmit 处理器名 | | dis| disabled | ro | readonly | | req| required | chk| checked | | id | 元素 ID(也作 upd 更新目标) | w/h/bg/fc | 宽/高/背景/字色 |

布尔属性(只写 key)

stripe dis ro req chk multi auto plain round closable bordered open pill dot leaf inline rounded container

完整列表以 parser.jsBOOLEAN_ATTRS Set 为准。

变体系统

DSL 写 v:primary,渲染器生成 CSS 类 dsl2ui-btn--primary。变体名经 VARIANTS 白名单校验,未知变体静默丢弃。

动态更新

[upd id:目标ID v/act/tt/tx:新值]    ; 更新已渲染组件的值/动作/标题/文本

完整参考

详细属性表与容器类型清单见 demo/Dsl2UI_DSL_REFERENCE.md


组件清单

按文件分组,开箱即用:

| 文件 | 组件 | |------|------| | basic.js | 标题 h1–h6、段落、链接、Markdown、代码块、代码高亮、徽标、按钮、提示、分隔线、固钉(affix)等 | | table.js | 表格(table / thead / tbody / tr / desc) | | form.js | 表单、输入框、文本域、下拉、单选/复选、开关、日期选择器、标签输入、分段控制器(segmented)、颜色选择(color-picker)等 | | layout.js | 卡片、栅格行/列、列表、图片集、描述列表、锚点导航(anchor)、漫游引导(tour)、图片预览组(preview-group)、命令式确认(modal.confirm,宿主侧 JS API)等 | | chart.js | 纯 SVG 零依赖图表:bar / line / pie / radar / donut / scatter / gantt / funnel | | lightbox.js | 图片灯箱预览 |

容器类型(需 [/type] 闭合,完整列表见 parser.jsCONTAINERS Set):

form table thead tbody card ft row col list select radio code imgs md textarea
tabs tab accordion collapse dialog btngroup picker timeline steps drawer ol ul i
item think bubble toolbar badge-box dropdown transfer cascader tree tn step desc
carousel popover input-tag watermark menu tour affix preview-group float-button masonry

Builder API(服务端)

Dsl2UIBuilder 提供链式调用生成 DSL,两种输出方式:

const b = new Dsl2UIBuilder();

// toString() —— 一次性输出完整字符串
b.card({ tt: '卡片' }).p('内容').end();
const dsl = b.toString();

// toChunks() —— 分块数组,配合 SSE 逐块推送
const chunks = b.reset().card({ tt: '卡片' }).p('内容').end().toChunks();

自动闭合toString() / toChunks() 内部调用 _finalizeChunks(),未关闭容器会自动补全,无需手动 endAll()

双行为方法thead()inputTag()quickReply()agent() 根据参数自动选择自闭合或容器模式。

命名避让:布局用 row_layout() / col_layout() 以避让表格的 row()


主题系统

通过 CSS 变量 + data-dsl2ui-theme 属性切换:

import { setTheme } from '@jboltai/dsl2ui';
setTheme('dark');   // 切换为暗色主题

自定义主题色可用色阶生成器:

import { generatePalette, generateThemeTokens } from '@jboltai/dsl2ui';
const tokens = generateThemeTokens({ primary: '#1677ff', danger: '#ff4d4f' });
// 输出 { '--dsl2ui-primary-1' ... '--dsl2ui-primary-10' } 共 10 级 CSS 变量映射

扩展组件

新增一个组件需四步:

  1. 注册渲染函数src/components/*.js):

    renderer.register('mycard', (node, rc, parentType) => {
      const el = renderer.el('div', { class: 'dsl2ui-mycard' });
      el.textContent = node.attrs.tt || '';
      rc(node.children, el);   // 递归渲染子节点
      return el;
    });
  2. 若为容器类型,加入 src/core/parser.jsCONTAINERS Set。若内容含 [ 不应被解析(如代码),同时加入 _isRawContent() 类型列表。

  3. 添加 Builder 方法src/server/dsl2ui-builder.js):自闭合用 _selfClosing(),容器用 _open() / end()

  4. 添加样式src/styles/dsl2ui.css):类名 .dsl2ui-mycard,变体用 .dsl2ui-mycard--{variant} 并加入 renderer.jsVARIANTS 白名单。

最后在 tests/ 补测试(见下)。


测试

基于 Node.js 内置 assert 的自定义 runner,零测试框架依赖:

npm test            # 全量 24 个测试文件,866+ 用例
npm run test:parser # 仅解析器
npm run test:builder
npm run test:core   # event-bus + theme + renderer
npm run typecheck   # tsc 类型检查(含反向 @ts-expect-error 断言)
npm run coverage    # c8 覆盖率(核心模块 ~91%)

node tests/test-xxx.js          # 跑单个测试文件

renderer 测试依赖 tests/helpers/dom-mock.js 提供的最小化 DOM mock。断言失败进程退出码为 1。


项目结构

.
├── src/
│   ├── core/              # 解析器、渲染器、事件总线、主题、色阶生成器
│   ├── components/        # 组件库(basic/table/form/layout/chart/lightbox)
│   ├── server/            # Builder 链式 API + SSE 演示服务器
│   ├── styles/            # dsl2ui.css + themes/(default, dark)
│   └── index.js           # 主入口,整合 Dsl2UI 类
├── packages/              # 框架适配器 monorepo(pnpm workspace)
│   ├── react/             # @jboltai/dsl2ui-react
│   ├── vue/               # @jboltai/dsl2ui-vue
│   ├── svelte/            # @jboltai/dsl2ui-svelte
│   ├── webc/              # @jboltai/dsl2ui-webc(Web Component)
├── demo/                  # 组件画廊演示
├── tests/                 # 自定义 runner 测试套件(24 文件 / 866+ 用例)
├── docs/                  # VitePress 文档站
└── package.json

路线图

Dsl2UI 正在向多语言后端 SDK 与多样式库前端主题演进。

图例:✅ 已支持 · 🚧 规划中

后端 SDK 多语言支持

| 语言 / 运行时 | 状态 | 说明 | |---------------|:----:|------| | Node.js | ✅ | Dsl2UIBuilder 链式 API + SSE 演示服务器(当前唯一实现) | | Python | 🚧 | 规划中 | | Rust | 🚧 | 规划中 | | Java | 🚧 | 规划中 | | Go | 🚧 | 规划中 | | 跨语言 DSL 规范固化 | 🚧 | 共享解析契约,保证各 SDK 输出一致 |

前端集成

| 能力 | 状态 | 说明 | |------|:----:|------| | React / Vue / Svelte / Web Component 适配器 | ✅ | @jboltai/dsl2ui-{react,vue,svelte,webc} | | CSS 变量主题(default / dark) | ✅ | data-dsl2ui-theme 切换 | | HSB 色板生成器 | ✅ | 任意主色生成 10 级色阶 | | TailwindCSS 适配 | 🚧 | 原子类映射 / 主题 token 桥接 | | UnoCSS 适配 | 🚧 | 规划中 | | 主题市场 / 主题分享 | 🚧 | 社区可分享主题包 |


License

MIT