十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

如何用 @hyperframes/parsers 解析 HTML 合成并安全改写 GSAP 时间线脚本

如何用 @hyperframes/parsers 解析 HTML 合成并安全改写 GSAP 时间线脚本 如何用 hyperframes/parsers 解析 HTML 合成并安全改写 GSAP 时间线脚本【免费下载链接】hyperframesWrite HTML. Render video. Built for agents.项目地址: https://gitcode.com/GitHub_Trending/hy/hyperframes当你在 hyperframes 组合composition之上构建工具——例如让 agent 自动调整动画节奏、批量移动时间线上的元素或做一个“改完写回原文件”的自动化脚本——就需要先把 HTML 组合解析成结构化模型再修改其中的 GSAP 时间线脚本同时保证脚本里与目标动画无关的代码一行都不变。hyperframes 仓库里的hyperframes/parsers包就是为这一层设计的它没有hyperframes/*运行时依赖可以脱离框架其余部分单独使用。GSAP 改写的核心是“解析 → 变更 → 重新序列化”的往返round-trip写路径按字节区间做 splice编辑区间之外的内容逐字节保留。这条路径的完整操作顺序是安装包 → 解析 HTML 组合取出 GSAP 脚本 → 把脚本解析成结构化动画模型 → 用 writer 助手函数改写 → 通过再解析与校验确认结果。安装与导入入口npm install hyperframes/parsers官方文档明确提示大多数用户不需要直接安装hyperframes/parsers——hyperframes/core已经重新导出了它需要的解析器 APICLI 和 studio 也是传递依赖它。只有当你想要纯解析层、不引入 core 的 runtime / compiler / generators 时才直接使用这个包。包提供一组聚焦的 subpath 入口本场景涉及的是导入路径用途hyperframes/parsersHTML 解析器、GSAP 序列化/校验助手、hf-ids、共享类型hyperframes/parsers/gsap-parser-acornAcorn 实现的 GSAP 解析器读路径browser-safehyperframes/parsers/gsap-writer-acornAcorn 实现的 GSAP 写路径mutation 助手函数hyperframes/parsers/gsap-constantsSUPPORTED_PROPS、SUPPORTED_EASES、属性分组hyperframes/parsers/hf-ids确定性的元素 id 打戳两个实现要点读路径基于 acorn acorn-walk无 Node 全局、无fs/require可以打进浏览器 bundle写路径基于 magic-string 做字节区间覆写编辑区间外的每一个字节都原样保留没有任何 pretty-printer 重排。hyperframes/parsers/gsap-parser-recast是遗留的 recast 实现新代码走 acorn 路径。解析 HTML 组合取出时间线脚本把组合 HTML 文件读入字符串后交给parseHtml它在 HTML 与结构化数据之间往返import { parseHtml, extractCompositionMetadata, validateCompositionHtml, } from hyperframes/parsers; // 把 HTML 解析成结构化数据 const parsed parseHtml(htmlString); // parsed.elements, parsed.gsapScript, parsed.styles, parsed.resolution, parsed.keyframes // 提取组合元数据id、duration、尺寸、variables const meta extractCompositionMetadata(htmlString); // 校验 HTML 结构 const result validateCompositionHtml(htmlString); // result.valid, result.errors如果validateCompositionHtml返回valid: false先根据errors处理文档结构问题再进入脚本改写环节。后续步骤的操作对象是parsed.gsapScript这个字符串。如果工具需要稳定的元素标识来做 diff 与编辑先用ensureHfIds给文档打戳import { ensureHfIds } from hyperframes/parsers/hf-ids; // 给文档中每个可编辑元素盖上 hf-id 属性 const withIds ensureHfIds(htmlString);hf-id是确定性的同一份文档每次打戳结果相同因此可以作为跨轮次 diff 和定位改写的锚点。只改时间线、不涉及元素身份识别的工具可以跳过这一步。把时间线脚本解析成结构化模型对parsed.gsapScript调用parseGsapScriptAcorn得到ParsedGsap对象import { parseGsapScriptAcorn, extractGsapLabels } from hyperframes/parsers/gsap-parser-acorn; const gsap parseGsapScriptAcorn(scriptContent); // gsap.animations, gsap.timelineVar, gsap.preamble, gsap.postamble几个关键点gsap.timelineVar是时间线变量名tl gsap.timeline()中的tlwriter 生成和定位 tween 语句时依赖它gsap.animations每一项是GsapAnimationid、targetSelector、methodset/to/from/fromTo、position、properties、duration、ease以及可选的keyframes与extrasstagger、yoyo、repeat 这类不可编辑配置往返时会被保留id是基于内容生成的不是基于位置——同一条 tween 无论排在脚本哪个位置id 都稳定。所以“先按targetSelector或 id 找到动画再拿 id 去改写”是安全的定位方式extractGsapLabels(script)可以取出脚本中的 label 信息供需要按 label 跳转的工具使用ParsedGsap上还有multipleTimelines和unsupportedTimelinePattern两个可选标志使用 writer 之前先确认脚本落在受支持的单一时间线形态内。改动前用常量表核对要写入的属性与缓动值是否在支持集合里import { SUPPORTED_PROPS, SUPPORTED_EASES } from hyperframes/parsers/gsap-constants;用 writer 助手函数改写脚本所有 mutation 助手都直接操作脚本文本并返回新字符串不相关的代码原样保留。主路径 API 如下签名与仓库源码一致import { updateAnimationInScript, addAnimationToScript, removeAnimationFromScript, shiftPositionsInScript, scalePositionsInScript, } from hyperframes/parsers/gsap-writer-acorn; // 更新单条动画文档中的标准示例 const next updateAnimationInScript(scriptContent, animationId, { duration: 2 }); // 新增动画返回值包含新条目的内容式 id const { script: withNew, id: newId } addAnimationToScript(scriptContent, newAnimation); // 按 id 移除一条动画 const cleaned removeAnimationFromScript(scriptContent, animationId); // 把某个 selector 的全部 tween 平移 delta 秒结果位置被钳制在 ≥ 0 const moved shiftPositionsInScript(scriptContent, #card, 0.5); // 把旧片段 [oldStart, oldDuration] 线性重映射到 [newStart, newDuration]position 与 duration 按比例换算 const resized scalePositionsInScript(scriptContent, #card, 0, 2, 0.5, 3);实现中内置了几条安全性质对照 gsapWriterAcorn.ts 源码可以逐一确认失败即 no-opwriter 助手内部先执行parseGsapScriptAcornForWrite解析失败或animationId找不到时原样返回输入脚本。也就是说“返回的字符串和输入完全相同”本身就是一次信号——改写没有生效先回到解析结果排查而不是以为改掉了更新语义要分清updateAnimationInScript传properties是替换可编辑属性集合不在更新里的可编辑 key 会被移除只传duration/ease/extras是就地 upsert传position会覆写 tween 调用的位置参数调用原本没有显式位置参数时则补一个每个元素只保留一个位置写入dedupePositionWritesInScript(script, selector, keepId?)会移除同一 selector 上其他纯位置写入包括duration: 0的退化 tween避免两处位置写入互相静默覆盖。提交位置类改动拖拽、加 keyframe之后应调用它维持该不变量keyframe 级编辑对使用keyframes: { ... }的脚本另有updateKeyframeInScript/addKeyframeToScript/removeKeyframeFromScript等助手。如果脚本里的值是运行时动态算出来的注意可编辑性边界。解析器会给每条 tween 标注来源provenance并据此划分三种可编辑性direct—— 字面量 tween可直接就地编辑unroll—— helper/循环展开生成需先展开成字面量 tween 再编辑source—— 运行时动态值静态编辑不适用只能直接改源码。所以改写前检查目标动画的hasUnresolvedSelector/hasUnresolvedKeyframes值来自source的动画AST 改写路径不适用改代码本身。端到端示例与结果验证下面是一个可运行的最小端到端示例脚本内容为示例值API 调用可直接执行import { parseGsapScriptAcorn } from hyperframes/parsers/gsap-parser-acorn; import { updateAnimationInScript, shiftPositionsInScript } from hyperframes/parsers/gsap-writer-acorn; import { validateCompositionGsap } from hyperframes/parsers; const script [ const tl gsap.timeline();, tl.from(#title, { opacity: 0, y: 40, duration: 0.8, ease: power2.out }, 0);, tl.to(#card, { x: 120, duration: 1.2, ease: power1.inOut }, 0.4);, ].join(\n); // 1) 解析并定位动画 const before parseGsapScriptAcorn(script); const target before.animations.find((a) a.targetSelector #card); // 2) 改写把 duration 改为 2s再把该 selector 整体后移 0.5s let next updateAnimationInScript(script, target.id, { duration: 2 }); next shiftPositionsInScript(next, #card, 0.5); // 3) 验证重新解析确认改动落地、条目数量未变 const after parseGsapScriptAcorn(next); const edited after.animations.find((a) a.id target.id); console.assert(edited.duration 2, duration should be 2); console.assert(edited.position 0.9, position should be 0.4 0.5); console.assert(after.animations.length before.animations.length, animation count unchanged); // 4) 脚本级校验 const check validateCompositionGsap(next); console.assert(check.valid, check.errors.join(; ));验证逻辑逐条说明再解析 diffid基于内容稳定shiftPositionsInScript只重写目标 selector 的位置参数所以“同 id 字段已更新 总数不变”三者同时成立才说明改到了正确的那条动画且没伤及其他条目no-op 检查如果next script说明改写完全没有发生——脚本没解析成功或 id 不匹配回到解析结果里核对脚本级校验validateCompositionGsap返回valid与errors也可以用getAnimationsForElementId拉取某元素的全部动画做交叉核对仓库自身用 golden 文件锁定这套往返契约goldens目录 提供 minimal、moderate、complex、fromto 四组.parsed.json/.serialized.js样本对gsapParser.golden.test.ts 用它们断言解析与序列化结果gsapWriter.parity.test.ts 交叉核对 acorn 与 recast 两种写实现的输出。如果你的批量改写工具需要回归保障可以照这个思路为自己的一组输入/输出样本建 golden 断言。边界与不支持项不要使用 recast 路径hyperframes/parsers/gsap-parser-recast是遗留实现源码注释明确读路径已切换到parseGsapScriptAcorn、写路径切换到 acorn writer新代码一律用gsap-parser-acorn/gsap-writer-acorn。asset-pathssubpath 仅限 Nodehyperframes/parsers/asset-paths提供的资产路径改写助手是 Node-only 的主入口与 acorn 解析/写路径是 browser-safe。工具若要在浏览器运行不要引入该 subpath。单一时间线形态编辑前确认ParsedGsap的multipleTimelines/unsupportedTimelinePattern均未置位否则不要对该脚本走 writer 路径。与 core 的 API 不重复引入如果你的工具已经依赖hyperframes/core直接使用它重新导出的解析器 API 即可hyperframes/lint与hyperframes/studio-server同样构建在 parsers 之上写校验或预览类工具时可以先看这两个包的消费方式。下一步本包的完整入口清单与使用提示见 parsers 包文档改写后的脚本要过 lint 的话见 lint 包文档元素身份打戳的规则见 hfIds.tsHTML 解析与校验的实现见 htmlParser.ts。【免费下载链接】hyperframesWrite HTML. Render video. Built for agents.项目地址: https://gitcode.com/GitHub_Trending/hy/hyperframes创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表