From fbb8879874a5b1f5469f36fb7dd68d734f0f5639 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20=C3=81ngel?= Date: Mon, 13 Jul 2026 21:32:10 +0000 Subject: [PATCH] fix(lint): flag videos nested in visual wrappers --- packages/lint/src/rules/media.test.ts | 21 ++++++++ packages/lint/src/rules/media.ts | 74 +++++++++------------------ 2 files changed, 44 insertions(+), 51 deletions(-) diff --git a/packages/lint/src/rules/media.test.ts b/packages/lint/src/rules/media.test.ts index 3be4187a2d..4ed2b14a67 100644 --- a/packages/lint/src/rules/media.test.ts +++ b/packages/lint/src/rules/media.test.ts @@ -171,6 +171,27 @@ describe("media rules", () => { expect(finding).toBeUndefined(); }); + it("reports video nested in an untimed visual wrapper", async () => { + // The renderer only discovers managed media that are direct children of + // the host composition root. An untimed wrapper is enough to make the + // video render black even though the wrapper itself is not a clip. + const html = ` + +
+
+ +
+
+ +`; + const result = await lintHyperframeHtml(html); + const finding = result.findings.find((f) => f.code === "video_nested_in_timed_element"); + expect(finding).toBeDefined(); + expect(finding?.severity).toBe("error"); + expect(finding?.elementId).toBe("wrapped-video"); + expect(finding?.fixHint).toContain("direct child"); + }); + it("reports imperative play() control on managed media ids", async () => { const html = ` diff --git a/packages/lint/src/rules/media.ts b/packages/lint/src/rules/media.ts index 1fa14d2496..760ff47410 100644 --- a/packages/lint/src/rules/media.ts +++ b/packages/lint/src/rules/media.ts @@ -283,61 +283,33 @@ export const mediaRules: Array<(ctx: LintContext) => HyperframeLintFinding[]> = }, // video_nested_in_timed_element - ({ source, tags }) => { + ({ tags, rootTag }) => { const findings: HyperframeLintFinding[] = []; - // HTML5 void elements cannot contain children, so they can never be a - // parent of a nested