7139c5ea6f87ae7027d3aaede359906356fa1971
CI / test (pull_request) Successful in 5m48s
The video-detection pipeline was finding nothing on pages that have a bare
<video> element. Two root causes:
1. world: 'MAIN' placement. The deep probe + scraper are injected with
chrome.scripting.executeScript. Their code (and its own comments) requires
the MAIN world to see page globals — window.Hls, per-<video> Hls instances,
video._goon_hls_manifest, and window.__goon_plugin_data (written by the
main-world interceptors). The calls were missing it, so every main-world
strategy (A/A2/E/H) found 0. It was also briefly placed inside `target`,
which chrome.scripting rejects ("Unexpected property: 'world'"); `world` is
a sibling of `target` on ScriptInjection. Restore it as a sibling of target.
2. fake "manifest" classification. Strategy H was reporting 10 nav links /
server-side route TEMPLATES as manifests — e.g. /playlists/,
/playlists/liked/, /playlist/%1%/video/%2%/, /members/%ID%/playlists/ —
because the old /playlist|/manifest substring check matches nav menus and
leaves %1%/%ID%/%DIR% template placeholders intact. Those then became the
stored "video" entries, drowning out the real element.
isManifestUrl and isValidManifestUrl now reject:
- dynamic route templates (%NAME% or {name} tokens), using a negative
lookahead so genuine %-encoded tokens like %2B/%2F are preserved
(the invariant the codebase explicitly protects),
- plural collection paths (/playlists, /manifests),
- trailing-slash directory listings.
The 'World: ISOLATED' probe log was also misleading (typeof chrome is not a
world discriminator — the probe provably runs in MAIN); replaced it.
Adds a regression test (hls_qa) reproducing thisvid's pageContext.langUrls
scenario: all 10 templates are rejected while a real .m3u8 carrying a %2B token
is still detected. 90/90 tests pass; 0 lint errors; build OK.
VidPlex
A Chrome extension (Manifest V3) that finds videos on the current page and displays them in a 2x2 grid.
Features
- Click the extension icon → "Find Videos" to scan the current tab for all
<video>elements - Videos are listed in the popup for reference (clickable links, "Copy All URLs" button)
- Click "Open Viewer" to open a new window with videos in a 2x2 grid (autoplay muted)
- Click "Clear" to reset the stored video list
Getting started
# 1. Install deps
npm i
# 2. Run in watch mode
npm run dev
# 3. Build for distribution
npm run build
Loading in Chrome
- Open
chrome://extensions/ - Enable Developer mode (top-right)
- Click Load unpacked → select the project root folder (where
manifest.jsonis located)
Project structure
manifest.json — Extension manifest (MV3)
package.json — Dev tooling (Vite + Vitest + TS)
vite.config.ts — Build config
src/
background/ — Service worker (MV3 background)
content/ — Content script
viewer/ — Popup UI + video viewer
index.html — Popup (Find Videos, Open Viewer buttons)
index.js — Popup logic (scans current tab for videos)
index.css — Popup styles
viewer.html — Viewer page (2x2 video grid in new window)
viewer.js — Viewer logic (renders video panels)
viewer.css — Viewer grid styles
icons/ — Extension icons (place .png files here)
Recommended extensions (VS Code)
- Chrome Extension Developer (extension-list-viewer)
- ESLint
- Prettier
VS Code workspace
Open vidplex.code-workspace to get the project with recommended extensions pre-installed.