mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-20 20:21:20 -08:00
refactor(jassub): [PKG-JASSUB-04] migrate owned TypeScript and preserve public types
This commit is contained in:
1 parent
38e7b37878
commit
5e445b1af6
33 files changed
+3636
-61
No files matched your search
@@ -2,4 +2,5 @@ node_modules
|
||||
.DS_Store
|
||||
yarn.lock
|
||||
package-lock.json
|
||||
src
|
||||
src
|
||||
tsconfig.json
|
||||
@@ -1,7 +1,7 @@
|
||||
# JASSUB maintenance
|
||||
|
||||
`src/index.js` preserves the lazy factory and delegates registration to
|
||||
`src/registration.js`. The registration module constructs the actual vendor object
|
||||
`src/index.ts` preserves the lazy factory and delegates registration to
|
||||
`src/registration.ts`. The registration module constructs the actual vendor object
|
||||
with `{ video: art.video, ...option }`, styles only a vendor-created canvas parent,
|
||||
binds host cleanup and synchronously returns `{ name: 'artplayerPluginJassub', instance }`.
|
||||
Options remain live until registration; a supplied video wins. This small split keeps
|
||||
@@ -27,11 +27,27 @@ messages. Keep this third-party file separate from the adapter's TypeScript migr
|
||||
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.
|
||||
`types/artplayer-plugin-jassub.d.ts` preserves the actual npm 1.0.0/1.1.0 declarations,
|
||||
including three required resource URLs, Promise-returning resize/setVideo/destroy and
|
||||
the historical force-first resize signature. Both option and instance retain their existing
|
||||
extension indexes. Do not correct this root file by narrowing fields or adding overloads:
|
||||
complete factory assignment and Parameters/ReturnType are compatibility boundaries.
|
||||
|
||||
`types/runtime-api.d.ts` separately describes the actual optional options, synchronous
|
||||
registration and methods, width/height/top/left/force resize, EventTarget events and
|
||||
Worker query/mutation data. `types/runtime.d.ts`, `.d.cts` and `.d.mts` expose it through
|
||||
the optional `/runtime` entry; it resolves to the same main/ESM JavaScript as the root.
|
||||
There is no second implementation and no new factory.default property. Root/legacy
|
||||
types remain unchanged; exact typesVersions mappings support old Node module resolution.
|
||||
See [type migration notes](types/README.md) before changing either surface.
|
||||
|
||||
`src/jassub.es.d.ts` is a private bridge for the frozen vendor JS, not a public export.
|
||||
It adds only the adapter's `_destroyed` read and `_canvasParent.style.zIndex` write to the
|
||||
accurate instance. The minimal style contract permits the historical numeric 20, which
|
||||
the native DOM setter converts to a string. The owned TS modules depend on RuntimeOption
|
||||
and RuntimeResult, while JassubHost needs only video/on/off. The implementation fixture
|
||||
checks actual Artplayer assignability. No broad any index, allowJs or ts-nocheck hides
|
||||
owned code; the isolated third-party JS remains an explicit provenance/07 exception.
|
||||
|
||||
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 instead matches
|
||||
@@ -48,6 +64,10 @@ Use the pinned Node/Yarn toolchain:
|
||||
|
||||
```sh
|
||||
yarn test:jassub
|
||||
yarn test:jassub-types
|
||||
yarn test:jassub-types-package
|
||||
yarn typecheck
|
||||
yarn build:ts artplayer-plugin-jassub
|
||||
node --test test/jassub-registration.test.js
|
||||
node refactor/scripts/jassub-provenance.test.mjs --network
|
||||
yarn build artplayer-plugin-jassub
|
||||
|
||||
@@ -11,6 +11,10 @@ jassub plugin for ArtPlayer
|
||||
See [maintenance notes](ARCHITECTURE.md) for adapter/vendor boundaries, resource paths,
|
||||
historical declaration differences and the current validation scope.
|
||||
|
||||
Existing imports keep their historical types. The optional
|
||||
[`artplayer-plugin-jassub/runtime` entry](types/README.md) provides accurate options,
|
||||
synchronous instance methods and subtitle query types using the same implementation.
|
||||
|
||||
## License
|
||||
|
||||
MIT © Harvey Zhao
|
||||
@@ -27,11 +27,31 @@
|
||||
"types": "./types/artplayer-plugin-jassub.d.ts",
|
||||
"import": "./dist/artplayer-plugin-jassub.legacy.js",
|
||||
"require": "./dist/artplayer-plugin-jassub.legacy.js"
|
||||
},
|
||||
"./runtime": {
|
||||
"import": {
|
||||
"types": "./types/runtime.d.mts",
|
||||
"default": "./dist/artplayer-plugin-jassub.mjs"
|
||||
},
|
||||
"require": {
|
||||
"types": "./types/runtime.d.cts",
|
||||
"default": "./dist/artplayer-plugin-jassub.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"
|
||||
"browserslist": "last 1 Chrome version",
|
||||
"typesVersions": {
|
||||
"*": {
|
||||
"legacy": [
|
||||
"types/artplayer-plugin-jassub.d.ts"
|
||||
],
|
||||
"runtime": [
|
||||
"types/runtime.d.ts"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
import { registerJassub } from './registration.js'
|
||||
|
||||
export default function artplayerPluginJassub(option) {
|
||||
return art => registerJassub(art, option)
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
import type { RuntimeOption } from '../types/runtime-api.js'
|
||||
import type { JassubHost } from './registration.js'
|
||||
import { registerJassub } from './registration.js'
|
||||
|
||||
export default function artplayerPluginJassub(option?: RuntimeOption) {
|
||||
return (art: JassubHost) => registerJassub(art, option)
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import type { RuntimeInstance, RuntimeOption } from '../types/runtime-api.js'
|
||||
|
||||
interface VendorInstance extends RuntimeInstance {
|
||||
_destroyed?: boolean
|
||||
// Minimal write contract: the DOM setter coerces the historical numeric 20.
|
||||
_canvasParent?: { style: { zIndex: string | number } }
|
||||
}
|
||||
|
||||
declare const JASSUB: {
|
||||
new (option: RuntimeOption): VendorInstance
|
||||
}
|
||||
export default JASSUB
|
||||
+8
-1
@@ -1,6 +1,13 @@
|
||||
import type { RuntimeOption, RuntimeResult } from '../types/runtime-api.js'
|
||||
import JASSUB from './jassub.es.js'
|
||||
|
||||
export function registerJassub(art, option) {
|
||||
export interface JassubHost {
|
||||
video: HTMLVideoElement
|
||||
on: (name: 'destroy', callback: () => void) => unknown
|
||||
off: (name: 'destroy', callback: () => void) => unknown
|
||||
}
|
||||
|
||||
export function registerJassub(art: JassubHost, option?: RuntimeOption): RuntimeResult {
|
||||
const instance = new JASSUB({ video: art.video, ...option })
|
||||
let disposed = false
|
||||
const dispose = () => {
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": { "allowJs": false },
|
||||
"include": ["src/**/*.ts", "../../refactor/fixtures/implementation/jassub.ts"]
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
# JASSUB type compatibility
|
||||
|
||||
The root and `/legacy` declarations retain the complete npm 1.0.0 and 1.1.0 type
|
||||
shape, including known mistakes. Existing TypeScript consumers do not need to
|
||||
change imports as part of this migration. Both releases used the same declarations.
|
||||
The generated online-editor global also preserves this historical surface.
|
||||
|
||||
For accurate types, explicitly opt into the additive entry:
|
||||
|
||||
```ts
|
||||
import jassub from 'artplayer-plugin-jassub/runtime'
|
||||
|
||||
const register = jassub({
|
||||
workerUrl: '/assets/jassub-worker.js',
|
||||
wasmUrl: '/assets/jassub-worker.wasm',
|
||||
modernWasmUrl: '/assets/jassub-worker-modern.wasm',
|
||||
subUrl: '/subtitles.ass',
|
||||
})
|
||||
// Add register to the existing Artplayer plugins option.
|
||||
// When called with an Artplayer, it synchronously returns { name, instance }.
|
||||
```
|
||||
|
||||
`/runtime` uses the same JavaScript file as the root entry. It does not change
|
||||
defaults, wrap instances, download resources differently or introduce a second
|
||||
implementation. URLs are optional because the vendor has defaults; this does not
|
||||
mean its default relative URLs will exist on your site. Continue hosting compatible
|
||||
worker, WASM and font files and supplying the paths your deployment needs.
|
||||
|
||||
| Area | Historical root types | Accurate `/runtime` types and existing JavaScript |
|
||||
| --- | --- | --- |
|
||||
| Factory options | Required, with three required URLs | Optional options; optional resource URLs |
|
||||
| Instance resize | force, width, height, top, left | width, height, top, left, force |
|
||||
| resize/setVideo/destroy | Promise<void> | Synchronous; no-argument calls return void |
|
||||
| sendMessage | Unchecked extension | Promise<void>, resolves after posting, not after Worker completion |
|
||||
| Events/styles | Unchecked extension | Typed callbacks and partial mutation objects |
|
||||
| ASS event Style | Unchecked extension | Numeric libass style index |
|
||||
| ASS Start/Duration | Unchecked extension | Milliseconds; setCurrentTime uses seconds |
|
||||
| Unknown fields/methods | Existing any indexes | Named supported fields; unknown members rejected |
|
||||
|
||||
Switching to `/runtime` intentionally changes type inference. For example,
|
||||
`instance.resize(640, 360, 0, 0, true)` describes the actual call order.
|
||||
`await instance.destroy()` remains legal JavaScript, but `.then()` on that result
|
||||
never worked at runtime. Resource teardown completion is not represented by a Promise.
|
||||
The callback error channel is `Error | ErrorEvent | null`; an error may omit the data.
|
||||
The currently frozen vendor has a request timeout/error bug that throws before user
|
||||
callbacks run. PKG-JASSUB-07 tracks the fix; typing that channel does not fix or guarantee
|
||||
callback delivery. Query outputs do not contain the upstream npm declaration's `_index`.
|
||||
|
||||
The accurate instance extends EventTarget and preserves its normal listener APIs.
|
||||
`destroy(error)` returns the original Error, or converts a nonempty string to Error;
|
||||
an empty string is returned unchanged. Repeated direct destruction and construction/
|
||||
video clock failures remain separate vendor lifecycle work, documented in ARCHITECTURE.md.
|
||||
|
||||
NodeNext ESM retains the root declaration's historical CommonJS namespace behavior.
|
||||
If existing code uses the root namespace's `.default` to satisfy that declaration,
|
||||
keep that form or opt into `/runtime`, whose conditional `.d.mts` is directly callable.
|
||||
CommonJS accurate types use `import jassub = require('artplayer-plugin-jassub/runtime')`.
|
||||
Do not invent `jassub.default`: the current JavaScript factory has no self alias.
|
||||
Older TypeScript resolves `/legacy` and `/runtime` through exact typesVersions mappings.
|
||||
Existing direct declaration paths are retained; no wildcard remaps unrelated paths.
|
||||
|
||||
Maintain `runtime-api.d.ts` against the frozen wrapper and worker behavior, not a new
|
||||
upstream version. Keep CJS/ESM entry aliases synchronized. Run `yarn test:jassub-types`,
|
||||
`yarn test:jassub-types-package`, `yarn test:jassub`, and `yarn typecheck` after changes.
|
||||
The package runner installs actual historical archives and the candidate outside the
|
||||
workspace, checks strict positive/negative consumers, and verifies artifact identity.
|
||||
This is type/distribution evidence, not browser playback or final release acceptance.
|
||||
@@ -0,0 +1,155 @@
|
||||
// Core exposes a default constructor in Node10/ESM and export= in NodeNext CJS.
|
||||
// Extract the same instance without requiring esModuleInterop in consumers.
|
||||
type CoreModule = typeof import('artplayer')
|
||||
type Artplayer = CoreModule extends { default: { prototype: infer Instance } }
|
||||
? Instance
|
||||
: CoreModule extends { prototype: infer Instance } ? Instance : never
|
||||
|
||||
export type FontSource = string | Uint8Array
|
||||
|
||||
/** Options are read when the registrar runs; the host supplies video by default. */
|
||||
export interface RuntimeOption {
|
||||
video?: HTMLVideoElement | null
|
||||
canvas?: HTMLCanvasElement
|
||||
blendMode?: 'js' | 'wasm'
|
||||
asyncRender?: boolean
|
||||
offscreenRender?: boolean
|
||||
onDemandRender?: boolean
|
||||
targetFps?: number
|
||||
timeOffset?: number
|
||||
debug?: boolean
|
||||
prescaleFactor?: number
|
||||
prescaleHeightLimit?: number
|
||||
maxRenderHeight?: number
|
||||
dropAllAnimations?: boolean
|
||||
dropAllBlur?: boolean
|
||||
workerUrl?: string
|
||||
wasmUrl?: string
|
||||
legacyWasmUrl?: string
|
||||
modernWasmUrl?: string
|
||||
subUrl?: string
|
||||
subContent?: string
|
||||
fonts?: FontSource[]
|
||||
availableFonts?: Record<string, FontSource>
|
||||
fallbackFont?: string
|
||||
useLocalFonts?: boolean
|
||||
libassMemoryLimit?: number
|
||||
libassGlyphLimit?: number
|
||||
}
|
||||
|
||||
/** Fields actually serialized by the frozen worker's getEvents response. */
|
||||
export interface AssEvent {
|
||||
/** Milliseconds; distinct from setCurrentTime's seconds. */
|
||||
Start: number
|
||||
Duration: number
|
||||
/** Numeric libass style index, not the ASS text format's style name. */
|
||||
Style: number
|
||||
Name: string
|
||||
MarginL: number
|
||||
MarginR: number
|
||||
MarginV: number
|
||||
Effect: string
|
||||
Text: string
|
||||
ReadOrder: number
|
||||
Layer: number
|
||||
}
|
||||
|
||||
/** Fields actually serialized by the frozen worker's getStyles response. */
|
||||
export interface AssStyle {
|
||||
Name: string
|
||||
FontName: string
|
||||
FontSize: number
|
||||
PrimaryColour: number
|
||||
SecondaryColour: number
|
||||
OutlineColour: number
|
||||
BackColour: number
|
||||
Bold: number
|
||||
Italic: number
|
||||
Underline: number
|
||||
StrikeOut: number
|
||||
ScaleX: number
|
||||
ScaleY: number
|
||||
Spacing: number
|
||||
Angle: number
|
||||
BorderStyle: number
|
||||
Outline: number
|
||||
Shadow: number
|
||||
Alignment: number
|
||||
MarginL: number
|
||||
MarginR: number
|
||||
MarginV: number
|
||||
Encoding: number
|
||||
treat_fontname_as_pattern: number
|
||||
Blur: number
|
||||
Justify: number
|
||||
}
|
||||
|
||||
/** Worker mutation handlers assign supplied keys; unspecified fields are not sent. */
|
||||
export type AssEventInput = Partial<AssEvent>
|
||||
export type AssStyleInput = Partial<AssStyle>
|
||||
|
||||
/** Timeout errors and native Worker error events are separate channels. */
|
||||
export type WorkerRequestError = Error | ErrorEvent
|
||||
/**
|
||||
* Success supplies null plus an array. Error payloads are absent.
|
||||
* The frozen vendor currently throws before notifying this callback on request
|
||||
* errors/timeouts; PKG-JASSUB-07 owns that defect. These types do not guarantee
|
||||
* callback delivery or claim that the error path has been repaired.
|
||||
*/
|
||||
export type EventsCallback = (error: WorkerRequestError | null, events?: AssEvent[]) => void
|
||||
export type StylesCallback = (error: WorkerRequestError | null, styles?: AssStyle[]) => void
|
||||
|
||||
export interface RuntimeEventMap {
|
||||
ready: CustomEvent<null>
|
||||
error: ErrorEvent
|
||||
}
|
||||
|
||||
/** The actual vendor EventTarget instance, rather than an adapter copy. */
|
||||
export interface RuntimeInstance extends EventTarget {
|
||||
timeOffset: number
|
||||
debug: boolean
|
||||
prescaleFactor: number
|
||||
prescaleHeightLimit: number
|
||||
maxRenderHeight: number
|
||||
/** Present when the selected rendering path uses demand/busy state. */
|
||||
busy?: boolean
|
||||
/** These two fields were explicitly exposed by npm jassub 1.8.8. */
|
||||
_canvas: HTMLCanvasElement
|
||||
_ctx: CanvasRenderingContext2D | false | null
|
||||
|
||||
resize: (width?: number, height?: number, top?: number, left?: number, force?: boolean) => void
|
||||
setVideo: (video: HTMLVideoElement) => void
|
||||
runBenchmark: () => void
|
||||
setTrackByUrl: (url: string) => void
|
||||
setTrack: (content: string) => void
|
||||
freeTrack: () => void
|
||||
setIsPaused: (isPaused: boolean) => void
|
||||
setRate: (rate: number) => void
|
||||
/** Current time is measured in seconds. */
|
||||
setCurrentTime: (isPaused?: boolean, currentTime?: number, rate?: number) => void
|
||||
createEvent: (event: AssEventInput) => void
|
||||
setEvent: (event: AssEventInput, index: number) => void
|
||||
removeEvent: (index: number) => void
|
||||
getEvents: (callback: EventsCallback) => void
|
||||
createStyle: (style: AssStyleInput) => void
|
||||
setStyle: (style: AssStyleInput, index: number) => void
|
||||
removeStyle: (index: number) => void
|
||||
getStyles: (callback: StylesCallback) => void
|
||||
styleOverride: (style: AssStyleInput) => void
|
||||
disableStyleOverride: () => void
|
||||
setDefaultFont: (font: string) => void
|
||||
addFont: (font: FontSource) => void
|
||||
/** Resolves after posting the message; it is not a Worker-operation acknowledgement. */
|
||||
sendMessage: (target: string, data?: Record<string, unknown> | null, transferable?: Transferable[]) => Promise<void>
|
||||
destroy: (() => void) & ((error: Error) => Error) & ((error: string) => Error | '') & ((error: Error | string | undefined) => Error | '' | undefined)
|
||||
|
||||
addEventListener: (<Name extends keyof RuntimeEventMap>(type: Name, listener: (this: RuntimeInstance, event: RuntimeEventMap[Name]) => void, options?: boolean | AddEventListenerOptions) => void) & ((type: string, listener: EventListenerOrEventListenerObject | null, options?: boolean | AddEventListenerOptions) => void)
|
||||
removeEventListener: (<Name extends keyof RuntimeEventMap>(type: Name, listener: (this: RuntimeInstance, event: RuntimeEventMap[Name]) => void, options?: boolean | EventListenerOptions) => void) & ((type: string, listener: EventListenerOrEventListenerObject | null, options?: boolean | EventListenerOptions) => void)
|
||||
}
|
||||
|
||||
export interface RuntimeResult {
|
||||
name: 'artplayerPluginJassub'
|
||||
instance: RuntimeInstance
|
||||
}
|
||||
|
||||
export type RuntimeFactory = (option?: RuntimeOption) => (art: Artplayer) => RuntimeResult
|
||||
@@ -0,0 +1,20 @@
|
||||
import type { RuntimeFactory } from './runtime-api.js'
|
||||
|
||||
declare const artplayerPluginJassub: RuntimeFactory
|
||||
// eslint-disable-next-line ts/no-redeclare -- Ambient merge exposes types on the CommonJS factory.
|
||||
declare namespace artplayerPluginJassub {
|
||||
type FontSource = import('./runtime-api.js').FontSource
|
||||
type RuntimeOption = import('./runtime-api.js').RuntimeOption
|
||||
type AssEvent = import('./runtime-api.js').AssEvent
|
||||
type AssStyle = import('./runtime-api.js').AssStyle
|
||||
type AssEventInput = import('./runtime-api.js').AssEventInput
|
||||
type AssStyleInput = import('./runtime-api.js').AssStyleInput
|
||||
type WorkerRequestError = import('./runtime-api.js').WorkerRequestError
|
||||
type EventsCallback = import('./runtime-api.js').EventsCallback
|
||||
type StylesCallback = import('./runtime-api.js').StylesCallback
|
||||
type RuntimeEventMap = import('./runtime-api.js').RuntimeEventMap
|
||||
type RuntimeInstance = import('./runtime-api.js').RuntimeInstance
|
||||
type RuntimeResult = import('./runtime-api.js').RuntimeResult
|
||||
type RuntimeFactory = import('./runtime-api.js').RuntimeFactory
|
||||
}
|
||||
export = artplayerPluginJassub
|
||||
@@ -0,0 +1,5 @@
|
||||
import type { RuntimeFactory } from './runtime-api.js'
|
||||
|
||||
declare const artplayerPluginJassub: RuntimeFactory
|
||||
export default artplayerPluginJassub
|
||||
export type { AssEvent, AssEventInput, AssStyle, AssStyleInput, EventsCallback, FontSource, RuntimeEventMap, RuntimeFactory, RuntimeInstance, RuntimeOption, RuntimeResult, StylesCallback, WorkerRequestError } from './runtime-api.js'
|
||||
@@ -0,0 +1,20 @@
|
||||
import type { RuntimeFactory } from './runtime-api.js'
|
||||
|
||||
declare const artplayerPluginJassub: RuntimeFactory
|
||||
// eslint-disable-next-line ts/no-redeclare -- Ambient merge exposes types on the CommonJS factory.
|
||||
declare namespace artplayerPluginJassub {
|
||||
type FontSource = import('./runtime-api.js').FontSource
|
||||
type RuntimeOption = import('./runtime-api.js').RuntimeOption
|
||||
type AssEvent = import('./runtime-api.js').AssEvent
|
||||
type AssStyle = import('./runtime-api.js').AssStyle
|
||||
type AssEventInput = import('./runtime-api.js').AssEventInput
|
||||
type AssStyleInput = import('./runtime-api.js').AssStyleInput
|
||||
type WorkerRequestError = import('./runtime-api.js').WorkerRequestError
|
||||
type EventsCallback = import('./runtime-api.js').EventsCallback
|
||||
type StylesCallback = import('./runtime-api.js').StylesCallback
|
||||
type RuntimeEventMap = import('./runtime-api.js').RuntimeEventMap
|
||||
type RuntimeInstance = import('./runtime-api.js').RuntimeInstance
|
||||
type RuntimeResult = import('./runtime-api.js').RuntimeResult
|
||||
type RuntimeFactory = import('./runtime-api.js').RuntimeFactory
|
||||
}
|
||||
export = artplayerPluginJassub
|
||||
Reference in new issue
Block a user