Skip to content

feat: support github's react-based diff ui#167

Merged
hashiiiii merged 6 commits into
mainfrom
feat/react-diff-ui
Jul 16, 2026
Merged

feat: support github's react-based diff ui#167
hashiiiii merged 6 commits into
mainfrom
feat/react-diff-ui

Conversation

@hashiiiii

@hashiiiii hashiiiii commented Jul 16, 2026

Copy link
Copy Markdown
Owner

Summary

Support GitHub's new React-based "Files changed" UI (login-gated rollout, /pull/N/changes) in the Chrome extension: Unity-file detection, the per-file toggle, semantic-view injection, and the global toggle bar now work on both the classic and the React layouts.

Motivation

The extension only matched the classic DOM (.file-header[data-path], .js-file-content); on the React UI those selectors match nothing and the extension silently does nothing. The React UI has been GitHub's default for logged-in users since late 2025, so the product's primary channel was at risk.

Closes #159

Changes

  • parsePrUrl accepts /pull/N/changes and /pull/N/changes/<sha>..<sha> (a single sha under /changes/ is the commit view and stays out of scope), mirroring github-url-detection
  • detect.ts: FileEntry is now a per-layout adapter (attachHost / setRawHidden / collapsed / globalAnchor); the classic and React scanners always both run, and the non-matching one yields [] harmlessly — no layout probe needed
  • React scanner anchors on div[role="region"][id^="diff-"] plus hashed CSS-module class prefixes; the path is parsed from header text (LRM marks stripped, sr-only rename form preferred) because the React UI has no path attribute anywhere
  • content/index.ts: mounting goes through the adapter; a display-only, fetch-free sync() re-asserts hide/show on every scan because the React UI virtualizes the file list (TanStack Virtual) and recreates DOM nodes continuously; disconnected appliers are pruned every scan instead of only on PR change
  • Collapse is read from two independent signals: the chevron octicon swap and the DiffFileHeader-module__collapsed header class
  • e2e: new fixture pr-files-react.html + react.spec.ts covering detection/render, global-bar placement outside the virtualized list, collapse chevron + body remount re-hide, and a full virtualization remount inheriting the semantic default

React-UI DOM structure was cross-checked against refined-github, TombWater/github-codeowners, sudo-vaibhav/pr-diff-plus, dkareh/bookmarklets, DIO0550/github-html-preview-ext, a live-captured fixture (elad12390/group-gh-pr-files), and GitHub's own shipped component chunk (confirms role="region", id="diff-${pathDigest}", header wrapper as first region child, and the CSS-module class map).

Testing

  • pnpm test — 197 passed (17 files)
  • pnpm typecheck — clean
  • pnpm lint — exit 0
  • pnpm e2e — 14 passed (10 existing classic specs unchanged + 4 new react specs)

Live verification on the real React UI (performed 2026-07-16)

Verified on https://github.com/hashiiiii/unity-yaml-playground/pull/2/changes in a logged-in browser session, by injecting the built dist/content.js with the same chrome.* stub the e2e suite uses (canned semantic-diff response; the background fetch/wasm path is covered separately by the existing unit + classic e2e layers):

  • Scanner matched all 21 file regions; toggles attached to exactly the 19 UnityYAML files (both .meta files correctly excluded, including a renamed one)
  • Path extraction verified against the live DOM, including the rename case (sr-only "renamed to" form returns the new path)
  • Global bar rendered once, immediately before [data-testid="progressive-diffs-list"]
  • Semantic toggle: shadow-root view rendered, real React diff body hidden
  • Real collapse round-trip: chevron click unmounts the body (region children 2 → 1) and the semantic host hides; re-expand remounts a fresh body node which the per-scan sync() re-hides while the semantic view returns
  • Live DOM matched the fixture assumptions exactly (Diff-module__diffHeaderWrapper as first region child, chevron icon swap, DiffFileHeader-module__collapsed class stamped when collapsed)

Manual verification (for reviewers)

  1. Sign in to github.com with the new Files changed experience enabled (or click "Try the new experience" on a PR)
  2. Open a PR with UnityYAML changes (e.g. feat: mutate fixture corpus for diff demo unity-yaml-playground#2) and go to the Files changed tab (/changes)
  3. Confirm: the PrefabLens global bar sits above the diff list, each Unity file header has the Raw/Semantic toggle, Semantic replaces the raw diff, collapsing a file hides the semantic view, and scrolling far away and back preserves the chosen view

@github-actions github-actions Bot added the extension VS Code extension (TypeScript) label Jul 16, 2026
@hashiiiii
hashiiiii merged commit 2855e20 into main Jul 16, 2026
12 checks passed
@hashiiiii
hashiiiii deleted the feat/react-diff-ui branch July 16, 2026 07:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

extension VS Code extension (TypeScript)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support GitHub's new React-based diff UI in the extension

1 participant