You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: packages/core/src/lint/hyperframeLinter.ts
+163-3Lines changed: 163 additions & 3 deletions
Original file line number
Diff line number
Diff line change
@@ -265,11 +265,11 @@ export function lintHyperframeHtml(html: string, options: HyperframeLinterOption
265
265
continue;
266
266
}
267
267
pushFinding({
268
-
code: "suspicious_global_gsap_selector",
268
+
code: "unscoped_gsap_selector",
269
269
severity: "warning",
270
-
message: `Timeline "${localTimelineCompId}" uses a global selector "${window.targetSelector}" that may escape composition scope.`,
270
+
message: `Timeline "${localTimelineCompId}" uses unscoped selector "${window.targetSelector}" that will target elements in ALL compositions when bundled, causing data loss (opacity, transforms, etc.).`,
271
271
selector: window.targetSelector,
272
-
fixHint: `Scope the selector like \`[data-composition-id="${localTimelineCompId}"] ${window.targetSelector}\` or use a unique id.`,
272
+
fixHint: `Scope the selector: \`[data-composition-id="${localTimelineCompId}"] ${window.targetSelector}\` or use a unique id.`,
273
273
snippet: truncateSnippet(window.raw),
274
274
});
275
275
}
@@ -331,6 +331,75 @@ export function lintHyperframeHtml(html: string, options: HyperframeLinterOption
331
331
}
332
332
}
333
333
334
+
// #3.5: Self-closing <audio .../> or <video .../> — CRITICAL
335
+
// In HTML5, <audio> and <video> are NOT void elements. The browser silently
336
+
// ignores the "/>", leaving the tag open. All subsequent sibling elements
337
+
// become invisible fallback content inside the media tag, making entire
338
+
// compositions disappear. This is the #1 cause of "black preview" bugs.
message: `Self-closing <${tagName}/> is invalid HTML. The browser will leave the tag open, swallowing all subsequent elements as invisible fallback content. This makes compositions INVISIBLE.`,
349
+
elementId,
350
+
fixHint: `Change <${tagName} .../> to <${tagName} ...></${tagName}> — media elements MUST have explicit closing tags.`,
351
+
snippet: truncateSnippet(scMatch[0]),
352
+
});
353
+
}
354
+
}
355
+
356
+
// #3.6: Placeholder/fake media URLs — CRITICAL
357
+
// Agents sometimes fabricate URLs (placehold.co, placeholder.com, example.com)
358
+
// instead of using fetch_media or generate_image. These 404 at render time.
// Any embedded base64 audio is suspicious — real audio should be a file
393
+
pushFinding({
394
+
code: "fabricated_inline_media",
395
+
severity: "error",
396
+
message: `Embedded base64 ${isSuspicious ? "FABRICATED" : ""} media detected (${(dataSize/1024).toFixed(0)} KB). Inline base64 audio/video is almost always fake data that won't play. Use fetch_media or extract_audio to get real audio files.`,
397
+
fixHint: "Remove the data: URI. Use fetch_media to search for stock music, or extract_audio to get audio from a video.",
0 commit comments