diff --git a/docs/.vuepress/notes/zh/theme-guide.ts b/docs/.vuepress/notes/zh/theme-guide.ts index fcdc9e95..602550b3 100644 --- a/docs/.vuepress/notes/zh/theme-guide.ts +++ b/docs/.vuepress/notes/zh/theme-guide.ts @@ -95,6 +95,7 @@ export const themeGuide = defineNoteConfig({ 'pdf', 'bilibili', 'youtube', + 'artplayer', ], }, ], diff --git a/docs/.vuepress/theme.ts b/docs/.vuepress/theme.ts index 037e7168..bb2fd499 100644 --- a/docs/.vuepress/theme.ts +++ b/docs/.vuepress/theme.ts @@ -30,6 +30,7 @@ export const theme: Theme = plumeTheme({ caniuse: true, bilibili: true, youtube: true, + artPlayer: true, codepen: true, replit: true, codeSandbox: true, diff --git a/docs/notes/theme/guide/嵌入/artplayer.md b/docs/notes/theme/guide/嵌入/artplayer.md new file mode 100644 index 00000000..4ceed4d8 --- /dev/null +++ b/docs/notes/theme/guide/嵌入/artplayer.md @@ -0,0 +1,170 @@ +--- +title: artPlayer +icon: icon-park-outline:video +createTime: 2024/12/21 16:13:54 +permalink: /guide/embed/video/artplayer/ +--- + +## 概述 + +主题提供嵌入 自定义来源视频 的功能。 + +该功能由 [vuepress-plugin-md-power](../../config/plugins/markdownPower.md) 提供支持。 + +## 配置 + +该功能默认不启用。你需要在主题配置中开启。 + +::: code-tabs +@tab .vuepress/config.ts + +```ts +export default defineUserConfig({ + theme: plumeTheme({ + plugins: { + markdownPower: { + artPlayer: true, + }, + } + }) +}) +``` + +::: + +## 安装 + +该功能依赖于 `artplayer` 播放器实现,主题默认不安装该依赖,在启用 `artPlayer` 功能时,需要 +进行手动安装 + +::: npm-to + +```sh +npm i artplayer +``` + +::: + +artPlayer 播放器默认支持 `'mp4'`, `'mp3'`, `'webm'`, `'ogg'` 格式的视频格式。 + +同时还支持扩展其他格式的支持。 + +如果您的视频格式为 `'mpd'`, `'dash'`, 还需要再手动安装 `dashjs` : + +::: npm-to + +```sh +npm i dashjs +``` + +::: + +如果您的视频格式为 `'m3u8'`, `'hls'`, 还需要再手动安装 `hls.js` : + +::: npm-to + +```sh +npm i hls.js +``` + +::: + +如果您的视频格式为 `'ts'`, `'flv'`, 还需要再手动安装 `mpegts.js` : + +::: npm-to + +```sh +npm i mpegts.js +``` + +::: + +## markdown 语法 + +```md +@[artPlayer](src) +``` + +添加配置项: + +```md +@[artPlayer muted autoplay loop width="100%" height="400px" ratio="16:9"](src) +``` + +- `src`: 视频链接地址 + +**配置项说明:** + +- `width`: 视频宽度 +- `height`: 视频高度 +- `ratio`: 视频比例,默认 `16:9` +- `type`: 视频格式,默认从视频链接的文件地址中解析获取 +- `autoplay`: 是否自动播放 +- `muted`: 是否静音,autoplay 时,默认为 `true` +- `volume`: 音量大小,范围为 `0 - 1` +- `poster`:视频封面图链接地址 +- `auto-mini`: 当播放器滚动到浏览器视口以外时,自动进入 `迷你播放` 模式 + +## 全局组件 + +主题提供了全局组件 `` 以支持更灵活丰富的使用方式。 + +### Props + +|字段 |类型 |描述 | +| -- | -- | -- | +| src | `string` | 必填,视频播放地址 | +| type | `string` | 选填,视频格式,默认从 `src` 中截取 | +| width | `string` | 选填, 宽度, 默认 `100%` | +| height | `string` | 选填,高度 | +| ratio | `string` | 选填,宽高比,默认 `16:9` | + +更多 `Props` 请参考 [artPlayer 文档](https://artplayer.org/document/start/option.html) 主题支持所有选项。 + +## 示例 + +::: tip 说明 +示例中的视频资源来自 [artplayer.org](https://artplayer.org) 。 +::: + +**输入:** + +```md +@[artPlayer](https://artplayer.org/assets/sample/video.mp4) +``` + +**输出:** + +@[artPlayer](https://artplayer.org/assets/sample/video.mp4) + +**输入:** + +```md + +``` + +**输出:** + + + +## 说明 + +markdown 语法 `@[artPlayer](src)` 在主题内部转换为了 `` 组件,它等价于 + +```md + +``` diff --git a/docs/notes/theme/guide/嵌入/bilibili.md b/docs/notes/theme/guide/嵌入/bilibili.md index aa5dd7d8..8dd14ea9 100644 --- a/docs/notes/theme/guide/嵌入/bilibili.md +++ b/docs/notes/theme/guide/嵌入/bilibili.md @@ -1,6 +1,5 @@ --- title: Bilibili 视频 -author: pengzhanbo icon: ri:bilibili-fill createTime: 2024/03/28 12:26:47 permalink: /guide/embed/video/bilibili/ @@ -8,11 +7,9 @@ permalink: /guide/embed/video/bilibili/ ## 概述 -有时候,你想在你的文档中嵌入视频,以提高内容的表达能力。 - 主题提供了 嵌入 Bilibili 视频 的功能。 -该功能由 [vuepress-plugin-md-power](/) 提供支持。 +该功能由 [vuepress-plugin-md-power](../../config/plugins/markdownPower.md) 提供支持。 ## 配置 diff --git a/docs/notes/theme/guide/嵌入/youtube.md b/docs/notes/theme/guide/嵌入/youtube.md index e7c41205..a8f8ddca 100644 --- a/docs/notes/theme/guide/嵌入/youtube.md +++ b/docs/notes/theme/guide/嵌入/youtube.md @@ -1,6 +1,5 @@ --- title: Youtube 视频 -author: pengzhanbo icon: mdi:youtube createTime: 2024/03/28 14:30:33 permalink: /guide/embed/video/youtube/ @@ -8,11 +7,9 @@ permalink: /guide/embed/video/youtube/ ## 概述 -有时候,你想在你的文档中嵌入视频,以提高内容的表达能力。 - 主题提供了 嵌入 Youtube 视频 的功能。 -该功能由 [vuepress-plugin-md-power](/) 提供支持。 +该功能由 [vuepress-plugin-md-power](../../config/plugins/markdownPower.md) 提供支持。 ## 配置 diff --git a/plugins/plugin-md-power/__test__/__snapshots__/artPlayerPlugin.spec.ts.snap b/plugins/plugin-md-power/__test__/__snapshots__/artPlayerPlugin.spec.ts.snap new file mode 100644 index 00000000..3d7704a8 --- /dev/null +++ b/plugins/plugin-md-power/__test__/__snapshots__/artPlayerPlugin.spec.ts.snap @@ -0,0 +1,10 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`artPlayerPlugin > should not work 1`] = ` +"

@[artPlayer]xxx

+

@[ artPlayer]123456

+

@ artPlayer

+" +`; + +exports[`artPlayerPlugin > should work 1`] = `""`; diff --git a/plugins/plugin-md-power/__test__/artPlayerPlugin.spec.ts b/plugins/plugin-md-power/__test__/artPlayerPlugin.spec.ts new file mode 100644 index 00000000..b92debe0 --- /dev/null +++ b/plugins/plugin-md-power/__test__/artPlayerPlugin.spec.ts @@ -0,0 +1,46 @@ +import MarkdownIt from 'markdown-it' +import { describe, expect, it } from 'vitest' +import { artPlayerPlugin } from '../src/node/embed/video/artPlayer.js' + +function createMarkdown() { + return MarkdownIt().use((md) => { + md.block.ruler.before('code', 'import_code', () => false) + md.renderer.rules.import_code = () => '' + }).use(artPlayerPlugin) +} + +describe('artPlayerPlugin', () => { + it('should work', () => { + const md = createMarkdown() + const code = `\ +@[artPlayer](/xxx.mp4) + +@[artPlayer loop autoplay](/xxx.m3u8) + +@[artPlayer autoplay muted volume="0.55"](/xxx.flv) + +@[artPlayer width="100%" height="600px" ratio="16:9" auto-mini poster="xx.jpg"](/xxx.mpd) + +@[artPlayer type="mp3"](/xxx) +` + + expect(md.render(code)).toMatchSnapshot() + }) + + it('should not work', () => { + const md = createMarkdown() + const code = `\ +@[artPlayer]() + +@[artPlayer]xxx + +@[ artPlayer]123456 + +@[ artPlayer](/xxx.mp4) + +@[artPlayer type="xxx"](/xxx.xxx) +` + + expect(md.render(code)).toMatchSnapshot() + }) +}) diff --git a/plugins/plugin-md-power/package.json b/plugins/plugin-md-power/package.json index a16d3b83..03c5da66 100644 --- a/plugins/plugin-md-power/package.json +++ b/plugins/plugin-md-power/package.json @@ -37,12 +37,28 @@ "tsup": "tsup --config tsup.config.ts" }, "peerDependencies": { + "artplayer": "^5.2.0", + "dashjs": "^4.7.4", + "hls.js": "^1.5.18", "markdown-it": "^14.0.0", + "mpegts.js": "^1.7.3", "vuepress": "catalog:" }, "peerDependenciesMeta": { + "artplayer": { + "optional": true + }, + "dashjs": { + "optional": true + }, + "hls.js": { + "optional": true + }, "markdown-it": { "optional": true + }, + "mpegts.js": { + "optional": true } }, "dependencies": { @@ -65,7 +81,11 @@ "vue": "catalog:" }, "devDependencies": { - "@types/markdown-it": "^14.1.2" + "@types/markdown-it": "^14.1.2", + "artplayer": "^5.2.1", + "dashjs": "^4.7.4", + "hls.js": "^1.5.18", + "mpegts.js": "^1.7.3" }, "publishConfig": { "access": "public" diff --git a/plugins/plugin-md-power/src/client/components/ArtPlayer.vue b/plugins/plugin-md-power/src/client/components/ArtPlayer.vue new file mode 100644 index 00000000..6528c126 --- /dev/null +++ b/plugins/plugin-md-power/src/client/components/ArtPlayer.vue @@ -0,0 +1,155 @@ + + + + + diff --git a/plugins/plugin-md-power/src/client/options.ts b/plugins/plugin-md-power/src/client/options.ts index 10c4b9a0..7536d90c 100644 --- a/plugins/plugin-md-power/src/client/options.ts +++ b/plugins/plugin-md-power/src/client/options.ts @@ -1,5 +1,28 @@ import type { MarkdownPowerPluginOptions } from '../shared/index.js' declare const __MD_POWER_INJECT_OPTIONS__: MarkdownPowerPluginOptions +declare const __MD_POWER_DASHJS_INSTALLED__: boolean +declare const __MD_POWER_HLSJS_INSTALLED__: boolean +declare const __MD_POWER_MPEGTSJS_INSTALLED__: boolean export const pluginOptions = __MD_POWER_INJECT_OPTIONS__ + +export const installed = { + dashjs: __MD_POWER_DASHJS_INSTALLED__, + hlsjs: __MD_POWER_HLSJS_INSTALLED__, + mpegtsjs: __MD_POWER_MPEGTSJS_INSTALLED__, +} + +export const ART_PLAYER_SUPPORTED_VIDEO_TYPES = ['mp4', 'mp3', 'webm', 'ogg'] + +if (installed.dashjs) { + ART_PLAYER_SUPPORTED_VIDEO_TYPES.push('mpd', 'dash') +} + +if (installed.hlsjs) { + ART_PLAYER_SUPPORTED_VIDEO_TYPES.push('m3u8', 'hls') +} + +if (installed.mpegtsjs) { + ART_PLAYER_SUPPORTED_VIDEO_TYPES.push('ts', 'flv') +} diff --git a/plugins/plugin-md-power/src/node/embed/index.ts b/plugins/plugin-md-power/src/node/embed/index.ts index 5760312a..d7dceb26 100644 --- a/plugins/plugin-md-power/src/node/embed/index.ts +++ b/plugins/plugin-md-power/src/node/embed/index.ts @@ -6,6 +6,7 @@ import { codeSandboxPlugin } from './code/codeSandbox.js' import { jsfiddlePlugin } from './code/jsfiddle.js' import { replitPlugin } from './code/replit.js' import { pdfPlugin } from './pdf.js' +import { artPlayerPlugin } from './video/artPlayer.js' import { bilibiliPlugin } from './video/bilibili.js' import { youtubePlugin } from './video/youtube.js' @@ -33,6 +34,11 @@ export function embedSyntaxPlugin(md: Markdown, options: MarkdownPowerPluginOpti md.use(youtubePlugin) } + if (options.artPlayer) { + // @[artPlayer](url) + md.use(artPlayerPlugin) + } + if (options.codepen) { // @[codepen](user/slash) md.use(codepenPlugin) diff --git a/plugins/plugin-md-power/src/node/embed/video/artPlayer.ts b/plugins/plugin-md-power/src/node/embed/video/artPlayer.ts new file mode 100644 index 00000000..6d88a442 --- /dev/null +++ b/plugins/plugin-md-power/src/node/embed/video/artPlayer.ts @@ -0,0 +1,97 @@ +/** + * @[artPlayer](url) + * @[artPlayer muted autoplay autoMini loop volume=1 poster="xxxx"](url) + */ +import type { PluginWithOptions } from 'markdown-it' +import type { ArtPlayerTokenMeta } from '../../../shared/index.js' +import { isPackageExists } from 'local-pkg' +import { colors } from 'vuepress/utils' +import { parseRect } from '../../utils/parseRect.js' +import { resolveAttrs } from '../../utils/resolveAttrs.js' +import { createEmbedRuleBlock } from '../createEmbedRuleBlock.js' + +const installed = { + dashjs: isPackageExists('dashjs'), + hlsjs: isPackageExists('hls.js'), + mpegtsjs: isPackageExists('mpegts.js'), +} + +const SUPPORTED_VIDEO_TYPES = ['mp4', 'mp3', 'webm', 'ogg', 'mpd', 'dash', 'm3u8', 'hls', 'ts', 'flv'] + +export const artPlayerPlugin: PluginWithOptions = (md) => { + createEmbedRuleBlock(md, { + type: 'artPlayer', + name: 'video_artPlayer', + syntaxPattern: /^@\[artPlayer([^\]]*)\]\(([^)]*)\)/, + meta([, info, source]) { + const { attrs } = resolveAttrs(info) + const url = source.trim() + checkSupportType(attrs.type ?? url.split('.').pop()) + + return { + autoplay: attrs.autoplay ?? false, + muted: attrs.muted ?? attrs.autoplay ?? false, + autoMini: attrs.autoMini ?? false, + loop: attrs.loop ?? false, + volume: typeof attrs.volume !== 'undefined' ? Number(attrs.volume) : 0.75, + poster: attrs.poster, + width: attrs.width ? parseRect(attrs.width) : '100%', + height: attrs.height ? parseRect(attrs.height) : '', + ratio: attrs.ratio ? parseRect(`${attrs.ratio}`) : '', + type: attrs.type, + url, + } + }, + content({ autoMini, autoplay, loop, muted, poster, url, type, volume, width, height, ratio }) { + return `` + }, + }) +} + +function checkSupportType(type?: string) { + if (!type) + return + + /* istanbul ignore if -- @preserve */ + if (SUPPORTED_VIDEO_TYPES.includes(type)) { + let name = '' + switch (type.toLowerCase()) { + case 'm3u8': + case 'hls': + name = !installed.hlsjs ? 'hls.js' : '' + break + + case 'flv': + case 'ts': { + name = !installed.mpegtsjs ? 'mpegts.js' : '' + break + } + case 'mpd': + case 'dash': + name = !installed.dashjs ? 'dashjs' : '' + break + } + /* istanbul ignore if -- @preserve */ + if (name) { + console.warn(`${colors.yellow('[vuepress-plugin-md-power] artPlayer: ')} ${colors.cyan(name)} is not installed, please install it via npm or yarn or pnpm`) + } + } + else { + /* istanbul ignore next -- @preserve */ + console.warn(`${colors.yellow('[vuepress-plugin-md-power] artPlayer: ')} unsupported video type: ${colors.cyan(type)}`) + } +} diff --git a/plugins/plugin-md-power/src/node/plugin.ts b/plugins/plugin-md-power/src/node/plugin.ts index f7b16333..b4b002ac 100644 --- a/plugins/plugin-md-power/src/node/plugin.ts +++ b/plugins/plugin-md-power/src/node/plugin.ts @@ -1,6 +1,7 @@ import type { Plugin } from 'vuepress/core' import type { MarkdownPowerPluginOptions } from '../shared/index.js' import { addViteOptimizeDepsInclude } from '@vuepress/helper' +import { isPackageExists } from 'local-pkg' import { containerPlugin } from './container/index.js' import { embedSyntaxPlugin } from './embed/index.js' import { docsTitlePlugin } from './enhance/docsTitle.js' @@ -18,6 +19,9 @@ export function markdownPowerPlugin( define: { __MD_POWER_INJECT_OPTIONS__: options, + __MD_POWER_DASHJS_INSTALLED__: isPackageExists('dashjs'), + __MD_POWER_HLSJS_INSTALLED__: isPackageExists('hls.js'), + __MD_POWER_MPEGTSJS_INSTALLED__: isPackageExists('mpegts.js'), }, extendsBundlerOptions(bundlerOptions, app) { @@ -28,6 +32,13 @@ export function markdownPowerPlugin( ['shiki/core', 'shiki/wasm', 'shiki/engine/oniguruma'], ) } + if (options.artPlayer) { + addViteOptimizeDepsInclude( + bundlerOptions, + app, + ['artplayer', 'dashjs', 'hls.js', 'mpegts.js'], + ) + } }, extendsMarkdown: async (md, app) => { diff --git a/plugins/plugin-md-power/src/node/prepareConfigFile.ts b/plugins/plugin-md-power/src/node/prepareConfigFile.ts index 72f2da5e..c47c8c20 100644 --- a/plugins/plugin-md-power/src/node/prepareConfigFile.ts +++ b/plugins/plugin-md-power/src/node/prepareConfigFile.ts @@ -65,6 +65,11 @@ export async function prepareConfigFile(app: App, options: MarkdownPowerPluginOp enhances.add(`app.component('FileTreeItem', FileTreeItem)`) } + if (options.artPlayer) { + imports.add(`import ArtPlayer from '${CLIENT_FOLDER}components/ArtPlayer.vue'`) + enhances.add(`app.component('ArtPlayer', ArtPlayer)`) + } + return app.writeTemp( 'md-power/config.js', `\ diff --git a/plugins/plugin-md-power/src/shared/plugin.ts b/plugins/plugin-md-power/src/shared/plugin.ts index 6168af82..60fb9c0a 100644 --- a/plugins/plugin-md-power/src/shared/plugin.ts +++ b/plugins/plugin-md-power/src/shared/plugin.ts @@ -63,6 +63,13 @@ export interface MarkdownPowerPluginOptions { */ youtube?: boolean + /** + * 是否启用 artPlayer 视频嵌入 + * + * `@[artPlayer](url)` + */ + artPlayer?: boolean + // code embed /** * 是否启用 codepen 嵌入 diff --git a/plugins/plugin-md-power/src/shared/video.ts b/plugins/plugin-md-power/src/shared/video.ts index f04fa371..4d262571 100644 --- a/plugins/plugin-md-power/src/shared/video.ts +++ b/plugins/plugin-md-power/src/shared/video.ts @@ -23,3 +23,14 @@ export interface YoutubeTokenMeta extends SizeOptions { start?: string | number end?: string | number } + +export interface ArtPlayerTokenMeta extends SizeOptions { + muted?: boolean + autoplay?: boolean + autoMini?: boolean + loop?: boolean + volume?: number // 0-1 + poster?: string + url: string + type?: string +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 01fd5015..9a0ded3a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -325,6 +325,18 @@ importers: '@types/markdown-it': specifier: ^14.1.2 version: 14.1.2 + artplayer: + specifier: ^5.2.1 + version: 5.2.1 + dashjs: + specifier: ^4.7.4 + version: 4.7.4 + hls.js: + specifier: ^1.5.18 + version: 1.5.18 + mpegts.js: + specifier: ^1.7.3 + version: 1.7.3 plugins/plugin-search: dependencies: @@ -2610,6 +2622,9 @@ packages: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} engines: {node: '>=8'} + artplayer@5.2.1: + resolution: {integrity: sha512-xhNE9zSLT2z4O2CJwcMSWADsS3Cvq0PwNanvMzRsqgfUhsMOpum8HlMtIUPOTyMGjIhKV8sl109HFUalQK6WJQ==} + assertion-error@2.0.1: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} @@ -2654,6 +2669,15 @@ packages: resolution: {integrity: sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==} engines: {node: '>= 0.8'} + bcp-47-match@1.0.3: + resolution: {integrity: sha512-LggQ4YTdjWQSKELZF5JwchnBa1u0pIQSZf5lSdOHEdbVP55h0qICA/FUp3+W99q0xqxYa1ZQizTUH87gecII5w==} + + bcp-47-normalize@1.1.1: + resolution: {integrity: sha512-jWZ1Jdu3cs0EZdfCkS0UE9Gg01PtxnChjEBySeB+Zo6nkqtFfnvtoQQgP1qU1Oo4qgJgxhTI6Sf9y/pZIhPs0A==} + + bcp-47@1.0.8: + resolution: {integrity: sha512-Y9y1QNBBtYtv7hcmoX0tR+tUNSFZGZ6OL6vKPObq8BbOhkCoyayF6ogfLTgAli/KuAEbsYHYUNq2AQuY6IuLag==} + bcrypt-ts@5.0.3: resolution: {integrity: sha512-2FcgD12xPbwCoe5i9/HK0jJ1xA1m+QfC1e6htG9Bl/hNOnLyaFmQSlqLKcfe3QdnoMPKpKEGFCbESBTg+SJNOw==} engines: {node: '>=18'} @@ -2843,6 +2867,9 @@ packages: resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} engines: {node: '>=0.8'} + codem-isoboxer@0.3.9: + resolution: {integrity: sha512-4XOTqEzBWrGOZaMd+sTED2hLpzfBbiQCf1W6OBGkIHqk1D8uwy8WFLazVbdQwfDpQ+vf39lqTGPa9IhWW0roTA==} + color-convert@1.9.3: resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} @@ -2908,7 +2935,7 @@ packages: resolution: {integrity: sha512-7CEBgcMjVmitjYo5q8JTJVra6X5mQ20uTThdK+0kR7UEaDrAWEQcRiBtWJzga4eRpP6afNwwLsX2SET2JhVB1Q==} concat-map@0.0.1: - resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=} + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} confbox@0.1.7: resolution: {integrity: sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==} @@ -3263,6 +3290,9 @@ packages: resolution: {integrity: sha512-wAV9QHOsNbwnWdNW2FYvE1P56wtgSbM+3SZcdGiWQILwVjACCXDCI3Ai8QlCjMDB8YK5zySiXZYBiwGmNY3lnw==} engines: {node: '>=12'} + dashjs@4.7.4: + resolution: {integrity: sha512-+hldo25QPP3H/NOwqUrvt4uKdMse60/Gsz9AUAnoYfhga8qHWq4nWiojUosOiigbigkDTCAn9ORcvUaKCvmfCA==} + dayjs@1.11.13: resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==} @@ -3446,6 +3476,9 @@ packages: es-module-lexer@1.5.4: resolution: {integrity: sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==} + es6-promise@4.2.8: + resolution: {integrity: sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==} + esbuild@0.24.0: resolution: {integrity: sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==} engines: {node: '>=18'} @@ -3667,7 +3700,7 @@ packages: engines: {node: '>=0.10.0'} eve-raphael@0.5.0: - resolution: {integrity: sha1-F8dUt5K+7z+maE15z1pHxjxM2jA=} + resolution: {integrity: sha512-jrxnPsCGqng1UZuEp9DecX/AuSyAszATSjf4oEcRxvfxa1Oux4KkIPKBAAWWnpdwfARtr+Q0o9aPYWjsROD7ug==} eventemitter3@4.0.7: resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} @@ -3699,6 +3732,9 @@ packages: resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} engines: {node: '>=4'} + fast-deep-equal@2.0.1: + resolution: {integrity: sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w==} + fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} @@ -3910,7 +3946,7 @@ packages: engines: {node: '>=10.13.0'} glob2base@0.0.12: - resolution: {integrity: sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=} + resolution: {integrity: sha512-ZyqlgowMbfj2NPjxaZZ/EtsXlOch28FRXgMd64vqZWk1bT9+wvSRLYD1om9M7QfQru51zJPAT17qXm4/zd+9QA==} engines: {node: '>= 0.10'} glob@10.4.5: @@ -4030,6 +4066,9 @@ packages: resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} hasBin: true + hls.js@1.5.18: + resolution: {integrity: sha512-znxR+2jecWluu/0KOBqUcvVyAB5tLff10vjMGrpAlz1eFY+ZhF1bY3r82V+Bk7WJdk03iTjtja9KFFz5BrqjSA==} + homedir-polyfill@1.0.3: resolution: {integrity: sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==} engines: {node: '>=0.10.0'} @@ -4048,6 +4087,9 @@ packages: resolution: {integrity: sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==} engines: {node: '>=12'} + html-entities@1.4.0: + resolution: {integrity: sha512-8nxjcBcd8wovbeKx7h3wTji4e6+rhaVuPNpMqwWgnHh+N9ToqsCs6XztWRBPQ+UtzsoMAdKZtUENoVzU/EMtZA==} + html-escaper@2.0.2: resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} @@ -4114,6 +4156,9 @@ packages: engines: {node: '>=16.x'} hasBin: true + immediate@3.0.6: + resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==} + immutable@5.0.2: resolution: {integrity: sha512-1NU7hWZDkV7hJ4PJ9dur9gTNQ4ePNPN4k9/0YhwjzykTi/+3Q5pF93YU5QoVj8BuOnhLgaY8gs0U2pj4kSYVcw==} @@ -4124,6 +4169,9 @@ packages: import-meta-resolve@4.1.0: resolution: {integrity: sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==} + imsc@1.1.5: + resolution: {integrity: sha512-V8je+CGkcvGhgl2C1GlhqFFiUOIEdwXbXLiu1Fcubvvbo+g9inauqT3l0pNYXGoLPBj3jxtZz9t+wCopMkwadQ==} + imurmurhash@0.1.4: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} @@ -4161,6 +4209,12 @@ packages: resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==} engines: {node: '>=12'} + is-alphabetical@1.0.4: + resolution: {integrity: sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==} + + is-alphanumerical@1.0.4: + resolution: {integrity: sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==} + is-arrayish@0.2.1: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} @@ -4176,6 +4230,9 @@ packages: resolution: {integrity: sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==} engines: {node: '>= 0.4'} + is-decimal@1.0.4: + resolution: {integrity: sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==} + is-extendable@0.1.1: resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} engines: {node: '>=0.10.0'} @@ -4415,6 +4472,9 @@ packages: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} + lie@3.1.1: + resolution: {integrity: sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==} + lilconfig@3.1.2: resolution: {integrity: sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==} engines: {node: '>=14'} @@ -4455,6 +4515,9 @@ packages: resolution: {integrity: sha512-9rrA30MRRP3gBD3HTGnC6cDFpaE1kVDWxWgqWJUN0RvDNAo+Nz/9GxB+nHOH0ifbVFy0hSA1V6vFDvnx54lTEQ==} engines: {node: '>=14'} + localforage@1.10.0: + resolution: {integrity: sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==} + locate-path@5.0.0: resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} engines: {node: '>=8'} @@ -4831,6 +4894,9 @@ packages: mlly@1.7.3: resolution: {integrity: sha512-xUsx5n/mN0uQf4V548PKQ+YShA4/IW0KI1dZhrNrPCLG+xizETbHTkOa1f8/xut9JRPp8kQuMnz0oqwkTiLo/A==} + mpegts.js@1.7.3: + resolution: {integrity: sha512-kqZ1C1IsbAQN72cK8vMrzKeM7hwrwSBbFAwVAc7PPweOeoZxCANrc7fAVDKMfYUzxdNkMTnec9tVmlxmKZB0TQ==} + ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} @@ -4939,6 +5005,9 @@ packages: resolution: {integrity: sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==} hasBin: true + option-validator@2.0.6: + resolution: {integrity: sha512-tmZDan2LRIRQyhUGvkff68/O0R8UmF+Btmiiz0SmSw2ng3CfPZB9wJlIjHpe/MKUZqyIZkVIXCrwr1tIN+0Dzg==} + optionator@0.9.4: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} @@ -5672,6 +5741,9 @@ packages: engines: {node: '>=14.0.0'} hasBin: true + sax@1.2.1: + resolution: {integrity: sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA==} + sax@1.4.1: resolution: {integrity: sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==} @@ -6195,6 +6267,10 @@ packages: engines: {node: '>=14.17'} hasBin: true + ua-parser-js@1.0.39: + resolution: {integrity: sha512-k24RCVWlEcjkdOxYmVJgeD/0a1TiSpqLg+ZalVGV9lsnr4yqu0w7tX/x2xX6G4zpkgQnRf89lxuZ1wsbjXM8lw==} + hasBin: true + uc.micro@2.1.0: resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==} @@ -6505,6 +6581,9 @@ packages: webidl-conversions@4.0.2: resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==} + webworkify-webpack@2.1.5: + resolution: {integrity: sha512-2akF8FIyUvbiBBdD+RoHpoTbHMQF2HwjcxfDvgztAX5YwbZNyrtfUMgvfgFVsgDhDPVTlkbb5vyasqDHfIDPQw==} + whatwg-encoding@2.0.0: resolution: {integrity: sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==} engines: {node: '>=12'} @@ -8914,6 +8993,10 @@ snapshots: array-union@2.1.0: {} + artplayer@5.2.1: + dependencies: + option-validator: 2.0.6 + assertion-error@2.0.1: {} astral-regex@2.0.0: {} @@ -8956,6 +9039,19 @@ snapshots: dependencies: safe-buffer: 5.1.2 + bcp-47-match@1.0.3: {} + + bcp-47-normalize@1.1.1: + dependencies: + bcp-47: 1.0.8 + bcp-47-match: 1.0.3 + + bcp-47@1.0.8: + dependencies: + is-alphabetical: 1.0.4 + is-alphanumerical: 1.0.4 + is-decimal: 1.0.4 + bcrypt-ts@5.0.3: {} binary-extensions@2.3.0: {} @@ -9180,6 +9276,8 @@ snapshots: clone@1.0.4: {} + codem-isoboxer@0.3.9: {} + color-convert@1.9.3: dependencies: color-name: 1.1.3 @@ -9658,6 +9756,19 @@ snapshots: dargs@8.1.0: {} + dashjs@4.7.4: + dependencies: + bcp-47-match: 1.0.3 + bcp-47-normalize: 1.1.1 + codem-isoboxer: 0.3.9 + es6-promise: 4.2.8 + fast-deep-equal: 2.0.1 + html-entities: 1.4.0 + imsc: 1.1.5 + localforage: 1.10.0 + path-browserify: 1.0.1 + ua-parser-js: 1.0.39 + dayjs@1.11.13: {} de-indent@1.0.2: {} @@ -9804,6 +9915,8 @@ snapshots: es-module-lexer@1.5.4: {} + es6-promise@4.2.8: {} + esbuild@0.24.0: optionalDependencies: '@esbuild/aix-ppc64': 0.24.0 @@ -10181,6 +10294,8 @@ snapshots: iconv-lite: 0.4.24 tmp: 0.0.33 + fast-deep-equal@2.0.1: {} + fast-deep-equal@3.1.3: {} fast-glob@3.3.2: @@ -10553,6 +10668,8 @@ snapshots: he@1.2.0: {} + hls.js@1.5.18: {} + homedir-polyfill@1.0.3: dependencies: parse-passwd: 1.0.0 @@ -10569,6 +10686,8 @@ snapshots: dependencies: whatwg-encoding: 2.0.0 + html-entities@1.4.0: {} + html-escaper@2.0.2: {} html-tags@3.3.1: {} @@ -10642,6 +10761,8 @@ snapshots: dependencies: queue: 6.0.2 + immediate@3.0.6: {} + immutable@5.0.2: {} import-fresh@3.3.0: @@ -10651,6 +10772,10 @@ snapshots: import-meta-resolve@4.1.0: {} + imsc@1.1.5: + dependencies: + sax: 1.2.1 + imurmurhash@0.1.4: {} indent-string@4.0.0: {} @@ -10690,6 +10815,13 @@ snapshots: internmap@2.0.3: {} + is-alphabetical@1.0.4: {} + + is-alphanumerical@1.0.4: + dependencies: + is-alphabetical: 1.0.4 + is-decimal: 1.0.4 + is-arrayish@0.2.1: {} is-binary-path@2.1.0: @@ -10704,6 +10836,8 @@ snapshots: dependencies: hasown: 2.0.2 + is-decimal@1.0.4: {} + is-extendable@0.1.1: {} is-extglob@2.1.1: {} @@ -10902,6 +11036,10 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 + lie@3.1.1: + dependencies: + immediate: 3.0.6 + lilconfig@3.1.2: {} lilconfig@3.1.3: {} @@ -10959,6 +11097,10 @@ snapshots: mlly: 1.7.3 pkg-types: 1.2.1 + localforage@1.10.0: + dependencies: + lie: 3.1.1 + locate-path@5.0.0: dependencies: p-locate: 4.1.0 @@ -11508,6 +11650,11 @@ snapshots: pkg-types: 1.2.1 ufo: 1.5.4 + mpegts.js@1.7.3: + dependencies: + es6-promise: 4.2.8 + webworkify-webpack: 2.1.5 + ms@2.1.3: {} muggle-string@0.4.1: {} @@ -11608,6 +11755,10 @@ snapshots: opener@1.5.2: {} + option-validator@2.0.6: + dependencies: + kind-of: 6.0.3 + optionator@0.9.4: dependencies: deep-is: 0.1.4 @@ -12297,6 +12448,8 @@ snapshots: optionalDependencies: '@parcel/watcher': 2.4.1 + sax@1.2.1: {} + sax@1.4.1: {} scslre@0.3.0: @@ -12821,6 +12974,8 @@ snapshots: typescript@5.7.2: {} + ua-parser-js@1.0.39: {} + uc.micro@2.1.0: {} ufo@1.5.4: {} @@ -13125,6 +13280,8 @@ snapshots: webidl-conversions@4.0.2: {} + webworkify-webpack@2.1.5: {} + whatwg-encoding@2.0.0: dependencies: iconv-lite: 0.6.3