pierre-guard

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Pierre Integration Guard

Pierre集成防护

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.
Plannotator的代码审查UI封装了
@pierre/diffs
——一个使用Shadow DOM的开源差异渲染器。该集成集中在单个文件中,但依赖于未公开的内部实现(Shadow DOM选择器、CSS变量名、网格布局假设)。此技能有助于验证修改不会破坏该集成约定。

Source of Truth

权威来源

Always verify against the upstream repo or local
.d.ts
files — don't rely on memory of the API shape.
请始终以上游仓库或本地
.d.ts
文件为准——不要依赖对API形态的记忆。

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.
typescript
import { FileDiff } from '@pierre/diffs/react';
import { getSingularPatch, processFile } from '@pierre/diffs';
这是仅有的三个导入项。
DiffViewer.tsx
是唯一接触Pierre的文件。

API Surface to Guard

需要防护的API范围

1. Component Props (
FileDiff
)

1. 组件属性(
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
fileDiff
FileDiffMetadata
From
getSingularPatch()
or
processFile()
options
FileDiffOptions<T>
See options table below
lineAnnotations
DiffLineAnnotation<T>[]
{ side, lineNumber, metadata }
selectedLines
SelectedLineRange | null
{ start, end, side }
renderAnnotation
(ann) => ReactNode
Custom inline annotation renderer
renderHoverUtility
(getHoveredLine) => ReactNode
The
+
button on hover (deprecated upstream — watch for removal)
node_modules/@pierre/diffs/dist/react/index.d.ts
或上游源码读取当前属性类型。我们使用的属性:
属性类型说明
fileDiff
FileDiffMetadata
来自
getSingularPatch()
processFile()
options
FileDiffOptions<T>
见下方选项表格
lineAnnotations
DiffLineAnnotation<T>[]
{ side, lineNumber, metadata }
selectedLines
SelectedLineRange | null
{ start, end, side }
renderAnnotation
(ann) => ReactNode
自定义内联注释渲染器
renderHoverUtility
(getHoveredLine) => ReactNode
悬停时的“+”按钮(上游已废弃——需留意是否被移除)

2. Options Object

2. 选项对象

OptionValue We PassRisk
themeType
'dark' | 'light'
Low — standard enum
unsafeCSS
CSS stringHigh — targets internal selectors
diffStyle
'split' | 'unified'
Low — standard enum
diffIndicators
'bars'
Low
hunkSeparators
'line-info'
Low
enableLineSelection
true
Low
enableHoverUtility
true
Medium — deprecated prop
onLineSelectionEnd
callbackMedium — signature could change
选项我们传入的值风险等级
themeType
'dark' | 'light'
低——标准枚举
unsafeCSS
CSS字符串——针对内部选择器
diffStyle
'split' | 'unified'
低——标准枚举
diffIndicators
'bars'
hunkSeparators
'line-info'
enableLineSelection
true
enableHoverUtility
true
中——已废弃属性
onLineSelectionEnd
回调函数中——签名可能变更

3. Shadow DOM Selectors (via
unsafeCSS
)

3. Shadow DOM选择器(通过
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
这些是我们注入CSS规则所针对的选择器,它们指向Pierre Shadow DOM内的
data-*
属性。如果Pierre重命名或移除其中任何一个,我们的样式会静默失效。
当前使用的选择器:
  • :host
    —— Shadow根节点
  • [data-diff]
    —— 根差异容器
  • [data-file]
    —— 文件包装器
  • [data-diffs-header]
    —— 标题栏
  • [data-error-wrapper]
    —— 错误显示区域
  • [data-virtualizer-buffer]
    —— 虚拟滚动缓冲区
  • [data-file-info]
    —— 文件元数据行
  • [data-column-number]
    —— 行号 gutter
  • [data-diffs-header] [data-title]
    —— 标题(我们会隐藏它)
  • [data-diff-type='split']
    —— 拆分布局模式
  • [data-overflow='scroll']
    /
    [data-overflow='wrap']
    —— 溢出模式

4. CSS Variables We Override

4. 我们覆盖的CSS变量

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
我们覆盖这些
--diffs-*
变量来为Pierre设置主题:
  • --diffs-bg
    ,
    --diffs-fg
    —— 基础颜色
  • --diffs-dark-bg
    ,
    --diffs-light-bg
    —— 主题特定背景色
  • --diffs-dark
    ,
    --diffs-light
    —— 主题特定前景色

5. CSS Variables We Inject (Custom)

5. 我们注入的自定义CSS变量

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.
我们在Shadow DOM外的包装div上设置这些变量,依赖CSS自定义属性的继承性:
  • --split-left
    ,
    --split-right
    —— 控制拆分面板的网格比例
unsafeCSS
中的网格覆盖会引用这些变量:
grid-template-columns: var(--split-left, 1fr) var(--split-right, 1fr)
1fr
的回退值确保如果变量未设置,布局仍能正常工作。

6. Grid Layout Assumption

6. 网格布局假设

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.
Pierre的拆分视图使用CSS Grid,设置为
grid-template-columns: 1fr 1fr
。我们会覆盖此设置以实现可调整大小的拆分面板。如果Pierre更改其布局引擎(例如改为flexbox或不同的网格结构),该覆盖将失效。
验证方式: 在上游源码中,搜索差异组件样式中的
grid-template-columns

Verification Checklist

验证检查清单

When reviewing changes that touch the Pierre integration, check:
在审查涉及Pierre集成的修改时,请检查:

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? }
  • 读取当前
    .d.ts
    文件,确认属性名称和类型未变更
  • 检查
    renderHoverUtility
    是否仍受支持(已废弃——可能被移除)
  • 验证
    DiffLineAnnotation
    仍使用
    side: 'deletions' | 'additions'
    (而非
    'old' | 'new'
  • 确认
    SelectedLineRange
    的结构:
    { start, end, side? }

Shadow DOM Selectors

Shadow DOM选择器

  • 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
  • 在源码中搜索我们在
    unsafeCSS
    中针对的每个
    data-*
    属性
  • 如果升级包版本,对比新旧版本的CSS/HTML输出,检查是否有重命名的属性
  • 测试拆分和统一两种视图——选择器依赖布局

CSS Variables

CSS变量

  • 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)
  • 在源码中搜索
    --diffs-bg
    --diffs-fg
    以及我们覆盖的其他变量
  • 验证变量名称未被重命名或移除
  • 检查是否仍需要
    !important
    (Pierre可能更改了优先级)

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
  • 新UI元素必须使用主题令牌(
    bg-border
    bg-primary
    等),而非硬编码颜色如
    bg-blue-500
  • 现有
    ResizeHandle
    组件位于
    packages/ui/components/ResizeHandle.tsx
    ,定义了视觉规范——需与之匹配

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
  • 运行
    bun run dev:review
    ,验证差异在拆分和统一模式下均能正常渲染
  • 检查浏览器控制台是否有Pierre警告(例如
    parseLineType: Invalid firstChar
  • 测试仅添加和仅删除的文件(Pierre不会为这些文件渲染拆分网格)
  • 如果修改UI代码,请记住构建顺序:
    bun run --cwd apps/review build && bun run build:hook

When Upgrading @pierre/diffs

升级@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
  3. Search for renamed/removed data attributes in the new version
  4. Run through the full verification checklist above
  5. Test the resizable split pane — it depends on grid layout internals
  1. 查看上游变更日志/提交历史:https://github.com/pierrecomputer/pierre
  2. 对比新旧版本的
    .d.ts
    文件:
    bash
    # 升级前,快照当前类型定义
    cp -r node_modules/@pierre/diffs/dist /tmp/pierre-old
    # 升级后
    diff -r /tmp/pierre-old node_modules/@pierre/diffs/dist
  3. 在新版本中搜索是否有重命名/移除的data属性
  4. 完成上述完整的验证检查清单
  5. 测试可调整大小的拆分面板——它依赖网格布局的内部实现