Repository navigation
Conversation
deepmerge@4.3.1 (transitive via react-player, used in the Video component) has no upstream fix for a prototype pollution vuln. Patch mergeObject's unsafe-key check to reject __proto__/constructor/prototype keys, and pin all in-tree deepmerge ranges to the patched build via yarn resolutions. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This reverts commit 68b313c. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
… dependency react-player@2.x pulled in deepmerge@4.3.1, which has a prototype pollution vuln (CVE-2026-93753, CVSS 8.7) with no upstream fix. react-player@3 dropped deepmerge entirely in favor of native media elements, so upgrading removes the vulnerable dependency from @Codecademy/gamut's tree rather than patching it. - url prop renamed to src; youtube config no longer nests under playerVars; vimeo's config.title is now a boolean (native title overlay toggle), not a string, so the accessible video title is carried solely by the existing title prop - dropped the dead ReactPlayerWithWrapper type (v3's ref now forwards to the underlying HTMLVideoElement, not a wrapper element) - react-player is ESM-only in v3, so Jest needs it in transformIgnorePatterns; Video.test.tsx now mocks react-player directly (matching the existing pattern in Markdown.test.tsx) instead of rendering the real Vimeo/YouTube custom elements, which don't mount under jsdom Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
View your CI Pipeline Execution ↗ for commit 2a7ffd6 ☁️ Nx Cloud last updated this comment at |
…onsumers react-player@3's dependency tree (tiktok-video-element, vimeo-video-element, etc.) relies on package.json "exports" subpaths that legacy bundlers like webpack 4 can't resolve. Because @Codecademy/gamut's main entry re-exports every component from one flat barrel, ANY consumer resolving '@Codecademy/gamut' was forced to resolve react-player's exports-map-only subpaths at build time, even if they never rendered <Video> - this is what broke Codecademy's build despite it not importing Video anywhere. - Remove `export * from './Video'` from the main barrel; add a legacy subpath package (packages/gamut/Video/package.json, no "exports" field needed) so `@Codecademy/gamut/Video` still resolves via plain Node resolution. Consumers using Video need this one import path change. - Markdown's Iframe/MarkdownVideo overrides also statically imported Video via a relative path, so any Markdown consumer was equally exposed regardless of the Video split. Made these opt-in via new `iframeOverride`/`videoOverride` props instead of always-on defaults; without opting in, <iframe>/<video> tags in markdown now render as plain tags rather than the polished Video component. Iframe/MarkdownVideo are re-exported from the Video subpath so opting in doesn't touch the main barrel either. - Updated gamut's own internal Video usages (styleguide stories, code-connect) to the new subpath import. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…verrides Video.mdx now points at '@Codecademy/gamut/Video' instead of the main barrel, and explains why. Markdown.mdx gets a new Video overrides section covering iframeOverride/videoOverride, corrects the outdated skipDefaultOverrides claim about iframe, and adds stories/example.md copy showing both the opted-in and bare-tag fallback states. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
Now that Video lives behind the @Codecademy/gamut/Video subpath, the main barrel no longer imports either player library, so consumers who don't use Video shouldn't have to install them. - Move @vidstack/react and react-player from dependencies to optional peerDependencies; keep them as devDependencies for the repo's own build, tests, and styleguide. - Document the install step in the Video docs and the version plan, and add a pointer comment at the top of src/Video/index.tsx for anyone following a "Can't resolve" bundler error.
LinKCoding
left a comment
There was a problem hiding this comment.
Nice!
I left some comments, nothing's blocking, but I do think some points could be touched up :)
| createVideoOverride('video', { | ||
| component: MarkdownVideo, | ||
| }), | ||
| videoOverride && createVideoOverride('video', videoOverride), |
There was a problem hiding this comment.
Not sure the state of markdown updates, but would rather use objects to supply arguments.
esp for this one since the function would imply the 'video' is always the tag that is being supplied to createVideoOverride (as compared to more generic createTagOverride)
| it('loads a video with a vimeo URL', async () => { | ||
| const { view } = renderView({ | ||
| videoUrl: 'https://vimeo.com/145702525', | ||
| videoUrl: 'https://vimeo.com/1218916076', |
There was a problem hiding this comment.
lol this is so funny
optionally: update videoTitle here 😂
|
|
||
| ### Installation | ||
|
|
||
| `Video`'s player libraries are peer dependencies of `@codecademy/gamut`, so they aren't installed automatically. They're only needed if you import from `@codecademy/gamut/Video`; the main `@codecademy/gamut` barrel never loads them, so apps that don't use `Video` can skip them. Add them alongside Gamut to use `Video` (or the Markdown `Iframe`/`MarkdownVideo` overrides): |
There was a problem hiding this comment.
I think this language can be cleaned up a bit by explicitly stating what "they" are, and seems to repeat itself a bit. Something like:
Video's player libraries are peer dependencies of @codecademy/gamut, so they aren't installed automatically. If the Video component is needed, then import from @codecademy/gamut/Video. Add the following packages alongside Gamut to use Video (or the Markdown Iframe/MarkdownVideo overrides):
| yarn add @vidstack/react@~1.12.12 react-player@^3.4.0 | ||
| ``` | ||
|
|
||
| Pin the versions: `@vidstack/react`'s npm `latest` tag still points to 0.6.x (1.x is published under `next`), so a bare `yarn add @vidstack/react` installs 0.6, which lacks the `@vidstack/react/player/layouts/default` subpath `Video` imports and fails with `Module not found`. Versions 1.14+ use static class blocks, which break Jest in repos whose Babel config can't parse them (see "Babel and newer syntax" on the Installation page). |
There was a problem hiding this comment.
Maybe add a sample package.json for what a user should expect and do after installing vidstack and react-player?
// package.json
...
"dependencies": {
...
"@vidstack/react": "~1.12.12",
}
"resolutions": {
...
"@vidstack/react": "~1.12.12",
}
...
There was a problem hiding this comment.
is the resolution something that gamut should also do?
There was a problem hiding this comment.
i don't even think we need the resolution at all tbh, i;ll add an example though!
| import { Video } from '@codecademy/gamut/Video'; | ||
| ``` | ||
|
|
||
| `Video` is imported from `@codecademy/gamut/Video`, not the main `@codecademy/gamut` barrel. It depends on `react-player`, whose own dependency tree relies on package.json `"exports"` subpaths that legacy bundlers (e.g. webpack 4) can't resolve — keeping it off the main barrel means consumers who don't use `Video` never need to resolve that tree. To render video content embedded in `Markdown` text, see the [Video overrides](../Organisms/Markdown/Markdown.mdx#video-overrides) section on the Markdown docs page instead of importing `Video` directly. |
There was a problem hiding this comment.
Videois imported from@codecademy/gamut/Video, not the main@codecademy/gamutbarrel.
This repeats a lot of info in the first newly added paragraph (where imports are happening)
There was a problem hiding this comment.
It depends on
react-player, whose own dependency tree relies on package.json"exports"subpaths that legacy bundlers (e.g. webpack 4) can't resolve — keeping it off the main barrel means consumers who don't useVideonever need to resolve that tree.
Adding a sample package.json could potentially remove the need for this explanation.
There was a problem hiding this comment.
This linking doesn't work for me :\
|
📬 Published Alpha Packages:
|
|
🚀 Styleguide deploy preview ready! Preview URL: https://6ac9408d6d030ce5cd615f47--gamut-preview.netlify.app |
Overview
Upgrades
react-playerto v3 to drop the vulnerabledeepmerge@4.3.1(CVE-2026-93753, prototype pollution, no upstream fix), and movesVideoout of the main barrel so consumers who never render it, including webpack 4 apps, aren't broken by react-player v3's dependency tree. Replaces the patch-only approach in #3438.Dependencies
react-player— bumps^2.16.0to^3.4.0, which removesdeepmergefrom the tree (yarn why deepmergeconfirms)@vidstack/react,react-player— nowpeerDependencies(anddevDependencies) at~1.12.12and^3.4.0; consumers who useVideoinstall them themselves@vidstack/react— pinned to~1.12.12because 1.14+ uses static class blocks that break Jest in repos whose Babel config can't parse themVideo
Video— now imported from@codecademy/gamut/Video, not the main barrel; a legacy subpath package (packages/gamut/Video/package.json, no"exports") keeps it resolvable by webpack 4. Breaking: import path change forVideoconsumersVideo— adapts to the react-player v3 API (srcreplacesurl, YouTubecolorconfig) and drops the removedReactPlayerWithWrappertypeVideo— sets an accessibletitleon the provider iframe (videoTitle, or "Video player" as a fallback) as soon as it's inserted. react-player v3 putstitleon its custom element, so the inner iframe was unnamed and failed axeframe-title(e.g. portal-app's About page e2e)Markdown
Markdown—IframeandMarkdownVideooverrides are now opt-in viaiframeOverride/videoOverride, soMarkdownno longer statically importsVideo. Without opting in,<iframe>and<video>tags render as plain tags. Breaking: consumers relying on the polished embed must pass the overridesIframe,MarkdownVideo— re-exported from@codecademy/gamut/Videoso opting in doesn't touch the main barrelTests
Video.test.tsx— the react-player mock now mimics v3 (iframe inserted after mount, notitle,onReadynever called); adds a case for the default titleMarkdown.test.tsx— covers the opt-in overridesDocs / versioning
Installation.mdx,Video.mdx,Markdown.mdx— document the subpath import, peer dependencies, opt-in overrides, and Jest/Babel setup for newer vidstack.nx/version-plans— adds a version planPR Checklist
Testing Instructions
yarn jest packages/gamut/src/Video packages/gamut/src/Markdownandyarn tsc --noEmit -p packages/gamutpass.yarn why deepmergeshows it is no longer underreact-player.<iframe>has atitleattribute and the Console has no errors.<iframe>renders as a bare tag.yarn nx run ui-login-or-register:test:cipasses with@vidstack/react@~1.12.12andreact-player@^3.4.0installed.yarn build:appcompletes. It never importsVideodirectly, but@codecademy/branddoes.AboutPage.cy.tspasses the axeframe-titlecheckLinked consumer PRs:
https://github.com/codecademy-engineering/mono/pull/13776
https://github.com/codecademy-engineering/Codecademy/pull/41230