@zhang_jifan/fanui 2.1.0 → 2.1.1

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 CHANGED
@@ -3,6 +3,41 @@
3
3
  本项目的全部重要变更都记录在本文件中。格式基于 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/),
4
4
  版本遵循 [SemVer 2.0.0](https://semver.org/lang/zh-CN/)。
5
5
 
6
+ ## [2.1.1] - 2026-09-21
7
+
8
+ > 本次为**工具链与仓库整理**版本:库的公共 API(CSS 类名、`data-fanui-*`、`FanUI.*`)零变更,
9
+ > 使用者无需改动任何引用代码。`dist/` 除版本号字符串外与 2.1.0 一致。
10
+
11
+ ### 新增
12
+
13
+ - **`npm run selfcheck` —— 门禁元测试套件**(`scripts/selfcheck/`)。收录 5 个「验证门禁本身有没有牙齿」的脚本:
14
+ 包入口/副作用自洽(lint)、scope 归属(preflight)、a11y 违规捕获、install 超时退化、许可证声明与全文一致。
15
+ 每个脚本都**故意注入坏值**,坏值没被抓到即判失败。此前它们散落在 `_gate-logs/`(该目录被 `.gitignore` 忽略)
16
+ —— 换台机器就永久丢失,属结构性隐患;现提升为随仓库保留的正式资产。
17
+ - **`npm run verify:published` —— 「文档里的下载入口到底能不能下载」一键实测**(`scripts/verify-published.cjs`)。
18
+ 此前每条 CDN / npm 入口只在发布时人工点一遍,而 `<link>` 加载失败是**静默**的(页面只表现为「样式全没、控制台干净」)。
19
+ 现改为**从 `README.md` / `USAGE.md` / `PUBLISHING.md` / `demo/index.html` 自动抓取每一个 CDN URL**,与
20
+ `package.json` 入口字段推导出的「使用者会手拼的路径」合并,逐条真实请求并断言:
21
+ - HTTP 200 · 字节数 > 0 · 含 `.fanui-btn` / `--fanui-primary` / `FanUI` 特征串(不是「随便返回个 200 就算过」)
22
+ - **与本地 `dist/` 逐字节 sha256 比对**(证明下载到的就是本地产物)
23
+ - 网络类失败(ECONNRESET / 5xx / 429)**自动重试 3 次**后再判负 —— 避免 CDN 边缘节点抖动产生假红
24
+ - 真跑 `npm view`、`npm install`(装到临时目录、`require()` 取版本、检查包内关键文件齐全)、下载 registry tarball 并比对 `dist.shasum`
25
+ - **版本漂移检查**:文档里写死的版本号 ≠ `package.json` 的 version 时告警(发版后忘改文档会被抓出来)
26
+ 参数 `--quick`(只测链接,数秒)/ `--browser`(追加真实 Chrome 打开 CDN 页面读计算样式)/ `--json`(落报告)。
27
+ 退出码 `0` 全可用 · `1` 有入口失效 · `2` 本机网络不可达。**含断言链自检**:故意探测一个不存在的版本,若它没被判失败即报错退出。
28
+ 实测:`--quick` 11/11 全绿;完整版 12/12 全绿(`npm install` → `require()` 取到 `2.1.0`、关键文件齐全、tarball sha1 与 registry 记录一致);
29
+ `--browser` 12/12 全绿(Chrome 打开 CDN 页面:主按钮底色 `rgb(14, 116, 144)`、圆角 6px、卡片圆角 12px、`FanUI.version === "2.1.0"`、零加载失败)。
30
+ - **文档新增 `USAGE.md` §1.2.1「怎么确认这几条链接 / 命令真的能下载?」** —— 三档自检法(浏览器直接粘链接 / `curl -sI` + `npm view` / 一键脚本)与逐项判据表、退出码含义;`README.md` §3.0 与 `PUBLISHING.md`「第 4 步 · 立刻验证」均已加入指引。
31
+ ### 整理(仓库瘦身)
32
+
33
+ - **删除 183 个可再生产物 / 18.4 MB**,判据是 `.gitignore` 已声明的「每次跑门禁重建」:`_gate-logs/` 全部运行日志与一次性探针、
34
+ `shots/*.png`(保留 `visual-baseline/` 5 张基线)、`shots/_diff/`、`demo/shots/`、`examples/shots/`、`reports/*.json`。
35
+ - **删除 2 份已过时的过程文档**:`GAP-ANALYSIS.md`(38 项缺口清单,已 100% 完成)、`reports/COMPLETENESS-AUDIT.md`(完整度审计待办,所列问题均已修复)。
36
+ 两者结论均已完整收录进本文件 `[2.1.0]` 段;留着容易被误读为「仍有缺口」。
37
+ - **删除 1 个孤立脚本**:`scripts/debug-theme.cjs`(未被任何 npm script 引用,功能与 `audit-coverage.cjs` 重叠)。
38
+ - **删除 `_gate-logs/_verify-published.cjs`**(一次性探针,内含硬编码 npm 路径),其职责由 `verify:published --browser` 完整接管。
39
+ - 保留了 `reports/` 下的三份人读报告(`DELIVERY-VERIFICATION.md` / `audit-coverage.md` / `matrix-report.md`)与全部 `examples/`。
40
+
6
41
  ## [2.1.0] - 2026-09-18
7
42
 
8
43
  ### 新增(对应缺口清单 A / B / C / D / E / F / G 全量落地)
@@ -37,7 +72,14 @@
37
72
  - **文档:新增「`file://` 下 ES Module 不可用」的实测结论**。实测 `<script type="module">` 在 `file://` 下被 CORS 拦截(`Access to script ... blocked by CORS policy`),表现为「样式正常但 JS 完全没生效」;经典 `<script src>` 不受影响。已写入 `examples/README.md`,避免使用者把模块示例也理解成「双击即可运行」。
38
73
  - **文案:不再以「零依赖 / 零构建」作为卖点**,改为陈述真实交付能力(可直接引入编译产物 / 也可 npm + ESM + SCSS)。涉及 `package.json` description、`demo/index.html` meta 与能力卡、`README` 标语与章节名、`DESIGN-SYSTEM.md` 小节名、示例页与 `USAGE.md` 的脚注。
39
74
  - **验证报告**:完整的过程、证据与复现方式见 `reports/DELIVERY-VERIFICATION.md`。
40
- ### 命名与引用链路(2026-09-21 · 仍未发布,随 2.1.0 首发)
75
+ ### 🚀 首发发布(2026-09-21
76
+
77
+ - **`@zhang_jifan/fanui@2.1.0` 已发布到 npm**(`npm publish --access public`,EXIT=0 / 2m32s)。tarball `zhang_jifan-fanui-2.1.0.tgz` · 624.0 kB · 解包 3.9 MB · 127 文件 · shasum `7ee6225760357c7984318bc0073cc4901d4cf9df`。发布后 registry / jsDelivr / unpkg 全部 HTTP 200(发布前全 404)。
78
+ - **发布后终验(真实浏览器)**:从 registry 全新安装 → Chrome 引用页面。本地引用与 CDN 引用(jsDelivr CSS + unpkg JS)双路径均通过 —— 样式表 3508 条规则、主按钮底色 `rgb(14, 116, 144)`(= `--fanui-primary #0e7490`)、圆角 6px、卡片圆角 12px、`window.FanUI.version === "2.1.0"`、零控制台错误。
79
+ - **修复:`npm publish --dry-run` 必然假失败**(较高)。npm 会向子进程注入 `npm_config_dry_run=true`,使 `prepublishOnly` 里 `verify:install` 内层的 `npm pack` **变成「假装打包」不写文件**,门禁报「未产出 tarball」。而正式发布没有该标志、反倒正常 —— 极易被误判成代码缺陷。现 `scripts/verify-install.cjs` 的 npm 调用改用 `cleanEnv()` 剥离该变量;坏值自检:注入 `npm_config_dry_run=true` 后仍须 EXIT=0。
80
+ - **`preflight` 新增「scope 归属」硬检查**(见下节)。首发生效:注入伪用户名即阻断,注入真实用户名放行。
81
+ - **文档同步**:包上线后回改先前基于「未发布」写的告警 —— `USAGE.md` §1.2「CDN 引入」从「⚠️ 当前不可用(全部 404)」改为「✅ 已可用」并附实测读数;`README.md` 新增 §3.0「零安装:CDN 直接引用」;`demo/index.html`「三步接入」补回 CDN 命令行块(当初因无可用 CDN 而被移除);`PUBLISHING.md` §0 结论更新为「已发布」并新增 §3.7「用 token 直写登录 + 首次发布 404 的三处真因」。
82
+ ### 命名与引用链路(2026-09-21 · 已随 2.1.0 首发)
41
83
 
42
84
  - **包名改为 `@zhang_jifan/fanui`(scoped)**。原定包名 `fanui` 会被 npm 的 New Package Moniker 规则拦下 —— 新包名去标点并小写后与已存在的 `fan-ui` 相同,服务端在**最终 PUT** 时才返回 `Package name too similar to existing package`,而 `npm view` 返回 404、`npm publish --dry-run` 也会通过,本地自测永远发现不了。scoped 包不受该规则约束;其默认私有,故 `publishConfig.access` 已显式设为 `public`。**关键:CSS 类名前缀、`data-fanui-*` 属性与源码里的 `PREFIX` / `$prefix` 常量永远是 `fanui`,与包名无关** —— 改名时把它们一起改掉,运行时拼出的选择器会变成以 @ 开头、含斜杠的非法形式(形如 `.@scope/name-tabs`),一个常量出错即可让 15 项门禁炸掉 13 项(本次真实踩坑,已加哨兵防复发)。
43
85
  - **修复:`sideEffects` 白名单漏了 `dist/fanui.mjs`**(高)。该文件正是 `exports["."].import` / `.default` 的落点,漏掉它会让打包器把 `import "@zhang_jifan/fanui";` 这种**纯副作用引入**(只为触发 `data-fanui-*` 自动初始化)整块 tree-shake 掉,表现为「装了包但交互全部消失」。同时 `exports` 补齐 `"./style"` / `"./style.min"` 别名(此前只提供带 `.css` 后缀的写法)。
package/README.md CHANGED
@@ -62,18 +62,24 @@ fanUI/
62
62
  │ ├── _borders.scss # 边框 / 圆角 / 分割线
63
63
  │ ├── _effects.scss # 阴影 / 滤镜 / 背景 / 交互
64
64
  │ └── _texture.scss # ★ 极光/网格/噪点/渐变描边/流光/涟漪
65
- ├── scripts/
66
- │ ├── build.cjs # 构建脚本(自动定位 sass)
67
- │ ├── audit-theme.cjs # 对比度审计 → theme-audit.md
68
- └── verify-demo.cjs # 真实浏览器回归(组合遍历/交互/截图)
65
+ ├── scripts/ # 门禁与工具链(`npm run gates` 一键全跑)
66
+ │ ├── build.cjs # 构建脚本(自动定位 sass)
67
+ │ ├── run-gates.cjs # 全量门禁编排
68
+ ├── verify-*.cjs # 专项验证:demo / examples / ssr / install / visual / browsers / edge …
69
+ │ ├── audit-*.cjs # 审计:覆盖度 / 对比度 / 无障碍
70
+ │ ├── verify-published.cjs # 发布后:把文档里每个下载入口逐条实测
71
+ │ ├── preflight-publish.cjs # 发布资格自检
72
+ │ └── selfcheck/ # 门禁元测试(故意注入坏值,没被抓到就失败)
69
73
  ├── dist/ # 编译产物
70
- │ ├── fanui.css # 已展开(开发用)
71
- │ ├── fanui.min.css # 已压缩(生产用)
72
- └── fanui.js # JS 运行时(由 src 复制)
74
+ │ ├── fanui.css / fanui.min.css # 样式(展开版 / 压缩版)
75
+ │ ├── fanui.js / .mjs / .cjs # 运行时三种入口:IIFE / ESM / CommonJS(+SSR 门面)
76
+ ├── fanui.d.ts # TypeScript 类型声明
77
+ │ └── modules/ # 分模块 CSS(可单独引入其中一块)
78
+ ├── shots/
79
+ │ └── visual-baseline/ # 视觉回归基线(其余截图都是每次跑门禁重建的产物)
73
80
  └── demo/
74
81
  ├── index.html # ★ 场景化演示站:官网/博客/控制台/组件/设计系统 5 场景
75
- ├── components.html # 全组件百科页(令牌/排版/栅格/组件/工具类)
76
- └── shots/ # 浏览器回归截图(14 张)
82
+ └── components.html # 全组件百科页(令牌/排版/栅格/组件/工具类)
77
83
  ```
78
84
 
79
85
  ---
@@ -119,6 +125,20 @@ fanUI/
119
125
 
120
126
  > 逐步可照做的完整接入说明(含包管理器 / CDN / React 多版本 / Vue2·Vue3 写法)见 **[USAGE.md](./USAGE.md)**;下面是最短路径。
121
127
 
128
+ ### 3.0 零安装:CDN 直接引用(最快验证)
129
+
130
+ 不想装任何东西?把下面两行贴进 HTML 就能看到完整效果(包已发布到 npm,CDN 可用):
131
+
132
+ ```html
133
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@zhang_jifan/fanui@2.1.1/dist/fanui.min.css">
134
+ <script src="https://cdn.jsdelivr.net/npm/@zhang_jifan/fanui@2.1.1/dist/fanui.js"></script>
135
+ ```
136
+
137
+ > 也可换用 unpkg:把域名换成 `https://unpkg.com`,路径完全相同。
138
+ > `@2.1.1` 可写成 `@2` 自动跟进 2.x;正式项目建议锁定完整版本号。
139
+ > 内网或离线环境请看 [USAGE.md §1.2](./USAGE.md#12-方式二cdn-引入) 的本地镜像写法。
140
+ > **不确定这几条链接是否可用?** `npm run verify:published` 会把本文档里的每个下载入口真跑一遍;手工验证方法见 [USAGE.md §1.2.1](./USAGE.md#121-怎么确认这几条链接--命令真的能下载)。
141
+
122
142
  ### 3.1 直接使用编译产物(不接构建流程)
123
143
 
124
144
  ```html
package/USAGE.md CHANGED
@@ -128,30 +128,73 @@ fanUI 由**两个文件**组成,引入时只需要关心它们:
128
128
 
129
129
  ### 1.2 方式二:CDN 引入
130
130
 
131
- > ⚠️ **当前不可用(2026-09-21 实测核实):fanUI 尚未成功发布到 npm,本节的几条 CDN 链接一律返回 404。**
132
- > 症状是页面**完全没样式、且浏览器不报错**(`<link>` 加载失败是静默的,只看到裸 HTML)。
133
- > 在包正式发布之前,请改用「方式一:本地文件」或「方式三:本地安装」。
131
+ > **已可用(2026-09-21 发布后实测):`@zhang_jifan/fanui@2.1.1` 已发布到 npm,本节 CDN 链接全部返回 200。**
132
+ > 实测方式:真实 Chrome 加载 CDN 页面 → 样式表加载成功(3508 条规则)、主按钮底色 `rgb(14, 116, 144)`、`window.FanUI.version === "2.1.1"`。
134
133
  > 想确认包是否已发布:`npm view @zhang_jifan/fanui version`(返回 404 即尚未发布)。发布流程见 [PUBLISHING.md](./PUBLISHING.md)。
135
134
 
136
135
  **适用**:快速验证、演示页、内网无法 npm 的环境。**需要联网**(首次会下载文件)。
137
- **前提**:包已发布到 npm —— 未发布时本节写法不可用。
136
+ **前提**:包已发布到 npm(✅ `2.1.1` 已发布,可直接使用)。若 `npm view` 返回 404,说明版本被撤销或你写错了包名。
138
137
 
139
138
  ```html
140
139
  <!-- jsDelivr(需包已发布) -->
141
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@zhang_jifan/fanui@2.1.0/dist/fanui.min.css">
142
- <script src="https://cdn.jsdelivr.net/npm/@zhang_jifan/fanui@2.1.0/dist/fanui.js"></script>
140
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@zhang_jifan/fanui@2.1.1/dist/fanui.min.css">
141
+ <script src="https://cdn.jsdelivr.net/npm/@zhang_jifan/fanui@2.1.1/dist/fanui.js"></script>
143
142
 
144
143
  <!-- 或 unpkg(需包已发布) -->
145
- <link rel="stylesheet" href="https://unpkg.com/@zhang_jifan/fanui@2.1.0/dist/fanui.min.css">
146
- <script src="https://unpkg.com/@zhang_jifan/fanui@2.1.0/dist/fanui.js"></script>
144
+ <link rel="stylesheet" href="https://unpkg.com/@zhang_jifan/fanui@2.1.1/dist/fanui.min.css">
145
+ <script src="https://unpkg.com/@zhang_jifan/fanui@2.1.1/dist/fanui.js"></script>
147
146
  ```
148
147
 
149
148
  引入后的用法与「方式一」**完全相同**(同样是全局 `FanUI` 对象)。
150
149
 
151
- > 说明:`@2.1.0` 是版本号。写 `@2` 可自动跟进 2.x 小版本;正式项目建议锁定完整版本号。
150
+ > 说明:`@2.1.1` 是版本号。写 `@2` 可自动跟进 2.x 小版本;正式项目建议锁定完整版本号。
152
151
  > 若你所在环境无法访问公网 CDN,请回到「方式一」使用本地文件。
153
152
 
154
- **发布前想「像 CDN 那样」引用?** `dist/` 拷到任意静态服务器即可,效果与 CDN 等价:
153
+ #### 1.2.1 怎么确认这几条链接 / 命令真的能下载?
154
+
155
+ 三条链路(`npm install` · jsDelivr · unpkg)都可能在「包没发上去 / 版本号写错 / 路径拼错」时**静默失效** ——
156
+ `<link>` 加载失败不会报错,页面只表现为「样式全没、控制台干净」。所以别靠肉眼,按下面三档自检:
157
+
158
+ **① 最快(5 秒,只看链接通不通)**:把 CSS 链接**直接粘进浏览器地址栏**。
159
+ 看到一大段 CSS 文本 = 可下载;出现 404 / `Cannot find` 页面 = 不可用(此时页面引用必然没样式)。
160
+
161
+ **② 命令行逐条(不用装任何东西)**:
162
+
163
+ ```bash
164
+ # CDN 链接:期望第一行是 HTTP/2 200
165
+ curl -sI "https://cdn.jsdelivr.net/npm/@zhang_jifan/fanui@2.1.1/dist/fanui.min.css" | head -1
166
+ curl -sI "https://unpkg.com/@zhang_jifan/fanui@2.1.1/dist/fanui.js" | head -1
167
+
168
+ # 包是否在 registry 上(返回版本号即正常;报 404 说明未发布或版本写错)
169
+ npm view @zhang_jifan/fanui version
170
+
171
+ # 安装命令:在空目录里真装一遍
172
+ mkdir /tmp/t && cd /tmp/t && npm i @zhang_jifan/fanui
173
+ ```
174
+
175
+ **③ 一条命令全测(推荐,本仓库自带)**:
176
+
177
+ ```bash
178
+ npm run verify:published # 文档里每个下载入口都真跑一遍(网络 + npm 安装 + tarball)
179
+ npm run verify:published -- --quick # 跳过 npm install,只测链接(数秒)
180
+ npm run verify:published -- --browser # 追加:用真实 Chrome 打开 CDN 页面,读计算样式确认「真的生效」
181
+ ```
182
+
183
+ 它会**从 README / USAGE / demo 页里自动抓出每一个下载入口**,逐条给结论:
184
+
185
+ | 检查项 | 判据 |
186
+ |---|---|
187
+ | 死链扫描 | 文档里出现的每个 CDN URL 都必须 HTTP 200(文档写了死链也拦得住) |
188
+ | 不只是 200 | 字节数 > 0、含 `.fanui-btn` / `--fanui-primary` / `FanUI` 特征串 |
189
+ | 内容对得上 | 下载内容与本地 `dist/` 逐字节比对,一致才打 `=本地` |
190
+ | 版本漂移 | 链接里写死的版本号 ≠ `package.json` 的 version 时告警(防止发版后忘改文档) |
191
+ | npm 链路 | 真的 `npm view` + `npm install` 到临时目录,检查包内关键文件是否齐全 |
192
+ | tarball | 下载 tgz 并比对 registry 记录的 sha1 |
193
+ | 自检 | 故意探测一个不存在的版本,若它没被判失败 → 脚本报错退出(防止门禁被写成假通过) |
194
+
195
+ 退出码:`0` 全部可用 · `1` 有入口失效(按输出的 ✗ 逐条修)· `2` 本机网络不可达(换网络再跑,不是包的问题)。
196
+
197
+ **无法访问公网 CDN 时(内网 / 离线环境)?** 把 `dist/` 拷到任意静态服务器即可,效果与 CDN 等价:
155
198
 
156
199
  ```html
157
200
  <!-- 例:把 fanUI/dist 整个拷到站点下的 /fanui/ 目录 -->
@@ -159,8 +202,8 @@ fanUI 由**两个文件**组成,引入时只需要关心它们:
159
202
  <script src="/fanui/fanui.js"></script>
160
203
  ```
161
204
 
162
- > 内网分发也可 `npm pack` 打出 tarball(`zhang_jifan-fanui-2.1.0.tgz`)放到制品库,
163
- > 他人 `npm install ./zhang_jifan-fanui-2.1.0.tgz` 后即可按「方式三」引用 —— 这条链路正是 `npm run verify:install` 每次门禁都会实测的。
205
+ > 内网分发也可 `npm pack` 打出 tarball(`zhang_jifan-fanui-2.1.1.tgz`)放到制品库,
206
+ > 他人 `npm install ./zhang_jifan-fanui-2.1.1.tgz` 后即可按「方式三」引用 —— 这条链路正是 `npm run verify:install` 每次门禁都会实测的。
164
207
 
165
208
  ---
166
209
 
@@ -177,8 +220,8 @@ npm install @zhang_jifan/fanui
177
220
  # 或:还没发布时,直接把本仓库作为本地包安装(推荐,见 examples/)
178
221
  npm install ../fanUI # 路径写 fanUI 仓库目录
179
222
  # 或先打包再安装:
180
- # cd fanUI && npm pack → 生成 zhang_jifan-fanui-2.1.0.tgz
181
- # npm install ./zhang_jifan-fanui-2.1.0.tgz
223
+ # cd fanUI && npm pack → 生成 zhang_jifan-fanui-2.1.1.tgz
224
+ # npm install ./zhang_jifan-fanui-2.1.1.tgz
182
225
 
183
226
  # pnpm / yarn 同理
184
227
  pnpm add @zhang_jifan/fanui
@@ -1121,7 +1164,7 @@ document.addEventListener("fanui:pincomplete", (e) => {
1121
1164
  | `FanUI.$$(sel, scope)` | 同上 | `querySelectorAll` 快捷方式,返回**真数组** |
1122
1165
  | `FanUI.lockScroll()` / `unlockScroll()` | 无 | 手动锁定/解锁页面滚动(引用计数,可嵌套) |
1123
1166
  | `FanUI.ripple(host, event?)` | `host`:元素或选择器;`event`:点击事件(可不传,取元素中心) | 程序化触发涟漪 |
1124
- | `FanUI.version` / `FanUI.prefix` | 属性 | 当前版本号(`"2.1.0"`)/ 类名前缀(`"fanui"`) |
1167
+ | `FanUI.version` / `FanUI.prefix` | 属性 | 当前版本号(`"2.1.1"`)/ 类名前缀(`"fanui"`) |
1125
1168
 
1126
1169
  ---
1127
1170
 
@@ -1273,7 +1316,7 @@ document.addEventListener("fanui:pincomplete", (e) => {
1273
1316
 
1274
1317
  | 项 | 要求 | 说明 |
1275
1318
  |---|---|---|
1276
- | fanui | `2.1.0` | 本文档对应版本 |
1319
+ | fanui | `2.1.1` | 本文档对应版本 |
1277
1320
  | 浏览器 | Chrome / Edge / Firefox / Safari **最近两个大版本** | 常青浏览器 |
1278
1321
  | Node.js(仅自行编译 SCSS 时需要) | ≥ 18 | 只用 dist 产物则完全不需要 Node |
1279
1322
  | sass(仅自行编译 SCSS 时需要) | `>= 1.79.0` | devDependencies 里声明为 `^1.90.0`;`npm i -D sass` 即装 |
@@ -1289,7 +1332,7 @@ document.addEventListener("fanui:pincomplete", (e) => {
1289
1332
  4. **`file://` 协议**:`<script>` 引入方式可直接双击运行;但**原生 ESM 方式**(`type="module"`)会被 CORS 拦截,需本地服务器(`npx serve .`)。
1290
1333
  5. **剪贴板**:`data-fanui-copy` 优先用 Clipboard API(需 HTTPS 或 localhost),非安全上下文自动降级 `execCommand`。
1291
1334
  6. **localStorage**:偏好持久化在键 `fanui-prefs`;隐私模式下自动静默降级(不记忆但不报错)。
1292
- 7. **升级版本**:类名与 CSS 变量都有 `fanui` 前缀隔离,升级一般只需替换 dist 文件;建议锁定版本号(如 CDN 写 `@2.1.0`)。
1335
+ 7. **升级版本**:类名与 CSS 变量都有 `fanui` 前缀隔离,升级一般只需替换 dist 文件;建议锁定版本号(如 CDN 写 `@2.1.1`)。
1293
1336
 
1294
1337
  ---
1295
1338
 
package/dist/fanui.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  /* =============================================================================
2
- * fanUI v2.1.0 · CommonJS 入口
2
+ * fanUI v2.1.1 · CommonJS 入口
3
3
  * -----------------------------------------------------------------------------
4
4
  * const FanUI = require("@zhang_jifan/fanui");
5
5
  *
package/dist/fanui.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /* =============================================================================
2
- * fanUI v2.1.0 · TypeScript 类型声明
2
+ * fanUI v2.1.1 · TypeScript 类型声明
3
3
  * -----------------------------------------------------------------------------
4
4
  * tsconfig 中配置 "types": ["@zhang_jifan/fanui"] 或在代码里:
5
5
  * import FanUI from "@zhang_jifan/fanui";
package/dist/fanui.esm.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /* =============================================================================
2
- * fanUI v2.1.0 · ESM 入口
2
+ * fanUI v2.1.1 · ESM 入口
3
3
  * -----------------------------------------------------------------------------
4
4
  * import FanUI from "@zhang_jifan/fanui"; // 默认导出 = 完整命名空间
5
5
  * import { theme, toast } from "@zhang_jifan/fanui"; // 具名导出 = 各子模块
package/dist/fanui.js CHANGED
@@ -33,7 +33,7 @@
33
33
 
34
34
  var PREFIX = "fanui";
35
35
 
36
- var VERSION = "2.1.0";
36
+ var VERSION = "2.1.1";
37
37
 
38
38
  /** HTML 转义 —— 服务端与客户端共用,任何插值都必须过这里 */
39
39
  function escapeHtml(v) {
package/dist/fanui.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  /* =============================================================================
2
- * fanUI v2.1.0 · ESM 入口
2
+ * fanUI v2.1.1 · ESM 入口
3
3
  * -----------------------------------------------------------------------------
4
4
  * import FanUI from "@zhang_jifan/fanui"; // 默认导出 = 完整命名空间
5
5
  * import { theme, toast } from "@zhang_jifan/fanui"; // 具名导出 = 各子模块
@@ -1,4 +1,4 @@
1
- /* fanUI v2.1.0 · module: advanced(独立产物,自带令牌) */
1
+ /* fanUI v2.1.1 · module: advanced(独立产物,自带令牌) */
2
2
  @charset "UTF-8";
3
3
  .fanui-loading-bar {
4
4
  position: fixed;
@@ -1,4 +1,4 @@
1
- /* fanUI v2.1.0 · module: alert(独立产物,自带令牌) */
1
+ /* fanUI v2.1.1 · module: alert(独立产物,自带令牌) */
2
2
  .fanui-alert {
3
3
  position: relative;
4
4
  display: flex;
@@ -1,4 +1,4 @@
1
- /* fanUI v2.1.0 · module: badge(独立产物,自带令牌) */
1
+ /* fanUI v2.1.1 · module: badge(独立产物,自带令牌) */
2
2
  .fanui-badge {
3
3
  display: inline-flex;
4
4
  align-items: center;
@@ -1,4 +1,4 @@
1
- /* fanUI v2.1.0 · module: base(独立产物,自带令牌) */
1
+ /* fanUI v2.1.1 · module: base(独立产物,自带令牌) */
2
2
  @charset "UTF-8";
3
3
  *,
4
4
  *::before,
@@ -1,4 +1,4 @@
1
- /* fanUI v2.1.0 · module: blog(独立产物,自带令牌) */
1
+ /* fanUI v2.1.1 · module: blog(独立产物,自带令牌) */
2
2
  .fanui-read-meta {
3
3
  display: flex;
4
4
  flex-wrap: wrap;
@@ -1,4 +1,4 @@
1
- /* fanUI v2.1.0 · module: button(独立产物,自带令牌) */
1
+ /* fanUI v2.1.1 · module: button(独立产物,自带令牌) */
2
2
  .fanui-btn {
3
3
  --fanui-btn-bg: var(--fanui-primary);
4
4
  --fanui-btn-fg: var(--fanui-primary-fg, #fff);
@@ -1,4 +1,4 @@
1
- /* fanUI v2.1.0 · module: card(独立产物,自带令牌) */
1
+ /* fanUI v2.1.1 · module: card(独立产物,自带令牌) */
2
2
  .fanui-card {
3
3
  --fanui-card-padding: var(--fanui-space-5);
4
4
  --fanui-card-radius: var(--fanui-radius-lg);
@@ -1,4 +1,4 @@
1
- /* fanUI v2.1.0 · module: choice(独立产物,自带令牌) */
1
+ /* fanUI v2.1.1 · module: choice(独立产物,自带令牌) */
2
2
  .fanui-select, .fanui-select-multiple {
3
3
  display: block;
4
4
  width: 100%;
@@ -1,4 +1,4 @@
1
- /* fanUI v2.1.0 · module: dashboard(独立产物,自带令牌) */
1
+ /* fanUI v2.1.1 · module: dashboard(独立产物,自带令牌) */
2
2
  .fanui-kpi {
3
3
  display: flex;
4
4
  flex-direction: column;
@@ -1,4 +1,4 @@
1
- /* fanUI v2.1.0 · module: data(独立产物,自带令牌) */
1
+ /* fanUI v2.1.1 · module: data(独立产物,自带令牌) */
2
2
  .fanui-avatar {
3
3
  --fanui-avatar-size: 40px;
4
4
  --fanui-avatar-radius: 50%;
@@ -1,4 +1,4 @@
1
- /* fanUI v2.1.0 · module: feedback(独立产物,自带令牌) */
1
+ /* fanUI v2.1.1 · module: feedback(独立产物,自带令牌) */
2
2
  .fanui-progress {
3
3
  --fanui-progress-h: 8px;
4
4
  --fanui-progress-radius: var(--fanui-radius-full);
@@ -1,4 +1,4 @@
1
- /* fanUI v2.1.0 · module: form(独立产物,自带令牌) */
1
+ /* fanUI v2.1.1 · module: form(独立产物,自带令牌) */
2
2
  @charset "UTF-8";
3
3
  .fanui-form {
4
4
  display: block;
@@ -1,4 +1,4 @@
1
- /* fanUI v2.1.0 · module: glass(独立产物,自带令牌) */
1
+ /* fanUI v2.1.1 · module: glass(独立产物,自带令牌) */
2
2
  .fanui-glass {
3
3
  position: relative;
4
4
  isolation: isolate;
@@ -1,4 +1,4 @@
1
- /* fanUI v2.1.0 · module: input-plus(独立产物,自带令牌) */
1
+ /* fanUI v2.1.1 · module: input-plus(独立产物,自带令牌) */
2
2
  @charset "UTF-8";
3
3
  .fanui-slider {
4
4
  --fanui-slider-fill: 50%;
@@ -1,4 +1,4 @@
1
- /* fanUI v2.1.0 · module: interactive(独立产物,自带令牌) */
1
+ /* fanUI v2.1.1 · module: interactive(独立产物,自带令牌) */
2
2
  .fanui-command {
3
3
  position: fixed;
4
4
  top: 0;
@@ -1,4 +1,4 @@
1
- /* fanUI v2.1.0 · module: layout(独立产物,自带令牌) */
1
+ /* fanUI v2.1.1 · module: layout(独立产物,自带令牌) */
2
2
  .fanui-container {
3
3
  width: 100%;
4
4
  padding-inline-end: 16px;
@@ -1,4 +1,4 @@
1
- /* fanUI v2.1.0 · module: marketing(独立产物,自带令牌) */
1
+ /* fanUI v2.1.1 · module: marketing(独立产物,自带令牌) */
2
2
  @charset "UTF-8";
3
3
  .fanui-announcement {
4
4
  display: flex;
@@ -1,4 +1,4 @@
1
- /* fanUI v2.1.0 · module: nav(独立产物,自带令牌) */
1
+ /* fanUI v2.1.1 · module: nav(独立产物,自带令牌) */
2
2
  @charset "UTF-8";
3
3
  .fanui-navbar {
4
4
  --fanui-navbar-height: 56px;
@@ -1,4 +1,4 @@
1
- /* fanUI v2.1.0 · module: overlay(独立产物,自带令牌) */
1
+ /* fanUI v2.1.1 · module: overlay(独立产物,自带令牌) */
2
2
  .fanui-modal {
3
3
  position: fixed;
4
4
  inset: 0;
@@ -1,4 +1,4 @@
1
- /* fanUI v2.1.0 · module: table(独立产物,自带令牌) */
1
+ /* fanUI v2.1.1 · module: table(独立产物,自带令牌) */
2
2
  .fanui-table-wrap {
3
3
  position: relative;
4
4
  width: 100%;
@@ -1,4 +1,4 @@
1
- /* fanUI v2.1.0 · module: tabs(独立产物,自带令牌) */
1
+ /* fanUI v2.1.1 · module: tabs(独立产物,自带令牌) */
2
2
  .fanui-tabs {
3
3
  display: flex;
4
4
  flex-direction: column;
@@ -1,4 +1,4 @@
1
- /* fanUI v2.1.0 · module: themes(独立产物,自带令牌) */
1
+ /* fanUI v2.1.1 · module: themes(独立产物,自带令牌) */
2
2
  :root {
3
3
  --fanui-primary: #0e7490;
4
4
  --fanui-primary-fg: #ffffff;
@@ -1,4 +1,4 @@
1
- /* fanUI v2.1.0 · module: tokens(独立产物,自带令牌) */
1
+ /* fanUI v2.1.1 · module: tokens(独立产物,自带令牌) */
2
2
  :root {
3
3
  --fanui-primary-50: #ecfeff;
4
4
  --fanui-primary-100: #cffafe;
@@ -1,4 +1,4 @@
1
- /* fanUI v2.1.0 · module: utilities(独立产物,自带令牌) */
1
+ /* fanUI v2.1.1 · module: utilities(独立产物,自带令牌) */
2
2
  .fanui-m-0 {
3
3
  margin: 0;
4
4
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zhang_jifan/fanui",
3
- "version": "2.1.0",
3
+ "version": "2.1.1",
4
4
  "description": "fanUI —— 一套 UI 设计系统,内置 12 套可在运行时切换的主题配色,支持液态玻璃质感、明暗双模式;适配官网、博客与 B 端控制台场景。下载即可使用:可直接用 script/link 引入编译产物,也可通过 npm + ESM / SCSS 接入项目。",
5
5
  "keywords": [
6
6
  "css",
@@ -109,6 +109,8 @@
109
109
  "check:full": "npm run check && npm run audit:a11y && npm run verify:browsers && npm run verify:visual && npm run verify:edge",
110
110
  "gates": "node scripts/run-gates.cjs",
111
111
  "preflight": "node scripts/preflight-publish.cjs",
112
+ "verify:published": "node scripts/verify-published.cjs",
113
+ "selfcheck": "node scripts/selfcheck/run-all.cjs",
112
114
  "prepublishOnly": "npm run build && npm run lint && npm run check:size && npm run verify:install"
113
115
  },
114
116
  "devDependencies": {
package/src/fanui.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /* =============================================================================
2
- * fanUI v2.1.0 · TypeScript 类型声明
2
+ * fanUI v2.1.1 · TypeScript 类型声明
3
3
  * -----------------------------------------------------------------------------
4
4
  * tsconfig 中配置 "types": ["@zhang_jifan/fanui"] 或在代码里:
5
5
  * import FanUI from "@zhang_jifan/fanui";
package/src/fanui.js CHANGED
@@ -33,7 +33,7 @@
33
33
 
34
34
  var PREFIX = "fanui";
35
35
 
36
- var VERSION = "2.1.0";
36
+ var VERSION = "2.1.1";
37
37
 
38
38
  /** HTML 转义 —— 服务端与客户端共用,任何插值都必须过这里 */
39
39
  function escapeHtml(v) {
package/src/fanui.scss CHANGED
@@ -15,7 +15,7 @@
15
15
  // @use "@zhang_jifan/fanui/src/functions" as fn;
16
16
  // @use "@zhang_jifan/fanui/src/mixins" as mx;
17
17
  //
18
- // 版本:2.1.0
18
+ // 版本:2.1.1
19
19
  // =============================================================================
20
20
 
21
21
  // ---- 0. 变量配置入口(必须最先)---------------------------------------------