@hyperframes/lint 0.8.36 → 0.8.38

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.
package/dist/browser.js CHANGED
@@ -2840,10 +2840,6 @@ function targetHasNoStableIdentity(selector, identity) {
2840
2840
  if (identity) return false;
2841
2841
  return selector === UNRESOLVED_TARGET || selector === "dwell/hold" || selector.startsWith("proxy \u2192 ");
2842
2842
  }
2843
- function readRegisteredTimelineCompositionId(script) {
2844
- const match = script.match(WINDOW_TIMELINE_ASSIGN_PATTERN);
2845
- return match?.[1] || match?.[2] || null;
2846
- }
2847
2843
  function unwrapRaw(value) {
2848
2844
  if (typeof value === "number") return value;
2849
2845
  if (typeof value !== "string") return void 0;
@@ -3011,21 +3007,6 @@ function makesOverlayVisible(win) {
3011
3007
  if (win.method === "from" && isHiddenGsapState(win.propertyValues)) return true;
3012
3008
  return isVisibleGsapState(win.propertyValues);
3013
3009
  }
3014
- function isSceneBoundaryExit(win) {
3015
- if (win.end <= win.position) return false;
3016
- if (win.method !== "to" && win.method !== "fromTo") return false;
3017
- return isHiddenGsapState(win.propertyValues);
3018
- }
3019
- function isHardKillSet(win, selector, boundary) {
3020
- return win.method === "set" && win.targetSelector === selector && Math.abs(win.position - boundary) <= SCENE_BOUNDARY_EPSILON_SECONDS && isHiddenGsapState(win.propertyValues);
3021
- }
3022
- function hiddenStateLiteral(values) {
3023
- if (zeroValue(values.autoAlpha)) return "{ autoAlpha: 0 }";
3024
- if (zeroValue(values.opacity)) return "{ opacity: 0 }";
3025
- if (stringValue(values.visibility)?.toLowerCase() === "hidden") return '{ visibility: "hidden" }';
3026
- if (stringValue(values.display)?.toLowerCase() === "none") return '{ display: "none" }';
3027
- return "{ opacity: 0 }";
3028
- }
3029
3010
  function findTagEnd(source, tag) {
3030
3011
  const escapedTagName = tag.name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
3031
3012
  const pattern = new RegExp(`<\\/?${escapedTagName}\\b[^>]*>`, "gi");
@@ -3042,56 +3023,11 @@ function findTagEnd(source, tag) {
3042
3023
  }
3043
3024
  return source.length;
3044
3025
  }
3045
- function collectCompositionRanges(source, tags) {
3046
- return tags.map((tag) => {
3047
- const id = readDecodedAttr(tag.raw, "data-composition-id");
3048
- if (!id) return null;
3049
- return {
3050
- id,
3051
- start: tag.index,
3052
- end: findTagEnd(source, tag)
3053
- };
3054
- }).filter((range) => range !== null);
3055
- }
3056
- function findContainingCompositionId(tag, ranges) {
3057
- let match = null;
3058
- for (const range of ranges) {
3059
- if (tag.index < range.start || tag.index >= range.end) continue;
3060
- if (!match || range.start >= match.start) match = range;
3061
- }
3062
- return match?.id || null;
3063
- }
3064
3026
  function getClipTagClasses(tag) {
3065
3027
  const classAttr = readAttr(tag.raw, "class") || "";
3066
3028
  const classes = classAttr.split(/\s+/).filter(Boolean);
3067
3029
  return classes.includes("clip") ? { classAttr, classes } : null;
3068
3030
  }
3069
- function collectClipStartBoundariesByComposition(source, tags) {
3070
- const ranges = collectCompositionRanges(source, tags);
3071
- const boundaries = /* @__PURE__ */ new Map();
3072
- for (const tag of tags) {
3073
- if (!getClipTagClasses(tag)) continue;
3074
- const compositionId = findContainingCompositionId(tag, ranges);
3075
- if (!compositionId) continue;
3076
- const start = numberValue(readAttr(tag.raw, "data-start") ?? void 0);
3077
- if (start == null || start <= 0) continue;
3078
- const compositionBoundaries = boundaries.get(compositionId) ?? /* @__PURE__ */ new Set();
3079
- compositionBoundaries.add(start);
3080
- boundaries.set(compositionId, compositionBoundaries);
3081
- }
3082
- return new Map(
3083
- [...boundaries.entries()].map(([compositionId, values]) => [
3084
- compositionId,
3085
- [...values].sort((a, b) => a - b)
3086
- ])
3087
- );
3088
- }
3089
- function findMatchingSceneBoundary(time, boundaries) {
3090
- for (const boundary of boundaries) {
3091
- if (Math.abs(time - boundary) <= SCENE_BOUNDARY_EPSILON_SECONDS) return boundary;
3092
- }
3093
- return null;
3094
- }
3095
3031
  function readStyleProperty(style, property) {
3096
3032
  const escapedProperty = property.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
3097
3033
  const match = style.match(new RegExp(`(?:^|;)\\s*${escapedProperty}\\s*:\\s*([^;]+)`, "i"));
@@ -3590,7 +3526,7 @@ var gsapRules = [
3590
3526
  },
3591
3527
  // overlapping_gsap_tweens + gsap_animates_clip_element
3592
3528
  // fallow-ignore-next-line complexity
3593
- async ({ source, tags, scripts, styles, rootCompositionId }) => {
3529
+ async ({ tags, scripts, styles }) => {
3594
3530
  const findings = [];
3595
3531
  const authoredHiddenSelectors = new Set(
3596
3532
  scripts.flatMap((script) => [...extractStandaloneHiddenSelectors(script.content)])
@@ -3611,13 +3547,10 @@ var gsapRules = [
3611
3547
  if (cls !== "clip") clipClasses.set(`.${cls}`, info);
3612
3548
  }
3613
3549
  }
3614
- const clipStartBoundariesByComposition = collectClipStartBoundariesByComposition(source, tags);
3615
3550
  const styleRules = collectSimpleStyleRules(styles);
3616
3551
  const reportedVisibleOverlayKeys = /* @__PURE__ */ new Set();
3617
3552
  for (const script of scripts) {
3618
- const localTimelineCompId = readRegisteredTimelineCompositionId(script.content);
3619
3553
  const gsapWindows = await cachedExtractGsapWindows(script.content);
3620
- const clipStartBoundaries = clipStartBoundariesByComposition.get(localTimelineCompId || rootCompositionId || "") ?? [];
3621
3554
  for (let i = 0; i < gsapWindows.length; i++) {
3622
3555
  const left = gsapWindows[i];
3623
3556
  if (!left) continue;
@@ -3679,28 +3612,6 @@ ${right.raw}`)
3679
3612
  snippet: truncateSnippet(fromToWindows.map((win) => win.raw).join("\n"))
3680
3613
  });
3681
3614
  }
3682
- if (clipStartBoundaries.length > 0) {
3683
- for (const win of gsapWindows) {
3684
- if (win.targetSelector === UNRESOLVED_TARGET) continue;
3685
- if (!isSceneBoundaryExit(win)) continue;
3686
- const boundary = findMatchingSceneBoundary(win.end, clipStartBoundaries);
3687
- if (boundary == null) continue;
3688
- const hasHardKill = gsapWindows.some(
3689
- (candidate) => isHardKillSet(candidate, win.targetSelector, boundary)
3690
- );
3691
- if (hasHardKill) continue;
3692
- const exitClipInfo = clipIds.get(win.targetSelector) || clipClasses.get(win.targetSelector);
3693
- const fixHint = exitClipInfo ? `"${win.targetSelector}" is a clip element \u2014 the framework already manages its visibility. Wrap the scene's content in an inner non-clip <div>, move the exit tween and the hard kill (\`tl.set("<inner-selector>", ${hiddenStateLiteral(win.propertyValues)}, ${boundary.toFixed(2)})\`) onto that wrapper instead.` : `Add \`tl.set("${win.targetSelector}", ${hiddenStateLiteral(win.propertyValues)}, ${boundary.toFixed(2)})\` after the exit tween.`;
3694
- findings.push({
3695
- code: "gsap_exit_missing_hard_kill",
3696
- severity: "error",
3697
- message: `GSAP exit on "${win.targetSelector}" ends at the ${boundary.toFixed(2)}s clip start boundary without a matching tl.set hard kill. Non-linear seeking can land after the fade and leave stale visibility state.`,
3698
- selector: win.targetSelector,
3699
- fixHint,
3700
- snippet: truncateSnippet(win.raw)
3701
- });
3702
- }
3703
- }
3704
3615
  for (const tag of tags) {
3705
3616
  const selectors = tagSimpleSelectors(tag);
3706
3617
  if (selectors.length === 0) continue;