Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .agents/skills/implement-spf-use-case/references/workflow.md
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@ After Step 1's report:
- **HTML custom element** — `packages/html/src/media/<key>-video/`
(~5 LOC; wraps the media host in `CustomMediaElement` +
`MediaAttachMixin`) + `packages/html/src/define/media/<key>-video.ts`
+ `packages/html/src/cdn/media/<key>-video.ts` for the CDN entry.
+ `packages/cdn/src/media/<key>-video.ts` for the CDN entry.
Worked example: `hls-video/media.ts` →
`class HlsVideo extends MediaAttachMixin(CustomMediaElement('video', HlsVideoMedia)) {}`.
- **React component** — `packages/react/src/media/<key>-video/`
Expand Down Expand Up @@ -444,7 +444,7 @@ typical for use-case implementations:
- **HTML custom element + define entry + CDN entry** —
`packages/html/src/media/<key>-video/media.ts`,
`packages/html/src/define/media/<key>-video.ts`,
`packages/html/src/cdn/media/<key>-video.ts`. Inline implementation;
`packages/cdn/src/media/<key>-video.ts`. Inline implementation;
~5 LOC + boilerplate.
- **React component** — `packages/react/src/media/<key>-video/media.tsx`
exposing the props surface; ~37 LOC. Inline implementation.
Expand Down
1 change: 1 addition & 0 deletions .github/release-please/.release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"packages/cdn": "10.0.0-beta.32",
"packages/cli": "10.0.0-beta.32",
"packages/cloudflare-video": "10.0.0-beta.32",
"packages/core": "10.0.0-beta.32",
Expand Down
7 changes: 7 additions & 0 deletions .github/release-please/release-please-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"type": "linked-versions",
"groupName": "videojs",
"components": [
"@videojs/cdn",
"@videojs/cli",
"@videojs/cloudflare-video",
"@videojs/core",
Expand Down Expand Up @@ -43,6 +44,12 @@
}
],
"packages": {
"packages/cdn": {
"component": "@videojs/cdn",
"prerelease": true,
"prerelease-type": "beta",
"versioning": "prerelease"
},
"packages/cli": {
"component": "@videojs/cli",
"prerelease": true,
Expand Down
46 changes: 18 additions & 28 deletions .github/workflows/cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,13 @@ jobs:
id-token: write

steps:
# release-please needs a token other than GITHUB_TOKEN so the release
# branch push, the release PR, and the published releases still trigger
# release-pr.yml, CI, and changelog-prose.yml
# (see https://github.com/peter-evans/create-pull-request/issues/48).
# A GitHub App installation token attributes the release PRs and tags to
# the app's bot user rather than a maintainer.
- uses: actions/create-github-app-token@v2
id: app-token
with:
app-id: ${{ vars.RELEASE_APP_ID }}
private-key: ${{ secrets.RELEASE_APP_PRIVATE_KEY }}

- uses: googleapis/release-please-action@v4
id: release
with:
token: ${{ steps.app-token.outputs.token }}
# Use a fine grained token for release-please so this workflow
# can trigger other workflows like release-pr.yml
# see https://github.com/peter-evans/create-pull-request/issues/48
token: ${{ secrets.V10_WORKFLOW_TRIGGER_WORKFLOW_GH_TOKEN }}
config-file: .github/release-please/release-please-config.json
manifest-file: .github/release-please/.release-please-manifest.json

Expand All @@ -51,8 +42,8 @@ jobs:
fetch-depth: 0 # Fetch all history for all tags and branches
# release-please creates the tags while this job is running, so the
# triggering SHA is still the commit before the release PR. Build the
# exact commit tagged for @videojs/html instead.
ref: ${{ steps.release.outputs['packages/html--sha'] }}
# exact commit tagged for @videojs/cdn instead.
ref: ${{ steps.release.outputs['packages/cdn--sha'] }}

- name: Setup pnpm
if: ${{ steps.release.outputs.releases_created == 'true' }}
Expand All @@ -70,10 +61,9 @@ jobs:

- name: Verify release checkout
if: ${{ steps.release.outputs.releases_created == 'true' }}
run: |
node -e "process.exit(require('./packages/html/package.json').version === process.env.VERSION ? 0 : 1)"
run: node -e "process.exit(require('./packages/cdn/package.json').version === process.env.VERSION ? 0 : 1)"
env:
VERSION: ${{ steps.release.outputs['packages/html--version'] }}
VERSION: ${{ steps.release.outputs['packages/cdn--version'] }}

- name: Restore Vite Task cache
if: ${{ steps.release.outputs.releases_created == 'true' }}
Expand All @@ -100,11 +90,11 @@ jobs:
# CDN at runtime, which would break self-hosted and archive installs.
- name: Check CDN bundles are self-contained
if: ${{ steps.release.outputs.releases_created == 'true' }}
run: pnpm -F @videojs/html check:cdn
run: pnpm -F @videojs/cdn check:cdn

- name: Build distribution archive
if: ${{ steps.release.outputs.releases_created == 'true' }}
run: pnpm -F @videojs/html build:archive
run: pnpm -F @videojs/cdn build:archive

# The site build emits per-framework markdown to site/dist/docs/framework/{html,react}/.
# The @videojs/html and @videojs/react packages' prepack scripts (fired by `pnpm publish`
Expand All @@ -124,26 +114,26 @@ jobs:
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

# Attach the archive to the @videojs/html release so installers outside npm
# Attach the archive to the @videojs/cdn release so installers outside npm
# (Composer, Drupal) have a stable, versioned download. Use the outputs from
# the release that this run created, matching the SHA checked out above.
- name: Upload distribution archive to the release
if: ${{ steps.release.outputs.releases_created == 'true' }}
run: |
gh release upload "$RELEASE_TAG" \
"packages/html/archive/videojs-html-${VERSION}.zip" \
"packages/html/archive/videojs-html-${VERSION}.tar.gz" \
packages/html/archive/SHA256SUMS \
"packages/cdn/archive/videojs-cdn-${VERSION}.zip" \
"packages/cdn/archive/videojs-cdn-${VERSION}.tar.gz" \
packages/cdn/archive/SHA256SUMS \
--clobber

ASSETS=$(gh release view "$RELEASE_TAG" --json assets --jq '.assets[].name')
grep -Fx "videojs-html-${VERSION}.zip" <<< "$ASSETS"
grep -Fx "videojs-html-${VERSION}.tar.gz" <<< "$ASSETS"
grep -Fx "videojs-cdn-${VERSION}.zip" <<< "$ASSETS"
grep -Fx "videojs-cdn-${VERSION}.tar.gz" <<< "$ASSETS"
grep -Fx "SHA256SUMS" <<< "$ASSETS"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
RELEASE_TAG: ${{ steps.release.outputs['packages/html--tag_name'] }}
VERSION: ${{ steps.release.outputs['packages/html--version'] }}
RELEASE_TAG: ${{ steps.release.outputs['packages/cdn--tag_name'] }}
VERSION: ${{ steps.release.outputs['packages/cdn--version'] }}

- name: Update site/v10 branch
if: ${{ steps.release.outputs.releases_created == 'true' }}
Expand Down
5 changes: 3 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ jobs:
matrix:
package:
- '@videojs/cli'
- '@videojs/cdn'
- 'vjsc'
- '@videojs/core'
- '@videojs/icons'
Expand Down Expand Up @@ -248,10 +249,10 @@ jobs:
- name: Build CDN bundles
run: pnpm build:cdn

# Mirroring cdn/ onto another origin is supported, so the output must not
# Mirroring @videojs/cdn onto another origin is supported, so the output must not
# reference an external CDN or resolve outside the directory.
- name: Check CDN bundles are self-contained
run: pnpm -F @videojs/html check:cdn
run: pnpm -F @videojs/cdn check:cdn

- name: Save Vite Task cache
if: success()
Expand Down
9 changes: 4 additions & 5 deletions .github/workflows/pkg-pr-new.yml
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,9 @@ jobs:
- name: Build packages
run: pnpm build:packages

# `build:packages` runs the `build` task, which does not produce
# @videojs/html's `cdn/` tree; `build:cdn` is a separate task. `cdn` is in
# that package's `files`, and the sandbox resolves its CDN demos through
# the published export map, so skipping this leaves `./cdn/*` pointing at
# nothing in the preview tarball.
# `build:packages` intentionally excludes @videojs/cdn because its browser
# bundles have a separate task. The sandbox resolves its CDN demos through
# that package's published export map, so build it before packing previews.
- name: Build CDN bundles
run: pnpm build:cdn

Expand Down Expand Up @@ -123,6 +121,7 @@ jobs:
VIDEOJS_SKIP_PACKAGE_DOCS: '1'
run: >
pnpm exec pkg-pr-new publish --pnpm --previewVersion --peerDeps --packageManager=pnpm
'./packages/cdn'
'./packages/core'
'./packages/element'
'./packages/html'
Expand Down
4 changes: 2 additions & 2 deletions apps/e2e/scripts/generate-pages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,8 +138,8 @@ const REACT_MEDIA: Record<string, { component: string; importPath: string }> = {

// CDN import paths (override standard imports)
const CDN_IMPORTS: Record<string, string[]> = {
video: ['@videojs/html/cdn/video'],
'hlsjs-video': ['@videojs/html/cdn/video', '@videojs/html/cdn/media/hlsjs-video'],
video: ['@videojs/cdn/video'],
'hlsjs-video': ['@videojs/cdn/video', '@videojs/cdn/media/hlsjs-video'],
};

// ---------------------------------------------------------------------------
Expand Down
4 changes: 2 additions & 2 deletions apps/sandbox/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Open the printed URL. The root route renders an interactive shell — a navbar w

**Captions**, under **Playback** in the **Options** panel, adds one or two subtitle tracks to a video so the captions menu has something to show; the tracks are the page's, so no template spells them out. The source picker also carries a **Missing file** entry that opens the player's error dialog without waiting on a network.

**Language** is in the **Options** panel for every media (HTML, React, and CDN). **CDN** registers copy through `@videojs/html/cdn/i18n` (the same registry as the CDN player bundle), not source `@videojs/html/i18n`. After pulling template changes, restart `pnpm dev:sandbox` so `scripts/setup.ts` refreshes `src/` from `templates/`.
**Language** is in the **Options** panel for every media (HTML, React, and CDN). **CDN** registers copy through `@videojs/cdn/i18n` (the same registry as the CDN player bundle), not source `@videojs/html/i18n`. After pulling template changes, restart `pnpm dev:sandbox` so `scripts/setup.ts` refreshes `src/` from `templates/`.

The shell covers the main combinatorial matrix. One-off templates not in that matrix (e.g. `firefox-mse-repro`, `spf-segment-loading`, `hls-video-html`) are reachable by navigating directly to `/<template-name>/`. See `apps/sandbox/templates/` for the full list.

Expand Down Expand Up @@ -83,7 +83,7 @@ This previews every change first and prompts before doing anything. It overwrite

Every pull request publishes this directory as a StackBlitz template through [pkg.pr.new](https://github.com/stackblitz-labs/pkg.pr.new), booting it against that commit's preview packages. That makes the sandbox the one app here that must also run as a standalone project, which constrains it in two ways:

- **Nothing may reference a path outside this directory.** `vite.config.ts` locates the prebuilt `@videojs/html` CDN bundle through Node resolution rather than `../../packages/html`, carries its own copies of the task helpers from `build/task.ts`, and `tsconfig.json` is self-contained instead of extending `../../tsconfig.base.json` — Vite fails to start if a config import or that `extends` cannot be resolved. The one project file that does extend the base, `tsconfig.shared.json`, sits beside it under a name the transformer never looks up, so the shared sources still compile against `tsconfig.json`. The one exception is `vite.workspace.config.ts`, which imports the skins preset from `packages/skins`; the tasks only name it when that directory exists, so StackBlitz never loads it. Tasks that build sibling packages, such as `@videojs/html#build:cdn`, are likewise only declared when `pnpm-workspace.yaml` exists two directories up.
- **Nothing may reference a path outside this directory.** `vite.config.ts` locates the prebuilt `@videojs/cdn` bundles through Node resolution rather than `../../packages/cdn`, carries its own copies of the task helpers from `build/task.ts`, and `tsconfig.json` is self-contained instead of extending `../../tsconfig.base.json` — Vite fails to start if a config import or that `extends` cannot be resolved. The one project file that does extend the base, `tsconfig.shared.json`, sits beside it under a name the transformer never looks up, so the shared sources still compile against `tsconfig.json`. The one exception is `vite.workspace.config.ts`, which imports the skins preset from `packages/skins`; the tasks only name it when that directory exists, so StackBlitz never loads it. Tasks that build sibling packages, such as `@videojs/cdn#build:cdn`, are likewise only declared when `pnpm-workspace.yaml` exists two directories up.
- **Only published packages may be dependencies.** Package skins come from `@videojs/html` and `@videojs/react`. Setup uses the stock Shadcn CLI to install the ignored registry skins, three catalogs of eight, from the local built registry in the monorepo or `https://shadcn.videojs.org/r` elsewhere. The one private dependency, `@videojs/icons`, exists so authored skins dedupe onto a single copy inside the workspace; `scripts/prepare-template.ts`, which CI runs right before the upload, drops private workspace dependencies and inlines the `catalog:` versions from `pnpm-workspace.yaml`, since a lone `package.json` can resolve neither. When the hosted registry cannot be reached, setup carries on without the registry skins and the shell offers the package skins only.
- **The package manager has to be declared here.** Only the repo root says pnpm, and the root is never uploaded, so StackBlitz would otherwise default to npm. The `stackblitz` field in `package.json` turns off its automatic install and boots with pnpm instead and runs the `dev` task through `vp run dev`; Vite+ owns the task names, so `package.json` declares no `dev` script. `--ignore-scripts` is there because pnpm refuses to silently skip dependency build scripts and fails the install if it has to; the sandbox needs none of them, esbuild's native binary included. `--config.blockExoticSubdeps=false` is there because the preview packages depend on each other through pkg.pr.new URLs, which pnpm 11 otherwise refuses to follow from inside a dependency. The task runs with `--config.verifyDepsBeforeRun=false` because pnpm would otherwise re-run the install with its default settings first, and that install fails on the very build scripts the first one skipped.
- **Every cross-origin subresource has to be CORS-enabled.** StackBlitz previews are cross-origin isolated (`Cross-Origin-Embedder-Policy: require-corp`), so a no-CORS load from `stream.mux.com` or `image.mux.com` is blocked outright — neither host sends `Cross-Origin-Resource-Policy`. That is why every media element here carries a bare `crossorigin` (the CORS-settings attribute treats it as `anonymous`), which also puts the storyboard `<track>` into CORS mode and, through it, the thumbnail sprites. The poster has to be the template's own image — an HTML skin renders one only where you slot it, and a React skin left to itself renders an `<img>` no prop can reach — so the HTML templates slot `<img slot="poster" crossorigin>` and the React templates hand one to `renderPoster`. Both still pass the URL through the player and let the poster fill in the `src`; an image carrying its own would opt out of the blur-up load state. React has no bare-attribute form, so its templates write `crossOrigin=""`. One thing stays broken in a preview and cannot be fixed from here: a CSS `url()` can never be CORS-enabled, so the `placeholdersrc` blur-up does not render.
Expand Down
Loading
Loading