From a94246792f3f662fca62d86ca14ab42484cb21e7 Mon Sep 17 00:00:00 2001 From: Michael Barlock Date: Thu, 4 Jan 2024 10:54:23 -0500 Subject: [PATCH 1/2] fix: improve types and allow augmentation --- src/js/component.js | 22 +++++----- src/js/player.js | 104 ++++++++++++++++++++++---------------------- src/js/plugin.js | 64 +++++++++++++++++++++++++++ src/js/video.js | 7 +-- 4 files changed, 131 insertions(+), 66 deletions(-) diff --git a/src/js/component.js b/src/js/component.js index 3d7d2d8f20..b28ef26855 100644 --- a/src/js/component.js +++ b/src/js/component.js @@ -14,6 +14,12 @@ import {toTitleCase, toLowerCase} from './utils/str.js'; import {merge} from './utils/obj.js'; import keycode from 'keycode'; +/** + * @typedef {Object} ComponentOptions + * @property {Object[]} children + * @property {string} classname + */ + /** * Base class for all UI Components. * Components are UI objects which represent both a javascript object and an element @@ -38,17 +44,9 @@ class Component { * @param { import('./player').default } player * The `Player` that this class should be attached to. * - * @param {Object} [options] + * @param {ComponentOptions} [options] * The key/value store of component options. * - * @param {Object[]} [options.children] - * An array of children objects to initialize this component with. Children objects have - * a name property that will be used if more than one component of the same type needs to be - * added. - * - * @param {string} [options.className] - * A class or space separated list of classes to add the component - * * @param {ReadyCallback} [ready] * Function that gets called when the `Component` is ready. */ @@ -1777,11 +1775,11 @@ class Component { * * @param {string} name * The name of the `Component` to register. - * - * @param {Component} ComponentToRegister + * @template {Component} C + * @param {C} ComponentToRegister * The `Component` class to register. * - * @return {Component} + * @return {C} * The `Component` that was registered. */ static registerComponent(name, ComponentToRegister) { diff --git a/src/js/player.js b/src/js/player.js index 2594041816..2852e5f71b 100644 --- a/src/js/player.js +++ b/src/js/player.js @@ -4606,6 +4606,57 @@ class Player extends Component { }); } + // The following empty getters are defined below the class. They are declared here + // for `tsc` to pick them up in type definitions. + + /** + * Get the {@link VideoTrackList} + * + * @link https://html.spec.whatwg.org/multipage/embedded-content.html#videotracklist + * + * @return {VideoTrackList} + * the current video track list + * + * @method Player.prototype.videoTracks + */ + videoTracks() {} + + /** + * Get the {@link AudioTrackList} + * + * @link https://html.spec.whatwg.org/multipage/embedded-content.html#audiotracklist + * + * @return {AudioTrackList} + * the current audio track list + */ + audioTracks() {} + + /** + * Get the {@link TextTrackList} + * + * @link http://www.w3.org/html/wg/drafts/html/master/embedded-content-0.html#dom-media-texttracks + * + * @return {TextTrackList} + * the current text track list + */ + textTracks() {} + + /** + * Get the remote {@link TextTrackList} + * + * @return {TextTrackList} + * The current remote text track list + */ + remoteTextTracks() {} + + /** + * Get the remote {@link HtmlTrackElementList} tracks. + * + * @return {HtmlTrackElementList} + * The current remote text track element list + */ + remoteTextTrackEls() {} + /** * A helper method for adding a {@link TextTrack} to our * {@link TextTrackList}. @@ -5258,57 +5309,6 @@ class Player extends Component { } } -/** - * Get the {@link VideoTrackList} - * - * @link https://html.spec.whatwg.org/multipage/embedded-content.html#videotracklist - * - * @return {VideoTrackList} - * the current video track list - * - * @method Player.prototype.videoTracks - */ - -/** - * Get the {@link AudioTrackList} - * - * @link https://html.spec.whatwg.org/multipage/embedded-content.html#audiotracklist - * - * @return {AudioTrackList} - * the current audio track list - * - * @method Player.prototype.audioTracks - */ - -/** - * Get the {@link TextTrackList} - * - * @link http://www.w3.org/html/wg/drafts/html/master/embedded-content-0.html#dom-media-texttracks - * - * @return {TextTrackList} - * the current text track list - * - * @method Player.prototype.textTracks - */ - -/** - * Get the remote {@link TextTrackList} - * - * @return {TextTrackList} - * The current remote text track list - * - * @method Player.prototype.remoteTextTracks - */ - -/** - * Get the remote {@link HtmlTrackElementList} tracks. - * - * @return {HtmlTrackElementList} - * The current remote text track element list - * - * @method Player.prototype.remoteTextTrackEls - */ - TRACK_TYPES.names.forEach(function(name) { const props = TRACK_TYPES[name]; @@ -5484,3 +5484,5 @@ TECH_EVENTS_RETRIGGER.forEach(function(event) { Component.registerComponent('Player', Player); export default Player; +// Including a named export so Typescript can use module augmentation with plugins +export { Player }; diff --git a/src/js/plugin.js b/src/js/plugin.js index 52ab6e7e7d..0647a93654 100644 --- a/src/js/plugin.js +++ b/src/js/plugin.js @@ -206,6 +206,12 @@ class Plugin { this.log = this.player.log.createLogger(this.name); } + // Remove the placeholder event methods. If the component is evented, the + // real methods are added next + ['on', 'off', 'one', 'any', 'trigger'].forEach(fn => { + this[fn] = undefined; + }); + // Make this object evented, but remove the added `trigger` method so we // use the prototype version instead. evented(this); @@ -248,6 +254,61 @@ class Plugin { return hash; } + // `on`, `off`, `one`, and `any` are here so tsc includes them in definitions. + // They are replaced or removed in the constructor + + /** + * Adds an `event listener` to an instance of an `EventTarget`. An `event listener` is a + * function that will get called when an event with a certain name gets triggered. + * + * @param {string|string[]} type + * An event name or an array of event names. + * + * @param {Function} fn + * The function to call with `EventTarget`s + */ + on(type, fn) {} + + /** + * Removes an `event listener` for a specific event from an instance of `EventTarget`. + * This makes it so that the `event listener` will no longer get called when the + * named event happens. + * + * @param {string|string[]} type + * An event name or an array of event names. + * + * @param {Function} [fn] + * The function to remove. If not specified, all listeners managed by Video.js will be removed. + */ + off(type, fn) {} + + /** + * This function will add an `event listener` that gets triggered only once. After the + * first trigger it will get removed. This is like adding an `event listener` + * with {@link EventTarget#on} that calls {@link EventTarget#off} on itself. + * + * @param {string|string[]} type + * An event name or an array of event names. + * + * @param {Function} fn + * The function to be called once for each event name. + */ + one(type, fn) {} + + /** + * This function will add an `event listener` that gets triggered only once and is + * removed from all events. This is like adding an array of `event listener`s + * with {@link EventTarget#on} that calls {@link EventTarget#off} on all events the + * first time it is triggered. + * + * @param {string|string[]} type + * An event name or an array of event names. + * + * @param {Function} fn + * The function to be called once for each event name. + */ + any(type, fn) {} + /** * Triggers an event on the plugin object and overrides * {@link module:evented~EventedMixin.trigger|EventedMixin.trigger}. @@ -478,6 +539,9 @@ Player.prototype.hasPlugin = function(name) { export default Plugin; +// Including a named export so Typescript can use module augmentation with plugins +export { Plugin }; + /** * Signals that a plugin is about to be set up on a player. * diff --git a/src/js/video.js b/src/js/video.js index 9d2dde1f5a..d77c3f9cae 100644 --- a/src/js/video.js +++ b/src/js/video.js @@ -320,10 +320,11 @@ videojs.getComponent = Component.getComponent; * @param {string} name * The class name of the component * - * @param {typeof Component} comp - * The component class + * @template {typeof Component} C + * @param {C} comp + * The `Component` class to register. * - * @return {typeof Component} + * @return {C} * The newly registered component */ videojs.registerComponent = (name, comp) => { From 6b17e7ec9f6eaae635e7960f22552a9566e169af Mon Sep 17 00:00:00 2001 From: Michael Barlock Date: Fri, 9 Aug 2024 11:35:52 -0400 Subject: [PATCH 2/2] remove template --- src/js/component.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/js/component.js b/src/js/component.js index 8db2023c6e..5ce4789831 100644 --- a/src/js/component.js +++ b/src/js/component.js @@ -1966,11 +1966,10 @@ class Component { * * @param {string} name * The name of the `Component` to register. - * @template {Component} C - * @param {C} ComponentToRegister + * @param {Component} ComponentToRegister * The `Component` class to register. * - * @return {C} + * @return {Component} * The `Component` that was registered. */ static registerComponent(name, ComponentToRegister) {