@jboltai/tokui 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +35 -0
- package/LICENSE +21 -0
- package/README.md +423 -0
- package/README_EN.md +438 -0
- package/dist/tokui.cjs +11 -0
- package/dist/tokui.cjs.map +1 -0
- package/dist/tokui.css +2 -0
- package/dist/tokui.mjs +8792 -0
- package/dist/tokui.mjs.map +1 -0
- package/dist/tokui.umd.js +11 -0
- package/dist/tokui.umd.js.map +1 -0
- package/package.json +100 -0
- package/src/index.d.ts +116 -0
- package/src/server/tokui-builder.d.ts +89 -0
- package/src/server/tokui-builder.js +678 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
## [0.1.0] - 2026-06-25
|
|
6
|
+
|
|
7
|
+
首个公开 npm 发布版本(开源就绪)。零依赖流式 UI 描述与渲染框架。
|
|
8
|
+
|
|
9
|
+
### 新增
|
|
10
|
+
|
|
11
|
+
- **多格式构建产物**:`dist/tokui.{mjs,cjs}` + `dist/tokui.umd.js` + `tokui.css`,均带 sourcemap。`.mjs`/`.cjs` 用标准扩展名显式声明模块类型(消除 Node `MODULE_TYPELESS` 警告),ESM(打包器)/ UMD(CDN/`<script>`)/ CJS(Node `require`)三全。
|
|
12
|
+
- **框架适配器 monorepo**(pnpm workspace):
|
|
13
|
+
- `@jboltai/tokui-react` — `<TokUIView>` 组件 + `useTokUIStream()` hook
|
|
14
|
+
- `@jboltai/tokui-vue` — `<TokUIView>` 组件 + `useTokUIStream()` 组合式
|
|
15
|
+
- `@jboltai/tokui-svelte` — `use:tokui` action + `<TokUI>` 组件
|
|
16
|
+
- `@jboltai/tokui-webc` — `<tokui-view>` 自定义元素(框架无关)
|
|
17
|
+
- **SSR 安全**:核心入口懒解析 + 三态守卫(Node CJS / 浏览器 / SSR no-op),`import` 不依赖 `window`/`document`,可在 Next.js / Nuxt / SvelteKit 服务端导入。
|
|
18
|
+
- **测试基建**:`npm test` 改为全量 `test:all`(24 文件 / 866+ 用例);新增 `typecheck`(tsc,含反向断言)与 `coverage`(c8,核心模块 ~91%)。
|
|
19
|
+
- **发布防护**:`package.json` 的 `exports` 分流(import/require/browser/node)、`files` 白名单、`.npmignore`、`sideEffects`、`publishConfig.provenance`。
|
|
20
|
+
- **CDN 支持**:unpkg / jsdelivr 直接引用 UMD + CSS。
|
|
21
|
+
|
|
22
|
+
### 变更
|
|
23
|
+
|
|
24
|
+
- 包名从内部 `tokui` 改为 scoped `@jboltai/tokui`。
|
|
25
|
+
- `exports.require` 由 UMD 改指真 CJS(`tokui.cjs`),消除 Node `require` 的 UMD/伪 CJS 歧义。
|
|
26
|
+
- `engines.node` 提升到 `>=18`。
|
|
27
|
+
- DOM mock 的 `textContent`/`innerHTML` 改为 DOM 忠实行为(getter 聚合后代 / setter 以文本节点替换子节点),修复 `p v:muted` 变体与代码块未知语言回退两处测试。
|
|
28
|
+
|
|
29
|
+
### 修复
|
|
30
|
+
|
|
31
|
+
- `test-basic.js` 因 countdown 组件 `setInterval` 无销毁钩子导致进程挂起 —— runner 改为强制 `process.exit`。
|
|
32
|
+
- `test-layout.js` 的 `item content + nested list` 断言改为符合真实 DOM 聚合语义。
|
|
33
|
+
- `src/index.js` 与 `src/components/index.js` 的模块求值期裸读 `window.TokUI._internal` 改为运行期懒解析,SSR 导入不再依赖 bundler 保留 `require` 的怪癖。
|
|
34
|
+
|
|
35
|
+
[0.1.0]: https://github.com/jboltai/tokui/releases/tag/v0.1.0
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 jboltai.com
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
# TokUI - From Token to UI
|
|
2
|
+
|
|
3
|
+
**[English](./README_EN.md)** | 简体中文
|
|
4
|
+
|
|
5
|
+
> TokUI是全球首个 For AI & 零依赖的流式 UI 描述与渲染框架。后端用极简 DSL 描述组件,经 SSE 或 WebSocket 流式推送,前端增量解析、首个 Token 即开始渲染 —— 让 AI 使用极少的 Token 去输出更灵活、更具表现力的 UI。
|
|
6
|
+
|
|
7
|
+
[](https://www.npmjs.com/package/@jboltai/tokui)
|
|
8
|
+
[](https://www.npmjs.com/package/@jboltai/tokui)
|
|
9
|
+
[](./LICENSE)
|
|
10
|
+
[](#)
|
|
11
|
+
[](https://bundlephobia.com/package/@jboltai/tokui)
|
|
12
|
+
|
|
13
|
+
[在线体验(StackBlitz)](https://stackblitz.com/github/jboltai/tokui) · [组件画廊演示](./demo/index.html) · [DSL 完整参考](./demo/TOKUI_DSL_REFERENCE.md) · [文档站](https://tokui.jboltai.com/)
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## 目录
|
|
18
|
+
|
|
19
|
+
- [特性](#特性)
|
|
20
|
+
- [安装](#安装)
|
|
21
|
+
- [快速开始](#快速开始)
|
|
22
|
+
- [在框架中使用](#在框架中使用)
|
|
23
|
+
- [架构](#架构)
|
|
24
|
+
- [DSL 语法速查](#dsl-语法速查)
|
|
25
|
+
- [组件清单](#组件清单)
|
|
26
|
+
- [Builder API(服务端)](#builder-api服务端)
|
|
27
|
+
- [主题系统](#主题系统)
|
|
28
|
+
- [扩展组件](#扩展组件)
|
|
29
|
+
- [测试](#测试)
|
|
30
|
+
- [项目结构](#项目结构)
|
|
31
|
+
- [路线图](#路线图)
|
|
32
|
+
- [License](#license)
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## 特性
|
|
37
|
+
|
|
38
|
+
- **零运行时依赖** —— 前后端均为原生 API,不引入任何运行时 npm 包;产物自包含,gzip 后 ~86KB(ESM)。
|
|
39
|
+
- **流式优先** —— 状态机增量解析,边收边渲染,首个字符到达即开始绘制 DOM。
|
|
40
|
+
- **简洁 DSL** —— `[card tt:标题][p 内容][/card]` 一行描述一个组件,AI 易生成、人易读。
|
|
41
|
+
- **框架无关** —— 原生 JS 可用,另提供 React / Vue / Svelte / Web Component 官方适配器。
|
|
42
|
+
- **插件化组件** —— `renderer.register(type, fn)` 注册,开箱即用 30+ 组件(卡片、表格、表单、图表、Markdown、代码高亮等)。
|
|
43
|
+
- **事件安全** —— 事件处理器为命名引用(`clk:`/`sub:`),需预先 `registerHandler` 注册,禁止注入可执行代码。
|
|
44
|
+
- **主题驱动** —— CSS 变量 + `data-tokui-theme` 切换,内置 HSB 算法的 10 级色阶生成器。
|
|
45
|
+
- **SSR 友好** —— `import` 不依赖 `window`/`document`,可在 Next.js / Nuxt / SvelteKit 等服务端导入(渲染在客户端进行)。
|
|
46
|
+
- **容错降级** —— 未注册组件渲染为 `div.tokui-unknown`,渲染抛错生成 `details.tokui-error`,单点错误不炸整页。
|
|
47
|
+
- **资源防护** —— `maxBuffer`(1MB)与 `maxDepth`(100)防止恶意/超长输入耗尽资源。
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## 安装
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
# npm
|
|
55
|
+
npm install @jboltai/tokui
|
|
56
|
+
|
|
57
|
+
# pnpm
|
|
58
|
+
pnpm add @jboltai/tokui
|
|
59
|
+
|
|
60
|
+
# yarn
|
|
61
|
+
yarn add @jboltai/tokui
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### CDN(零构建)
|
|
65
|
+
|
|
66
|
+
```html
|
|
67
|
+
<link rel="stylesheet" href="https://unpkg.com/@jboltai/tokui/dist/tokui.css">
|
|
68
|
+
<script src="https://unpkg.com/@jboltai/tokui/dist/tokui.umd.js"></script>
|
|
69
|
+
<!-- 挂载到 window.TokUI 命名空间 -->
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
> jsdelivr 同样可用:把 `unpkg.com` 换成 `cdn.jsdelivr.net/npm`。
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## 快速开始
|
|
77
|
+
|
|
78
|
+
### 引入样式(npm 项目)
|
|
79
|
+
|
|
80
|
+
```js
|
|
81
|
+
import '@jboltai/tokui/css'; // 必须显式引入一次(库样式合一)
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### 三种渲染方式
|
|
85
|
+
|
|
86
|
+
**1. 一次性渲染**
|
|
87
|
+
|
|
88
|
+
```js
|
|
89
|
+
import { TokUI } from '@jboltai/tokui';
|
|
90
|
+
|
|
91
|
+
const tokui = new TokUI({ container: '#app' });
|
|
92
|
+
tokui.render('[h1 Hello TokUI][p 这是一段文本]');
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
**2. 流式渲染(`feed()` 逐步输入)**
|
|
96
|
+
|
|
97
|
+
```js
|
|
98
|
+
const tokui = new TokUI({ container: '#app' });
|
|
99
|
+
tokui.startStream();
|
|
100
|
+
tokui.feed('[card tt:');
|
|
101
|
+
tokui.feed('流式卡片]');
|
|
102
|
+
tokui.feed('[p 内容边到边渲染]');
|
|
103
|
+
tokui.feed('[/card]');
|
|
104
|
+
tokui.endStream(); // 刷出缓冲区
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
**3. SSE 连接(服务端推流)**
|
|
108
|
+
|
|
109
|
+
```js
|
|
110
|
+
const tokui = new TokUI({
|
|
111
|
+
container: '#chat',
|
|
112
|
+
onEvent: (type, data) => {
|
|
113
|
+
if (type === 'streamEnd') console.log('流结束');
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
tokui.connect('/api/chat', { prompt: '画一个登录卡片' });
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
> SSE 协议约定:`data:` 行内为 JSON,取 `tokui` 字段喂给解析器;`[DONE]` 标记流结束。
|
|
120
|
+
|
|
121
|
+
### Node.js(服务端 Builder)
|
|
122
|
+
|
|
123
|
+
```js
|
|
124
|
+
import { TokUIBuilder } from '@jboltai/tokui/builder';
|
|
125
|
+
|
|
126
|
+
const b = new TokUIBuilder();
|
|
127
|
+
b.card({ tt: '标题' }).h2('内容').p('描述').end();
|
|
128
|
+
console.log(b.toString()); // [card tt:标题][h2 内容][p 描述][/card]
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
> Builder 是纯逻辑模块,可在任意 Node 运行时(含 Edge / Serverless)使用,无需 DOM。
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## 在框架中使用
|
|
136
|
+
|
|
137
|
+
TokUI 提供官方框架适配器,让你用熟悉的声明式 API 渲染 DSL。适配器均 peer-depend 对应框架(不重复打包),并随 `@jboltai/tokui` 自动引入样式。
|
|
138
|
+
|
|
139
|
+
| 包 | 适用 | 入口 |
|
|
140
|
+
|------|------|------|
|
|
141
|
+
| [`@jboltai/tokui-react`](./packages/react) | React 16.8+ | `<TokUIView dsl={...} />` + `useTokUIStream()` |
|
|
142
|
+
| [`@jboltai/tokui-vue`](./packages/vue) | Vue 3 | `<TokUIView :dsl="..." />` + `useTokUIStream()` |
|
|
143
|
+
| [`@jboltai/tokui-svelte`](./packages/svelte) | Svelte 3.46+ | `use:tokui={{ dsl }}` action + `<TokUI />` |
|
|
144
|
+
| [`@jboltai/tokui-webc`](./packages/webc) | 任意框架 / 无框架 | `<tokui-view dsl="..."></tokui-view>` 自定义元素 |
|
|
145
|
+
|
|
146
|
+
### React
|
|
147
|
+
|
|
148
|
+
```jsx
|
|
149
|
+
import { TokUIView } from '@jboltai/tokui-react';
|
|
150
|
+
|
|
151
|
+
export function App() {
|
|
152
|
+
return <TokUIView dsl="[card tt:你好][p 流式 UI][/card]" theme="default" />;
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Vue 3
|
|
157
|
+
|
|
158
|
+
```vue
|
|
159
|
+
<script setup>
|
|
160
|
+
import { TokUIView } from '@jboltai/tokui-vue';
|
|
161
|
+
const dsl = '[card tt:你好][p 流式 UI][/card]';
|
|
162
|
+
</script>
|
|
163
|
+
<template><TokUIView :dsl="dsl" /></template>
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Svelte
|
|
167
|
+
|
|
168
|
+
```svelte
|
|
169
|
+
<script>
|
|
170
|
+
import { tokui } from '@jboltai/tokui-svelte';
|
|
171
|
+
</script>
|
|
172
|
+
<div use:tokui={{ dsl: '[card tt:你好][p 流式 UI][/card]' }}></div>
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Web Component(框架无关)
|
|
176
|
+
|
|
177
|
+
```js
|
|
178
|
+
import defineTokuiElement from '@jboltai/tokui-webc';
|
|
179
|
+
defineTokuiElement(); // 注册 <tokui-view>
|
|
180
|
+
```
|
|
181
|
+
```html
|
|
182
|
+
<tokui-view dsl="[card tt:你好][p 流式 UI][/card]"></tokui-view>
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
各适配器的流式 / SSE 用法见对应包 README。
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## 架构
|
|
190
|
+
|
|
191
|
+
### 三层数据流
|
|
192
|
+
|
|
193
|
+
```
|
|
194
|
+
后端 TokUIBuilder 生成 DSL → SSE 推送 → 前端 TokUIParser 增量解析 → TokUIRenderer 渲染 DOM
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### 核心模块
|
|
198
|
+
|
|
199
|
+
| 模块 | 职责 |
|
|
200
|
+
|------|------|
|
|
201
|
+
| `core/parser.js` | 基于状态机(TEXT / TAG_OPEN / TAG_CLOSE)的流式解析器,支持 `feed()` 增量与 `parse()` 一次性 |
|
|
202
|
+
| `core/renderer.js` | 组件渲染引擎,`slotStack` 管理嵌套容器插槽,`VARIANTS` 白名单校验变体,深度上限 50 |
|
|
203
|
+
| `core/event-bus.js` | 事件总线单例,`registerHandler(name, fn)` 注册,DSL 用 `clk:`/`sub:` 绑定 |
|
|
204
|
+
| `core/theme.js` | CSS 变量驱动主题管理,`data-tokui-theme` 切换 |
|
|
205
|
+
| `core/color-generator.js` | 基于 HSB 算法的 10 级色板与主题 token 生成器 |
|
|
206
|
+
| `components/*` | 按类型分文件的组件库,`index.js` 统一注册 |
|
|
207
|
+
| `server/tokui-builder.js` | 链式 API 生成 DSL,支持 `toString()` 与 `toChunks()` 两种输出 |
|
|
208
|
+
| `server/sse-server.js` | Node.js 原生 http 实现的 SSE 演示服务器 |
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## DSL 语法速查
|
|
213
|
+
|
|
214
|
+
```tokui
|
|
215
|
+
[组件类型 属性:值 内容文本] ; 自闭合
|
|
216
|
+
[card tt:标题][p 内容][/card] ; 容器嵌套
|
|
217
|
+
ph:"含空格的值" ; 值含空格用双引号
|
|
218
|
+
v:"primary,sm" ; 多变体逗号分隔
|
|
219
|
+
stripe ; 布尔属性(只写 key)
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### 常用属性简写
|
|
223
|
+
|
|
224
|
+
| 简写 | 含义 | 简写 | 含义 |
|
|
225
|
+
|------|------|------|------|
|
|
226
|
+
| `tt` | title | `tx` | text |
|
|
227
|
+
| `l` | label | `ph` | placeholder |
|
|
228
|
+
| `u` | url | `s` | src / source |
|
|
229
|
+
| `n` | name | `v` | value / variant |
|
|
230
|
+
| `act`| action | `mtd`| method |
|
|
231
|
+
| `clk`| onclick 处理器名 | `sub`| onsubmit 处理器名 |
|
|
232
|
+
| `dis`| disabled | `ro` | readonly |
|
|
233
|
+
| `req`| required | `chk`| checked |
|
|
234
|
+
| `id` | 元素 ID(也作 `upd` 更新目标) | `w/h/bg/fc` | 宽/高/背景/字色 |
|
|
235
|
+
|
|
236
|
+
### 布尔属性(只写 key)
|
|
237
|
+
|
|
238
|
+
`stripe` `dis` `ro` `req` `chk` `multi` `auto` `plain` `round` `closable` `bordered` `open` `pill` `dot` `leaf` `inline` `rounded` `container`
|
|
239
|
+
|
|
240
|
+
完整列表以 `parser.js` 的 `BOOLEAN_ATTRS` Set 为准。
|
|
241
|
+
|
|
242
|
+
### 变体系统
|
|
243
|
+
|
|
244
|
+
DSL 写 `v:primary`,渲染器生成 CSS 类 `tokui-btn--primary`。变体名经 `VARIANTS` 白名单校验,未知变体静默丢弃。
|
|
245
|
+
|
|
246
|
+
### 动态更新
|
|
247
|
+
|
|
248
|
+
```tokui
|
|
249
|
+
[upd id:目标ID v/act/tt/tx:新值] ; 更新已渲染组件的值/动作/标题/文本
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### 完整参考
|
|
253
|
+
|
|
254
|
+
详细属性表与容器类型清单见 [`demo/TOKUI_DSL_REFERENCE.md`](./demo/TOKUI_DSL_REFERENCE.md)。
|
|
255
|
+
|
|
256
|
+
---
|
|
257
|
+
|
|
258
|
+
## 组件清单
|
|
259
|
+
|
|
260
|
+
按文件分组,开箱即用:
|
|
261
|
+
|
|
262
|
+
| 文件 | 组件 |
|
|
263
|
+
|------|------|
|
|
264
|
+
| `basic.js` | 标题 h1–h6、段落、链接、Markdown、代码块、代码高亮、徽标、按钮、提示、分隔线等 |
|
|
265
|
+
| `table.js` | 表格(`table` / `thead` / `tbody` / `tr` / `desc`) |
|
|
266
|
+
| `form.js` | 表单、输入框、文本域、下拉、单选/复选、开关、日期选择器、标签输入等 |
|
|
267
|
+
| `layout.js` | 卡片、栅格行/列、列表、图片集、描述列表等 |
|
|
268
|
+
| `chart.js` | 纯 SVG 零依赖图表:bar / line / pie / radar / donut / scatter / gantt / funnel |
|
|
269
|
+
| `lightbox.js` | 图片灯箱预览 |
|
|
270
|
+
|
|
271
|
+
容器类型(需 `[/type]` 闭合,完整列表见 `parser.js` 的 `CONTAINERS` Set):
|
|
272
|
+
|
|
273
|
+
```
|
|
274
|
+
form table thead tbody card ft row col list select radio code imgs md textarea
|
|
275
|
+
tabs tab accordion collapse dialog btngroup picker timeline steps drawer ol ul i
|
|
276
|
+
item think bubble toolbar badge-box dropdown transfer cascader tree tn step desc
|
|
277
|
+
carousel popover input-tag watermark menu
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
---
|
|
281
|
+
|
|
282
|
+
## Builder API(服务端)
|
|
283
|
+
|
|
284
|
+
`TokUIBuilder` 提供链式调用生成 DSL,两种输出方式:
|
|
285
|
+
|
|
286
|
+
```js
|
|
287
|
+
const b = new TokUIBuilder();
|
|
288
|
+
|
|
289
|
+
// toString() —— 一次性输出完整字符串
|
|
290
|
+
b.card({ tt: '卡片' }).p('内容').end();
|
|
291
|
+
const dsl = b.toString();
|
|
292
|
+
|
|
293
|
+
// toChunks() —— 分块数组,配合 SSE 逐块推送
|
|
294
|
+
const chunks = b.reset().card({ tt: '卡片' }).p('内容').end().toChunks();
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
**自动闭合**:`toString()` / `toChunks()` 内部调用 `_finalizeChunks()`,未关闭容器会自动补全,无需手动 `endAll()`。
|
|
298
|
+
|
|
299
|
+
**双行为方法**:`thead()`、`inputTag()`、`quickReply()`、`agent()` 根据参数自动选择自闭合或容器模式。
|
|
300
|
+
|
|
301
|
+
**命名避让**:布局用 `row_layout()` / `col_layout()` 以避让表格的 `row()`。
|
|
302
|
+
|
|
303
|
+
---
|
|
304
|
+
|
|
305
|
+
## 主题系统
|
|
306
|
+
|
|
307
|
+
通过 CSS 变量 + `data-tokui-theme` 属性切换:
|
|
308
|
+
|
|
309
|
+
```js
|
|
310
|
+
import { setTheme } from '@jboltai/tokui';
|
|
311
|
+
setTheme('dark'); // 切换为暗色主题
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
自定义主题色可用色阶生成器:
|
|
315
|
+
|
|
316
|
+
```js
|
|
317
|
+
import { generatePalette, generateThemeTokens } from '@jboltai/tokui';
|
|
318
|
+
const tokens = generateThemeTokens({ primary: '#1677ff', danger: '#ff4d4f' });
|
|
319
|
+
// 输出 { '--tokui-primary-1' ... '--tokui-primary-10' } 共 10 级 CSS 变量映射
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
---
|
|
323
|
+
|
|
324
|
+
## 扩展组件
|
|
325
|
+
|
|
326
|
+
新增一个组件需四步:
|
|
327
|
+
|
|
328
|
+
1. **注册渲染函数**(`src/components/*.js`):
|
|
329
|
+
|
|
330
|
+
```js
|
|
331
|
+
renderer.register('mycard', (node, rc, parentType) => {
|
|
332
|
+
const el = renderer.el('div', { class: 'tokui-mycard' });
|
|
333
|
+
el.textContent = node.attrs.tt || '';
|
|
334
|
+
rc(node.children, el); // 递归渲染子节点
|
|
335
|
+
return el;
|
|
336
|
+
});
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
2. **若为容器类型**,加入 `src/core/parser.js` 的 `CONTAINERS` Set。若内容含 `[` 不应被解析(如代码),同时加入 `_isRawContent()` 类型列表。
|
|
340
|
+
|
|
341
|
+
3. **添加 Builder 方法**(`src/server/tokui-builder.js`):自闭合用 `_selfClosing()`,容器用 `_open()` / `end()`。
|
|
342
|
+
|
|
343
|
+
4. **添加样式**(`src/styles/tokui.css`):类名 `.tokui-mycard`,变体用 `.tokui-mycard--{variant}` 并加入 `renderer.js` 的 `VARIANTS` 白名单。
|
|
344
|
+
|
|
345
|
+
最后在 `tests/` 补测试(见下)。
|
|
346
|
+
|
|
347
|
+
---
|
|
348
|
+
|
|
349
|
+
## 测试
|
|
350
|
+
|
|
351
|
+
基于 Node.js 内置 `assert` 的自定义 runner,零测试框架依赖:
|
|
352
|
+
|
|
353
|
+
```bash
|
|
354
|
+
npm test # 全量 24 个测试文件,866+ 用例
|
|
355
|
+
npm run test:parser # 仅解析器
|
|
356
|
+
npm run test:builder
|
|
357
|
+
npm run test:core # event-bus + theme + renderer
|
|
358
|
+
npm run typecheck # tsc 类型检查(含反向 @ts-expect-error 断言)
|
|
359
|
+
npm run coverage # c8 覆盖率(核心模块 ~91%)
|
|
360
|
+
|
|
361
|
+
node tests/test-xxx.js # 跑单个测试文件
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
renderer 测试依赖 `tests/helpers/dom-mock.js` 提供的最小化 DOM mock。断言失败进程退出码为 1。
|
|
365
|
+
|
|
366
|
+
---
|
|
367
|
+
|
|
368
|
+
## 项目结构
|
|
369
|
+
|
|
370
|
+
```
|
|
371
|
+
.
|
|
372
|
+
├── src/
|
|
373
|
+
│ ├── core/ # 解析器、渲染器、事件总线、主题、色阶生成器
|
|
374
|
+
│ ├── components/ # 组件库(basic/table/form/layout/chart/lightbox)
|
|
375
|
+
│ ├── server/ # Builder 链式 API + SSE 演示服务器
|
|
376
|
+
│ ├── styles/ # tokui.css + themes/(default, dark)
|
|
377
|
+
│ └── index.js # 主入口,整合 TokUI 类
|
|
378
|
+
├── packages/ # 框架适配器 monorepo(pnpm workspace)
|
|
379
|
+
│ ├── react/ # @jboltai/tokui-react
|
|
380
|
+
│ ├── vue/ # @jboltai/tokui-vue
|
|
381
|
+
│ ├── svelte/ # @jboltai/tokui-svelte
|
|
382
|
+
│ ├── webc/ # @jboltai/tokui-webc(Web Component)
|
|
383
|
+
├── demo/ # 组件画廊演示
|
|
384
|
+
├── tests/ # 自定义 runner 测试套件(24 文件 / 866+ 用例)
|
|
385
|
+
├── docs/ # VitePress 文档站
|
|
386
|
+
└── package.json
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
---
|
|
390
|
+
|
|
391
|
+
## 路线图
|
|
392
|
+
|
|
393
|
+
TokUI 正在向多语言后端 SDK 与多样式库前端主题演进。
|
|
394
|
+
|
|
395
|
+
> 图例:✅ 已支持 · 🚧 规划中
|
|
396
|
+
|
|
397
|
+
### 后端 SDK 多语言支持
|
|
398
|
+
|
|
399
|
+
| 语言 / 运行时 | 状态 | 说明 |
|
|
400
|
+
|---------------|:----:|------|
|
|
401
|
+
| Node.js | ✅ | `TokUIBuilder` 链式 API + SSE 演示服务器(当前唯一实现) |
|
|
402
|
+
| Python | 🚧 | 规划中 |
|
|
403
|
+
| Rust | 🚧 | 规划中 |
|
|
404
|
+
| Java | 🚧 | 规划中 |
|
|
405
|
+
| Go | 🚧 | 规划中 |
|
|
406
|
+
| 跨语言 DSL 规范固化 | 🚧 | 共享解析契约,保证各 SDK 输出一致 |
|
|
407
|
+
|
|
408
|
+
### 前端集成
|
|
409
|
+
|
|
410
|
+
| 能力 | 状态 | 说明 |
|
|
411
|
+
|------|:----:|------|
|
|
412
|
+
| React / Vue / Svelte / Web Component 适配器 | ✅ | `@jboltai/tokui-{react,vue,svelte,webc}` |
|
|
413
|
+
| CSS 变量主题(`default` / `dark`) | ✅ | `data-tokui-theme` 切换 |
|
|
414
|
+
| HSB 色板生成器 | ✅ | 任意主色生成 10 级色阶 |
|
|
415
|
+
| TailwindCSS 适配 | 🚧 | 原子类映射 / 主题 token 桥接 |
|
|
416
|
+
| UnoCSS 适配 | 🚧 | 规划中 |
|
|
417
|
+
| 主题市场 / 主题分享 | 🚧 | 社区可分享主题包 |
|
|
418
|
+
|
|
419
|
+
---
|
|
420
|
+
|
|
421
|
+
## License
|
|
422
|
+
|
|
423
|
+
[MIT](./LICENSE)
|