mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-04 07:19:52 +00:00
fix(lint): recognize computed-key window.__timelines registrations (#1874)
WINDOW_TIMELINE_ASSIGN_PATTERN only matched window.__timelines["literal"] or window.__timelines.prop, so registrations via a computed key like window.__timelines[spec.id] (used by the code-particle-assemble and code-3d-extrude registry blocks) went undetected. That made gsap_timeline_not_registered false-fire on correctly registered timelines, and let root_composition_missing_duration_source wrongly demand an explicit data-duration on compositions that already have one.
This commit is contained in:
@@ -1159,6 +1159,20 @@ describe("composition rules", () => {
|
|||||||
expect(find(result.findings)).toBeUndefined();
|
expect(find(result.findings)).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("does not error when a GSAP timeline is registered with a computed bracket key", async () => {
|
||||||
|
const html = `<html><body>
|
||||||
|
<div data-composition-id="main" data-start="0" data-width="1920" data-height="1080"></div>
|
||||||
|
<script>
|
||||||
|
var spec = { id: "main" };
|
||||||
|
window.__timelines = window.__timelines || {};
|
||||||
|
const tl = gsap.timeline({ paused: true });
|
||||||
|
window.__timelines[spec.id] = tl;
|
||||||
|
</script>
|
||||||
|
</body></html>`;
|
||||||
|
const result = await lintHyperframeHtml(html);
|
||||||
|
expect(find(result.findings)).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
it("does not error for a finite CSS animation (runtime auto-infers duration)", async () => {
|
it("does not error for a finite CSS animation (runtime auto-infers duration)", async () => {
|
||||||
const html = `<html><body>
|
const html = `<html><body>
|
||||||
<div data-composition-id="main" data-start="0" data-width="1920" data-height="1080">
|
<div data-composition-id="main" data-start="0" data-width="1920" data-height="1080">
|
||||||
|
|||||||
@@ -1296,6 +1296,26 @@ describe("GSAP rules", () => {
|
|||||||
expect(finding).toBeUndefined();
|
expect(finding).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("does NOT warn when timeline is registered with a computed bracket key", async () => {
|
||||||
|
const html = `
|
||||||
|
<html><body>
|
||||||
|
<div data-composition-id="root" data-width="1920" data-height="1080">
|
||||||
|
<div id="box">Hello</div>
|
||||||
|
</div>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/gsap@3/dist/gsap.min.js"></script>
|
||||||
|
<script>
|
||||||
|
var spec = { id: "root" };
|
||||||
|
window.__timelines = window.__timelines || {};
|
||||||
|
const tl = gsap.timeline({ paused: true });
|
||||||
|
tl.to("#box", { opacity: 0.5, duration: 2 });
|
||||||
|
window.__timelines[spec.id] = tl;
|
||||||
|
</script>
|
||||||
|
</body></html>`;
|
||||||
|
const result = await lintHyperframeHtml(html);
|
||||||
|
const finding = result.findings.find((f) => f.code === "gsap_timeline_not_registered");
|
||||||
|
expect(finding).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
it("does NOT warn for sub-compositions (template-based)", async () => {
|
it("does NOT warn for sub-compositions (template-based)", async () => {
|
||||||
const html = `
|
const html = `
|
||||||
<template>
|
<template>
|
||||||
|
|||||||
@@ -28,8 +28,16 @@ export const TIMELINE_REGISTRY_OBJECT_LITERAL_PATTERN =
|
|||||||
/window\.__timelines\s*=\s*\{\s*(?:["'][^"']+["']|[A-Za-z_$][\w$]*)\s*:/i;
|
/window\.__timelines\s*=\s*\{\s*(?:["'][^"']+["']|[A-Za-z_$][\w$]*)\s*:/i;
|
||||||
export const TIMELINE_REGISTRY_ASSIGN_PATTERN =
|
export const TIMELINE_REGISTRY_ASSIGN_PATTERN =
|
||||||
/window\.__timelines(?:\[[^\]]+\]|\.[A-Za-z_$][\w$]*)\s*=/i;
|
/window\.__timelines(?:\[[^\]]+\]|\.[A-Za-z_$][\w$]*)\s*=/i;
|
||||||
|
// The bracket branch accepts either a quoted string key (`["root"]`) or a
|
||||||
|
// computed key (`[spec.id]`, `[id]`) — a bare-identifier-only bracket branch
|
||||||
|
// missed `window.__timelines[spec.id] = tl`, a pattern the shipped
|
||||||
|
// code-particle-assemble/code-3d-extrude registry blocks actually use,
|
||||||
|
// making gsap_timeline_not_registered false-fire on correctly registered
|
||||||
|
// timelines. The computed-key alternative is deliberately non-capturing:
|
||||||
|
// its text isn't a literal composition id, so callers reading group 1/2
|
||||||
|
// (readRegisteredTimelineCompositionId) must keep falling back to null for it.
|
||||||
export const WINDOW_TIMELINE_ASSIGN_PATTERN =
|
export const WINDOW_TIMELINE_ASSIGN_PATTERN =
|
||||||
/window\.__timelines(?:\[\s*["']([^"']+)["']\s*\]|\.\s*([A-Za-z_$][\w$]*))\s*=\s*([A-Za-z_$][\w$]*)/i;
|
/window\.__timelines(?:\[\s*(?:["']([^"']+)["']|[A-Za-z_$][\w$.]*)\s*\]|\.\s*([A-Za-z_$][\w$]*))\s*=\s*([A-Za-z_$][\w$]*)/i;
|
||||||
export const INVALID_SCRIPT_CLOSE_PATTERN = /<script[^>]*>[\s\S]*?<\s*\/\s*script(?!>)/i;
|
export const INVALID_SCRIPT_CLOSE_PATTERN = /<script[^>]*>[\s\S]*?<\s*\/\s*script(?!>)/i;
|
||||||
|
|
||||||
const TIMELINE_REGISTRY_KEY_PATTERN =
|
const TIMELINE_REGISTRY_KEY_PATTERN =
|
||||||
|
|||||||
Reference in New Issue
Block a user