@hyperframes/parsers 0.7.15 → 0.7.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -370,6 +370,31 @@ function objectExpressionToRecord(node, scope, source) {
370
370
  function isGsapTimelineCall(node) {
371
371
  return node?.type === "CallExpression" && node.callee?.type === "MemberExpression" && node.callee.object?.name === "gsap" && node.callee.property?.name === "timeline";
372
372
  }
373
+ function staticMemberKey(node) {
374
+ if (!node || node.type !== "MemberExpression") return null;
375
+ if (node.computed) {
376
+ const p = node.property;
377
+ if (p?.type === "Literal" && typeof p.value === "string") return p.value;
378
+ return null;
379
+ }
380
+ return node.property?.type === "Identifier" ? node.property.name : null;
381
+ }
382
+ function isStaticMemberRef(node) {
383
+ return node?.type === "MemberExpression" && staticMemberKey(node) !== null;
384
+ }
385
+ function sameMemberAccess(a, b) {
386
+ if (a?.type !== "MemberExpression" || b?.type !== "MemberExpression") return false;
387
+ if (staticMemberKey(a) !== staticMemberKey(b) || staticMemberKey(a) === null) return false;
388
+ const ao = a.object;
389
+ const bo = b.object;
390
+ if (ao?.type === "Identifier" && bo?.type === "Identifier") return ao.name === bo.name;
391
+ if (ao?.type === "MemberExpression" && bo?.type === "MemberExpression")
392
+ return sameMemberAccess(ao, bo);
393
+ return false;
394
+ }
395
+ function timelineRootSource(ref, script) {
396
+ return ref.kind === "identifier" ? ref.name : script.slice(ref.node.start, ref.node.end);
397
+ }
373
398
  function extractTimelineDefaults(callNode, scope) {
374
399
  const arg = callNode.arguments?.[0];
375
400
  if (!arg || arg.type !== "ObjectExpression") return void 0;
@@ -389,6 +414,7 @@ function extractTimelineDefaults(callNode, scope) {
389
414
  }
390
415
  function findTimelineVar(ast, scope) {
391
416
  let timelineVar = null;
417
+ let ref = null;
392
418
  let timelineCount = 0;
393
419
  let defaults;
394
420
  const emptyScope = scope ?? /* @__PURE__ */ new Map();
@@ -396,8 +422,9 @@ function findTimelineVar(ast, scope) {
396
422
  VariableDeclarator(node) {
397
423
  if (isGsapTimelineCall(node.init)) {
398
424
  timelineCount += 1;
399
- if (!timelineVar) {
400
- timelineVar = node.id?.name ?? null;
425
+ if (!ref && node.id?.type === "Identifier") {
426
+ timelineVar = node.id.name;
427
+ ref = { kind: "identifier", name: node.id.name };
401
428
  defaults = extractTimelineDefaults(node.init, emptyScope);
402
429
  }
403
430
  }
@@ -405,15 +432,21 @@ function findTimelineVar(ast, scope) {
405
432
  AssignmentExpression(node) {
406
433
  if (isGsapTimelineCall(node.right)) {
407
434
  timelineCount += 1;
408
- if (!timelineVar) {
435
+ if (!ref) {
409
436
  const left = node.left;
410
- if (left?.type === "Identifier") timelineVar = left.name;
411
- defaults = extractTimelineDefaults(node.right, emptyScope);
437
+ if (left?.type === "Identifier") {
438
+ timelineVar = left.name;
439
+ ref = { kind: "identifier", name: left.name };
440
+ defaults = extractTimelineDefaults(node.right, emptyScope);
441
+ } else if (isStaticMemberRef(left)) {
442
+ ref = { kind: "member", node: left };
443
+ defaults = extractTimelineDefaults(node.right, emptyScope);
444
+ }
412
445
  }
413
446
  }
414
447
  }
415
448
  });
416
- return { timelineVar, timelineCount, defaults };
449
+ return { timelineVar, ref, timelineCount, defaults };
417
450
  }
418
451
  var BUILTIN_VAR_KEYS = /* @__PURE__ */ new Set(["duration", "ease", "delay"]);
419
452
  var DROPPED_VAR_KEYS = /* @__PURE__ */ new Set(["onComplete", "onStart", "onUpdate", "onRepeat"]);
@@ -426,14 +459,15 @@ var EXTRAS_KEYS = /* @__PURE__ */ new Set([
426
459
  "overwrite",
427
460
  "immediateRender"
428
461
  ]);
429
- function isTimelineRootedCall(callNode, timelineVar) {
462
+ function isTimelineRootedCall(callNode, ref) {
430
463
  let obj = callNode.callee?.object;
431
464
  while (obj?.type === "CallExpression") {
432
465
  obj = obj.callee?.object;
433
466
  }
434
- return obj?.type === "Identifier" && obj.name === timelineVar;
467
+ if (ref.kind === "identifier") return obj?.type === "Identifier" && obj.name === ref.name;
468
+ return sameMemberAccess(obj, ref.node);
435
469
  }
436
- function findAllTweenCalls(ast, timelineVar, scope, targetBindings) {
470
+ function findAllTweenCalls(ast, ref, scope, targetBindings) {
437
471
  const results = [];
438
472
  function visit(node, ancestors) {
439
473
  if (!node || typeof node !== "object") return;
@@ -442,7 +476,7 @@ function findAllTweenCalls(ast, timelineVar, scope, targetBindings) {
442
476
  const callee = node.callee;
443
477
  const gsapSetArg = node.arguments?.[0];
444
478
  const isGlobalSet = callee?.type === "MemberExpression" && callee.object?.type === "Identifier" && callee.object.name === "gsap" && callee.property?.type === "Identifier" && callee.property.name === "set" && (gsapSetArg?.type === "StringLiteral" || gsapSetArg?.type === "Literal" && typeof gsapSetArg.value === "string");
445
- if (callee?.type === "MemberExpression" && callee.property?.type === "Identifier" && (isTimelineRootedCall(node, timelineVar) || isGlobalSet) && GSAP_METHODS.has(callee.property.name)) {
479
+ if (callee?.type === "MemberExpression" && callee.property?.type === "Identifier" && (isTimelineRootedCall(node, ref) || isGlobalSet) && GSAP_METHODS.has(callee.property.name)) {
446
480
  const method = callee.property.name;
447
481
  const args = node.arguments;
448
482
  const selectorValue = args.length >= 1 ? resolveTargetSelector(args[0], nodeAncestors, scope, targetBindings) ?? "__unresolved__" : "__unresolved__";
@@ -895,8 +929,9 @@ function parseGsapScriptAcornForWrite(script) {
895
929
  const scope = collectScopeBindings(ast);
896
930
  const targetBindings = collectTargetBindings(ast, scope);
897
931
  const detection = findTimelineVar(ast, scope);
898
- const timelineVar = detection.timelineVar ?? "tl";
899
- const calls = findAllTweenCalls(ast, timelineVar, scope, targetBindings);
932
+ const ref = detection.ref ?? { kind: "identifier", name: "tl" };
933
+ const timelineVar = timelineRootSource(ref, script);
934
+ const calls = findAllTweenCalls(ast, ref, scope, targetBindings);
900
935
  sortBySourcePosition(calls);
901
936
  const rawAnims = calls.map((call) => tweenCallToAnimation(call, scope, script));
902
937
  applyTimelineDefaults(rawAnims, detection.defaults);
@@ -907,7 +942,7 @@ function parseGsapScriptAcornForWrite(script) {
907
942
  call,
908
943
  animation: animations[i]
909
944
  }));
910
- return { ast, timelineVar, hasTimeline: detection.timelineVar !== null, located };
945
+ return { ast, timelineVar, hasTimeline: detection.ref !== null, located };
911
946
  } catch {
912
947
  return null;
913
948
  }
@@ -1063,9 +1098,11 @@ function reconcileEditableProps(ms, objNode, source, newProps, nonEditableOverri
1063
1098
  }
1064
1099
  ms.overwrite(objNode.start, objNode.end, `{ ${entries.join(", ")} }`);
1065
1100
  }
1066
- function isTimelineRooted(node, timelineVar) {
1101
+ function isTimelineRooted(node, timelineVar, script) {
1067
1102
  if (node?.type === "Identifier") return node.name === timelineVar;
1068
- if (node?.type === "CallExpression") return isTimelineRooted(node.callee?.object, timelineVar);
1103
+ if (node?.type === "MemberExpression") return script.slice(node.start, node.end) === timelineVar;
1104
+ if (node?.type === "CallExpression")
1105
+ return isTimelineRooted(node.callee?.object, timelineVar, script);
1069
1106
  return false;
1070
1107
  }
1071
1108
  function findInsertionPoint(parsed) {
@@ -1372,10 +1409,17 @@ function updateKeyframeInScript(script, animationId, percentage, properties, eas
1372
1409
  if (kfPropNode.value?.type !== "ObjectExpression") return script;
1373
1410
  const match = findKfPropByPct(kfPropNode.value, percentage);
1374
1411
  if (!match) return script;
1375
- const record = { ...properties };
1376
- if (ease) record.ease = ease;
1377
1412
  const ms = new MagicString(script);
1378
- ms.overwrite(match.prop.value.start, match.prop.value.end, recordToCode(record));
1413
+ if (match.prop.value?.type === "ObjectExpression") {
1414
+ for (const [k, v] of Object.entries(properties)) {
1415
+ upsertProp(ms, match.prop.value, k, v);
1416
+ }
1417
+ if (ease !== void 0) upsertProp(ms, match.prop.value, "ease", ease);
1418
+ } else {
1419
+ const record = { ...properties };
1420
+ if (ease) record.ease = ease;
1421
+ ms.overwrite(match.prop.value.start, match.prop.value.end, recordToCode(record));
1422
+ }
1379
1423
  return ms.toString();
1380
1424
  }
1381
1425
  function updateArrayKeyframeByPct(script, arrayNode, percentage, properties, ease) {
@@ -1854,18 +1898,18 @@ function splitIntoPropertyGroupsFromScript(script, animationId) {
1854
1898
  const newIds = (reParsed?.located ?? []).filter((l) => l.animation.targetSelector === animation.targetSelector).map((l) => l.id);
1855
1899
  return { script: result, ids: newIds };
1856
1900
  }
1857
- function isTimelineMethodCall(expr, timelineVar, method) {
1858
- return expr?.type === "CallExpression" && expr.callee?.type === "MemberExpression" && isTimelineRooted(expr.callee.object, timelineVar) && expr.callee.property?.name === method;
1901
+ function isTimelineMethodCall(expr, timelineVar, method, script) {
1902
+ return expr?.type === "CallExpression" && expr.callee?.type === "MemberExpression" && isTimelineRooted(expr.callee.object, timelineVar, script) && expr.callee.property?.name === method;
1859
1903
  }
1860
- function isAddLabelCall(expr, timelineVar, name) {
1904
+ function isAddLabelCall(expr, timelineVar, name, script) {
1861
1905
  const firstArg = expr?.arguments?.[0];
1862
- return isTimelineMethodCall(expr, timelineVar, "addLabel") && firstArg?.type === "Literal" && firstArg.value === name;
1906
+ return isTimelineMethodCall(expr, timelineVar, "addLabel", script) && firstArg?.type === "Literal" && firstArg.value === name;
1863
1907
  }
1864
- function findLabelStatements(parsed, name) {
1908
+ function findLabelStatements(parsed, name, script) {
1865
1909
  const targets = [];
1866
1910
  acornWalk2.simple(parsed.ast, {
1867
1911
  ExpressionStatement(node) {
1868
- if (isAddLabelCall(node.expression, parsed.timelineVar, name)) targets.push(node);
1912
+ if (isAddLabelCall(node.expression, parsed.timelineVar, name, script)) targets.push(node);
1869
1913
  }
1870
1914
  });
1871
1915
  return targets;
@@ -1873,7 +1917,7 @@ function findLabelStatements(parsed, name) {
1873
1917
  function addLabelToScript(script, name, position) {
1874
1918
  const parsed = parseGsapScriptAcornForWrite(script);
1875
1919
  if (!parsed) return script;
1876
- const existing = findLabelStatements(parsed, name)[0];
1920
+ const existing = findLabelStatements(parsed, name, script)[0];
1877
1921
  if (existing) {
1878
1922
  const ms2 = new MagicString(script);
1879
1923
  const posArg = existing.expression.arguments?.[1];
@@ -1891,7 +1935,7 @@ function addLabelToScript(script, name, position) {
1891
1935
  function removeLabelFromScript(script, name) {
1892
1936
  const parsed = parseGsapScriptAcornForWrite(script);
1893
1937
  if (!parsed) return script;
1894
- const targets = findLabelStatements(parsed, name);
1938
+ const targets = findLabelStatements(parsed, name, script);
1895
1939
  if (!targets.length) return script;
1896
1940
  const ms = new MagicString(script);
1897
1941
  for (const target of targets) {