为 GitHub PR 添加 before/after 视觉证据Sanity 仓库 before-and-after Skill 与 format.mjs 实战指南【免费下载链接】sanitySanity Studio – Rapidly configure content workspaces powered by structured content项目地址: https://gitcode.com/GitHub_Trending/sa/sanity本指南基于 Sanity 仓库中的 before-and-after Skill 文档 及其唯一捆绑脚本 format.mjs 编写完整讲解如何在 GitHub Pull Request 描述中插入改造前后对比或纯预览的截图与录屏证据块包括捕获规范、格式化命令、PR 内证据排版顺序、发布工作流与脚本契约。读完本文你将能独立把一个包含桌面端/移动端 before/after 截图、受保护 Vercel Preview 录屏、甚至video对比表格的视觉证据块安全地发布到 PR 描述中且不破坏原 PR 的任何其他内容。Sanity 是一个面向结构化内容的快速配置工作台Studio项目。当开发者通过 Agent 对 Studio 的界面、表单组件或布局做视觉改动时PR 中最有说服力的描述不是文字而是改动前 vs 改动后的真实截图或录屏。本仓库的.agents/skills/before-and-after正是为这一场景设计的 Agent 技能Skill它只负责GitHub PR 附件的编排工作流浏览器导航与画面捕获则交给agent-browser完成职责边界清晰。一、Skill 的职责边界与整体流程该 Skill 的 frontmatter 明确定义了它的能力边界name: before-and-after description: Add existing screenshots or screen recordings to a GitHub pull request as a before/after or preview block. Use when a PR needs visual media attached to its description. Browser navigation and capture belong to agent-browser.即截图或录屏的生成由agent-browser负责本 Skill 只拥有 GitHub PR 附件工作流。整体流程分为四个阶段Capture捕获用agent-browser打开页面、设置状态、截取全页截图或录制视频将媒体文件保存到仓库内、路径不含空格的目录Format格式化用scripts/format.mjs把本地媒体生成带!-- before-and-after:start/end --标记的 Markdown 块Place放置读取现有 PR 描述把视觉证据块插入到合适位置Publish发布用gh pr edit --body-file合并标记块与既有描述必要时用gh --attach上传本地媒体。二、Capture捕获阶段的硬性规范2.1 指令与受保护部署先通过agent-browser skills get core --full加载与版本匹配的核心指令并遵循其中的会话、导航、页面状态、截图与录屏约定如果目标 Vercel URL 受保护需加载agent-browser skills get protected-vercel-deployments --full不要在本 Skill 中复刻其认证工作流职责分离。2.2 媒体保存路径媒体文件必须保存在仓库内且路径不能包含空白字符例如captures/desktop-before.png captures/desktop-after.png captures/mobile-before.png captures/mobile-after.png格式化器支持PNG、JPEG、GIF、WebP图片以及MP4、MOV、WebM视频六种格式。如果只提供--after文件而没有配对的--before文件则该对会渲染为纯新增预览Preview块。2.3 屏幕录制的三个坑新上下文不继承认证agent-browser record start会创建全新的浏览器上下文虽然保留了 cookie 与 local storage但用于打开受保护 Vercel Preview 的按来源origin限定的 header不会带入新上下文。正确顺序是加载protected-vercel-deployments技能 → 在空白页启动录制上下文 → 在该上下文内应用认证方法 → 认证生效后再导航到 Preview必要时裁剪掉导航前的引导画面。不要假设record start之前能访问的页面在录制上下文内依然保持认证状态。帧率是硬编码的agent-browser0.35.2与0.36.0版本以硬编码 10 fps捕获且没有 CLI 或环境变量可覆盖。应检查实际安装版本及其录制参考文档不要假设后续版本仍是 10 fps。转码时应保留源帧率——把容器改成 30 或 60 fps 只会复制帧并不会让动画更流畅。需要更高真实帧率的动画证据时应使用真正的高帧率捕获路径而不是对 agent-browser 输出做上采样。录屏时长与内容录制完成后应确认导航引导段lead-in已被裁剪。2.4 等高图片对Equal-height image pairsGitHub 在 Markdown 表格单元格内会垂直居中较矮的图片。对于全页 before/after 截图应让两张图像素高度完全一致使顶部边缘对齐。操作步骤在两个会话中以相同的 viewport 和页面状态打开两页分别读取document.documentElement.scrollHeight给较矮的页面只追加底部空间直到两个 scroll height 一致然后分别截取--full全页截图。注意追加的 padding 可以是透明的也可以使用捕获工具的默认画布色永远不要在页面顶部加空白对于组件/区块级对比应截取相同的局部区域而不是给无关页面内容加 padding这一 DOM 调整应使用原始的agent-browser eval完成不要给本 Skill 引入图片处理依赖发布前必须确认两个文件的像素尺寸相等。三、Format用 format.mjs 生成标记块3.1 基础用法before/after 图片对每组对比传一对--before与--after多组对比重复传参并用--label标识node skill/scripts/format.mjs \ --before captures/desktop-before.png \ --after captures/desktop-after.png \ --before captures/mobile-before.png \ --after captures/mobile-after.png \ --label Desktop \ --label Mobile \ /tmp/before-and-after.md输出结构为带标记的 Markdown 表格图片渲染在表格单元格内!-- before-and-after:start -- | Before (Desktop) | After (Desktop) | |:---:|:---:| | Before | After | | Before (Mobile) | After (Mobile) | |:---:|:---:| | Before | After | !-- before-and-after:end --3.2 After-only 纯预览node skill/scripts/format.mjs \ --after captures/new-page.png \ /tmp/before-and-after.md此时每个无--before配对的条目会被渲染为Preview表格。3.3 归属署名加--attribution name会在标记块顶部输出一行 Before/after by name用于在 PR 中标注证据的生产者。3.4 本地视频与gh --attach的两步机制图片在表格中渲染本地视频默认渲染在独立行这样gh --attach才能上传它们并暴露最终的附件 URL。由于gh --attach不会改写video src属性内的本地引用before/after 视频表格必须使用下文发布阶段的两步工作流。四、Place视觉证据在 PR 描述中的放置顺序插入新标记块前先读取现有 PR 描述。放置原则视觉证据放在靠近顶部的位置——紧随简短的导语、以及已有的 Preview 或部署链接章节之后放在实现细节类章节Details、Changes、Testing、Notes之前块内阅读顺序第一优先真正证明本 PR 的 before/after 或 Preview 证据其次补充格式、替代状态或演示任何用于演示本 Skill 本身而非 PR 的内容必须标注为 demo并注明材料限制例如当前安装的 agent-browser 录制器在动效流畅性关键时只有 10 fps。排版约束语义化提示而非强制命名标题只是语义提示不是必需名称不要为了生成锚点而凭空发明或重写段落文字严禁把一个段落、列表、表格、代码块或其他 Markdown 结构拆开如果找不到安全的插入锚点就追加块而不是冒险破坏结构如果 PR 中已存在标记块只移动或替换整块其余无关文字必须逐字节保留发布后打开渲染后的 PR确认主要证据出现在补充演示之前、实现细节之前。五、Publish用 gh CLI 发布5.1 保留既有描述、替换标记块发布的核心是保留现有 PR 描述只替换本 Skill 的标记块PR123 gh pr view $PR --json body --jq .body /tmp/pr-body.md node skill/scripts/format.mjs \ --body-file /tmp/pr-body.md \ --before captures/desktop-before.png \ --after captures/desktop-after.png \ /tmp/pr-body-next.md ATTACH_ARGS() while IFS read -r file; do ATTACH_ARGS(--attach $file) done ( node skill/scripts/format.mjs \ --attach-list \ --before captures/desktop-before.png \ --after captures/desktop-after.png ) gh pr edit $PR --body-file /tmp/pr-body-next.md ${ATTACH_ARGS[]}要点格式化器与gh必须在同一目录运行gh --attach会把本地文件上传到 GitHub并在 PR 正文中改写对应的本地引用发布后重新获取/打开 PR 描述确认标记块内不再残留./captures/...引用且证据按预期阅读顺序出现。5.2 发布视频表格两阶段操作视频对比是一等公民的两步发布流程第 1 步用默认的独立行输出 gh pr comment --attach把本地视频先上传到一个临时 PR 评论中第 2 步通过gh api获取该评论按 before/after 顺序收集稳定的https://github.com/user-attachments/assets/...附件 URL第 3 步用这些最终 URL 生成 HTML 表格并替换 PR 标记块node skill/scripts/format.mjs \ --body-file /tmp/pr-body.md \ --before-video-url https://github.com/user-attachments/assets/BEFORE_ID \ --after-video-url https://github.com/user-attachments/assets/AFTER_ID \ --label Desktop hero \ /tmp/pr-body-next.md gh pr edit $PR --body-file /tmp/pr-body-next.md生成的表格形态为tabletr/th/td结构video src... width100% controls/video位于单元格内before 与 after 各占一列支持controls播放。第 4 步在删除临时评论前先获取编辑后的 PR 正文确认两个最终 URL 都在、没有任何本地视频路径残留然后才删除临时评论第 5 步打开渲染后的 PR确认两个video元素都在对比表格内、达到可播放的 ready 状态并显示控件。回退策略如果 URL 提取、格式化或 PR 校验失败保留临时评论其上传的附件仍可恢复从最后一个成功阶段重试独立行视频是简单的回退方案。5.3 安全红线绝不发布包含以下内容的捕获文件Vercel OIDC token、绕过密钥bypass secrets、已认证的 query 参数、浏览器状态文件。六、脚本契约format.mjs 源码级解读scripts/format.mjs是有意为之的唯一捆绑脚本这一点由 Skill 文档与源码共同确认。结合 format.mjs 的源码其职责契约如下能力源码实现说明格式化已有本地媒体formatMarkdown()format.mjs图片渲染为\| Before \| After \|两列表格after-only 渲染为单列Preview格式化 GitHub 视频附件 URL 为 HTML 对比表formatVideoTables()与githubAttachmentUrl()format.mjs只接受https://github.com/user-attachments/assets/...形式协议/主机/路径三段校验after-only 媒体标记为PreviewrenderImagePair()/renderVideoPair()的 else 分支无--before时表头为Preview输出精确的附件路径列表attachList()format.mjs对 before/after 做Set去重供gh --attach消费插入或替换标记块、不碰其他 PR 文字replaceMarkedBlock()format.mjs以!-- before-and-after:start --/!-- before-and-after:end --为界整体替换值得注意的源码细节媒体类型校验mediaKind()format.mjs按扩展名识别 image/video不支持的格式直接抛错formatMarkdown()还要求 before 与 after必须是同一媒体类型图片对图片、视频对视频否则抛错路径安全约束localRef()format.mjs强制媒体文件必须位于工作目录内不允许..逃逸且路径不得含空白字符——与文档中的保存规范一一对应参数配对校验buildPairs()format.mjs要求--after至少一个、--before要么全无要么与--after一一对应、--label不超过--after数量两种模式互斥main()format.mjs强制本地--after文件与最终--after-video-url只能二选一--attach-list也仅限本地媒体模式标记块唯一性replaceMarkedBlock()会拒绝标记块不完整只有 start 没有 end 或反之以及存在多个标记块的 PR 正文避免破坏性合并。这些参数随本 Skill 版本演化不是公开的库 API——即format.mjs的 CLI 参数只对本 Skill 有契约意义不应作为外部项目依赖使用。七、适用前提与局限本文所有命令、参数与行为均以当前仓库 SKILL.md 与 format.mjs 的实现为准10 fps 录制上限是agent-browser0.35.2/0.36.0的行为应检查实际安装版本而非假设未来版本不变视频表格发布依赖 GitHub 的user-attachments附件机制与ghCLI 的--attach、pr edit、pr comment、api子命令需在与格式化器相同的目录下运行本 Skill 与agent-browser之间的职责边界是捕获归浏览器工具编排与发布归本 Skill——不要试图在本 Skill 中复刻认证或捕获逻辑。【免费下载链接】sanitySanity Studio – Rapidly configure content workspaces powered by structured content项目地址: https://gitcode.com/GitHub_Trending/sa/sanity创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考