diff --git a/web/eslint.config.js b/web/eslint.config.js index 3be1b21708e2..daba5c146add 100644 --- a/web/eslint.config.js +++ b/web/eslint.config.js @@ -115,6 +115,10 @@ export default tseslint.config( startLines: 1, }, ], + "jsdoc/check-tag-names": [ + "error", + { definedTags: ["privateRemarks"] }, + ], }, settings: { jsdoc: { diff --git a/web/package-lock.json b/web/package-lock.json index c007986d862c..dc0d829820ab 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -38,6 +38,7 @@ "stylelint-prettier": "^5.0.2", "ts-loader": "^9.5.1", "tsx": "^4.19.1", + "typedoc-plugin-mdn-links": "^3.3.2", "typescript": "^5.6.2", "typescript-eslint": "^8.8.0", "webdriverio": "^8.40.0", @@ -15823,6 +15824,15 @@ "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x" } }, + "node_modules/typedoc-plugin-mdn-links": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/typedoc-plugin-mdn-links/-/typedoc-plugin-mdn-links-3.3.2.tgz", + "integrity": "sha512-5CGxkdfsG4Yki6UsFOvVN8vWXXDb25SozOlyThk9Dq8JvKcUgY+Ra+cZvkFWs3hLlO4W8xpFbYQxNngCLf9MMA==", + "dev": true, + "peerDependencies": { + "typedoc": ">= 0.23.14 || 0.24.x || 0.25.x || 0.26.x" + } + }, "node_modules/typedoc/node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", diff --git a/web/package.json b/web/package.json index def98d269944..5190a2150f54 100644 --- a/web/package.json +++ b/web/package.json @@ -35,6 +35,7 @@ "stylelint-prettier": "^5.0.2", "ts-loader": "^9.5.1", "tsx": "^4.19.1", + "typedoc-plugin-mdn-links": "^3.3.2", "typescript": "^5.6.2", "typescript-eslint": "^8.8.0", "webdriverio": "^8.40.0", diff --git a/web/packages/core/src/build-info.ts b/web/packages/core/src/build-info.ts index d6cf11db2ea4..7fda18c68e1d 100644 --- a/web/packages/core/src/build-info.ts +++ b/web/packages/core/src/build-info.ts @@ -1,5 +1,10 @@ /** - * Stores build information. The string literals are replaced at compile time by `set_version.ts`. + * Stores build information about this specific version of the `ruffle-core` library. + * + * It does not represent the version of Ruffle that may be in use by the page (for example, if a browser extension overrides it). + * + * @privateRemarks + * This is generated at build time via `set_version.ts`. */ export const buildInfo = { versionNumber: "%VERSION_NUMBER%", diff --git a/web/packages/core/src/index.ts b/web/packages/core/src/index.ts index d1086c308638..f7b900ea9026 100644 --- a/web/packages/core/src/index.ts +++ b/web/packages/core/src/index.ts @@ -1,19 +1,7 @@ -/** - * This is the public API of the web version of Ruffle. - * - * Types should only be exported here if they are intended to be part of that public API, not internal. - */ +export * as Setup from "./public/setup"; + +export * as Config from "./public/config"; + +export * as Player from "./public/player"; -export * from "./polyfills"; -export * from "./public-api"; -export * from "./version"; -export * from "./version-range"; -export * from "./config"; -export * from "./load-options"; export * from "./build-info"; -export * from "./swf-utils"; -export * from "./movie-metadata"; -export * from "./install"; -export * from "./public/flash"; -export * from "./public/legacy"; -export * from "./public/player"; diff --git a/web/packages/core/src/internal/builder.ts b/web/packages/core/src/internal/builder.ts index c576b4cbda5d..f60083800441 100644 --- a/web/packages/core/src/internal/builder.ts +++ b/web/packages/core/src/internal/builder.ts @@ -1,5 +1,5 @@ import type { RuffleInstanceBuilder } from "../../dist/ruffle_web"; -import { BaseLoadOptions, Duration, SecsDuration } from "../load-options"; +import { BaseLoadOptions, Duration, SecsDuration } from "../public/config"; /** * Checks if the given value is explicitly `T` (not null, not undefined) diff --git a/web/packages/core/src/internal/internal-source-api.ts b/web/packages/core/src/internal/internal-source-api.ts new file mode 100644 index 000000000000..ab4ddc9ac4aa --- /dev/null +++ b/web/packages/core/src/internal/internal-source-api.ts @@ -0,0 +1,52 @@ +import { buildInfo } from "../build-info"; +import { pluginPolyfill, polyfill } from "../polyfills"; +import { PlayerElement } from "../public/player"; +import { registerElement } from "./register-element"; +import { RufflePlayerElement } from "./player/ruffle-player-element"; +import { InstallationOptions } from "../public/setup"; + +/** + * The actual source API that describes this installation. + * This isn't part of the public API and may contain extra details. + */ +export const internalSourceApi = { + /** + * The version of this particular API, as a string in a semver compatible format. + */ + version: + buildInfo.versionNumber + "+" + buildInfo.buildDate.substring(0, 10), + + /** + * Start up the polyfills. + * + * Do not run polyfills for more than one Ruffle source at a time. + */ + polyfill(): void { + polyfill(); + }, + + /** + * Polyfill the plugin detection. + * + * This needs to run before any plugin detection script does. + */ + pluginPolyfill(): void { + pluginPolyfill(); + }, + + /** + * Create a Ruffle player element using this particular version of Ruffle. + * + * @returns The player element. This is a DOM element that may be inserted + * into the current page as you wish. + */ + createPlayer(): PlayerElement { + const name = registerElement("ruffle-player", RufflePlayerElement); + return document.createElement(name) as RufflePlayerElement; + }, + + /** + * Options specified by the user of this library. + */ + options: {} as InstallationOptions, +}; diff --git a/web/packages/core/src/internal/player/inner.tsx b/web/packages/core/src/internal/player/inner.tsx index 78a955a402ec..8884a3ba413a 100644 --- a/web/packages/core/src/internal/player/inner.tsx +++ b/web/packages/core/src/internal/player/inner.tsx @@ -7,8 +7,9 @@ import { UnmuteOverlay, URLLoadOptions, WindowMode, -} from "../../load-options"; -import type { MovieMetadata } from "../../movie-metadata"; + DEFAULT_CONFIG, +} from "../../public/config"; +import type { MovieMetadata } from "../../public/player"; import { ruffleShadowTemplate } from "../ui/shadow-template"; import { text, textAsParagraphs } from "../i18n"; import { swfFileName } from "../../swf-utils"; @@ -25,7 +26,6 @@ import { showPanicScreen } from "../ui/panic"; import { createRuffleBuilder } from "../../load-ruffle"; import { lookupElement } from "../register-element"; import { configureBuilder } from "../builder"; -import { DEFAULT_CONFIG } from "../../config"; const DIMENSION_REGEX = /^\s*(\d+(\.\d+)?(%)?)/; @@ -42,7 +42,13 @@ declare global { webkitCancelFullScreen?: () => void; } interface Element { + /** + * @ignore + */ webkitRequestFullscreen?: (options: unknown) => unknown; + /** + * @ignore + */ webkitRequestFullScreen?: (options: unknown) => unknown; } } @@ -1592,7 +1598,7 @@ export class InnerPlayer { // Then we have to close the context menu manually after the callback finishes. this.hideContextMenu(); - } + }; if (this.contextMenuSupported) { menuItem.addEventListener("click", itemAction); menuItem.addEventListener("contextmenu", itemAction); diff --git a/web/packages/core/src/internal/player/ruffle-embed-element.ts b/web/packages/core/src/internal/player/ruffle-embed-element.ts index 4a1561d568cb..b96cdb4c7e89 100644 --- a/web/packages/core/src/internal/player/ruffle-embed-element.ts +++ b/web/packages/core/src/internal/player/ruffle-embed-element.ts @@ -12,7 +12,7 @@ import { isSwf } from "../../swf-utils"; * A polyfill html element. * * This specific class tries to polyfill existing `` tags, - * and should not be used. Prefer [[RufflePlayer]] instead. + * and should not be used. Prefer {@link RufflePlayer} instead. * * @internal */ diff --git a/web/packages/core/src/internal/player/ruffle-object-element.ts b/web/packages/core/src/internal/player/ruffle-object-element.ts index 5379a4fb1bb7..1caf0588d485 100644 --- a/web/packages/core/src/internal/player/ruffle-object-element.ts +++ b/web/packages/core/src/internal/player/ruffle-object-element.ts @@ -17,7 +17,7 @@ import { isSwf } from "../../swf-utils"; * @param obj Object to check * @param key Key to find * @param defaultValue Value if not found - * @returns Value if found, else [[defaultValue]] + * @returns Value if found, else {@link defaultValue} */ function findCaseInsensitive( obj: Record, @@ -34,7 +34,7 @@ function findCaseInsensitive( } /** - * Returns all flash params ([[HTMLParamElement]]) that are for the given object. + * Returns all flash params ({@link HTMLParamElement}) that are for the given object. * * @param elem Element to check. * @returns A record of every parameter. @@ -59,7 +59,7 @@ function paramsOf(elem: Element): Record { * A polyfill html element. * * This specific class tries to polyfill existing `` tags, - * and should not be used. Prefer [[RufflePlayer]] instead. + * and should not be used. Prefer {@link RufflePlayer} instead. * * @internal */ diff --git a/web/packages/core/src/internal/player/ruffle-player-element.tsx b/web/packages/core/src/internal/player/ruffle-player-element.tsx index 81329b89a092..d9ac7596926f 100644 --- a/web/packages/core/src/internal/player/ruffle-player-element.tsx +++ b/web/packages/core/src/internal/player/ruffle-player-element.tsx @@ -1,14 +1,13 @@ -import type { DataLoadOptions, URLLoadOptions } from "../../load-options"; -import type { MovieMetadata } from "../../movie-metadata"; +import type { DataLoadOptions, URLLoadOptions } from "../../public/config"; +import type { MovieMetadata, PlayerElement } from "../../public/player"; import { InnerPlayer, ReadyState } from "./inner"; -import { Player } from "../../public/player"; /** * The ruffle player element that should be inserted onto the page. * * This element will represent the rendered and intractable flash movie. */ -export class RufflePlayerElement extends HTMLElement implements Player { +export class RufflePlayerElement extends HTMLElement implements PlayerElement { #inner: InnerPlayer; get onFSCommand(): ((command: string, args: string) => boolean) | null { diff --git a/web/packages/core/src/load-ruffle.ts b/web/packages/core/src/load-ruffle.ts index fa4b4c6821a8..6b474f61a9e4 100644 --- a/web/packages/core/src/load-ruffle.ts +++ b/web/packages/core/src/load-ruffle.ts @@ -11,7 +11,8 @@ import { } from "wasm-feature-detect"; import type { RuffleInstanceBuilder, ZipWriter } from "../dist/ruffle_web"; import { setPolyfillsOnLoad } from "./js-polyfills"; -import { internalSourceApi } from "./source-api"; + +import { internalSourceApi } from "./internal/internal-source-api"; type ProgressCallback = (bytesLoaded: number, bytesTotal: number) => void; diff --git a/web/packages/core/src/polyfills.ts b/web/packages/core/src/polyfills.ts index a3e8a4b606a9..eb5b58c5e609 100644 --- a/web/packages/core/src/polyfills.ts +++ b/web/packages/core/src/polyfills.ts @@ -2,7 +2,7 @@ import { RuffleObjectElement } from "./internal/player/ruffle-object-element"; import { RuffleEmbedElement } from "./internal/player/ruffle-embed-element"; import { installPlugin, FLASH_PLUGIN } from "./plugin-polyfill"; import { publicPath } from "./public-path"; -import type { DataLoadOptions, URLLoadOptions } from "./load-options"; +import type { DataLoadOptions, URLLoadOptions } from "./public/config"; import { isExtension } from "./current-script"; const globalConfig: DataLoadOptions | URLLoadOptions | object = diff --git a/web/packages/core/src/public-path.ts b/web/packages/core/src/public-path.ts index a546cd90baee..fb6576a68806 100644 --- a/web/packages/core/src/public-path.ts +++ b/web/packages/core/src/public-path.ts @@ -1,4 +1,4 @@ -import { BaseLoadOptions } from "./load-options"; +import { BaseLoadOptions } from "./public/config"; import { currentScriptURL, isExtension } from "./current-script"; /** diff --git a/web/packages/core/src/config.ts b/web/packages/core/src/public/config/default.ts similarity index 100% rename from web/packages/core/src/config.ts rename to web/packages/core/src/public/config/default.ts diff --git a/web/packages/core/src/public/config/index.ts b/web/packages/core/src/public/config/index.ts new file mode 100644 index 000000000000..5a1ae261d316 --- /dev/null +++ b/web/packages/core/src/public/config/index.ts @@ -0,0 +1,11 @@ +/** + * The Config module contains all the types that Ruffle uses for movie configs. + * + * The main interface of interest here is {@link BaseLoadOptions}, which you can apply to `window.RufflePlayer.config` + * to set the default configuration of all players. + * + * @module + */ + +export * from "./default"; +export * from "./load-options"; diff --git a/web/packages/core/src/load-options.ts b/web/packages/core/src/public/config/load-options.ts similarity index 99% rename from web/packages/core/src/load-options.ts rename to web/packages/core/src/public/config/load-options.ts index ffd98b6cc2a3..8586c11373d3 100644 --- a/web/packages/core/src/load-options.ts +++ b/web/packages/core/src/public/config/load-options.ts @@ -676,7 +676,7 @@ export interface URLLoadOptions extends BaseLoadOptions { /** * The URL to load a movie from. * - * If there is a query portion of this URL, then default [[parameters]] + * If there is a query portion of this URL, then default {@link parameters} * will be extracted from that. */ url: string; diff --git a/web/packages/core/src/public/flash.ts b/web/packages/core/src/public/player/flash.ts similarity index 87% rename from web/packages/core/src/public/flash.ts rename to web/packages/core/src/public/player/flash.ts index 70bf94d7c330..64754bfbf1b4 100644 --- a/web/packages/core/src/public/flash.ts +++ b/web/packages/core/src/public/player/flash.ts @@ -1,5 +1,5 @@ /** - * These are properties and methods that Flash added to its / tags. + * These are properties and methods that Flash added to its `/` tags. * These don't seem to be documented in full anywhere, and Ruffle adds them as we encounter some. * You are discouraged from using these, and they exist only to support legacy websites from decades ago. * diff --git a/web/packages/core/src/public/player/index.ts b/web/packages/core/src/public/player/index.ts new file mode 100644 index 000000000000..0ef102322544 --- /dev/null +++ b/web/packages/core/src/public/player/index.ts @@ -0,0 +1,10 @@ +/** + * The Player module contains the actual {@link PlayerElement} and the various interfaces that exist to interact with the player. + * + * @module + */ + +export * from "./flash"; +export * from "./player-element"; +export * from "./movie-metadata"; +export * from "./legacy"; diff --git a/web/packages/core/src/public/legacy.ts b/web/packages/core/src/public/player/legacy.ts similarity index 88% rename from web/packages/core/src/public/legacy.ts rename to web/packages/core/src/public/player/legacy.ts index 0ca499d28e03..605c4d50e41b 100644 --- a/web/packages/core/src/public/legacy.ts +++ b/web/packages/core/src/public/player/legacy.ts @@ -1,6 +1,6 @@ -import { DataLoadOptions, URLLoadOptions } from "../load-options"; -import { MovieMetadata } from "../movie-metadata"; -import { ReadyState } from "../internal/player/inner"; +import { DataLoadOptions, URLLoadOptions } from "../config"; +import { MovieMetadata } from "./movie-metadata"; +import { ReadyState } from "../../internal/player/inner"; /** * Legacy interface to the Ruffle API. @@ -48,7 +48,7 @@ export interface LegacyRuffleAPI { get metadata(): MovieMetadata | null; /** - * Reloads the player, as if you called {@link RufflePlayer.load} with the same config as the last time it was called. + * Reloads the player, as if you called {@link load} with the same config as the last time it was called. * * If this player has never been loaded, this method will return an error. */ @@ -61,13 +61,13 @@ export interface LegacyRuffleAPI { * * @param options One of the following: * - A URL, passed as a string, which will load a URL with default options. - * - A [[URLLoadOptions]] object, to load a URL with options. - * - A [[DataLoadOptions]] object, to load data with options. + * - A {@link URLLoadOptions} object, to load a URL with options. + * - A {@link DataLoadOptions} object, to load data with options. * The options, if provided, must only contain values provided for this specific movie. * They must not contain any default values, since those would overwrite other configuration * settings with a lower priority (e.g. the general RufflePlayer config). * - * The options will be defaulted by the [[config]] field, which itself + * The options will be defaulted by the {@link config} field, which itself * is defaulted by a global `window.RufflePlayer.config`. */ load(options: string | URLLoadOptions | DataLoadOptions): Promise; @@ -105,7 +105,7 @@ export interface LegacyRuffleAPI { /** * Checks if this player is allowed to be fullscreen by the browser. * - * @returns True if you may call [[enterFullscreen]]. + * @returns True if you may call {@link enterFullscreen}. */ get fullscreenEnabled(): boolean; @@ -127,7 +127,7 @@ export interface LegacyRuffleAPI { /** * Requests the browser to make this player fullscreen. * - * This is not guaranteed to succeed, please check [[fullscreenEnabled]] first. + * This is not guaranteed to succeed, please check {@link fullscreenEnabled} first. */ enterFullscreen(): void; diff --git a/web/packages/core/src/movie-metadata.ts b/web/packages/core/src/public/player/movie-metadata.ts similarity index 100% rename from web/packages/core/src/movie-metadata.ts rename to web/packages/core/src/public/player/movie-metadata.ts diff --git a/web/packages/core/src/public/player.ts b/web/packages/core/src/public/player/player-element.ts similarity index 57% rename from web/packages/core/src/public/player.ts rename to web/packages/core/src/public/player/player-element.ts index 36956e2ca0b1..97b663382b6d 100644 --- a/web/packages/core/src/public/player.ts +++ b/web/packages/core/src/public/player/player-element.ts @@ -4,9 +4,9 @@ import { FlashAPI } from "./flash"; /** * A Ruffle player's HTML element. * - * This is either created through `window.RufflePlayer.createPlayer()`, or polyfilled from a ``/`` tag. + * This is either created through `window.RufflePlayer.latest().createPlayer()`, or polyfilled from a ``/`` tag. * * In addition to usual HTML attributes, this player contains methods and properties that belong to both * the **Flash JS API** and **legacy Ruffle API**s. */ -export interface Player extends HTMLElement, LegacyRuffleAPI, FlashAPI {} +export interface PlayerElement extends HTMLElement, LegacyRuffleAPI, FlashAPI {} diff --git a/web/packages/core/src/public/setup/index.ts b/web/packages/core/src/public/setup/index.ts new file mode 100644 index 000000000000..eb86b3c22c21 --- /dev/null +++ b/web/packages/core/src/public/setup/index.ts @@ -0,0 +1,20 @@ +/** + * The Setup module contains the interfaces and methods needed to install Ruffle onto a page, + * and create a {@link PlayerElement} with the latest version of Ruffle available. + * + * This is primarily relevant to users of `ruffle-core` as a npm module, as the "selfhosted" version of Ruffle preinstalls itself, + * and without type checking the interfaces here are of limited use. + * + * For users of `ruffle-core` as a npm module, you are encouraged to call {@link installRuffle} once during page load to + * make the `ruffle-core` library register itself as a version of Ruffle on the page. + * + * Multiple sources of Ruffle may exist - for example, the Ruffle browser extension also installs itself on page load. + * For this reason, you are required to call `window.RufflePlayer.latest()` (for example) to grab the latest {@link SourceAPI}, + * from which you can create a {@link PlayerElement} via {@link SourceAPI.createPlayer}. + * + * @module + */ + +export * from "./public-api"; +export * from "./source-api"; +export * from "./install"; diff --git a/web/packages/core/src/install.ts b/web/packages/core/src/public/setup/install.ts similarity index 96% rename from web/packages/core/src/install.ts rename to web/packages/core/src/public/setup/install.ts index 1c5473cf7ebd..2254bd9d315d 100644 --- a/web/packages/core/src/install.ts +++ b/web/packages/core/src/public/setup/install.ts @@ -1,5 +1,6 @@ import { PublicAPI } from "./public-api"; -import { internalSourceApi } from "./source-api"; + +import { internalSourceApi } from "../../internal/internal-source-api"; /** * Options to use with this specific installation of Ruffle. diff --git a/web/packages/core/src/public-api.ts b/web/packages/core/src/public/setup/public-api.ts similarity index 95% rename from web/packages/core/src/public-api.ts rename to web/packages/core/src/public/setup/public-api.ts index a65472cae1a1..7e7ac422428a 100644 --- a/web/packages/core/src/public-api.ts +++ b/web/packages/core/src/public/setup/public-api.ts @@ -1,15 +1,15 @@ -import { Version } from "./version"; -import { VersionRange } from "./version-range"; +import { Version } from "../../version"; +import { VersionRange } from "../../version-range"; import { SourceAPI } from "./source-api"; -import type { DataLoadOptions, URLLoadOptions } from "./load-options"; +import type { DataLoadOptions, URLLoadOptions } from "../config"; declare global { interface Window { /** * The public API for generating a ruffle player. * This may be a config holder, which will be converted to a - * [[PublicAPI]] via [[installRuffle]], or an actual - * [[PublicAPI]] instance itself. + * {@link PublicAPI} via {@link installRuffle}, or an actual + * {@link PublicAPI} instance itself. */ RufflePlayer?: PublicAPILike | PublicAPI; } @@ -18,8 +18,8 @@ declare global { /** * Represents a potential installation of a Ruffle public API. * - * Unlike [[PublicAPI]], this may come from any source, past or future. - * It needs to be forwards compatible and convertible into a modern day [[PublicAPI]]. + * Unlike {@link PublicAPI}, this may come from any source, past or future. + * It needs to be forwards compatible and convertible into a modern day {@link PublicAPI}. */ export interface PublicAPILike { config?: DataLoadOptions | URLLoadOptions | object; diff --git a/web/packages/core/src/public/setup/source-api.ts b/web/packages/core/src/public/setup/source-api.ts new file mode 100644 index 000000000000..0e88b4e25e83 --- /dev/null +++ b/web/packages/core/src/public/setup/source-api.ts @@ -0,0 +1,38 @@ +import { PlayerElement } from "../player"; + +/** + * Represents this particular version of Ruffle. + * + * Multiple APIs can be instantiated from different sources; e.g. an "extension" + * version, versus a "local" version. This expresses to the Public API + * negotiator (see {@link PublicAPI}) what this particular version of Ruffle is and + * how to control it. + */ +export interface SourceAPI { + /** + * The version of this particular API, as a string in a semver compatible format. + */ + version: string; + + /** + * Start up the polyfills. + * + * Do not run polyfills for more than one Ruffle source at a time. + */ + polyfill(): void; + + /** + * Polyfill the plugin detection. + * + * This needs to run before any plugin detection script does. + */ + pluginPolyfill(): void; + + /** + * Create a Ruffle player element using this particular version of Ruffle. + * + * @returns The player element. This is a DOM element that may be inserted + * into the current page as you wish. + */ + createPlayer(): PlayerElement; +} diff --git a/web/packages/core/src/source-api.ts b/web/packages/core/src/source-api.ts deleted file mode 100644 index 5ea1dc61ab9c..000000000000 --- a/web/packages/core/src/source-api.ts +++ /dev/null @@ -1,89 +0,0 @@ -import { pluginPolyfill, polyfill } from "./polyfills"; -import { registerElement } from "./internal/register-element"; -import { RufflePlayerElement } from "./internal/player/ruffle-player-element"; -import { buildInfo } from "./build-info"; -import { InstallationOptions } from "./install"; -import { Player } from "./public/player"; - -/** - * Represents this particular version of Ruffle. - * - * Multiple APIs can be instantiated from different sources; e.g. an "extension" - * version, versus a "local" version. This expresses to the Public API - * negotiator (see [[PublicAPI]]) what this particular version of Ruffle is and - * how to control it. - */ -export interface SourceAPI { - /** - * The version of this particular API, as a string in a semver compatible format. - */ - version: string; - - /** - * Start up the polyfills. - * - * Do not run polyfills for more than one Ruffle source at a time. - */ - polyfill(): void; - - /** - * Polyfill the plugin detection. - * - * This needs to run before any plugin detection script does. - */ - pluginPolyfill(): void; - - /** - * Create a Ruffle player element using this particular version of Ruffle. - * - * @returns The player element. This is a DOM element that may be inserted - * into the current page as you wish. - */ - createPlayer(): Player; -} - -/** - * The actual source API that describes this installation. - * This isn't part of the public API and may contain extra details. - */ -export const internalSourceApi = { - /** - * The version of this particular API, as a string in a semver compatible format. - */ - version: - buildInfo.versionNumber + "+" + buildInfo.buildDate.substring(0, 10), - - /** - * Start up the polyfills. - * - * Do not run polyfills for more than one Ruffle source at a time. - */ - polyfill(): void { - polyfill(); - }, - - /** - * Polyfill the plugin detection. - * - * This needs to run before any plugin detection script does. - */ - pluginPolyfill(): void { - pluginPolyfill(); - }, - - /** - * Create a Ruffle player element using this particular version of Ruffle. - * - * @returns The player element. This is a DOM element that may be inserted - * into the current page as you wish. - */ - createPlayer(): Player { - const name = registerElement("ruffle-player", RufflePlayerElement); - return document.createElement(name) as RufflePlayerElement; - }, - - /** - * Options specified by the user of this library. - */ - options: {} as InstallationOptions, -}; diff --git a/web/packages/core/src/version-range.ts b/web/packages/core/src/version-range.ts index db9ff17dbf7b..65ff105c0f4e 100644 --- a/web/packages/core/src/version-range.ts +++ b/web/packages/core/src/version-range.ts @@ -43,7 +43,7 @@ export class VersionRange { * Constructs a range of versions as specified by the given requirements. * * If you wish to construct this object from a string representation, - * then use [[fromRequirementString]]. + * then use {@link fromRequirementString}. * * @param requirements Requirements to set this range by */ diff --git a/web/packages/core/src/version.ts b/web/packages/core/src/version.ts index b4a3e186ec6f..b8fd6f33b600 100644 --- a/web/packages/core/src/version.ts +++ b/web/packages/core/src/version.ts @@ -5,7 +5,7 @@ export class Version { /** * Construct a Version from specific components. * - * If you wish to parse a string into a Version then please use [[fromSemver]]. + * If you wish to parse a string into a Version then please use {@link fromSemver}. * * @param major The major version component. * @param minor The minor version component. diff --git a/web/packages/core/typedoc.json b/web/packages/core/typedoc.json index 23f8cff4b40a..ff9f8bd599bc 100644 --- a/web/packages/core/typedoc.json +++ b/web/packages/core/typedoc.json @@ -2,5 +2,7 @@ "entryPoints": ["./src/index.ts"], "excludePrivate": true, "excludeProtected": true, - "sort": "enum-member-source-order" + "excludeExternals": true, + "sort": "enum-member-source-order", + "plugin": ["typedoc-plugin-mdn-links"] } diff --git a/web/packages/demo/src/App.tsx b/web/packages/demo/src/App.tsx index fec9df73b026..d0af1119e241 100644 --- a/web/packages/demo/src/App.tsx +++ b/web/packages/demo/src/App.tsx @@ -1,11 +1,11 @@ import { Player } from "./player.tsx"; import { useRef, useState, DragEvent, useCallback } from "react"; -import { BaseLoadOptions, MovieMetadata } from "ruffle-core"; +import type { Config, Player as RufflePlayer } from "ruffle-core"; import { Navbar } from "./navbar.tsx"; import { MetadataPanel } from "./metadata.tsx"; interface AppProperties { - ruffleBaseConfig: BaseLoadOptions; + ruffleBaseConfig: Config.BaseLoadOptions; allowUrlLoading: boolean; allowSampleSwfs: boolean; } @@ -15,7 +15,9 @@ export function App({ allowUrlLoading, allowSampleSwfs, }: AppProperties) { - const [metadata, setMetadata] = useState(null); + const [metadata, setMetadata] = useState( + null, + ); const [metadataVisible, setMetadataVisible] = useState(false); const [selectedFilename, setSelectedFilename] = useState( null, @@ -33,9 +35,12 @@ export function App({ }; // useCallback because this will be called from useEffect, we need this function to not change - const onSelectUrl = useCallback((url: string, options: BaseLoadOptions) => { - player.current?.loadUrl(url, options); - }, []); + const onSelectUrl = useCallback( + (url: string, options: Config.BaseLoadOptions) => { + player.current?.loadUrl(url, options); + }, + [], + ); const onSelectFile = (file: File) => { player.current?.loadFile(file); diff --git a/web/packages/demo/src/main.tsx b/web/packages/demo/src/main.tsx index 846c45ad35ba..0d8afe8a6dad 100644 --- a/web/packages/demo/src/main.tsx +++ b/web/packages/demo/src/main.tsx @@ -4,24 +4,18 @@ import "./common.css"; import "./lato.css"; import "./index.css"; import { App } from "./App.tsx"; -import { - AutoPlay, - Letterbox, - LogLevel, - installRuffle, - UnmuteOverlay, -} from "ruffle-core"; +import { Config, Setup } from "ruffle-core"; -installRuffle("local"); +Setup.installRuffle("local"); ReactDOM.createRoot(document.getElementById("root")!).render( FP Version {metadata - ? swfToFlashVersion[metadata.swfVersion] ?? "Unknown" + ? (swfToFlashVersion[metadata.swfVersion] ?? "Unknown") : ""} diff --git a/web/packages/demo/src/navbar.tsx b/web/packages/demo/src/navbar.tsx index cae8bac9b08c..18e5b7d8890d 100644 --- a/web/packages/demo/src/navbar.tsx +++ b/web/packages/demo/src/navbar.tsx @@ -7,7 +7,7 @@ import { useState, DragEvent, } from "react"; -import { BaseLoadOptions } from "ruffle-core"; +import type { Config } from "ruffle-core"; import { DemoSwf, SampleSelection } from "./navbar/samples.tsx"; declare global { @@ -25,7 +25,7 @@ interface NavbarProps { allowSampleSwfs: boolean; onToggleMetadata: () => void; onReloadMovie: () => void; - onSelectUrl: (url: string, options: BaseLoadOptions) => void; + onSelectUrl: (url: string, options: Config.BaseLoadOptions) => void; onSelectFile: (file: File) => void; selectedFilename: string | null; setSelectedFilename: (value: string | null) => void; diff --git a/web/packages/demo/src/navbar/samples.tsx b/web/packages/demo/src/navbar/samples.tsx index f2fb15be988f..5ecd4f98a9f4 100644 --- a/web/packages/demo/src/navbar/samples.tsx +++ b/web/packages/demo/src/navbar/samples.tsx @@ -6,7 +6,7 @@ import { useEffect, useState, } from "react"; -import { BaseLoadOptions } from "ruffle-core"; +import type { Config } from "ruffle-core"; type SampleCategory = "Animation" | "Game"; @@ -20,7 +20,7 @@ export interface DemoSwf { title?: string; author?: string; authorLink?: string; - config?: BaseLoadOptions; + config?: Config.BaseLoadOptions; type: SampleCategory | null; } @@ -29,7 +29,7 @@ interface SampleSelectionProperties { selectedSample: DemoSwf | null; setSelectedSample: (value: DemoSwf | null) => void; setSelectedFilename: (name: string | null) => void; - onSelectUrl: (url: string, config: BaseLoadOptions) => void; + onSelectUrl: (url: string, config: Config.BaseLoadOptions) => void; } export function SampleSelection({ diff --git a/web/packages/demo/src/player.tsx b/web/packages/demo/src/player.tsx index eb1f2cdfdd51..f58bb5074df7 100644 --- a/web/packages/demo/src/player.tsx +++ b/web/packages/demo/src/player.tsx @@ -1,16 +1,11 @@ import React, { ReactNode, DragEvent } from "react"; -import { - PublicAPI, - Player as RufflePlayer, - MovieMetadata, - BaseLoadOptions, -} from "ruffle-core"; +import { Setup, Player as RufflePlayer, Config } from "ruffle-core"; export interface PlayerAttributes { id?: string | undefined; children?: ReactNode; - onLoadedMetadata: (metadata: MovieMetadata) => void; - baseConfig?: BaseLoadOptions; + onLoadedMetadata: (metadata: RufflePlayer.MovieMetadata) => void; + baseConfig?: Config.BaseLoadOptions; onDragEnter: (event: DragEvent) => void; onDragLeave: (event: DragEvent) => void; onDragOver: (event: DragEvent) => void; @@ -19,7 +14,7 @@ export interface PlayerAttributes { export class Player extends React.Component { private readonly container: React.RefObject; - private player: RufflePlayer | null = null; + private player: RufflePlayer.PlayerElement | null = null; // [NA] Ruffle has a bug where if you load a swf whilst it's already loading another swf, it breaks // Combine this with React testing everything by loading things twice to catch bugs - well, they caught the bug for sure. @@ -33,7 +28,7 @@ export class Player extends React.Component { } componentDidMount() { - this.player = (window.RufflePlayer as PublicAPI) + this.player = (window.RufflePlayer as Setup.PublicAPI) .newest()! .createPlayer()!; this.player.id = "player"; @@ -78,7 +73,7 @@ export class Player extends React.Component { } } - loadUrl(url: string, options: BaseLoadOptions) { + loadUrl(url: string, options: Config.BaseLoadOptions) { if (!this.isLoading) { this.isLoading = true; this.player diff --git a/web/packages/extension/src/common.ts b/web/packages/extension/src/common.ts index 19293db4804f..4dec1094742b 100644 --- a/web/packages/extension/src/common.ts +++ b/web/packages/extension/src/common.ts @@ -1,7 +1,7 @@ import * as utils from "./utils"; -import type { BaseLoadOptions } from "ruffle-core"; +import type { Config } from "ruffle-core"; -export interface Options extends BaseLoadOptions { +export interface Options extends Config.BaseLoadOptions { ruffleEnable: boolean; ignoreOptout: boolean; autostart: boolean; diff --git a/web/packages/extension/src/messages.ts b/web/packages/extension/src/messages.ts index 3d1d3b477948..9eda0b2caae9 100644 --- a/web/packages/extension/src/messages.ts +++ b/web/packages/extension/src/messages.ts @@ -1,8 +1,8 @@ -import { BaseLoadOptions } from "ruffle-core"; +import type { Config } from "ruffle-core"; export interface LoadMessage { type: "load"; - config: BaseLoadOptions; + config: Config.BaseLoadOptions; } export interface PingMessage { diff --git a/web/packages/extension/src/player.ts b/web/packages/extension/src/player.ts index 7daeb91837d3..2a9e0df0e77d 100644 --- a/web/packages/extension/src/player.ts +++ b/web/packages/extension/src/player.ts @@ -1,11 +1,7 @@ import * as utils from "./utils"; -import { installRuffle, PublicAPI } from "ruffle-core"; -import type { - Letterbox, - Player, - DataLoadOptions, - URLLoadOptions, -} from "ruffle-core"; +import { Setup } from "ruffle-core"; + +import type { Config, Player } from "ruffle-core"; declare global { interface Navigator { @@ -17,9 +13,9 @@ declare global { } } -installRuffle("local"); -const ruffle = (window.RufflePlayer as PublicAPI).newest()!; -let player: Player; +Setup.installRuffle("local"); +const ruffle = (window.RufflePlayer as Setup.PublicAPI).newest()!; +let player: Player.PlayerElement; const playerContainer = document.getElementById("player-container")!; const overlay = document.getElementById("overlay")!; @@ -39,7 +35,7 @@ const grant = document.getElementById("grant")! as HTMLButtonElement; // This is the base config always used by the extension player. // It has the highest priority and its options cannot be overwritten. const baseExtensionConfig = { - letterbox: "on" as Letterbox, + letterbox: "on" as Config.Letterbox, forceScale: true, forceAlign: true, showSwfDownload: true, @@ -102,7 +98,9 @@ function unload() { } } -async function load(options: string | DataLoadOptions | URLLoadOptions) { +async function load( + options: string | Config.DataLoadOptions | Config.URLLoadOptions, +) { unload(); player = ruffle.createPlayer(); player.id = "player"; diff --git a/web/packages/extension/src/ruffle.ts b/web/packages/extension/src/ruffle.ts index ed518da3ba66..91e2ce4c9c87 100644 --- a/web/packages/extension/src/ruffle.ts +++ b/web/packages/extension/src/ruffle.ts @@ -1,4 +1,4 @@ -import { installRuffle } from "ruffle-core"; +import { Setup } from "ruffle-core"; import { Message } from "./messages"; function handleMessage(message: Message) { @@ -15,7 +15,7 @@ function handleMessage(message: Message) { ...window.RufflePlayer.config, openInNewTab, }; - installRuffle("extension"); + Setup.installRuffle("extension"); return {}; } case "ping": diff --git a/web/packages/extension/src/utils.ts b/web/packages/extension/src/utils.ts index c2d3e1a25bbd..35815cf2ff55 100644 --- a/web/packages/extension/src/utils.ts +++ b/web/packages/extension/src/utils.ts @@ -1,8 +1,8 @@ import type { Options } from "./common"; -import { DEFAULT_CONFIG as CORE_DEFAULT_CONFIG } from "ruffle-core"; +import { Config } from "ruffle-core"; const DEFAULT_OPTIONS: Required = { - ...CORE_DEFAULT_CONFIG, + ...Config.DEFAULT_CONFIG, ruffleEnable: true, ignoreOptout: false, autostart: false, diff --git a/web/packages/selfhosted/js/ruffle.js b/web/packages/selfhosted/js/ruffle.js index c65550803584..b426b18458a3 100644 --- a/web/packages/selfhosted/js/ruffle.js +++ b/web/packages/selfhosted/js/ruffle.js @@ -1,7 +1,7 @@ // eslint-disable-next-line no-unused-vars /* global __webpack_public_path__:writable */ -import { installRuffle } from "ruffle-core"; +import { Setup } from "ruffle-core"; let currentScriptURL = null; @@ -46,7 +46,7 @@ function publicPath(config) { return path; } -installRuffle("local", { +Setup.installRuffle("local", { onFirstLoad: () => { __webpack_public_path__ = publicPath(window.RufflePlayer?.config); }, diff --git a/web/packages/selfhosted/test/js_api/load.ts b/web/packages/selfhosted/test/js_api/load.ts index f897570c9708..e083fc6e93cb 100644 --- a/web/packages/selfhosted/test/js_api/load.ts +++ b/web/packages/selfhosted/test/js_api/load.ts @@ -12,7 +12,7 @@ describe("RufflePlayer.load", () => { const player = await browser.$(""); await browser.execute(async (playerElement) => { // https://github.com/webdriverio/webdriverio/issues/6486 - const player = playerElement as unknown as Player; + const player = playerElement as unknown as Player.PlayerElement; await player.load("/test_assets/example.swf"); }, player); await playAndMonitor(browser, player); diff --git a/web/packages/selfhosted/test/js_api/metadata.ts b/web/packages/selfhosted/test/js_api/metadata.ts index eace4b07fdb2..8645af8259c2 100644 --- a/web/packages/selfhosted/test/js_api/metadata.ts +++ b/web/packages/selfhosted/test/js_api/metadata.ts @@ -12,7 +12,7 @@ describe("RufflePlayer.metadata", () => { const player = await browser.$(""); const metadata = await browser.execute( // https://github.com/webdriverio/webdriverio/issues/6486 - (player) => (player as unknown as Player).metadata, + (player) => (player as unknown as Player.PlayerElement).metadata, player, ); // [NA] Work around a chrome 87 bug where it's (somehow) adding extra data to this object diff --git a/web/packages/selfhosted/test/utils.ts b/web/packages/selfhosted/test/utils.ts index 8f8c7f1357bd..ba524c426b95 100644 --- a/web/packages/selfhosted/test/utils.ts +++ b/web/packages/selfhosted/test/utils.ts @@ -1,5 +1,5 @@ import { expect } from "chai"; -import { Player, PublicAPI } from "ruffle-core"; +import { Player, Setup } from "ruffle-core"; declare global { interface Window { @@ -7,8 +7,8 @@ declare global { } } -declare module "ruffle-core" { - interface Player { +declare module "ruffle-core/dist/public/player" { + interface PlayerElement { __ruffle_log__: string; } } @@ -31,7 +31,7 @@ export async function isRufflePlayerLoaded( (player) => // https://github.com/webdriverio/webdriverio/issues/6486 // TODO: How can we import ReadyState enum? - (player as unknown as Player).readyState, + (player as unknown as Player.PlayerElement).readyState, player, )) === 2 ); @@ -103,7 +103,7 @@ export async function setupAndPlay( ) { await browser.execute((playerElement) => { // https://github.com/webdriverio/webdriverio/issues/6486 - const player = playerElement as unknown as Player; + const player = playerElement as unknown as Player.PlayerElement; player.__ruffle_log__ = ""; player.traceObserver = (msg) => { player.__ruffle_log__ += msg + "\n"; @@ -122,7 +122,8 @@ export async function getTraceOutput( return ( (await browser.execute((player) => { // https://github.com/webdriverio/webdriverio/issues/6486 - return (player as unknown as Player).__ruffle_log__; + return (player as unknown as Player.PlayerElement) + .__ruffle_log__; }, player)) !== "" ); }, @@ -134,7 +135,7 @@ export async function getTraceOutput( // Get the output, and replace it with an empty string for any future test return await browser.execute((playerElement) => { // https://github.com/webdriverio/webdriverio/issues/6486 - const player = playerElement as unknown as Player; + const player = playerElement as unknown as Player.PlayerElement; const log = player.__ruffle_log__; player.__ruffle_log__ = ""; return log; @@ -178,7 +179,7 @@ export function loadJsAPI(swf?: string) { await injectRuffleAndWait(browser); player = (await browser.execute(() => { - const ruffle = (window.RufflePlayer as PublicAPI).newest(); + const ruffle = (window.RufflePlayer as Setup.PublicAPI).newest(); const player = ruffle!.createPlayer(); const container = document.getElementById("test-container"); container!.appendChild(player); @@ -190,7 +191,7 @@ export function loadJsAPI(swf?: string) { await browser.execute( async (player, swf) => { // https://github.com/webdriverio/webdriverio/issues/6486 - await (player as unknown as Player).load(swf); + await (player as unknown as Player.PlayerElement).load(swf); }, player, swf,