用途
pierre-guard 用于保护 Plannotator 代码审查界面中与 @pierre/diffs 的集成。Plannotator 的代码审查 UI 封装了 @pierre/diffs——一个使用 Shadow DOM 的开源 diff 渲染器。该集成集中在单个文件 DiffViewer.tsx 中,但依赖未公开的内部实现,包括 shadow DOM 选择器、CSS 变量名和网格布局假设。此技能帮助验证改动不会破坏这一契约。
事实来源
- 上游仓库:https://github.com/pierrecomputer/pierre/tree/main/packages/diffs
- 本地类型:node_modules/@pierre/diffs/dist/(.d.ts 文件)
- 集成点:packages/review-editor/components/DiffViewer.tsx
- 当前版本:查看 packages/review-editor/package.json 中锁定的版本
始终对照上游仓库或本地 .d.ts 文件进行验证,不要依赖对 API 形态的记忆。
导入内容
import { FileDiff } from '@pierre/diffs/react';
import { getSingularPatch, processFile } from '@pierre/diffs';
只有这三个导入。DiffViewer.tsx 是唯一接触 Pierre 的文件。
需要守护的 API 表面
1. 组件 Props(FileDiff)
从 node_modules/@pierre/diffs/dist/react/index.d.ts 或上游源码读取当前 prop 类型。使用的 props 包括:
- 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 对象
- themeType:'dark' | 'light',低风险——标准枚举
- unsafeCSS:CSS 字符串,高风险——针对内部选择器
- diffStyle:'split' | 'unified',低风险——标准枚举
- diffIndicators:'bars',低风险
- hunkSeparators:'line-info',低风险
- enableLineSelection:true,低风险
- enableHoverUtility:true,中风险——已弃用 prop
- onLineSelectionEnd:callback,中风险——签名可能变化
3. Shadow DOM 选择器(通过 unsafeCSS)
这些是通过 unsafeCSS 注入 CSS 规则所针对的选择器,它们指向 Pierre shadow DOM 内部的 data-* 属性。如果 Pierre 重命名或移除其中任何一个,样式会静默失效。当前使用:
- :host — shadow root
- [data-diff] — 根 diff 容器
- [data-file] — 文件包装器
- [data-diffs-header] — 头部栏
- [data-error-wrapper] — 错误显示
- [data-virtualizer-buffer] — 虚拟滚动缓冲区
- [data-file-info] — 文件元数据行
- [data-column-number] — 行号栏
- [data-diffs-header] [data-title] — 标题(被隐藏)
- [data-diff-type='split'] — 分栏布局模式
- [data-overflow='scroll'] / [data-overflow='wrap'] — 溢出模式
4. 覆盖的 CSS 变量
覆盖以下 --diffs-* 变量来为 Pierre 设置主题:
- --diffs-bg, --diffs-fg — 基础颜色
- --diffs-dark-bg, --diffs-light-bg — 主题特定背景
- --diffs-dark, --diffs-light — 主题特定前景
5. 注入的自定义 CSS 变量
在 shadow DOM 外部的包装 div 上设置这些变量,依赖 CSS 自定义属性继承:
- --split-left, --split-right — 控制分栏窗格网格比例
unsafeCSS 网格覆盖引用这些变量:grid-template-columns: var(--split-left, 1fr) var(--split-right, 1fr)。1fr 回退确保变量未设置时布局安全。
6. 网格布局假设
Pierre 的分栏视图使用 CSS Grid,grid-template-columns: 1fr 1fr。为可调整大小的分栏窗格覆盖了此设置。如果 Pierre 更改布局引擎(例如改为 flexbox 或不同的网格结构),覆盖将停止工作。
验证方法:在上游源码中搜索 diff 组件样式里的 grid-template-columns。
验证检查清单
审查涉及 Pierre 集成的改动时,检查:
Props 与类型
- 阅读当前 .d.ts 文件,确认 prop 名称和类型未变化
- 检查 renderHoverUtility 是否仍受支持(已弃用——可能被移除)
- 验证 DiffLineAnnotation 仍使用 side: 'deletions' | 'additions'(而非 'old' | 'new')
- 确认 SelectedLineRange 结构:{ start, end, side? }
Shadow DOM 选择器
- 在上游源码中 grep 每个在 unsafeCSS 中针对的 data-* 属性
- 升级包版本时,对比新旧 CSS/HTML 输出中重命名的属性
- 测试分栏和统一视图——选择器依赖布局
CSS 变量
- 在上游 grep --diffs-bg、--diffs-fg 及其他覆盖的变量
- 验证变量名未被重命名或移除
- 检查 !important 是否仍需要(Pierre 可能改变特异性)
主题合规
- 新 UI 元素必须使用主题令牌(bg-border、bg-primary 等),而非硬编码颜色如 bg-blue-500
- packages/ui/components/ResizeHandle.tsx 中现有的 ResizeHandle 组件设定了视觉约定——与之匹配
构建与运行时
- 运行 bun run dev:review,验证 diff 在分栏和统一模式下均能渲染
- 检查浏览器控制台中的 Pierre 警告(例如 parseLineType: Invalid firstChar)
- 测试仅添加和仅删除的文件(Pierre 不为这些渲染分栏网格)
- 如果更改 UI 代码,记住构建顺序:bun run --cwd apps/review build && bun run build:hook
升级 @pierre/diffs 时
- 查看上游变更日志/提交历史:https://github.com/pierrecomputer/pierre
- 对比新旧版本之间的 .d.ts 文件:
# 升级前,快照当前类型
cp -r node_modules/@pierre/diffs/dist /tmp/pierre-old
# 升级后
diff -r /tmp/pierre-old node_modules/@pierre/diffs/dist
- 在新版本中搜索重命名/移除的 data 属性
- 运行上述完整验证检查清单
- 测试可调整大小的分栏窗格——它依赖网格布局内部实现
适用场景
适用于修改 DiffViewer.tsx、升级 @pierre/diffs 包版本、调整代码审查 UI 样式或布局,以及审查任何可能影响 Pierre 集成的改动时。
限制
该技能依赖 @pierre/diffs 未公开的内部实现(shadow DOM 选择器、CSS 变量名、网格布局),这些可能随上游版本变化而失效。renderHoverUtility 已在上游弃用,可能被移除。资料未提供具体的收费、价格或平台信息。