feat(review): add review.visual.themes config for dark-mode capture - #3680
Conversation
|
Superagent didn't find any vulnerabilities or security issues in this PR. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #3680 +/- ##
=======================================
Coverage 93.34% 93.34%
=======================================
Files 315 315
Lines 32107 32129 +22
Branches 11769 11780 +11
=======================================
+ Hits 29969 29991 +22
Misses 1507 1507
Partials 631 631
🚀 New features to boost your workflow:
|
|
Tip 🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩 ✅ Gittensory review result - approve/merge recommendedReview updated: 2026-07-06 02:55:37 UTC
✅ Suggested Action - Approve/Merge
Review summary Nits — 6 non-blocking
Review context
Contributor next steps
Signal definitions
🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed 💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →. Checked by Gittensory, a quiet PR intelligence layer for OSS maintainers.
|
Adds review.visual.themes: string[] (validated against the "light" /
"dark" enum, following the same list-parsing idiom as
review.visual.routes.paths) so a repo can request before/after
evidence for both color schemes instead of only whatever a page
defaults to.
- shot.ts: captureShot accepts a theme option and calls
page.emulateMediaFeatures([{name: "prefers-color-scheme", value}])
before navigation. Undefined (every existing caller) means no
emulation call at all. handleShot's on-demand render (?url=) also
reads a matching &theme= query param, since an on-demand fallback
URL needs to carry the same information a persisted capture's cache
key does.
- capture.ts: capturePage's cache-key fingerprint and on-demand
fallback URL both include the theme (only when set, so the format
is byte-identical when it's not); buildCapture resolves the
configured theme list (default: a single implicit undefined pass,
identical to today) and produces one CaptureRoute per (route,
theme) pair, tagging it with `theme` only when explicitly
requested.
- unified-comment-bridge.ts: the viewport column gets a theme suffix
("desktop (dark)") when a route has one, unlabeled otherwise.
Verified with a real headless-Chromium render (browserless) that
emulating "light" produces byte-identical output to no emulation at
all (confirming the default is unaffected), and that "dark" produces
a genuinely different, visually-inverted render via a real
prefers-color-scheme media query -- not just a passing mocked test.
Part of #3607. Closes #3678.
88a4a6e to
8266ff4
Compare
Summary
review.visual.themes: string[]to the manifest schema (focus-manifest.ts), validated againstlight | dark, following the same list-parsing idiom asreview.visual.routes.paths(dedupe, cap, warn-and-drop invalid entries).captureShot(shot.ts) accepts an optionalthemeand callspage.emulateMediaFeatures([{ name: "prefers-color-scheme", value: theme }])before navigation.handleShot's on-demand render mode also reads/validates a&theme=query param end to end.buildCaptureresolves the configured theme list (default → single untagged capture, byte-identical to today) and produces oneCaptureRouteper (route, theme) pair, reusing the existing per-viewport capture/diff logic inside an outer theme loop. Cache-key fingerprints and on-demand shot URLs include the theme so light/dark never collide.unified-comment-bridge.ts's "Visual preview" table shows the theme in the viewport label when set (e.g.desktop (dark)), unchanged when absent..gittensory.yml.exampleandconfig/examples/gittensory.full.ymlboth document the newthemes:block (kept byte-identical perconfig-templates.test.ts).Part of #3607. Closes #3678.
Scope
src/signals/focus-manifest.ts—VisualThemetype,parseVisualThemes, schema wiring, JSON round-trip.src/review/visual/shot.ts—ShotTheme,emulateMediaFeaturescall,handleShot's&theme=param.src/review/visual/capture.ts— theme loop inbuildCapture, theme-aware cache keys + on-demand URLs.src/review/unified-comment-bridge.ts— theme label in the Visual preview table..gittensory.yml.example,config/examples/gittensory.full.yml— matching documentation.focus-manifest.test.ts,signals-coverage.test.ts,visual-config-wiring.test.ts,visual-capture.test.ts,visual-collapsible.test.ts,visual-shot.test.ts.Validation
npx tsc --noEmitclean.npx vitest run).git diff --checkclean (no whitespace conflict markers).npm audit --audit-level=moderate— 0 vulnerabilities.browserless/chromium+puppeteer-core): confirmedemulateMediaFeatureswithlightproduces byte-identical output to no emulation, anddarkproduces a genuinely different render — not just a different tag on the same image.ui:openapi/cf-typegen/migrations not applicable.Safety
review.visual.themesconfigured) is byte-identical to pre-feat(review): add review.visual.themes config for dark-mode capture #3678 behavior: a single untagged capture, noemulateMediaFeaturescall, no&theme=in on-demand URLs. Verified by dedicated tests in each touched file.wantedPaths; does not touchsite/,CNAME, or**/lovable/**.