mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-12 23:36:15 -08:00
197 lines
14 KiB
Markdown
197 lines
14 KiB
Markdown
# Danmuku 公共契约基线
|
||
|
||
PKG-DANMUKU-01;冻结提交 `b0cfbfe3a09a84a295a257e45e4577847588d1cb`。
|
||
实际输入及逐文件 SHA 见 [danmuku-release.json](danmuku-release.json),执行结果见
|
||
[danmuku-contract-validation.json](danmuku-contract-validation.json)。本次不改生产代码。
|
||
|
||
## 发布依据与覆盖范围
|
||
|
||
2026-09-13 直接读取 [npm registry](https://registry.npmjs.org/artplayer-plugin-danmuku),
|
||
HTTP 200,目录有 81 个稳定版,latest 为 5.3.0。冻结全部版本的发布时间、tarball、
|
||
integrity、gitHead;实际下载并校验全部 13 个 5.x 版,另加前两代末版 4.4.11、3.5.31,
|
||
共 15 个归档。其余 66 个版本只有目录证据,不能说其运行时已验证或全部兼容。
|
||
这是代表性历史覆盖,不是新最低支持版本,也不把旧 major 的产品行为自动带入候选。
|
||
|
||
当前包全部跟踪文件、12 个 SVG、三个 dist、声明、README、可运行 demo 和 VitePress
|
||
弹幕文档共 28 个输入冻结。最新归档中的 README、manifest、声明及三个 dist 与冻结
|
||
Git 文件逐字节相同;源码行为另通过冻结 Git 模块受控执行对照,不把可读源码等同于
|
||
历史打包过程已可重复构建。
|
||
|
||
| 归档版本 | registry gitHead 的插件版本 | 同提交核心版本 | 说明 |
|
||
| --- | --- | --- | --- |
|
||
| 3.5.31 | 3.5.31 | 3.5.31 | 历史 major 对照 |
|
||
| 4.4.11 | 4.4.10 | 4.5.8 | manifest 版本不一致 |
|
||
| 5.0.0 / 5.0.1 | 5.0.0 / 5.0.1 | 5.0.0 / 5.0.5 | 分别冻结 |
|
||
| 5.1.0 / 5.1.1 | 5.1.0 / 5.1.0 | 5.1.2 / 5.1.5 | 5.1.1 版本不一致 |
|
||
| 5.1.2 / 5.1.3 / 5.1.4 | 同归档版本 | 5.1.6 | 分别冻结 |
|
||
| 5.1.5 / 5.1.6 | 5.1.4 / 5.1.6 | 5.2.2 | 5.1.5 版本不一致 |
|
||
| 5.1.7 | 缺 gitHead | 未知 | 不推测来源提交 |
|
||
| 5.1.8 | 5.1.7 | 5.2.4 | manifest 版本不一致 |
|
||
| 5.2.0 | 5.1.9 | 5.3.0-beta.3 | 核心是提交关联预发布号 |
|
||
| 5.3.0 | 5.2.1 | 5.3.1 | 不宣称核心 5.3.1 是 npm 稳定版 |
|
||
|
||
真实 manifest 是归档身份依据;提交关联不是最低核心支持声明。归档与关联 Git 路径
|
||
各成员的匹配/不匹配均在 JSON 中保存。registry 缺失的提交信息保持缺失。
|
||
未独立验证 npm 签名及发布者授权。5.1.7 归档的目录头没有尾随斜线;专属 verifier
|
||
用 tar 条目类型区分目录与普通文件,拒绝重复、越界和非普通文件,不改共享解包函数。
|
||
|
||
## 分发与静态属性
|
||
|
||
| 版本 | 实际 CommonJS | manifest 分发入口 | 静态 icons |
|
||
| --- | --- | --- | --- |
|
||
| 3.5.31 | 直接函数 | main;未声明 types/module/legacy | 无 |
|
||
| 4.4.11 | 对象.default | main/types | 无 |
|
||
| 5.0.0–5.0.1 | 对象.default | main/types/legacy | 无 |
|
||
| 5.1.0–5.1.6、5.1.8 | 对象.default | main/types/legacy;无 module/exports | 12 项 |
|
||
| 5.1.7 | 对象.default | module 是 `.esm.js`;平铺 import/require/default exports | 12 项 |
|
||
| 5.2.0 | 对象.default | `.mjs`、root/legacy 条件 exports;types 条件在后 | 12 项 |
|
||
| 5.3.0 | 直接函数 | `.mjs`、root/legacy 条件 exports;types 条件在前 | 12 项 |
|
||
|
||
main/legacy 共 28 个实际模块已在 Node VM 执行;三个 manifest ESM 的实际字节通过
|
||
data URL 动态 import 执行。此项只证明模块代码能求值,不等于在消费者目录通过
|
||
Node 包解析;真实安装、NodeNext/Node10、AMD/global/script、编辑器仍由 06/09 验证。
|
||
|
||
`artplayerPluginDanmuku.icons` 是可写、可配置、可枚举的对象值,顺序为:
|
||
`$on/$off/$config/$style/$mode_0_off/$mode_0_on/$mode_1_off/$mode_1_on/`
|
||
`$mode_2_off/$mode_2_on/$check_on/$check_off`。静态 icons 不是 getter;设置模板使用
|
||
模块内 SVG 字符串,没有读取工厂 icons 的后续改写。这一读码事实尚未验证热替换用法。
|
||
|
||
## 最新版工厂与方法
|
||
|
||
`factory(option)(art)` 同步返回门面;字段按 `name/emit/load/config/hide/show/reset/`
|
||
`mount/option/isHide/isStop` 顺序枚举,name 为 `artplayerPluginDanmuku`。
|
||
后三项是可枚举、可配置、没有 setter 的 getter,读取内部当前值。方法已 bind,可抽取调用。
|
||
工厂 option 没有默认对象;`{ danmuku: [] }` 是基准合法调用。初始化不等待异步载入完成。
|
||
|
||
| API | 最新真实行为 | 声明/兼容注意 |
|
||
| --- | --- | --- |
|
||
| `emit(danmu)` | async;验证并修改传入对象,filter 通过后同步入队;Promise 最终返回内部 Danmuku | 旧声明错误写同步 Result;不自动改旧根类型 |
|
||
| `load()` | 读当前 option.danmuku,reset 后清空队列再逐条 emit | Promise 返回内部对象;不是门面 |
|
||
| `load(target)` | 追加到现有队列,不自动改 option.danmuku | 包括数组、函数、同 realm Promise、XML URL |
|
||
| `config(partial)` | 合并默认值、当前值与 partial,验证、钳位;变化比较用 JSON.stringify,单独更换函数会被忽略 | 旧类型要求完整 Option,实际 partial 有效 |
|
||
| `hide/show` | 更新 isHide、层 opacity、option.visible,并发事件 | 返回内部对象;重复调用也发事件 |
|
||
| `reset()` | 全队列回到 wait,回收已分配 DOM,再发 reset | 返回内部对象,不清空队列 |
|
||
| `mount(target)` | selector 或元素;移动设置输入框并 reset 设置 UI | 返回 undefined;声明允许省略,但运行时无目标会抛错 |
|
||
| `option` | 当前合并后的对象;config 可能更换其引用 | 声明可写,实际仅 getter |
|
||
| `isHide/isStop` | 初始 false;show/hide 与 video start/stop 更新 | 不应解释为 video.paused 或 layer DOM 是否存在 |
|
||
|
||
内部 Danmuku 没有公开门面的 `name/mount`,但历史链式返回会将其暴露给调用方。
|
||
后续整理必须先评估返回身份,不能为了匹配旧错误声明静默返回门面。
|
||
`load(undefined)` 清空;其他显式 falsy 值通过 `target = argument || option.danmuku`
|
||
回退但不走清空分支;这只是读码事实,不把未声明参数纳入必须支持的接口。
|
||
|
||
## 全部配置与弹幕项
|
||
|
||
| 配置 | 默认值/范围 |
|
||
| --- | --- |
|
||
| danmuku | `[]`;声明含数组、URL、返回 Promise 的函数、Promise;初始 Promise 被实际 validator 拒绝,load(Promise) 可用 |
|
||
| speed / margin / opacity | `5`,钳位 1–10;`[10,'25%']`;`1`,钳位 0–1 |
|
||
| color / mode / modes | `#FFFFFF`;`0`,钳位 0–2;`[0,1,2]`,显示模式由 dataset/CSS 控制 |
|
||
| fontSize | `25`;数值或百分比,使用时钳位 12 到播放器高度 |
|
||
| antiOverlap / synchronousPlayback | `true` / `false` |
|
||
| mount / heatmap / width / points | controlsCenter / false / 512 / [] |
|
||
| filter / beforeEmit / beforeVisible | 默认均返回 true;filter 同步,另外两个支持异步 |
|
||
| visible / emitter | true / true |
|
||
| maxLength / lockTime / theme | 200(1–1000)/ 5(1–60)/ dark |
|
||
| OPACITY / FONT_SIZE / MARGIN / SPEED / COLOR | `{}` / `{}` / `{}` / `{}` / `[]`,设置组件再补默认滑块与颜色 |
|
||
|
||
Danmu 声明成员为 `text/mode/color/time/border/style`;runtime 还验证可选 string `id`,
|
||
并传播额外字段。mode 只入队 0/1/2,空白 text 与 filter 拒绝项忽略。time 不存在或为 0
|
||
时写为 currentTime + 0.5;负数钳到 0。入队时额外生成 `$state/$index/$ref/$restTime/`
|
||
`$lastStartTime`,loaded/visible 事件会暴露这些字段和对象引用。
|
||
|
||
直接 emit/load 调用 filter,以当前 option 为 this,不经过 beforeEmit。设置 UI 的
|
||
发送按钮/Enter 先 trim 输入,防锁定/重复提交,await beforeEmit;只有严格 true 继续,
|
||
加 border、删除 time、再调用 emit,清输入并锁定。beforeVisible 在准备显示前调用,
|
||
也以 option 为 this。三者不能合并成一个全局异步过滤器。
|
||
|
||
最新声明有六个命名类型 `Mode/Danmuku/Slider/Danmu/Option/Result`。
|
||
4.4.11/5.0.x 旧声明中 Danmuku 表示结果,而 5.1.x 起表示输入,旧配置还出现
|
||
useWorker/minWidth/maxWidth;不能将较早声明与最新声明拼成未经评估的根类型。
|
||
06 按已批准的 [统一类型规则](../type-compatibility-policy.md) 处理:最新 npm 根声明的
|
||
合法完整工厂赋值、Parameters/ReturnType、NodeNext 历史模块形态都需安装消费者证据;
|
||
准确异步类型可用独立 runtime 入口,较早冲突写迁移说明。本次没有改类型或声称编译矩阵通过。
|
||
|
||
## 事件、DOM、设置与热力图
|
||
|
||
| 事件 | 参数/时机 |
|
||
| --- | --- |
|
||
| artplayerPluginDanmuku:config | 当前 option 引用;show/hide 在它之前发生 |
|
||
| artplayerPluginDanmuku:loaded | 完成当前 load 后的实际 queue 引用;空数组初始化可在工厂返回前同步发生 |
|
||
| artplayerPluginDanmuku:error | load 捕获的原错误,然后再次抛出;直接 emit 不自动发这个事件 |
|
||
| artplayerPluginDanmuku:visible | worker 返回位置且允许显示后,实际内部 danmu |
|
||
| artplayerPluginDanmuku:start / stop | 无参数,video:play/playing / pause/waiting 对应触发 |
|
||
| artplayerPluginDanmuku:show / hide / reset | 无参数,对应方法更新状态之后 |
|
||
| artplayerPluginDanmuku:destroy | stop、worker terminate 和解除部分监听之后 |
|
||
| artplayerPluginDanmuku:points | 消费方发入的热力图数据事件,插件不主动 emit |
|
||
|
||
这些是十个输出事件和一个输入事件;不新增虚构的 `:emit` 事件。
|
||
[] 初始化的已复现顺序为 show → config → reset → loaded;非空/异步输入顺序和错误
|
||
重入仍需 02 扩展。Setting 还订阅 resize/fullscreen/fullscreenWeb/document:pointermove/
|
||
document:pointerup/show/hide。热力图订阅 ready/resize/loaded/timeupdate/setBar/points。
|
||
|
||
设置入口是 `new Setting` 创建的独立 `.artplayer-plugin-danmuku` 输入框和弹出面板,
|
||
不是核心 setting registry 的单个项目。内部使用 `.apd-*` 类、mode/color/state/id 数据,
|
||
外部挂载可在 fullscreen/fullscreenWeb 时移回控制栏;默认挂载在宽度低于 width 时移到
|
||
播放器底部。默认不透明度 0–100、字号 12–120;MARGIN 四档 `[10,'75%']/[10,'50%']/`
|
||
`[10,'25%']/[10,10]`;SPEED 五档 10/7.5/5/2.5/1。滑块读取 step.hide,而声明写 show;
|
||
MARGIN step.value 是数组,声明只有 number|string。
|
||
|
||
设置 style 在模块求值时插入 id=`artplayer-plugin-danmuku` 的全局 style;完整类名、
|
||
选择器、SVG 和样式源码已整体哈希冻结。视觉、CSS 覆盖、重复 style 与外部节点回收
|
||
未在本次 mock 中模拟,交 02/05/08 的真实页面验证。
|
||
|
||
heatmap=true/object 创建 name=`heatmap`、position=`top` 的控件。源码按 `[x,y]` 二元组
|
||
使用 points 事件数据;`option.points` 当前只存储,未被 heatmap update 消费,声明却为
|
||
`{time,value}[]`。初始化开启 heatmap 后 config 开关不会自动新增/移除控件。上面两项为
|
||
读码事实,尚未浏览器复现。窄尺寸下默认 sampling=floor(width/100) 可为 0;需 02 用
|
||
独立超时保护测试确认循环风险,不在 UI 主线程盲跑。
|
||
|
||
## Bilibili XML 与 worker
|
||
|
||
string 输入调用 fetch(url) → response.text(),没有显式 HTTP 状态判断。XML 用正则读
|
||
`<d p="...">...</d>`,要求至少八个逗号分隔字段;模式 1/2/3→0、4→2、5→1,其他→0;
|
||
trim 后按 quot/apos/lt/gt/amp 顺序解实体。输出 text/time/mode/fontSize/color/timestamp/
|
||
pool/userID/rowID;color 用十六进制字符串,不补齐六位,数字异常也不额外过滤。
|
||
|
||
优先生成 Blob worker,message 含 `{xml,id}`,结果 `{danmus,id}`,成功后 terminate;
|
||
Worker 构建同步失败时 console.error 并退回相同 parser。正则和 fallback 已执行;真实
|
||
网络、Worker 消息和 CSP/Blob 能力未验证。源码用 async Promise executor,fetch/text
|
||
拒绝发生在 try 之外,且未 revokeObjectURL;空 XML/worker error/销毁竞态是待 02 复现项。
|
||
调度 worker 接口 `{type:'getDanmuTop',id,target,visibles,antiOverlap,clientWidth,clientHeight,marginBottom,marginTop}`
|
||
→ `{result,id}`,当前 Date.now 作为 id 并覆盖 onmessage;并发/旧回复仍待测试。
|
||
|
||
## 已复现差异与后续责任
|
||
|
||
| 编号 | 证据级别 | 内容 | 后续任务 |
|
||
| --- | --- | --- | --- |
|
||
| DANMUKU-TYPE-01 | 运行时复现 + 逐字声明 | emit Promise、内部返回身份、getter、mount 省略、初始 Promise 和声明不一致 | 03/06 |
|
||
| DANMUKU-INPUT-01 | 冻结源码和真实 5.3 main/legacy 复现 | time:0 被改为 current+0.5;输入对象被修改 | 02/03,分别评估修正和保留 |
|
||
| DANMUKU-CONFIG-01 | 同上 | 单独 config({filter:新函数}) 被 JSON.stringify 比较判为未变化 | 02/03 |
|
||
| DANMUKU-CLEANUP-01 | 同上 | resize 注册 this.resize,销毁 off(this.reset);设置锁定 timer 未清 | 02/05 |
|
||
| DANMUKU-TYPE-02 | 读码/声明观察 | id/icons 缺失、Slider value/hide、points 类型与使用漂移、config partial | 05/06 |
|
||
| DANMUKU-ASYNC-01 | 待复现 | Bilibili fetch/text/worker 错误、load 乱序、beforeVisible/worker 晚回调、重复 start | 02/03/04/05 |
|
||
| DANMUKU-HEATMAP-01 | 待复现 | 小于 100px 时 sampling=0、事件 tuple/option.points、重复实例 SVG id | 02/05 |
|
||
| DANMUKU-SOURCE-01 | 归档与 Git 核验 | gitHead 版本错位、5.1.7 无 gitHead、12 SVG 无单独来源授权证据 | 09 |
|
||
|
||
历史缺陷断言仅冻结观察,不要求候选保留。修复必须有独立候选正常断言与明确迁移影响。
|
||
包 README 只有简介/demo/license,主要公开说明来自冻结 VitePress 文档和 demo。
|
||
demo 使用本地 video.mp4/danmuku.xml,适合作为后续 8082/Monaco/Run 的本地输入。
|
||
本次不证明实际播放、密集弹幕碰撞/时钟、mask/全屏/PiP、真实 WebKit/设备或 npm 发布可行。
|
||
|
||
## 重放
|
||
|
||
在固定 Node 24.21.0 / Yarn 1.22.22 与已安装根依赖下运行:
|
||
|
||
```text
|
||
node refactor/scripts/danmuku-contract.mjs
|
||
node --test refactor/scripts/danmuku-contract.test.mjs
|
||
node node_modules/eslint/bin/eslint.js refactor/scripts/danmuku-contract.mjs refactor/scripts/danmuku-contract.test.mjs
|
||
```
|
||
|
||
缺缓存时 verifier 仅从冻结 npm URL 下载并验证 SHA512/SHA256;不执行 registry 包脚本。
|
||
完整目录可再次读取 `https://registry.npmjs.org/artplayer-plugin-danmuku`,但返回的新目录
|
||
不应覆盖本次不可变基线。原始 registry body 的 SHA 保存在 JSON,原始响应在专属 cache。
|
||
测试使用真实发布核心 5.4.0 的 validator、受控 DOM/计时器/Worker,仅源码编译在内存中
|
||
完成,不生成或修改 dist/docs。仅访问 npm 元数据及归档,未请求媒体或 Bilibili 资源。
|