mirror of
https://github.com/zoriya/v10.git
synced 2026-08-16 02:45:09 +00:00
feat(site): API reference pages for media elements (#1342)
This commit is contained in:
Vendored
+18
-1
@@ -6,6 +6,15 @@
|
||||
* AudioEvents extends a subset (no text track events).
|
||||
*/
|
||||
|
||||
// Mirrors the real MediaStreamTypes const object. Exercises default-value
|
||||
// resolution of property-access expressions (e.g. MediaStreamTypes.UNKNOWN)
|
||||
// through an import to a `... as const` object literal.
|
||||
export const MediaStreamTypes = {
|
||||
ON_DEMAND: 'on-demand',
|
||||
LIVE: 'live',
|
||||
UNKNOWN: 'unknown',
|
||||
} as const;
|
||||
|
||||
export interface EventLike<Detail = void> {
|
||||
readonly type: string;
|
||||
readonly timeStamp: number;
|
||||
@@ -62,6 +71,13 @@ export interface TextTrackListEvents {
|
||||
trackmodechange: EventLike;
|
||||
}
|
||||
|
||||
// Video.js-specific event promoted into the typed contract — mirrors the real
|
||||
// MediaStreamTypeEvents. The host that fires it also carries an `@fires` tag, so
|
||||
// it appears in BOTH the native list and the described element-specific list.
|
||||
export interface MediaStreamTypeEvents {
|
||||
streamtypechange: EventLike;
|
||||
}
|
||||
|
||||
export interface VideoEvents
|
||||
extends MediaPlaybackEvents,
|
||||
MediaPauseEvents,
|
||||
@@ -71,7 +87,8 @@ export interface VideoEvents
|
||||
MediaPlaybackRateEvents,
|
||||
MediaBufferEvents,
|
||||
MediaErrorEvents,
|
||||
TextTrackListEvents {}
|
||||
TextTrackListEvents,
|
||||
MediaStreamTypeEvents {}
|
||||
|
||||
export interface AudioEvents
|
||||
extends MediaPlaybackEvents,
|
||||
|
||||
Vendored
+9
@@ -0,0 +1,9 @@
|
||||
/**
|
||||
* Mock audio host base — mirrors the real audio-host.ts.
|
||||
*
|
||||
* Adds no methods of its own: audio elements get only the shared media-host
|
||||
* methods.
|
||||
*/
|
||||
import { HTMLMediaElementHost } from './media-host';
|
||||
|
||||
export class HTMLAudioElementHost extends HTMLMediaElementHost {}
|
||||
+24
-1
@@ -3,10 +3,23 @@
|
||||
*
|
||||
* Exercises: multiple getter/setter pairs with JSDoc descriptions,
|
||||
* readonly properties, boolean type, overlap with native attributes
|
||||
* (src, preload) that should be deduplicated by the builder.
|
||||
* (src, preload) that should be deduplicated by the builder, and default
|
||||
* values declared in a co-located `*DefaultProps` export (mirrors
|
||||
* hlsMediaDefaultProps) including a const-object member reference.
|
||||
*/
|
||||
import { MediaStreamTypes } from '../../../core/media/types';
|
||||
import { HTMLVideoElementHost } from '../simple';
|
||||
|
||||
export const complexMediaDefaultProps = {
|
||||
src: '',
|
||||
type: undefined,
|
||||
preferPlayback: 'mse',
|
||||
config: {},
|
||||
debug: false,
|
||||
preload: 'metadata',
|
||||
streamType: MediaStreamTypes.UNKNOWN,
|
||||
};
|
||||
|
||||
export class ComplexHost extends HTMLVideoElementHost {
|
||||
#src: string = '';
|
||||
#type: string | undefined;
|
||||
@@ -15,6 +28,7 @@ export class ComplexHost extends HTMLVideoElementHost {
|
||||
#debug: boolean = false;
|
||||
#preload: string = 'metadata';
|
||||
#engine: object | null = null;
|
||||
#streamType: string = complexMediaDefaultProps.streamType;
|
||||
|
||||
get src(): string {
|
||||
return this.#src;
|
||||
@@ -71,4 +85,13 @@ export class ComplexHost extends HTMLVideoElementHost {
|
||||
get engine(): object | null {
|
||||
return this.#engine;
|
||||
}
|
||||
|
||||
/** Current stream type. */
|
||||
get streamType(): string {
|
||||
return this.#streamType;
|
||||
}
|
||||
|
||||
set streamType(value: string) {
|
||||
this.#streamType = value;
|
||||
}
|
||||
}
|
||||
|
||||
+32
-2
@@ -3,13 +3,25 @@
|
||||
*
|
||||
* Exercises: host inheritance. The builder must walk the extends chain
|
||||
* to extract properties from both this class and its parent (ComplexHost).
|
||||
* Child properties override parent properties of the same name.
|
||||
* Child properties override parent properties of the same name. Defaults
|
||||
* spread the parent's defaultProps (mirrors muxMediaDefaultProps) — the
|
||||
* builder must resolve the spread through the import. `customDomain`
|
||||
* deliberately has no default.
|
||||
*/
|
||||
import { ComplexHost } from '../complex';
|
||||
import { ComplexHost, complexMediaDefaultProps } from '../complex';
|
||||
|
||||
export const extendingMediaDefaultProps = {
|
||||
...complexMediaDefaultProps,
|
||||
playbackId: '',
|
||||
tokens: { drm: '' },
|
||||
maxResolution: 1080,
|
||||
};
|
||||
|
||||
export class ExtendingHost extends ComplexHost {
|
||||
#playbackId: string = '';
|
||||
#customDomain: string = '';
|
||||
#tokens: Record<string, string> = { ...extendingMediaDefaultProps.tokens };
|
||||
#maxResolution: number = extendingMediaDefaultProps.maxResolution;
|
||||
|
||||
/** The playback ID for the video. */
|
||||
get playbackId(): string {
|
||||
@@ -29,6 +41,24 @@ export class ExtendingHost extends ComplexHost {
|
||||
this.#customDomain = value;
|
||||
}
|
||||
|
||||
/** Playback tokens keyed by purpose. */
|
||||
get tokens(): Record<string, string> {
|
||||
return this.#tokens;
|
||||
}
|
||||
|
||||
set tokens(value: Record<string, string>) {
|
||||
this.#tokens = value;
|
||||
}
|
||||
|
||||
/** Maximum rendition height to request. */
|
||||
get maxResolution(): number {
|
||||
return this.#maxResolution;
|
||||
}
|
||||
|
||||
set maxResolution(value: number) {
|
||||
this.#maxResolution = value;
|
||||
}
|
||||
|
||||
/** Overrides parent debug — adds network logging. */
|
||||
get debug(): boolean {
|
||||
return super.debug;
|
||||
|
||||
Vendored
+33
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Mock shared media host base — mirrors the real media-host.ts.
|
||||
*
|
||||
* Exercises method extraction: the builder collects public instance methods
|
||||
* from this class (per media type) for the reference's `methods` field.
|
||||
* Lifecycle methods (attach/detach/destroy) and accessors are excluded.
|
||||
*/
|
||||
export class HTMLMediaElementHost {
|
||||
// Lifecycle methods — excluded from `methods`.
|
||||
attach(_target: EventTarget): void {}
|
||||
detach(): void {}
|
||||
destroy(): void {}
|
||||
|
||||
// Internal — excluded by the `_` prefix.
|
||||
_forward(): void {}
|
||||
|
||||
// Accessor — excluded (getters/setters are properties, not methods).
|
||||
get src(): string {
|
||||
return '';
|
||||
}
|
||||
|
||||
play(): Promise<void> {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
pause(): void {}
|
||||
|
||||
load(): void {}
|
||||
|
||||
canPlayType(_type: string): string {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* Mock base host for the mixin chain fixture.
|
||||
*
|
||||
* Exercises: parent class providing a JSDoc-described property that the
|
||||
* mixin chain may override without re-declaring the description (tests
|
||||
* description fallback through the chain).
|
||||
*/
|
||||
import { HTMLVideoElementHost } from '../simple';
|
||||
|
||||
export class MixinBaseHost extends HTMLVideoElementHost {
|
||||
#src: string = '';
|
||||
|
||||
/** Source URL of the media. */
|
||||
get src(): string {
|
||||
return this.#src;
|
||||
}
|
||||
|
||||
set src(value: string) {
|
||||
this.#src = value;
|
||||
}
|
||||
}
|
||||
site/scripts/api-docs-builder/src/tests/fixtures/monorepo/packages/core/src/dom/media/mixin/index.ts
Vendored
+24
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* Mock mixin-chain leaf class — mirrors MuxVideoMedia / NativeHlsMedia.
|
||||
*
|
||||
* Exercises: a class extending MixinB(MixinA(BaseHost)) — a chain of two
|
||||
* mixins of different syntactic shapes. The builder must walk the
|
||||
* call-expression extends, follow each mixin to its source file, and
|
||||
* collect getters/setters from each mixin's inner class.
|
||||
*/
|
||||
import { MixinBaseHost } from './base-host';
|
||||
import { MixinAFooMixin } from './mixin-a';
|
||||
import { MixinBVolumeMixin } from './mixin-b';
|
||||
|
||||
export class MixinHost extends MixinBVolumeMixin(MixinAFooMixin(MixinBaseHost)) {
|
||||
#bar: number = 0;
|
||||
|
||||
/** Leaf class own property. */
|
||||
get bar(): number {
|
||||
return this.#bar;
|
||||
}
|
||||
|
||||
set bar(value: number) {
|
||||
this.#bar = value;
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Mock mixin (Shape A — function declaration).
|
||||
*
|
||||
* Exercises:
|
||||
* - Function-declaration mixin walking
|
||||
* - Property addition with JSDoc
|
||||
* - A dispatched-but-untagged event (foochange) is NOT documented — only
|
||||
* `@fires`-tagged events surface in the element-specific list.
|
||||
* - A `@fires` event that is ALSO part of the native contract (streamtypechange,
|
||||
* in VideoEvents via MediaStreamTypeEvents) — mirrors HlsMedia. It must surface
|
||||
* in the described element-specific list even though it is a native event.
|
||||
* - Defaults declared in the mixin's own file (mirrors muxDataMediaDefaultProps)
|
||||
*/
|
||||
type Constructor<T = object> = new (...args: any[]) => T;
|
||||
|
||||
export const mixinAFooDefaultProps = {
|
||||
foo: '',
|
||||
};
|
||||
|
||||
/**
|
||||
* @fires streamtypechange - Fired when the detected stream type changes.
|
||||
*/
|
||||
export function MixinAFooMixin<Base extends Constructor>(BaseClass: Base) {
|
||||
class MixinAFoo extends BaseClass {
|
||||
#foo: string = '';
|
||||
|
||||
/** Mixin A documentation. */
|
||||
get foo(): string {
|
||||
return this.#foo;
|
||||
}
|
||||
|
||||
set foo(value: string) {
|
||||
this.#foo = value;
|
||||
(this as unknown as EventTarget).dispatchEvent(new Event('foochange'));
|
||||
}
|
||||
}
|
||||
|
||||
return MixinAFoo as unknown as Base & Constructor<{ foo: string }>;
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Mock mixin (Shape B — const arrow function).
|
||||
*
|
||||
* Exercises:
|
||||
* - Arrow-function mixin walking
|
||||
* - Override of a native HTMLMediaElement member (volume) without JSDoc → overridesNative
|
||||
* - Override of a parent property (src) without JSDoc → description fallback
|
||||
*/
|
||||
type Constructor<T = object> = new (...args: any[]) => T;
|
||||
|
||||
export const MixinBVolumeMixin = <Base extends Constructor>(superclass: Base) => {
|
||||
class MixinBVolume extends superclass {
|
||||
#volume: number = 1;
|
||||
#src: string = '';
|
||||
|
||||
// Overrides HTMLMediaElement.volume without JSDoc — exercises overridesNative.
|
||||
get volume(): number {
|
||||
return this.#volume;
|
||||
}
|
||||
|
||||
set volume(value: number) {
|
||||
this.#volume = value;
|
||||
}
|
||||
|
||||
// Overrides parent.src without JSDoc — exercises description fallback.
|
||||
get src(): string {
|
||||
return this.#src;
|
||||
}
|
||||
|
||||
set src(value: string) {
|
||||
this.#src = value;
|
||||
}
|
||||
}
|
||||
|
||||
return MixinBVolume as unknown as Base & Constructor<{ volume: number; src: string }>;
|
||||
};
|
||||
+10
-1
@@ -3,6 +3,8 @@
|
||||
*
|
||||
* Exercises: minimal host with just src (read-write) and engine (readonly).
|
||||
* No JSDoc on properties — tests that missing descriptions produce undefined.
|
||||
* `engine` has no return-type annotation — tests that the checker infers the
|
||||
* type (mirrors DashMedia's unannotated `get engine()`).
|
||||
*/
|
||||
|
||||
// Stub — the builder walks the prototype chain and stops here.
|
||||
@@ -12,6 +14,13 @@ export class HTMLVideoElementHost {
|
||||
destroy(): void {}
|
||||
}
|
||||
|
||||
// Stub — audio counterpart, also a prototype-chain stop.
|
||||
export class HTMLAudioElementHost {
|
||||
attach(_target: EventTarget): void {}
|
||||
detach(): void {}
|
||||
destroy(): void {}
|
||||
}
|
||||
|
||||
export class SimpleHost extends HTMLVideoElementHost {
|
||||
#src: string = '';
|
||||
#engine: object = {};
|
||||
@@ -24,7 +33,7 @@ export class SimpleHost extends HTMLVideoElementHost {
|
||||
this.#src = value;
|
||||
}
|
||||
|
||||
get engine(): object {
|
||||
get engine() {
|
||||
return this.#engine;
|
||||
}
|
||||
}
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* Mock audio-only host — mirrors SimpleHlsAudioOnlyMedia.
|
||||
*
|
||||
* Exercises: a host whose only mixin lives in a different workspace package
|
||||
* (spf), reached through that package's barrel file, composed onto the
|
||||
* audio host base.
|
||||
*/
|
||||
import { SpfAudioOnlyMediaMixin } from '../../../../../spf/src/hls';
|
||||
import { HTMLAudioElementHost } from '../simple';
|
||||
|
||||
export class SpfAudioHost extends SpfAudioOnlyMediaMixin(HTMLAudioElementHost) {}
|
||||
Vendored
+13
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Mock video host base — mirrors the real video-host.ts.
|
||||
*
|
||||
* Exercises video-specific method extraction: requestFullscreen is added on
|
||||
* top of the shared media-host methods for video elements only.
|
||||
*/
|
||||
import { HTMLMediaElementHost } from './media-host';
|
||||
|
||||
export class HTMLVideoElementHost extends HTMLMediaElementHost {
|
||||
requestFullscreen(): Promise<void> {
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* Mock mixin-chain element registration — mirrors define/media/mux-video.ts.
|
||||
*
|
||||
* Exercises: element whose host is a mixin chain (call-expression extends).
|
||||
*/
|
||||
import { MixinVideo } from '../../media/mixin-video';
|
||||
|
||||
export class MixinVideoElement extends MixinVideo {
|
||||
static readonly tagName = 'mixin-video';
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* Mock audio-only element registration — mirrors define/media/simple-hls-audio-only.ts.
|
||||
*
|
||||
* Exercises: discovery of an audio element whose host mixin lives in another
|
||||
* workspace package.
|
||||
*/
|
||||
import { SpfAudio } from '../../media/spf-audio';
|
||||
|
||||
export class SpfAudioElement extends SpfAudio {
|
||||
static readonly tagName = 'spf-audio';
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* Mock mixin-chain media element — mirrors MuxVideo / NativeHlsVideo.
|
||||
*
|
||||
* Exercises: standard composition where the host is a mixin chain.
|
||||
*/
|
||||
import { CustomMediaElement } from '../../../../core/src/dom/media/custom-media-element';
|
||||
import { MixinHost } from '../../../../core/src/dom/media/mixin';
|
||||
|
||||
// Stub — the builder parses the AST, it doesn't run the code.
|
||||
function MediaAttachMixin(base: any) {
|
||||
return base;
|
||||
}
|
||||
|
||||
export class MixinVideo extends MediaAttachMixin(CustomMediaElement('video', MixinHost)) {}
|
||||
site/scripts/api-docs-builder/src/tests/fixtures/monorepo/packages/html/src/media/spf-audio/index.ts
Vendored
+15
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* Mock audio-only media element — mirrors SimpleHlsAudioOnly.
|
||||
*
|
||||
* Exercises: audio media type ('audio' tag argument) with a cross-package
|
||||
* mixin host.
|
||||
*/
|
||||
import { CustomMediaElement } from '../../../../core/src/dom/media/custom-media-element';
|
||||
import { SpfAudioHost } from '../../../../core/src/dom/media/spf-audio';
|
||||
|
||||
// Stub — the builder parses the AST, it doesn't run the code.
|
||||
function MediaAttachMixin(base: any) {
|
||||
return base;
|
||||
}
|
||||
|
||||
export class SpfAudio extends MediaAttachMixin(CustomMediaElement('audio', SpfAudioHost)) {}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* Mock spf hls barrel — mirrors the @videojs/spf/hls subpath entry.
|
||||
*
|
||||
* The import + bare `export { … }` shape matches what tsdown emits in rolled-up
|
||||
* entry `.d.ts` files (import the implementation, re-export without a module
|
||||
* specifier). The builder must follow the import binding to the declaration.
|
||||
*/
|
||||
import { SpfAudioOnlyMediaMixin } from '../playback/engines/hls/adapter-audio-only';
|
||||
|
||||
export { spfAudioOnlyMediaDefaultProps } from '../playback/engines/hls/adapter-audio-only';
|
||||
export { SpfAudioOnlyMediaMixin };
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* Mock SPF audio-only adapter mixin — mirrors SimpleHlsAudioOnlyMediaMixin.
|
||||
*
|
||||
* Exercises:
|
||||
* - Cross-package mixin resolution (host lives in core, mixin in spf)
|
||||
* - Defaults declared in the mixin's own file (spfAudioOnlyMediaDefaultProps)
|
||||
* - `@fires`-declared events: `audiomodechange` also has a dispatch site,
|
||||
* `manifestparsed` is dispatched from a helper the builder never scans —
|
||||
* the @fires tag is its only source.
|
||||
*/
|
||||
type Constructor<T = object> = new (...args: any[]) => T;
|
||||
|
||||
export const spfAudioOnlyMediaDefaultProps = {
|
||||
src: '',
|
||||
preload: '',
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds SPF audio-only HLS playback to a host.
|
||||
*
|
||||
* @fires audiomodechange - Fired when the audio-only rendition changes.
|
||||
* @fires manifestparsed - Fired after the multivariant playlist is parsed.
|
||||
*/
|
||||
export const SpfAudioOnlyMediaMixin = <Base extends Constructor>(BaseClass: Base) => {
|
||||
class SpfAudioOnlyMedia extends BaseClass {
|
||||
#src: string = spfAudioOnlyMediaDefaultProps.src;
|
||||
#preload: string = spfAudioOnlyMediaDefaultProps.preload;
|
||||
|
||||
/** Source URL of the HLS manifest. */
|
||||
get src(): string {
|
||||
return this.#src;
|
||||
}
|
||||
|
||||
set src(value: string) {
|
||||
this.#src = value;
|
||||
(this as unknown as EventTarget).dispatchEvent(new Event('audiomodechange'));
|
||||
}
|
||||
|
||||
/** Preload hint forwarded to the internal audio element. */
|
||||
get preload(): string {
|
||||
return this.#preload;
|
||||
}
|
||||
|
||||
set preload(value: string) {
|
||||
this.#preload = value;
|
||||
}
|
||||
}
|
||||
|
||||
return SpfAudioOnlyMedia as unknown as Base & Constructor<{ src: string; preload: string }>;
|
||||
};
|
||||
Reference in New Issue
Block a user