diff --git a/refactor/baselines/README.md b/refactor/baselines/README.md index 198df2d5a..e73da5763 100644 --- a/refactor/baselines/README.md +++ b/refactor/baselines/README.md @@ -36,3 +36,7 @@ BASE-02 已在内置浏览器取得核心/chapter 的同步 API 和描述符快 ## 事件与生命周期报告 BASE-03 已在内置浏览器实测播放推进、暂停/seek/切源、事件及销毁;两次 27 项断言通过,并保存 6 项历史问题。见 [覆盖与复现](lifecycle-coverage.md) 和 [原始报告](lifecycle.json)。受控拒绝与真正媒体播放分别标注,不代替全环境验收。 + +## DOM 与官方示例路径 + +BASE-04 已在内置浏览器完成两轮 16 项 DOM/样式/实际输入断言。见 [覆盖/复现/历史问题](dom-coverage.md)、[冻结报告](dom.json) 和 [29 示例/36 HTML/22 包路径](demo-inventory.json)。轻量夹具通过不代表 Monaco 或所有官方示例已验证。 diff --git a/refactor/baselines/demo-inventory.json b/refactor/baselines/demo-inventory.json new file mode 100644 index 000000000..327193559 --- /dev/null +++ b/refactor/baselines/demo-inventory.json @@ -0,0 +1,1106 @@ +{ + "schemaVersion": 1, + "task": "BASE-04", + "sourceCommit": "94893929", + "capturedAt": "2026-09-10T12:11:47.047Z", + "note": "Historical source inventory, not browser or network evidence. ScriptSources excludes comments but does not resolve inline scripts, import maps or dynamic SDK loading. Hashes use LF and describe this capture; check validates coverage, not current content identity.", + "examples": [ + { + "name": "ads", + "source": "docs/assets/example/ads.js", + "sha256Lf": "c84a97d2b1970c323a0c2538b846312bff38513e10de271fe5f239953da88cd3", + "menuLinks": [ + "/?libs=./uncompiled/artplayer-plugin-ads/index.js&example=ads" + ], + "route": "/?libs=./uncompiled/artplayer-plugin-ads/index.js&example=ads", + "libs": [ + "./uncompiled/artplayer-plugin-ads/index.js" + ], + "status": "not-run", + "owner": "EX-03", + "note": "Existing menu route; SDK and media loading have not been validated." + }, + { + "name": "ambilight", + "source": "docs/assets/example/ambilight.js", + "sha256Lf": "f97c1404886ba6474b4e14339c563fd2de50b7d50fdc4c9d59d85a3142a1ad52", + "menuLinks": [ + "/?libs=./uncompiled/artplayer-plugin-ambilight/index.js&example=ambilight" + ], + "route": "/?libs=./uncompiled/artplayer-plugin-ambilight/index.js&example=ambilight", + "libs": [ + "./uncompiled/artplayer-plugin-ambilight/index.js" + ], + "status": "not-run", + "owner": "EX-03", + "note": "Existing menu route; SDK and media loading have not been validated." + }, + { + "name": "asr", + "source": "docs/assets/example/asr.js", + "sha256Lf": "bb7fd5eee3df887b7e0c72a6f42f74f0253350f9bc884f73cb9c2996f0e35724", + "menuLinks": [ + "/?libs=./uncompiled/artplayer-plugin-asr/index.js&example=asr" + ], + "route": "/?libs=./uncompiled/artplayer-plugin-asr/index.js&example=asr", + "libs": [ + "./uncompiled/artplayer-plugin-asr/index.js" + ], + "status": "not-run", + "owner": "EX-03", + "note": "Existing menu route; SDK and media loading have not been validated." + }, + { + "name": "audio.track", + "source": "docs/assets/example/audio.track.js", + "sha256Lf": "9ed26b2ee006e1a430db68b2a1b308c4801dd3a4cc87c74e8a8f5ccf3456ac8d", + "menuLinks": [ + "/?libs=./uncompiled/artplayer-plugin-audio-track/index.js&example=audio.track" + ], + "route": "/?libs=./uncompiled/artplayer-plugin-audio-track/index.js&example=audio.track", + "libs": [ + "./uncompiled/artplayer-plugin-audio-track/index.js" + ], + "status": "not-run", + "owner": "EX-03", + "note": "Existing menu route; SDK and media loading have not been validated." + }, + { + "name": "auto.thumbnail", + "source": "docs/assets/example/auto.thumbnail.js", + "sha256Lf": "e0f706bbbab8e2d0f3201ea6b91f1d5530c6bb65f5c1745dc8ade9acc6d66295", + "menuLinks": [ + "/?libs=./uncompiled/artplayer-plugin-auto-thumbnail/index.js&example=auto.thumbnail" + ], + "route": "/?libs=./uncompiled/artplayer-plugin-auto-thumbnail/index.js&example=auto.thumbnail", + "libs": [ + "./uncompiled/artplayer-plugin-auto-thumbnail/index.js" + ], + "status": "not-run", + "owner": "EX-03", + "note": "Existing menu route; SDK and media loading have not been validated." + }, + { + "name": "canvas", + "source": "docs/assets/example/canvas.js", + "sha256Lf": "95a971773e93cfb340a07eebcd49e333825f49ce0d167514ad98a188cd027799", + "menuLinks": [ + "/?libs=./uncompiled/artplayer-proxy-canvas/index.js&example=canvas" + ], + "route": "/?libs=./uncompiled/artplayer-proxy-canvas/index.js&example=canvas", + "libs": [ + "./uncompiled/artplayer-proxy-canvas/index.js" + ], + "status": "not-run", + "owner": "EX-03", + "note": "Existing menu route; SDK and media loading have not been validated." + }, + { + "name": "chapter", + "source": "docs/assets/example/chapter.js", + "sha256Lf": "93f2378a1b7a105721511d34fd632ec7745b4b20c472072c410f76b25383c96b", + "menuLinks": [ + "/?libs=./uncompiled/artplayer-plugin-chapter/index.js&example=chapter" + ], + "route": "/?libs=./uncompiled/artplayer-plugin-chapter/index.js&example=chapter", + "libs": [ + "./uncompiled/artplayer-plugin-chapter/index.js" + ], + "status": "not-run", + "owner": "EX-03", + "note": "Existing menu route; SDK and media loading have not been validated." + }, + { + "name": "chromecast", + "source": "docs/assets/example/chromecast.js", + "sha256Lf": "edd4d232a667a3ca5bae247dca3c557431975b9ae38dc56cc590b57e327d048f", + "menuLinks": [ + "/?libs=./uncompiled/artplayer-plugin-chromecast/index.js&example=chromecast" + ], + "route": "/?libs=./uncompiled/artplayer-plugin-chromecast/index.js&example=chromecast", + "libs": [ + "./uncompiled/artplayer-plugin-chromecast/index.js" + ], + "status": "not-run", + "owner": "EX-03", + "note": "Existing menu route; SDK and media loading have not been validated." + }, + { + "name": "danmuku", + "source": "docs/assets/example/danmuku.js", + "sha256Lf": "3f91461e2466f13ed4e72e6bd69986461192d8c6a9ca866fa347599f6958e021", + "menuLinks": [ + "/?libs=./uncompiled/artplayer-plugin-danmuku/index.js&example=danmuku" + ], + "route": "/?libs=./uncompiled/artplayer-plugin-danmuku/index.js&example=danmuku", + "libs": [ + "./uncompiled/artplayer-plugin-danmuku/index.js" + ], + "status": "not-run", + "owner": "EX-03", + "note": "Existing menu route; SDK and media loading have not been validated." + }, + { + "name": "danmuku.mask", + "source": "docs/assets/example/danmuku.mask.js", + "sha256Lf": "c0fe4f2d4cd60738583c4bfeebc24bc3365d8ca382e6f4ff86e1056f5a2729a8", + "menuLinks": [ + "/?libs=./uncompiled/artplayer-plugin-danmuku/index.js%0A./uncompiled/artplayer-plugin-danmuku-mask/index.js&example=danmuku.mask" + ], + "route": "/?libs=./uncompiled/artplayer-plugin-danmuku/index.js%0A./uncompiled/artplayer-plugin-danmuku-mask/index.js&example=danmuku.mask", + "libs": [ + "./uncompiled/artplayer-plugin-danmuku/index.js", + "./uncompiled/artplayer-plugin-danmuku-mask/index.js" + ], + "status": "not-run", + "owner": "EX-03", + "note": "Existing menu route; SDK and media loading have not been validated." + }, + { + "name": "dash.control", + "source": "docs/assets/example/dash.control.js", + "sha256Lf": "edc4326f03262a222e06bb780aab05c903ee162829dec60970e738c1e260eef2", + "menuLinks": [ + "/?libs=https://cdnjs.cloudflare.com/ajax/libs/dashjs/5.2.1/modern/umd/dash.all.min.js%0A./uncompiled/artplayer-plugin-dash-control/index.js&example=dash.control" + ], + "route": "/?libs=https://cdnjs.cloudflare.com/ajax/libs/dashjs/5.2.1/modern/umd/dash.all.min.js%0A./uncompiled/artplayer-plugin-dash-control/index.js&example=dash.control", + "libs": [ + "https://cdnjs.cloudflare.com/ajax/libs/dashjs/5.2.1/modern/umd/dash.all.min.js", + "./uncompiled/artplayer-plugin-dash-control/index.js" + ], + "status": "not-run", + "owner": "EX-03", + "note": "Existing menu route; SDK and media loading have not been validated." + }, + { + "name": "dash", + "source": "docs/assets/example/dash.js", + "sha256Lf": "49a7837016b6f0e8ac045e6aba7bb95e1997e6fd834243b4c62d0c97a2938776", + "menuLinks": [ + "/?libs=https://cdnjs.cloudflare.com/ajax/libs/dashjs/5.2.1/modern/umd/dash.all.min.js&example=dash" + ], + "route": "/?libs=https://cdnjs.cloudflare.com/ajax/libs/dashjs/5.2.1/modern/umd/dash.all.min.js&example=dash", + "libs": [ + "https://cdnjs.cloudflare.com/ajax/libs/dashjs/5.2.1/modern/umd/dash.all.min.js" + ], + "status": "not-run", + "owner": "EX-03", + "note": "Existing menu route; SDK and media loading have not been validated." + }, + { + "name": "document.pip", + "source": "docs/assets/example/document.pip.js", + "sha256Lf": "2600948ff0128e2e77fe08fbefa9be96543d8fcd81421534dfbfe9cb84e91fde", + "menuLinks": [ + "/?libs=./uncompiled/artplayer-plugin-document-pip/index.js&example=document.pip" + ], + "route": "/?libs=./uncompiled/artplayer-plugin-document-pip/index.js&example=document.pip", + "libs": [ + "./uncompiled/artplayer-plugin-document-pip/index.js" + ], + "status": "not-run", + "owner": "EX-03", + "note": "Existing menu route; SDK and media loading have not been validated." + }, + { + "name": "flv", + "source": "docs/assets/example/flv.js", + "sha256Lf": "51e052e5423318aa25c69eae90a5181c1325edf2d0975fa169308eadb6b395eb", + "menuLinks": [ + "/?libs=https://cdnjs.cloudflare.com/ajax/libs/flv.js/1.6.2/flv.min.js&example=flv" + ], + "route": "/?libs=https://cdnjs.cloudflare.com/ajax/libs/flv.js/1.6.2/flv.min.js&example=flv", + "libs": [ + "https://cdnjs.cloudflare.com/ajax/libs/flv.js/1.6.2/flv.min.js" + ], + "status": "not-run", + "owner": "EX-03", + "note": "Existing menu route; SDK and media loading have not been validated." + }, + { + "name": "hls.control", + "source": "docs/assets/example/hls.control.js", + "sha256Lf": "b02fd290d79999790501447fad95736642344b9b30af3ccdbe353f80c7d53a6e", + "menuLinks": [ + "/?libs=https://cdnjs.cloudflare.com/ajax/libs/hls.js/1.5.17/hls.min.js%0A./uncompiled/artplayer-plugin-hls-control/index.js&example=hls.control" + ], + "route": "/?libs=https://cdnjs.cloudflare.com/ajax/libs/hls.js/1.5.17/hls.min.js%0A./uncompiled/artplayer-plugin-hls-control/index.js&example=hls.control", + "libs": [ + "https://cdnjs.cloudflare.com/ajax/libs/hls.js/1.5.17/hls.min.js", + "./uncompiled/artplayer-plugin-hls-control/index.js" + ], + "status": "not-run", + "owner": "EX-03", + "note": "Existing menu route; SDK and media loading have not been validated." + }, + { + "name": "hls", + "source": "docs/assets/example/hls.js", + "sha256Lf": "7f82d60442223ced637daa896199607ca9bd52ac50dabbb47c75561f84e9ff48", + "menuLinks": [ + "/?libs=https://cdnjs.cloudflare.com/ajax/libs/hls.js/1.5.17/hls.min.js&example=hls" + ], + "route": "/?libs=https://cdnjs.cloudflare.com/ajax/libs/hls.js/1.5.17/hls.min.js&example=hls", + "libs": [ + "https://cdnjs.cloudflare.com/ajax/libs/hls.js/1.5.17/hls.min.js" + ], + "status": "not-run", + "owner": "EX-03", + "note": "Existing menu route; SDK and media loading have not been validated." + }, + { + "name": "iframe", + "source": "docs/assets/example/iframe.js", + "sha256Lf": "00a8441d2a9873f7be342a98b58acab1cf6aca2359414f126ffb63f6ee20c218", + "menuLinks": [ + "/?libs=./uncompiled/artplayer-tool-iframe/index.js&example=iframe" + ], + "route": "/?libs=./uncompiled/artplayer-tool-iframe/index.js&example=iframe", + "libs": [ + "./uncompiled/artplayer-tool-iframe/index.js" + ], + "status": "not-run", + "owner": "EX-03", + "note": "Existing menu route; SDK and media loading have not been validated." + }, + { + "name": "index", + "source": "docs/assets/example/index.js", + "sha256Lf": "7fd8b85433ced107add0e0b3731ef192113435330d976166cbb63992b7625571", + "menuLinks": [], + "route": "/?example=index", + "libs": [], + "status": "not-run", + "owner": "EX-03", + "note": "No menu link; example route follows common.js loader. Required globals are not automatically loaded." + }, + { + "name": "jassub", + "source": "docs/assets/example/jassub.js", + "sha256Lf": "4c93c554aa0a65ac19c1386bb0cfd9df6545f95b8a6f65541a0db8c072975f6d", + "menuLinks": [ + "/?libs=./uncompiled/artplayer-plugin-jassub/index.js&example=jassub" + ], + "route": "/?libs=./uncompiled/artplayer-plugin-jassub/index.js&example=jassub", + "libs": [ + "./uncompiled/artplayer-plugin-jassub/index.js" + ], + "status": "not-run", + "owner": "EX-03", + "note": "Existing menu route; SDK and media loading have not been validated." + }, + { + "name": "mediabunny", + "source": "docs/assets/example/mediabunny.js", + "sha256Lf": "dad4cecb76b2e5ce9164a4da715793911123e8fd2bc4b93f4bcc86a7053bad7d", + "menuLinks": [ + "/?libs=./uncompiled/artplayer-proxy-mediabunny/index.js&example=mediabunny" + ], + "route": "/?libs=./uncompiled/artplayer-proxy-mediabunny/index.js&example=mediabunny", + "libs": [ + "./uncompiled/artplayer-proxy-mediabunny/index.js" + ], + "status": "not-run", + "owner": "EX-03", + "note": "Existing menu route; SDK and media loading have not been validated." + }, + { + "name": "mobile", + "source": "docs/assets/example/mobile.js", + "sha256Lf": "c117fcd0e8b0f3da3745f5b97d2544b52aea49f28a7779704b0455f2a54d00e3", + "menuLinks": [], + "route": "/?example=mobile", + "libs": [], + "status": "not-run", + "owner": "EX-03", + "note": "No menu link; example route follows common.js loader. Required globals are not automatically loaded." + }, + { + "name": "mpegts", + "source": "docs/assets/example/mpegts.js", + "sha256Lf": "2e819af74536e02fdbccbf3379467dec7b1cf6f3aff7e46c370355320485a482", + "menuLinks": [ + "/?libs=https://cdn.jsdelivr.net/npm/mpegts.js@1.7.3/dist/mpegts.min.js&example=mpegts" + ], + "route": "/?libs=https://cdn.jsdelivr.net/npm/mpegts.js@1.7.3/dist/mpegts.min.js&example=mpegts", + "libs": [ + "https://cdn.jsdelivr.net/npm/mpegts.js@1.7.3/dist/mpegts.min.js" + ], + "status": "not-run", + "owner": "EX-03", + "note": "Existing menu route; SDK and media loading have not been validated." + }, + { + "name": "multiple.subtitles", + "source": "docs/assets/example/multiple.subtitles.js", + "sha256Lf": "d9ccbd334d4c77f26826144870d6700e4b62f1f00b7f8f49817b3ac2583e5cc4", + "menuLinks": [ + "/?libs=./uncompiled/artplayer-plugin-multiple-subtitles/index.js&example=multiple.subtitles" + ], + "route": "/?libs=./uncompiled/artplayer-plugin-multiple-subtitles/index.js&example=multiple.subtitles", + "libs": [ + "./uncompiled/artplayer-plugin-multiple-subtitles/index.js" + ], + "status": "not-run", + "owner": "EX-03", + "note": "Existing menu route; SDK and media loading have not been validated." + }, + { + "name": "setting.test", + "source": "docs/assets/example/setting.test.js", + "sha256Lf": "84d6489b87556df556cbf567c9e72895366e0abeba524b9bb67ef9561d1dda60", + "menuLinks": [], + "route": "/?example=setting.test", + "libs": [], + "status": "not-run", + "owner": "EX-03", + "note": "No menu link; example route follows common.js loader. Required globals are not automatically loaded." + }, + { + "name": "thumbnail", + "source": "docs/assets/example/thumbnail.js", + "sha256Lf": "e166845905f131dea0979eb77471f5531a59b93ab2dc28fef1b6791adb42fc30", + "menuLinks": [], + "route": "/?example=thumbnail", + "libs": [], + "status": "not-run", + "owner": "EX-03", + "note": "References artplayer-plugin-thumbnail, which is absent from the 22 current workspace packages; dependency and route need reconciliation." + }, + { + "name": "tool.thumbnail", + "source": "docs/assets/example/tool.thumbnail.js", + "sha256Lf": "ef830a5f499e14c09d51aa31aaa0a194ea1f910b27f14ef97c0ca8f67d529a54", + "menuLinks": [ + "/?libs=./uncompiled/artplayer-tool-thumbnail/index.js&example=tool.thumbnail" + ], + "route": "/?libs=./uncompiled/artplayer-tool-thumbnail/index.js&example=tool.thumbnail", + "libs": [ + "./uncompiled/artplayer-tool-thumbnail/index.js" + ], + "status": "not-run", + "owner": "EX-03", + "note": "Existing menu route; SDK and media loading have not been validated." + }, + { + "name": "vast", + "source": "docs/assets/example/vast.js", + "sha256Lf": "ce93b48fabc2f1fd39fdaa8af3ae9f86a420c9aa65551e2e196d754070f36064", + "menuLinks": [ + "/?libs=./uncompiled/artplayer-plugin-vast/index.js&example=vast" + ], + "route": "/?libs=./uncompiled/artplayer-plugin-vast/index.js&example=vast", + "libs": [ + "./uncompiled/artplayer-plugin-vast/index.js" + ], + "status": "not-run", + "owner": "EX-03", + "note": "Existing menu route; SDK and media loading have not been validated." + }, + { + "name": "vtt.thumbnail", + "source": "docs/assets/example/vtt.thumbnail.js", + "sha256Lf": "05465b0da63b23626a3032a9c1f44d3e78ed501a313aaed885ac232ab720ffee", + "menuLinks": [ + "/?libs=./uncompiled/artplayer-plugin-vtt-thumbnail/index.js&example=vtt.thumbnail" + ], + "route": "/?libs=./uncompiled/artplayer-plugin-vtt-thumbnail/index.js&example=vtt.thumbnail", + "libs": [ + "./uncompiled/artplayer-plugin-vtt-thumbnail/index.js" + ], + "status": "not-run", + "owner": "EX-03", + "note": "Existing menu route; SDK and media loading have not been validated." + }, + { + "name": "webtorrent", + "source": "docs/assets/example/webtorrent.js", + "sha256Lf": "11e6541fbaeb2f854b43ed4ea2bea36f411505343dc79a3f3a9ede9d856b2226", + "menuLinks": [ + "/?libs=https://cdn.jsdelivr.net/npm/webtorrent@1/webtorrent.min.js&example=webtorrent" + ], + "route": "/?libs=https://cdn.jsdelivr.net/npm/webtorrent@1/webtorrent.min.js&example=webtorrent", + "libs": [ + "https://cdn.jsdelivr.net/npm/webtorrent@1/webtorrent.min.js" + ], + "status": "not-run", + "owner": "EX-03", + "note": "Existing menu route; SDK and media loading have not been validated." + } + ], + "pages": [ + { + "source": "docs/document/404.html", + "route": "/document/404.html", + "sha256Lf": "35330fa7a4443bb2bf2a44b7f474acc04b2d886f1acb1e800eff44e6ca8152b3", + "kind": "generated-docs", + "scriptSources": [ + "/document/assets/app.CkD0mcCX.js", + "/document/main.js", + "https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-8579453810848662" + ], + "status": "not-run", + "owner": "EX-03" + }, + { + "source": "docs/document/advanced/built-in.html", + "route": "/document/advanced/built-in.html", + "sha256Lf": "5879aef25987cedbdcbeed27b529a3db61811af4707460de4b26332197afe9fe", + "kind": "generated-docs", + "scriptSources": [ + "/document/assets/app.CkD0mcCX.js", + "/document/main.js", + "https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-8579453810848662" + ], + "status": "not-run", + "owner": "EX-03" + }, + { + "source": "docs/document/advanced/class.html", + "route": "/document/advanced/class.html", + "sha256Lf": "20253766226e1eea67923ed8b246e288973fa9274f6e2c78c9c5aabb7d094bb0", + "kind": "generated-docs", + "scriptSources": [ + "/document/assets/app.CkD0mcCX.js", + "/document/main.js", + "https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-8579453810848662" + ], + "status": "not-run", + "owner": "EX-03" + }, + { + "source": "docs/document/advanced/event.html", + "route": "/document/advanced/event.html", + "sha256Lf": "492f23ac44a57f38f5a8441a318c5db3921d35f237542f6ed75f7c299c42054c", + "kind": "generated-docs", + "scriptSources": [ + "/document/assets/app.CkD0mcCX.js", + "/document/main.js", + "https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-8579453810848662" + ], + "status": "not-run", + "owner": "EX-03" + }, + { + "source": "docs/document/advanced/global.html", + "route": "/document/advanced/global.html", + "sha256Lf": "1cde634d00316a5e66f90ad1763aa868fd84564bbc1f8ba7beded72e29a07d89", + "kind": "generated-docs", + "scriptSources": [ + "/document/assets/app.CkD0mcCX.js", + "/document/main.js", + "https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-8579453810848662" + ], + "status": "not-run", + "owner": "EX-03" + }, + { + "source": "docs/document/advanced/plugin.html", + "route": "/document/advanced/plugin.html", + "sha256Lf": "2cbc89cb96d6715995e28ab1a0ed6b74ef6e06e0b57a062d3208e1b7ca8ade8a", + "kind": "generated-docs", + "scriptSources": [ + "/document/assets/app.CkD0mcCX.js", + "/document/main.js", + "https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-8579453810848662" + ], + "status": "not-run", + "owner": "EX-03" + }, + { + "source": "docs/document/advanced/property.html", + "route": "/document/advanced/property.html", + "sha256Lf": "f020b32d5a0e67a237100cdb1bd2ad2129c829a1233608137ceb1442f4e69ae0", + "kind": "generated-docs", + "scriptSources": [ + "/document/assets/app.CkD0mcCX.js", + "/document/main.js", + "https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-8579453810848662" + ], + "status": "not-run", + "owner": "EX-03" + }, + { + "source": "docs/document/component/contextmenu.html", + "route": "/document/component/contextmenu.html", + "sha256Lf": "4b8ac7383e49262a41c842a84c946a880ff08a3defc9c1d160a109478e3bb9f8", + "kind": "generated-docs", + "scriptSources": [ + "/document/assets/app.CkD0mcCX.js", + "/document/main.js", + "https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-8579453810848662" + ], + "status": "not-run", + "owner": "EX-03" + }, + { + "source": "docs/document/component/controls.html", + "route": "/document/component/controls.html", + "sha256Lf": "c89c72f3fc06aa3b38c3793491c6cc1b2ced60823d34880c99336a741c740371", + "kind": "generated-docs", + "scriptSources": [ + "/document/assets/app.CkD0mcCX.js", + "/document/main.js", + "https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-8579453810848662" + ], + "status": "not-run", + "owner": "EX-03" + }, + { + "source": "docs/document/component/layers.html", + "route": "/document/component/layers.html", + "sha256Lf": "85d2bf5d6eecb10053bd677bff01dfe953d5e826c9e267b07a265eb51d78ce7e", + "kind": "generated-docs", + "scriptSources": [ + "/document/assets/app.CkD0mcCX.js", + "/document/main.js", + "https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-8579453810848662" + ], + "status": "not-run", + "owner": "EX-03" + }, + { + "source": "docs/document/component/setting.html", + "route": "/document/component/setting.html", + "sha256Lf": "e1910d93dfe2a4834dad24b15217d4f0e2679afa832d4ff2a8e57c0c6924136b", + "kind": "generated-docs", + "scriptSources": [ + "/document/assets/app.CkD0mcCX.js", + "/document/main.js", + "https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-8579453810848662" + ], + "status": "not-run", + "owner": "EX-03" + }, + { + "source": "docs/document/en/advanced/built-in.html", + "route": "/document/en/advanced/built-in.html", + "sha256Lf": "be5d00e9a4377b8b3e64a6ac669855b8784664c3ebaf49c2dce2bbd631d2a7b7", + "kind": "generated-docs", + "scriptSources": [ + "/document/assets/app.CkD0mcCX.js", + "/document/main.js", + "https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-8579453810848662" + ], + "status": "not-run", + "owner": "EX-03" + }, + { + "source": "docs/document/en/advanced/class.html", + "route": "/document/en/advanced/class.html", + "sha256Lf": "9a46b027c57e339ab406c48252d091b69daf51cfa423b9781cf9fed63b355145", + "kind": "generated-docs", + "scriptSources": [ + "/document/assets/app.CkD0mcCX.js", + "/document/main.js", + "https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-8579453810848662" + ], + "status": "not-run", + "owner": "EX-03" + }, + { + "source": "docs/document/en/advanced/event.html", + "route": "/document/en/advanced/event.html", + "sha256Lf": "0b59419963a461639888270048b96862abb14a6d045e2a3899567bc5aed7d854", + "kind": "generated-docs", + "scriptSources": [ + "/document/assets/app.CkD0mcCX.js", + "/document/main.js", + "https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-8579453810848662" + ], + "status": "not-run", + "owner": "EX-03" + }, + { + "source": "docs/document/en/advanced/global.html", + "route": "/document/en/advanced/global.html", + "sha256Lf": "d150fecaa5c258ac62b56d4c3f6a75ea2d7457d5da5006cb851b7cfa96e0471b", + "kind": "generated-docs", + "scriptSources": [ + "/document/assets/app.CkD0mcCX.js", + "/document/main.js", + "https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-8579453810848662" + ], + "status": "not-run", + "owner": "EX-03" + }, + { + "source": "docs/document/en/advanced/plugin.html", + "route": "/document/en/advanced/plugin.html", + "sha256Lf": "90af8fe2cb080a799cfa0a6eae7e66bd7916b59a0a456dc25ee20ffb813f9235", + "kind": "generated-docs", + "scriptSources": [ + "/document/assets/app.CkD0mcCX.js", + "/document/main.js", + "https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-8579453810848662" + ], + "status": "not-run", + "owner": "EX-03" + }, + { + "source": "docs/document/en/advanced/property.html", + "route": "/document/en/advanced/property.html", + "sha256Lf": "b38ae4ce4607dbdc70710d0615749c6760599b61e6428989cfcc2e3e1196a0da", + "kind": "generated-docs", + "scriptSources": [ + "/document/assets/app.CkD0mcCX.js", + "/document/main.js", + "https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-8579453810848662" + ], + "status": "not-run", + "owner": "EX-03" + }, + { + "source": "docs/document/en/component/contextmenu.html", + "route": "/document/en/component/contextmenu.html", + "sha256Lf": "f0426201d0dd91dce3eb1159ed4587acaba245dc393752675dc919108977d060", + "kind": "generated-docs", + "scriptSources": [ + "/document/assets/app.CkD0mcCX.js", + "/document/main.js", + "https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-8579453810848662" + ], + "status": "not-run", + "owner": "EX-03" + }, + { + "source": "docs/document/en/component/controls.html", + "route": "/document/en/component/controls.html", + "sha256Lf": "c8547522f8b9347aba1cd759159d60d067528e3d5c1431494f80381ce71531fc", + "kind": "generated-docs", + "scriptSources": [ + "/document/assets/app.CkD0mcCX.js", + "/document/main.js", + "https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-8579453810848662" + ], + "status": "not-run", + "owner": "EX-03" + }, + { + "source": "docs/document/en/component/layers.html", + "route": "/document/en/component/layers.html", + "sha256Lf": "eafb4ee60806ee346acf8bde70e96772302ea396df7afade4668e74eda01a195", + "kind": "generated-docs", + "scriptSources": [ + "/document/assets/app.CkD0mcCX.js", + "/document/main.js", + "https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-8579453810848662" + ], + "status": "not-run", + "owner": "EX-03" + }, + { + "source": "docs/document/en/component/setting.html", + "route": "/document/en/component/setting.html", + "sha256Lf": "e7687900bdcf1ba2202b57f154d32ff07c27fac821bf90f072d89deadf89555d", + "kind": "generated-docs", + "scriptSources": [ + "/document/assets/app.CkD0mcCX.js", + "/document/main.js", + "https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-8579453810848662" + ], + "status": "not-run", + "owner": "EX-03" + }, + { + "source": "docs/document/en/index.html", + "route": "/document/en/", + "sha256Lf": "f50df7a7ddd77accd512782a47a79d7d78218168ca6b6bae4c8121debd124993", + "kind": "generated-docs", + "scriptSources": [ + "/document/assets/app.CkD0mcCX.js", + "/document/main.js", + "https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-8579453810848662" + ], + "status": "not-run", + "owner": "EX-03" + }, + { + "source": "docs/document/en/start/i18n.html", + "route": "/document/en/start/i18n.html", + "sha256Lf": "cbf63c77cede2fd83221077a6600405a43b0025d61b4f87259107185c38a1bef", + "kind": "generated-docs", + "scriptSources": [ + "/document/assets/app.CkD0mcCX.js", + "/document/main.js", + "https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-8579453810848662" + ], + "status": "not-run", + "owner": "EX-03" + }, + { + "source": "docs/document/en/start/option.html", + "route": "/document/en/start/option.html", + "sha256Lf": "3bce1c34c6e56144726eb83052cf2f68b52a7e9a815101912257696b4a8bd1ba", + "kind": "generated-docs", + "scriptSources": [ + "/document/assets/app.CkD0mcCX.js", + "/document/main.js", + "https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-8579453810848662" + ], + "status": "not-run", + "owner": "EX-03" + }, + { + "source": "docs/document/index.html", + "route": "/document/", + "sha256Lf": "641d24f3fb5b98a09e193debb2b749f4d63e3708ee3fa6860efbbfd1c4722e73", + "kind": "generated-docs", + "scriptSources": [ + "/document/assets/app.CkD0mcCX.js", + "/document/main.js", + "https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-8579453810848662" + ], + "status": "not-run", + "owner": "EX-03" + }, + { + "source": "docs/document/plugin/danmuku.html", + "route": "/document/plugin/danmuku.html", + "sha256Lf": "4460414baf1a9c313ef7bba74f50fa009825ef3bcc1be3b1462e6571b47a2d67", + "kind": "generated-docs", + "scriptSources": [ + "/document/assets/app.CkD0mcCX.js", + "/document/main.js", + "https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-8579453810848662" + ], + "status": "not-run", + "owner": "EX-03" + }, + { + "source": "docs/document/start/i18n.html", + "route": "/document/start/i18n.html", + "sha256Lf": "8e219e949ab7b25b32c5c0e8f4ff8674d195492ccfa24b07e98722f27443ac97", + "kind": "generated-docs", + "scriptSources": [ + "/document/assets/app.CkD0mcCX.js", + "/document/main.js", + "https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-8579453810848662" + ], + "status": "not-run", + "owner": "EX-03" + }, + { + "source": "docs/document/start/option.html", + "route": "/document/start/option.html", + "sha256Lf": "5819935c8660dc958ad60a0211a2bbff1f7208c62b930d4b70a8972a1bd72c70", + "kind": "generated-docs", + "scriptSources": [ + "/document/assets/app.CkD0mcCX.js", + "/document/main.js", + "https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-8579453810848662" + ], + "status": "not-run", + "owner": "EX-03" + }, + { + "source": "docs/esm.html", + "route": "/esm.html", + "sha256Lf": "bf9eaaf69b7705d53edab101fade2ce467dd63bb2830a89d4bc4cda44667ff3c", + "kind": "demo-or-editor", + "scriptSources": [], + "status": "not-run", + "owner": "EX-03" + }, + { + "source": "docs/googlebcdef0d1e9238554.html", + "route": "/googlebcdef0d1e9238554.html", + "sha256Lf": "db372eb59ddfb090f7b09273bfeb87da90fb8d3454f7aa89b12a6c43ab27ed43", + "kind": "site-verification", + "scriptSources": [], + "status": "not-run", + "owner": "SITE-01" + }, + { + "source": "docs/i18n.html", + "route": "/i18n.html", + "sha256Lf": "4e54b71d58f85ee386698d0e53267b3e3fa6251f48087a9724dd08c07495d03b", + "kind": "demo-or-editor", + "scriptSources": [ + "./compiled/artplayer.js", + "./compiled/i18n/ar.js", + "./compiled/i18n/cs.js", + "./compiled/i18n/es.js", + "./compiled/i18n/fa.js", + "./compiled/i18n/fr.js", + "./compiled/i18n/id.js", + "./compiled/i18n/pl.js", + "./compiled/i18n/ru.js", + "./compiled/i18n/tr.js", + "./compiled/i18n/vi.js", + "./compiled/i18n/zh-tw.js" + ], + "status": "not-run", + "owner": "EX-03" + }, + { + "source": "docs/iframe.html", + "route": "/iframe.html", + "sha256Lf": "bc262262c66ad32459b7c91ae22a97217414dd5b18cbf68fe105c2269456f879", + "kind": "demo-or-editor", + "scriptSources": [ + "./uncompiled/artplayer/index.js", + "./uncompiled/artplayer-tool-iframe/index.js" + ], + "status": "not-run", + "owner": "EX-03" + }, + { + "source": "docs/index.html", + "route": "/", + "sha256Lf": "bd2e7e32efce80725b70f2054c4d9c95465de567118f245924f2e6d17567ff23", + "kind": "demo-or-editor", + "scriptSources": [ + "https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-8579453810848662", + "./assets/js/console.js", + "./assets/js/vs/loader.js" + ], + "status": "not-run", + "owner": "EX-03" + }, + { + "source": "docs/mobile.html", + "route": "/mobile.html", + "sha256Lf": "f6cf85608023ee57750af773908d4c8ecd95c1065b1aa587e28e2361b2cee7fd", + "kind": "demo-or-editor", + "scriptSources": [ + "https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-8579453810848662", + "./assets/js/vconsole.min.js", + "./uncompiled/artplayer/index.js", + "./assets/js/mobile.js" + ], + "status": "not-run", + "owner": "EX-03" + }, + { + "source": "docs/test/index.html", + "route": "/test/", + "sha256Lf": "67132147ebbb63867c05be182ec18fc6c3129df89808bf17819c92cee9a4769c", + "kind": "demo-or-editor", + "scriptSources": [ + "./chai.js", + "./mocha.js", + "../compiled/artplayer.js", + "../compiled/artplayer-plugin-ads.js", + "../compiled/artplayer-plugin-danmuku.js", + "../compiled/artplayer-plugin-dash-control.js", + "../compiled/artplayer-plugin-hls-control.js", + "../compiled/artplayer-tool-iframe.js", + "../compiled/artplayer-plugin-vtt-thumbnail.js", + "../compiled/artplayer-plugin-chapter.js", + "https://cdnjs.cloudflare.com/ajax/libs/hls.js/1.5.17/hls.min.js", + "https://cdnjs.cloudflare.com/ajax/libs/dashjs/5.2.1/modern/umd/dash.all.min.js", + "https://cdnjs.cloudflare.com/ajax/libs/flv.js/1.6.2/flv.min.js", + "./test.js" + ], + "status": "not-run", + "owner": "EX-03" + }, + { + "source": "docs/upscaler/index.html", + "route": "/upscaler/", + "sha256Lf": "a04d9e364ee20cb1245c0ac9200ba28d6a3ffff51407a71725f943a1026051aa", + "kind": "standalone-tool", + "scriptSources": [ + "https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-8579453810848662", + "https://cdn.tailwindcss.com", + "upscaler.js" + ], + "status": "not-run", + "owner": "EX-03" + } + ], + "packages": [ + { + "name": "artplayer", + "examples": [], + "status": "not-run", + "owner": "EX-03" + }, + { + "name": "artplayer-plugin-ads", + "examples": [ + "ads" + ], + "status": "not-run", + "owner": "EX-03" + }, + { + "name": "artplayer-plugin-ambilight", + "examples": [ + "ambilight" + ], + "status": "not-run", + "owner": "EX-03" + }, + { + "name": "artplayer-plugin-asr", + "examples": [ + "asr" + ], + "status": "not-run", + "owner": "EX-03" + }, + { + "name": "artplayer-plugin-audio-track", + "examples": [ + "audio.track" + ], + "status": "not-run", + "owner": "EX-03" + }, + { + "name": "artplayer-plugin-auto-thumbnail", + "examples": [ + "auto.thumbnail" + ], + "status": "not-run", + "owner": "EX-03" + }, + { + "name": "artplayer-plugin-chapter", + "examples": [ + "chapter" + ], + "status": "not-run", + "owner": "EX-03" + }, + { + "name": "artplayer-plugin-chromecast", + "examples": [ + "chromecast" + ], + "status": "not-run", + "owner": "EX-03" + }, + { + "name": "artplayer-plugin-danmuku", + "examples": [ + "danmuku", + "danmuku.mask" + ], + "status": "not-run", + "owner": "EX-03" + }, + { + "name": "artplayer-plugin-danmuku-mask", + "examples": [ + "danmuku.mask" + ], + "status": "not-run", + "owner": "EX-03" + }, + { + "name": "artplayer-plugin-dash-control", + "examples": [ + "dash.control" + ], + "status": "not-run", + "owner": "EX-03" + }, + { + "name": "artplayer-plugin-document-pip", + "examples": [ + "document.pip" + ], + "status": "not-run", + "owner": "EX-03" + }, + { + "name": "artplayer-plugin-hls-control", + "examples": [ + "hls.control" + ], + "status": "not-run", + "owner": "EX-03" + }, + { + "name": "artplayer-plugin-jassub", + "examples": [ + "jassub" + ], + "status": "not-run", + "owner": "EX-03" + }, + { + "name": "artplayer-plugin-multiple-subtitles", + "examples": [ + "multiple.subtitles" + ], + "status": "not-run", + "owner": "EX-03" + }, + { + "name": "artplayer-plugin-vast", + "examples": [ + "vast" + ], + "status": "not-run", + "owner": "EX-03" + }, + { + "name": "artplayer-plugin-vtt-thumbnail", + "examples": [ + "vtt.thumbnail" + ], + "status": "not-run", + "owner": "EX-03" + }, + { + "name": "artplayer-proxy-canvas", + "examples": [ + "canvas" + ], + "status": "not-run", + "owner": "EX-03" + }, + { + "name": "artplayer-proxy-mediabunny", + "examples": [ + "mediabunny" + ], + "status": "not-run", + "owner": "EX-03" + }, + { + "name": "artplayer-tool-iframe", + "examples": [ + "iframe" + ], + "status": "not-run", + "owner": "EX-03" + }, + { + "name": "artplayer-tool-thumbnail", + "examples": [ + "tool.thumbnail" + ], + "status": "not-run", + "owner": "EX-03" + }, + { + "name": "artplayer-vitepress", + "examples": [], + "status": "not-run", + "owner": "SITE-01" + } + ], + "editor": { + "source": "docs/assets/js/common.js", + "sha256Lf": "2db7c8e198b06986a626631f0932fe7d8a687f758f196136833acdd00b71b107", + "storage": [ + "prod", + "ts", + "code", + "log" + ], + "isolation": "Use separate test origin; record keys, do not erase user browser data.", + "core": { + "prodTrue": "./compiled/artplayer.js", + "otherwise": "./uncompiled/artplayer/index.js" + }, + "pluginSources": "URL libs parameter; independent of prod toggle", + "execution": "Run evaluates editor text; TS mode alone is not strict tsc validation.", + "runtimeStatus": "not-run" + } +} diff --git a/refactor/baselines/dom-coverage.md b/refactor/baselines/dom-coverage.md new file mode 100644 index 000000000..186832c7c --- /dev/null +++ b/refactor/baselines/dom-coverage.md @@ -0,0 +1,46 @@ +# DOM、CSS、输入与官方 demo 基线 + +BASE-04 使用固定 npm artplayer 5.4.0 / chapter 1.1.0,在 Codex 内置浏览器最终两次独立 reload 后真实点击和按键。16 项断言通过,DOM 语义快照相同,errors/unhandled 和浏览器 error/warn 日志为空。来源和时间见 [dom.json](dom.json),不是当前工作区候选或外部 Chrome 扩展验收。 + +## 已记录的扩展契约 + +| 契约 | 固定测试 ID / 数据 | 后续责任 | +| --- | --- | --- | +| API-08 模板/样式 | DOM.version-template、user-style;snapshot.template/tree/cssClasses/cssVariables | CORE-12:模板、88 个核心 CSS 类名匹配、43 个 CSS 变量;保留用户选择器和覆盖入口 | +| API-06/08 chapter | DOM.chapter-markup;chapters、chapterStylePresent | PKG-CHAPTER-01/02:两个章节、start/end/title 数据及样式注入,其他参数/悬停/销毁行为继续补测 | +| API-07 控件/图层 | DOM.control-click/update/remove、layer-remove、destroy | CORE-13:真实 click 的 this/参数、按 name 替换和清理;controls.update 返回 undefined,元素通过 controls[name] 获取 | +| API-07 设置 | DOM.setting-select/update/remove;selected | CORE-14:选择 High,当前节点 art-current,默认值 false/true,回调 this/参数和移除 | +| API-08/10 网页全屏 | DOM.fullscreen-web-enter/exit;Escape interaction | CORE-16:点击后挂到 body,Escape 恢复原容器/class;未测原生全屏或 PiP 权限 | +| API-10 输入/焦点 | DOM.keyboard-seek、input-ignores-hotkey;interactions | CORE-17/23:ArrowRight 从 0 到 5 秒,输入框相同键不 seek;Tab/焦点、可信事件来源有记录 | +| API-08 布局 | DOM.narrow-container;wide/narrow | CORE-13:640x360 和 320x180 容器边界及控件测量;不是移动 viewport/触摸/真机验证 | +| API-08/10 可访问属性 | controlAttributes、tree 的 role/aria/tabindex;实际 Tab 两次 | CORE-23:DOM 属性不是完整 accessibility tree 审计;浏览器 snapshot 中按钮为 generic,用户输入层 textbox 可用 | + +上述短 ID 均使用 DOM. 前缀,完整列表由 dom.mjs 的 domChecks 固定。模板是发布版 Artplayer.html 原文;运行时树保留节点嵌套、class、role、aria、tabindex、type,省略 SVG 内部路径和变动文本。CSS 清单从发布 STYLE 提取,不是全部伪类/组合选择器/所有主题的视觉回归。用户规则 `.player .user-hook` 和 `art.cssVar('--art-theme', ...)` 通过计算样式验证。章节样式依赖固定发布成员哈希,未另做全部插件 CSS 清单。 + +## 历史问题与界限 + +| ID | 已观察事实 | 责任与候选要求 | +| --- | --- | --- | +| BASE-DOM-01 | 实际 Tab 从外部按钮到用户 input,再到播放器后的按钮;8 个 .art-control 根节点均为 DIV / tabIndex -1 / 无 role。部分控件及子节点已有 aria-label,不能概括为完全没有名称 | CORE-23,关联 CORE-17:补主要控件/设置可达性与名称,保持旧快捷键/DOM 钩子;不要求候选重复不可达状态 | +| BASE-DOM-02 | 默认桌面控件加 Probe control,在 320x180 容器中设置和网页全屏控件越过右边界;截图目视确认裁切,player.scrollWidth 仍为 320 | CORE-13:补窄容器布局回归;CORE-14 同时检查设置面板定位;不把截图当移动端通过 | +| BASE-DEMO-01 | docs/assets/example/thumbnail.js 引用 artplayer-plugin-thumbnail,当前 22 包不存在它,首页也无该示例菜单链接 | SITE-01 / EX-03:核实历史外部包与迁移路径,不自动改成 auto-thumbnail 或删除旧示例 | + +问题只登记与分配,不在基线任务修改生产代码。dom.mjs --compare 比较同一发布基线;候选修复产生差异时应新增正向测试和解释,不能要求修复后仍保留错误,也不能覆盖历史报告消除差异。 + +## 重跑 + +1. 按 toolchain-setup.md 使用固定 Node/Yarn。运行 `node refactor/scripts/browser-server.mjs`,打开 `http://127.0.0.1:8083/fixtures/dom.html`。独立 origin 使用固定发布脚本和本地 MP4,未运行 Monaco 或读取编辑器四个开关。 +2. 等待 DOM.version-template / user-style / chapter-markup 出现。点击 Tab start,按 Tab 到 Typing probe,再按 Tab 到 Inspect narrow container,观察原始可达性。 +3. 点击 Probe control,再按 ArrowRight;点击 Typing probe,再按 ArrowRight。依次点击设置、Baseline selector、High;点击网页全屏,再按 Escape。 +4. 点击 Inspect narrow container,检查右侧裁切和章节条;点击 Save DOM baseline。报告写到 refactor/.cache/reports/dom.json,必须显示 16 checks / errors 0。 +5. 运行 `node refactor/scripts/dom.mjs --compare refactor/.cache/reports/dom.json`。重载重复实际操作,不用 dispatchEvent 代替 trusted 输入。 + +`node refactor/scripts/dom.mjs --check` 只校验冻结报告,`node --test refactor/scripts/dom.test.mjs` 验证缺输入、trusted=false、错误媒体/热键、类名/变量/布局差异等拒绝机制。报告不是抗恶意篡改证明;操作与来源记录须一起审查。小数像素宽度不作跨环境精确比较,容器边界、类名与可访问属性变化会报告差异。 + +## 全量路径台账 + +[demo-inventory.json](demo-inventory.json) 覆盖 29 个 example JS、36 个 HTML 路径与 22 包。包含 25 条首页菜单链接及 libs、4 个无菜单示例、6 个 demo/编辑器入口、28 个生成文档页面、独立 upscaler 工具页和站点验证页。核心通过所有示例使用,vitepress 通过 document 页面覆盖;两者没有插件式 libs 菜单不是缺包。 + +所有官方 docs 页面仍标 not-run,只有独立轻量夹具已实测。没有把 core/chapter 夹具通过改写成官方 chapter 示例或 Monaco 已通过。外部 SDK、媒体 URL、动态 import/脚本和无菜单示例依赖仍由 SITE-01 / EX-03 核实;scriptSources 仅列非注释的静态 script src,动态来源见 docs-browser-testing.md。 + +`node refactor/scripts/demos.mjs --check` 检查文件/HTML/菜单/包覆盖,不代表网络或浏览器通过。源码 LF 哈希描述历史采集,内容演进不自动覆盖旧值;路径增删需要显式补充和记录。负例进入 test:baseline。生成 document 页面依旧不手改。 diff --git a/refactor/baselines/dom.json b/refactor/baselines/dom.json new file mode 100644 index 000000000..eb2d9c1e5 --- /dev/null +++ b/refactor/baselines/dom.json @@ -0,0 +1,1630 @@ +{ + "schemaVersion": 1, + "task": "BASE-04", + "sourceCommit": "94893929", + "browserSurface": "Codex in-app browser", + "report": { + "kind": "dom", + "environment": { + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/152.0.0.0 Safari/537.36", + "language": "zh-CN" + }, + "scripts": [ + "/releases/artplayer/dist/artplayer.js", + "/releases/artplayer-plugin-chapter/dist/artplayer-plugin-chapter.js", + "/fixtures/dom.js" + ], + "checks": [ + { + "id": "DOM.chapter-markup", + "passed": true + }, + { + "id": "DOM.control-click", + "passed": true + }, + { + "id": "DOM.control-remove", + "passed": true + }, + { + "id": "DOM.control-update", + "passed": true + }, + { + "id": "DOM.destroy", + "passed": true + }, + { + "id": "DOM.fullscreen-web-enter", + "passed": true + }, + { + "id": "DOM.fullscreen-web-exit", + "passed": true + }, + { + "id": "DOM.input-ignores-hotkey", + "passed": true + }, + { + "id": "DOM.keyboard-seek", + "passed": true + }, + { + "id": "DOM.layer-remove", + "passed": true + }, + { + "id": "DOM.narrow-container", + "passed": true + }, + { + "id": "DOM.setting-remove", + "passed": true + }, + { + "id": "DOM.setting-select", + "passed": true + }, + { + "id": "DOM.setting-update", + "passed": true + }, + { + "id": "DOM.user-style", + "passed": true + }, + { + "id": "DOM.version-template", + "passed": true + } + ], + "errors": [], + "unhandled": [], + "interactions": [ + { + "focus": "BUTTON", + "label": null, + "id": "tab-start" + }, + { + "time": 0, + "hotkeys": 0, + "focused": false, + "target": "BUTTON", + "code": "Tab", + "trusted": true, + "afterTime": 0, + "afterHotkeys": 0, + "activeTag": "BUTTON", + "activeLabel": null + }, + { + "focus": "INPUT", + "label": "Typing probe", + "id": "" + }, + { + "time": 0, + "hotkeys": 0, + "focused": false, + "target": "INPUT", + "code": "Tab", + "trusted": true, + "afterTime": 0, + "afterHotkeys": 0, + "activeTag": "INPUT", + "activeLabel": "Typing probe" + }, + { + "focus": "BUTTON", + "label": null, + "id": "narrow" + }, + { + "time": 0, + "hotkeys": 0, + "focused": true, + "target": "BODY", + "code": "ArrowRight", + "trusted": true, + "afterTime": 5, + "afterHotkeys": 1, + "activeTag": "BODY", + "activeLabel": null + }, + { + "focus": "INPUT", + "label": "Typing probe", + "id": "" + }, + { + "time": 5, + "hotkeys": 1, + "focused": true, + "target": "INPUT", + "code": "ArrowRight", + "trusted": true, + "afterTime": 5, + "afterHotkeys": 1, + "activeTag": "INPUT", + "activeLabel": "Typing probe" + }, + { + "time": 5, + "hotkeys": 1, + "focused": true, + "target": "BODY", + "code": "Escape", + "trusted": true, + "afterTime": 5, + "afterHotkeys": 2, + "activeTag": "BODY", + "activeLabel": null + }, + { + "focus": "BUTTON", + "label": null, + "id": "narrow" + }, + { + "focus": "BUTTON", + "label": null, + "id": "finish" + } + ], + "observations": { + "wide": { + "width": 640, + "height": 360, + "scrollWidth": 640, + "controls": [ + { + "class": "art-control art-control-progress", + "width": 640, + "withinPlayer": true, + "display": "flex" + }, + { + "class": "art-control art-control-thumbnails", + "width": 0, + "withinPlayer": true, + "display": "block" + }, + { + "class": "art-control art-control-playAndPause", + "width": 46, + "withinPlayer": true, + "display": "flex" + }, + { + "class": "art-control art-control-volume", + "width": 46, + "withinPlayer": true, + "display": "flex" + }, + { + "class": "art-control art-control-time", + "width": 106.69, + "withinPlayer": true, + "display": "flex" + }, + { + "class": "art-control art-control-compat hint--rounded hint--top", + "width": 91.19, + "withinPlayer": true, + "display": "flex" + }, + { + "class": "art-control art-control-setting hint--rounded hint--top", + "width": 46, + "withinPlayer": true, + "display": "flex" + }, + { + "class": "art-control art-control-fullscreenWeb hint--rounded hint--top", + "width": 46, + "withinPlayer": true, + "display": "flex" + } + ] + }, + "selected": { + "html": "High", + "defaults": [ + false, + true + ] + }, + "narrow": { + "width": 320, + "height": 180, + "scrollWidth": 320, + "controls": [ + { + "class": "art-control art-control-progress", + "width": 300, + "withinPlayer": true, + "display": "flex" + }, + { + "class": "art-control art-control-thumbnails", + "width": 0, + "withinPlayer": true, + "display": "block" + }, + { + "class": "art-control art-control-playAndPause", + "width": 46, + "withinPlayer": true, + "display": "flex" + }, + { + "class": "art-control art-control-volume", + "width": 46, + "withinPlayer": true, + "display": "flex" + }, + { + "class": "art-control art-control-time", + "width": 106.69, + "withinPlayer": true, + "display": "flex" + }, + { + "class": "art-control art-control-compat hint--rounded hint--top", + "width": 91.19, + "withinPlayer": true, + "display": "flex" + }, + { + "class": "art-control art-control-setting hint--rounded hint--top", + "width": 46, + "withinPlayer": false, + "display": "flex" + }, + { + "class": "art-control art-control-fullscreenWeb hint--rounded hint--top", + "width": 46, + "withinPlayer": false, + "display": "flex" + } + ] + } + }, + "snapshot": { + "template": "\n
Use Probe control, ArrowRight, Typing probe + ArrowRight, settings Baseline selector / High, and web fullscreen + Escape. Then inspect narrow layout and save.
+ + + + +Loading published player
+ + + + + diff --git a/refactor/fixtures/dom.js b/refactor/fixtures/dom.js new file mode 100644 index 000000000..5c6807bd4 --- /dev/null +++ b/refactor/fixtures/dom.js @@ -0,0 +1,119 @@ +/* global Artplayer, artplayerPluginChapter */ +(() => { + const report = { + kind: 'dom', environment: { userAgent: navigator.userAgent, language: navigator.language }, + scripts: [...document.scripts].map(script => new URL(script.src).pathname), + checks: [], errors: [], unhandled: [], interactions: [], observations: {}, + } + const status = document.querySelector('#status') + const check = (id, passed) => { + if (report.checks.some(item => item.id === id)) return + report.checks.push({ id, passed: Boolean(passed) }) + if (!passed) throw new Error(id) + status.textContent = report.checks.map(item => item.id).join(' | ') + } + addEventListener('error', event => report.errors.push(event.message)) + addEventListener('unhandledrejection', event => report.unhandled.push(String(event.reason))) + function tree(element) { + return { + tag: element.tagName.toLowerCase(), + attributes: Object.fromEntries([...element.attributes].filter(attr => /^(class|role|aria-.+|tabindex|data-tooltip|type)$/.test(attr.name)).map(attr => [attr.name, attr.value])), + children: element.tagName.toLowerCase() === 'svg' ? [] : [...element.children].map(tree), + } + } + function layout() { + const player = art.template.$player + const rect = player.getBoundingClientRect() + return { + width: rect.width, height: rect.height, scrollWidth: player.scrollWidth, + controls: [...player.querySelectorAll('.art-control')].map(el => { + const r = el.getBoundingClientRect() + return { class: el.className, width: Math.round(r.width * 100) / 100, withinPlayer: r.left >= rect.left - 1 && r.right <= rect.right + 1, display: getComputedStyle(el).display } + }), + } + } + const art = new Artplayer({ + container: '.player', url: '/assets/sample/video.mp4', muted: true, lang: 'en', + setting: true, playbackRate: true, aspectRatio: true, fullscreenWeb: true, hotkey: true, + controls: [{ name: 'compat', position: 'right', html: 'Probe control', tooltip: 'Probe control', click(component, event) { + check('DOM.control-click', this === art && component === art.controls && event.isTrusted) + } }], + layers: [{ name: 'compat', html: '', style: { top: '12px', left: '12px' } }], + settings: [{ name: 'compat-setting', html: 'Baseline selector', selector: [{ html: 'Low', default: true }, { html: 'High' }], onSelect(item, element, event) { + check('DOM.setting-select', this === art && item.html === 'High' && element.classList.contains('art-current') && event.isTrusted) + report.observations.selected = { html: item.html, defaults: item.$parent.selector.map(value => value.default) } + return item.html + } }], + plugins: [artplayerPluginChapter({ chapters: [{ start: 0, end: 10, title: 'First' }, { start: 10, end: Infinity, title: 'Second' }] })], + }) + let ready = false + art.once('ready', () => { + check('DOM.version-template', Artplayer.version === '5.4.0' && art.query('.art-video') === art.video) + art.cssVar('--art-theme', 'rgb(1, 2, 3)') + check('DOM.user-style', getComputedStyle(art.query('.user-hook')).color === 'rgb(12, 34, 56)' && art.cssVar('--art-theme').trim() === 'rgb(1, 2, 3)') + const chapters = [...art.query('.art-chapters').children].map(el => ({ class: el.className, start: Number(el.dataset.start), end: Number(el.dataset.end), title: el.dataset.title })) + check('DOM.chapter-markup', chapters.length === 2 && chapters[0].title === 'First' && chapters[1].title === 'Second') + report.snapshot = { + template: Artplayer.html, tree: tree(art.template.$player), + cssVariables: [...new Set(Artplayer.STYLE.match(/--art-[\w-]+/g))].sort(), + cssClasses: [...new Set(Artplayer.STYLE.match(/\.art-[\w-]+/g))].sort(), + chapters, + controlAttributes: [...art.template.$player.querySelectorAll('.art-control')].map(el => ({ class: el.className, tag: el.tagName, tabIndex: el.tabIndex, role: el.getAttribute('role'), ariaLabel: el.getAttribute('aria-label'), tooltip: el.getAttribute('data-tooltip'), title: el.getAttribute('title') })), + chapterStylePresent: Boolean(document.getElementById('artplayer-plugin-chapter')), + } + report.observations.wide = layout() + ready = true + }) + let beforeKey + let hotkeys = 0 + document.addEventListener('keydown', event => { + beforeKey = { time: art.currentTime, hotkeys, focused: art.isFocus, target: event.target.tagName, code: event.code, trusted: event.isTrusted } + }, true) + art.on('hotkey', () => hotkeys++) + document.addEventListener('keydown', event => { + if (!ready) return + const after = { ...beforeKey, afterTime: art.currentTime, afterHotkeys: hotkeys, activeTag: document.activeElement.tagName, activeLabel: document.activeElement.getAttribute('aria-label') } + report.interactions.push(after) + if (event.code === 'ArrowRight' && beforeKey.target !== 'INPUT') check('DOM.keyboard-seek', beforeKey.trusted && beforeKey.focused && hotkeys === beforeKey.hotkeys + 1 && Math.abs(art.currentTime - beforeKey.time - Artplayer.SEEK_STEP) < 0.05) + if (event.code === 'ArrowRight' && beforeKey.target === 'INPUT') check('DOM.input-ignores-hotkey', beforeKey.trusted && beforeKey.focused && hotkeys === beforeKey.hotkeys && art.currentTime === beforeKey.time) + }) + document.addEventListener('focusin', event => report.interactions.push({ focus: event.target.tagName, label: event.target.getAttribute('aria-label'), id: event.target.id })) + art.on('fullscreenWeb', value => { + if (value) check('DOM.fullscreen-web-enter', art.template.$player.parentElement === document.body && art.template.$player.classList.contains('art-fullscreen-web')) + else check('DOM.fullscreen-web-exit', art.template.$player.parentElement === art.template.$container && !art.template.$player.classList.contains('art-fullscreen-web')) + }) + document.querySelector('#narrow').onclick = () => { + document.querySelector('.player').style.cssText = 'width:320px;height:180px' + requestAnimationFrame(() => { + report.observations.narrow = layout() + check('DOM.narrow-container', report.observations.narrow.width === 320 && report.observations.narrow.height === 180) + }) + } + document.querySelector('#finish').onclick = async () => { + try { + const previous = art.controls.compat + const updateResult = art.controls.update({ name: 'compat', html: 'Updated control' }) + const replacement = art.controls.compat + check('DOM.control-update', updateResult === undefined && replacement instanceof HTMLElement && !previous.isConnected && art.template.$player.querySelectorAll('.art-control-compat').length === 1) + art.controls.remove('compat') + check('DOM.control-remove', !replacement.isConnected && !art.controls.compat) + art.setting.update({ name: 'compat-setting', html: 'Updated selector' }) + check('DOM.setting-update', art.setting.find('compat-setting').html === 'Updated selector') + art.setting.remove('compat-setting') + check('DOM.setting-remove', !art.setting.find('compat-setting')) + art.layers.remove('compat') + check('DOM.layer-remove', !art.query('.user-hook')) + art.destroy() + check('DOM.destroy', document.querySelector('.player').children.length === 0 && Artplayer.instances.length === 0) + } + catch (error) { + report.errors.push(error.message) + if (Artplayer.instances.includes(art)) art.destroy() + } + report.checks.sort((a, b) => a.id.localeCompare(b.id)) + document.querySelector('#result').textContent = JSON.stringify(report, null, 2) + const response = await fetch('/reports/dom', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(report) }) + status.textContent = response.ok ? `Saved ${report.checks.length} checks; errors ${report.errors.length}` : `Save failed: ${response.status}` + document.querySelector('#finish').disabled = true + } +})() diff --git a/refactor/plan.md b/refactor/plan.md index fd5a1447f..b3c967daf 100644 --- a/refactor/plan.md +++ b/refactor/plan.md @@ -4,7 +4,7 @@ 基线:`40fcda6a37d0049d42e49c1e64e70d4fd9ba5f7f`。总任务 214 项,范围 22 个包及工作区/示例。 -状态:todo 194 / doing 0 / blocked 0 / done 20 / deferred 0。风险 L/M/H 表示兼容风险,不表示工期。 +状态:todo 193 / doing 0 / blocked 0 / done 21 / deferred 0。风险 L/M/H 表示兼容风险,不表示工期。 前置依赖是启动条件;验收是完成条件。任务可以继续拆分,但不能复用或悄悄删除旧 ID。 @@ -63,7 +63,7 @@ | BASE-HARNESS-01 | workspace