PromptCrate 第一次被认真 review 的时候,结果有点刺眼:REQUEST CHANGES。更尴尬的是,那个版本并非完全跑不起来。pnpm test 通过,pnpm check 通过,pnpm build 也通过。换成我刚开始写个人项目时的心态,可能已经觉得“差不多能发了”。
真正的问题藏在这些绿色结果旁边。pnpm lint 扫到了打包后解开的 release 目录,一口气报了 778 个错误。它们大多来自构建产物,可这件事本身已经说明发布流程不干净:一个准备交给别人侧载试用的插件,连本地质量门禁都需要开发者记住“别扫那个目录”,这很脆。
另一个拦路点是 dev 依赖审计。Vite、Vitest、esbuild 相关工具链有高危和严重告警。它们不会进入扩展运行时,可 README 里会鼓励开发者跑本地 dev server,CI 和测试也依赖这套链路。浏览器插件本来就运行在别人的网页上,我不想在发布前留下这种“只影响开发环境”的含糊账。
文字显示出来,不代表网页接住了
PromptCrate 的卖点很简单:按快捷键,把本地 prompt 模板插进网页输入框。原生 textarea 很容易,普通 input 也还好,麻烦来自真实 Web App。很多站点用 React controlled input、contenteditable 富文本、iframe、Shadow DOM。直接改 value 或插一个 text node,看起来能显示文字,提交时却可能被框架状态吞掉。
Review 里那句风险提醒很准:用户看到文字进去了,不代表网页真的接住了。
后面我把修复拆成几件小事。release 解包目录被明确忽略,lint 不再被构建产物污染。工具链升级后重新跑 audit,已知漏洞清零。文本输入改成 beforeinput、原生 value setter 和 input 事件组合;contenteditable 优先走 beforeinput 和 execCommand("insertText") fallback。iframe 场景也补了 frame-aware 的探测和消息路由,菜单会发给真正聚焦输入框所在的 frame。
顺手清掉几笔旧账
数据这边也清了一轮。导入 JSON 会拒绝重复 template id;storage 初始化和写入都经过 normalize、业务校验和重复 id 检查;非法历史数据会备份到 promptCrate.invalidTemplatesBackup 后再重置。content script 里那套重复的 template/storage 逻辑被删掉,改为复用 shared 模块,避免 options 和页面菜单以后各走各的规则。
最后补的是可访问性。菜单 dialog 加上 aria-modal、焦点陷阱和关闭后的焦点返回;搜索框补齐 combobox/listbox 语义;关闭按钮也从一个含糊的 x 变成有明确名称的按钮。这些改动不抢眼,可插件依赖键盘快捷键打开,键盘和读屏体验就不能靠运气。
第二天的门禁
修完后再跑一遍,结果才配得上“可侧载候选”:
- 9 个测试文件、33 个测试通过;
pnpm lint、pnpm check、pnpm build全部通过;pnpm audit --audit-level moderate没有已知漏洞;pnpm package:zip重新生成了侧载包。
它依然还没到 Chrome Web Store 发布状态,我更愿意把它叫作 side-load candidate。
这次 review 给我留下了一个很具体的提醒:小插件的工程质量,经常坏在“看起来只是边角”的地方。release 目录、dev audit、iframe、焦点返回、重复 id,这些都不像主功能,却会决定别人第一次安装时会不会信任它。PromptCrate 被打回那天不算舒服,但那份 REQUEST CHANGES 比一次草率通过更有价值。
后来
之后 PromptCrate 推进到了发布准备阶段:权限与隐私说明、release checklist、截图、图标和试用 zip 都齐了,仍然通过开发者模式侧载试用。10 月又补了一次修复,拒绝无效的、或者无法确认真的生效的模板插入——还是那句话,文字显示出来,不代表网页接住了。它还没有提交到扩展商店。