MCPcopy Create free account
hub / github.com/heygen-com/hyperframes / removeKeyframeFromScript

Function removeKeyframeFromScript

packages/parsers/src/gsapParser.ts:2261–2323  ·  view source on GitHub ↗
(
  script: string,
  animationId: string,
  percentage: number,
)

Source from the content-addressed store, hash-verified

2259 * remaining keyframe's properties.
2260 */
2261export function removeKeyframeFromScript(
2262 script: string,
2263 animationId: string,
2264 percentage: number,
2265): string {
2266 // Array-form keyframes (`keyframes: [{x,y}, …]`) have no explicit percentages —
2267 // GSAP distributes them evenly. The object-form path below can't see them
2268 // (findKeyframesObjectNode only matches ObjectExpression), so removing from an
2269 // array-form tween silently no-op'd. Resolve the element by its implicit
2270 // percentage and splice it; collapse to a flat tween when fewer than two remain.
2271 const arrLoc = locateAnimationWithFallback(script, animationId);
2272 // findPropertyNode here returns the property's VALUE node directly.
2273 const arrVal = arrLoc && findPropertyNode(arrLoc.target.call.varsArg, "keyframes");
2274 if (arrLoc && arrVal?.type === "ArrayExpression") {
2275 const elements: AstNode[] = (arrVal.elements ?? []).filter(
2276 (e: AstNode | null): e is AstNode => !!e && e.type === "ObjectExpression",
2277 );
2278 const n = elements.length;
2279 if (n === 0) return script;
2280 let matchIdx = -1;
2281 let bestDist = Number.POSITIVE_INFINITY;
2282 for (let i = 0; i < n; i++) {
2283 const pct = n > 1 ? (i / (n - 1)) * 100 : 0;
2284 const dist = Math.abs(pct - percentage);
2285 if (dist <= PCT_TOLERANCE && dist < bestDist) {
2286 matchIdx = i;
2287 bestDist = dist;
2288 }
2289 }
2290 if (matchIdx === -1) return script;
2291 const remaining = elements.filter((_, i) => i !== matchIdx);
2292 if (remaining.length < 2) {
2293 const sole = remaining[0];
2294 const record = sole ? objectExpressionToRecord(sole, arrLoc.parsed.scope) : {};
2295 collapseKeyframesToFlat(arrLoc.target.call.varsArg, record);
2296 } else {
2297 const realIdx = arrVal.elements.indexOf(elements[matchIdx]);
2298 arrVal.elements.splice(realIdx, 1);
2299 }
2300 return recast.print(arrLoc.parsed.ast).code;
2301 }
2302
2303 const ctx = locateKeyframeCtx(script, animationId, percentage);
2304 if (!ctx) return script;
2305 const { loc, kfNode } = ctx;
2306
2307 const match = findKeyframePropByPct(kfNode, percentage);
2308 if (!match) return script;
2309 const removeIdx = match.idx;
2310
2311 kfNode.properties.splice(removeIdx, 1);
2312
2313 const remainingKfs = filterPercentageProps(kfNode);
2314 if (remainingKfs.length < 2) {
2315 const record =
2316 remainingKfs.length === 1
2317 ? objectExpressionToRecord(remainingKfs[0]!.value, loc.parsed.scope)
2318 : {};

Calls 8

locateKeyframeCtxFunction · 0.85
findKeyframePropByPctFunction · 0.85
filterPercentagePropsFunction · 0.85
absMethod · 0.80
findPropertyNodeFunction · 0.70
objectExpressionToRecordFunction · 0.70
collapseKeyframesToFlatFunction · 0.70

Tested by

no test coverage detected