(null);
+
+ useEffect(() => {
+ ShakaP2PEngine.registerPlugins(shaka);
+ return () => ShakaP2PEngine.unregisterPlugins(shaka);
+ }, []);
+
+ useEffect(() => {
+ if (!shaka.Player.isBrowserSupported()) {
+ setIsShakaSupported(false);
+ return;
+ }
+
+ let isCleanedUp = false;
+
+ let shakaP2PEngine: ShakaP2PEngine | undefined;
+ let player: shaka.Player | undefined;
+ let ui: shaka.ui.Overlay | undefined;
+
+ const cleanup = () => {
+ isCleanedUp = true;
+ void player?.destroy();
+ player = undefined;
+ shakaP2PEngine?.destroy();
+ void ui?.destroy();
+ };
+
+ const setupPlayer = async () => {
+ if (!videoRef.current || !videoContainerRef.current) return;
+
+ try {
+ const playerInit = new shaka.Player();
+ const uiInit = new shaka.ui.Overlay(
+ playerInit,
+ videoContainerRef.current,
+ videoRef.current,
+ );
+
+ const shakaP2PEngineInit = new ShakaP2PEngine(
+ {
+ core: {
+ announceTrackers,
+ },
+ },
+ shaka,
+ );
+
+ await playerInit.attach(videoRef.current);
+
+ subscribeToUiEvents({
+ engine: shakaP2PEngineInit,
+ onPeerConnect,
+ onPeerDisconnect,
+ onChunkDownloaded,
+ onChunkUploaded,
+ });
+
+ shakaP2PEngineInit.configureAndInitShakaPlayer(playerInit);
+ await playerInit.load(streamUrl);
+
+ player = playerInit;
+ ui = uiInit;
+ shakaP2PEngine = shakaP2PEngineInit;
+
+ if (isCleanedUp) cleanup();
+ } catch (error) {
+ // eslint-disable-next-line no-console
+ console.error("Error setting up Shaka Player:", error);
+ cleanup();
+ }
+ };
+
+ void setupPlayer();
+
+ return () => cleanup();
+ }, [
+ announceTrackers,
+ onChunkDownloaded,
+ onChunkUploaded,
+ onPeerConnect,
+ onPeerDisconnect,
+ streamUrl,
+ ]);
+
+ return isShakaSupported ? (
+
+
+
+ ) : (
+
+
Shaka Player is not supported in this browser
+
+ );
+};
diff --git a/packages/p2p-media-loader-demo/src/components/players/shaka/ShakaClappr.tsx b/packages/p2p-media-loader-demo/src/components/players/shaka/ShakaClappr.tsx
new file mode 100644
index 00000000..5952e616
--- /dev/null
+++ b/packages/p2p-media-loader-demo/src/components/players/shaka/ShakaClappr.tsx
@@ -0,0 +1,86 @@
+import "../clappr.css";
+import { useEffect, useRef, useState } from "react";
+import { PlayerProps } from "../../../types";
+import { ShakaP2PEngine } from "p2p-media-loader-shaka";
+import { subscribeToUiEvents } from "../utils";
+
+export const ShakaClappr = ({
+ streamUrl,
+ announceTrackers,
+ onPeerConnect,
+ onPeerDisconnect,
+ onChunkDownloaded,
+ onChunkUploaded,
+}: PlayerProps) => {
+ const [isShakaSupported, setIsShakaSupported] = useState(true);
+
+ const containerRef = useRef(null);
+
+ useEffect(() => {
+ ShakaP2PEngine.registerPlugins();
+ return () => ShakaP2PEngine.unregisterPlugins();
+ }, []);
+
+ useEffect(() => {
+ if (!window.shaka.Player.isBrowserSupported()) {
+ setIsShakaSupported(false);
+ return;
+ }
+
+ if (!containerRef.current) return;
+
+ const shakaP2PEngine = new ShakaP2PEngine(
+ {
+ core: {
+ announceTrackers,
+ },
+ },
+ window.shaka,
+ );
+
+ /* eslint-disable */
+ // @ts-ignore
+ const clapprPlayer = new Clappr.Player({
+ parentId: `#${containerRef.current.id}`,
+ source: streamUrl,
+ plugins: [window.DashShakaPlayback, window.LevelSelector],
+ playback: {
+ playInline: true,
+ },
+ shakaOnBeforeLoad: (shakaPlayerInstance: shaka.Player) => {
+ subscribeToUiEvents({
+ engine: shakaP2PEngine,
+ onPeerConnect,
+ onPeerDisconnect,
+ onChunkDownloaded,
+ onChunkUploaded,
+ });
+
+ shakaP2PEngine.configureAndInitShakaPlayer(shakaPlayerInstance);
+ },
+ width: "100%",
+ height: "100%",
+ });
+
+ return () => {
+ shakaP2PEngine.destroy();
+ clapprPlayer.destroy();
+ };
+ /* eslint-enable */
+ }, [
+ announceTrackers,
+ onChunkDownloaded,
+ onChunkUploaded,
+ onPeerConnect,
+ onPeerDisconnect,
+ streamUrl,
+ ]);
+
+ return isShakaSupported ? (
+
+ ) : (
+
+
Shaka Player is not supported in this browser
+
+ );
+};
diff --git a/packages/p2p-media-loader-demo/src/components/players/shaka/ShakaDPlayer.tsx b/packages/p2p-media-loader-demo/src/components/players/shaka/ShakaDPlayer.tsx
new file mode 100644
index 00000000..e6cd022b
--- /dev/null
+++ b/packages/p2p-media-loader-demo/src/components/players/shaka/ShakaDPlayer.tsx
@@ -0,0 +1,87 @@
+import { ShakaP2PEngine } from "p2p-media-loader-shaka";
+import { PlayerProps } from "../../../types";
+import { useEffect, useRef, useState } from "react";
+import DPlayer from "dplayer";
+import { subscribeToUiEvents } from "../utils";
+import shaka from "./shaka-import";
+
+export const ShakaDPlayer = ({
+ streamUrl,
+ announceTrackers,
+ onPeerConnect,
+ onPeerDisconnect,
+ onChunkDownloaded,
+ onChunkUploaded,
+}: PlayerProps) => {
+ const [isShakaSupported, setIsShakaSupported] = useState(true);
+
+ const containerRef = useRef(null);
+
+ useEffect(() => {
+ ShakaP2PEngine.registerPlugins(shaka);
+ return () => ShakaP2PEngine.unregisterPlugins(shaka);
+ }, []);
+
+ useEffect(() => {
+ if (!shaka.Player.isBrowserSupported()) {
+ setIsShakaSupported(false);
+ return;
+ }
+
+ const shakaP2PEngine = new ShakaP2PEngine(
+ {
+ core: {
+ announceTrackers,
+ },
+ },
+ shaka,
+ );
+
+ const player = new DPlayer({
+ container: containerRef.current,
+ video: {
+ url: "",
+ type: "customHlsOrDash",
+ customType: {
+ customHlsOrDash: (video: HTMLVideoElement) => {
+ const shakaPlayer = new shaka.Player();
+ void shakaPlayer.attach(video);
+
+ subscribeToUiEvents({
+ engine: shakaP2PEngine,
+ onPeerConnect,
+ onPeerDisconnect,
+ onChunkDownloaded,
+ onChunkUploaded,
+ });
+
+ shakaP2PEngine.configureAndInitShakaPlayer(shakaPlayer);
+ void shakaPlayer.load(streamUrl);
+ },
+ },
+ },
+ });
+
+ return () => {
+ shakaP2PEngine.destroy();
+ player.destroy();
+ };
+ }, [
+ announceTrackers,
+ onChunkDownloaded,
+ onChunkUploaded,
+ onPeerConnect,
+ onPeerDisconnect,
+ streamUrl,
+ ]);
+
+ return isShakaSupported ? (
+
+
+
+ ) : (
+
+
Shaka Player is not supported in this browser
+
+ );
+};
diff --git a/packages/p2p-media-loader-demo/src/components/players/shaka/ShakaPlyr.tsx b/packages/p2p-media-loader-demo/src/components/players/shaka/ShakaPlyr.tsx
new file mode 100644
index 00000000..92c1ac2c
--- /dev/null
+++ b/packages/p2p-media-loader-demo/src/components/players/shaka/ShakaPlyr.tsx
@@ -0,0 +1,139 @@
+import "plyr/dist/plyr.css";
+import { useEffect, useRef, useState } from "react";
+import shaka from "../shaka/shaka-import";
+import { ShakaP2PEngine } from "p2p-media-loader-shaka";
+import { PlayerProps } from "../../../types";
+import Plyr, { Options } from "plyr";
+import { subscribeToUiEvents } from "../utils";
+
+export const ShakaPlyr = ({
+ streamUrl,
+ announceTrackers,
+ onPeerConnect,
+ onPeerDisconnect,
+ onChunkDownloaded,
+ onChunkUploaded,
+}: PlayerProps) => {
+ const [isShakaSupported, setIsShakaSupported] = useState(true);
+
+ const containerRef = useRef(null);
+
+ useEffect(() => {
+ ShakaP2PEngine.registerPlugins(shaka);
+ return () => ShakaP2PEngine.unregisterPlugins(shaka);
+ }, []);
+
+ useEffect(() => {
+ if (!shaka.Player.isBrowserSupported()) {
+ setIsShakaSupported(false);
+ return;
+ }
+
+ if (!containerRef.current) return;
+
+ const videoContainer = document.createElement("div");
+ videoContainer.className = "video-container";
+ containerRef.current.appendChild(videoContainer);
+
+ const videoElement = document.createElement("video");
+ videoElement.id = "player";
+ videoElement.playsInline = true;
+ videoContainer.appendChild(videoElement);
+
+ let plyrPlayer: Plyr | undefined;
+ let playerShaka: shaka.Player | undefined;
+ let shakaP2PEngine: ShakaP2PEngine | undefined;
+ let isCleanedUp = false;
+
+ const cleanup = () => {
+ isCleanedUp = true;
+ shakaP2PEngine?.destroy();
+ void playerShaka?.destroy();
+ playerShaka = undefined;
+ void plyrPlayer?.destroy();
+ plyrPlayer = undefined;
+ videoContainer.remove();
+ };
+
+ const initPlayer = async () => {
+ try {
+ const shakaP2PEngineInit = new ShakaP2PEngine(
+ {
+ core: {
+ announceTrackers,
+ },
+ },
+ shaka,
+ );
+ const shakaPlayerInit = new shaka.Player();
+
+ await shakaPlayerInit.attach(videoElement);
+
+ subscribeToUiEvents({
+ engine: shakaP2PEngineInit,
+ onPeerConnect,
+ onPeerDisconnect,
+ onChunkDownloaded,
+ onChunkUploaded,
+ });
+ shakaP2PEngineInit.configureAndInitShakaPlayer(shakaPlayerInit);
+
+ await shakaPlayerInit.load(streamUrl);
+
+ const levels = shakaPlayerInit.getVariantTracks();
+
+ const quality: Options["quality"] = {
+ default: levels[levels.length - 1]?.height ?? 0,
+ options: levels
+ .map((level) => level.height)
+ .filter((height): height is number => height != null)
+ .sort((a, b) => a - b),
+ forced: true,
+ onChange: (newQuality: number) => {
+ levels.forEach((level) => {
+ if (level.height === newQuality) {
+ shakaPlayerInit.configure({
+ abr: { enabled: false },
+ });
+ shakaPlayerInit.selectVariantTrack(level, true);
+ }
+ });
+ },
+ };
+
+ const plyrPlayerInit = new Plyr(videoElement, {
+ quality,
+ });
+
+ playerShaka = shakaPlayerInit;
+ plyrPlayer = plyrPlayerInit;
+ shakaP2PEngine = shakaP2PEngineInit;
+
+ if (isCleanedUp) cleanup();
+ } catch (error) {
+ // eslint-disable-next-line no-console
+ console.error("Error setting up Shaka Player:", error);
+ cleanup();
+ }
+ };
+
+ void initPlayer();
+
+ return () => cleanup();
+ }, [
+ announceTrackers,
+ onChunkDownloaded,
+ onChunkUploaded,
+ onPeerConnect,
+ onPeerDisconnect,
+ streamUrl,
+ ]);
+
+ return isShakaSupported ? (
+
+ ) : (
+
+
Shaka Player is not supported in this browser
+
+ );
+};
diff --git a/packages/p2p-media-loader-demo/src/components/players/shaka/shaka-import.ts b/packages/p2p-media-loader-demo/src/components/players/shaka/shaka-import.ts
new file mode 100644
index 00000000..db14974d
--- /dev/null
+++ b/packages/p2p-media-loader-demo/src/components/players/shaka/shaka-import.ts
@@ -0,0 +1,4 @@
+// eslint-disable-next-line @typescript-eslint/ban-ts-comment
+// @ts-ignore
+import shakaModule from "shaka-player/dist/shaka-player.ui";
+export default shakaModule as typeof shaka;
diff --git a/packages/p2p-media-loader-demo/src/components/players/utils.ts b/packages/p2p-media-loader-demo/src/components/players/utils.ts
new file mode 100644
index 00000000..e2b89c44
--- /dev/null
+++ b/packages/p2p-media-loader-demo/src/components/players/utils.ts
@@ -0,0 +1,26 @@
+import { HlsJsP2PEngine } from "p2p-media-loader-hlsjs";
+import { PlayerEvents } from "./../../types";
+import { ShakaP2PEngine } from "p2p-media-loader-shaka";
+
+type UIEventsProps = PlayerEvents & {
+ engine: HlsJsP2PEngine | ShakaP2PEngine;
+};
+
+export const subscribeToUiEvents = ({
+ engine,
+ onPeerConnect,
+ onPeerDisconnect,
+ onChunkDownloaded,
+ onChunkUploaded,
+}: UIEventsProps) => {
+ if (onPeerConnect) engine.addEventListener("onPeerConnect", onPeerConnect);
+ if (onPeerDisconnect) {
+ engine.addEventListener("onPeerClose", onPeerDisconnect);
+ }
+ if (onChunkDownloaded) {
+ engine.addEventListener("onChunkDownloaded", onChunkDownloaded);
+ }
+ if (onChunkUploaded) {
+ engine.addEventListener("onChunkUploaded", onChunkUploaded);
+ }
+};
diff --git a/packages/p2p-media-loader-demo/src/constants.ts b/packages/p2p-media-loader-demo/src/constants.ts
index 0d09dcaa..3de1f366 100644
--- a/packages/p2p-media-loader-demo/src/constants.ts
+++ b/packages/p2p-media-loader-demo/src/constants.ts
@@ -1,6 +1,18 @@
-export const PLAYERS = ["hlsjs", "hlsjs-dplayer"] as const;
+export const PLAYERS = {
+ vidstack_hls: "Vidstack",
+ hlsjs_hls: "Hls.js",
+ dplayer_hls: "DPlayer",
+ clappr_hls: "Clappr",
+ plyr_hls: "Plyr",
+ openPlayer_hls: "OpenPlayerJS",
+ mediaElement_hls: "MediaElement",
+ shaka: "Shaka",
+ dplayer_shaka: "DPlayer",
+ clappr_shaka: "Clappr (DASH only)",
+ plyr_shaka: "Plyr",
+} as const;
export const DEFAULT_STREAM =
- "https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8";
+ "https://fcc3ddae59ed.us-west-2.playback.live-video.net/api/video/v1/us-west-2.893648527354.channel.DmumNckWFTqz.m3u8";
export const COLORS = {
yellow: "#faf21b",
lightOrange: "#ff7f0e",
@@ -8,3 +20,4 @@ export const COLORS = {
torchRed: "#ff1745",
};
export const DEFAULT_TRACKERS = `wss://tracker.webtorrent.dev,wss://tracker.files.fm:7073/announce,wss://tracker.openwebtorrent.com`;
+export const DEBUG_COMPONENT_ENABLED = "true";
diff --git a/packages/p2p-media-loader-demo/src/hooks/useQueryParams.ts b/packages/p2p-media-loader-demo/src/hooks/useQueryParams.ts
index 921c5c12..bb18c58d 100644
--- a/packages/p2p-media-loader-demo/src/hooks/useQueryParams.ts
+++ b/packages/p2p-media-loader-demo/src/hooks/useQueryParams.ts
@@ -4,33 +4,34 @@ import { DEFAULT_STREAM, DEFAULT_TRACKERS, PLAYERS } from "../constants";
type QueryParamsType = Record;
const defaultParams: QueryParamsType = {
- player: PLAYERS[0],
+ player: Object.keys(PLAYERS)[0],
streamUrl: DEFAULT_STREAM,
trackers: DEFAULT_TRACKERS,
+ debug: "",
};
+function getInitialParams(searchParams: URLSearchParams): QueryParamsType {
+ return Object.keys(defaultParams).reduce((params, key) => {
+ params[key] = searchParams.get(key) ?? defaultParams[key];
+ return params;
+ }, {} as QueryParamsType);
+}
+
export function useQueryParams() {
const searchParamsRef = useRef(new URLSearchParams(window.location.search));
- const [queryParams, setQueryParams] =
- useState(defaultParams);
+ const [queryParams, setQueryParams] = useState(() =>
+ getInitialParams(searchParamsRef.current),
+ );
const updateQueryParamsFromURL = useCallback(() => {
const searchParams = searchParamsRef.current;
- const paramsObj: QueryParamsType = {};
+ const newParams = getInitialParams(searchParams);
setQueryParams((prevParams) => {
- let hasChanges = false;
-
- Object.keys(defaultParams).forEach((key) => {
- const newValue = searchParams.get(key) ?? defaultParams[key];
- paramsObj[key] = newValue;
-
- if (prevParams[key] !== newValue) {
- hasChanges = true;
- }
- });
-
- return hasChanges ? paramsObj : prevParams;
+ const hasChanges = Object.keys(newParams).some(
+ (key) => prevParams[key] !== newParams[key],
+ );
+ return hasChanges ? newParams : prevParams;
});
}, []);
@@ -67,7 +68,6 @@ export function useQueryParams() {
updateQueryParamsFromURL();
};
- updateQueryParamsFromURL();
window.addEventListener("popstate", handlePopState);
return () => {
diff --git a/packages/p2p-media-loader-demo/src/types.ts b/packages/p2p-media-loader-demo/src/types.ts
index af21995f..bf0b7040 100644
--- a/packages/p2p-media-loader-demo/src/types.ts
+++ b/packages/p2p-media-loader-demo/src/types.ts
@@ -1,3 +1,5 @@
+import { PLAYERS } from "./constants";
+
export type DownloadStats = {
httpDownloaded: number;
p2pDownloaded: number;
@@ -12,3 +14,17 @@ export type SvgDimensionsType = {
export type ChartsData = {
seconds: number;
} & DownloadStats;
+
+export type PlayerKey = keyof typeof PLAYERS;
+export type PlayerName = (typeof PLAYERS)[PlayerKey];
+
+export type PlayerProps = {
+ streamUrl: string;
+ announceTrackers: string[];
+ onPeerConnect?: (peerId: string) => void;
+ onPeerDisconnect?: (peerId: string) => void;
+ onChunkDownloaded?: (bytesLength: number, downloadSource: string) => void;
+ onChunkUploaded?: (bytesLength: number) => void;
+};
+
+export type PlayerEvents = Omit;
diff --git a/packages/p2p-media-loader-hlsjs/src/engine-static.ts b/packages/p2p-media-loader-hlsjs/src/engine-static.ts
index 7cc3f16d..49dc7cac 100644
--- a/packages/p2p-media-loader-hlsjs/src/engine-static.ts
+++ b/packages/p2p-media-loader-hlsjs/src/engine-static.ts
@@ -1,16 +1,11 @@
-import { HlsJsP2PEngine, PartialHlsJsP2PEngineConfig } from "./engine";
+import {
+ HlsJsP2PEngine,
+ PartialHlsJsP2PEngineConfig,
+ HlsWithP2PInstance,
+ HlsWithP2PConfig,
+} from "./engine";
import { DeepReadonly } from "ts-essentials";
-type P2PConfig = {
- p2p?: DeepReadonly & {
- onHlsJsCreated?: (
- hls: T & {
- readonly p2pEngine: HlsJsP2PEngine;
- },
- ) => void;
- };
-};
-
export function injectMixin<
// eslint-disable-next-line @typescript-eslint/no-explicit-any
HlsJsConstructor extends new (...args: any[]) => any,
@@ -24,7 +19,11 @@ export function injectMixin<
// eslint-disable-next-line @typescript-eslint/no-explicit-any
constructor(...args: any[]) {
- const config = args[0] as P2PConfig>;
+ const config = args[0] as {
+ p2p?: DeepReadonly & {
+ onHlsJsCreated?: (hls: InstanceType) => void;
+ };
+ } & Record;
const { p2p, ...hlsJsConfig } = config ?? {};
@@ -38,9 +37,6 @@ export function injectMixin<
p2p?.onHlsJsCreated?.(this as InstanceType);
}
} as new (
- config?: ConstructorParameters[0] &
- P2PConfig>,
- ) => InstanceType & {
- readonly p2pEngine: HlsJsP2PEngine;
- };
+ config?: HlsWithP2PConfig,
+ ) => HlsWithP2PInstance>;
}
diff --git a/packages/p2p-media-loader-hlsjs/src/engine.ts b/packages/p2p-media-loader-hlsjs/src/engine.ts
index d5b020d7..1c0e35b6 100644
--- a/packages/p2p-media-loader-hlsjs/src/engine.ts
+++ b/packages/p2p-media-loader-hlsjs/src/engine.ts
@@ -34,6 +34,17 @@ export type DynamicHlsJsP2PEngineConfig = {
core?: DynamicCoreConfig;
};
+export type HlsWithP2PInstance = HlsType & {
+ readonly p2pEngine: HlsJsP2PEngine;
+};
+
+export type HlsWithP2PConfig unknown> =
+ ConstructorParameters[0] & {
+ p2p?: DeepReadonly & {
+ onHlsJsCreated?: (hls: HlsWithP2PInstance) => void;
+ };
+ };
+
export class HlsJsP2PEngine {
private readonly core: Core;
private readonly segmentManager: SegmentManager;
diff --git a/packages/p2p-media-loader-hlsjs/src/index.ts b/packages/p2p-media-loader-hlsjs/src/index.ts
index 1878e3d7..860e56f2 100644
--- a/packages/p2p-media-loader-hlsjs/src/index.ts
+++ b/packages/p2p-media-loader-hlsjs/src/index.ts
@@ -1,6 +1,9 @@
export { HlsJsP2PEngine } from "./engine";
+
export type {
DynamicHlsJsP2PEngineConfig,
HlsJsP2PEngineConfig,
PartialHlsJsP2PEngineConfig,
+ HlsWithP2PInstance,
+ HlsWithP2PConfig,
} from "./engine";
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index edddce2c..e7fb2b7c 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -106,18 +106,39 @@ importers:
packages/p2p-media-loader-demo:
dependencies:
+ '@vidstack/react':
+ specifier: ^1.11.21
+ version: 1.11.21(@types/react@18.2.66)(react@18.2.0)
d3:
specifier: ^7.9.0
version: 7.9.0
+ dplayer:
+ specifier: ^1.27.1
+ version: 1.27.1
hls.js:
specifier: ^1.5.7
version: 1.5.7
+ mediaelement:
+ specifier: ^7.0.5
+ version: 7.0.5
+ openplayerjs:
+ specifier: ^2.14.3
+ version: 2.14.3
p2p-media-loader-core:
specifier: workspace:*
version: link:../p2p-media-loader-core
p2p-media-loader-hlsjs:
specifier: workspace:*
version: link:../p2p-media-loader-hlsjs
+ p2p-media-loader-shaka:
+ specifier: workspace:*
+ version: link:../p2p-media-loader-shaka
+ plyr:
+ specifier: ^3.7.8
+ version: 3.7.8
+ shaka-player:
+ specifier: ^4.7.13
+ version: 4.7.13
devDependencies:
'@types/d3':
specifier: ^7.4.3
@@ -784,6 +805,13 @@ packages:
'@ungap/structured-clone@1.2.0':
resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==}
+ '@vidstack/react@1.11.21':
+ resolution: {integrity: sha512-eaMh8raSJw8L523UtmooC7IkBxMriny9X1LMk0qsJ1oZ+JGjvgLEYTPkdyLsDIJjrP4hmeeK+12kPZepHSC1pw==}
+ engines: {node: '>=18'}
+ peerDependencies:
+ '@types/react': ^18.0.0
+ react: ^18.0.0
+
'@vitejs/plugin-react@4.2.1':
resolution: {integrity: sha512-oojO9IDc4nCUUi8qIR11KoQm0XFFLIwsRBwHRR4d/88IWghn1y6ckz/bJ8GHDCsYEJee8mDzqtJxh15/cisJNQ==}
engines: {node: ^14.18.0 || >=16.0.0}
@@ -885,6 +913,11 @@ packages:
asynckit@0.4.0:
resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
+ auto-changelog@2.4.0:
+ resolution: {integrity: sha512-vh17hko1c0ItsEcw6m7qPRf3m45u+XK5QyCrrBFViElZ8jnKrPC1roSznrd1fIB/0vR/zawdECCRJtTuqIXaJw==}
+ engines: {node: '>=8.3'}
+ hasBin: true
+
available-typed-arrays@1.0.7:
resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==}
engines: {node: '>= 0.4'}
@@ -1048,6 +1081,9 @@ packages:
convert-source-map@2.0.0:
resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
+ core-js@3.37.0:
+ resolution: {integrity: sha512-fu5vHevQ8ZG4og+LXug8ulUtVxjOcEYvifJr7L5Bfq9GOztVqsKd9/59hUk2ZSbCrS3BqUr3EpaYGIYzq7g3Ug==}
+
core-util-is@1.0.3:
resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==}
@@ -1089,6 +1125,9 @@ packages:
csstype@3.1.3:
resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
+ custom-event-polyfill@1.0.7:
+ resolution: {integrity: sha512-TDDkd5DkaZxZFM8p+1I3yAlvM3rSr1wbrOliG4yJiwinMZN8z/iGL7BTlDkrJcYTmgUSb4ywVCc3ZaUtOtC76w==}
+
d3-array@3.2.4:
resolution: {integrity: sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==}
engines: {node: '>=12'}
@@ -1575,6 +1614,11 @@ packages:
graphemer@1.4.0:
resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
+ handlebars@4.7.8:
+ resolution: {integrity: sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==}
+ engines: {node: '>=0.4.7'}
+ hasBin: true
+
has-bigints@1.0.2:
resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==}
@@ -1849,6 +1893,9 @@ packages:
resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
engines: {node: '>= 0.8.0'}
+ loadjs@4.3.0:
+ resolution: {integrity: sha512-vNX4ZZLJBeDEOBvdr2v/F+0aN5oMuPu7JTqrMwp+DtgK+AryOlpy6Xtm2/HpNr+azEa828oQjOtWsB6iDtSfSQ==}
+
locate-path@6.0.0:
resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
engines: {node: '>=10'}
@@ -1882,6 +1929,13 @@ packages:
md5.js@1.3.5:
resolution: {integrity: sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==}
+ media-captions@1.0.3:
+ resolution: {integrity: sha512-y2Qi5rqjwgH97zoko1vzu5Q6nnS0KzEQSvd4NOjnFym9JqnFb5VSsUg21RNb5cQ/nhCFJ0wz/XK+2uMwFCr6TQ==}
+ engines: {node: '>=16'}
+
+ mediaelement@7.0.5:
+ resolution: {integrity: sha512-KFtaLZa7FzK3yuES/G+pL/W1OxGjaklSxdbmLgVs/Ls2JY45XPTZ4U8iOGwVr+nrytrRT0fJw73epPF6xCVvyQ==}
+
meow@12.1.1:
resolution: {integrity: sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==}
engines: {node: '>=16.10'}
@@ -1948,6 +2002,9 @@ packages:
natural-compare@1.4.0:
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
+ neo-async@2.6.2:
+ resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==}
+
nested-error-stacks@2.1.1:
resolution: {integrity: sha512-9iN1ka/9zmX1ZvLV9ewJYEk9h7RyRRtqdK0woXcqohu8EWIerfPUjYJPg0ULy0UqP7cslmdGc8xKDJcojlKiaw==}
@@ -1955,6 +2012,15 @@ packages:
resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==}
engines: {node: '>=10.5.0'}
+ node-fetch@2.7.0:
+ resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==}
+ engines: {node: 4.x || >=6.0.0}
+ peerDependencies:
+ encoding: ^0.1.0
+ peerDependenciesMeta:
+ encoding:
+ optional: true
+
node-fetch@3.3.2:
resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
@@ -2007,6 +2073,10 @@ packages:
once@1.4.0:
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
+ openplayerjs@2.14.3:
+ resolution: {integrity: sha512-1fY19ShTCNVgUaKkD+aL6Jf55jf8S2EUTZ958UwERN6qsofHRBIp3dGPjoG9jOHw/bY6zFxZKlpXx3tJgXp7YQ==}
+ engines: {node: '>=16.0.0'}
+
optionator@0.9.3:
resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==}
engines: {node: '>= 0.8.0'}
@@ -2053,6 +2123,11 @@ packages:
resolution: {integrity: sha512-CTM5kuWR3sx9IFamcl5ErfPl6ea/N8IYwiJ+vpeB2g+1iknv7zBl5uPwbMbRVznRVbrNY6lGuDoE5b30grmbqg==}
engines: {node: '>= 0.10'}
+ parse-github-url@1.0.2:
+ resolution: {integrity: sha512-kgBf6avCbO3Cn6+RnzRGLkUsv4ZVqv/VfAYkRsyBcgkshNvVBkRn1FEZcW0Jb+npXQWm2vHPnnOqFteZxRRGNw==}
+ engines: {node: '>=0.10.0'}
+ hasBin: true
+
path-browserify@1.0.1:
resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==}
@@ -2094,6 +2169,9 @@ packages:
resolution: {integrity: sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==}
engines: {node: '>=10'}
+ plyr@3.7.8:
+ resolution: {integrity: sha512-yG/EHDobwbB/uP+4Bm6eUpJ93f8xxHjjk2dYcD1Oqpe1EcuQl5tzzw9Oq+uVAzd2lkM11qZfydSiyIpiB8pgdA==}
+
possible-typed-array-names@1.0.0:
resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==}
engines: {node: '>= 0.4'}
@@ -2160,6 +2238,9 @@ packages:
randomfill@1.0.4:
resolution: {integrity: sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==}
+ rangetouch@2.0.1:
+ resolution: {integrity: sha512-sln+pNSc8NGaHoLzwNBssFSf/rSYkqeBXzX1AtJlkJiUaVSJSbRAWJk+4omsXkN+EJalzkZhWQ3th1m0FpR5xA==}
+
react-dom@18.2.0:
resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==}
peerDependencies:
@@ -2287,6 +2368,10 @@ packages:
resolution: {integrity: sha512-zHyuL/cph3xKbci/Ovba/Swyni6g3cj79cN+84BCCrD3tWR9WEBwc8svcqPIXNQX/7VYb3uwaOa+85eBQKPkMg==}
engines: {node: '>=14'}
+ shaka-player@4.7.13:
+ resolution: {integrity: sha512-PTU0lTEx1C8LdyNdZSSTea3Wf1/WT4KJzp6o07CofZqq8fzrGDiWElbir+LQIH1CTZpicO1otJQ24xjPgXz9kg==}
+ engines: {node: '>=14'}
+
shebang-command@2.0.0:
resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
engines: {node: '>=8'}
@@ -2323,6 +2408,10 @@ packages:
resolution: {integrity: sha512-9vC2SfsJzlej6MAaMPLu8HiBSHGdRAJ9hVFYN1ibZoNkeanmDmLUcIrj6G9DGL7XMJ54AKg/G75akXl1/izTOw==}
engines: {node: '>=0.10.0'}
+ source-map@0.6.1:
+ resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
+ engines: {node: '>=0.10.0'}
+
sprintf-js@1.1.3:
resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==}
@@ -2390,6 +2479,10 @@ packages:
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
engines: {node: '>= 0.4'}
+ svg4everybody@2.1.9:
+ resolution: {integrity: sha512-AS9WORVV/vk520ZHxGTlQzyDBizp/h6WyAYUbKhze/kwvQr43DwJpkIIPBomsUyKqN7N+h1deF92N9PmW+o+9A==}
+ engines: {node: '>=0.8.0'}
+
text-table@0.2.0:
resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
@@ -2405,6 +2498,9 @@ packages:
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
engines: {node: '>=8.0'}
+ tr46@0.0.3:
+ resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==}
+
ts-api-utils@1.3.0:
resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==}
engines: {node: '>=16'}
@@ -2461,6 +2557,11 @@ packages:
engines: {node: '>=14.17'}
hasBin: true
+ uglify-js@3.17.4:
+ resolution: {integrity: sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==}
+ engines: {node: '>=0.8.0'}
+ hasBin: true
+
uint8-util@2.2.4:
resolution: {integrity: sha512-uEI5lLozmKQPYEevfEhP9LY3Je5ZmrQhaWXrzTVqrLNQl36xsRh8NiAxYwB9J+2BAt99TRbmCkROQB2ZKhx4UA==}
@@ -2479,6 +2580,9 @@ packages:
uri-js@4.4.1:
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
+ url-polyfill@1.1.12:
+ resolution: {integrity: sha512-mYFmBHCapZjtcNHW0MDq9967t+z4Dmg5CJ0KqysK3+ZbyoNOWQHksGCTWwDhxGXllkWlOc10Xfko6v4a3ucM6A==}
+
url@0.11.3:
resolution: {integrity: sha512-6hxOLGfZASQK/cijlZnZJTq8OXAkt/3YGfQX45vvMYXpZoo8NdWZcY73K108Jf759lS1Bv/8wXnHDTSz17dSRw==}
@@ -2532,6 +2636,12 @@ packages:
resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==}
engines: {node: '>= 8'}
+ webidl-conversions@3.0.1:
+ resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
+
+ whatwg-url@5.0.0:
+ resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==}
+
which-boxed-primitive@1.0.2:
resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==}
@@ -2552,6 +2662,9 @@ packages:
engines: {node: '>= 8'}
hasBin: true
+ wordwrap@1.0.0:
+ resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==}
+
wrap-ansi@7.0.0:
resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
engines: {node: '>=10'}
@@ -3218,6 +3331,12 @@ snapshots:
'@ungap/structured-clone@1.2.0': {}
+ '@vidstack/react@1.11.21(@types/react@18.2.66)(react@18.2.0)':
+ dependencies:
+ '@types/react': 18.2.66
+ media-captions: 1.0.3
+ react: 18.2.0
+
'@vitejs/plugin-react@4.2.1(vite@5.1.6)':
dependencies:
'@babel/core': 7.24.0
@@ -3350,6 +3469,16 @@ snapshots:
asynckit@0.4.0: {}
+ auto-changelog@2.4.0:
+ dependencies:
+ commander: 7.2.0
+ handlebars: 4.7.8
+ node-fetch: 2.7.0
+ parse-github-url: 1.0.2
+ semver: 7.6.0
+ transitivePeerDependencies:
+ - encoding
+
available-typed-arrays@1.0.7:
dependencies:
possible-typed-array-names: 1.0.0
@@ -3566,6 +3695,8 @@ snapshots:
convert-source-map@2.0.0: {}
+ core-js@3.37.0: {}
+
core-util-is@1.0.3: {}
cp-file@10.0.0:
@@ -3641,6 +3772,8 @@ snapshots:
csstype@3.1.3: {}
+ custom-event-polyfill@1.0.7: {}
+
d3-array@3.2.4:
dependencies:
internmap: 2.0.3
@@ -4339,6 +4472,15 @@ snapshots:
graphemer@1.4.0: {}
+ handlebars@4.7.8:
+ dependencies:
+ minimist: 1.2.8
+ neo-async: 2.6.2
+ source-map: 0.6.1
+ wordwrap: 1.0.0
+ optionalDependencies:
+ uglify-js: 3.17.4
+
has-bigints@1.0.2: {}
has-flag@3.0.0: {}
@@ -4590,6 +4732,8 @@ snapshots:
prelude-ls: 1.2.1
type-check: 0.4.0
+ loadjs@4.3.0: {}
+
locate-path@6.0.0:
dependencies:
p-locate: 5.0.0
@@ -4624,6 +4768,13 @@ snapshots:
inherits: 2.0.4
safe-buffer: 5.2.1
+ media-captions@1.0.3: {}
+
+ mediaelement@7.0.5:
+ dependencies:
+ global: 4.4.0
+ svg4everybody: 2.1.9
+
meow@12.1.1: {}
merge2@1.4.1: {}
@@ -4677,10 +4828,16 @@ snapshots:
natural-compare@1.4.0: {}
+ neo-async@2.6.2: {}
+
nested-error-stacks@2.1.1: {}
node-domexception@1.0.0: {}
+ node-fetch@2.7.0:
+ dependencies:
+ whatwg-url: 5.0.0
+
node-fetch@3.3.2:
dependencies:
data-uri-to-buffer: 4.0.1
@@ -4767,6 +4924,13 @@ snapshots:
dependencies:
wrappy: 1.0.2
+ openplayerjs@2.14.3:
+ dependencies:
+ auto-changelog: 2.4.0
+ core-js: 3.37.0
+ transitivePeerDependencies:
+ - encoding
+
optionator@0.9.3:
dependencies:
'@aashutoshrathi/word-wrap': 1.2.6
@@ -4817,6 +4981,8 @@ snapshots:
pbkdf2: 3.1.2
safe-buffer: 5.2.1
+ parse-github-url@1.0.2: {}
+
path-browserify@1.0.1: {}
path-exists@4.0.0: {}
@@ -4850,6 +5016,14 @@ snapshots:
dependencies:
find-up: 5.0.0
+ plyr@3.7.8:
+ dependencies:
+ core-js: 3.37.0
+ custom-event-polyfill: 1.0.7
+ loadjs: 4.3.0
+ rangetouch: 2.0.1
+ url-polyfill: 1.1.12
+
possible-typed-array-names@1.0.0: {}
postcss@8.4.36:
@@ -4910,6 +5084,8 @@ snapshots:
randombytes: 2.1.0
safe-buffer: 5.2.1
+ rangetouch@2.0.1: {}
+
react-dom@18.2.0(react@18.2.0):
dependencies:
loose-envify: 1.4.0
@@ -5073,6 +5249,10 @@ snapshots:
dependencies:
eme-encryption-scheme-polyfill: 2.1.1
+ shaka-player@4.7.13:
+ dependencies:
+ eme-encryption-scheme-polyfill: 2.1.1
+
shebang-command@2.0.0:
dependencies:
shebang-regex: 3.0.0
@@ -5101,6 +5281,8 @@ snapshots:
source-map-js@1.1.0: {}
+ source-map@0.6.1: {}
+
sprintf-js@1.1.3: {}
stream-browserify@3.0.0:
@@ -5198,6 +5380,8 @@ snapshots:
supports-preserve-symlinks-flag@1.0.0: {}
+ svg4everybody@2.1.9: {}
+
text-table@0.2.0: {}
timers-browserify@2.0.12:
@@ -5210,6 +5394,8 @@ snapshots:
dependencies:
is-number: 7.0.0
+ tr46@0.0.3: {}
+
ts-api-utils@1.3.0(typescript@5.4.2):
dependencies:
typescript: 5.4.2
@@ -5270,6 +5456,9 @@ snapshots:
typescript@5.4.2: {}
+ uglify-js@3.17.4:
+ optional: true
+
uint8-util@2.2.4:
dependencies:
base64-arraybuffer: 1.0.2
@@ -5293,6 +5482,8 @@ snapshots:
dependencies:
punycode: 2.3.1
+ url-polyfill@1.1.12: {}
+
url@0.11.3:
dependencies:
punycode: 1.4.1
@@ -5333,6 +5524,13 @@ snapshots:
web-streams-polyfill@3.3.3: {}
+ webidl-conversions@3.0.1: {}
+
+ whatwg-url@5.0.0:
+ dependencies:
+ tr46: 0.0.3
+ webidl-conversions: 3.0.1
+
which-boxed-primitive@1.0.2:
dependencies:
is-bigint: 1.0.4
@@ -5375,6 +5573,8 @@ snapshots:
dependencies:
isexe: 2.0.0
+ wordwrap@1.0.0: {}
+
wrap-ansi@7.0.0:
dependencies:
ansi-styles: 4.3.0