backnotprop/plannotator

pierre-guard

Guard against breaking the @pierre/diffs integration in Plannotator's code review UI.

ソースを見る
リポジトリの原文

見出し、例、コード、表、リンク、参照画像を含む原文を表示しています。

Pierre Integration Guard

Plannotator's code review UI wraps @pierre/diffs — an open-source diff renderer that uses Shadow DOM. The integration is concentrated in a single file but relies on undocumented internals (shadow DOM selectors, CSS variable names, grid layout assumptions). This skill helps verify changes don't break that contract.

Source of Truth

  • Upstream repo: https://github.com/pierrecomputer/pierre/tree/main/packages/diffs
  • Local types: node_modules/@pierre/diffs/dist/ (.d.ts files)
  • Integration point: packages/review-editor/components/DiffViewer.tsx
  • Current version: check packages/review-editor/package.json for the pinned version

Always verify against the upstream repo or local .d.ts files — don't rely on memory of the API shape.

What We Import

typescript
import { FileDiff } from '@pierre/diffs/react';
import { getSingularPatch, processFile } from '@pierre/diffs';

These are the only three imports. DiffViewer.tsx is the only file that touches Pierre.

API Surface to Guard

1. Component Props (FileDiff)

Read the current prop types from node_modules/@pierre/diffs/dist/react/index.d.ts or the upstream source. The props we use:

PropTypeNotes
fileDiffFileDiffMetadataFrom getSingularPatch() or processFile()
optionsFileDiffOptions<T>See options table below
lineAnnotationsDiffLineAnnotation<T>[]{ side, lineNumber, metadata }
selectedLines`SelectedLineRange \null`{ start, end, side }
renderAnnotation(ann) => ReactNodeCustom inline annotation renderer
renderHoverUtility(getHoveredLine) => ReactNodeThe + button on hover (deprecated upstream — watch for removal)

2. Options Object

OptionValue We PassRisk
themeType`'dark' \'light'`Low — standard enum
unsafeCSSCSS stringHigh — targets internal selectors
diffStyle`'split' \'unified'`Low — standard enum
diffIndicators'bars'Low
hunkSeparators'line-info'Low
enableLineSelectiontrueLow
enableHoverUtilitytrueMedium — deprecated prop
onLineSelectionEndcallbackMedium — signature could change

3. Shadow DOM Selectors (via unsafeCSS)

These are the selectors we inject CSS rules against. They target data-* attributes inside Pierre's shadow DOM. If Pierre renames or removes any of these, our styling breaks silently.

Currently used:

  • :host — shadow root
  • [data-diff] — root diff container
  • [data-file] — file wrapper
  • [data-diffs-header] — header bar
  • [data-error-wrapper] — error display
  • [data-virtualizer-buffer] — virtual scroll buffer
  • [data-file-info] — file metadata row
  • [data-column-number] — line number gutter
  • [data-diffs-header] [data-title] — title (we hide it)
  • [data-diff-type='split'] — split layout mode
  • [data-overflow='scroll'] / [data-overflow='wrap'] — overflow mode

4. CSS Variables We Override

We override these --diffs-* variables to theme Pierre:

  • --diffs-bg, --diffs-fg — base colors
  • --diffs-dark-bg, --diffs-light-bg — theme-specific backgrounds
  • --diffs-dark, --diffs-light — theme-specific foregrounds

5. CSS Variables We Inject (Custom)

We set these on a wrapper div outside the shadow DOM, relying on CSS custom property inheritance:

  • --split-left, --split-right — control the split pane grid ratio

The unsafeCSS grid override references these: grid-template-columns: var(--split-left, 1fr) var(--split-right, 1fr). The 1fr fallback ensures the layout is safe if the variables aren't set.

6. Grid Layout Assumption

Pierre's split view uses CSS Grid with grid-template-columns: 1fr 1fr. We override this for the resizable split pane. If Pierre changes its layout engine (e.g., to flexbox or a different grid structure), the override will stop working.

How to verify: In the upstream source, search for grid-template-columns in the diff component styles.

Verification Checklist

When reviewing changes that touch the Pierre integration, check:

Props & Types

  • [ ] Read the current .d.ts files to confirm prop names and types haven't changed
  • [ ] Check if renderHoverUtility is still supported (it's deprecated — may be removed)
  • [ ] Verify DiffLineAnnotation still uses side: 'deletions' | 'additions' (not 'old' | 'new')
  • [ ] Confirm SelectedLineRange shape: { start, end, side? }

Shadow DOM Selectors

  • [ ] Grep the upstream source for each data-* attribute we target in unsafeCSS
  • [ ] If upgrading the package version, diff the old and new CSS/HTML output for renamed attributes
  • [ ] Test both split and unified views — selectors are layout-dependent

CSS Variables

  • [ ] Grep upstream for --diffs-bg, --diffs-fg, and other variables we override
  • [ ] Verify the variable names haven't been renamed or removed
  • [ ] Check that !important is still needed (Pierre may change specificity)

Theme Compliance

  • [ ] New UI elements must use theme tokens (bg-border, bg-primary, etc.), not hardcoded colors like bg-blue-500
  • [ ] The existing ResizeHandle component in packages/ui/components/ResizeHandle.tsx sets the visual convention — match it

Build & Runtime

  • [ ] Run bun run dev:review and verify the diff renders in both split and unified modes
  • [ ] Check the browser console for Pierre warnings (e.g., parseLineType: Invalid firstChar)
  • [ ] Test with add-only and delete-only files (Pierre doesn't render split grid for these)
  • [ ] If changing UI code, remember build order: bun run --cwd apps/review build && bun run build:hook

When Upgrading @pierre/diffs

  1. Check the upstream changelog / commit history at https://github.com/pierrecomputer/pierre
  2. Diff the .d.ts files between old and new versions:
bash
   # Before upgrading, snapshot current types
   cp -r node_modules/@pierre/diffs/dist /tmp/pierre-old
   # After upgrading
   diff -r /tmp/pierre-old node_modules/@pierre/diffs/dist
  1. Search for renamed/removed data attributes in the new version
  2. Run through the full verification checklist above
  3. Test the resizable split pane — it depends on grid layout internals
同じリポジトリから

関連する Skills

すべての Skills