关于 apply-comments
apply-comments 是处理幻灯片 JSX 文件中反馈的技能,适用于在 open-slide 编辑器中修改幻灯片。它会解码评论标记、按要求编辑并移除已处理标记,随后检查结果。
主要功能
- 01查找并解码幻灯片评论标记
- 02按 slide-authoring 规则编辑
- 03针对目标元素或区域应用意见
- 04修改后移除标记
- 05检查 JSX 和编辑后的页面
适用场景
- 01根据视觉反馈修改幻灯片
- 02按评论更新文本或样式
- 03处理多个幻灯片文件中的评论
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ open-slide/ open-slide --skill apply-comments安装后在 Claude Code 中输入/apply-comments确认已加载。
详细介绍
应用幻灯片评论
开放幻灯片编辑器具有评论模式,用户可以点击渲染后的页面元素,或在页面区域上拖动,然后附加文字评论(例如 “把这个改成红色”、“改为 ‘Open Slide Rocks’”)。每条评论都会作为源代码中的 JSX 标记保存在 slides/<slideId>/index.tsx 中。
你的任务:读取这些标记,执行其中描述的编辑,然后删除这些标记。
在编辑任何页面之前,请先查阅
slide-authoring技能 — 它是有关slides/<id>/index.tsx结构(画布、字号比例、调色板、资源、文件约定)的技术参考。像 “把这个放大” 或 “更改强调色” 这样的评论,应以符合这些规则的方式处理。
标记格式
{/* @slide-comment id="c-<8hex>" ts="<ISO>" text="<base64url(JSON)>" */}
-
位于其所指 JSX 元素内部的第一个子元素(即该元素的开标签
>与其他子元素之间)。标记会插入其目标元素内部,而不是浮在上方。新写入的标记会单独占一行;较早的标记可能与后续内容位于同一行。 -
text是经 base64url 编码的 JSON:{"note": "...", "hint"?: "...", "rect"?: {"x", "y", "w", "h"}, "page"?: n}。- 当评论是针对拖动选中的区域而非元素时,会包含
rect。其值是以像素为单位的 1920×1080 页面画布坐标,从页面左上角开始测量。标记仍位于包含该区域的最深层元素内部,但评论指的是该区域内的内容 — 可能是多个子元素,也可能只是外层元素的一部分。 page是留下评论的页面在默认导出数组中的索引(从 0 开始)。
- 当评论是针对拖动选中的区域而非元素时,会包含
-
检测正则表达式(权威 — 请严格使用此表达式):
/\{\/\*\s*@slide-comment\s+id="(c-[a-f0-9]+)"\s+ts="([^"]+)"\s+text="([A-Za-z0-9_\-]+={0,2})"\s*\*\/\}/g
流程
-
确定目标幻灯片。
- 如果用户指定了一张(
getting-started、q2-roadmap等),则只处理对应的slides/<slideId>/index.tsx。 - 如果用户说“全部”或未指定,则扫描所有
slides/*/index.tsx。逐张处理幻灯片。
- 如果用户指定了一张(
-
读取文件并查找所有标记。
- 对整个文件运行上述正则表达式。
- 对每个匹配项,对
text进行 base64url 解码并用JSON.parse解析,得到{ note, hint?, rect?, page? }。 - 将每个命中项记录为
{ id, lineIndex (从 0 开始), note, hint, rect, page }。 - 如果没有标记,告知用户并停止。
-
结合上下文理解每条注释。
- 目标 JSX 元素是标记所在的外层元素——也就是说,从标记所在行向上查找,直到找到一个未闭合的 JSX 开始标签,其主体包含该标记。该元素就是目标。(对于
<img />这类自闭合元素,检查器会将标记提升到最近的非自闭合祖先;此时注释通常指的是外层元素的子元素,而不是外层元素本身——根据note文本判断。) - 阅读足够多的周边代码(父元素、同级元素、内联样式),以便准确应用更改。例如,
<div>中的注释若位于带有内联background样式的元素内,通常指的是该元素的样式。 - 如果载荷中有
rect,则根据其位置和尺寸与 1920×1080 画布上的rect对比,判断外层元素中哪些子元素位于该区域内,并对这些子元素应用注释,而不是对整个外层元素应用。 - 如果
note含义不明确,采用最小的合理解释,并在总结中说明所作假设。
- 目标 JSX 元素是标记所在的外层元素——也就是说,从标记所在行向上查找,直到找到一个未闭合的 JSX 开始标签,其主体包含该标记。该元素就是目标。(对于
-
按行号倒序应用编辑。
- 按
lineIndex降序排列标记,并逐个使用Edit工具处理。 - 从上往下处理会导致文件增删行后,后续标记的行号失效。
- 按
-
应用更改后移除每个标记。
- 删除标记 token。如果该行没有其他内容,则连同末尾的
\n一起删除整行;如果该行还有其他内容,则保留这些内容。 - 应用编辑后绝不能留下标记——这表示处理失败。根据下文边缘情况有意跳过的标记除外,这些标记应保留。
- 删除标记 token。如果该行没有其他内容,则连同末尾的
-
验证。
- 完成所有编辑后,重新读取文件,并确认剩余的标记只有已报告为跳过的标记。
- 确认编辑后的 JSX 格式正确(标签闭合,属性完整)。如果项目的
package.json中有类型检查或 lint 脚本,则使用项目的包管理器运行;脚手架项目不会附带 TypeScript 或 linter,因此应依靠正在运行的开发服务器(或build脚本)检查编译错误。修复引入的所有错误。 - 如果开发服务器正在运行,则通过
/s/<id>/preview?p=N为每个已编辑页面截图,确认更改的视觉效果——请参阅slide-authoring中的页面视觉预览。
-
报告。
- 总结:
应用 N 项,跳过 M 项,并为每项更改提供一行说明(包括幻灯片 ID)。
- 总结:
base64url 解码辅助代码
function decode(s) {
const pad = s.length % 4 === 0 ? '' : '='.repeat(4 - (s.length % 4));
return Buffer.from(s.replace(/-/g, '+').replace(/_/g, '/') + pad, 'base64').toString('utf8');
}
如果需要检查载荷,可以通过 node -e '...' 内联运行;否则,直接根据解码后的字符串进行判断即可。
边缘情况
- 标记没有包围它的 JSX 元素(不应该发生——检查器不会写入这种标记,但如果你发现了):删除它并注明为孤立标记。
- 同一元素内的连续多行上堆叠了多个标记:它们都指向该包围元素。按源码顺序阅读其中的备注,理解其综合意图,然后应用修改,并按步骤 4 从下往上删除标记。
- 注释要求的内容超出了目标元素的范围(例如“添加一个新页面”):尽可能进行合理的修改,并在摘要中说明扩展了范围。
- 无法处理该注释(例如确实存在歧义,或文件结构已发生变化,导致目标元素不存在):保留标记,并报告为已跳过。不要猜测。
不要
- 不要修改
package.json、open-slide.config.ts或slides/目录以外的文件。 - 不要添加依赖项。
- 不要重新引入标记或留下
TODO提示——用户已经在 git 中留有记录。