test(jassub): [PKG-JASSUB-01] freeze published contracts and vendor evidence

This commit is contained in:
Harvey Zhao committed 2026-09-13 12:35:21 +08:00
1 parent d44e81ce22
commit 2c73e2b105
20 files changed
+1949 -16

No files matched your search

+3 -2
View File
@@ -51,7 +51,7 @@
"ci:build": "yarn build:types && yarn build all && yarn build:i18n && yarn build:ts && yarn build:docs && yarn test:imports",
"test:imports": "node --test test/esm.test.js test/i18n.test.js test/ssr.test.js",
"typecheck": "node scripts/typecheck.mjs",
"test:unit": "node --test test/multiple-subtitles-merge.test.js test/multiple-subtitles-lifecycle.test.js test/multiple-subtitles-failures.test.js test/multiple-subtitles.test.js test/multiple-subtitles-vendor.test.js test/vtt-thumbnail-parser.test.js test/vtt-thumbnail-lifecycle.test.js test/vtt-thumbnail.test.js test/auto-thumbnail-frames.test.js test/auto-thumbnail-lifecycle.test.js test/auto-thumbnail.test.js test/thumbnail-emitter.test.js test/thumbnail-runtime.test.js test/thumbnail-vendor.test.js test/thumbnail-lifecycle.test.js test/thumbnail-input.test.js test/thumbnail.test.js test/iframe-navigation.test.js test/iframe-boundaries.test.js test/iframe-lifecycle.test.js test/iframe.test.js test/mediabunny.test.js test/mediabunny-shim.test.js test/mediabunny-coordination.test.js test/mediabunny-video.test.js test/mediabunny-audio.test.js test/mediabunny-hls.test.js test/mediabunny-entry.test.js test/mediabunny-capability.test.js test/mediabunny-load.test.js test/mediabunny-input.test.js test/dpip.test.js test/dpip-lifecycle.test.js test/canvas.test.js test/canvas-lifecycle.test.js test/ambilight.test.js test/ambilight-lifecycle.test.js test/ambilight-proxy.test.js test/vast.test.js test/vast-lifecycle.test.js test/ads.test.js test/ads-lifecycle.test.js test/playback.test.js test/dash-control.test.js test/dash-contract.test.js test/dash-lifecycle.test.js test/dash-events.test.js test/hls-control.test.js test/audio-track.test.js test/public-behavior.test.js test/helpers.test.js test/chapter.test.js test/utils.test.js test/resource-scope.test.js test/instance-lifecycle.test.js test/options.test.js test/media-hosts.test.js test/plugins.test.js test/source.test.js test/playback-properties.test.js test/media-events.test.js test/template-resources.test.js test/core-vendor.test.js test/component-resources.test.js test/setting-model.test.js test/setting-layout.test.js test/setting-resources.test.js test/subtitle.test.js test/display-native.test.js test/display-video-fullscreen.test.js test/display-pip.test.js test/display-mini.test.js test/display-sizing.test.js test/display-orientation.test.js test/hotkey.test.js test/listener-registry.test.js test/global-events.test.js test/pointer-events.test.js test/gesture.test.js test/event-scheduling.test.js test/notice.test.js test/fast-forward.test.js test/auto-playback.test.js test/builtin-layers.test.js test/prompt-components.test.js test/screenshot.test.js test/thumbnails.test.js test/progress.test.js test/environment.test.js test/storage.test.js test/facade-properties.test.js test/dom-boundaries.test.js test/initialization.test.js test/entry.test.js test/accessibility-button.test.js test/accessibility-focus.test.js test/accessibility-slider.test.js",
"test:unit": "node --test test/jassub.test.js test/multiple-subtitles-merge.test.js test/multiple-subtitles-lifecycle.test.js test/multiple-subtitles-failures.test.js test/multiple-subtitles.test.js test/multiple-subtitles-vendor.test.js test/vtt-thumbnail-parser.test.js test/vtt-thumbnail-lifecycle.test.js test/vtt-thumbnail.test.js test/auto-thumbnail-frames.test.js test/auto-thumbnail-lifecycle.test.js test/auto-thumbnail.test.js test/thumbnail-emitter.test.js test/thumbnail-runtime.test.js test/thumbnail-vendor.test.js test/thumbnail-lifecycle.test.js test/thumbnail-input.test.js test/thumbnail.test.js test/iframe-navigation.test.js test/iframe-boundaries.test.js test/iframe-lifecycle.test.js test/iframe.test.js test/mediabunny.test.js test/mediabunny-shim.test.js test/mediabunny-coordination.test.js test/mediabunny-video.test.js test/mediabunny-audio.test.js test/mediabunny-hls.test.js test/mediabunny-entry.test.js test/mediabunny-capability.test.js test/mediabunny-load.test.js test/mediabunny-input.test.js test/dpip.test.js test/dpip-lifecycle.test.js test/canvas.test.js test/canvas-lifecycle.test.js test/ambilight.test.js test/ambilight-lifecycle.test.js test/ambilight-proxy.test.js test/vast.test.js test/vast-lifecycle.test.js test/ads.test.js test/ads-lifecycle.test.js test/playback.test.js test/dash-control.test.js test/dash-contract.test.js test/dash-lifecycle.test.js test/dash-events.test.js test/hls-control.test.js test/audio-track.test.js test/public-behavior.test.js test/helpers.test.js test/chapter.test.js test/utils.test.js test/resource-scope.test.js test/instance-lifecycle.test.js test/options.test.js test/media-hosts.test.js test/plugins.test.js test/source.test.js test/playback-properties.test.js test/media-events.test.js test/template-resources.test.js test/core-vendor.test.js test/component-resources.test.js test/setting-model.test.js test/setting-layout.test.js test/setting-resources.test.js test/subtitle.test.js test/display-native.test.js test/display-video-fullscreen.test.js test/display-pip.test.js test/display-mini.test.js test/display-sizing.test.js test/display-orientation.test.js test/hotkey.test.js test/listener-registry.test.js test/global-events.test.js test/pointer-events.test.js test/gesture.test.js test/event-scheduling.test.js test/notice.test.js test/fast-forward.test.js test/auto-playback.test.js test/builtin-layers.test.js test/prompt-components.test.js test/screenshot.test.js test/thumbnails.test.js test/progress.test.js test/environment.test.js test/storage.test.js test/facade-properties.test.js test/dom-boundaries.test.js test/initialization.test.js test/entry.test.js test/accessibility-button.test.js test/accessibility-focus.test.js test/accessibility-slider.test.js",
"test:coverage": "node --test test/coverage.test.js && node scripts/coverage.mjs",
"test": "yarn test:node && yarn test:baseline",
"test:browser": "playwright test",
@@ -89,7 +89,8 @@
"test:vtt-thumbnail": "node --test test/vtt-thumbnail-parser.test.js test/vtt-thumbnail-lifecycle.test.js test/vtt-thumbnail.test.js refactor/scripts/vtt-thumbnail-contract.test.mjs refactor/scripts/vtt-thumbnail-types.test.mjs",
"test:vtt-thumbnail-types-package": "node refactor/scripts/vtt-thumbnail-package-types.mjs",
"test:multiple-subtitles": "node --test test/multiple-subtitles-merge.test.js test/multiple-subtitles-lifecycle.test.js test/multiple-subtitles-failures.test.js test/multiple-subtitles.test.js test/multiple-subtitles-vendor.test.js refactor/scripts/multiple-subtitles-contract.test.mjs refactor/scripts/multiple-subtitles-runtime-types.test.mjs refactor/scripts/multiple-subtitles-types.test.mjs",
"test:multiple-subtitles-types-package": "node refactor/scripts/multiple-subtitles-package-types.mjs"
"test:multiple-subtitles-types-package": "node refactor/scripts/multiple-subtitles-package-types.mjs",
"test:jassub": "node --test test/jassub.test.js refactor/scripts/jassub-contract.test.mjs"
},
"browserslist": "last 1 Chrome version",
"devDependencies": {
@@ -0,0 +1,38 @@
# JASSUB maintenance
`src/index.js` is the ArtPlayer-owned adapter. It forwards `{ video: art.video, ...option }`
to the vendored constructor, sets the canvas parent's z-index to 20, registers a destroy
listener, and synchronously returns `{ name: 'artplayerPluginJassub', instance }`. The instance
is the actual vendor object. Options remain live until registration; a supplied video wins.
`src/jassub.es.js` owns rendering, media listeners, canvas state, capability checks and worker
messages. Keep this third-party file separate from the adapter's TypeScript migration.
`worker/` contains worker/WASM files; the actual 1.0.0/1.1.0 npm packages do not ship those
files. The local demo explicitly hosts its resources under `docs/assets/jassub/` and selects
fonts in `docs/assets/example/jassub.js`. Do not move or rename those URLs as an internal cleanup.
`types/artplayer-plugin-jassub.d.ts` currently requires three resource URLs and describes
resize/setVideo/destroy as Promise-returning. Actual historical methods are synchronous, and
resize is width/height/top/left/force. Keep the existing declarations until the dedicated public
type compatibility work has assessed extraction, callbacks and replacement consumers.
Both option and instance expose extension indexes; they are existing compatibility boundaries.
Provenance is incomplete. The wrapper matches upstream jassub 1.8.8 apart from formatting and
the ESLint header; worker JS and default font match that archive byte-for-byte. Local WASM
files validate but differ from its build. Other font metadata includes different source and
license clues; do not infer redistribution rights from family names or embedding flags.
Task PKG-JASSUB-01 and VENDOR-04/05 remain open. Full original acquisition history is unknown.
Use the pinned Node/Yarn toolchain:
```sh
yarn test:jassub
yarn build artplayer-plugin-jassub
```
The baseline runner verifies both actual published packages and frozen workspace inputs.
Set ARTPLAYER_JASSUB_CANDIDATE=1 for current source behavior; ARTPLAYER_JASSUB_ARTIFACT can point
at a main/legacy artifact. Tests use controlled DOM, Worker and SIMD detection, with actual
vendor JavaScript. They do not render ASS or execute worker WASM. Real browser, failures,
repeated destroy and resource cleanup remain later steps. See
`../../refactor/baselines/jassub-contract.md` for precise contract and provenance evidence.
@@ -6,6 +6,11 @@ jassub plugin for ArtPlayer
[https://artplayer.org](https://artplayer.org/?libs=./uncompiled/artplayer-plugin-jassub/index.js&example=jassub)
## Maintenance
See [maintenance notes](ARCHITECTURE.md) for adapter/vendor boundaries, resource paths,
historical declaration differences and the current validation scope.
## License
MIT © Harvey Zhao
@@ -0,0 +1,506 @@
{
"schemaVersion": 1,
"task": "PKG-JASSUB-01",
"status": "contract-and-provenance-checkpoint-validated",
"parentCommit": "d44e81ce220d0d4475bf4f0f0c2e02ea5b09402a",
"checks": [
{
"command": "yarn test:jassub",
"tests": 48,
"historicalRuntime": 42,
"contract": 6,
"file": "refactor/.cache/jassub01-package-final.log",
"sha256": "f70a0897db9539a6cf40e37fc6869eb6fb33d32595350b23555250dc901794ce"
},
{
"command": "yarn ci:check",
"tests": 2392,
"unit": 2031,
"engineering": 14,
"baseline": 347,
"strictProductionTS": 353,
"file": "refactor/.cache/jassub01-ci.log",
"sha256": "40e23951bda7194fffd310fb14d8f0a87638015bbd94a18e18d6c9aa33e65dca"
},
{
"command": "explicit ESLint",
"file": "refactor/.cache/jassub01-lint.log",
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
},
{
"command": "font metadata extraction with cache-only pinned tools",
"tools": {
"python": "bundled 3.12",
"fonttools": "4.60.1",
"brotli": "1.1.0"
},
"file": "refactor/.cache/jassub01-font-tools-install.log",
"sha256": "f71cd9769dfefed0d9af8083155795c77dd4c540258dd1c783ead5dba0202af1"
}
],
"exports": [
{
"name": "published-1.1.0-main",
"type": "function",
"keys": [],
"defaultType": "undefined"
},
{
"name": "published-1.1.0-legacy",
"type": "function",
"keys": [],
"defaultType": "undefined"
},
{
"name": "published-1.0.0-main",
"type": "object",
"keys": [
"default"
],
"defaultType": "function"
},
{
"name": "published-1.0.0-legacy",
"type": "object",
"keys": [
"default"
],
"defaultType": "function"
},
{
"name": "frozen-workspace-source",
"type": "object",
"keys": [
"default"
],
"defaultType": "function"
},
{
"name": "frozen-workspace-js",
"type": "function",
"keys": [],
"defaultType": "undefined"
},
{
"name": "frozen-workspace-legacy.js",
"type": "function",
"keys": [],
"defaultType": "undefined"
}
],
"wasmSections": [
{
"name": "jassub-worker.wasm",
"local": [
{
"id": 1,
"size": 633,
"sha256": "79485b4b23b968eefc463bb3a3adabd6e26136e74c56cf84c8c9e8f25c321bf9"
},
{
"id": 2,
"size": 216,
"sha256": "25a57a6a3fe3583d1d96602fdf0d8bd7f18d29489844a172698d4ad725a21e71"
},
{
"id": 3,
"size": 1618,
"sha256": "4442c87575ae02eafca8969f6e571c9d1bdcf03329811bb61255b4050da71d1d"
},
{
"id": 4,
"size": 7,
"sha256": "726ed65c5ec59a1d081332ce302c238fbe9cb661b2fef8cb8b9d9e3ef4f2985d"
},
{
"id": 6,
"size": 13,
"sha256": "7b46893c04c3ac28872a2651297611eb2c2af3adc8da709f524347396b5faf8d"
},
{
"id": 7,
"size": 58,
"sha256": "2653238382beb1fc644ca2f2ad5ff496ab746ba15fe73fe571b1a4162b8041dc"
},
{
"id": 8,
"size": 2,
"sha256": "3629b242adba7b3ceb2b1671781bbf97ac4528828f06615302b3763f9c0d5694"
},
{
"id": 9,
"size": 1986,
"sha256": "859b7d004cc1d0322a745c95c6c7ff8b274b3c785cfdcc018d4af8b3c7c69ee6"
},
{
"id": 12,
"size": 2,
"sha256": "6d82d88c2b99bec8e610281530ca069be0388a4dec57a467b32a6fd18b67b784"
},
{
"id": 10,
"size": 1429042,
"sha256": "8bc110e2216251065bf49786f9f01ad879217d45d13df3d123a9bd8406689914"
},
{
"id": 11,
"size": 535485,
"sha256": "2a7a807682278ae6f71d4c687432df23c800792effb01b6eedb68c427e27622f"
}
],
"upstream": [
{
"id": 1,
"size": 633,
"sha256": "79485b4b23b968eefc463bb3a3adabd6e26136e74c56cf84c8c9e8f25c321bf9"
},
{
"id": 2,
"size": 216,
"sha256": "25a57a6a3fe3583d1d96602fdf0d8bd7f18d29489844a172698d4ad725a21e71"
},
{
"id": 3,
"size": 1618,
"sha256": "4442c87575ae02eafca8969f6e571c9d1bdcf03329811bb61255b4050da71d1d"
},
{
"id": 4,
"size": 7,
"sha256": "726ed65c5ec59a1d081332ce302c238fbe9cb661b2fef8cb8b9d9e3ef4f2985d"
},
{
"id": 6,
"size": 13,
"sha256": "3da39da845dc9cd47aafdecf9b23b22172ea2805d566e0a81b115fe428a58996"
},
{
"id": 7,
"size": 58,
"sha256": "2653238382beb1fc644ca2f2ad5ff496ab746ba15fe73fe571b1a4162b8041dc"
},
{
"id": 8,
"size": 2,
"sha256": "3629b242adba7b3ceb2b1671781bbf97ac4528828f06615302b3763f9c0d5694"
},
{
"id": 9,
"size": 1986,
"sha256": "859b7d004cc1d0322a745c95c6c7ff8b274b3c785cfdcc018d4af8b3c7c69ee6"
},
{
"id": 12,
"size": 2,
"sha256": "0c09b67bcc41802c042b1e78002b25dbd7ce99f4b871e499fe59633df7b6848a"
},
{
"id": 10,
"size": 1429093,
"sha256": "7e6390f9446b975dd0679f9dfc94109230fdea81daea9c8a2a8a018ac62d8781"
},
{
"id": 11,
"size": 535511,
"sha256": "0ff8ec6983949e6d37553a06a7da6f9f07c67a24b3bb8ae75050203e3fe32cfa"
}
]
},
{
"name": "jassub-worker-modern.wasm",
"local": [
{
"id": 1,
"size": 644,
"sha256": "200a66233e30abc43c92f60a09d1b27101bbe9c712a4d40d0b02e90d4c932421"
},
{
"id": 2,
"size": 216,
"sha256": "25a57a6a3fe3583d1d96602fdf0d8bd7f18d29489844a172698d4ad725a21e71"
},
{
"id": 3,
"size": 1616,
"sha256": "632dfd99ca961cd746829e88e73c263cabc4ef24bc204d9f46667db5bb604b9e"
},
{
"id": 4,
"size": 7,
"sha256": "726ed65c5ec59a1d081332ce302c238fbe9cb661b2fef8cb8b9d9e3ef4f2985d"
},
{
"id": 6,
"size": 13,
"sha256": "7b46893c04c3ac28872a2651297611eb2c2af3adc8da709f524347396b5faf8d"
},
{
"id": 7,
"size": 58,
"sha256": "ce711c976114c2954e5f42071dc72b30b024182826e8e8449b2097534ee14b5a"
},
{
"id": 8,
"size": 2,
"sha256": "d466368e8e31f09570156d6587d324e68a559765aa56dd3c53f08b27abba3831"
},
{
"id": 9,
"size": 1986,
"sha256": "595e0c3671ed4942cd8028c351e39c66b21c7aec6bcde55c9e352011b6983f66"
},
{
"id": 12,
"size": 2,
"sha256": "6d82d88c2b99bec8e610281530ca069be0388a4dec57a467b32a6fd18b67b784"
},
{
"id": 10,
"size": 1497124,
"sha256": "a4e5b0b8bb699381f969384c058c20b844ce085f550555ff29769657bd1c3b96"
},
{
"id": 11,
"size": 535485,
"sha256": "ca2b95033623c2b3198f8ce8a8ecb3d71260727c8ccbb037e42ca267ef03d765"
}
],
"upstream": [
{
"id": 1,
"size": 644,
"sha256": "200a66233e30abc43c92f60a09d1b27101bbe9c712a4d40d0b02e90d4c932421"
},
{
"id": 2,
"size": 216,
"sha256": "25a57a6a3fe3583d1d96602fdf0d8bd7f18d29489844a172698d4ad725a21e71"
},
{
"id": 3,
"size": 1616,
"sha256": "632dfd99ca961cd746829e88e73c263cabc4ef24bc204d9f46667db5bb604b9e"
},
{
"id": 4,
"size": 7,
"sha256": "726ed65c5ec59a1d081332ce302c238fbe9cb661b2fef8cb8b9d9e3ef4f2985d"
},
{
"id": 6,
"size": 13,
"sha256": "3da39da845dc9cd47aafdecf9b23b22172ea2805d566e0a81b115fe428a58996"
},
{
"id": 7,
"size": 58,
"sha256": "ce711c976114c2954e5f42071dc72b30b024182826e8e8449b2097534ee14b5a"
},
{
"id": 8,
"size": 2,
"sha256": "d466368e8e31f09570156d6587d324e68a559765aa56dd3c53f08b27abba3831"
},
{
"id": 9,
"size": 1986,
"sha256": "595e0c3671ed4942cd8028c351e39c66b21c7aec6bcde55c9e352011b6983f66"
},
{
"id": 12,
"size": 2,
"sha256": "0c09b67bcc41802c042b1e78002b25dbd7ce99f4b871e499fe59633df7b6848a"
},
{
"id": 10,
"size": 1497126,
"sha256": "c4406cdfd8ca166894b6beee8bdbbdc8efb5287478306389988efc20f26aa7c1"
},
{
"id": 11,
"size": 535512,
"sha256": "af5af9c253fb605eb87b8c268510826b37e00e8fb3cba6f1ed27751f19bf2cf8"
}
]
}
],
"upstreamComparisons": [
{
"name": "jassub",
"version": "1.8.8",
"tarball": "https://registry.npmjs.org/jassub/-/jassub-1.8.8.tgz",
"integrity": "sha512-Vtw27Z0/hN2Tm2Qs4HAR+eONwwSD5ULo/hisPvmiaW9Ya6aFCt7esvWQSZy6nvBASbRyKmpghgeioIPqXGHA0Q==",
"sha256": "92668938b5f8ca47b26a1641a6dddf649a8c3e72a27bc54c4e7da3558c38b1bf",
"members": [
"package/LICENSE",
"package/README.md",
"package/dist/COPYRIGHT",
"package/dist/default.woff2",
"package/dist/jassub-worker-modern.wasm",
"package/dist/jassub-worker.js",
"package/dist/jassub-worker.wasm",
"package/dist/jassub-worker.wasm.js",
"package/dist/jassub.es.js",
"package/dist/jassub.umd.js",
"package/index.d.ts",
"package/package.json",
"package/src/jassub.js"
],
"matches": [
{
"member": "package/dist/default.woff2",
"file": "docs/assets/jassub/default.woff2",
"equal": true,
"lfEqual": false,
"upstream": "886929903707c5bb28b07cd2eed69921b3d5ef5c49c73a0dd1e187ebf6546a4c",
"local": "886929903707c5bb28b07cd2eed69921b3d5ef5c49c73a0dd1e187ebf6546a4c"
},
{
"member": "package/dist/jassub-worker.js",
"file": "packages/artplayer-plugin-jassub/worker/jassub-worker.js",
"equal": true,
"lfEqual": true,
"upstream": "0fb9a83f96fc39426e733a94f3e7fe4e37099324c08328450ba032b653e85707",
"local": "0fb9a83f96fc39426e733a94f3e7fe4e37099324c08328450ba032b653e85707"
}
]
},
{
"name": "jassub",
"version": "1.8.6",
"tarball": "https://registry.npmjs.org/jassub/-/jassub-1.8.6.tgz",
"integrity": "sha512-56ZTtjM7LfdKsi7boUN/seNOQSOclLuDWEXxnHO55xNakj95SlBrv36hLyNDw0NmoOtLVeqzbpBU1VxT+ubFpg==",
"sha256": "407fdc9267652280aac56a9d2795037960a9f30b524043023662facc5a7dd1f8",
"members": [
"package/LICENSE",
"package/README.md",
"package/dist/COPYRIGHT",
"package/dist/default.woff2",
"package/dist/jassub-worker-modern.wasm",
"package/dist/jassub-worker.js",
"package/dist/jassub-worker.wasm",
"package/dist/jassub-worker.wasm.js",
"package/dist/jassub.es.js",
"package/dist/jassub.umd.js",
"package/index.d.ts",
"package/package.json",
"package/src/jassub.js"
],
"matches": [
{
"member": "package/dist/default.woff2",
"file": "docs/assets/jassub/default.woff2",
"equal": true,
"lfEqual": false,
"upstream": "886929903707c5bb28b07cd2eed69921b3d5ef5c49c73a0dd1e187ebf6546a4c",
"local": "886929903707c5bb28b07cd2eed69921b3d5ef5c49c73a0dd1e187ebf6546a4c"
}
]
},
{
"name": "jassub",
"version": "1.8.5",
"tarball": "https://registry.npmjs.org/jassub/-/jassub-1.8.5.tgz",
"integrity": "sha512-BKf3qureEQcJ0WKi7rSJ86UsQF8hTcQqJaIWcwqezxIVTCOatT+tnShM6fauS0pdjeG4bLLFS2+51xMasl/WCw==",
"sha256": "93dfeb3fc3f2140a0c38085be06da38ce8aeddb5892eec01c1e2f4d18114a6dd",
"members": [
"package/LICENSE",
"package/README.md",
"package/dist/COPYRIGHT",
"package/dist/default.woff2",
"package/dist/jassub-worker-modern.wasm",
"package/dist/jassub-worker.js",
"package/dist/jassub-worker.wasm",
"package/dist/jassub-worker.wasm.js",
"package/dist/jassub.es.js",
"package/dist/jassub.umd.js",
"package/index.d.ts",
"package/package.json",
"package/src/jassub.js"
],
"matches": [
{
"member": "package/dist/default.woff2",
"file": "docs/assets/jassub/default.woff2",
"equal": true,
"lfEqual": false,
"upstream": "886929903707c5bb28b07cd2eed69921b3d5ef5c49c73a0dd1e187ebf6546a4c",
"local": "886929903707c5bb28b07cd2eed69921b3d5ef5c49c73a0dd1e187ebf6546a4c"
}
]
},
{
"name": "jassub",
"version": "2.0.10",
"tarball": "https://registry.npmjs.org/jassub/-/jassub-2.0.10.tgz",
"integrity": "sha512-xPQt2jlPgDC14TPu8utTllrgMsN4qAD+zKQcmrxVmuF0HxLuXT+9pzh+LgtQMrxDsj2YF1V4U4J/wF630EJD0w==",
"sha256": "a37059ac16d6e8ebe35b50c9ee235fb39f077d9ff51bfab8d361a5e3ec9e433b",
"members": [
"package/LICENSE",
"package/README.md",
"package/dist/jassub.d.ts",
"package/dist/jassub.js",
"package/dist/jassub.js.map",
"package/dist/wasm/jassub-worker-modern.d.ts",
"package/dist/wasm/jassub-worker-modern.js.map",
"package/dist/wasm/jassub-worker-modern.wasm",
"package/dist/wasm/jassub-worker.d.ts",
"package/dist/wasm/jassub-worker.js",
"package/dist/wasm/jassub-worker.js.map",
"package/dist/wasm/jassub-worker.wasm",
"package/dist/wasm/old.js",
"package/dist/wasm/types.d.ts",
"package/dist/worker/util.d.ts",
"package/dist/worker/util.js",
"package/dist/worker/util.js.map",
"package/dist/worker/webgpu-renderer.d.ts",
"package/dist/worker/webgpu-renderer.js",
"package/dist/worker/webgpu-renderer.js.map",
"package/dist/worker/worker.d.ts",
"package/dist/worker/worker.js",
"package/dist/worker/worker.js.map",
"package/package.json"
],
"matches": []
}
],
"inputs": [
{
"file": "refactor/baselines/jassub-release.json",
"sha256": "b97edb655e7deb5b11b4d69b69291cc8a78abb791f00ddceb3cc9b25a7113925"
},
{
"file": "refactor/baselines/jassub-vendor.json",
"sha256": "a04f2e65a4ad250e964ecc03712848989c7eb63953dfbc08808d71768977c4b4"
},
{
"file": "refactor/baselines/jassub-font-metadata.json",
"sha256": "6f110c76f204081daa61a20127dd974fbcc476a87882bee195348239e1b85128"
},
{
"file": "test/helpers/jassub.js",
"sha256": "16e7506ca140c61526e16bcc748c8f1d559f522950bebfbbbe1014317d7a283d"
},
{
"file": "test/jassub.test.js",
"sha256": "ae93edfed7a7593ee9cfc53a63da043154c717bc8094ff3561757af1b77b9d08"
},
{
"file": "refactor/scripts/jassub-contract.mjs",
"sha256": "728f8eeb464b57a6983f00039b334be0714ed3dd710bf20a7e64f4219bf892a1"
},
{
"file": "refactor/scripts/jassub-contract.test.mjs",
"sha256": "e7ba3bc112331f0334f5c99047e9bf761ef8e91a382ca9775720aa2be5c034d4"
},
{
"file": "refactor/scripts/jassub-font-metadata.py",
"sha256": "dfb70c69c2464db49b3c7f1f387721428b4f30d6e5d0a228b849283fbef8dbb4"
},
{
"file": "package.json",
"sha256": "49fd72466907785af0cb5375e704095a9dd4e3489fe2accba7001ac8635d0efc"
}
],
"limits": "No production implementation/type/worker/WASM/font changes or browser render acceptance. Wrapper format equivalence, worker/default-font exact bytes and valid but different WASM are distinguished. Font names and fsType do not prove acquisition or redistribution rights. Task 01 and VENDOR-04/05 remain open; unsupported assumptions are not promoted into a completed migration."
}
+76
View File
@@ -0,0 +1,76 @@
# JASSUB 历史契约与来源检查点
PKG-JASSUB-01 仍为 doing。本记录冻结实现事实,不将尚未确认的 WASM/字体来源或设备
验证标成完成。输入见 [发布清单](jassub-release.json)、[上游比较源](jassub-vendor.json)
和 [字体内嵌元数据](jassub-font-metadata.json)。
## 来源与分发
实际 npm 仅有 1.0.0 / 1.1.0 两个已发布版本(本次 registry 查询);分别为
2026-01-03 / 2026-03-12 发布。两个 tarball 都固定 SHA-512、SHA-256 和全部六成员,
共有 README、manifest、main/legacy/ESM、类型声明,没有 worker/WASM/font 负载。
对应 registry gitHead 的核心版本为 5.3.1-beta.1 / 5.3.1,只是源码关联,不是支持矩阵证据。
工作区文本固定在 d44e81ce220d0d4475bf4f0f0c2e02ea5b09402a 的九份 Git 输入;本地
worker、WASM、font、ASS、MP4 清点为实际字节哈希,不做文本换行归一化。
1.0.0 CommonJS main/legacy 是带 default 的对象;1.1.0 是直接函数,未带 default。
两版声明均为 default export。两版真实 ESM 都只有 default,导入和创建工厂不启动 worker。
冻结源码的 CJS/IIFE 编译结果是测试用源码入口,不冒充旧发布 UMD;六份真实 UMD 另测。
## 工厂和实例
- `artplayerPluginJassub(option)` 只返回 registrar;注册同步构建 JASSUB 并返回
`{ name: 'artplayerPluginJassub', instance }`,不等待 worker ready,不返回 Promise。
- wrapper 调用 `new JASSUB({ video: art.video, ...option })`,option.video 可以覆盖宿主视频。
工厂保留原 option 引用,注册前改 option 可观察;fonts/availableFonts 等传递引用不复制。
- 注册设置 `_canvasParent.style.zIndex = 20`,在 art 的 destroy 事件调用 instance.destroy()。
没有额外封装、重试、切源跟随或私有实例副本。result.instance 暴露真实 vendor 实例。
- 工厂省略参数在当前/历史 JS 中有效,因为 object spread 忽略 undefined;声明却必填
JassubOption,且 workerUrl/wasmUrl/modernWasmUrl 必填。vendor 提供 worker/wasm/font 默认值。
- 实际 resize(width, height, top, left, force)、setVideo(video)、destroy() 为同步方法;
声明误把 resize 第一参数写成 force、其余次序向后移动,并把三方法都写成 Promise<void>。
不得通过迁移源码直接把错误类型转成实现,也不得静默删除已有字段或开放扩展索引。
- Option/instance 各保留 `[key: string]: any`;它们可能被消费者用于未列出的 vendor 能力。
`setTrack`、`setTrackByUrl`、`freeTrack` 等实际方法由 vendor 提供,类型范围在 04 审查。
## 资源与渲染边界
插件不改写资源 URL。workerUrl 进入 Worker 构造;wasmUrl/modernWasmUrl 由 vendor 的 SIMD
能力检测选择后发给 worker。默认 worker 为 jassub-worker.js,默认 WASM 为
jassub-worker.wasm,默认 availableFonts 指向 ./default.woff2。默认值最终如何相对宿主/
worker URL 解析、请求失败和字体回退仍须真实 worker/browser 验证,不能由本基线推断。
demo 显式使用 `/assets/jassub/` 的 MP4、ASS、worker/WASM 和字体,并设置 timeOffset=-0.041。
wrapper 创建字幕容器,vendor 管理 canvas、视频事件与 worker 消息。`sendMessage` 等待
私有 loaded Promise;本基线使用受控 ready 消息验证同步方法与消息内容,未执行 WASM。
销毁会终止 worker 并移除容器,但重复销毁、ready 前销毁、直接 instance.destroy 与
art.destroy 叠加、构造失败清理、custom canvas 等边界仍归 02/03;不要宣称生命周期已修复。
## 第三方来源结论
上游 [JASSUB](https://github.com/ThaUnknown/jassub) 是来源线索,当前 main 已变化,不能用
最新文档替代历史 API。固定比较源为实际 npm jassub@1.8.8 tarball:
- 本地 jassub.es.js 与其 dist/jassub.es.js 的差异仅为 eslint-disable 和格式;已用规范化
编译结果相同及逐行 diff 核对。此结论不表示知道原始取得该文件的操作或 revision。
- package/docs 两份 worker JS 与 1.8.8 dist/jassub-worker.js 字节一致。
- docs 默认 Liberation Sans WOFF2 与 1.8.8 默认字体字节一致。
- package/docs 两套 WASM 彼此字节一致,且基线和上游文件均通过 WebAssembly.validate;
但不匹配 1.8.8。差异涉及 global/code/data 等 section,不只是自定义元数据。额外
1.8.6、1.8.5 和 2.0.10 比较未找到匹配,不把近似版本写成精确来源。
- 1.8.8 LICENSE 和 dist/COPYRIGHT 的完整原始成员哈希已冻结,可从校验后的 archive 读取。
它们不能自动代表尚未匹配的本地 WASM 的完整子组件图与对应来源;VENDOR-04 保持 open。
- 12 个字体的 name 表和 OS/2 fsType 已提取。含 Liberation Sans、Averia、Lato、CHAWP 的
开放许可线索,也含 Arial、Garamond、Franklin Gothic、Slate Pro 等不同授权文字,以及
缺少完整许可字段的字体。内嵌文字不等于取得或再分发凭证,VENDOR-05 保持 open。
字体检查只在缓存安装 fonttools 4.60.1、brotli 1.1.0,以 bundled Python 3.12 执行
`refactor/scripts/jassub-font-metadata.py`;没有修改生产依赖和 yarn.lock。重跑时将这两个
固定版本安装到 refactor/.cache/font-inspector,并通过 PYTHONPATH 指向该目录。
## 已覆盖与下一步
48 项包含七份实现的 42 个受控行为和六项发布/vendor/资源/字体/真实 ESM 检查。
所有输入均校验实际 tarball 或 Git 哈希。Worker/DOM/SIMD 为受控对象,不能计为真实
ASS 绘制、WASM 初始化、字体外观、视频时钟/seek/倍率同步或完整浏览器验收。
下一步继续 WASM 构建及字体授权/通知来源核对;02 再补异常/资源与实际渲染失败基线。
@@ -0,0 +1,529 @@
{
"schemaVersion": 1,
"task": "PKG-JASSUB-01",
"tools": {
"fonttools": "4.60.1",
"brotli": "1.1.0"
},
"scope": "Read-only embedded OpenType names and OS/2 fsType. These are source clues, not proof of original acquisition or redistribution authorization.",
"fonts": [
{
"file": "docs/assets/jassub/default.woff2",
"bytes": 145972,
"sha256": "886929903707c5bb28b07cd2eed69921b3d5ef5c49c73a0dd1e187ebf6546a4c",
"names": {
"0": [
"Digitized data copyright (c) 2010 Google Corporation. \nCopyright (c) 2012 Red Hat, Inc."
],
"1": [
"Liberation Sans"
],
"2": [
"Regular"
],
"4": [
"Liberation Sans"
],
"5": [
"Version 2.00.5"
],
"6": [
"LiberationSans"
],
"8": [
"Ascender Corporation"
],
"9": [
"Steve Matteson"
],
"11": [
"http://www.ascendercorp.com/"
],
"13": [
"Licensed under the SIL Open Font License, Version 1.1"
],
"14": [
"http://scripts.sil.org/OFL"
]
},
"fsType": 0
},
{
"file": "docs/assets/jassub/fonts/allison-script.regular.otf",
"bytes": 107896,
"sha256": "97cd66bb6f89bdd32af2a9592f439536c85aa7553516514e2623bb1e81c65bd6",
"names": {
"0": [
"Copyright (c) 2019 by Emil Bertell. All rights reserved."
],
"1": [
"Allison Script"
],
"2": [
"Regular"
],
"4": [
"Allison Script Regular",
"AllisonScript-Regular"
],
"5": [
"Version 1.000"
],
"6": [
"AllisonScript-Regular"
],
"8": [
"Emil Bertell"
],
"9": [
"Emil Bertell"
],
"11": [
"http://fenotype.com"
]
},
"fsType": 0
},
{
"file": "docs/assets/jassub/fonts/architext.regular.ttf",
"bytes": 30568,
"sha256": "a6b8e33ce190ee9c871590b982cff37e137b303bb73dcab55ef3ff7154ba143a",
"names": {
"0": [
"\u00a9 Grant Marshall www.marshallarts.co.za "
],
"1": [
"Architext"
],
"2": [
"Regular"
],
"4": [
"Architext"
],
"5": [
"1.0 03/07/21"
],
"6": [
"Architext"
]
},
"fsType": 0
},
{
"file": "docs/assets/jassub/fonts/arial.ttf",
"bytes": 1036584,
"sha256": "c9b76220a5be42ead4733611e417cd65c5fd8aeaa33eb56576ac378a37d130a1",
"names": {
"0": [
"\u00a9 2017 The Monotype Corporation. All Rights Reserved. \r\n\r\nHebrew OpenType Layout logic copyright \u00a9 2003 & 2007, Ralph Hancock & John Hudson. This layout logic for Biblical Hebrew is open source software under the MIT License; see embedded license description for details.",
"\u00a9 2017 The Monotype Corporation. All Rights Reserved. \r\rHebrew OpenType Layout logic copyright \u00a9 2003 & 2007, Ralph Hancock & John Hudson. This layout logic for Biblical Hebrew is open source software under the MIT License; see embedded license description for details."
],
"1": [
"Arial"
],
"2": [
"Arrunta",
"Navadno",
"Normaali",
"Normal",
"Normale",
"Normalny",
"Norm\u00e1l",
"Norm\u00e1lne",
"Regular",
"Standaard",
"Standard",
"normal",
"oby\u010dejn\u00e9",
"th\u01b0\u01a1\u0300ng",
"\u039a\u03b1\u03bd\u03bf\u03bd\u03b9\u03ba\u03ac",
"\u041e\u0431\u044b\u0447\u043d\u044b\u0439"
],
"4": [
"Arial"
],
"5": [
"Version 7.00"
],
"6": [
"ArialMT"
],
"8": [
"The Monotype Corporation"
],
"9": [
"Monotype Type Drawing Office - Robin Nicholas, Patricia Saunders 1982"
],
"13": [
"Microsoft supplied font. You may use this font to create, display, and print content as permitted by the license terms or terms of use, of the Microsoft product, service, or content in which this font was included. You may only (i) embed this font in content as permitted by the embedding restrictions included in this font; and (ii) temporarily download this font to a printer or other output device to help print content. Any other use is prohibited.\r\n\r\nThe following license, based on the MIT license (http://en.wikipedia.org/wiki/MIT_License), applies to the OpenType Layout logic for Biblical Hebrew \u201cLayout Logic\u201d as jointly developed by Ralph Hancock and John Hudson. \r\n\r\nPermission is hereby granted, free of charge, to any person obtaining a copy of the OpenType Layout logic for Biblical Hebrew and associated documentation files (the \u201cLayout Logic Software\u201d), to deal in the Layout Logic Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Layout Logic Software, and to permit persons to whom the Layout Logic Software is furnished to do so, subject to the following conditions:\r\n\r\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Layout Logic Software.\r\n\r\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.",
"Microsoft supplied font. You may use this font to create, display, and print content as permitted by the license terms or terms of use, of the Microsoft product, service, or content in which this font was included. You may only (i) embed this font in content as permitted by the embedding restrictions included in this font; and (ii) temporarily download this font to a printer or other output device to help print content. Any other use is prohibited.\r\rThe following license, based on the MIT license (http://en.wikipedia.org/wiki/MIT_License), applies to the OpenType Layout logic for Biblical Hebrew \u201cLayout Logic\u201d as jointly developed by Ralph Hancock and John Hudson. \r\rPermission is hereby granted, free of charge, to any person obtaining a copy of the OpenType Layout logic for Biblical Hebrew and associated documentation files (the \u201cLayout Logic Software\u201d), to deal in the Layout Logic Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Layout Logic Software, and to permit persons to whom the Layout Logic Software is furnished to do so, subject to the following conditions:\r\rThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Layout Logic Software.\r\rTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE."
]
},
"fsType": 8
},
{
"file": "docs/assets/jassub/fonts/Averia Sans Libre Light.ttf",
"bytes": 106684,
"sha256": "df4ca526f9a941afda1f9c5a275695beb066a531f5b008c1e28ddc2c5f6e4390",
"names": {
"0": [
"Copyright (c) 2011, Dan Sayers (i@iotic.com), with Reserved Font Name 'Averia' and 'Averia Libre'."
],
"1": [
"Averia Sans Libre Light"
],
"2": [
"Regular"
],
"4": [
"Averia Sans Libre Light"
],
"5": [
"Version 1.002"
],
"6": [
"AveriaSansLibre-Light"
],
"13": [
"This Font Software is licensed under the SIL Open Font License, Version 1.1. This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL"
],
"14": [
"http://scripts.sil.org/OFL"
]
},
"fsType": 0
},
{
"file": "docs/assets/jassub/fonts/Averia Serif Simple Light.ttf",
"bytes": 110612,
"sha256": "fb6398238298a7010920e1c216f7b29bc920477bc810f8bcc677ae4e6f411b4b",
"names": {
"0": [
"Copyright (c) 2011, Dan Sayers (i@iotic.com), with Reserved Font Name 'Averia' and 'Averia Libre'."
],
"1": [
"Averia Serif Simple Light"
],
"2": [
"Regular"
],
"4": [
"Averia Serif Simple Light"
],
"5": [
"Version 1.002"
],
"6": [
"AveriaSerifSimple-Light"
],
"13": [
"This Font Software is licensed under the SIL Open Font License, Version 1.1. This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL"
],
"14": [
"http://scripts.sil.org/OFL"
]
},
"fsType": 0
},
{
"file": "docs/assets/jassub/fonts/chawp.otf",
"bytes": 122620,
"sha256": "9107241585a4328ce1438dfeabbfb1a8d0cd513dab6902be9a1a5774eab607c6",
"names": {
"0": [
"Copyright (c) 2013 by Ancient Wisdom Productions, Inc.. All rights reserved."
],
"1": [
"CHAWP"
],
"2": [
"Regular"
],
"4": [
"CHAWP"
],
"5": [
"Version 1.000"
],
"6": [
"CHAWP"
],
"8": [
"Tyler Finck"
],
"9": [
"Tyler Finck"
],
"11": [
"http://www.awpny.com"
],
"13": [
"OFL"
],
"14": [
"http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL"
]
},
"fsType": 4
},
{
"file": "docs/assets/jassub/fonts/default.woff2",
"bytes": 145972,
"sha256": "886929903707c5bb28b07cd2eed69921b3d5ef5c49c73a0dd1e187ebf6546a4c",
"names": {
"0": [
"Digitized data copyright (c) 2010 Google Corporation. \nCopyright (c) 2012 Red Hat, Inc."
],
"1": [
"Liberation Sans"
],
"2": [
"Regular"
],
"4": [
"Liberation Sans"
],
"5": [
"Version 2.00.5"
],
"6": [
"LiberationSans"
],
"8": [
"Ascender Corporation"
],
"9": [
"Steve Matteson"
],
"11": [
"http://www.ascendercorp.com/"
],
"13": [
"Licensed under the SIL Open Font License, Version 1.1"
],
"14": [
"http://scripts.sil.org/OFL"
]
},
"fsType": 0
},
{
"file": "docs/assets/jassub/fonts/FRABK.TTF",
"bytes": 152700,
"sha256": "9ad3d0e5ef31c4a9a98cb0e169e4e625286aa34c712add3e001c0100138730d4",
"names": {
"0": [
" ITC Franklin Gothic is a trademark of The International Typeface Corporation which may be registered in certain jurisdictions. Portions copyright Microsoft Corporation. All rights reserved."
],
"1": [
"Franklin Gothic Book"
],
"2": [
"Arrunta",
"Navadno",
"Normaali",
"Normal",
"Normale",
"Normalny",
"Norm\u00e1l",
"Norm\u00e1lne",
"Regular",
"Standaard",
"Standard",
"normal",
"oby\u010dejn\u00e9",
"\u039a\u03b1\u03bd\u03bf\u03bd\u03b9\u03ba\u03ac",
"\u041e\u0431\u044b\u0447\u043d\u044b\u0439"
],
"4": [
"Franklin Gothic Book"
],
"5": [
"Version 2.01"
],
"6": [
"FranklinGothic-Book"
],
"8": [
"International Typeface Corporation"
],
"9": [
"Victor Caruso"
],
"11": [
"http://www.itcfonts.com"
],
"13": [
"Please contact the vendor to learn more about license restrictions."
],
"14": [
"http://www.itcfonts.com/itc/licensing.html"
]
},
"fsType": 8
},
{
"file": "docs/assets/jassub/fonts/Gramond.ttf",
"bytes": 173484,
"sha256": "072859788bc577d35df2e852225c52cc5670339a4859d86b5edb96b1724a2177",
"names": {
"0": [
"Digitized data copyright Monotype Typography, Ltd 1991-1995. All rights reserved. Monotype Garamond\u00ae is a trademark of Monotype Typography, Ltd which may be registered in certain jurisdictions."
],
"1": [
"Garamond"
],
"2": [
"Bold",
"Fet",
"Fett",
"F\u00e9lk\u00f6v\u00e9r",
"Gras",
"Grassetto",
"Halvfet",
"Kal\u0131n",
"Krepko",
"Lihavoitu",
"Lodia",
"Negreta",
"Negrita",
"Negrito",
"Pogrubiony",
"Vet",
"fed",
"tu\u010dn\u00e9",
"\u0388\u03bd\u03c4\u03bf\u03bd\u03b1",
"\u041f\u043e\u043b\u0443\u0436\u0438\u0440\u043d\u044b\u0439"
],
"4": [
"Garamond Bold",
"Garamond Fet",
"Garamond Fett",
"Garamond F\u00e9lk\u00f6v\u00e9r",
"Garamond Gras",
"Garamond Grassetto",
"Garamond Halvfet",
"Garamond Kal\u0131n",
"Garamond Krepko",
"Garamond Lihavoitu",
"Garamond Lodia",
"Garamond Negreta",
"Garamond Negrita",
"Garamond Negrito",
"Garamond Pogrubiony",
"Garamond Vet",
"Garamond fed",
"Garamond tu\u010dn\u00e9",
"Garamond \u0388\u03bd\u03c4\u03bf\u03bd\u03b1",
"Garamond \u041f\u043e\u043b\u0443\u0436\u0438\u0440\u043d\u044b\u0439"
],
"5": [
"Version 2.30"
],
"6": [
"Garamond-Bold"
],
"8": [
"Monotype Typography, Inc."
],
"9": [
"Claude Garamond"
],
"11": [
"http://www.monotype.com/html/mtname/ms_welcome.html"
],
"13": [
"NOTIFICATION OF LICENSE AGREEMENT\r\n\r\nThis typeface is the property of Monotype Typography and its use by you is covered under the terms of a license agreement. You have obtained this typeface software either directly from Monotype or together with software distributed by one of Monotype\u2019s licensees.\r\n\r\nThis software is a valuable asset of Monotype. Unless you have entered into a specific license agreement granting you additional rights, your use of this software is limited to your workstation for your own publishing use. You may not copy or distribute this software.\r\n\r\nIf you have any question concerning your rights you should review the license agreement you received with the software or contact Monotype for a copy of the license agreement.\r\n\r\nMonotype can be contacted at:\r\n\r\nUSA 847-718-0400 UK 44(0)1737 765959\r\n\r\nFor license terms and usage rights, please visit our web site at www.monotype.com/html/type/license.html\r\n \r\nLizenzbedingungen und Nutzungsrechte finden Sie auf unserer Webseite www.monotype.com/html/type/license.html\r\n\r\nPour plus d'informations concernant les droits d'utilisation et les questions contractuelles, veuillez consultez notre site www.monotype.com/html/type/license.html\r\n\r\nPara obtener informaci\u00f3n acerca de los t\u00e9rminos de licencia y los derechos de uso, visite nuestro sitio en el Web en www.monotype.com/html/type/license.html\r\n\r\nPer le condizioni contrattuali ed i diritti d'uso, visitate il nostro sito web all'indirizzo www.monotype.com/html/type/license.html\r\n"
],
"14": [
"http://www.monotype.com/html/type/license.html"
]
},
"fsType": 8
},
{
"file": "docs/assets/jassub/fonts/Lato-Regular.ttf",
"bytes": 657212,
"sha256": "6f6940be0835c3ddec9199e5fc42be4cbc61ebcfd58c623fdf719366253f1780",
"names": {
"0": [
"Copyright (c) 2011-2015 by tyPoland Lukasz Dziedzic (http://www.typoland.com/) with Reserved Font Name \"Lato\". Licensed under the SIL Open Font License, Version 1.1 (http://scripts.sil.org/OFL). "
],
"1": [
"Lato"
],
"2": [
"Regular"
],
"4": [
"Lato Regular"
],
"5": [
"Version 2.015; 2015-08-06; http://www.latofonts.com/"
],
"6": [
"Lato-Regular"
],
"8": [
"tyPoland Lukasz Dziedzic"
],
"9": [
"Lukasz Dziedzic with Adam Twardoch and Botio Nikoltchev"
],
"11": [
"http://www.typoland.com/"
],
"13": [
"Copyright (c) 2011-2015 by tyPoland Lukasz Dziedzic (http://www.typoland.com/) with Reserved Font Name \"Lato\". Licensed under the SIL Open Font License, Version 1.1 (http://scripts.sil.org/OFL). "
],
"14": [
"http://scripts.sil.org/OFL"
]
},
"fsType": 0
},
{
"file": "docs/assets/jassub/fonts/SlatePro-Medium.otf",
"bytes": 80944,
"sha256": "56aa0fc2878bf782c10e5bba6dc45de1982a572d14ba9e10cd9d5a4414b6171e",
"names": {
"0": [
"Copyright 2006 - 2007 Monotype Imaging Inc. All rights reserved."
],
"1": [
"Slate Pro",
"Slate Pro Medium"
],
"2": [
"Medium",
"Regular"
],
"4": [
"Slate Pro Medium",
"SlatePro-Medium"
],
"5": [
"Version 1.000"
],
"6": [
"SlatePro-Medium"
],
"9": [
"Rod McDonald"
],
"11": [
"http://www.monotypeimaging.com"
],
"13": [
"\r\nNOTIFICATION OF LICENSE AGREEMENT \r\n\r\nThis typeface is the property of Monotype Imaging Inc. and its use by you is covered under the terms of a license agreement. You have obtained this typeface software either directly from Monotype Imaging or together with software distributed by one of the licencees of Monotype Imaging. \r\n\r\nThis software is a valuable asset of Monotype Imaging. Unless you have entered into a specific license agreement granting you additional rights, your use of this software is limited to use on up to five (5) workstation for your own publishing use. You may not copy or distribute this software. \r\n\r\nIf you have any questions concerning your rights you should review the license agreement you received with the software or contact Monotype Imaging for a copy of the license agreement. \r\n\r\nGeneral information:\r\nwww.fonts.com\r\n\r\nFor license terms and usage rights, please visit our web site at:\r\nwww.monotypeimaging.com\r\n\r\nLizenzbedingungen und Nutzungsrechte finden Sie auf unserer Webseite:\r\nwww.monotypeimaging.com\r\n\r\nPour plus d'informations concernant les droits d'utilisation et les questions contractuelles, veuillez consultez notre site:\r\nwww.monotypeimaging.com\r\n\r\nPara obtener informaci\u0097n acerca de los t\u008erminos de licencia y los derechos de uso, visite nuestro sitio en el Web en:\r\nwww.monotypeimaging.com\r\n\r\nPer le condizioni contrattuali ed i diritti d'uso, visitate il nostro sito web all'indirizzo:\r\nwww.monotypeimaging.com",
"\r\nNOTIFICATION OF LICENSE AGREEMENT \r\n\r\nThis typeface is the property of Monotype Imaging Inc. and its use by you is covered under the terms of a license agreement. You have obtained this typeface software either directly from Monotype Imaging or together with software distributed by one of the licencees of Monotype Imaging. \r\n\r\nThis software is a valuable asset of Monotype Imaging. Unless you have entered into a specific license agreement granting you additional rights, your use of this software is limited to use on up to five (5) workstation for your own publishing use. You may not copy or distribute this software. \r\n\r\nIf you have any questions concerning your rights you should review the license agreement you received with the software or contact Monotype Imaging for a copy of the license agreement. \r\n\r\nGeneral information:\r\nwww.fonts.com\r\n\r\nFor license terms and usage rights, please visit our web site at:\r\nwww.monotypeimaging.com\r\n\r\nLizenzbedingungen und Nutzungsrechte finden Sie auf unserer Webseite:\r\nwww.monotypeimaging.com\r\n\r\nPour plus d'informations concernant les droits d'utilisation et les questions contractuelles, veuillez consultez notre site:\r\nwww.monotypeimaging.com\r\n\r\nPara obtener informaci\u00f3n acerca de los t\u00e9rminos de licencia y los derechos de uso, visite nuestro sitio en el Web en:\r\nwww.monotypeimaging.com\r\n\r\nPer le condizioni contrattuali ed i diritti d'uso, visitate il nostro sito web all'indirizzo:\r\nwww.monotypeimaging.com"
],
"14": [
"http://www.monotypeimaging.com"
]
},
"fsType": 4
}
]
}
+247
View File
@@ -0,0 +1,247 @@
{
"schemaVersion": 1,
"registry": "https://registry.npmjs.org/artplayer-plugin-jassub",
"capturedAt": "2026-09-13T04:17:17.507Z",
"sourceCommit": "d44e81ce220d0d4475bf4f0f0c2e02ea5b09402a",
"sourceNormalization": "Text Git blobs normalized to LF; asset bytes hashed unchanged.",
"source": {
"packages/artplayer-plugin-jassub/package.json": "fdbc6dd1441eb9bebc5bbec1a95a2105256febf56bb1160ca672646feb132be1",
"packages/artplayer-plugin-jassub/src/index.js": "697c2109b34e23bebb76c118a92ee216ae2e23af84bcb351a2138835b1fbd3dc",
"packages/artplayer-plugin-jassub/src/jassub.es.js": "b973508ade00b5b9cea2f299d49f4943003372729be7350b6938e44fddb32038",
"packages/artplayer-plugin-jassub/types/artplayer-plugin-jassub.d.ts": "b591ab9895eef714e5bf3db17c805a2c5278c3244f6bbd614c7c02c397a0d450",
"packages/artplayer-plugin-jassub/README.md": "20bc5783470c0bc5c9afbb0e067f6d2f49f03d4a7f7dd1c974d047adda478a27",
"packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.js": "271d5284e5246fbd04575526510b3e381e5e60d414c030acecce92fcf2e9b10a",
"packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.legacy.js": "0726c96bf0df2aab2662ac8973bb7676a0ca7f8e4cb806aa44cb3ec9de296e64",
"packages/artplayer-plugin-jassub/dist/artplayer-plugin-jassub.mjs": "31e4be88838ddd786f1f2180d2662792ac3b2bcce00b7ccac977b59b9d659716",
"docs/assets/example/jassub.js": "4c93c554aa0a65ac19c1386bb0cfd9df6545f95b8a6f65541a0db8c072975f6d"
},
"assets": [
{
"file": "packages/artplayer-plugin-jassub/worker/jassub-worker-modern.wasm",
"bytes": 2037191,
"sha256": "8a8b37463713d1f2ddbc1fbb8a35889d9565e5a6670851758b46b2216d8e513c"
},
{
"file": "packages/artplayer-plugin-jassub/worker/jassub-worker.js",
"bytes": 31069,
"sha256": "0fb9a83f96fc39426e733a94f3e7fe4e37099324c08328450ba032b653e85707"
},
{
"file": "packages/artplayer-plugin-jassub/worker/jassub-worker.wasm",
"bytes": 1969100,
"sha256": "73880d99ba9260ac39fc4476491cf254ca784c76f3af2fb03f3f9be8065ad3c0"
},
{
"file": "docs/assets/jassub/default.woff2",
"bytes": 145972,
"sha256": "886929903707c5bb28b07cd2eed69921b3d5ef5c49c73a0dd1e187ebf6546a4c"
},
{
"file": "docs/assets/jassub/FGOBD.ass",
"bytes": 11241131,
"sha256": "8f49fb7e72229d3eb491f0eff29db9a2d8312671bc8f1c4701ec2164e562a057"
},
{
"file": "docs/assets/jassub/FGOBD.mp4",
"bytes": 26122892,
"sha256": "fa39d2623338e3f8a447eda7f259cdb70673634f1294d8b77a2c9972defb207b"
},
{
"file": "docs/assets/jassub/fonts/allison-script.regular.otf",
"bytes": 107896,
"sha256": "97cd66bb6f89bdd32af2a9592f439536c85aa7553516514e2623bb1e81c65bd6"
},
{
"file": "docs/assets/jassub/fonts/architext.regular.ttf",
"bytes": 30568,
"sha256": "a6b8e33ce190ee9c871590b982cff37e137b303bb73dcab55ef3ff7154ba143a"
},
{
"file": "docs/assets/jassub/fonts/arial.ttf",
"bytes": 1036584,
"sha256": "c9b76220a5be42ead4733611e417cd65c5fd8aeaa33eb56576ac378a37d130a1"
},
{
"file": "docs/assets/jassub/fonts/Averia Sans Libre Light.ttf",
"bytes": 106684,
"sha256": "df4ca526f9a941afda1f9c5a275695beb066a531f5b008c1e28ddc2c5f6e4390"
},
{
"file": "docs/assets/jassub/fonts/Averia Serif Simple Light.ttf",
"bytes": 110612,
"sha256": "fb6398238298a7010920e1c216f7b29bc920477bc810f8bcc677ae4e6f411b4b"
},
{
"file": "docs/assets/jassub/fonts/chawp.otf",
"bytes": 122620,
"sha256": "9107241585a4328ce1438dfeabbfb1a8d0cd513dab6902be9a1a5774eab607c6"
},
{
"file": "docs/assets/jassub/fonts/default.woff2",
"bytes": 145972,
"sha256": "886929903707c5bb28b07cd2eed69921b3d5ef5c49c73a0dd1e187ebf6546a4c"
},
{
"file": "docs/assets/jassub/fonts/FRABK.TTF",
"bytes": 152700,
"sha256": "9ad3d0e5ef31c4a9a98cb0e169e4e625286aa34c712add3e001c0100138730d4"
},
{
"file": "docs/assets/jassub/fonts/Gramond.ttf",
"bytes": 173484,
"sha256": "072859788bc577d35df2e852225c52cc5670339a4859d86b5edb96b1724a2177"
},
{
"file": "docs/assets/jassub/fonts/Lato-Regular.ttf",
"bytes": 657212,
"sha256": "6f6940be0835c3ddec9199e5fc42be4cbc61ebcfd58c623fdf719366253f1780"
},
{
"file": "docs/assets/jassub/fonts/SlatePro-Medium.otf",
"bytes": 80944,
"sha256": "56aa0fc2878bf782c10e5bba6dc45de1982a572d14ba9e10cd9d5a4414b6171e"
},
{
"file": "docs/assets/jassub/jassub-worker-modern.wasm",
"bytes": 2037191,
"sha256": "8a8b37463713d1f2ddbc1fbb8a35889d9565e5a6670851758b46b2216d8e513c"
},
{
"file": "docs/assets/jassub/jassub-worker.js",
"bytes": 31069,
"sha256": "0fb9a83f96fc39426e733a94f3e7fe4e37099324c08328450ba032b653e85707"
},
{
"file": "docs/assets/jassub/jassub-worker.wasm",
"bytes": 1969100,
"sha256": "73880d99ba9260ac39fc4476491cf254ca784c76f3af2fb03f3f9be8065ad3c0"
}
],
"release": {
"name": "artplayer-plugin-jassub",
"version": "1.1.0",
"published": "2026-03-12T14:19:56.051Z",
"tarball": "https://registry.npmjs.org/artplayer-plugin-jassub/-/artplayer-plugin-jassub-1.1.0.tgz",
"integrity": "sha512-vQwEtZMmkwr5utbxfUAeE/gRccl2nfcz+SYP2Subn/L8cVIFdMXWMgicm7ZkPVtAoBbCav7p0yP4pwXkCKMzAg==",
"sha256": "00713b4eee4b90e7dc13d1f2c88bc785f9b62f3903b00be6f7bec738fbb78c57",
"registryGitHead": "daf133b22630b4a0eecfa3336bbddab0e9119d96",
"manifest": {
"name": "artplayer-plugin-jassub",
"version": "1.1.0",
"description": "jassub plugin for ArtPlayer",
"author": "Harvey Zhao <laozhaochaguan@gmail.com>",
"license": "MIT",
"homepage": "https://artplayer.org",
"repository": {
"type": "git",
"url": "git+https://github.com/zhw2590582/ArtPlayer.git"
},
"bugs": {
"url": "https://github.com/zhw2590582/ArtPlayer/issues"
},
"keywords": [
"html5",
"video",
"player"
],
"exports": {
".": {
"types": "./types/artplayer-plugin-jassub.d.ts",
"import": "./dist/artplayer-plugin-jassub.mjs",
"require": "./dist/artplayer-plugin-jassub.js"
},
"./legacy": {
"types": "./types/artplayer-plugin-jassub.d.ts",
"import": "./dist/artplayer-plugin-jassub.legacy.js",
"require": "./dist/artplayer-plugin-jassub.legacy.js"
}
},
"main": "dist/artplayer-plugin-jassub.js",
"module": "./dist/artplayer-plugin-jassub.mjs",
"types": "types/artplayer-plugin-jassub.d.ts",
"legacy": "dist/artplayer-plugin-jassub.legacy.js",
"browserslist": "last 1 Chrome version"
},
"files": {
"package/README.md": "20bc5783470c0bc5c9afbb0e067f6d2f49f03d4a7f7dd1c974d047adda478a27",
"package/dist/artplayer-plugin-jassub.js": "271d5284e5246fbd04575526510b3e381e5e60d414c030acecce92fcf2e9b10a",
"package/dist/artplayer-plugin-jassub.legacy.js": "0726c96bf0df2aab2662ac8973bb7676a0ca7f8e4cb806aa44cb3ec9de296e64",
"package/dist/artplayer-plugin-jassub.mjs": "31e4be88838ddd786f1f2180d2662792ac3b2bcce00b7ccac977b59b9d659716",
"package/package.json": "fdbc6dd1441eb9bebc5bbec1a95a2105256febf56bb1160ca672646feb132be1",
"package/types/artplayer-plugin-jassub.d.ts": "b591ab9895eef714e5bf3db17c805a2c5278c3244f6bbd614c7c02c397a0d450"
},
"missingEntrypoints": {},
"historicalCore": {
"commit": "daf133b22630b4a0eecfa3336bbddab0e9119d96",
"file": "packages/artplayer/package.json",
"version": "5.3.1",
"sha256LF": "862f3697876fe915dd0ada178da766ce823aae7563ed30b3e5b11b811202929c",
"scope": "Source-associated core version only, not verified supported core range."
}
},
"previous": [
{
"name": "artplayer-plugin-jassub",
"version": "1.0.0",
"published": "2026-01-03T11:09:32.550Z",
"tarball": "https://registry.npmjs.org/artplayer-plugin-jassub/-/artplayer-plugin-jassub-1.0.0.tgz",
"integrity": "sha512-v8O9qXVF728YfQUCtvuSW16U954mDTiYO2QgjBdNSWOZe0o4e/7lN1mrv938lKB//efBCSdmJWjjkspF3TBWhw==",
"sha256": "3b46d3ea149af65150cdc42f9ca5eee5fef2893a87bb9ee108050e73849811dc",
"registryGitHead": "b69d020c5a5d06e093c63f456ad7d0c7777b0b03",
"manifest": {
"name": "artplayer-plugin-jassub",
"version": "1.0.0",
"description": "jassub plugin for ArtPlayer",
"author": "Harvey Zack <laozhaochaguan@gmail.com>",
"license": "MIT",
"homepage": "https://artplayer.org",
"repository": {
"type": "git",
"url": "git+https://github.com/zhw2590582/ArtPlayer.git"
},
"bugs": {
"url": "https://github.com/zhw2590582/ArtPlayer/issues"
},
"keywords": [
"html5",
"video",
"player"
],
"exports": {
".": {
"types": "./types/artplayer-plugin-jassub.d.ts",
"import": "./dist/artplayer-plugin-jassub.mjs",
"require": "./dist/artplayer-plugin-jassub.js"
},
"./legacy": {
"types": "./types/artplayer-plugin-jassub.d.ts",
"import": "./dist/artplayer-plugin-jassub.legacy.js",
"require": "./dist/artplayer-plugin-jassub.legacy.js"
}
},
"main": "dist/artplayer-plugin-jassub.js",
"module": "./dist/artplayer-plugin-jassub.mjs",
"types": "types/artplayer-plugin-jassub.d.ts",
"legacy": "dist/artplayer-plugin-jassub.legacy.js",
"browserslist": "last 1 Chrome version"
},
"files": {
"package/README.md": "13bd3f7a1249e99a51f5883727d2be984f52fa08fa17f34e482fe3b29542d079",
"package/dist/artplayer-plugin-jassub.js": "5284245ef50b909d9a5f4982e724b86e58357576b98d3ee573afd95320819975",
"package/dist/artplayer-plugin-jassub.legacy.js": "d2bfa0f38910b3fc450fbee7237a22a3cc377bb8bff7c2ad38c548cc6c912245",
"package/dist/artplayer-plugin-jassub.mjs": "d79a1006a91160264310915011dd288b90e5ad13a70b2d29d6248de09430bd35",
"package/package.json": "443d0b77bcdbe914bc8e29402ea409ad54ad721fe2b9d94435ef1d51a7c1bc62",
"package/types/artplayer-plugin-jassub.d.ts": "b591ab9895eef714e5bf3db17c805a2c5278c3244f6bbd614c7c02c397a0d450"
},
"missingEntrypoints": {},
"historicalCore": {
"commit": "b69d020c5a5d06e093c63f456ad7d0c7777b0b03",
"file": "packages/artplayer/package.json",
"version": "5.3.1-beta.1",
"sha256LF": "e1a0a390ec10cd8c1c12006ac6515414ae98a964300dd3e9c288377def948497",
"scope": "Source-associated core version only, not verified supported core range."
}
}
],
"scope": "Both actual published releases, frozen workspace text and local worker/WASM/font/demo asset bytes. Registry Git head is a source clue, not proof of a supported core range or upstream vendor identity."
}
+23
View File
@@ -0,0 +1,23 @@
{
"name": "jassub",
"version": "1.8.8",
"tarball": "https://registry.npmjs.org/jassub/-/jassub-1.8.8.tgz",
"integrity": "sha512-Vtw27Z0/hN2Tm2Qs4HAR+eONwwSD5ULo/hisPvmiaW9Ya6aFCt7esvWQSZy6nvBASbRyKmpghgeioIPqXGHA0Q==",
"sha256": "92668938b5f8ca47b26a1641a6dddf649a8c3e72a27bc54c4e7da3558c38b1bf",
"files": {
"package/LICENSE": "f300758600ecf59b736407f80f6dc8338a9879a062c6bcb16cc739d14814ec75",
"package/README.md": "7ffeaeac7d4b4b7eaf7c5eb6cf0b4115f5cf4624dd0890b8198c5e799ef1930a",
"package/dist/COPYRIGHT": "420f27cc7703563bb12842b10244f4a4951dc8bbcc5456050e696db96533edfb",
"package/dist/default.woff2": "886929903707c5bb28b07cd2eed69921b3d5ef5c49c73a0dd1e187ebf6546a4c",
"package/dist/jassub-worker-modern.wasm": "465401b1b406e4f010dd2494a9cee47d78a1725b8adc3f381437fd32f0c1e9c2",
"package/dist/jassub-worker.js": "0fb9a83f96fc39426e733a94f3e7fe4e37099324c08328450ba032b653e85707",
"package/dist/jassub-worker.wasm": "b6e9d3b1a6318ecfb9728c03a763b1e60796ca59d454820913deec62eebb8927",
"package/dist/jassub-worker.wasm.js": "edbffd1c7bf23152dcad837efbe9f488136e47f73e5beebfcd5aa2bddfe9834a",
"package/dist/jassub.es.js": "dd25d6534ccf4c7701477518064effcf81af27f1f32bc00aa18a9cf2ff102c62",
"package/dist/jassub.umd.js": "ec8f992cfc9b69a435f8cd0fb7a060745184c5dfc5aac68ae3807cb7532c875d",
"package/index.d.ts": "56802e69e7c689af6f78c1ecd663a64c03d8b28f52995699e4c759a25870b91b",
"package/package.json": "a0b75625530ae19154596f598a62fa0e264dcc9693821571698bcdb504f62903",
"package/src/jassub.js": "8a1aac7a02e2c1790cb76867042e1570dc891a3bfd3b8afab2380f5b3cd69d77"
},
"scope": "Comparison source for the wrapper, worker JS and default font; WASM bytes differ and exact build provenance remains unresolved."
}
@@ -0,0 +1,47 @@
# PKG-JASSUB-01 发布契约与来源检查点
开始 JASSUB 包迁移,保留原生产源码、vendor、声明和全部媒体资源。冻结两个实际 npm 包、
十二个成员、九份 Git 文本和本地 worker/WASM/font/ASS/MP4 字节清单。同步建立包内维护
地图和 [契约记录](../baselines/jassub-contract.md),任务为 doing,不标完成。
## 已发现的实际差异
工厂惰性、注册同步返回真实 instance;传入 video 可覆盖 art.video,options 在注册前
仍可修改。声明错误地要求所有三个资源路径,并将同步 resize/setVideo/destroy 声明为
Promise;resize 的参数顺序也不同。新增 JASSUB-TYPE-01 交给 04,保留公开声明。
两个版本的 CJS 分别为 object.default 和直接函数,新增 EXPORT 风险交给 04/06。
历史 ESM 都只有 default 且工厂创建不启动 worker;真实 npm 包不含 worker/WASM/fonts。
匹配上游 jassub 1.8.8:wrapper 仅格式/eslint-disable 差异,worker JS/default font 精确
字节一致。WASM 与该版本不同,且差异涉及代码与数据 section;两份本地模块均能校验。
1.8.6/1.8.5/2.0.10 的进一步比对未找到相同 WASM。完整版本和组件图仍未知,VENDOR-04
保持 open;未替换二进制、未把近似来源标成精确版本。
12 个字体读取 name 表与 OS/2 标志,保存完整元数据及字节哈希。部分包含 OFL 线索,
部分是不同授权文字或缺失许可字段;没有据此推断来源凭证,VENDOR-05 保持 open。
上游 LICENSE/COPYRIGHT 成员冻结可追溯,但本地 WASM/全部字体 notices 尚未闭环。
## 测试和工具
- `test/jassub.test.js` 对六个真实发布/冻结 UMD 及一个冻结源码实现各测六项:CJS/global
惰性工厂、同步注册/销毁、SIMD 两分支资源配置、live option/video 覆盖、实际同步方法、
省略选项默认值,共 42 项。代码运行真实 vendor JS,DOM/Worker/SIMD 是受控替身。
- 初次冻结源码的 global 用例误用了生成 CJS,报 module 未定义。已修正为单独生成
IIFE;生产源码/真实 UMD 不变,不将测试构造错误当成产品缺陷。
- 六项基线检查覆盖发布与源码完整性、旧声明差异、外置资源清点、实际 ESM、上游逐成员
校验与部分精确匹配、全部字体元数据指纹;本包 48 项通过。
- 新增 `yarn test:jassub`,root test:unit 显式加入新测试;契约 runner 自动进入 baseline。
显式 lint 通过。完整 CI 2392 项通过(2031 单元、14 工程、347 基线),严格生产 TS
仍 353 文件。证据见 [验证记录](../baselines/jassub-contract-validation.json)。
- 字体元数据用 bundled Python 3.12,在缓存隔离安装 fonttools 4.60.1、brotli 1.1.0;
`jassub-font-metadata.py` 是无网络只读检查器。安装位置/重跑方法见契约文档。
不修改生产依赖、Yarn 锁或包版本,不构建/手改 dist/docs 产物。
## 未完成项与回退
本轮没有真实 worker/WASM 渲染、字体外观或浏览器测试。WebAssembly.validate 只证明
模块可校验,不证明初始化、消息协议或 ASS 绘制成功。资源失败/重复销毁/切源/seek/
倍率/resize 组合仍待 02 及后续阶段;WASM 和字体来源/通知仍待 01。原始取得过程未知。
这是独立本地检查点,不推送、不发布。回退移除新测试/脚本/基线与维护文档,生产行为
保持原样。多字幕与 VTT 的旧 CommonJS 类型取舍未收到新答复,维持原待决状态。
+3 -2
View File
@@ -4,7 +4,7 @@
基线:`40fcda6a37d0049d42e49c1e64e70d4fd9ba5f7f`。总任务 223 项,范围 22 个包及工作区/示例。
状态:todo 88 / doing 14 / blocked 0 / done 121 / deferred 0。风险 L/M/H 表示兼容风险,不表示工期。
状态:todo 87 / doing 15 / blocked 0 / done 121 / deferred 0。风险 L/M/H 表示兼容风险,不表示工期。
前置依赖是启动条件;验收是完成条件。任务可以继续拆分,但不能复用或悄悄删除旧 ID。
@@ -228,7 +228,7 @@
| ID | 范围 / 步骤 | 前置依赖 | 交付物 | 验收条件 | 风险 | 状态 |
| --- | --- | --- | --- | --- | --- | --- |
| PKG-JASSUB-01 | artplayer-plugin-jassub<br>核对包契约与历史用法 | BASE-05 | 选项透传、result.instance、vendor 来源、worker/WASM/font 路径 | 源码/声明/README/demo/发布包差异已登记;公开形状和版本范围冻结;接续 VENDOR-04/05,核对 wrapper/worker/WASM/font 的独立来源与通知,保持资源路径和选项透传 | H | todo |
| PKG-JASSUB-01 | artplayer-plugin-jassub<br>核对包契约与历史用法 | BASE-05 | 选项透传、result.instance、vendor 来源、worker/WASM/font 路径 | 源码/声明/README/demo/发布包差异已登记;公开形状和版本范围冻结;接续 VENDOR-04/05,核对 wrapper/worker/WASM/font 的独立来源与通知,保持资源路径和选项透传 | H | doing |
| PKG-JASSUB-02 | artplayer-plugin-jassub<br>建立特有行为与错误测试 | PKG-JASSUB-01, ENG-03, ENG-05 | ASS 字体、时钟/seek/倍率/resize、加载失败和销毁 | 旧版本行为可重跑,成功/失败/切源/销毁有必要断言 | H | todo |
| PKG-JASSUB-03 | artplayer-plugin-jassub<br>整理内部职责与资源 | PKG-JASSUB-02, CORE-15, CORE-16 | 仅整理自有 adapter/销毁;保留第三方文件及来源 | 结构变化和缺陷修复分开记录;原 API/事件/资源生命周期通过 | H | todo |
| PKG-JASSUB-04 | artplayer-plugin-jassub<br>迁移自有源码和公开类型 | PKG-JASSUB-03, ENG-04, ENG-06, CORE-07 | JASSUB option/instance 的兼容类型包装,vendor JS 例外记录 | 严格类型检查、旧消费样例通过;声明路径/导出和同步异步兼容 | H | todo |
@@ -517,6 +517,7 @@
- PKG-MULTI-SUB-03: [记录](baselines/multiple-subtitles-resources.json) [记录](changes/2026-09-13-PKG-MULTI-SUB-03-resources.md)
- PKG-MULTI-SUB-04: [记录](baselines/multiple-subtitles-runtime-types.json) [记录](changes/2026-09-13-PKG-MULTI-SUB-04-runtime-types.md) [记录](baselines/multiple-subtitles-public-types.json) [记录](changes/2026-09-13-PKG-MULTI-SUB-04-public-types.md)
- PKG-MULTI-SUB-07: [记录](baselines/multiple-subtitles-timestamps.json) [记录](changes/2026-09-13-PKG-MULTI-SUB-07-timestamps.md)
- PKG-JASSUB-01: [记录](baselines/jassub-release.json) [记录](baselines/jassub-vendor.json) [记录](baselines/jassub-font-metadata.json) [记录](baselines/jassub-contract.md) [记录](baselines/jassub-contract-validation.json) [记录](changes/2026-09-13-PKG-JASSUB-01-baseline.md)
- PKG-ADS-01: [记录](baselines/ads-release.json) [记录](baselines/ads-contract.md) [记录](baselines/ads-contract-validation.json) [记录](changes/2026-09-12-PKG-ADS-01-contract.md) [记录](scripts/ads-contract.test.mjs)
- PKG-ADS-02: [记录](changes/2026-09-12-PKG-ADS-02-tests.md) [记录](ads-validation.md) [记录](baselines/ads-validation.json)
- PKG-ADS-03: [记录](changes/2026-09-12-PKG-ADS-03-lifecycle.md) [记录](ads-validation.md) [记录](baselines/ads-lifecycle-validation.json)
+16
View File
@@ -1,5 +1,21 @@
# 进度与证据
## PKG-JASSUB-01 发布与来源检查点(doing)
冻结两个真实 npm 版本、12 成员、9 份 Git 文本及本地 worker/WASM/font/ASS/MP4 指纹。
七份实现 42 项行为与六项契约检查,本包 48 项通过,主 test:unit/baseline 均已接入。
确认同步注册、真实 instance、live options/video 覆盖和同步方法;声明的必填 URL、
Promise/resize 参数顺序有已复现差异,TYPE/EXPORT 两项新风险归 04/06。
wrapper 与 npm jassub 1.8.8 仅格式差异,worker JS/default font 精确匹配;WASM 可校验
但代码/数据段不同。12 字体元数据已提取,原始来源/通知未闭环,VENDOR-04/05 保持 open。
完整 CI 2392 项通过(2031 单元、14 工程、347 基线),严格生产 TS 仍 353 文件。
没有改 JASSUB 生产源码、声明、二进制、字体或版本;没有浏览器 ASS 渲染证据。
见[契约](baselines/jassub-contract.md)、[验证](baselines/jassub-contract-validation.json)及
[检查点](changes/2026-09-13-PKG-JASSUB-01-baseline.md)。新增只读字体脚本,检查依赖仅装缓存。
223 项:121 done、15 doing、87 todo;200 项风险。01 继续来源核对,未标完成。
独立本地检查点提交,不推送、不发布。多字幕/VTT 类型取舍仍待回复。
## PKG-MULTI-SUB-04 公开类型与仓库外安装检查点(doing)
保留 root/legacy 的旧必填 subtitles、同步 LegacyResult 提取与可替换工厂;新增 runtime
+4 -2
View File
@@ -28,8 +28,8 @@
| VENDOR-01 | resolved / 源码/产物事实 | screenfull 来源、版本与许可闭环 | CORE-12 |
| VENDOR-02 | resolved / 源码/产物事实 | hint.css 来源、版本与许可闭环 | CORE-12 |
| VENDOR-03 | resolved / 已复现 | webvtt-parser 来源、版本与许可闭环 | PKG-MULTI-SUB-01 |
| VENDOR-04 | open / 待取证 | jassub-code-and-workers 来源、版本与许可闭环 | PKG-JASSUB-01 |
| VENDOR-05 | open / 待取证 | jassub-font-assets 来源、版本与许可闭环 | PKG-JASSUB-01, SITE-01 |
| VENDOR-04 | open / 源码/产物事实 | jassub-code-and-workers 来源、版本与许可闭环 | PKG-JASSUB-01 |
| VENDOR-05 | open / 源码/产物事实 | jassub-font-assets 来源、版本与许可闭环 | PKG-JASSUB-01, SITE-01 |
| VENDOR-06 | open / 待取证 | monaco-static-assets 来源、版本与许可闭环 | SITE-01, SITE-05 |
| VENDOR-07 | open / 待取证 | vconsole 来源、版本与许可闭环 | SITE-01 |
| VENDOR-08 | open / 待取证 | console-bundle 来源、版本与许可闭环 | SITE-01 |
@@ -202,3 +202,5 @@
| MULTI-SUB-HOST-01 | resolved / 已复现 | Subtitle init rejections are ignored and failed installation or URL replacement leaks or invalidates resources | PKG-MULTI-SUB-03, PKG-MULTI-SUB-05 |
| MULTI-SUB-TIMESTAMP-01 | resolved / 已复现 | Text wrappers replace numeric inline cue timestamps and serialize NaN times | PKG-MULTI-SUB-07, PKG-MULTI-SUB-05 |
| MULTI-SUB-ENTITY-01 | open / 已复现 | Vendored cue entity decoding retains semicolons after lt, gt and amp entities | PKG-MULTI-SUB-05 |
| JASSUB-TYPE-01 | open / 已复现 | JASSUB declared required URLs, Promise methods and resize parameter order differ from actual historical behavior | PKG-JASSUB-04 |
| JASSUB-EXPORT-01 | open / 已复现 | JASSUB historical CommonJS object.default changes to a direct factory in 1.1.0 | PKG-JASSUB-04, PKG-JASSUB-06 |
+49 -4
View File
@@ -535,7 +535,7 @@
{
"id": "VENDOR-04",
"title": "jassub-code-and-workers 来源、版本与许可闭环",
"confirmation": "unverified",
"confirmation": "source-observed",
"status": "open",
"owners": [
"PKG-JASSUB-01"
@@ -546,7 +546,13 @@
"packages/artplayer-plugin-jassub/worker",
"docs/assets/jassub/jassub-worker.js",
"docs/assets/jassub/jassub-worker.wasm",
"docs/assets/jassub/jassub-worker-modern.wasm"
"docs/assets/jassub/jassub-worker-modern.wasm",
"refactor/baselines/jassub-release.json",
"refactor/baselines/jassub-vendor.json",
"refactor/baselines/jassub-font-metadata.json",
"refactor/baselines/jassub-contract.md",
"refactor/baselines/jassub-contract-validation.json",
"refactor/changes/2026-09-13-PKG-JASSUB-01-baseline.md"
],
"compatibleResolution": "Keep separate from owned TS migration. Verify source/version/diff and license notices before replacement; preserve API/CSS/worker URLs and run owning package tests.",
"closureCriteria": "固定上游版本/内容差异、完整组件许可与分发 notices,兼容测试通过;仅当前上游许可证名称不足以关闭。"
@@ -554,7 +560,7 @@
{
"id": "VENDOR-05",
"title": "jassub-font-assets 来源、版本与许可闭环",
"confirmation": "unverified",
"confirmation": "source-observed",
"status": "open",
"owners": [
"PKG-JASSUB-01",
@@ -563,7 +569,13 @@
"evidence": [
"refactor/third-party.json",
"docs/assets/jassub/default.woff2",
"docs/assets/jassub/fonts"
"docs/assets/jassub/fonts",
"refactor/baselines/jassub-release.json",
"refactor/baselines/jassub-vendor.json",
"refactor/baselines/jassub-font-metadata.json",
"refactor/baselines/jassub-contract.md",
"refactor/baselines/jassub-contract-validation.json",
"refactor/changes/2026-09-13-PKG-JASSUB-01-baseline.md"
],
"compatibleResolution": "Keep separate from owned TS migration. Verify source/version/diff and license notices before replacement; preserve API/CSS/worker URLs and run owning package tests.",
"closureCriteria": "固定上游版本/内容差异、完整组件许可与分发 notices,兼容测试通过;仅当前上游许可证名称不足以关闭。"
@@ -4451,6 +4463,39 @@
],
"compatibleResolution": "Independently fix valid named-entity decoding, documenting the vendor patch and preserving provenance checks and ordinary cue behavior.",
"closureCriteria": "Nine historical implementations reproduce the defect; candidate entity/markup regressions and real subtitle display pass, with vendor adaptation and provenance documentation updated."
},
{
"id": "JASSUB-TYPE-01",
"title": "JASSUB declared required URLs, Promise methods and resize parameter order differ from actual historical behavior",
"confirmation": "reproduced",
"status": "open",
"owners": [
"PKG-JASSUB-04"
],
"evidence": [
"refactor/baselines/jassub-contract.md",
"test/jassub.test.js",
"refactor/scripts/jassub-contract.test.mjs"
],
"compatibleResolution": "Keep synchronous registration and real instance methods while separately preserving old parameter/return extraction and extension indexes. Do not implement the old inaccurate declaration as new runtime behavior.",
"closureCriteria": "Strict old/new consumers and actual installed declarations cover option defaults, instance methods, callback/return extraction, resize order and existing extension fields."
},
{
"id": "JASSUB-EXPORT-01",
"title": "JASSUB historical CommonJS object.default changes to a direct factory in 1.1.0",
"confirmation": "reproduced",
"status": "open",
"owners": [
"PKG-JASSUB-04",
"PKG-JASSUB-06"
],
"evidence": [
"refactor/baselines/jassub-contract-validation.json",
"refactor/baselines/jassub-release.json",
"test/jassub.test.js"
],
"compatibleResolution": "Preserve actual historical JS default/direct forms and validate their declared module views independently.",
"closureCriteria": "Installed CJS/ESM/global/legacy consumers and public types preserve the supported historical forms."
}
]
}
+29
View File
@@ -0,0 +1,29 @@
import assert from 'node:assert/strict'
import { execFileSync } from 'node:child_process'
import fs from 'node:fs'
import path from 'node:path'
import { archiveFiles, ensureArchive, hash, readMember, refactorDir } from './releases.mjs'
export async function verifyJassubContract() {
const baseline = JSON.parse(fs.readFileSync(path.join(refactorDir, 'baselines/jassub-release.json'), 'utf8'))
const archives = new Map()
for (const release of [baseline.release, ...baseline.previous]) {
const archive = await ensureArchive(release)
assert.deepEqual(archiveFiles(archive), Object.keys(release.files).sort())
for (const [file, expected] of Object.entries(release.files))
assert.equal(hash(readMember(archive, file)), expected, `${release.version}/${file}`)
assert.deepEqual(JSON.parse(readMember(archive, 'package/package.json')), release.manifest)
const core = release.historicalCore
const coreSource = execFileSync('git', ['show', `${core.commit}:${core.file}`], { encoding: 'utf8' }).replaceAll('\r\n', '\n')
assert.equal(hash(coreSource), core.sha256LF)
assert.equal(JSON.parse(coreSource).version, core.version)
archives.set(release.version, archive)
}
const sources = new Map()
for (const [file, expected] of Object.entries(baseline.source)) {
const source = execFileSync('git', ['show', `${baseline.sourceCommit}:${file}`], { encoding: 'utf8', maxBuffer: 16 * 1024 * 1024 }).replaceAll('\r\n', '\n')
assert.equal(hash(source), expected, file)
sources.set(file, source)
}
return { baseline, archives, sources }
}
+84
View File
@@ -0,0 +1,84 @@
import assert from 'node:assert/strict'
import { Buffer } from 'node:buffer'
import fs from 'node:fs'
// eslint-disable-next-line test/no-import-node-test -- Published and vendor provenance checks use the repository runner.
import test from 'node:test'
import { transformSync } from 'esbuild'
import { verifyJassubContract } from './jassub-contract.mjs'
import { archiveFiles, ensureArchive, hash, readMember } from './releases.mjs'
const contract = await verifyJassubContract()
const releases = [contract.baseline.release, ...contract.baseline.previous]
test('JASSUB freezes both actual releases, twelve members and nine Git text inputs', () => {
assert.deepEqual(releases.map(item => item.version), ['1.1.0', '1.0.0'])
assert.equal(releases.reduce((count, item) => count + Object.keys(item.files).length, 0), 12)
assert.equal(contract.sources.size, 9)
assert.deepEqual(releases.map(item => item.historicalCore.version), ['5.3.1', '5.3.1-beta.1'])
for (const release of releases) assert.deepEqual(release.missingEntrypoints, {})
})
test('JASSUB historical declarations require resource paths and incorrectly describe synchronous methods', () => {
for (const release of releases) {
const source = readMember(contract.archives.get(release.version), 'package/types/artplayer-plugin-jassub.d.ts').toString()
for (const key of ['workerUrl', 'wasmUrl', 'modernWasmUrl']) assert.match(source, new RegExp(`${key}: string`))
assert.match(source, /resize: \(force\?: boolean, width\?: number, height\?: number, top\?: number, left\?: number\) => Promise<void>/)
assert.match(source, /setVideo: \(video: HTMLVideoElement\) => Promise<void>/)
assert.match(source, /destroy: \(\) => Promise<void>/)
assert.equal(source.match(/\[key: string\]: any/g).length, 2)
assert.match(source, /export default artplayerPluginJassub/)
}
})
test('JASSUB published packages omit worker/WASM/font payloads while the demo uses independently hosted assets', () => {
for (const release of releases)
assert(!Object.keys(release.files).some(file => /\.(?:wasm|ttf|otf|woff2?)$|\/worker\//.test(file)))
const demo = contract.sources.get('docs/assets/example/jassub.js')
for (const resource of ['jassub-worker.js', 'jassub-worker.wasm', 'jassub-worker-modern.wasm', 'default.woff2']) assert(demo.includes(`/assets/jassub/${resource}`))
for (const asset of contract.baseline.assets) {
assert.equal(hash(fs.readFileSync(asset.file)), asset.sha256, asset.file)
assert.equal(fs.statSync(asset.file).size, asset.bytes, asset.file)
}
})
test('JASSUB actual historical ESM artifacts expose only a lazy default factory', async () => {
for (const release of releases) {
const source = readMember(contract.archives.get(release.version), 'package/dist/artplayer-plugin-jassub.mjs').toString()
const module = await import(`data:text/javascript;base64,${Buffer.from(source).toString('base64')}`)
assert.deepEqual(Object.keys(module), ['default'])
assert.equal(typeof module.default, 'function')
assert.equal(typeof module.default({ workerUrl: '/worker.js' }), 'function')
}
})
test('JASSUB 1.8.8 comparison proves wrapper/worker/default font matches without claiming different WASM builds match', async () => {
const upstream = JSON.parse(fs.readFileSync('refactor/baselines/jassub-vendor.json', 'utf8'))
const archive = await ensureArchive(upstream)
assert.deepEqual(archiveFiles(archive), Object.keys(upstream.files).sort())
for (const [file, expected] of Object.entries(upstream.files)) assert.equal(hash(readMember(archive, file)), expected)
const normalize = source => transformSync(source, { format: 'esm', target: 'es2020', legalComments: 'none' }).code
assert.equal(normalize(contract.sources.get('packages/artplayer-plugin-jassub/src/jassub.es.js')), normalize(readMember(archive, 'package/dist/jassub.es.js').toString()))
for (const file of ['packages/artplayer-plugin-jassub/worker/jassub-worker.js', 'docs/assets/jassub/jassub-worker.js'])
assert.deepEqual(fs.readFileSync(file), readMember(archive, 'package/dist/jassub-worker.js'))
assert.deepEqual(fs.readFileSync('docs/assets/jassub/default.woff2'), readMember(archive, 'package/dist/default.woff2'))
for (const name of ['jassub-worker.wasm', 'jassub-worker-modern.wasm']) {
const local = fs.readFileSync(`packages/artplayer-plugin-jassub/worker/${name}`)
const reference = readMember(archive, `package/dist/${name}`)
assert.deepEqual(local, fs.readFileSync(`docs/assets/jassub/${name}`))
assert(!local.equals(reference))
assert(WebAssembly.validate(local))
assert(WebAssembly.validate(reference))
}
})
test('JASSUB font source clues cover every actual font without promoting embedded metadata to redistribution proof', () => {
const metadata = JSON.parse(fs.readFileSync('refactor/baselines/jassub-font-metadata.json', 'utf8'))
const files = contract.baseline.assets.filter(item => /\.(?:ttf|otf|woff2?)$/i.test(item.file))
assert.equal(metadata.fonts.length, 12)
assert.deepEqual(metadata.fonts.map(item => item.file).sort(), files.map(item => item.file).sort())
for (const font of metadata.fonts) {
assert.equal(hash(fs.readFileSync(font.file)), font.sha256)
assert(font.names['1']?.length)
}
assert.match(metadata.scope, /not proof/)
assert.deepEqual(metadata.tools, { fonttools: '4.60.1', brotli: '1.1.0' })
})
+39
View File
@@ -0,0 +1,39 @@
"""Read font metadata only; embedded notices do not establish acquisition rights."""
import hashlib
import importlib.metadata
import json
from pathlib import Path
from fontTools.ttLib import TTFont
def inspect_fonts():
root = Path(__file__).resolve().parents[2]
records = []
for file in sorted((root / "docs/assets/jassub").rglob("*")):
if file.suffix.lower() not in {".ttf", ".otf", ".woff", ".woff2"}:
continue
with TTFont(file, lazy=True) as font:
names = {}
for record in font["name"].names:
if record.nameID in {0, 1, 2, 4, 5, 6, 8, 9, 11, 13, 14}:
names.setdefault(str(record.nameID), set()).add(record.toUnicode())
records.append({
"file": file.relative_to(root).as_posix(),
"bytes": file.stat().st_size,
"sha256": hashlib.sha256(file.read_bytes()).hexdigest(),
"names": {key: sorted(values) for key, values in names.items()},
"fsType": font["OS/2"].fsType if "OS/2" in font else None,
})
return {
"schemaVersion": 1,
"task": "PKG-JASSUB-01",
"tools": {name: importlib.metadata.version(name) for name in ["fonttools", "brotli"]},
"scope": "Read-only embedded OpenType names and OS/2 fsType. These are source clues, not proof of original acquisition or redistribution authorization.",
"fonts": records,
}
if __name__ == "__main__":
print(json.dumps(inspect_fonts(), ensure_ascii=True, indent=2))
+9 -2
View File
@@ -2394,11 +2394,18 @@
"dependsOn": [
"BASE-05"
],
"status": "todo",
"status": "doing",
"risk": "H",
"deliverable": "选项透传、result.instance、vendor 来源、worker/WASM/font 路径",
"acceptance": "源码/声明/README/demo/发布包差异已登记;公开形状和版本范围冻结;接续 VENDOR-04/05,核对 wrapper/worker/WASM/font 的独立来源与通知,保持资源路径和选项透传",
"evidence": []
"evidence": [
"baselines/jassub-release.json",
"baselines/jassub-vendor.json",
"baselines/jassub-font-metadata.json",
"baselines/jassub-contract.md",
"baselines/jassub-contract-validation.json",
"changes/2026-09-13-PKG-JASSUB-01-baseline.md"
]
},
{
"id": "PKG-JASSUB-02",
+5 -4
View File
@@ -354,12 +354,13 @@
"owners": [
"PKG-JASSUB-01"
],
"sourceStatus": "JASSUB example links upstream; exact wrapper/worker/WASM build version and subcomponent graph not established.",
"sourceStatus": "Wrapper matches npm jassub 1.8.8 after formatting/ESLint-header adaptation; package/docs worker JS matches exact bytes. WASM files validate but code/data differ from 1.8.8; exact build/source/component graph remains unresolved. See baselines/jassub-contract.md.",
"licenseStatus": "Current upstream wrapper LICENSE is MIT; this does not certify linked WASM libraries, fonts, or the exact local build.",
"upstreamSources": [
"https://github.com/ThaUnknown/jassub/blob/main/LICENSE"
"https://github.com/ThaUnknown/jassub/blob/main/LICENSE",
"https://registry.npmjs.org/jassub/-/jassub-1.8.8.tgz"
],
"upstreamReviewedAt": "2026-09-10",
"upstreamReviewedAt": "2026-09-13",
"updatePolicy": "Keep separate from owned TS migration. Verify source/version/diff and license notices before replacement; preserve API/CSS/worker URLs and run owning package tests.",
"fingerprints": [
{
@@ -410,7 +411,7 @@
"PKG-JASSUB-01",
"SITE-01"
],
"sourceStatus": "Mixed named font files; version/source provenance unavailable from file names alone.",
"sourceStatus": "All 12 font name tables and embedding flags extracted with hashes; default font matches npm jassub 1.8.8. Other embedded notices are source clues only; original acquisition and redistribution evidence remain unresolved. See baselines/jassub-font-metadata.json.",
"licenseStatus": "Font redistribution rights are unverified; do not infer licenses from root MIT or font names.",
"upstreamSources": [],
"upstreamReviewedAt": null,
+158
View File
@@ -0,0 +1,158 @@
import assert from 'node:assert/strict'
import fs from 'node:fs'
import process from 'node:process'
import vm from 'node:vm'
import { transform } from 'esbuild'
import { verifyJassubContract } from '../../refactor/scripts/jassub-contract.mjs'
import { readMember } from '../../refactor/scripts/releases.mjs'
import { compilePackage } from './load.js'
export async function jassubCandidate() {
return { name: 'candidate', version: 'candidate', code: process.env.ARTPLAYER_JASSUB_ARTIFACT ? fs.readFileSync(process.env.ARTPLAYER_JASSUB_ARTIFACT, 'utf8') : await compilePackage('artplayer-plugin-jassub', 'umd') }
}
export async function jassubHistorical() {
const { baseline, archives, sources } = await verifyJassubContract()
const prefix = 'packages/artplayer-plugin-jassub'
const implementations = []
for (const release of [baseline.release, ...baseline.previous]) {
for (const field of ['main', 'legacy'])
implementations.push({ name: `published-${release.version}-${field}`, version: release.version, code: readMember(archives.get(release.version), `package/${release.manifest[field].replace(/^\.\//, '')}`).toString() })
}
const vendor = sources.get(`${prefix}/src/jassub.es.js`)
const exported = vendor.match(/export\s*\{\s*(\w+) as default\s*\};?\s*$/)
assert(exported, 'Frozen vendor must have one explicit default class export')
const source = vendor.slice(0, exported.index) + sources.get(`${prefix}/src/index.js`).replace('import JASSUB from \'./jassub.es.js\'', `const JASSUB = ${exported[1]}`)
implementations.push({ name: 'frozen-workspace-source', version: 'workspace', code: (await transform(source, { format: 'cjs', target: 'es2020' })).code, scriptCode: (await transform(source, { format: 'iife', globalName: 'artplayerPluginJassub', target: 'es2020' })).code })
for (const suffix of ['js', 'legacy.js'])
implementations.push({ name: `frozen-workspace-${suffix}`, version: 'workspace', code: sources.get(`${prefix}/dist/artplayer-plugin-jassub.${suffix}`) })
return implementations
}
export function jassubEnvironment(implementation, { script = false, simd = false } = {}) {
const workers = []
const errors = []
const listeners = new Map()
class Element extends EventTarget {
constructor() {
super()
this.style = {}
this.children = []
}
appendChild(child) {
this.children.push(child)
child.parentNode = this
return child
}
removeChild(child) {
assert(this.children.includes(child))
this.children.splice(this.children.indexOf(child), 1)
child.parentNode = null
return child
}
remove() { this.parentNode?.removeChild(this) }
insertAdjacentElement(position, child) {
assert.equal(position, 'afterend')
this.parentNode.appendChild(child)
}
getBoundingClientRect() { return { x: 0, y: 0, top: 0, left: 0, width: 640, height: 360 } }
}
class Video extends Element {
constructor() {
super()
this.videoWidth = 0
this.videoHeight = 0
this.paused = true
this.currentTime = 0
this.readyState = 0
this.playbackRate = 1
}
}
class Canvas extends Element {
constructor() {
super()
this.width = 300
this.height = 150
this.context = { clearRect() { }, putImageData() { }, drawImage() { }, getImageData: () => ({ data: new Uint8ClampedArray(4) }) }
}
getContext(type) {
assert.equal(type, '2d')
return this.context
}
}
class Worker {
constructor(url) {
this.url = url
this.messages = []
this.terminated = 0
workers.push(this)
}
postMessage(message) { this.messages.push(message) }
terminate() { this.terminated++ }
}
class ImageData {
constructor(data, width, height) {
this.data = data
this.width = width
this.height = height
}
}
class ErrorEvent extends Event {
constructor(type, options) {
super(type)
this.error = options.error
}
}
const parent = new Element()
const video = parent.appendChild(new Video())
const module = { exports: {} }
const context = {
EventTarget,
Event,
CustomEvent,
ErrorEvent,
HTMLVideoElement: Video,
HTMLCanvasElement: Canvas,
ImageData,
Worker,
WebAssembly: { validate: () => simd },
document: { createElement: name => name === 'canvas' ? new Canvas() : new Element() },
console: {
log() {},
error(error) { errors.push(error) },
},
performance,
}
context.window = context
context.self = context
if (!script) {
context.module = module
context.exports = module.exports
}
vm.runInNewContext(script && implementation.scriptCode ? implementation.scriptCode : implementation.code, context, { timeout: 5000 })
const exported = script ? context.artplayerPluginJassub : module.exports
const factory = exported.default || exported
const art = { video, on(name, callback) {
if (!listeners.has(name))
listeners.set(name, [])
listeners.get(name).push(callback)
return art
} }
const emit = name => listeners.get(name)?.forEach(callback => callback())
const flush = async () => {
for (let index = 0;
index < 12;
index++)
await Promise.resolve()
}
const ready = async () => {
await flush()
workers.at(-1).onmessage({ data: { target: 'ready' } })
await flush()
}
return { factory, exported, art, workers, parent, errors, listeners, emit, ready, flush, createVideo: () => parent.appendChild(new Video()) }
}
+79
View File
@@ -0,0 +1,79 @@
import assert from 'node:assert/strict'
import process from 'node:process'
// eslint-disable-next-line test/no-import-node-test -- Frozen JASSUB consumer contracts use the repository runner.
import test from 'node:test'
import { jassubCandidate, jassubEnvironment, jassubHistorical } from './helpers/jassub.js'
const implementations = process.env.ARTPLAYER_JASSUB_CANDIDATE === '1' || process.env.ARTPLAYER_JASSUB_ARTIFACT ? [await jassubCandidate()] : await jassubHistorical()
for (const implementation of implementations) {
for (const script of [false, true]) {
test(`JASSUB ${implementation.name}: ${script ? 'global' : 'CJS'} factory is lazy and registration synchronously exposes the actual instance`, async () => {
const env = jassubEnvironment(implementation, { script })
const register = env.factory({ workerUrl: 'worker.js', subContent: '[Script Info]' })
assert.equal(env.workers.length, 0)
const result = register(env.art)
assert.deepEqual(Object.keys(result), ['name', 'instance'])
assert.equal(result.name, 'artplayerPluginJassub')
assert.equal(result.then, undefined)
assert.equal(result.instance._video, env.art.video)
assert.equal(String(result.instance._canvasParent.style.zIndex), '20')
assert.equal(env.listeners.get('destroy').length, 1)
assert.equal(env.workers[0].url, 'worker.js')
await env.ready()
assert.equal(env.workers[0].messages[0].subContent, '[Script Info]')
env.emit('destroy')
assert.equal(env.workers[0].terminated, 1)
assert.equal(env.parent.children.length, 1)
})
}
for (const simd of [false, true]) {
test(`JASSUB ${implementation.name}: resource URLs and vendor options retain selection semantics SIMD=${simd}`, async () => {
const env = jassubEnvironment(implementation, { simd })
const fonts = ['a.ttf']
const availableFonts = { test: 'test.woff2' }
const result = env.factory({ workerUrl: '/worker.js', wasmUrl: '/base.wasm', modernWasmUrl: '/simd.wasm', subUrl: '/sub.ass', fonts, availableFonts, fallbackFont: 'test', timeOffset: -0.041, targetFps: 30, libassMemoryLimit: 64 })(env.art)
await env.ready()
const init = env.workers[0].messages[0]
assert.equal(init.target, 'init')
assert.equal(init.wasmUrl, simd ? '/simd.wasm' : '/base.wasm')
assert.equal(init.fonts, fonts)
assert.equal(init.availableFonts, availableFonts)
assert.equal(init.subUrl, '/sub.ass')
assert.equal(init.fallbackFont, 'test')
assert.equal(init.targetFps, 30)
assert.equal(init.libassMemoryLimit, 64)
assert.equal(result.instance.timeOffset, -0.041)
env.emit('destroy')
})
}
test(`JASSUB ${implementation.name}: mutable options override video and historical instance methods return synchronously`, async () => {
const env = jassubEnvironment(implementation)
const option = { workerUrl: 'old.js' }
const register = env.factory(option)
option.workerUrl = 'new.js'
option.video = env.createVideo()
const result = register(env.art)
assert.equal(result.instance._video, option.video)
assert.equal(env.workers[0].url, 'new.js')
await env.ready()
assert.equal(result.instance.resize(640, 360, 4, 5, false), undefined)
assert.equal(result.instance.setVideo(option.video), undefined)
assert.equal(result.instance.setTrack('[Script Info]'), undefined)
assert.equal(result.instance.destroy(), undefined)
await env.flush()
assert.equal(env.workers[0].terminated, 1)
const resize = env.workers[0].messages.find(message => message.target === 'canvas')
assert.equal(resize.width, 640)
assert.equal(resize.height, 360)
})
test(`JASSUB ${implementation.name}: omitted options retain worker and font defaults`, async () => {
const env = jassubEnvironment(implementation)
const result = env.factory()(env.art)
assert.equal(env.workers[0].url, 'jassub-worker.js')
await env.ready()
const init = env.workers[0].messages[0]
assert.equal(init.wasmUrl, 'jassub-worker.wasm')
assert.equal(init.availableFonts['liberation sans'], './default.woff2')
result.instance.destroy()
})
}