@hyperframes/lint 0.7.16 → 0.7.17

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/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils.ts","../src/context.ts","../src/rules/core.ts","../src/rules/media.ts","../src/rules/gsap.ts","../src/rules/captions.ts","../src/rules/composition.ts","../src/rules/adapters.ts","../src/rules/textures.ts","../src/rules/fonts.ts","../src/rules/slideshow.ts","../src/hyperframeLinter.ts","../src/project.ts"],"sourcesContent":["// Shared types, regex constants, and utility functions used across lint rule modules.\n// Nothing in this file should emit findings — it only parses and extracts.\n\nexport type OpenTag = {\n raw: string;\n name: string;\n attrs: string;\n index: number;\n};\n\nexport type ExtractedBlock = {\n attrs: string;\n content: string;\n raw: string;\n index: number;\n};\n\nconst TAG_PATTERN = /<([a-z][\\w:-]*)(\\s[^<>]*?)?>/gi;\nexport const STYLE_BLOCK_PATTERN = /<style\\b([^>]*)>([\\s\\S]*?)<\\/style>/gi;\nexport const SCRIPT_BLOCK_PATTERN = /<script\\b([^>]*)>([\\s\\S]*?)<\\/script>/gi;\nconst COMPOSITION_ID_IN_CSS_PATTERN = /\\[data-composition-id=[\"']([^\"']+)[\"']\\]/g;\nexport const TIMELINE_REGISTRY_INIT_PATTERN =\n /window\\.__timelines\\s*=\\s*window\\.__timelines\\s*\\|\\|\\s*\\{\\}|window\\.__timelines\\s*=\\s*\\{\\}|window\\.__timelines\\s*\\?\\?=\\s*\\{\\}/i;\nexport const TIMELINE_REGISTRY_ASSIGN_PATTERN =\n /window\\.__timelines(?:\\[[^\\]]+\\]|\\.[A-Za-z_$][\\w$]*)\\s*=/i;\nexport const WINDOW_TIMELINE_ASSIGN_PATTERN =\n /window\\.__timelines(?:\\[\\s*[\"']([^\"']+)[\"']\\s*\\]|\\.\\s*([A-Za-z_$][\\w$]*))\\s*=\\s*([A-Za-z_$][\\w$]*)/i;\nexport const INVALID_SCRIPT_CLOSE_PATTERN = /<script[^>]*>[\\s\\S]*?<\\s*\\/\\s*script(?!>)/i;\n\nconst TIMELINE_REGISTRY_KEY_PATTERN =\n /window\\.__timelines(?:\\[\\s*[\"']([^\"']+)[\"']\\s*\\]|\\.\\s*([A-Za-z_$][\\w$]*))\\s*=/g;\n\nexport function extractOpenTags(source: string): OpenTag[] {\n const tags: OpenTag[] = [];\n let match: RegExpExecArray | null;\n const pattern = new RegExp(TAG_PATTERN.source, TAG_PATTERN.flags);\n while ((match = pattern.exec(source)) !== null) {\n const raw = match[0];\n if (raw.startsWith(\"</\") || raw.startsWith(\"<!\")) continue;\n tags.push({\n raw,\n name: (match[1] || \"\").toLowerCase(),\n attrs: match[2] || \"\",\n index: match.index,\n });\n }\n return tags;\n}\n\nexport function extractBlocks(source: string, pattern: RegExp): ExtractedBlock[] {\n const blocks: ExtractedBlock[] = [];\n let match: RegExpExecArray | null;\n const p = new RegExp(pattern.source, pattern.flags);\n while ((match = p.exec(source)) !== null) {\n blocks.push({\n attrs: match[1] || \"\",\n content: match[2] || \"\",\n raw: match[0],\n index: match.index,\n });\n }\n return blocks;\n}\n\n/**\n * Find the `<html>` open tag in the source. Distinct from `findRootTag`,\n * which returns the first element inside `<body>` — the latter is \"the\n * composition's visible root\", whereas `<html>` is where document-level\n * metadata like `data-composition-variables` lives.\n */\nexport function findHtmlTag(source: string): OpenTag | null {\n const match = /<html\\b([^<>]*)>/i.exec(source);\n if (!match) return null;\n return {\n raw: match[0],\n name: \"html\",\n attrs: match[1] ?? \"\",\n index: match.index,\n };\n}\n\nexport function findRootTag(source: string): OpenTag | null {\n const bodyOpenMatch = /<body\\b([^>]*)>/i.exec(source);\n const bodyCloseMatch = /<\\/body>/i.exec(source);\n if (\n bodyOpenMatch &&\n (readAttr(bodyOpenMatch[0], \"data-composition-id\") ||\n readAttr(bodyOpenMatch[0], \"data-width\") ||\n readAttr(bodyOpenMatch[0], \"data-height\"))\n ) {\n return {\n raw: bodyOpenMatch[0],\n name: \"body\",\n attrs: bodyOpenMatch[1] ?? \"\",\n index: bodyOpenMatch.index,\n };\n }\n const bodyStart = bodyOpenMatch ? bodyOpenMatch.index + bodyOpenMatch[0].length : 0;\n const bodyEnd =\n bodyOpenMatch && bodyCloseMatch && bodyCloseMatch.index > bodyStart\n ? bodyCloseMatch.index\n : source.length;\n const bodyContent = bodyOpenMatch ? source.slice(bodyStart, bodyEnd) : source;\n const bodyTags = extractOpenTags(bodyContent);\n for (const tag of bodyTags) {\n if ([\"script\", \"style\", \"meta\", \"link\", \"title\"].includes(tag.name)) continue;\n return { ...tag, index: tag.index + bodyStart };\n }\n return null;\n}\n\nexport function readAttr(tagSource: string, attr: string): string | null {\n if (!tagSource) return null;\n const escaped = attr.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n const match = tagSource.match(new RegExp(`\\\\b${escaped}\\\\s*=\\\\s*[\"']([^\"']+)[\"']`, \"i\"));\n return match?.[1] || null;\n}\n\n/**\n * Read an attribute that may legitimately contain the opposite quote\n * character. `readAttr` truncates `data-variable-values='{\"title\":\"Hello\"}'`\n * at the first internal `\"` because its `[^\"']+` class excludes both quote\n * types. This variant alternates: a double-quoted value never contains an\n * unescaped `\"`, and a single-quoted value never contains an unescaped `'`,\n * so each branch can use a quote-specific class.\n *\n * Use for attributes whose values are JSON or otherwise carry the opposite\n * quote character. Existing single-token attributes (`id`, `class`, etc.)\n * stick with `readAttr` for consistency with the rest of the lint code.\n */\nexport function readJsonAttr(tagSource: string, attr: string): string | null {\n if (!tagSource) return null;\n const escaped = attr.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n const match = tagSource.match(new RegExp(`\\\\b${escaped}\\\\s*=\\\\s*(?:\"([^\"]*)\"|'([^']*)')`, \"i\"));\n if (!match) return null;\n return match[1] ?? match[2] ?? null;\n}\n\nexport function collectCompositionIds(tags: OpenTag[]): Set<string> {\n const ids = new Set<string>();\n for (const tag of tags) {\n const compId = readAttr(tag.raw, \"data-composition-id\");\n if (compId) ids.add(compId);\n }\n return ids;\n}\n\nexport function extractCompositionIdsFromCss(css: string): string[] {\n const ids = new Set<string>();\n let match: RegExpExecArray | null;\n const pattern = new RegExp(\n COMPOSITION_ID_IN_CSS_PATTERN.source,\n COMPOSITION_ID_IN_CSS_PATTERN.flags,\n );\n while ((match = pattern.exec(css)) !== null) {\n if (match[1]) ids.add(match[1]);\n }\n return [...ids];\n}\n\nexport function extractTimelineRegistryKeys(source: string): string[] {\n const keys = new Set<string>();\n let match: RegExpExecArray | null;\n const pattern = new RegExp(\n TIMELINE_REGISTRY_KEY_PATTERN.source,\n TIMELINE_REGISTRY_KEY_PATTERN.flags,\n );\n while ((match = pattern.exec(source)) !== null) {\n const key = match[1] ?? match[2];\n if (key) keys.add(key);\n }\n return [...keys];\n}\n\nexport function getInlineScriptSyntaxError(source: string): string | null {\n if (!source.trim()) return null;\n try {\n // eslint-disable-next-line no-new-func\n new Function(source);\n return null;\n } catch (error) {\n if (error instanceof Error) return error.message;\n return String(error);\n }\n}\n\n// fallow-ignore-next-line complexity\nexport function stripJsComments(source: string): string {\n let out = \"\";\n let i = 0;\n let quote: \"'\" | '\"' | \"`\" | null = null;\n let escaped = false;\n\n while (i < source.length) {\n const ch = source[i] ?? \"\";\n const next = source[i + 1] ?? \"\";\n\n if (quote) {\n out += ch;\n if (escaped) {\n escaped = false;\n } else if (ch === \"\\\\\") {\n escaped = true;\n } else if (ch === quote) {\n quote = null;\n }\n i += 1;\n continue;\n }\n\n if (ch === \"'\" || ch === '\"' || ch === \"`\") {\n quote = ch;\n out += ch;\n i += 1;\n continue;\n }\n\n if (ch === \"/\" && next === \"/\") {\n out += \" \";\n i += 2;\n while (i < source.length && source[i] !== \"\\n\" && source[i] !== \"\\r\") {\n out += \" \";\n i += 1;\n }\n continue;\n }\n\n if (ch === \"/\" && next === \"*\") {\n out += \" \";\n i += 2;\n while (i < source.length) {\n const blockCh = source[i] ?? \"\";\n const blockNext = source[i + 1] ?? \"\";\n if (blockCh === \"*\" && blockNext === \"/\") {\n out += \" \";\n i += 2;\n break;\n }\n out += blockCh === \"\\n\" || blockCh === \"\\r\" ? blockCh : \" \";\n i += 1;\n }\n continue;\n }\n\n out += ch;\n i += 1;\n }\n\n return out;\n}\n\n// One linear pass that drops every `<!-- … -->` region. Uses indexOf, not a\n// `/<!--[\\s\\S]*?-->/` regex: that pattern backtracks O(n²) on inputs with many\n// unterminated \"<!--\" (CodeQL js/polynomial-redos). An unterminated \"<!--\" with\n// no closing \"-->\" is kept verbatim, matching the prior regex's no-match behavior.\nfunction stripHtmlCommentsOnce(source: string): string {\n let out = \"\";\n let i = 0;\n for (;;) {\n const start = source.indexOf(\"<!--\", i);\n if (start < 0) return out + source.slice(i);\n const end = source.indexOf(\"-->\", start + 4);\n if (end < 0) return out + source.slice(i);\n out += source.slice(i, start);\n i = end + 3;\n }\n}\n\n// Strip HTML comments to a fixpoint. A single pass is not enough: deleting one\n// comment can splice adjacent markers into a fresh, complete <!-- … --> (e.g.\n// \"<<!-- -->!-- … -->\" → \"<!-- … -->\"), which would otherwise survive and let a\n// commented-out <template>/tag hijack the linter's tag scan.\nexport function stripHtmlComments(source: string): string {\n let out = source;\n for (let prev = \"\"; prev !== out; ) {\n prev = out;\n out = stripHtmlCommentsOnce(out);\n }\n return out;\n}\n\nexport function extractScriptTextsAndSrcs(scripts: ExtractedBlock[]): {\n texts: string[];\n srcs: string[];\n} {\n const texts = scripts.filter((s) => !/\\bsrc\\s*=/.test(s.attrs)).map((s) => s.content);\n const srcs = scripts.map((s) => readAttr(`<script ${s.attrs}>`, \"src\") || \"\").filter(Boolean);\n return { texts, srcs };\n}\n\nexport function isMediaTag(tagName: string): boolean {\n return tagName === \"video\" || tagName === \"audio\" || tagName === \"img\";\n}\n\nexport function truncateSnippet(value: string, maxLength = 220): string | undefined {\n const normalized = value.replace(/\\s+/g, \" \").trim();\n if (!normalized) return undefined;\n if (normalized.length <= maxLength) return normalized;\n return `${normalized.slice(0, maxLength - 3)}...`;\n}\n","import type { HyperframeLintFinding, HyperframeLinterOptions } from \"./types\";\nimport {\n extractBlocks,\n extractOpenTags,\n findRootTag,\n collectCompositionIds,\n readAttr,\n stripHtmlComments,\n STYLE_BLOCK_PATTERN,\n SCRIPT_BLOCK_PATTERN,\n} from \"./utils\";\nimport type { OpenTag, ExtractedBlock } from \"./utils\";\n\nexport type { OpenTag, ExtractedBlock };\n\nexport type LintContext = {\n source: string;\n rawSource: string;\n tags: OpenTag[];\n styles: ExtractedBlock[];\n scripts: ExtractedBlock[];\n compositionIds: Set<string>;\n rootTag: OpenTag | null;\n rootCompositionId: string | null;\n options: HyperframeLinterOptions;\n};\n\n// Re-export for convenience so rule modules only need one import for the finding type\nexport type { HyperframeLintFinding };\n\nexport function buildLintContext(html: string, options: HyperframeLinterOptions = {}): LintContext {\n const rawSource = html || \"\";\n // Strip HTML comments before scanning so a commented-out <template> or tag can't\n // hijack the boundary match below. Linear + fixpoint (see stripHtmlComments) to\n // stay ReDoS-free and catch markers that re-form when a comment is removed.\n let source = stripHtmlComments(rawSource);\n const templateMatch = source.match(/<template[^>]*>([\\s\\S]*)<\\/template>/i);\n if (templateMatch?.[1]) source = templateMatch[1];\n\n const tags = extractOpenTags(source);\n const styles = [\n ...extractBlocks(source, STYLE_BLOCK_PATTERN),\n ...(options.externalStyles ?? []).map((style) => ({\n attrs: `href=\"${style.href}\"`,\n content: style.content,\n raw: style.content,\n index: -1,\n })),\n ];\n const scripts = extractBlocks(source, SCRIPT_BLOCK_PATTERN);\n const compositionIds = collectCompositionIds(tags);\n const rootTag = findRootTag(source);\n const rootCompositionId = readAttr(rootTag?.raw || \"\", \"data-composition-id\");\n\n return {\n source,\n rawSource,\n tags,\n styles,\n scripts,\n compositionIds,\n rootTag,\n rootCompositionId,\n options,\n };\n}\n","import type { LintContext, HyperframeLintFinding } from \"../context\";\nimport postcss from \"postcss\";\nimport {\n readAttr,\n truncateSnippet,\n stripJsComments,\n extractCompositionIdsFromCss,\n extractTimelineRegistryKeys,\n getInlineScriptSyntaxError,\n TIMELINE_REGISTRY_INIT_PATTERN,\n TIMELINE_REGISTRY_ASSIGN_PATTERN,\n INVALID_SCRIPT_CLOSE_PATTERN,\n} from \"../utils\";\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\nfunction selectorTargetsCompositionId(selector: string, compositionId: string): boolean {\n const escaped = escapeRegExp(compositionId);\n return new RegExp(\n String.raw`\\[\\s*data-composition-id\\s*=\\s*(?:\"${escaped}\"|'${escaped}')\\s*\\]`,\n ).test(selector);\n}\n\nfunction isStudioTimelineElement(tag: { raw: string; name: string }): boolean {\n if ([\"script\", \"style\", \"link\", \"meta\", \"template\", \"noscript\"].includes(tag.name)) {\n return false;\n }\n return Boolean(\n readAttr(tag.raw, \"data-start\") ||\n readAttr(tag.raw, \"data-track-index\") ||\n readAttr(tag.raw, \"data-track\") ||\n readAttr(tag.raw, \"data-composition-src\") ||\n readAttr(tag.raw, \"data-composition-file\"),\n );\n}\n\nfunction describeStudioElement(tag: { raw: string; name: string }): string {\n const parts = [`<${tag.name}`];\n const className = readAttr(tag.raw, \"class\");\n const compositionId = readAttr(tag.raw, \"data-composition-id\");\n const dataStart = readAttr(tag.raw, \"data-start\");\n const dataTrack = readAttr(tag.raw, \"data-track-index\") ?? readAttr(tag.raw, \"data-track\");\n\n if (className) {\n const primaryClass = className\n .split(/\\s+/)\n .map((value) => value.trim())\n .find((value) => value && value !== \"clip\");\n if (primaryClass) parts.push(` class=\"${primaryClass}\"`);\n }\n if (compositionId) parts.push(` data-composition-id=\"${compositionId}\"`);\n if (dataStart) parts.push(` data-start=\"${dataStart}\"`);\n if (dataTrack) parts.push(` data-track-index=\"${dataTrack}\"`);\n parts.push(\">\");\n return parts.join(\"\");\n}\n\nconst HEAD_BLOCKS_TO_IGNORE_PATTERN =\n /<(?:style|script|template|title|noscript)\\b[^>]*>[\\s\\S]*?<\\/(?:style|script|template|title|noscript)(?:\\s[^>]*)?>/gi;\nconst HTML_TAG_PATTERN = /<[^>]+>/g;\nconst HEAD_CONTENT_PATTERN = /<head\\b[^>]*>([\\s\\S]*?)(?:<\\/head>|<body\\b|$)/gi;\nconst AFTER_HEAD_BEFORE_BODY_PATTERN = /<\\/head(?:\\s[^>]*)?>([\\s\\S]*?)(?=<body\\b|$)/gi;\nconst STRAY_HEAD_CLOSE_PATTERN = /<\\/(?:style|script)(?:\\s[^>]*)?>/i;\nconst MARKDOWN_CODE_FENCE_PATTERN = /```[^\\r\\n`]*(?:\\r?\\n|$)[\\s\\S]*?```/i;\nconst ORPHAN_CSS_AT_RULE_PATTERN =\n /(?:^|\\s)@(?:container|font-face|keyframes|layer|media|page|property|scope|supports)[^{<]*\\{[\\s\\S]*?:[\\s\\S]*?\\}/i;\nconst ORPHAN_CSS_RULE_PATTERN =\n /(?:^|\\s)(?:\\/\\*[\\s\\S]*?\\*\\/\\s*)?(?:@[a-z-]+[^{}<]*|[.#][\\w-]+[^{}<]*|[a-z][\\w-]*(?:\\s+[.#:[\\w-][^{}<]*)?)\\s*\\{[^{}]*:[^{}]*\\}/i;\n\nfunction findCodeFenceLeak(headWithoutValidBlocks: string): string | null {\n return MARKDOWN_CODE_FENCE_PATTERN.exec(headWithoutValidBlocks)?.[0] ?? null;\n}\n\nfunction findOrphanCssLeak(headContent: string): string | null {\n const residualText = headContent\n .replace(HEAD_BLOCKS_TO_IGNORE_PATTERN, \" \")\n .replace(HTML_TAG_PATTERN, \" \");\n return (\n ORPHAN_CSS_AT_RULE_PATTERN.exec(residualText)?.[0] ??\n ORPHAN_CSS_RULE_PATTERN.exec(residualText)?.[0] ??\n null\n );\n}\n\nfunction findStrayCloseLeak(headWithoutValidBlocks: string): string | null {\n return STRAY_HEAD_CLOSE_PATTERN.exec(headWithoutValidBlocks)?.[0] ?? null;\n}\n\nfunction findLeakedTextInHeadContent(headContent: string): string | null {\n const withoutValidBlocks = headContent.replace(HEAD_BLOCKS_TO_IGNORE_PATTERN, \" \");\n return (\n findCodeFenceLeak(withoutValidBlocks) ??\n findOrphanCssLeak(headContent) ??\n findStrayCloseLeak(withoutValidBlocks)\n );\n}\n\nfunction findLeakedTextInHead(rawSource: string): string | null {\n const headMatches = [...rawSource.matchAll(HEAD_CONTENT_PATTERN)];\n for (const match of headMatches) {\n const leakedText = findLeakedTextInHeadContent(match[1] ?? \"\");\n if (leakedText) return leakedText;\n }\n return null;\n}\n\nfunction findLeakedTextBetweenHeadAndBody(rawSource: string): string | null {\n const boundaryMatches = [...rawSource.matchAll(AFTER_HEAD_BEFORE_BODY_PATTERN)];\n for (const match of boundaryMatches) {\n const leakedText = findLeakedTextInHeadContent(match[1] ?? \"\");\n if (leakedText) return leakedText;\n }\n return null;\n}\n\nfunction findLeakedTextBeforeCompositionRoot(\n source: string,\n rootTag: LintContext[\"rootTag\"],\n): string | null {\n if (!rootTag || rootTag.name === \"body\") return null;\n const bodyOpenMatch = /<body\\b[^>]*>/i.exec(source);\n const prefixStart = bodyOpenMatch ? bodyOpenMatch.index + bodyOpenMatch[0].length : 0;\n const prefixEnd = rootTag.index;\n if (prefixEnd <= prefixStart) return null;\n return findLeakedTextInHeadContent(source.slice(prefixStart, prefixEnd));\n}\n\nexport const coreRules: Array<(ctx: LintContext) => HyperframeLintFinding[]> = [\n // root_missing_composition_id + root_missing_dimensions\n ({ rootTag }) => {\n const findings: HyperframeLintFinding[] = [];\n if (!rootTag || !readAttr(rootTag.raw, \"data-composition-id\")) {\n findings.push({\n code: \"root_missing_composition_id\",\n severity: \"error\",\n message: \"Root composition is missing `data-composition-id`.\",\n elementId: rootTag ? readAttr(rootTag.raw, \"id\") || undefined : undefined,\n fixHint: \"Add a stable `data-composition-id` to the entry composition wrapper.\",\n snippet: truncateSnippet(rootTag?.raw || \"\"),\n });\n }\n if (!rootTag || !readAttr(rootTag.raw, \"data-width\") || !readAttr(rootTag.raw, \"data-height\")) {\n findings.push({\n code: \"root_missing_dimensions\",\n severity: \"error\",\n message: \"Root composition is missing `data-width` or `data-height`.\",\n elementId: rootTag ? readAttr(rootTag.raw, \"id\") || undefined : undefined,\n fixHint: \"Set numeric `data-width` and `data-height` on the entry composition root.\",\n snippet: truncateSnippet(rootTag?.raw || \"\"),\n });\n }\n return findings;\n },\n\n // head_leaked_text\n ({ source, rootTag }) => {\n const snippet =\n findLeakedTextInHead(source) ??\n findLeakedTextBetweenHeadAndBody(source) ??\n findLeakedTextBeforeCompositionRoot(source, rootTag);\n if (!snippet) return [];\n return [\n {\n code: \"head_leaked_text\",\n severity: \"error\",\n message:\n \"Detected leaked code or CSS text around the document `<head>` or before the composition root. Browsers render this as visible text in the video.\",\n fixHint:\n \"Move CSS into a single `<style>...</style>` block and remove stray close tags, markdown fences, or code text from `<head>`, the `</head>`/`<body>` boundary, or the pre-root body prefix.\",\n snippet: truncateSnippet(snippet),\n },\n ];\n },\n\n // missing_timeline_registry + timeline_registry_missing_init\n ({ source, rawSource, options }) => {\n // Sub-compositions inherit window.__timelines from the host composition\n if (options.isSubComposition || rawSource.trimStart().toLowerCase().startsWith(\"<template\")) {\n return [];\n }\n const findings: HyperframeLintFinding[] = [];\n if (\n !TIMELINE_REGISTRY_INIT_PATTERN.test(source) &&\n !TIMELINE_REGISTRY_ASSIGN_PATTERN.test(source)\n ) {\n findings.push({\n code: \"missing_timeline_registry\",\n severity: \"error\",\n message: \"Missing `window.__timelines` registration.\",\n fixHint: \"Register each composition timeline on `window.__timelines[compositionId]`.\",\n });\n }\n if (\n TIMELINE_REGISTRY_ASSIGN_PATTERN.test(source) &&\n !TIMELINE_REGISTRY_INIT_PATTERN.test(source)\n ) {\n findings.push({\n code: \"timeline_registry_missing_init\",\n severity: \"error\",\n message:\n \"`window.__timelines[…] = …` is used without initializing `window.__timelines` first.\",\n fixHint:\n \"Add `window.__timelines = window.__timelines || {};` before any timeline assignment.\",\n });\n }\n return findings;\n },\n\n // timeline_id_mismatch\n ({ source }) => {\n const findings: HyperframeLintFinding[] = [];\n const htmlCompIds = new Set<string>();\n const timelineRegKeys = new Set<string>();\n const compIdRe = /data-composition-id\\s*=\\s*[\"']([^\"']+)[\"']/gi;\n let m: RegExpExecArray | null;\n while ((m = compIdRe.exec(source)) !== null) {\n if (m[1]) htmlCompIds.add(m[1]);\n }\n for (const key of extractTimelineRegistryKeys(source)) {\n timelineRegKeys.add(key);\n }\n for (const key of timelineRegKeys) {\n if (!htmlCompIds.has(key)) {\n findings.push({\n code: \"timeline_id_mismatch\",\n severity: \"error\",\n message: `Timeline registered as \"${key}\" but no element has data-composition-id=\"${key}\". The runtime cannot auto-nest this timeline.`,\n fixHint: `Change window.__timelines[\"${key}\"] to match the data-composition-id attribute, or vice versa.`,\n });\n }\n }\n return findings;\n },\n\n // invalid_inline_script_syntax (malformed close tag)\n ({ source }) => {\n if (!INVALID_SCRIPT_CLOSE_PATTERN.test(source)) return [];\n return [\n {\n code: \"invalid_inline_script_syntax\",\n severity: \"error\",\n message: \"Detected malformed inline `<script>` closing syntax.\",\n fixHint: \"Close inline scripts with a valid `</script>` tag.\",\n },\n ];\n },\n\n // invalid_inline_script_syntax (JS parse error)\n ({ scripts }) => {\n const findings: HyperframeLintFinding[] = [];\n for (const script of scripts) {\n const attrs = script.attrs || \"\";\n if (\n /\\bsrc\\s*=/.test(attrs) ||\n /\\btype\\s*=\\s*[\"'](?:application\\/json|application\\/hyperframes-slideshow\\+json|importmap|module)[\"']/.test(\n attrs,\n )\n )\n continue;\n const syntaxError = getInlineScriptSyntaxError(script.content);\n if (!syntaxError) continue;\n findings.push({\n code: \"invalid_inline_script_syntax\",\n severity: \"error\",\n message: `Inline script has invalid syntax: ${syntaxError}`,\n fixHint: \"Fix the inline script syntax before render verification.\",\n snippet: truncateSnippet(script.content),\n });\n }\n return findings;\n },\n\n // host_missing_composition_id\n ({ tags }) => {\n const findings: HyperframeLintFinding[] = [];\n for (const tag of tags) {\n const src = readAttr(tag.raw, \"data-composition-src\");\n if (!src) continue;\n if (readAttr(tag.raw, \"data-composition-id\")) continue;\n findings.push({\n code: \"host_missing_composition_id\",\n severity: \"error\",\n message: `Composition host for \"${src}\" is missing \\`data-composition-id\\`.`,\n elementId: readAttr(tag.raw, \"id\") || undefined,\n fixHint: \"Set `data-composition-id` on every `data-composition-src` host element.\",\n snippet: truncateSnippet(tag.raw),\n });\n }\n return findings;\n },\n\n // scoped_css_missing_wrapper\n ({ styles, compositionIds }) => {\n const findings: HyperframeLintFinding[] = [];\n const scopedCssCompositionIds = new Set<string>();\n for (const style of styles) {\n for (const compId of extractCompositionIdsFromCss(style.content)) {\n scopedCssCompositionIds.add(compId);\n }\n }\n for (const compId of scopedCssCompositionIds) {\n if (compositionIds.has(compId)) continue;\n findings.push({\n code: \"scoped_css_missing_wrapper\",\n severity: \"warning\",\n message: `Scoped CSS targets composition \"${compId}\" but no matching wrapper exists in this HTML.`,\n selector: `[data-composition-id=\"${compId}\"]`,\n fixHint:\n \"Preserve the matching composition wrapper or align the CSS scope to an existing wrapper.\",\n });\n }\n return findings;\n },\n\n // composition_self_attribute_selector\n ({ styles, rootCompositionId, rootTag }) => {\n const findings: HyperframeLintFinding[] = [];\n if (!rootCompositionId) return findings;\n const seenSelectors = new Set<string>();\n const rootId = readAttr(rootTag?.raw || \"\", \"id\");\n for (const style of styles) {\n let root: postcss.Root;\n try {\n root = postcss.parse(style.content);\n } catch {\n continue;\n }\n root.walkRules((rule) => {\n for (const selector of rule.selectors) {\n if (!selectorTargetsCompositionId(selector, rootCompositionId)) continue;\n if (seenSelectors.has(selector)) continue;\n seenSelectors.add(selector);\n findings.push({\n code: \"composition_self_attribute_selector\",\n severity: \"warning\",\n message:\n \"Selector matches the block's own id; will leak to sibling instances when the block is embedded twice.\",\n selector,\n fixHint: rootId\n ? `Use #${rootId} for clearer authoring intent and instance-isolated styling.`\n : \"Add a stable id to the composition root and use that id selector for clearer authoring intent and instance-isolated styling.\",\n });\n }\n });\n }\n return findings;\n },\n\n // studio_missing_editable_id\n ({ tags, rootTag }) => {\n const findings: HyperframeLintFinding[] = [];\n for (const tag of tags) {\n if (rootTag && tag.index === rootTag.index) continue;\n if (!isStudioTimelineElement(tag)) continue;\n if (readAttr(tag.raw, \"id\")) continue;\n\n const descriptor = describeStudioElement(tag);\n findings.push({\n code: \"studio_missing_editable_id\",\n severity: \"warning\",\n message: `${descriptor} has no id, so Studio cannot use a stable edit target for its timeline and canvas controls.`,\n selector: readAttr(tag.raw, \"data-composition-id\")\n ? `[data-composition-id=\"${readAttr(tag.raw, \"data-composition-id\")}\"]`\n : undefined,\n fixHint:\n 'Add a stable, human-readable id such as id=\"hero-title\" or id=\"scene-1-card\" to every timeline-visible element you want agents or Studio to edit.',\n snippet: truncateSnippet(tag.raw),\n });\n }\n return findings;\n },\n\n // non_deterministic_code\n ({ scripts }) => {\n const findings: HyperframeLintFinding[] = [];\n const patterns: Array<{ pattern: RegExp; label: string; hint: string }> = [\n {\n pattern: /Math\\.random\\s*\\(/,\n label: \"Math.random()\",\n hint: \"Use a seeded PRNG (e.g. a simple mulberry32) so renders are deterministic across frames.\",\n },\n {\n pattern: /Date\\.now\\s*\\(/,\n label: \"Date.now()\",\n hint: \"Remove time-dependent code. Use GSAP timeline position instead of wall-clock time.\",\n },\n {\n pattern: /new\\s+Date\\s*\\(/,\n label: \"new Date()\",\n hint: \"Remove time-dependent code. Use GSAP timeline position instead of wall-clock time.\",\n },\n {\n pattern: /performance\\.now\\s*\\(/,\n label: \"performance.now()\",\n hint: \"Remove time-dependent code. Use GSAP timeline position instead of wall-clock time.\",\n },\n {\n pattern: /crypto\\.getRandomValues\\s*\\(/,\n label: \"crypto.getRandomValues()\",\n hint: \"Remove time-dependent code. Use a seeded PRNG for deterministic renders.\",\n },\n ];\n\n for (const script of scripts) {\n const stripped = stripJsComments(script.content);\n for (const { pattern, label, hint } of patterns) {\n if (pattern.test(stripped)) {\n findings.push({\n code: \"non_deterministic_code\",\n severity: \"error\",\n message: `Script contains \\`${label}\\` which produces non-deterministic output. Renders may differ between frames or runs.`,\n fixHint: hint,\n snippet: truncateSnippet(script.content),\n });\n }\n }\n }\n return findings;\n },\n\n // pointer_events_none\n // fallow-ignore-next-line complexity\n ({ tags, styles }) => {\n const findings: HyperframeLintFinding[] = [];\n const reported = new Set<string>();\n\n for (const tag of tags) {\n if ([\"script\", \"style\", \"link\", \"meta\", \"template\", \"noscript\"].includes(tag.name)) continue;\n const inlineStyle = readAttr(tag.raw, \"style\") ?? \"\";\n if (!/pointer-events\\s*:\\s*none/i.test(inlineStyle)) continue;\n const id = readAttr(tag.raw, \"id\");\n const key = id ?? tag.raw;\n if (reported.has(key)) continue;\n reported.add(key);\n findings.push({\n code: \"pointer_events_none\",\n severity: \"info\",\n message: `<${tag.name}${id ? ` id=\"${id}\"` : \"\"}> has \\`pointer-events: none\\` in its inline style. Elements with this property are harder to select in the Studio preview.`,\n elementId: id || undefined,\n fixHint:\n \"If this element should be selectable in the Studio, remove `pointer-events: none` or move it to a wrapper that doesn't contain editable content.\",\n snippet: truncateSnippet(tag.raw),\n });\n }\n\n for (const style of styles) {\n let root: postcss.Root;\n try {\n root = postcss.parse(style.content);\n } catch {\n continue;\n }\n root.walkDecls(\"pointer-events\", (decl) => {\n if (decl.value.trim().toLowerCase() !== \"none\") return;\n const rule = decl.parent;\n if (!rule || rule.type !== \"rule\") return;\n const selector = (rule as postcss.Rule).selector;\n if (reported.has(selector)) return;\n reported.add(selector);\n findings.push({\n code: \"pointer_events_none\",\n severity: \"info\",\n message: `\\`${selector}\\` sets \\`pointer-events: none\\`. Elements matching this selector are harder to select in the Studio preview.`,\n selector,\n fixHint:\n \"If these elements should be selectable in the Studio, remove `pointer-events: none` or move it to a wrapper that doesn't contain editable content.\",\n });\n });\n }\n\n return findings;\n },\n];\n","import type { LintContext, HyperframeLintFinding } from \"../context\";\nimport { readAttr, truncateSnippet, isMediaTag } from \"../utils\";\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\nfunction hasAttrName(tagSource: string, attr: string): boolean {\n const escaped = escapeRegExp(attr);\n const attrs = tagSource.replace(/^<\\s*[a-z][\\w:-]*/i, \"\");\n return new RegExp(`(?:^|\\\\s)${escaped}(?:\\\\s*=|\\\\s|/?>)`, \"i\").test(attrs);\n}\n\nfunction classNamesFromAttr(classAttr: string | null): string[] {\n if (!classAttr) return [];\n return classAttr.split(/\\s+/).filter(Boolean);\n}\n\ntype MediaSelectorIndex = {\n ids: Set<string>;\n classes: Set<string>;\n hasVideo: boolean;\n hasAudio: boolean;\n};\n\nfunction selectorTargetsManagedMedia(selector: string, mediaIndex: MediaSelectorIndex): boolean {\n const normalized = selector.trim();\n if (!normalized) return false;\n if (mediaIndex.hasVideo && /\\bvideo\\b/i.test(normalized)) return true;\n if (mediaIndex.hasAudio && /\\baudio\\b/i.test(normalized)) return true;\n for (const mediaId of mediaIndex.ids) {\n const escapedId = escapeRegExp(mediaId);\n if (\n new RegExp(`#${escapedId}(?![\\\\w-])`).test(normalized) ||\n normalized.includes(`[id=\"${mediaId}\"]`) ||\n normalized.includes(`[id='${mediaId}']`)\n ) {\n return true;\n }\n }\n for (const className of mediaIndex.classes) {\n if (new RegExp(`\\\\.${escapeRegExp(className)}(?![\\\\w-])`).test(normalized)) {\n return true;\n }\n }\n return false;\n}\n\nfunction findImperativeMediaControlFindings(ctx: LintContext): HyperframeLintFinding[] {\n const findings: HyperframeLintFinding[] = [];\n const mediaTags = ctx.tags.filter((tag) => tag.name === \"video\" || tag.name === \"audio\");\n const mediaIndex: MediaSelectorIndex = {\n ids: new Set(\n mediaTags.map((tag) => readAttr(tag.raw, \"id\")).filter((id): id is string => Boolean(id)),\n ),\n classes: new Set(mediaTags.flatMap((tag) => classNamesFromAttr(readAttr(tag.raw, \"class\")))),\n hasVideo: mediaTags.some((tag) => tag.name === \"video\"),\n hasAudio: mediaTags.some((tag) => tag.name === \"audio\"),\n };\n\n if (mediaTags.length === 0 || ctx.scripts.length === 0) return findings;\n\n for (const script of ctx.scripts) {\n const mediaVars = new Map<string, string | undefined>();\n const assignmentPatterns = [\n {\n pattern:\n /\\b(?:const|let|var)\\s+([A-Za-z_$][\\w$]*)\\s*=\\s*(?:document|window\\.document)\\.getElementById\\(\\s*[\"']([^\"']+)[\"']\\s*\\)/g,\n variableIndex: 1,\n targetIndex: 2,\n },\n {\n pattern:\n /\\b(?:const|let|var)\\s+([A-Za-z_$][\\w$]*)\\s*=\\s*(?:document|window\\.document)\\.querySelector\\(\\s*([\"'])([\\s\\S]*?)\\2\\s*\\)/g,\n variableIndex: 1,\n targetIndex: 3,\n },\n ];\n\n for (const { pattern, variableIndex, targetIndex } of assignmentPatterns) {\n let match: RegExpExecArray | null;\n while ((match = pattern.exec(script.content)) !== null) {\n const variableName = match[variableIndex];\n const target = match[targetIndex];\n if (!variableName || !target) continue;\n if (mediaIndex.ids.has(target) || selectorTargetsManagedMedia(target, mediaIndex)) {\n mediaVars.set(variableName, mediaIndex.ids.has(target) ? target : undefined);\n }\n }\n }\n\n const directIdPatterns = [\n {\n pattern:\n /\\b(?:document|window\\.document)\\.getElementById\\(\\s*[\"']([^\"']+)[\"']\\s*\\)\\.play\\s*\\(/g,\n kind: \"play()\",\n targetIndex: 1,\n },\n {\n pattern:\n /\\b(?:document|window\\.document)\\.getElementById\\(\\s*[\"']([^\"']+)[\"']\\s*\\)\\.pause\\s*\\(/g,\n kind: \"pause()\",\n targetIndex: 1,\n },\n {\n pattern:\n /\\b(?:document|window\\.document)\\.getElementById\\(\\s*[\"']([^\"']+)[\"']\\s*\\)\\.currentTime\\s*=/g,\n kind: \"currentTime\",\n targetIndex: 1,\n },\n {\n pattern:\n /\\b(?:document|window\\.document)\\.getElementById\\(\\s*[\"']([^\"']+)[\"']\\s*\\)\\.muted\\s*=/g,\n kind: \"muted assignment\",\n targetIndex: 1,\n },\n {\n pattern:\n /\\b(?:document|window\\.document)\\.querySelector\\(\\s*([\"'])([\\s\\S]*?)\\1\\s*\\)\\.play\\s*\\(/g,\n kind: \"play()\",\n targetIndex: 2,\n },\n {\n pattern:\n /\\b(?:document|window\\.document)\\.querySelector\\(\\s*([\"'])([\\s\\S]*?)\\1\\s*\\)\\.pause\\s*\\(/g,\n kind: \"pause()\",\n targetIndex: 2,\n },\n {\n pattern:\n /\\b(?:document|window\\.document)\\.querySelector\\(\\s*([\"'])([\\s\\S]*?)\\1\\s*\\)\\.currentTime\\s*=/g,\n kind: \"currentTime\",\n targetIndex: 2,\n },\n {\n pattern:\n /\\b(?:document|window\\.document)\\.querySelector\\(\\s*([\"'])([\\s\\S]*?)\\1\\s*\\)\\.muted\\s*=/g,\n kind: \"muted assignment\",\n targetIndex: 2,\n },\n ];\n\n for (const { pattern, kind, targetIndex } of directIdPatterns) {\n let match: RegExpExecArray | null;\n while ((match = pattern.exec(script.content)) !== null) {\n const target = match[targetIndex];\n if (!target) continue;\n const elementId = mediaIndex.ids.has(target)\n ? target\n : selectorTargetsManagedMedia(target, mediaIndex)\n ? undefined\n : null;\n if (elementId === null) continue;\n findings.push({\n code: \"imperative_media_control\",\n severity: \"error\",\n message: `Inline <script> imperatively controls managed media via ${kind}. HyperFrames must own media play/pause/seek to keep preview, timeline, and renders deterministic.`,\n elementId: elementId || undefined,\n fixHint:\n \"Remove imperative media play/pause/currentTime/muted control. Express timing with data-start/data-duration and media offsets like data-media-start or data-playback-start instead.\",\n snippet: truncateSnippet(match[0]),\n });\n }\n }\n\n for (const [variableName, elementId] of mediaVars) {\n const escapedVar = escapeRegExp(variableName);\n const variablePatterns = [\n { pattern: new RegExp(`\\\\b${escapedVar}\\\\.play\\\\s*\\\\(`, \"g\"), kind: \"play()\" },\n { pattern: new RegExp(`\\\\b${escapedVar}\\\\.pause\\\\s*\\\\(`, \"g\"), kind: \"pause()\" },\n { pattern: new RegExp(`\\\\b${escapedVar}\\\\.currentTime\\\\s*=`, \"g\"), kind: \"currentTime\" },\n {\n pattern: new RegExp(`\\\\b${escapedVar}\\\\.muted\\\\s*=`, \"g\"),\n kind: \"muted assignment\",\n },\n ];\n for (const { pattern, kind } of variablePatterns) {\n let match: RegExpExecArray | null;\n while ((match = pattern.exec(script.content)) !== null) {\n findings.push({\n code: \"imperative_media_control\",\n severity: \"error\",\n message: `Inline <script> imperatively controls managed media via ${kind}. HyperFrames must own media play/pause/seek to keep preview, timeline, and renders deterministic.`,\n elementId,\n fixHint:\n \"Remove imperative media play/pause/currentTime/muted control. Express timing with data-start/data-duration and media offsets like data-media-start or data-playback-start instead.\",\n snippet: truncateSnippet(match[0]),\n });\n }\n }\n }\n }\n\n return findings;\n}\n\nexport const mediaRules: Array<(ctx: LintContext) => HyperframeLintFinding[]> = [\n // duplicate_media_id + duplicate_media_discovery_risk\n ({ tags }) => {\n const findings: HyperframeLintFinding[] = [];\n const mediaById = new Map<string, typeof tags>();\n const mediaFingerprintCounts = new Map<string, number>();\n\n for (const tag of tags) {\n if (!isMediaTag(tag.name)) continue;\n const elementId = readAttr(tag.raw, \"id\");\n if (elementId) {\n const existing = mediaById.get(elementId) || [];\n existing.push(tag);\n mediaById.set(elementId, existing);\n }\n const fingerprint = [\n tag.name,\n readAttr(tag.raw, \"src\") || \"\",\n readAttr(tag.raw, \"data-start\") || \"\",\n readAttr(tag.raw, \"data-duration\") || \"\",\n ].join(\"|\");\n mediaFingerprintCounts.set(fingerprint, (mediaFingerprintCounts.get(fingerprint) || 0) + 1);\n }\n\n for (const [elementId, mediaTags] of mediaById) {\n if (mediaTags.length < 2) continue;\n findings.push({\n code: \"duplicate_media_id\",\n severity: \"error\",\n message: `Media id \"${elementId}\" is defined multiple times.`,\n elementId,\n fixHint:\n \"Give each media element a unique id so preview and producer discover the same media graph.\",\n snippet: truncateSnippet(mediaTags[0]?.raw || \"\"),\n });\n }\n\n for (const [fingerprint, count] of mediaFingerprintCounts) {\n if (count < 2) continue;\n const [tagName, src, dataStart, dataDuration] = fingerprint.split(\"|\");\n findings.push({\n code: \"duplicate_media_discovery_risk\",\n severity: \"warning\",\n message: `Detected ${count} matching ${tagName} entries with the same source/start/duration.`,\n fixHint: \"Avoid duplicated media nodes that can be discovered twice during compilation.\",\n snippet: truncateSnippet(\n `${tagName} src=${src} data-start=${dataStart} data-duration=${dataDuration}`,\n ),\n });\n }\n return findings;\n },\n\n // video_missing_muted\n ({ tags }) => {\n const findings: HyperframeLintFinding[] = [];\n for (const tag of tags) {\n if (tag.name !== \"video\") continue;\n const hasMuted = hasAttrName(tag.raw, \"muted\");\n const hasDeclaredAudio = readAttr(tag.raw, \"data-has-audio\") === \"true\";\n if (!hasMuted && !hasDeclaredAudio && readAttr(tag.raw, \"data-start\")) {\n const elementId = readAttr(tag.raw, \"id\") || undefined;\n findings.push({\n code: \"video_missing_muted\",\n severity: \"error\",\n message: `<video${elementId ? ` id=\"${elementId}\"` : \"\"}> has data-start but is not muted. Mark audible videos with data-has-audio=\"true\"; otherwise keep video muted and use a separate <audio> element for sound.`,\n elementId,\n fixHint:\n 'Add the `muted` attribute for silent video, or add data-has-audio=\"true\" when the video track should contribute audio.',\n snippet: truncateSnippet(tag.raw),\n });\n }\n if (hasMuted && hasDeclaredAudio) {\n const elementId = readAttr(tag.raw, \"id\") || undefined;\n findings.push({\n code: \"video_muted_with_declared_audio\",\n severity: \"error\",\n message: `<video${elementId ? ` id=\"${elementId}\"` : \"\"}> declares data-has-audio=\"true\" but also has muted. Studio preview will silence the video audio.`,\n elementId,\n fixHint:\n 'Remove the `muted` attribute if this video should be audible, or remove data-has-audio=\"true\" and use data-volume=\"0\" for silent visual video.',\n snippet: truncateSnippet(tag.raw),\n });\n }\n }\n return findings;\n },\n\n // video_nested_in_timed_element\n ({ source, tags }) => {\n const findings: HyperframeLintFinding[] = [];\n // HTML5 void elements cannot contain children, so they can never be a\n // parent of a nested <video>. Skipping them avoids false positives where\n // the linter looks for `</img>` and never finds it.\n const voidElements = new Set([\n \"area\",\n \"base\",\n \"br\",\n \"col\",\n \"embed\",\n \"hr\",\n \"img\",\n \"input\",\n \"link\",\n \"meta\",\n \"source\",\n \"track\",\n \"wbr\",\n ]);\n const timedTagPositions: Array<{ name: string; start: number; id?: string }> = [];\n for (const tag of tags) {\n if (tag.name === \"video\" || tag.name === \"audio\") continue;\n if (voidElements.has(tag.name)) continue;\n // Skip the composition root — it uses data-start as a playback anchor, not as a clip timer\n if (readAttr(tag.raw, \"data-composition-id\")) continue;\n if (readAttr(tag.raw, \"data-start\")) {\n timedTagPositions.push({\n name: tag.name,\n start: tag.index,\n id: readAttr(tag.raw, \"id\") || undefined,\n });\n }\n }\n for (const tag of tags) {\n if (tag.name !== \"video\") continue;\n if (!readAttr(tag.raw, \"data-start\")) continue;\n for (const parent of timedTagPositions) {\n if (parent.start < tag.index) {\n const parentClosePattern = new RegExp(`</${parent.name}>`, \"gi\");\n const between = source.substring(parent.start, tag.index);\n if (!parentClosePattern.test(between)) {\n findings.push({\n code: \"video_nested_in_timed_element\",\n severity: \"error\",\n message: `<video> with data-start is nested inside <${parent.name}${parent.id ? ` id=\"${parent.id}\"` : \"\"}> which also has data-start. The framework cannot manage playback of nested media — video will be FROZEN in renders.`,\n elementId: readAttr(tag.raw, \"id\") || undefined,\n fixHint:\n \"Move the <video> to be a direct child of the stage, or remove data-start from the wrapper div (use it as a non-timed visual container).\",\n snippet: truncateSnippet(tag.raw),\n });\n break;\n }\n }\n }\n }\n return findings;\n },\n\n // media_in_subcomposition — <video>/<audio> only render as a DIRECT child of the host\n // root (index.html). Inside a sub-composition <template> the runtime never seeks/decodes\n // them, so they render BLANK/black in preview and renders — and the other lint/validate\n // passes otherwise miss it (only a per-frame snapshot reveals the blank panel).\n ({ tags, options }) => {\n const findings: HyperframeLintFinding[] = [];\n if (!options.isSubComposition) return findings;\n for (const tag of tags) {\n if (tag.name !== \"video\" && tag.name !== \"audio\") continue;\n const elementId = readAttr(tag.raw, \"id\") || undefined;\n findings.push({\n code: \"media_in_subcomposition\",\n severity: \"error\",\n message: `<${tag.name}${elementId ? ` id=\"${elementId}\"` : \"\"}> is inside a sub-composition. The runtime only drives media that is a DIRECT child of the host root (index.html); media inside a sub-comp <template> is never seeked/decoded and renders BLANK/black in preview and renders.`,\n elementId,\n fixHint:\n \"Move the media OUT of the sub-composition: place the <video>/<audio> as a direct child of #root in index.html, positioned over the scene, and drive any per-scene motion on the MAIN timeline at global time (a sub-comp timeline cannot reach host elements). See composition-patterns.md archetype B.\",\n snippet: truncateSnippet(tag.raw),\n });\n }\n return findings;\n },\n\n // self_closing_media_tag\n ({ source }) => {\n const findings: HyperframeLintFinding[] = [];\n const selfClosingMediaRe = /<(audio|video)\\b[^>]*\\/>/gi;\n let scMatch: RegExpExecArray | null;\n while ((scMatch = selfClosingMediaRe.exec(source)) !== null) {\n const tagName = scMatch[1] || \"audio\";\n const elementId = readAttr(scMatch[0], \"id\") || undefined;\n findings.push({\n code: \"self_closing_media_tag\",\n severity: \"error\",\n 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.`,\n elementId,\n fixHint: `Change <${tagName} .../> to <${tagName} ...></${tagName}> — media elements MUST have explicit closing tags.`,\n snippet: truncateSnippet(scMatch[0]),\n });\n }\n return findings;\n },\n\n // placeholder_media_url\n ({ tags }) => {\n const findings: HyperframeLintFinding[] = [];\n const PLACEHOLDER_DOMAINS =\n /\\b(placehold\\.co|placeholder\\.com|placekitten\\.com|picsum\\.photos|example\\.com|via\\.placeholder\\.com|dummyimage\\.com)\\b/i;\n for (const tag of tags) {\n if (!isMediaTag(tag.name)) continue;\n const src = readAttr(tag.raw, \"src\");\n if (!src) continue;\n if (PLACEHOLDER_DOMAINS.test(src)) {\n const elementId = readAttr(tag.raw, \"id\") || undefined;\n findings.push({\n code: \"placeholder_media_url\",\n severity: \"error\",\n message: `<${tag.name}${elementId ? ` id=\"${elementId}\"` : \"\"}> uses a placeholder URL that will 404 at render time: ${src.slice(0, 80)}`,\n elementId,\n fixHint: \"Replace with a real media URL. Placeholder domains will 404 at render time.\",\n snippet: truncateSnippet(tag.raw),\n });\n }\n }\n return findings;\n },\n\n // base64_media_prohibited\n ({ source }) => {\n const findings: HyperframeLintFinding[] = [];\n const base64MediaRe =\n /src\\s*=\\s*[\"'](data:(?:audio|video)\\/[^;]+;base64,([A-Za-z0-9+/=]{20,}))[\"']/gi;\n let b64Match: RegExpExecArray | null;\n while ((b64Match = base64MediaRe.exec(source)) !== null) {\n const sample = (b64Match[2] || \"\").slice(0, 200);\n const uniqueChars = new Set(sample.replace(/[A-Za-z0-9+/=]/g, (c) => c)).size;\n const dataSize = Math.round(((b64Match[2] || \"\").length * 3) / 4);\n const isSuspicious = uniqueChars < 15 || (dataSize > 1000 && dataSize < 50000);\n findings.push({\n code: \"base64_media_prohibited\",\n severity: \"error\",\n message: `Inline base64 audio/video detected (${(dataSize / 1024).toFixed(0)} KB)${isSuspicious ? \" — likely fabricated data\" : \"\"}. Base64 media is prohibited — it bloats file size and breaks rendering.`,\n fixHint:\n \"Use a relative path (assets/music.mp3) or HTTPS URL for the audio/video src. Never embed media as base64.\",\n snippet: truncateSnippet((b64Match[1] ?? \"\").slice(0, 80) + \"...\"),\n });\n }\n return findings;\n },\n\n // media_missing_data_start + media_missing_id + media_missing_src + media_preload_none\n ({ tags }) => {\n const findings: HyperframeLintFinding[] = [];\n for (const tag of tags) {\n if (tag.name !== \"video\" && tag.name !== \"audio\") continue;\n const hasDataStart = readAttr(tag.raw, \"data-start\");\n const hasId = readAttr(tag.raw, \"id\");\n const hasSrc = readAttr(tag.raw, \"src\");\n if (hasSrc && !hasDataStart) {\n findings.push({\n code: \"media_missing_data_start\",\n severity: \"error\",\n message: `<${tag.name}${hasId ? ` id=\"${hasId}\"` : \"\"}> has src but no data-start. HyperFrames cannot own playback for untimed media, so preview and render behavior can diverge.`,\n elementId: hasId || undefined,\n fixHint: `Add data-start=\"0\" (or the intended start time) and data-duration if the clip should stop before the source ends.`,\n snippet: truncateSnippet(tag.raw),\n });\n }\n if (hasDataStart && !hasId) {\n findings.push({\n code: \"media_missing_id\",\n severity: \"error\",\n message: `<${tag.name}> has data-start but no id attribute. The renderer requires id to discover media elements — this ${tag.name === \"audio\" ? \"audio will be SILENT\" : \"video will be FROZEN\"} in renders.`,\n fixHint: `Add a unique id attribute: <${tag.name} id=\"my-${tag.name}\" ...>`,\n snippet: truncateSnippet(tag.raw),\n });\n }\n if (hasDataStart && hasId && !hasSrc) {\n findings.push({\n code: \"media_missing_src\",\n severity: \"error\",\n message: `<${tag.name} id=\"${hasId}\"> has data-start but no src attribute. The renderer cannot load this media.`,\n elementId: hasId,\n fixHint: `Add a src attribute to the <${tag.name}> element directly. If using <source> children, the renderer still requires src on the parent element.`,\n snippet: truncateSnippet(tag.raw),\n });\n }\n if (readAttr(tag.raw, \"preload\") === \"none\") {\n findings.push({\n code: \"media_preload_none\",\n severity: \"warning\",\n message: `<${tag.name}${hasId ? ` id=\"${hasId}\"` : \"\"}> has preload=\"none\" which prevents the renderer from loading this media. The compiler strips it for renders, but preview may also have issues.`,\n elementId: hasId || undefined,\n fixHint: `Remove preload=\"none\" or change to preload=\"auto\". The framework manages media loading.`,\n snippet: truncateSnippet(tag.raw),\n });\n }\n }\n return findings;\n },\n\n // video_audio_double_source — catches audible <video> paired with a separate\n // <audio> pointing to the same file, which causes double playback at runtime\n ({ tags }) => {\n const findings: HyperframeLintFinding[] = [];\n const videoSources = new Map<string, { id?: string; raw: string }>();\n const audioSources = new Map<string, { id?: string; raw: string }>();\n\n for (const tag of tags) {\n if (!readAttr(tag.raw, \"data-start\")) continue;\n const src = readAttr(tag.raw, \"src\");\n if (!src) continue;\n const elementId = readAttr(tag.raw, \"id\") || undefined;\n if (tag.name === \"video\") {\n const isMuted = hasAttrName(tag.raw, \"muted\");\n if (!isMuted) {\n videoSources.set(src, { id: elementId, raw: tag.raw });\n }\n } else if (tag.name === \"audio\") {\n audioSources.set(src, { id: elementId, raw: tag.raw });\n }\n }\n\n for (const [src, audioInfo] of audioSources) {\n const videoInfo = videoSources.get(src);\n if (!videoInfo) continue;\n findings.push({\n code: \"video_audio_double_source\",\n severity: \"error\",\n message: `<audio${audioInfo.id ? ` id=\"${audioInfo.id}\"` : \"\"}> and <video${videoInfo.id ? ` id=\"${videoInfo.id}\"` : \"\"}> both point to the same source. The unmuted video already provides audio — the duplicate <audio> will cause double playback and echo.`,\n elementId: audioInfo.id,\n fixHint:\n \"Either mute the video (add `muted` attribute) and keep the separate <audio>, or remove the <audio> element and let the video provide its own audio track.\",\n snippet: truncateSnippet(audioInfo.raw),\n });\n }\n return findings;\n },\n\n // imperative_media_control\n findImperativeMediaControlFindings,\n];\n","interface LintParsedGsap {\n animations: Array<{\n targetSelector: string;\n method: string;\n position: number | string;\n properties: Record<string, number | string>;\n duration?: number;\n ease?: string;\n extras?: Record<string, unknown>;\n }>;\n timelineVar: string;\n}\n\n// Use the acorn read parser: it resolves computed timelines (helpers, bounded\n// loops) so lint findings like overlapping_gsap_tweens reflect true positions\n// instead of all-collapsed-at-0. It's also browser-safe, so this keeps recast\n// out of the lint graph entirely. Dynamic import preserves the lazy load.\nasync function loadParseGsapScript(): Promise<(script: string) => LintParsedGsap> {\n const mod = await import(\"@hyperframes/parsers/gsap-parser-acorn\");\n return mod.parseGsapScriptAcorn as unknown as (script: string) => LintParsedGsap;\n}\nimport type { LintContext } from \"../context\";\nimport type { HyperframeLintFinding, LintRule } from \"../types\";\nimport type { OpenTag } from \"../utils\";\nimport {\n readAttr,\n truncateSnippet,\n stripJsComments,\n WINDOW_TIMELINE_ASSIGN_PATTERN,\n} from \"../utils\";\n\n// ── GSAP-specific types ────────────────────────────────────────────────────\n\ntype GsapWindow = {\n targetSelector: string;\n position: number;\n end: number;\n properties: string[];\n propertyValues: Record<string, string | number>;\n overwriteAuto: boolean;\n method: string;\n raw: string;\n};\n\ntype CompositionRange = {\n id: string;\n start: number;\n end: number;\n};\n\nconst SCENE_BOUNDARY_EPSILON_SECONDS = 0.05;\n\n// ── GSAP parsing utilities ─────────────────────────────────────────────────\n\nfunction countClassUsage(tags: OpenTag[]): Map<string, number> {\n const counts = new Map<string, number>();\n for (const tag of tags) {\n const classAttr = readAttr(tag.raw, \"class\");\n if (!classAttr) continue;\n for (const className of classAttr.split(/\\s+/).filter(Boolean)) {\n counts.set(className, (counts.get(className) || 0) + 1);\n }\n }\n return counts;\n}\n\nfunction readRegisteredTimelineCompositionId(script: string): string | null {\n const match = script.match(WINDOW_TIMELINE_ASSIGN_PATTERN);\n return match?.[1] || match?.[2] || null;\n}\n\n/** Strip a `__raw:` prefix the parser adds to unresolvable values. */\nfunction unwrapRaw(value: unknown): string | number | undefined {\n if (typeof value === \"number\") return value;\n if (typeof value !== \"string\") return undefined;\n const code = value.startsWith(\"__raw:\") ? value.slice(6) : value;\n return code.replace(/^\\s*[\"']|[\"']\\s*$/g, \"\");\n}\n\nfunction extrasNumber(value: unknown): number {\n const unwrapped = unwrapRaw(value);\n const numeric = typeof unwrapped === \"number\" ? unwrapped : Number(unwrapped);\n return Number.isFinite(numeric) ? numeric : 0;\n}\n\n/** A readable single-line snippet of a tween for finding messages. */\nfunction synthesizeWindowRaw(\n timelineVar: string,\n anim: LintParsedGsap[\"animations\"][number],\n): string {\n const entries = Object.entries(anim.properties).map(([k, v]) => {\n if (typeof v === \"string\" && v.startsWith(\"__raw:\")) return `${k}: ${v.slice(6)}`;\n return `${k}: ${typeof v === \"string\" ? JSON.stringify(v) : v}`;\n });\n if (anim.duration !== undefined) entries.push(`duration: ${anim.duration}`);\n if (anim.ease) entries.push(`ease: ${JSON.stringify(anim.ease)}`);\n const pos = typeof anim.position === \"number\" ? anim.position : JSON.stringify(anim.position);\n return `${timelineVar}.${anim.method}(\"${anim.targetSelector}\", { ${entries.join(\", \")} }, ${pos})`;\n}\n\nconst gsapWindowsCache = new Map<string, GsapWindow[]>();\n\nasync function cachedExtractGsapWindows(scriptContent: string): Promise<GsapWindow[]> {\n const cached = gsapWindowsCache.get(scriptContent);\n if (cached) return cached;\n const windows = await extractGsapWindows(scriptContent);\n gsapWindowsCache.set(scriptContent, windows);\n return windows;\n}\n\n// fallow-ignore-next-line complexity\nasync function extractGsapWindows(script: string): Promise<GsapWindow[]> {\n if (!/gsap\\.timeline/.test(script)) return [];\n const parseGsapScript = await loadParseGsapScript();\n const parsed = parseGsapScript(script);\n if (parsed.animations.length === 0) return [];\n\n const windows: GsapWindow[] = [];\n for (const animation of parsed.animations) {\n // Skip animations with string positions (e.g. \"+=1\", \"<\") — their absolute\n // timing depends on runtime evaluation and can't be statically linted.\n if (typeof animation.position !== \"number\") continue;\n const repeat = extrasNumber(animation.extras?.repeat);\n const cycleCount = repeat > 0 ? repeat + 1 : 1;\n const effectiveDuration =\n animation.method === \"set\" ? 0 : (animation.duration ?? 0) * cycleCount;\n windows.push({\n targetSelector: animation.targetSelector,\n position: animation.position,\n end: animation.position + effectiveDuration,\n properties: Object.keys(animation.properties),\n propertyValues: animation.properties,\n overwriteAuto: unwrapRaw(animation.extras?.overwrite) === \"auto\",\n method: animation.method,\n raw: synthesizeWindowRaw(parsed.timelineVar, animation),\n });\n }\n return windows;\n}\n\nfunction numberValue(value: string | number | undefined): number | null {\n if (typeof value === \"number\") return value;\n if (typeof value === \"string\" && value.trim()) {\n const numeric = Number(value);\n return Number.isFinite(numeric) ? numeric : null;\n }\n return null;\n}\n\nfunction stringValue(value: string | number | undefined): string | null {\n if (typeof value === \"string\") return value;\n if (typeof value === \"number\") return String(value);\n return null;\n}\n\nfunction zeroValue(value: string | number | undefined): boolean {\n if (typeof value === \"number\") return value === 0;\n if (typeof value !== \"string\") return false;\n return Number(value.trim()) === 0;\n}\n\nfunction isHiddenGsapState(values: Record<string, string | number>): boolean {\n const visibility = stringValue(values.visibility)?.toLowerCase();\n const display = stringValue(values.display)?.toLowerCase();\n return (\n zeroValue(values.opacity) ||\n zeroValue(values.autoAlpha) ||\n visibility === \"hidden\" ||\n display === \"none\"\n );\n}\n\nfunction oneValue(\n values: Record<string, string | number>,\n keys: string[],\n): string | number | undefined {\n for (const key of keys) {\n const value = values[key];\n if (value !== undefined) return value;\n }\n return undefined;\n}\n\nfunction isVisibleGsapState(values: Record<string, string | number>): boolean {\n const opacity = oneValue(values, [\"opacity\", \"autoAlpha\"]);\n if (typeof opacity === \"number\") return opacity > 0;\n if (typeof opacity === \"string\" && opacity.trim()) {\n const numeric = Number(opacity);\n if (Number.isFinite(numeric)) return numeric > 0;\n }\n\n const visibility = stringValue(values.visibility)?.toLowerCase();\n if (visibility === \"visible\" || visibility === \"inherit\") return true;\n\n const display = stringValue(values.display)?.toLowerCase();\n if (display && display !== \"none\") return true;\n\n return false;\n}\n\nfunction makesOverlayVisible(win: GsapWindow): boolean {\n if (win.method === \"from\" && isHiddenGsapState(win.propertyValues)) return true;\n return isVisibleGsapState(win.propertyValues);\n}\n\nfunction isSceneBoundaryExit(win: GsapWindow): boolean {\n if (win.end <= win.position) return false;\n if (win.method !== \"to\" && win.method !== \"fromTo\") return false;\n return isHiddenGsapState(win.propertyValues);\n}\n\nfunction isHardKillSet(win: GsapWindow, selector: string, boundary: number): boolean {\n return (\n win.method === \"set\" &&\n win.targetSelector === selector &&\n Math.abs(win.position - boundary) <= SCENE_BOUNDARY_EPSILON_SECONDS &&\n isHiddenGsapState(win.propertyValues)\n );\n}\n\nfunction hiddenStateLiteral(values: Record<string, string | number>): string {\n if (zeroValue(values.autoAlpha)) return \"{ autoAlpha: 0 }\";\n if (zeroValue(values.opacity)) return \"{ opacity: 0 }\";\n if (stringValue(values.visibility)?.toLowerCase() === \"hidden\") return '{ visibility: \"hidden\" }';\n if (stringValue(values.display)?.toLowerCase() === \"none\") return '{ display: \"none\" }';\n return \"{ opacity: 0 }\";\n}\n\nfunction findTagEnd(source: string, tag: OpenTag): number {\n const escapedTagName = tag.name.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n const pattern = new RegExp(`<\\\\/?${escapedTagName}\\\\b[^>]*>`, \"gi\");\n pattern.lastIndex = tag.index;\n\n let depth = 0;\n let match: RegExpExecArray | null;\n while ((match = pattern.exec(source)) !== null) {\n const raw = match[0];\n const isClosing = /^<\\s*\\//.test(raw);\n const isSelfClosing = /\\/\\s*>$/.test(raw);\n if (!isClosing && !isSelfClosing) depth += 1;\n if (isClosing) depth -= 1;\n if (depth === 0) return pattern.lastIndex;\n }\n\n return source.length;\n}\n\nfunction collectCompositionRanges(source: string, tags: OpenTag[]): CompositionRange[] {\n return tags\n .map((tag) => {\n const id = readAttr(tag.raw, \"data-composition-id\");\n if (!id) return null;\n return {\n id,\n start: tag.index,\n end: findTagEnd(source, tag),\n };\n })\n .filter((range) => range !== null);\n}\n\nfunction findContainingCompositionId(tag: OpenTag, ranges: CompositionRange[]): string | null {\n let match: CompositionRange | null = null;\n for (const range of ranges) {\n if (tag.index < range.start || tag.index >= range.end) continue;\n if (!match || range.start >= match.start) match = range;\n }\n return match?.id || null;\n}\n\nfunction collectClipStartBoundariesByComposition(\n source: string,\n tags: OpenTag[],\n): Map<string, number[]> {\n const ranges = collectCompositionRanges(source, tags);\n const boundaries = new Map<string, Set<number>>();\n\n for (const tag of tags) {\n const classAttr = readAttr(tag.raw, \"class\") || \"\";\n const classes = classAttr.split(/\\s+/).filter(Boolean);\n if (!classes.includes(\"clip\")) continue;\n const compositionId = findContainingCompositionId(tag, ranges);\n if (!compositionId) continue;\n const start = numberValue(readAttr(tag.raw, \"data-start\") ?? undefined);\n if (start == null || start <= 0) continue;\n const compositionBoundaries = boundaries.get(compositionId) ?? new Set<number>();\n compositionBoundaries.add(start);\n boundaries.set(compositionId, compositionBoundaries);\n }\n\n return new Map(\n [...boundaries.entries()].map(([compositionId, values]) => [\n compositionId,\n [...values].sort((a, b) => a - b),\n ]),\n );\n}\n\nfunction findMatchingSceneBoundary(time: number, boundaries: number[]): number | null {\n for (const boundary of boundaries) {\n if (Math.abs(time - boundary) <= SCENE_BOUNDARY_EPSILON_SECONDS) return boundary;\n }\n return null;\n}\n\nfunction isSuspiciousGlobalSelector(selector: string): boolean {\n if (!selector) return false;\n if (selector.includes(\"[data-composition-id=\")) return false;\n if (selector.startsWith(\"#\")) return false;\n return selector.startsWith(\".\") || /^[a-z]/i.test(selector);\n}\n\nfunction getSingleClassSelector(selector: string): string | null {\n const match = selector.trim().match(/^\\.(?<name>[A-Za-z0-9_-]+)$/);\n return match?.groups?.name || null;\n}\n\nfunction readStyleProperty(style: string, property: string): string | null {\n const escapedProperty = property.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n const match = style.match(new RegExp(`(?:^|;)\\\\s*${escapedProperty}\\\\s*:\\\\s*([^;]+)`, \"i\"));\n return match?.[1]?.trim() || null;\n}\n\nfunction cssZero(value: string | null): boolean {\n if (!value) return false;\n return /^0(?:\\.0+)?(?:px|%|vw|vh|rem|em)?$/i.test(value.trim());\n}\n\nfunction styleHasHiddenInitialState(style: string): boolean {\n const opacity = readStyleProperty(style, \"opacity\");\n if (opacity && Number(opacity) === 0) return true;\n if (readStyleProperty(style, \"visibility\")?.toLowerCase() === \"hidden\") return true;\n if (readStyleProperty(style, \"display\")?.toLowerCase() === \"none\") return true;\n return false;\n}\n\nfunction styleHasOpaqueBackground(style: string): boolean {\n const background =\n readStyleProperty(style, \"background\") || readStyleProperty(style, \"background-color\");\n if (!background) return false;\n const normalized = background.toLowerCase().replace(/\\s+/g, \"\");\n if (normalized === \"transparent\" || normalized === \"none\") return false;\n if (/rgba?\\([^)]*,0(?:\\.0+)?\\)$/.test(normalized)) return false;\n if (/hsla?\\([^)]*,0(?:\\.0+)?\\)$/.test(normalized)) return false;\n return true;\n}\n\nfunction styleLooksFullFrameOverlay(style: string): boolean {\n const position = readStyleProperty(style, \"position\")?.toLowerCase();\n if (position !== \"fixed\" && position !== \"absolute\") return false;\n const coversFrame =\n cssZero(readStyleProperty(style, \"inset\")) ||\n (cssZero(readStyleProperty(style, \"top\")) &&\n cssZero(readStyleProperty(style, \"right\")) &&\n cssZero(readStyleProperty(style, \"bottom\")) &&\n cssZero(readStyleProperty(style, \"left\")));\n return coversFrame && styleHasOpaqueBackground(style);\n}\n\nfunction collectSimpleStyleRules(styles: LintContext[\"styles\"]): Map<string, string> {\n const rules = new Map<string, string>();\n for (const style of styles) {\n for (const [, selectorList, body] of style.content.matchAll(/([^{}]+)\\{([^}]+)\\}/g)) {\n if (!selectorList || !body) continue;\n for (const selector of selectorList.split(\",\")) {\n const token = selector.trim();\n if (!/^[#.][A-Za-z0-9_-]+$/.test(token)) continue;\n rules.set(token, `${rules.get(token) || \"\"};${body}`);\n }\n }\n }\n return rules;\n}\n\nfunction tagSimpleSelectors(tag: OpenTag): string[] {\n const selectors: string[] = [];\n const id = readAttr(tag.raw, \"id\");\n if (id) selectors.push(`#${id}`);\n const classes = readAttr(tag.raw, \"class\")?.split(/\\s+/).filter(Boolean) ?? [];\n for (const className of classes) selectors.push(`.${className}`);\n return selectors;\n}\n\nfunction combinedTagStyle(tag: OpenTag, styleRules: Map<string, string>): string {\n const styles = [readAttr(tag.raw, \"style\") || \"\"];\n for (const selector of tagSimpleSelectors(tag)) {\n const ruleStyle = styleRules.get(selector);\n if (ruleStyle) styles.push(ruleStyle);\n }\n return styles.filter(Boolean).join(\";\");\n}\n\n// fallow-ignore-next-line complexity\nfunction cssTransformToGsapProps(cssTransform: string): string | null {\n const parts: string[] = [];\n\n // translate(-50%, -50%) or translate(X, Y)\n const translateMatch = cssTransform.match(\n /translate\\(\\s*(-?[\\d.]+)(%|px)?\\s*,\\s*(-?[\\d.]+)(%|px)?\\s*\\)/,\n );\n if (translateMatch) {\n const [, xVal, xUnit, yVal, yUnit] = translateMatch;\n if (xUnit === \"%\") parts.push(`xPercent: ${xVal}`);\n else parts.push(`x: ${xVal}`);\n if (yUnit === \"%\") parts.push(`yPercent: ${yVal}`);\n else parts.push(`y: ${yVal}`);\n }\n\n // translateX(-50%) or translateX(px)\n const txMatch = cssTransform.match(/translateX\\(\\s*(-?[\\d.]+)(%|px)?\\s*\\)/);\n if (txMatch) {\n const [, val, unit] = txMatch;\n parts.push(unit === \"%\" ? `xPercent: ${val}` : `x: ${val}`);\n }\n\n // translateY(-50%) or translateY(px)\n const tyMatch = cssTransform.match(/translateY\\(\\s*(-?[\\d.]+)(%|px)?\\s*\\)/);\n if (tyMatch) {\n const [, val, unit] = tyMatch;\n parts.push(unit === \"%\" ? `yPercent: ${val}` : `y: ${val}`);\n }\n\n // scale(N)\n const scaleMatch = cssTransform.match(/scale\\(\\s*([\\d.]+)\\s*\\)/);\n if (scaleMatch) {\n parts.push(`scale: ${scaleMatch[1]}`);\n }\n\n return parts.length > 0 ? parts.join(\", \") : null;\n}\n\n// ── CSS-transform ↔ GSAP-transform conflict matching ─────────────────────────\n\n// Transform components that COMBINE with a CSS translate/scale on the same\n// element. GSAP bakes the element's existing CSS transform in when it seeks, so\n// these stack rather than override in the capture path (e.g. CSS translateX(-50%)\n// + xPercent:-50 renders as -100% — off-centre). `rotation` is excluded: it maps\n// to CSS rotate(), which this rule treats separately (no false positive on spin).\nconst CONFLICTING_TRANSLATE_PROPS = [\"x\", \"y\", \"xPercent\", \"yPercent\"];\nconst CONFLICTING_SCALE_PROPS = [\"scale\", \"scaleX\", \"scaleY\"];\n\ntype GsapTransformCall = {\n method: string;\n selector: string;\n properties: string[];\n raw: string;\n};\n\n// Decompose a (possibly grouped / descendant / compound) GSAP target selector\n// into the simple `#id` / `.class` tokens of the elements it actually targets —\n// the RIGHTMOST compound of each comma group is the targeted element. This lets a\n// CSS rule keyed by a simple selector (`.m04-label`) match a scoped GSAP selector\n// (`\"#root .m04-label, #root .m04-sub\"`), which the prior exact-string lookup\n// missed — so every scoped/grouped selector slipped past the rule entirely.\nfunction targetedSelectorTokens(selector: string): Set<string> {\n const tokens = new Set<string>();\n for (const group of selector.split(\",\")) {\n const compounds = group\n .trim()\n .split(/[\\s>+~]+/)\n .filter(Boolean);\n const last = compounds[compounds.length - 1];\n if (!last) continue;\n const simple = last.match(/[#.][A-Za-z0-9_-]+/g);\n if (simple) for (const token of simple) tokens.add(token);\n }\n return tokens;\n}\n\n// Find a CSS transform conflicting with a GSAP target selector: exact-string\n// match first (fast path + back-compat with the original behaviour), then a\n// token match so scoped/grouped/descendant selectors resolve to their class/id.\nfunction matchCssTransform(gsapSelector: string, cssMap: Map<string, string>): string | undefined {\n if (cssMap.size === 0) return undefined;\n const direct = cssMap.get(gsapSelector);\n if (direct) return direct;\n const tokens = targetedSelectorTokens(gsapSelector);\n for (const [cssSelector, value] of cssMap) {\n if (tokens.has(cssSelector)) return value;\n }\n return undefined;\n}\n\n// Scan for STANDALONE `gsap.set/to/from/fromTo(\"selector\", { ...props })` calls.\n// The acorn timeline parser only captures calls rooted on the timeline var\n// (`tl.to`, `tl.set`, …); a top-level `gsap.set(\"#root .label\", { xPercent: -50 })`\n// — a common way to seat shared base transforms before the timeline runs — is\n// invisible to it, so the conflict rule never saw it. Variable selectors\n// (`gsap.set(kicker, …)`) can't be resolved statically and are skipped.\nfunction extractStandaloneGsapTransformCalls(script: string): GsapTransformCall[] {\n const calls: GsapTransformCall[] = [];\n const pattern = /gsap\\.(set|to|from|fromTo)\\s*\\(\\s*([\"'])([^\"']+)\\2\\s*,\\s*\\{([^{}]*)\\}/g;\n let match: RegExpExecArray | null;\n while ((match = pattern.exec(script)) !== null) {\n const method = match[1] ?? \"set\";\n const selector = match[3] ?? \"\";\n const propsBody = match[4] ?? \"\";\n const properties = [...propsBody.matchAll(/([A-Za-z_$][\\w$]*)\\s*:/g)].map((m) => m[1] ?? \"\");\n calls.push({ method, selector, properties, raw: truncateSnippet(match[0]) ?? match[0] });\n }\n return calls;\n}\n\n// ── GSAP rules ─────────────────────────────────────────────────────────────\n\n// fallow-ignore-next-line complexity\nexport const gsapRules: LintRule<LintContext>[] = [\n // overlapping_gsap_tweens + gsap_animates_clip_element + unscoped_gsap_selector\n // fallow-ignore-next-line complexity\n async ({ source, tags, scripts, styles, rootCompositionId }) => {\n const findings: HyperframeLintFinding[] = [];\n\n // Build clip element selector map\n type ClipInfo = { tag: string; id: string; classes: string };\n const clipIds = new Map<string, ClipInfo>();\n const clipClasses = new Map<string, ClipInfo>();\n for (const tag of tags) {\n const classAttr = readAttr(tag.raw, \"class\") || \"\";\n const classes = classAttr.split(/\\s+/).filter(Boolean);\n if (!classes.includes(\"clip\")) continue;\n const id = readAttr(tag.raw, \"id\");\n const info: ClipInfo = {\n tag: tag.name,\n id: id || \"\",\n classes: classAttr,\n };\n if (id) clipIds.set(`#${id}`, info);\n for (const cls of classes) {\n if (cls !== \"clip\") clipClasses.set(`.${cls}`, info);\n }\n }\n\n const classUsage = countClassUsage(tags);\n const clipStartBoundariesByComposition = collectClipStartBoundariesByComposition(source, tags);\n const styleRules = collectSimpleStyleRules(styles);\n const reportedVisibleOverlayKeys = new Set<string>();\n\n for (const script of scripts) {\n const localTimelineCompId = readRegisteredTimelineCompositionId(script.content);\n const gsapWindows = await cachedExtractGsapWindows(script.content);\n const clipStartBoundaries =\n clipStartBoundariesByComposition.get(localTimelineCompId || rootCompositionId || \"\") ?? [];\n\n // overlapping_gsap_tweens\n for (let i = 0; i < gsapWindows.length; i++) {\n const left = gsapWindows[i];\n if (!left) continue;\n if (left.end <= left.position) continue;\n for (let j = i + 1; j < gsapWindows.length; j++) {\n const right = gsapWindows[j];\n if (!right) continue;\n if (right.end <= right.position) continue;\n if (left.targetSelector !== right.targetSelector) continue;\n const overlapStart = Math.max(left.position, right.position);\n const overlapEnd = Math.min(left.end, right.end);\n if (overlapEnd <= overlapStart) continue;\n if (left.overwriteAuto || right.overwriteAuto) continue;\n const sharedProperties = left.properties.filter((prop) =>\n right.properties.includes(prop),\n );\n if (sharedProperties.length === 0) continue;\n findings.push({\n code: \"overlapping_gsap_tweens\",\n severity: \"warning\",\n message: `GSAP tweens overlap on \"${left.targetSelector}\" for ${sharedProperties.join(\", \")} between ${overlapStart.toFixed(2)}s and ${overlapEnd.toFixed(2)}s.`,\n selector: left.targetSelector,\n fixHint: 'Shorten the earlier tween, move the later tween, or add `overwrite: \"auto\"`.',\n snippet: truncateSnippet(`${left.raw}\\n${right.raw}`),\n });\n }\n }\n\n // gsap_exit_missing_hard_kill\n if (clipStartBoundaries.length > 0) {\n for (const win of gsapWindows) {\n if (!isSceneBoundaryExit(win)) continue;\n const boundary = findMatchingSceneBoundary(win.end, clipStartBoundaries);\n if (boundary == null) continue;\n const hasHardKill = gsapWindows.some((candidate) =>\n isHardKillSet(candidate, win.targetSelector, boundary),\n );\n if (hasHardKill) continue;\n\n findings.push({\n code: \"gsap_exit_missing_hard_kill\",\n severity: \"error\",\n message:\n `GSAP exit on \"${win.targetSelector}\" ends at the ${boundary.toFixed(2)}s clip start boundary ` +\n \"without a matching tl.set hard kill. Non-linear seeking can land after the fade and leave stale visibility state.\",\n selector: win.targetSelector,\n fixHint:\n `Add \\`tl.set(\"${win.targetSelector}\", ${hiddenStateLiteral(win.propertyValues)}, ${boundary.toFixed(2)})\\` ` +\n \"after the exit tween.\",\n snippet: truncateSnippet(win.raw),\n });\n }\n }\n\n // gsap_fullscreen_overlay_starts_visible\n for (const tag of tags) {\n const selectors = tagSimpleSelectors(tag);\n if (selectors.length === 0) continue;\n const overlayKey = readAttr(tag.raw, \"id\") || String(tag.index);\n if (reportedVisibleOverlayKeys.has(overlayKey)) continue;\n const authoredStyle = combinedTagStyle(tag, styleRules);\n if (!authoredStyle || !styleLooksFullFrameOverlay(authoredStyle)) continue;\n if (styleHasHiddenInitialState(authoredStyle)) continue;\n\n const visibilityWindows = gsapWindows\n .filter((win) => {\n const tokens = targetedSelectorTokens(win.targetSelector);\n if (!selectors.some((selector) => tokens.has(selector))) return false;\n return win.properties.some((prop) =>\n [\"opacity\", \"autoAlpha\", \"visibility\", \"display\"].includes(prop),\n );\n })\n .sort((a, b) => a.position - b.position);\n const startsHiddenAtZero = visibilityWindows.some(\n (win) =>\n win.position <= SCENE_BOUNDARY_EPSILON_SECONDS && isHiddenGsapState(win.propertyValues),\n );\n if (startsHiddenAtZero) continue;\n const firstVisible = visibilityWindows.find((win) => makesOverlayVisible(win));\n if (!firstVisible) continue;\n const selector =\n selectors.find((candidate) =>\n targetedSelectorTokens(firstVisible.targetSelector).has(candidate),\n ) ||\n selectors[0] ||\n tag.name;\n const laterHidden = visibilityWindows.some(\n (win) => win.position >= firstVisible.position && isHiddenGsapState(win.propertyValues),\n );\n if (firstVisible.method !== \"from\" && !laterHidden) continue;\n\n reportedVisibleOverlayKeys.add(overlayKey);\n findings.push({\n code: \"gsap_fullscreen_overlay_starts_visible\",\n severity: \"error\",\n message:\n `Full-frame overlay \"${selector}\" starts visible before its first GSAP opacity tween at ` +\n `${firstVisible.position.toFixed(2)}s. It will cover earlier render frames, often as a blank/white video.`,\n selector,\n elementId: readAttr(tag.raw, \"id\") || undefined,\n fixHint:\n `Add \\`opacity: 0\\` to \"${selector}\" in CSS/inline styles, or add ` +\n `\\`tl.set(\"${selector}\", { opacity: 0 }, 0)\\` before the reveal tween.`,\n snippet: truncateSnippet(firstVisible.raw),\n });\n }\n\n // gsap_animates_clip_element — only error when GSAP animates visibility/display\n for (const win of gsapWindows) {\n const sel = win.targetSelector;\n const clipInfo = clipIds.get(sel) || clipClasses.get(sel);\n if (!clipInfo) continue;\n const conflictingProps = win.properties.filter(\n (p) => p === \"visibility\" || p === \"display\",\n );\n if (conflictingProps.length === 0) continue;\n const elDesc = `<${clipInfo.tag}${clipInfo.id ? ` id=\"${clipInfo.id}\"` : \"\"} class=\"${clipInfo.classes}\">`;\n findings.push({\n code: \"gsap_animates_clip_element\",\n severity: \"error\",\n message: `GSAP animation sets ${conflictingProps.join(\", \")} on a clip element. Selector \"${sel}\" resolves to element ${elDesc}. The framework manages clip visibility via ${conflictingProps.join(\"/\")} — do not animate these properties on clip elements.`,\n selector: sel,\n elementId: clipInfo.id || undefined,\n fixHint:\n \"Remove the visibility/display tween, or move the content into a child <div> and target that instead.\",\n snippet: truncateSnippet(win.raw),\n });\n }\n\n // unscoped_gsap_selector\n if (!localTimelineCompId || localTimelineCompId === rootCompositionId) continue;\n for (const win of gsapWindows) {\n if (!isSuspiciousGlobalSelector(win.targetSelector)) continue;\n const className = getSingleClassSelector(win.targetSelector);\n if (className && (classUsage.get(className) || 0) < 2) continue;\n findings.push({\n code: \"unscoped_gsap_selector\",\n severity: \"error\",\n message: `Timeline \"${localTimelineCompId}\" uses unscoped selector \"${win.targetSelector}\" that will target elements in ALL compositions when bundled, causing data loss (opacity, transforms, etc.).`,\n selector: win.targetSelector,\n fixHint: `Scope the selector: \\`[data-composition-id=\"${localTimelineCompId}\"] ${win.targetSelector}\\` or use a unique id.`,\n snippet: truncateSnippet(win.raw),\n });\n }\n }\n return findings;\n },\n\n // gsap_css_transform_conflict\n // fallow-ignore-next-line complexity\n async ({ styles, scripts, tags }) => {\n const findings: HyperframeLintFinding[] = [];\n const cssTranslateSelectors = new Map<string, string>();\n const cssScaleSelectors = new Map<string, string>();\n\n // Check <style> blocks for transform rules\n for (const style of styles) {\n for (const [, selector, body] of style.content.matchAll(\n /([#.][a-zA-Z0-9_-]+)\\s*\\{([^}]+)\\}/g,\n )) {\n const tMatch = body?.match(/transform\\s*:\\s*([^;]+)/);\n if (!tMatch || !tMatch[1]) continue;\n const transformVal = tMatch[1].trim();\n if (/translate/i.test(transformVal))\n cssTranslateSelectors.set((selector ?? \"\").trim(), transformVal);\n if (/scale/i.test(transformVal))\n cssScaleSelectors.set((selector ?? \"\").trim(), transformVal);\n }\n }\n\n // Also check inline style=\"...\" attributes on tags\n for (const tag of tags) {\n const inlineStyle = readAttr(tag.raw, \"style\");\n if (!inlineStyle) continue;\n const tMatch = inlineStyle.match(/transform\\s*:\\s*([^;]+)/);\n if (!tMatch || !tMatch[1]) continue;\n const transformVal = tMatch[1].trim();\n // Derive selectors from the tag's id and all classes\n const id = readAttr(tag.raw, \"id\");\n const classes = readAttr(tag.raw, \"class\")?.split(/\\s+/).filter(Boolean) ?? [];\n const selectors: string[] = [];\n if (id) selectors.push(`#${id}`);\n for (const cls of classes) selectors.push(`.${cls}`);\n if (selectors.length === 0) continue;\n for (const sel of selectors) {\n if (/translate/i.test(transformVal) && !cssTranslateSelectors.has(sel))\n cssTranslateSelectors.set(sel, transformVal);\n if (/scale/i.test(transformVal) && !cssScaleSelectors.has(sel))\n cssScaleSelectors.set(sel, transformVal);\n }\n }\n\n if (cssTranslateSelectors.size === 0 && cssScaleSelectors.size === 0) return findings;\n\n for (const script of scripts) {\n if (!/gsap\\.timeline/.test(script.content)) continue;\n const windows = await cachedExtractGsapWindows(script.content);\n\n // Two sources of transform-setting calls: timeline-rooted tweens (from the\n // acorn parser) and standalone gsap.* calls (regex — the parser ignores\n // these). Normalize both into one shape and run the same conflict check.\n const calls: GsapTransformCall[] = [\n ...windows.map((win) => ({\n method: win.method,\n selector: win.targetSelector,\n properties: win.properties,\n raw: win.raw,\n })),\n ...extractStandaloneGsapTransformCalls(stripJsComments(script.content)),\n ];\n\n type Conflict = { cssTransform: string; props: Set<string>; raw: string };\n const conflicts = new Map<string, Conflict>();\n\n for (const call of calls) {\n // from() and fromTo() both supply explicit start values so GSAP owns\n // the full transform from t=0, making the CSS conflict moot\n if (call.method === \"fromTo\" || call.method === \"from\") continue;\n const sel = call.selector;\n const translateProps = call.properties.filter((p) =>\n CONFLICTING_TRANSLATE_PROPS.includes(p),\n );\n const scaleProps = call.properties.filter((p) => CONFLICTING_SCALE_PROPS.includes(p));\n const cssFromTranslate =\n translateProps.length > 0 ? matchCssTransform(sel, cssTranslateSelectors) : undefined;\n const cssFromScale =\n scaleProps.length > 0 ? matchCssTransform(sel, cssScaleSelectors) : undefined;\n if (!cssFromTranslate && !cssFromScale) continue;\n const existing = conflicts.get(sel) ?? {\n cssTransform: [cssFromTranslate, cssFromScale].filter(Boolean).join(\" \"),\n props: new Set<string>(),\n raw: call.raw,\n };\n for (const p of [...translateProps, ...scaleProps]) existing.props.add(p);\n conflicts.set(sel, existing);\n }\n\n for (const [sel, { cssTransform, props, raw }] of conflicts) {\n const propList = [...props].join(\"/\");\n const gsapEquivalent = cssTransformToGsapProps(cssTransform);\n const fixHint = gsapEquivalent\n ? `Remove \\`transform: ${cssTransform}\\` from CSS and replace with GSAP properties: ${gsapEquivalent}. ` +\n `Example: tl.fromTo('${sel}', { ${gsapEquivalent} }, { ${gsapEquivalent}, ...yourAnimation }). ` +\n `tl.fromTo is exempt from this rule.`\n : `Remove the transform from CSS and use tl.fromTo('${sel}', ` +\n `{ xPercent: -50, x: -1000 }, { xPercent: -50, x: 0 }) so GSAP owns ` +\n `the full transform state. tl.fromTo is exempt from this rule.`;\n findings.push({\n code: \"gsap_css_transform_conflict\",\n severity: \"error\",\n message:\n `\"${sel}\" has CSS \\`transform: ${cssTransform}\\` and a GSAP tween animates ` +\n `${propList}. GSAP will overwrite the full CSS transform, discarding any ` +\n `translateX(-50%) centering or CSS scale value.`,\n selector: sel,\n fixHint,\n snippet: truncateSnippet(raw),\n });\n }\n }\n return findings;\n },\n\n // missing_gsap_script\n ({ scripts, rawSource, options }) => {\n const allScriptTexts = scripts.filter((s) => !/\\bsrc\\s*=/.test(s.attrs)).map((s) => s.content);\n const allScriptSrcs = scripts\n .map((s) => readAttr(`<script ${s.attrs}>`, \"src\") || \"\")\n .filter(Boolean);\n const canInheritGsapFromHost =\n options.isSubComposition || rawSource.trimStart().toLowerCase().startsWith(\"<template\");\n\n const usesGsap = allScriptTexts.some((t) =>\n /gsap\\.(to|from|fromTo|timeline|set|registerPlugin)\\b/.test(t),\n );\n const hasGsapScript = allScriptSrcs.some((src) => /gsap/i.test(src));\n // Detect GSAP bundled inline (no src attribute). Match:\n // - Producer's CDN-inlining comment: /* inlined: ...gsap... */\n // - GSAP library internals: _gsScope, GreenSock, gsap.config\n // - Large inline scripts (>5KB) that reference gsap (likely bundled library)\n const hasInlineGsap = allScriptTexts.some(\n (t) =>\n /\\/\\*\\s*inlined:.*gsap/i.test(t) ||\n /\\b_gsScope\\b/.test(t) ||\n /\\bGreenSock\\b/.test(t) ||\n /\\bgsap\\.(config|defaults|version)\\b/.test(t) ||\n (t.length > 5000 && /\\bgsap\\b/i.test(t)),\n );\n\n if (!usesGsap || hasGsapScript || hasInlineGsap || canInheritGsapFromHost) return [];\n return [\n {\n code: \"missing_gsap_script\",\n severity: \"error\",\n message: \"Composition uses GSAP but no GSAP script is loaded. The animation will not run.\",\n fixHint:\n 'Add <script src=\"https://cdn.jsdelivr.net/npm/gsap@3/dist/gsap.min.js\"></script> before your animation script.',\n },\n ];\n },\n\n // audio_reactive_single_tween_per_group\n // fallow-ignore-next-line complexity\n ({ scripts, styles }) => {\n const findings: HyperframeLintFinding[] = [];\n const isCaptionFile = styles.some((s) => /\\.caption[-_]?(?:group|word)/i.test(s.content));\n if (!isCaptionFile) return findings;\n\n for (const script of scripts) {\n const content = script.content;\n // Detect audio data loading\n const hasAudioData = /AUDIO|audio[-_]?data|bands\\[/.test(content);\n if (!hasAudioData) continue;\n\n // Detect caption group loop\n const hasCaptionLoop = /forEach/.test(content) && /caption|group|cg-/.test(content);\n if (!hasCaptionLoop) continue;\n\n // Check if audio-reactive tweens are created at intervals (loop inside the group loop)\n // vs a single tween per group (no inner time-sampling loop)\n const hasInnerSamplingLoop =\n /for\\s*\\(\\s*var\\s+\\w+\\s*=\\s*group\\.start/.test(content) ||\n /for\\s*\\(\\s*var\\s+at\\s*=/.test(content) ||\n /while\\s*\\(\\s*\\w+\\s*<\\s*group\\.end/.test(content);\n\n if (!hasInnerSamplingLoop) {\n // Check if there's at least a peak-based single tween (the minimal pattern)\n const hasPeakTween =\n /peak(?:Bass|Treble|Energy)/.test(content) && /group\\.start/.test(content);\n if (hasPeakTween) {\n findings.push({\n code: \"audio_reactive_single_tween_per_group\",\n severity: \"warning\",\n message:\n \"Audio-reactive captions use a single tween per group based on peak values. \" +\n \"This sets one static value at group.start — not perceptible as audio reactivity.\",\n fixHint:\n \"Sample audio data at 100-200ms intervals throughout each group's lifetime \" +\n \"(for loop from group.start to group.end) and create a tween at each sample \" +\n \"point for visible pulsing.\",\n });\n }\n }\n }\n return findings;\n },\n\n // gsap_infinite_repeat\n ({ scripts }) => {\n const findings: HyperframeLintFinding[] = [];\n for (const script of scripts) {\n const content = stripJsComments(script.content);\n // Match repeat: -1 in GSAP tweens or timeline configs\n const pattern = /repeat\\s*:\\s*-1(?!\\d)/g;\n let match: RegExpExecArray | null;\n while ((match = pattern.exec(content)) !== null) {\n const contextStart = Math.max(0, match.index - 60);\n const contextEnd = Math.min(content.length, match.index + match[0].length + 60);\n const snippet = content.slice(contextStart, contextEnd).trim();\n findings.push({\n code: \"gsap_infinite_repeat\",\n severity: \"error\",\n message:\n \"GSAP tween uses `repeat: -1` (infinite). Infinite repeats break the deterministic \" +\n \"capture engine which seeks to exact frame times. Use a finite repeat count calculated \" +\n \"from the composition duration: `repeat: Math.floor(duration / cycleDuration) - 1`.\",\n fixHint:\n \"Replace `repeat: -1` with a finite count, e.g. `repeat: Math.floor(totalDuration / singleCycleDuration) - 1`. \" +\n \"Use Math.floor (not Math.ceil) to ensure the animation fits within the total duration.\",\n snippet: truncateSnippet(snippet),\n });\n }\n }\n return findings;\n },\n\n // gsap_repeat_ceil_overshoot\n ({ scripts }) => {\n const findings: HyperframeLintFinding[] = [];\n for (const script of scripts) {\n const content = script.content;\n // Match patterns like: repeat: Math.ceil(duration / X) - 1\n // or repeat: Math.ceil(totalDuration / cycleDuration) - 1\n const pattern = /repeat\\s*:\\s*Math\\.ceil\\s*\\([^)]+\\)\\s*-\\s*1/g;\n let match: RegExpExecArray | null;\n while ((match = pattern.exec(content)) !== null) {\n const contextStart = Math.max(0, match.index - 40);\n const contextEnd = Math.min(content.length, match.index + match[0].length + 40);\n const snippet = content.slice(contextStart, contextEnd).trim();\n findings.push({\n code: \"gsap_repeat_ceil_overshoot\",\n severity: \"warning\",\n message:\n \"GSAP repeat calculation uses `Math.ceil` which can overshoot the composition duration. \" +\n \"For example, Math.ceil(10.5 / 2) - 1 = 5 repeats → 6 cycles × 2s = 12s, exceeding 10.5s.\",\n fixHint:\n \"Use `Math.floor` instead of `Math.ceil` to ensure the animation fits within the duration: \" +\n \"`repeat: Math.floor(totalDuration / cycleDuration) - 1`. \" +\n \"Math.floor(10.5 / 2) - 1 = 4 repeats → 5 cycles × 2s = 10s ✓\",\n snippet: truncateSnippet(snippet),\n });\n }\n }\n return findings;\n },\n\n // scene_layer_missing_visibility_kill\n ({ scripts, tags }) => {\n const findings: HyperframeLintFinding[] = [];\n\n // Detect multi-scene compositions: multiple elements with \"scene\" in their id\n const sceneElements = tags.filter((t) => {\n const id = readAttr(t.raw, \"id\") || \"\";\n return /^scene\\d+$/i.test(id);\n });\n if (sceneElements.length < 2) return findings;\n\n for (const script of scripts) {\n const content = stripJsComments(script.content);\n // For each scene, check if there's a visibility:hidden set after exit tweens\n for (const tag of sceneElements) {\n const id = readAttr(tag.raw, \"id\") || \"\";\n // Check if this scene has exit tweens (opacity: 0)\n const exitPattern = new RegExp(`[\"']#${id}[\"'][^)]*opacity\\\\s*:\\\\s*0`);\n const hasExit = exitPattern.test(content);\n if (!hasExit) continue;\n\n // Check if there's a hard visibility kill\n const killPattern = new RegExp(`[\"']#${id}[\"'][^)]*visibility\\\\s*:\\\\s*[\"']hidden[\"']`);\n const hasKill = killPattern.test(content);\n if (!hasKill) {\n findings.push({\n code: \"scene_layer_missing_visibility_kill\",\n severity: \"error\",\n elementId: id,\n message:\n `Scene layer \"#${id}\" exits via opacity tween but has no visibility: hidden hard kill. ` +\n \"When scrubbing or when tweens conflict, the scene may remain partially visible and overlap the next scene.\",\n fixHint: `Add \\`tl.set(\"#${id}\", { visibility: \"hidden\" }, <exit-end-time>)\\` after the scene's exit tweens.`,\n });\n }\n }\n }\n return findings;\n },\n\n // gsap_timeline_not_registered\n ({ scripts, rawSource, options }) => {\n const findings: HyperframeLintFinding[] = [];\n const canInheritFromHost =\n options.isSubComposition || rawSource.trimStart().toLowerCase().startsWith(\"<template\");\n\n for (const script of scripts) {\n const content = script.content;\n if (!/gsap\\.timeline/.test(content)) continue;\n const hasRegistration = WINDOW_TIMELINE_ASSIGN_PATTERN.test(content);\n if (hasRegistration || canInheritFromHost) continue;\n findings.push({\n code: \"gsap_timeline_not_registered\",\n severity: \"error\",\n message:\n \"GSAP timeline is created but never registered in window.__timelines. \" +\n \"The runtime discovers timelines from this registry — without registration, \" +\n \"animations will not play during preview or render.\",\n fixHint:\n \"Add `window.__timelines = window.__timelines || {};` and \" +\n '`window.__timelines[\"root\"] = tl;` after creating the timeline (use the ' +\n \"composition's data-composition-id as the key).\",\n });\n }\n return findings;\n },\n\n // gsap_timeline_registered_before_async_build — registering window.__timelines[id]\n // BEFORE the timeline is built inside document.fonts.ready (or any async callback)\n // leaves an EMPTY timeline registered. The runtime's sub-composition readiness gate\n // treats \"key present\" as \"ready\" and nests the child ONCE, while still empty — so the\n // animation never renders when this composition is mounted as a sub-composition.\n // Register only AFTER the build completes (the documented async-setup contract).\n ({ scripts }) => {\n const findings: HyperframeLintFinding[] = [];\n for (const script of scripts) {\n const content = stripJsComments(script.content);\n const regIdx = content.search(/window\\s*\\.\\s*__timelines\\s*\\[/);\n if (regIdx < 0) continue;\n const fontsReadyIdx = content.search(/document\\s*\\.\\s*fonts\\s*\\.\\s*ready/);\n if (fontsReadyIdx < 0) continue;\n // Registering after the async boundary is the correct pattern — skip it.\n if (regIdx >= fontsReadyIdx) continue;\n // Confirm the build is actually deferred past the boundary (a tween/build call\n // appears after document.fonts.ready), i.e. the registered timeline starts empty.\n const tail = content.slice(fontsReadyIdx);\n if (!/\\.(?:to|from|fromTo)\\s*\\(|buildEffect\\s*\\(/.test(tail)) continue;\n findings.push({\n code: \"gsap_timeline_registered_before_async_build\",\n severity: \"error\",\n message:\n \"window.__timelines is assigned BEFORE the timeline is built inside \" +\n \"document.fonts.ready. An empty timeline registered early gets nested empty \" +\n \"when this composition is used as a sub-composition (the readiness gate treats \" +\n '\"key present\" as \"ready\" and never re-nests), so the animation renders blank.',\n fixHint:\n \"Move the `window.__timelines[id] = tl;` assignment to the END of the \" +\n \"document.fonts.ready callback, after the tweens are added. Optionally call \" +\n \"window.__hfForceTimelineRebind() right after, to re-nest the populated timeline.\",\n });\n }\n return findings;\n },\n\n // gsap_from_opacity_noop — CSS opacity:0 + gsap.from({opacity:0}) = invisible forever\n // fallow-ignore-next-line complexity\n async ({ styles, scripts, tags }) => {\n const findings: HyperframeLintFinding[] = [];\n const cssOpacityZeroSelectors = new Set<string>();\n\n for (const style of styles) {\n for (const [, selector, body] of style.content.matchAll(\n /([#.][a-zA-Z0-9_-]+)\\s*\\{([^}]+)\\}/g,\n )) {\n if (body && /opacity\\s*:\\s*0\\s*[;}]/.test(body)) {\n cssOpacityZeroSelectors.add((selector ?? \"\").trim());\n }\n }\n }\n\n for (const tag of tags) {\n const inlineStyle = readAttr(tag.raw, \"style\");\n if (!inlineStyle || !/opacity\\s*:\\s*0/.test(inlineStyle)) continue;\n const id = readAttr(tag.raw, \"id\");\n const classes = readAttr(tag.raw, \"class\")?.split(/\\s+/).filter(Boolean) ?? [];\n if (id) cssOpacityZeroSelectors.add(`#${id}`);\n for (const cls of classes) cssOpacityZeroSelectors.add(`.${cls}`);\n }\n\n if (cssOpacityZeroSelectors.size === 0) return findings;\n\n for (const script of scripts) {\n if (!/gsap\\.timeline/.test(script.content)) continue;\n const windows = await cachedExtractGsapWindows(script.content);\n\n for (const win of windows) {\n if (win.method !== \"from\") continue;\n if (!win.properties.includes(\"opacity\")) continue;\n // Only a noop when the tween animates FROM 0 (same as the CSS value)\n if (win.propertyValues[\"opacity\"] !== 0) continue;\n const sel = win.targetSelector;\n const cssKey = sel.startsWith(\"#\") || sel.startsWith(\".\") ? sel : `#${sel}`;\n if (!cssOpacityZeroSelectors.has(cssKey)) continue;\n\n findings.push({\n code: \"gsap_from_opacity_noop\",\n severity: \"error\",\n message:\n `\"${sel}\" has CSS \\`opacity: 0\\` and a gsap.${win.method}() that also sets opacity to 0. ` +\n `gsap.from() animates FROM the specified value TO the current CSS value — ` +\n `since CSS is already 0, the element animates from 0→0 and never becomes visible.`,\n selector: sel,\n fixHint:\n `Remove \\`opacity: 0\\` from the CSS/inline style on \"${sel}\". ` +\n `Let gsap.from({opacity: 0}) handle the initial hidden state — ` +\n `it will animate FROM 0 TO the CSS value (1 by default).`,\n snippet: truncateSnippet(win.raw),\n });\n }\n }\n return findings;\n },\n\n // gsap_group_selector_keyframes\n ({ scripts }) => {\n const findings: HyperframeLintFinding[] = [];\n for (const script of scripts) {\n const content = stripJsComments(script.content);\n const pattern = /\\.(?:to|from|fromTo)\\(\\s*[\"']([^\"']+,\\s*[^\"']+)[\"']\\s*,\\s*\\{[^}]*keyframes/g;\n let match: RegExpExecArray | null;\n while ((match = pattern.exec(content)) !== null) {\n const selector = match[1]!;\n const count = selector.split(\",\").length;\n const contextStart = Math.max(0, match.index - 20);\n const contextEnd = Math.min(content.length, match.index + match[0].length + 40);\n findings.push({\n code: \"gsap_group_selector_keyframes\",\n severity: \"warning\",\n message:\n `GSAP tween targets ${count} elements with shared keyframes (\"${truncateSnippet(selector, 60)}\"). ` +\n `Editing one element's keyframes in Studio will affect all ${count} elements. ` +\n `Split into individual tweens for per-element keyframe control.`,\n fixHint:\n `Replace the group selector with individual tl.to() calls per element, ` +\n `each with their own keyframes object.`,\n snippet: truncateSnippet(content.slice(contextStart, contextEnd)),\n });\n }\n }\n return findings;\n },\n];\n","import type { LintContext, HyperframeLintFinding } from \"../context\";\n\n/** Extract a bracket-balanced array literal starting at the `[` found by `varMatch`. */\n// fallow-ignore-next-line complexity\nfunction extractArrayLiteral(src: string, varMatch: RegExpExecArray): string | null {\n const openIdx = varMatch.index + varMatch[0].length - 1;\n let depth = 0;\n let inStr = false;\n let strChar = \"\";\n for (let i = openIdx; i < src.length; i++) {\n const c = src[i]!;\n if (inStr) {\n if (c === \"\\\\\") {\n i++;\n continue;\n }\n if (c === strChar) inStr = false;\n } else if (c === '\"' || c === \"'\") {\n inStr = true;\n strChar = c;\n } else if (c === \"[\") {\n depth++;\n } else if (c === \"]\") {\n depth--;\n if (depth === 0) return src.slice(openIdx, i + 1);\n }\n }\n return null;\n}\n\nexport const captionRules: Array<(ctx: LintContext) => HyperframeLintFinding[]> = [\n // caption_exit_missing_hard_kill\n ({ scripts, styles, options, rootCompositionId }) => {\n const findings: HyperframeLintFinding[] = [];\n // Only the ACTUAL captions composition. A content frame that merely mentions\n // \"karaoke\" / \"caption-*\" in a comment (or uses an unrelated forEach + opacity:0\n // screen-swap) is NOT captions — gating here prevents the false positive that fired\n // on a content frame whose only caption signal was a descriptive comment.\n const isCaptionComposition =\n Boolean(options.filePath && /caption/i.test(options.filePath)) ||\n rootCompositionId === \"captions\" ||\n styles.some((s) => /\\.caption[-_]?(?:group|word|line|block)\\b|\\.cg-/.test(s.content));\n if (!isCaptionComposition) return findings;\n for (const script of scripts) {\n const content = script.content;\n const hasExitTween = /\\.to\\s*\\([^,]+,\\s*\\{[^}]*opacity\\s*:\\s*0/.test(content);\n const hasHardKill =\n /\\.set\\s*\\([^,]+,\\s*\\{[^}]*(?:visibility\\s*:\\s*[\"']hidden[\"']|opacity\\s*:\\s*0)/.test(\n content,\n );\n const hasCaptionLoop =\n /forEach|\\.forEach\\s*\\(/.test(content) &&\n /karaoke|caption[-_]?(?:group|word|line|block)|cg-/.test(content);\n if (hasCaptionLoop && hasExitTween && !hasHardKill) {\n findings.push({\n code: \"caption_exit_missing_hard_kill\",\n severity: \"error\",\n message:\n \"Caption exit animations (tl.to with opacity: 0) detected without a hard tl.set kill. \" +\n \"Exit tweens can fail when karaoke word-level tweens conflict, leaving captions stuck on screen.\",\n fixHint:\n 'Add `tl.set(groupEl, { opacity: 0, visibility: \"hidden\" }, group.end)` after every ' +\n \"exit tl.to animation as a deterministic kill.\",\n });\n }\n }\n return findings;\n },\n\n // caption_text_overflow_risk\n ({ styles }) => {\n const findings: HyperframeLintFinding[] = [];\n for (const style of styles) {\n const captionBlocks = style.content.matchAll(\n /(\\.caption[-_]?(?:group|container|text|line|word)|#caption[-_]?container)\\s*\\{([^}]+)\\}/gi,\n );\n for (const [, selector, body] of captionBlocks) {\n if (!body) continue;\n const hasNowrap = /white-space\\s*:\\s*nowrap/i.test(body);\n const hasMaxWidth = /max-width/i.test(body);\n if (hasNowrap && !hasMaxWidth) {\n findings.push({\n code: \"caption_text_overflow_risk\",\n severity: \"warning\",\n selector: (selector ?? \"\").trim(),\n message: `Caption selector \"${(selector ?? \"\").trim()}\" has white-space: nowrap but no max-width. Long phrases will clip off-screen.`,\n fixHint:\n \"Add max-width: 1600px (landscape) or max-width: 900px (portrait) and overflow: hidden.\",\n });\n }\n }\n }\n return findings;\n },\n\n // caption_transcript_not_inline\n // fallow-ignore-next-line complexity\n ({ scripts, styles, options }) => {\n const findings: HyperframeLintFinding[] = [];\n // Only check files that look like caption compositions\n const isCaptionFile =\n (options.filePath && /caption/i.test(options.filePath)) ||\n styles.some((s) => /\\.caption[-_]?(?:group|word)/i.test(s.content));\n if (!isCaptionFile) return findings;\n\n const allScript = scripts.map((s) => s.content).join(\"\\n\");\n const hasInlineTranscript = /(?:const|let|var)\\s+(?:TRANSCRIPT|script)\\s*=\\s*\\[/.test(\n allScript,\n );\n const hasFetchTranscript = /fetch\\s*\\(\\s*[\"'][^\"']*transcript/i.test(allScript);\n\n if (!hasInlineTranscript && hasFetchTranscript) {\n findings.push({\n code: \"caption_transcript_not_inline\",\n severity: \"error\",\n message:\n \"Captions composition loads transcript via fetch(). The studio caption editor \" +\n \"requires an inline `var TRANSCRIPT = [...]` array to detect and edit captions.\",\n fixHint:\n 'Embed the transcript as `var TRANSCRIPT = [{ \"text\": \"...\", \"start\": 0, \"end\": 1 }, ...]` ' +\n \"with JSON-quoted property keys. See the captions skill for details.\",\n });\n }\n\n if (hasInlineTranscript) {\n // Verify the inline transcript can be parsed.\n // Use a balanced-bracket scan instead of a regex to correctly handle\n // nested arrays (e.g. word-level timing arrays inside each entry).\n const varStart = /(?:const|let|var)\\s+(?:TRANSCRIPT|script)\\s*=\\s*\\[/.exec(allScript);\n const transcriptJson = varStart ? extractArrayLiteral(allScript, varStart) : null;\n if (transcriptJson) {\n try {\n JSON.parse(transcriptJson);\n } catch {\n findings.push({\n code: \"caption_transcript_parse_error\",\n severity: \"error\",\n message:\n \"Inline TRANSCRIPT array is not valid JSON. The studio caption editor may fail \" +\n \"to parse it. Common cause: unquoted property keys with apostrophes in text.\",\n fixHint:\n 'Use JSON-quoted keys: { \"text\": \"don\\'t\", \"start\": 0, \"end\": 1 } instead of ' +\n '{ text: \"don\\'t\", start: 0, end: 1 }.',\n });\n }\n }\n }\n\n return findings;\n },\n\n // caption_container_relative_position\n ({ styles }) => {\n const findings: HyperframeLintFinding[] = [];\n for (const style of styles) {\n const captionBlocks = style.content.matchAll(\n /(\\.caption[-_]?(?:group|container|text|line)|#caption[-_]?container)\\s*\\{([^}]+)\\}/gi,\n );\n for (const [, selector, body] of captionBlocks) {\n if (!body) continue;\n if (/position\\s*:\\s*relative/i.test(body)) {\n findings.push({\n code: \"caption_container_relative_position\",\n severity: \"error\",\n selector: (selector ?? \"\").trim(),\n message: `Caption selector \"${(selector ?? \"\").trim()}\" uses position: relative which causes overflow and breaks caption stacking.`,\n fixHint: \"Use position: absolute for all caption elements.\",\n });\n }\n }\n }\n return findings;\n },\n\n // caption_overflow_clips_scaled_words\n ({ styles, scripts }) => {\n const findings: HyperframeLintFinding[] = [];\n const hasScaledWords = scripts.some(\n (s) => /scale\\s*:\\s*1\\.[2-9]/.test(s.content) && /caption|word|cg-/.test(s.content),\n );\n if (!hasScaledWords) return findings;\n\n for (const style of styles) {\n const captionBlocks = style.content.matchAll(\n /(\\.caption[-_]?(?:group|container)|#caption[-_]?(?:layer|container))\\s*\\{([^}]+)\\}/gi,\n );\n for (const [, selector, body] of captionBlocks) {\n if (!body) continue;\n if (/overflow\\s*:\\s*hidden/i.test(body)) {\n findings.push({\n code: \"caption_overflow_clips_scaled_words\",\n severity: \"error\",\n selector: (selector ?? \"\").trim(),\n message: `\"${(selector ?? \"\").trim()}\" has overflow: hidden but GSAP scales caption words above 1.0x. Scaled emphasis words and their glow effects will be clipped.`,\n fixHint:\n \"Use overflow: visible on caption containers. Rely on fitTextFontSize with reduced maxWidth to prevent overflow instead.\",\n });\n }\n }\n }\n return findings;\n },\n\n // caption_textshadow_on_group_container\n ({ scripts, styles }) => {\n const findings: HyperframeLintFinding[] = [];\n const isCaptionFile = styles.some((s) => /\\.caption[-_]?(?:group|word)/i.test(s.content));\n if (!isCaptionFile) return findings;\n\n for (const script of scripts) {\n // Detect textShadow tweened on a group container (div with child word spans)\n const groupShadowPattern =\n /\\.to\\s*\\(\\s*(?:div|groupEl|el|captionEl|document\\.getElementById\\s*\\(\\s*[\"']cg-)\\s*[^,]*,\\s*\\{[^}]*textShadow/g;\n // Also catch selector-based targeting of group containers\n const selectorShadowPattern =\n /\\.to\\s*\\(\\s*[\"'](?:#cg-\\d+|\\.caption[-_]?group)[\"']\\s*,\\s*\\{[^}]*textShadow/g;\n if (groupShadowPattern.test(script.content) || selectorShadowPattern.test(script.content)) {\n findings.push({\n code: \"caption_textshadow_on_group_container\",\n severity: \"warning\",\n message:\n \"textShadow is tweened on a caption group container. When children have semi-transparent \" +\n \"color (e.g., inactive karaoke words at rgba opacity), the glow renders as a visible \" +\n \"rectangle behind the entire group.\",\n fixHint:\n \"Apply textShadow to individual active word elements instead of the group container. \" +\n \"Use scale on the group for bass-reactive pulsing.\",\n });\n }\n }\n return findings;\n },\n\n // caption_fittext_scale_mismatch\n // fallow-ignore-next-line complexity\n ({ scripts }) => {\n const findings: HyperframeLintFinding[] = [];\n for (const script of scripts) {\n const content = script.content;\n const fitTextMatch = content.match(/fitTextFontSize\\s*\\([^)]*maxWidth\\s*:\\s*(\\d+)/);\n if (!fitTextMatch) continue;\n const maxWidth = parseInt(fitTextMatch[1] ?? \"0\", 10);\n if (!maxWidth) continue;\n\n // Find max scale on caption words\n const scaleMatches = [...content.matchAll(/scale\\s*:\\s*(1\\.\\d+)/g)];\n const captionContext = /caption|word|cg-|karaoke/i.test(content);\n if (!captionContext || scaleMatches.length === 0) continue;\n\n let maxScale = 1;\n for (const m of scaleMatches) {\n const val = parseFloat(m[1] ?? \"1\");\n if (val > maxScale) maxScale = val;\n }\n\n // Check if maxWidth * maxScale exceeds safe bounds (1920 - reasonable margins)\n const effectiveWidth = maxWidth * maxScale;\n if (effectiveWidth > 1760) {\n findings.push({\n code: \"caption_fittext_scale_mismatch\",\n severity: \"warning\",\n message:\n `fitTextFontSize uses maxWidth: ${maxWidth}px but emphasis words scale up to ${maxScale}x. ` +\n `Effective width ${Math.round(effectiveWidth)}px may overflow the composition (1920px minus margins).`,\n fixHint: `Reduce maxWidth to ${Math.floor(1700 / maxScale)}px to leave headroom for scaled emphasis words.`,\n });\n }\n }\n return findings;\n },\n];\n","import type { LintContext, HyperframeLintFinding, ExtractedBlock } from \"../context\";\nimport { findHtmlTag, readAttr, readJsonAttr, stripJsComments, truncateSnippet } from \"../utils\";\nimport { COMPOSITION_VARIABLE_TYPES } from \"@hyperframes/parsers\";\n\n// Agent guidance thresholds: warning-only nudges for files/tracks that become hard\n// to inspect and revise reliably in a single composition.\nconst MAX_COMPOSITION_LINES = 300;\nconst MAX_TIMED_ELEMENTS_PER_TRACK = 3;\nconst TRACK_DENSITY_EXEMPT_TAGS = new Set([\"audio\", \"script\", \"style\", \"video\"]);\n\nfunction countPhysicalLines(source: string): number {\n if (source.length === 0) return 0;\n\n const normalized = source.replace(/\\r\\n/g, \"\\n\").replace(/\\r/g, \"\\n\");\n const withoutFinalNewline = normalized.endsWith(\"\\n\") ? normalized.slice(0, -1) : normalized;\n return withoutFinalNewline.split(\"\\n\").length;\n}\n\nfunction countStructuralLines(source: string): number {\n return countPhysicalLines(source.replace(/<style\\b[^>]*>[\\s\\S]*?<\\/style>/gi, \"<style></style>\"));\n}\n\nexport function isRegistrySourceFile(filePath?: string): boolean {\n if (!filePath) return false;\n\n const normalized = filePath.replace(/\\\\/g, \"/\");\n return /(?:^|\\/)registry\\/blocks\\/([^/]+)\\/\\1\\.html$/i.test(normalized);\n}\n\nexport function isRegistryInstalledFile(rawSource: string): boolean {\n return /^\\s*<!--\\s*hyperframes-registry-item:[^>]*-->/i.test(rawSource.slice(0, 512));\n}\n\nfunction isCompositionRootOrMount(rawTag: string): boolean {\n return Boolean(\n readAttr(rawTag, \"data-composition-id\") || readAttr(rawTag, \"data-composition-src\"),\n );\n}\n\n// Asset references inside CSS `url(...)`/`url(\"...\")`/`url('...')` functions.\n// Returns the inner path without quotes; comments are stripped first so\n// `/* url(foo) */` is ignored. Bare `url()` and `data:` are excluded by the\n// rules that consume this — the helper just yields raw URL values.\nfunction extractCssUrlReferences(css: string): string[] {\n const out: string[] = [];\n const noComments = css.replace(/\\/\\*[\\s\\S]*?\\*\\//g, \"\");\n const urlPattern = /\\burl\\(\\s*([\"']?)([^)\"']+)\\1\\s*\\)/g;\n let m: RegExpExecArray | null;\n while ((m = urlPattern.exec(noComments)) !== null) {\n const raw = (m[2] ?? \"\").trim();\n if (raw) out.push(raw);\n }\n return out;\n}\n\n// Top-level CSS selectors (comma-split) in a stylesheet, skipping at-rule headers\n// (@media/@keyframes/...) and keyframe stops. Heuristic — the lint layer has no\n// full CSS parser, and rules elsewhere in this file scan CSS the same way.\nfunction extractCssSelectors(css: string): string[] {\n const out: string[] = [];\n const noComments = css.replace(/\\/\\*[\\s\\S]*?\\*\\//g, \"\");\n const ruleHeader = /([^{}]+)\\{/g;\n let m: RegExpExecArray | null;\n while ((m = ruleHeader.exec(noComments)) !== null) {\n const header = (m[1] ?? \"\").trim();\n if (!header || header.startsWith(\"@\")) continue;\n for (const sel of header.split(\",\")) {\n const s = sel.trim();\n if (s) out.push(s);\n }\n }\n return out;\n}\n\n// Class tokens in a selector's leftmost compound (before the first descendant /\n// child / sibling combinator). `.frame .title` → [\"frame\"]; `.a.b > .c` → [\"a\",\"b\"].\nfunction leftmostCompoundClasses(selector: string): string[] {\n const leftmost = selector.trim().split(/[\\s>+~]+/)[0] ?? \"\";\n return (leftmost.match(/\\.([\\w-]+)/g) ?? []).map((c) => c.slice(1));\n}\n\n// Distinct selectors across all <style> blocks whose leftmost compound keys off one\n// of the root element's own classes — the ones that break under id-scoping.\nfunction rootClassStyledSelectors(styles: ExtractedBlock[], rootClasses: string[]): string[] {\n const offenders: string[] = [];\n for (const style of styles) {\n for (const selector of extractCssSelectors(style.content)) {\n const hitsRoot = leftmostCompoundClasses(selector).some((c) => rootClasses.includes(c));\n if (hitsRoot && !offenders.includes(selector)) offenders.push(selector);\n }\n }\n return offenders;\n}\n\nexport const compositionRules: Array<(ctx: LintContext) => HyperframeLintFinding[]> = [\n // invalid_parent_traversal_in_asset_path — catches `../` traversal in src,\n // href, inline-style url(), and <style> url() asset references on\n // compositions. Sub-compositions live under compositions/ but are served\n // with the project root as their base URL, so any `../`-traversing path\n // climbs above the project root and 404s in Studio preview. Renders\n // tolerate it because the server-side bundler rewrites `../foo` against\n // each sub-composition's source path; the runtime now mirrors that fallback\n // (see rewriteSubCompositionAssetPaths in runtime/compositionLoader.ts), but\n // the authoring-time signal is still wrong — flag it at lint time so the\n // baked path is plain root-relative and matches what the bundler emits.\n //\n // Mirrors the runtime fallback's surface: `[src]` / `[href]` attribute\n // values, `[style]` inline url(), and `<style>` block url() references.\n // Skips absolute URLs (http(s)://, //, data:, /-prefixed root-relative),\n // hash anchors, and plain relative paths (`assets/x.mp4`) — only `../`\n // traversal is flagged. Subsumes the older `../capture/`-specific rule.\n // fallow-ignore-next-line complexity\n ({ tags, styles, rawSource, options }) => {\n if (isRegistrySourceFile(options.filePath) || isRegistryInstalledFile(rawSource)) return [];\n\n const offenders: string[] = [];\n const collect = (value: string | null) => {\n if (!value) return;\n const trimmed = value.trim();\n if (!trimmed.startsWith(\"../\") && trimmed !== \"..\") return;\n offenders.push(trimmed);\n };\n\n for (const tag of tags) {\n collect(readAttr(tag.raw, \"src\"));\n collect(readAttr(tag.raw, \"href\"));\n // Use readJsonAttr for `style` — inline url('...') values contain the\n // opposite quote, which readAttr's [^\"']+ class would truncate.\n const styleAttr = readJsonAttr(tag.raw, \"style\");\n if (styleAttr) {\n for (const url of extractCssUrlReferences(styleAttr)) collect(url);\n }\n }\n for (const style of styles) {\n for (const url of extractCssUrlReferences(style.content)) collect(url);\n }\n\n if (offenders.length === 0) return [];\n\n // Group counts by leading path token (e.g. ../capture/, ../assets/, ../../assets/)\n // so the message names the offending prefixes instead of a bare count.\n const prefixCounts = new Map<string, number>();\n for (const path of offenders) {\n const prefix = path.match(/^(?:\\.\\.\\/)+[^/]+\\//)?.[0] ?? path;\n prefixCounts.set(prefix, (prefixCounts.get(prefix) ?? 0) + 1);\n }\n const prefixSummary = Array.from(prefixCounts.entries())\n .sort(([, a], [, b]) => b - a)\n .map(([prefix, count]) => (count > 1 ? `${prefix} (${count})` : prefix))\n .join(\", \");\n\n return [\n {\n code: \"invalid_parent_traversal_in_asset_path\",\n severity: \"error\",\n message:\n `Found ${offenders.length} asset path(s) traversing above the project root with \"../\" ` +\n `(${prefixSummary}). Renders rewrite this against each sub-composition's source path, but Studio preview and other live consumers resolve against the project root and 404.`,\n fixHint:\n 'Use plain root-relative paths (e.g. \"assets/...\", \"capture/...\", \"fonts/...\") — compositions are served with the project root as their base URL, so paths must be root-relative, not relative to the compositions/ directory.',\n },\n ];\n },\n\n // composition_file_too_large\n ({ rawSource, options }) => {\n if (isRegistrySourceFile(options.filePath) || isRegistryInstalledFile(rawSource)) return [];\n\n const lineCount = countStructuralLines(rawSource);\n if (lineCount <= MAX_COMPOSITION_LINES) return [];\n\n const splitTarget = options.isSubComposition\n ? \"Split this sub-composition further into smaller .html files\"\n : \"Split coherent scenes or layers into separate .html files under compositions/\";\n\n return [\n {\n code: \"composition_file_too_large\",\n severity: \"warning\",\n message: `This HTML composition file has ${lineCount} lines. Smaller sub-compositions are easier to read, iterate on, and diff.`,\n fixHint: `${splitTarget}, then mount them from the parent with data-composition-src so each file stays small enough to inspect, revise, and validate independently.`,\n },\n ];\n },\n\n // timeline_track_too_dense\n // fallow-ignore-next-line complexity\n ({ tags, options }) => {\n const trackCounts = new Map<string, number>();\n for (const tag of tags) {\n if (TRACK_DENSITY_EXEMPT_TAGS.has(tag.name)) continue;\n if (isCompositionRootOrMount(tag.raw)) continue;\n if (!readAttr(tag.raw, \"data-start\")) continue;\n\n const track = readAttr(tag.raw, \"data-track-index\");\n if (!track) continue;\n trackCounts.set(track, (trackCounts.get(track) ?? 0) + 1);\n }\n\n const findings: HyperframeLintFinding[] = [];\n for (const [track, count] of trackCounts) {\n if (count <= MAX_TIMED_ELEMENTS_PER_TRACK) continue;\n const splitTarget = options.isSubComposition\n ? \"Move coherent scene groups into smaller .html files\"\n : \"Move coherent scene groups into separate .html files under compositions/\";\n findings.push({\n code: \"timeline_track_too_dense\",\n severity: \"warning\",\n message: `Track ${track} has ${count} timed elements in this HTML file. Smaller sub-compositions keep timelines easier to read, iterate on, and diff.`,\n fixHint: `${splitTarget} and mount them from the parent with data-composition-src so the timeline stays easier to inspect, revise, and validate.`,\n });\n }\n\n return findings;\n },\n\n // timed_element_missing_visibility_hidden\n // fallow-ignore-next-line complexity\n ({ tags }) => {\n const findings: HyperframeLintFinding[] = [];\n for (const tag of tags) {\n if (tag.name === \"audio\" || tag.name === \"script\" || tag.name === \"style\") continue;\n if (!readAttr(tag.raw, \"data-start\")) continue;\n if (readAttr(tag.raw, \"data-composition-id\")) continue;\n if (readAttr(tag.raw, \"data-composition-src\")) continue;\n const classAttr = readAttr(tag.raw, \"class\") || \"\";\n const styleAttr = readAttr(tag.raw, \"style\") || \"\";\n const hasClip = classAttr.split(/\\s+/).includes(\"clip\");\n const hasHiddenStyle =\n /visibility\\s*:\\s*hidden/i.test(styleAttr) || /opacity\\s*:\\s*0/i.test(styleAttr);\n if (!hasClip && !hasHiddenStyle) {\n const elementId = readAttr(tag.raw, \"id\") || undefined;\n findings.push({\n code: \"timed_element_missing_visibility_hidden\",\n severity: \"info\",\n message: `<${tag.name}${elementId ? ` id=\"${elementId}\"` : \"\"}> has data-start but no class=\"clip\", visibility:hidden, or opacity:0. Consider adding initial hidden state if the element should not be visible before its start time.`,\n elementId,\n fixHint:\n 'Add class=\"clip\" (with CSS: .clip { visibility: hidden; }) or style=\"opacity:0\" if the element should start hidden.',\n snippet: truncateSnippet(tag.raw),\n });\n }\n }\n return findings;\n },\n\n // deprecated_data_layer + deprecated_data_end\n // fallow-ignore-next-line complexity\n ({ tags }) => {\n const findings: HyperframeLintFinding[] = [];\n for (const tag of tags) {\n if (readAttr(tag.raw, \"data-layer\") && !readAttr(tag.raw, \"data-track-index\")) {\n const elementId = readAttr(tag.raw, \"id\") || undefined;\n findings.push({\n code: \"deprecated_data_layer\",\n severity: \"error\",\n message: `<${tag.name}${elementId ? ` id=\"${elementId}\"` : \"\"}> uses data-layer instead of data-track-index.`,\n elementId,\n fixHint: \"Replace data-layer with data-track-index. The runtime reads data-track-index.\",\n snippet: truncateSnippet(tag.raw),\n });\n }\n if (readAttr(tag.raw, \"data-end\") && !readAttr(tag.raw, \"data-duration\")) {\n const elementId = readAttr(tag.raw, \"id\") || undefined;\n findings.push({\n code: \"deprecated_data_end\",\n severity: \"error\",\n message: `<${tag.name}${elementId ? ` id=\"${elementId}\"` : \"\"}> uses data-end without data-duration. Use data-duration in source HTML.`,\n elementId,\n fixHint:\n \"Replace data-end with data-duration. The compiler generates data-end from data-duration automatically.\",\n snippet: truncateSnippet(tag.raw),\n });\n }\n }\n return findings;\n },\n\n // split_data_attribute_selector\n ({ scripts, styles }) => {\n const findings: HyperframeLintFinding[] = [];\n const splitDataAttrSelectorPattern =\n /\\[data-composition-id=([\"'])([^\"'\\]]+)\\1\\s+(data-[\\w:-]+)=([\"'])([^\"'\\]]*)\\4\\]/g;\n const scan = (content: string) => {\n splitDataAttrSelectorPattern.lastIndex = 0;\n let match: RegExpExecArray | null;\n while ((match = splitDataAttrSelectorPattern.exec(content)) !== null) {\n const compId = match[2] ?? \"\";\n const attrName = match[3] ?? \"\";\n const attrValue = match[5] ?? \"\";\n findings.push({\n code: \"split_data_attribute_selector\",\n severity: \"error\",\n message:\n `Selector \"${match[0]}\" combines two attributes inside one CSS attribute selector. ` +\n \"Browsers reject it, so GSAP timelines or querySelector calls will fail before registering.\",\n selector: match[0],\n fixHint: `Use separate attribute selectors: [data-composition-id=\"${compId}\"][${attrName}=\"${attrValue}\"].`,\n snippet: truncateSnippet(match[0]),\n });\n }\n };\n for (const style of styles) scan(style.content);\n for (const script of scripts) scan(script.content);\n return findings;\n },\n\n // template_literal_selector\n ({ scripts }) => {\n const findings: HyperframeLintFinding[] = [];\n for (const script of scripts) {\n const templateLiteralSelectorPattern =\n /(?:querySelector|querySelectorAll)\\s*\\(\\s*`[^`]*\\$\\{[^}]+\\}[^`]*`\\s*\\)/g;\n let tlMatch: RegExpExecArray | null;\n while ((tlMatch = templateLiteralSelectorPattern.exec(script.content)) !== null) {\n findings.push({\n code: \"template_literal_selector\",\n severity: \"error\",\n message:\n \"querySelector uses a template literal variable (e.g. `${compId}`). \" +\n \"The HTML bundler's CSS parser crashes on these. Use a hardcoded string instead.\",\n fixHint:\n \"Replace the template literal variable with a hardcoded string. The bundler's CSS parser cannot handle interpolated variables in script content.\",\n snippet: truncateSnippet(tlMatch[0]),\n });\n }\n }\n return findings;\n },\n\n // timed_element_missing_clip_class\n // fallow-ignore-next-line complexity\n ({ tags }) => {\n const findings: HyperframeLintFinding[] = [];\n const skipTags = new Set([\"audio\", \"video\", \"script\", \"style\", \"template\"]);\n for (const tag of tags) {\n if (skipTags.has(tag.name)) continue;\n // Skip composition hosts\n if (readAttr(tag.raw, \"data-composition-id\")) continue;\n if (readAttr(tag.raw, \"data-composition-src\")) continue;\n\n const hasStart = readAttr(tag.raw, \"data-start\") !== null;\n const hasDuration = readAttr(tag.raw, \"data-duration\") !== null;\n // data-track-index alone marks a layer container, not a time-bounded clip\n if (!hasStart && !hasDuration) continue;\n\n const classAttr = readAttr(tag.raw, \"class\") || \"\";\n const hasClip = classAttr.split(/\\s+/).includes(\"clip\");\n if (hasClip) continue;\n\n const elementId = readAttr(tag.raw, \"id\") || undefined;\n findings.push({\n code: \"timed_element_missing_clip_class\",\n severity: \"error\",\n message: `<${tag.name}${elementId ? ` id=\"${elementId}\"` : \"\"}> has timing attributes but no class=\"clip\". The element will be visible for the entire composition instead of only during its scheduled time range.`,\n elementId,\n fixHint:\n 'Add class=\"clip\" to the element. The HyperFrames runtime uses .clip to control visibility based on data-start/data-duration.',\n snippet: truncateSnippet(tag.raw),\n });\n }\n return findings;\n },\n\n // overlapping_clips_same_track\n // fallow-ignore-next-line complexity\n ({ tags }) => {\n const findings: HyperframeLintFinding[] = [];\n\n type ClipInfo = { start: number; end: number; elementId?: string; snippet: string };\n const trackMap = new Map<string, ClipInfo[]>();\n\n for (const tag of tags) {\n const startStr = readAttr(tag.raw, \"data-start\");\n const durationStr = readAttr(tag.raw, \"data-duration\");\n const trackStr = readAttr(tag.raw, \"data-track-index\");\n if (!startStr || !durationStr || !trackStr) continue;\n\n const start = Number(startStr);\n const duration = Number(durationStr);\n const track = trackStr;\n\n // Skip non-numeric (relative timing references like \"intro-comp\")\n if (Number.isNaN(start) || Number.isNaN(duration)) continue;\n\n const clips = trackMap.get(track) || [];\n clips.push({\n start,\n end: start + duration,\n elementId: readAttr(tag.raw, \"id\") || undefined,\n snippet: truncateSnippet(tag.raw) || \"\",\n });\n trackMap.set(track, clips);\n }\n\n for (const [track, clips] of trackMap) {\n clips.sort((a, b) => a.start - b.start);\n for (let i = 0; i < clips.length - 1; i++) {\n const current = clips[i];\n const next = clips[i + 1];\n if (!current || !next) continue;\n if (current.end > next.start) {\n findings.push({\n code: \"overlapping_clips_same_track\",\n severity: \"error\",\n message: `Track ${track}: clip ending at ${current.end}s overlaps with clip starting at ${next.start}s. Overlapping clips on the same track cause rendering conflicts.`,\n fixHint:\n \"Adjust data-start or data-duration so clips on the same track do not overlap, or move one clip to a different data-track-index.\",\n });\n }\n }\n }\n\n return findings;\n },\n\n // root_composition_missing_data_start\n ({ rootTag, options }) => {\n const findings: HyperframeLintFinding[] = [];\n if (options.isSubComposition) return findings;\n if (!rootTag) return findings;\n const compId = readAttr(rootTag.raw, \"data-composition-id\");\n if (!compId) return findings;\n const hasStart = readAttr(rootTag.raw, \"data-start\") !== null;\n if (!hasStart) {\n findings.push({\n code: \"root_composition_missing_data_start\",\n severity: \"error\",\n message: `Root composition \"${compId}\" is missing data-start. The runtime needs data-start=\"0\" on the root element to begin playback.`,\n fixHint: 'Add data-start=\"0\" to the root composition element.',\n snippet: truncateSnippet(rootTag.raw),\n });\n }\n return findings;\n },\n\n // standalone_composition_wrapped_in_template\n ({ rawSource, options }) => {\n const findings: HyperframeLintFinding[] = [];\n if (options.isSubComposition) return findings;\n const trimmed = rawSource.trimStart().toLowerCase();\n if (trimmed.startsWith(\"<template\")) {\n findings.push({\n code: \"standalone_composition_wrapped_in_template\",\n severity: \"error\",\n message:\n \"Root index.html is wrapped in a <template> tag. \" +\n \"Only sub-compositions loaded via data-composition-src should use <template> wrappers. \" +\n \"The runtime cannot play a standalone composition inside a template.\",\n fixHint:\n \"Remove the <template> wrapper. Use <!DOCTYPE html><html>...<div data-composition-id>...</div>...</html> instead.\",\n });\n }\n return findings;\n },\n\n // root_composition_missing_html_wrapper\n ({ rawSource, rootTag, options }) => {\n const findings: HyperframeLintFinding[] = [];\n if (options.isSubComposition) return findings;\n const trimmed = rawSource.trimStart().toLowerCase();\n // Compositions inside <template> are caught by standalone_composition_wrapped_in_template\n if (trimmed.startsWith(\"<template\")) return findings;\n const hasDoctype = trimmed.startsWith(\"<!doctype\") || trimmed.startsWith(\"<html\");\n const hasComposition = rawSource.includes(\"data-composition-id\");\n if (hasComposition && !hasDoctype) {\n findings.push({\n code: \"root_composition_missing_html_wrapper\",\n severity: \"error\",\n message:\n \"Composition starts with a bare element instead of a proper HTML document. \" +\n \"An index.html that contains data-composition-id but no <!DOCTYPE html>, <html>, or <body> \" +\n \"is a fragment — browsers quirks-mode it, the preview server cannot load it, and \" +\n \"the bundler will fail to inject runtime scripts.\",\n fixHint:\n 'Wrap the composition in <!DOCTYPE html><html><head><meta charset=\"UTF-8\"></head><body>...</body></html>.',\n snippet: rootTag ? truncateSnippet(rootTag.raw) : undefined,\n });\n }\n return findings;\n },\n\n // requestanimationframe_in_composition\n ({ scripts, rawSource, options }) => {\n if (isRegistrySourceFile(options.filePath) || isRegistryInstalledFile(rawSource)) return [];\n const findings: HyperframeLintFinding[] = [];\n for (const script of scripts) {\n const stripped = stripJsComments(script.content);\n if (/requestAnimationFrame\\s*\\(/.test(stripped)) {\n findings.push({\n code: \"requestanimationframe_in_composition\",\n severity: \"error\",\n message:\n \"`requestAnimationFrame` runs on wall-clock time, not the GSAP timeline. It will not sync with frame capture and may cause flickering or missed frames during rendering.\",\n fixHint:\n \"Use GSAP tweens or onUpdate callbacks instead of requestAnimationFrame for animation logic.\",\n snippet: truncateSnippet(script.content),\n });\n }\n }\n return findings;\n },\n\n // invalid_variable_values_json\n // Host elements (`[data-composition-src]`) carry per-instance values via\n // `data-variable-values`. The runtime swallows JSON errors silently and\n // falls back to declared defaults, which masks typos. This rule surfaces\n // the parse failure so authors notice before render time.\n // fallow-ignore-next-line complexity\n ({ tags }) => {\n const findings: HyperframeLintFinding[] = [];\n for (const tag of tags) {\n const raw = readJsonAttr(tag.raw, \"data-variable-values\");\n if (!raw) continue;\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (err) {\n const reason = err instanceof Error ? err.message : \"unknown\";\n findings.push({\n code: \"invalid_variable_values_json\",\n severity: \"error\",\n message: `data-variable-values is not valid JSON (${reason}).`,\n fixHint:\n 'Wrap the attribute value in single quotes and the JSON keys/values in double quotes, e.g. data-variable-values=\\'{\"title\":\"Hello\"}\\'.',\n elementId: readAttr(tag.raw, \"id\") || undefined,\n snippet: truncateSnippet(tag.raw),\n });\n continue;\n }\n\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n findings.push({\n code: \"invalid_variable_values_json\",\n severity: \"error\",\n message:\n 'data-variable-values must be a JSON object keyed by variable id (e.g. {\"title\":\"Hello\"}).',\n fixHint:\n \"Replace the value with a JSON object whose keys are variable ids declared in the sub-composition's data-composition-variables.\",\n elementId: readAttr(tag.raw, \"id\") || undefined,\n snippet: truncateSnippet(tag.raw),\n });\n }\n }\n return findings;\n },\n\n // invalid_composition_variables_declaration\n // The runtime parses `data-composition-variables` and silently returns []\n // on any structural problem. Surface JSON / shape failures so authors\n // catch them at lint time rather than wondering why their `getVariables()`\n // defaults aren't applied.\n // fallow-ignore-next-line complexity\n ({ source }) => {\n const htmlTag = findHtmlTag(source);\n if (!htmlTag) return [];\n const raw = readJsonAttr(htmlTag.raw, \"data-composition-variables\");\n if (!raw) return [];\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (err) {\n const reason = err instanceof Error ? err.message : \"unknown\";\n return [\n {\n code: \"invalid_composition_variables_declaration\",\n severity: \"error\",\n message: `data-composition-variables is not valid JSON (${reason}).`,\n fixHint:\n 'Provide a JSON array of variable declarations: data-composition-variables=\\'[{\"id\":\"title\",\"type\":\"string\",\"label\":\"Title\",\"default\":\"Hello\"}]\\'.',\n snippet: truncateSnippet(htmlTag.raw),\n },\n ];\n }\n\n if (!Array.isArray(parsed)) {\n return [\n {\n code: \"invalid_composition_variables_declaration\",\n severity: \"error\",\n message: \"data-composition-variables must be a JSON array of variable declarations.\",\n fixHint:\n 'Wrap declarations in [] and give each an id, type, label, and default: \\'[{\"id\":\"title\",\"type\":\"string\",\"label\":\"Title\",\"default\":\"Hello\"}]\\'.',\n snippet: truncateSnippet(htmlTag.raw),\n },\n ];\n }\n\n const findings: HyperframeLintFinding[] = [];\n const knownTypes = new Set<string>(COMPOSITION_VARIABLE_TYPES);\n for (let i = 0; i < parsed.length; i += 1) {\n const entry = parsed[i];\n if (!entry || typeof entry !== \"object\" || Array.isArray(entry)) {\n findings.push({\n code: \"invalid_composition_variables_declaration\",\n severity: \"error\",\n message: `data-composition-variables entry [${i}] must be an object with id, type, label, and default.`,\n snippet: truncateSnippet(htmlTag.raw),\n });\n continue;\n }\n const e = entry as Record<string, unknown>;\n const missing: string[] = [];\n if (typeof e.id !== \"string\") missing.push(\"id\");\n if (typeof e.type !== \"string\" || !knownTypes.has(e.type)) missing.push(\"type\");\n if (typeof e.label !== \"string\") missing.push(\"label\");\n if (!(\"default\" in e)) missing.push(\"default\");\n if (missing.length > 0) {\n findings.push({\n code: \"invalid_composition_variables_declaration\",\n severity: \"error\",\n message: `data-composition-variables entry [${i}] is missing or has invalid: ${missing.join(\", \")}. Type must be one of string, number, color, boolean, enum, font, image.`,\n snippet: truncateSnippet(htmlTag.raw),\n });\n }\n }\n return findings;\n },\n\n // subcomposition_blanks_before_host\n // Warns when a full-bleed sub-composition slot ends before the host composition\n // does, leaving the slot blank for the remainder (issue #1540). Scoped narrowly to\n // the high-signal shape — a sole/dominant external mount starting at ~0 — so it\n // stays silent on intentional short clips (an intro followed by other clips that\n // carry the timeline forward).\n // fallow-ignore-next-line complexity\n ({ tags, rootTag }) => {\n if (!rootTag) return [];\n const rootDuration = Number(readAttr(rootTag.raw, \"data-duration\"));\n if (!Number.isFinite(rootDuration) || rootDuration <= 0) return [];\n\n // Two independent knobs that happen to share a 0.5s magnitude. Tuned for\n // real hosts (tens to hundreds of seconds); on a very short host (~6s) the\n // EPSILON slack would let a ~10% blank tail pass unflagged — acceptable\n // because the silent-blank trap this rule targets only matters at scale.\n const EPSILON = 0.5; // seconds; tolerance for \"ends/covers near the host end\"\n const START_TOLERANCE = 0.5; // seconds; \"starts at the composition start\"\n const round3 = (n: number) => Math.round(n * 1000) / 1000;\n\n // Timed children of the root. An element with data-start but no usable\n // data-duration is treated as covering the tail (end = Infinity), so an\n // unknown-length sibling suppresses the warning rather than triggering it.\n const timed = tags\n .filter((tag) => tag.index !== rootTag.index && readAttr(tag.raw, \"data-start\") !== null)\n .map((tag) => {\n const start = Number(readAttr(tag.raw, \"data-start\")) || 0;\n const dur = Number(readAttr(tag.raw, \"data-duration\"));\n const end = Number.isFinite(dur) && dur > 0 ? start + dur : Infinity;\n return { tag, start, end };\n });\n\n // `tags` is a flat list (no nesting depth), so a timed element nested\n // *inside* a candidate slot is treated as a tail-covering sibling rather\n // than a descendant. Acceptable: external src mounts are empty by\n // convention (content is loaded from the linked file), so the only\n // false-negative path is rare and matches the flat-tag scope of the\n // sibling rules in this file.\n const tailCovered = (exceptIndex: number) =>\n timed.some((t) => t.tag.index !== exceptIndex && t.end >= rootDuration - EPSILON);\n\n const findings: HyperframeLintFinding[] = [];\n for (const t of timed) {\n if (readAttr(t.tag.raw, \"data-composition-src\") === null) continue; // external slot only\n if (t.start > START_TOLERANCE) continue; // must start at the composition start\n if (!Number.isFinite(t.end)) continue; // known, finite slot length\n if (t.end >= rootDuration - EPSILON) continue; // already fills the host window\n if (tailCovered(t.tag.index)) continue; // another clip covers the tail — not full-bleed\n const elementId = readAttr(t.tag.raw, \"id\") || undefined;\n const gap = round3(rootDuration - t.end);\n findings.push({\n code: \"subcomposition_blanks_before_host\",\n severity: \"warning\",\n message: `<${t.tag.name}${elementId ? ` id=\"${elementId}\"` : \"\"}> sub-composition ends at ${round3(t.end)}s but the composition runs to ${round3(rootDuration)}s — its slot will be blank for ~${gap}s.`,\n elementId,\n fixHint: `data-duration is the slot's visible window. Set this sub-composition's data-duration to ${round3(rootDuration - t.start)} to fill the host window, or add another clip to cover the remaining ~${gap}s.`,\n snippet: truncateSnippet(t.tag.raw),\n });\n }\n return findings;\n },\n\n // subcomposition_root_styled_by_class\n // A sub-composition's <style> is scoped at render time to\n // `[data-composition-id=\"<id>\"] <selector>` so scenes inlined into one document\n // can't leak styles into each other. A rule whose LEFTMOST selector is the ROOT\n // element's own class (e.g. `.frame { ... }` on the same element that carries\n // data-composition-id) therefore becomes a DESCENDANT selector that can never\n // match the root — the whole scene renders unstyled (tiny text top-left, images\n // at natural size). lint/validate/inspect evaluate the file in isolation (no\n // scoping) and Studio previews each scene in its own iframe (no scoping), so the\n // break is invisible until the composited MP4 render. Style the root via `#root`\n // (the scoper special-cases the root id) and descendants via plain selectors,\n // like the registry blocks — the runtime already scopes each scene by id, so a\n // class namespace on the root is redundant.\n ({ rootTag, rootCompositionId, styles, options }) => {\n if (!options.isSubComposition) return [];\n if (isRegistrySourceFile(options.filePath)) return [];\n if (!rootTag || !rootCompositionId) return [];\n\n const rootClasses = (readAttr(rootTag.raw, \"class\") || \"\").split(/\\s+/).filter(Boolean);\n if (rootClasses.length === 0) return [];\n\n const offenders = rootClassStyledSelectors(styles, rootClasses);\n if (offenders.length === 0) return [];\n\n const example = offenders.slice(0, 3).join(\", \");\n return [\n {\n code: \"subcomposition_root_styled_by_class\",\n severity: \"error\",\n message:\n `Root element has class=\"${rootClasses.join(\" \")}\" and is styled by ${offenders.length} rule(s) keyed off that class (e.g. ${example}). ` +\n `At render, every sub-composition rule is scoped to [data-composition-id=\"${rootCompositionId}\"] <selector>, so a selector whose leftmost part is the ROOT's own class becomes a descendant selector that cannot match the root — the scene renders unstyled (tiny text top-left, full-size images). ` +\n `lint/validate/inspect and Studio's per-frame iframe preview do not scope, so this passes every static check and looks correct in preview.`,\n selector: example,\n fixHint: `Give the root id=\"root\" and style it with \\`#root { ... }\\` plus plain descendant selectors (\\`.kicker\\`, \\`#hero\\`) — the runtime already scopes each sub-composition by data-composition-id, so a class namespace on the root is redundant and breaks under scoping.`,\n snippet: truncateSnippet(rootTag.raw),\n },\n ];\n },\n];\n","import type { LintContext, HyperframeLintFinding } from \"../context\";\nimport { readAttr, extractScriptTextsAndSrcs } from \"../utils\";\n\nexport const adapterRules: Array<(ctx: LintContext) => HyperframeLintFinding[]> = [\n // missing_lottie_script\n ({ tags, scripts }) => {\n const { texts, srcs } = extractScriptTextsAndSrcs(scripts);\n\n const hasLottieAttr = tags.some((t) => readAttr(t.raw, \"data-lottie-src\") !== null);\n const usesLottieApi = texts.some((t) =>\n /lottie\\.(loadAnimation|setSpeed|play|stop|destroy)\\b/.test(t),\n );\n const hasLottieScript = srcs.some((src) => /lottie/i.test(src));\n\n if (!(hasLottieAttr || usesLottieApi) || hasLottieScript) return [];\n return [\n {\n code: \"missing_lottie_script\",\n severity: \"error\",\n message:\n \"Composition uses Lottie but no Lottie script is loaded. The animation will not render.\",\n fixHint:\n 'Add <script src=\"https://cdn.jsdelivr.net/npm/lottie-web@5/build/player/lottie.min.js\"></script> before your Lottie code.',\n },\n ];\n },\n\n // missing_three_script\n ({ scripts }) => {\n const { texts, srcs } = extractScriptTextsAndSrcs(scripts);\n\n const usesThree = texts.some((t) => /\\bTHREE\\./.test(t));\n const hasThreeScript = srcs.some((src) => /three/i.test(src));\n const hasThreeImportMap = texts.some(\n (t) =>\n /[\"']three[\"']/.test(t) &&\n /importmap/.test(scripts.find((s) => s.content === t)?.attrs || \"\"),\n );\n const hasThreeModuleImport = texts.some(\n (t) => /\\bimport\\b.*['\"]three['\"]/.test(t) || /\\bfrom\\s+['\"]three['\"]/.test(t),\n );\n\n if (!usesThree || hasThreeScript || hasThreeImportMap || hasThreeModuleImport) return [];\n return [\n {\n code: \"missing_three_script\",\n severity: \"error\",\n message:\n \"Composition uses Three.js but no Three.js script is loaded. The 3D scene will not render.\",\n fixHint:\n 'Add <script src=\"https://cdn.jsdelivr.net/npm/three@0.160/build/three.min.js\"></script> before your Three.js code.',\n },\n ];\n },\n];\n","import postcss from \"postcss\";\nimport type { LintContext, HyperframeLintFinding, OpenTag } from \"../context\";\nimport { readAttr, truncateSnippet } from \"../utils\";\n\nconst TEXTURE_BASE_CLASS = \"hf-texture-text\";\nconst TEXTURE_CLASS_PREFIX = \"hf-texture-\";\n\ntype DropShadowRule = {\n selector: string;\n directlyTargetsTexture: boolean;\n};\n\nfunction classNames(tag: OpenTag): string[] {\n return (readAttr(tag.raw, \"class\") ?? \"\").split(/\\s+/).filter(Boolean);\n}\n\nfunction isTextureMaterialClass(className: string): boolean {\n return className.startsWith(TEXTURE_CLASS_PREFIX) && className !== TEXTURE_BASE_CLASS;\n}\n\nfunction hasInlineMaskImage(tag: OpenTag): boolean {\n const style = readAttr(tag.raw, \"style\") ?? \"\";\n return /\\b(?:-webkit-)?mask-image\\s*:/i.test(style);\n}\n\nfunction hasInlineDropShadow(tag: OpenTag): boolean {\n const style = readAttr(tag.raw, \"style\") ?? \"\";\n return /\\bfilter\\s*:\\s*[^;]*\\bdrop-shadow\\s*\\(/i.test(style);\n}\n\nfunction classNamesInSelector(selector: string): string[] {\n const classes = new Set<string>();\n const pattern = /\\.([A-Za-z_][\\w-]*)/g;\n let match: RegExpExecArray | null;\n while ((match = pattern.exec(selector)) !== null) {\n const className = match[1];\n if (!className) continue;\n classes.add(className);\n }\n return [...classes];\n}\n\nfunction textureClassesInSelector(selector: string): string[] {\n return classNamesInSelector(selector).filter(isTextureMaterialClass);\n}\n\nfunction simpleSelectorMatchesTag(selector: string, tag: OpenTag, tagClasses: string[]): boolean {\n const trimmed = selector.trim();\n const simpleSelectorPattern = /^(?:[A-Za-z][\\w-]*)?(?:\\.[A-Za-z_][\\w-]*)+$/;\n if (!simpleSelectorPattern.test(trimmed)) return false;\n\n const typeMatch = /^([A-Za-z][\\w-]*)/.exec(trimmed);\n if (typeMatch && typeMatch[1]!.toLowerCase() !== tag.name) return false;\n\n const selectorClasses = classNamesInSelector(trimmed);\n return (\n selectorClasses.length > 0 &&\n selectorClasses.every((className) => tagClasses.includes(className))\n );\n}\n\nfunction collectTextureCss(styles: LintContext[\"styles\"]): {\n definedTextureClasses: Set<string>;\n dropShadowRules: DropShadowRule[];\n} {\n const definedTextureClasses = new Set<string>();\n const dropShadowRules: DropShadowRule[] = [];\n const roots: postcss.Root[] = [];\n\n for (const style of styles) {\n let root: postcss.Root;\n try {\n root = postcss.parse(style.content);\n } catch {\n continue;\n }\n roots.push(root);\n\n // fallow-ignore-next-line complexity\n root.walkRules((rule) => {\n const selectors = rule.selectors ?? [];\n let hasMaskImage = false;\n\n for (const node of rule.nodes ?? []) {\n if (node.type !== \"decl\") continue;\n const prop = node.prop.toLowerCase();\n if (prop === \"mask-image\" || prop === \"-webkit-mask-image\") hasMaskImage = true;\n }\n\n if (hasMaskImage) {\n for (const selector of selectors) {\n for (const className of textureClassesInSelector(selector)) {\n definedTextureClasses.add(className);\n }\n }\n }\n });\n }\n\n for (const root of roots) {\n // fallow-ignore-next-line complexity\n root.walkRules((rule) => {\n const selectors = rule.selectors ?? [];\n let hasDropShadow = false;\n\n for (const node of rule.nodes ?? []) {\n if (node.type !== \"decl\") continue;\n if (node.prop.toLowerCase() === \"filter\" && /\\bdrop-shadow\\s*\\(/i.test(node.value)) {\n hasDropShadow = true;\n }\n }\n\n if (hasDropShadow) {\n for (const selector of selectors) {\n const targetsBaseClass = /\\.hf-texture-text\\b/.test(selector);\n const targetsDefinedTextureClass = textureClassesInSelector(selector).some((className) =>\n definedTextureClasses.has(className),\n );\n dropShadowRules.push({\n selector,\n directlyTargetsTexture: targetsBaseClass || targetsDefinedTextureClass,\n });\n }\n }\n });\n }\n\n return { definedTextureClasses, dropShadowRules };\n}\n\n// fallow-ignore-next-line complexity\nexport const textureRules: Array<(ctx: LintContext) => HyperframeLintFinding[]> = [\n ({ tags, styles }) => {\n const findings: HyperframeLintFinding[] = [];\n const { definedTextureClasses, dropShadowRules } = collectTextureCss(styles);\n\n for (const { selector, directlyTargetsTexture } of dropShadowRules) {\n if (!directlyTargetsTexture) continue;\n findings.push({\n code: \"texture_drop_shadow_on_text\",\n severity: \"warning\",\n message: \"Drop shadow is applied directly to textured text.\",\n selector,\n fixHint:\n \"Wrap the textured text and apply `filter: drop-shadow(...)` to the wrapper, not the `hf-texture-text` element.\",\n });\n }\n\n for (const tag of tags) {\n if (tag.name === \"style\" || tag.name === \"script\") continue;\n\n const classes = classNames(tag);\n if (classes.length === 0) continue;\n\n const hasBaseClass = classes.includes(TEXTURE_BASE_CLASS);\n const textureClasses = classes.filter(isTextureMaterialClass);\n\n if (textureClasses.length > 0 && !hasBaseClass) {\n findings.push({\n code: \"texture_class_missing_base\",\n severity: \"warning\",\n message: `Texture material class \\`${textureClasses[0]}\\` is used without \\`${TEXTURE_BASE_CLASS}\\`.`,\n elementId: readAttr(tag.raw, \"id\") || undefined,\n fixHint: `Add \\`${TEXTURE_BASE_CLASS}\\` alongside the material class, for example \\`class=\"${TEXTURE_BASE_CLASS} ${textureClasses[0]}\"\\`.`,\n snippet: truncateSnippet(tag.raw),\n });\n }\n\n if (hasBaseClass && textureClasses.length === 0 && !hasInlineMaskImage(tag)) {\n findings.push({\n code: \"texture_text_missing_mask\",\n severity: \"warning\",\n message: `\\`${TEXTURE_BASE_CLASS}\\` is used without a texture material class or custom mask image.`,\n elementId: readAttr(tag.raw, \"id\") || undefined,\n fixHint:\n \"Add a material class such as `hf-texture-lava`, or set `mask-image` and `-webkit-mask-image` on the element.\",\n snippet: truncateSnippet(tag.raw),\n });\n }\n\n for (const textureClass of textureClasses) {\n if (definedTextureClasses.has(textureClass)) continue;\n findings.push({\n code: \"texture_class_unknown\",\n severity: \"error\",\n message: `Texture material class \\`${textureClass}\\` is not defined by local CSS.`,\n elementId: readAttr(tag.raw, \"id\") || undefined,\n fixHint:\n \"Paste the Texture Mask Text component `<style>...</style>` block into the composition, or fix the texture class typo.\",\n snippet: truncateSnippet(tag.raw),\n });\n }\n\n if (hasBaseClass) {\n for (const rule of dropShadowRules) {\n if (rule.directlyTargetsTexture) continue;\n if (!simpleSelectorMatchesTag(rule.selector, tag, classes)) continue;\n findings.push({\n code: \"texture_drop_shadow_on_text\",\n severity: \"warning\",\n message: \"Drop shadow is applied directly to textured text.\",\n selector: rule.selector,\n elementId: readAttr(tag.raw, \"id\") || undefined,\n fixHint:\n \"Wrap the textured text and apply `filter: drop-shadow(...)` to the wrapper, not the `hf-texture-text` element.\",\n snippet: truncateSnippet(tag.raw),\n });\n }\n }\n\n if (hasBaseClass && hasInlineDropShadow(tag)) {\n findings.push({\n code: \"texture_drop_shadow_on_text\",\n severity: \"warning\",\n message: \"Drop shadow is applied directly to textured text.\",\n elementId: readAttr(tag.raw, \"id\") || undefined,\n fixHint:\n \"Wrap the textured text and apply `filter: drop-shadow(...)` to the wrapper, not the `hf-texture-text` element.\",\n snippet: truncateSnippet(tag.raw),\n });\n }\n }\n\n return findings;\n },\n];\n","import { FONT_ALIAS_KEYS, resolveAliasDisplayName } from \"@hyperframes/core/fonts/aliases\";\nimport type { LintContext, HyperframeLintFinding } from \"../context\";\nimport { isRegistrySourceFile, isRegistryInstalledFile } from \"./composition\";\n\nconst GENERIC_FAMILIES = new Set([\n \"serif\",\n \"sans-serif\",\n \"monospace\",\n \"cursive\",\n \"fantasy\",\n \"system-ui\",\n \"ui-serif\",\n \"ui-sans-serif\",\n \"ui-monospace\",\n \"ui-rounded\",\n \"math\",\n \"emoji\",\n \"fangsong\",\n \"inherit\",\n \"initial\",\n \"unset\",\n \"revert\",\n]);\n\n// A CSS comment can contain a `}` (e.g. `@font-face { /* 400 } regular */\n// font-family: 'X'; ... }`), which truncates the naive `@font-face\\s*\\{[^}]*\\}`\n// block match at the comment's brace — so the rule never sees the real\n// `font-family` and reports a false-positive font_family_without_font_face.\n// Large/\"framework\" stylesheets hit this far more often than minimal ones,\n// which is why a simple <style> passes while a complex one fails. Strip\n// comments before scanning so a brace inside one cannot split a block. See #1534.\nfunction stripCssComments(css: string): string {\n return css.replace(/\\/\\*[\\s\\S]*?\\*\\//g, \" \");\n}\n\nfunction extractFontFaceFamilies(styles: Array<{ content: string }>): Set<string> {\n const families = new Set<string>();\n const fontFaceRe = /@font-face\\s*\\{[^}]*\\}/gi;\n const familyRe = /font-family\\s*:\\s*(['\"]?)([^;'\"]+)\\1/i;\n for (const style of styles) {\n const content = stripCssComments(style.content);\n let match: RegExpExecArray | null;\n while ((match = fontFaceRe.exec(content)) !== null) {\n const familyMatch = match[0].match(familyRe);\n if (familyMatch?.[2]) {\n families.add(familyMatch[2].trim().toLowerCase());\n }\n }\n }\n return families;\n}\n\nfunction extractUsedFontFamilies(styles: Array<{ content: string }>): string[] {\n const used: string[] = [];\n const seen = new Set<string>();\n const propRe = /font-family\\s*:\\s*([^;}{]+)/gi;\n for (const style of styles) {\n const withoutFontFace = stripCssComments(style.content).replace(/@font-face\\s*\\{[^}]*\\}/gi, \"\");\n let match: RegExpExecArray | null;\n while ((match = propRe.exec(withoutFontFace)) !== null) {\n const stack = match[1]!;\n for (const part of stack.split(\",\")) {\n const name = part\n .trim()\n .replace(/^['\"]|['\"]$/g, \"\")\n .trim()\n .toLowerCase();\n if (name && !GENERIC_FAMILIES.has(name) && !seen.has(name)) {\n seen.add(name);\n used.push(name);\n }\n }\n }\n }\n return used;\n}\n\nfunction collectAliasedFonts(used: string[], declared: Set<string>): string[] {\n const aliased: string[] = [];\n for (const name of used) {\n if (declared.has(name)) continue;\n const displayName = resolveAliasDisplayName(name);\n if (!displayName) continue;\n if (displayName.toLowerCase() === name) continue;\n aliased.push(`'${name}' → ${displayName}`);\n }\n return aliased;\n}\n\nfunction normalizeFontFamily(name: string): string | null {\n const decoded = name.replace(/\\+/g, \" \").trim();\n if (!decoded) return null;\n try {\n return decodeURIComponent(decoded).trim().toLowerCase() || null;\n } catch {\n return decoded.toLowerCase();\n }\n}\n\nfunction extractGoogleFontFamiliesFromUrl(rawUrl: string): string[] {\n const url = rawUrl.replace(/&amp;/gi, \"&\");\n let parsed: URL;\n try {\n parsed = new URL(url, \"https://fonts.googleapis.com\");\n } catch {\n return [];\n }\n\n if (parsed.hostname.toLowerCase() !== \"fonts.googleapis.com\") return [];\n const families: string[] = [];\n for (const value of parsed.searchParams.getAll(\"family\")) {\n for (const familySpec of value.split(\"|\")) {\n const family = normalizeFontFamily(familySpec.split(\":\")[0] || \"\");\n if (family) families.push(family);\n }\n }\n return families;\n}\n\nfunction collectGoogleFontFamilies(\n source: string,\n styles: Array<{ content: string }>,\n): Set<string> {\n const families = new Set<string>();\n const addUrl = (url: string) => {\n for (const family of extractGoogleFontFamiliesFromUrl(url)) families.add(family);\n };\n\n const linkHrefRe =\n /<link\\b[^>]*\\bhref\\s*=\\s*(?:([\"'])([^\"']*fonts\\.googleapis\\.com[^\"']*)\\1|([^\\s>]*fonts\\.googleapis\\.com[^\\s>]*))[^>]*>/gi;\n for (const match of source.matchAll(linkHrefRe)) {\n const href = match[2] || match[3];\n if (href) addUrl(href);\n }\n\n const importUrlRe =\n /@import\\s+(?:url\\(\\s*)?([\"']?)([^\"')\\s]*fonts\\.googleapis\\.com[^\"')\\s]*)\\1\\s*\\)?/gi;\n for (const style of styles) {\n for (const match of style.content.matchAll(importUrlRe)) {\n if (match[2]) addUrl(match[2]);\n }\n }\n\n return families;\n}\n\nexport const fontRules: Array<(ctx: LintContext) => HyperframeLintFinding[]> = [\n // google_fonts_import\n ({ styles, source, rawSource, options }) => {\n if (isRegistrySourceFile(options.filePath) || isRegistryInstalledFile(rawSource)) return [];\n const findings: HyperframeLintFinding[] = [];\n const googleFontsInLink = /<link\\b[^>]*fonts\\.googleapis\\.com[^>]*>/i.test(source);\n const googleFontsInImport = styles.some((s) =>\n /@import\\s+url\\s*\\(\\s*['\"]?[^)]*fonts\\.googleapis\\.com/i.test(s.content),\n );\n\n if (googleFontsInLink || googleFontsInImport) {\n findings.push({\n code: \"google_fonts_import\",\n severity: \"warning\",\n message:\n \"Composition loads fonts from fonts.googleapis.com. The producer resolves Google Fonts \" +\n \"during compile/render, but raw external font requests add latency and can fail before \" +\n \"canonicalization. Prefer mapped family names or local @font-face declarations when possible.\",\n fixHint:\n \"For bundled fonts, remove the Google Fonts <link> or @import and keep the font-family \" +\n \"declaration. For custom fonts, use @font-face { font-family: '...'; src: url('...woff2'); }.\",\n });\n }\n return findings;\n },\n\n // system_font_will_alias — inform when a font will be silently substituted\n ({ styles, options }) => {\n const declared = extractFontFaceFamilies(styles);\n const used = extractUsedFontFamilies(styles);\n const aliased = collectAliasedFonts(used, declared);\n if (aliased.length === 0) return [];\n // In distributed / Lambda renders system-font capture is disabled, so\n // the alias substitution does NOT happen — elevate to a warning.\n const severity = options.distributed ? (\"warning\" as const) : (\"info\" as const);\n return [\n {\n code: \"system_font_will_alias\",\n severity,\n message:\n `Font ${aliased.length === 1 ? \"family\" : \"families\"} will be substituted at render time: ${aliased.join(\", \")}. ` +\n (options.distributed\n ? \"In distributed/Lambda rendering system-font capture is disabled — these fonts will fall back to OS defaults. Embed explicit @font-face declarations instead.\"\n : \"The renderer maps these to bundled fonts for cross-platform consistency. \" +\n \"Use the target font name directly for consistent preview and render results.\"),\n },\n ];\n },\n\n // font_family_without_font_face\n ({ styles, source, rawSource, options }) => {\n if (isRegistrySourceFile(options.filePath) || isRegistryInstalledFile(rawSource)) return [];\n const findings: HyperframeLintFinding[] = [];\n const declared = extractFontFaceFamilies(styles);\n const used = extractUsedFontFamilies(styles);\n const googleFonts = collectGoogleFontFamilies(source, styles);\n\n const undeclared = used.filter(\n (name) => !declared.has(name) && !FONT_ALIAS_KEYS.has(name) && !googleFonts.has(name),\n );\n if (undeclared.length === 0) return findings;\n\n findings.push({\n code: \"font_family_without_font_face\",\n severity: \"error\",\n message:\n `Font ${undeclared.length === 1 ? \"family\" : \"families\"} used without @font-face declaration: ${undeclared.join(\", \")}. ` +\n \"These are not in the auto-resolved font list, so the renderer cannot supply them automatically. \" +\n \"Text will fall back to a generic font, producing incorrect typography in the video.\",\n fixHint:\n \"Add @font-face { font-family: '...'; src: url('capture/assets/fonts/...woff2'); } \" +\n \"for each font family, pointing to the captured .woff2 files.\",\n });\n return findings;\n },\n];\n","import type { LintContext, HyperframeLintFinding } from \"../context\";\nimport type { LintRule } from \"../types\";\nimport { readAttr } from \"../utils\";\nimport {\n parseSlideshowManifest,\n resolveSlideshow,\n isSceneLikeCompositionId,\n} from \"@hyperframes/core/slideshow\";\n\ntype Scene = { id: string; start: number; duration: number };\n\nfunction parseTiming(raw: string): { start: number; duration: number } | null {\n const startStr = readAttr(raw, \"data-start\");\n if (startStr === null) return null;\n const start = Number(startStr);\n if (!Number.isFinite(start)) return null;\n\n const durationStr = readAttr(raw, \"data-duration\");\n if (durationStr !== null) {\n const duration = Number(durationStr);\n if (Number.isFinite(duration)) return { start, duration };\n }\n const endStr = readAttr(raw, \"data-end\") ?? readAttr(raw, \"data-hf-authored-end\");\n if (endStr !== null) {\n const end = Number(endStr);\n if (Number.isFinite(end) && end > start) return { start, duration: end - start };\n }\n return null;\n}\n\nfunction collectCompositionIdScenes(ctx: LintContext, seen: Set<string>, out: Scene[]): void {\n for (const tag of ctx.tags) {\n const compositionId = readAttr(tag.raw, \"data-composition-id\");\n if (!compositionId || !isSceneLikeCompositionId(compositionId) || seen.has(compositionId))\n continue;\n const timing = parseTiming(tag.raw);\n if (!timing || timing.duration <= 0) continue;\n seen.add(compositionId);\n out.push({ id: compositionId, ...timing });\n }\n}\n\nfunction extractScenesFromClips(ctx: LintContext): Scene[] {\n const seen = new Set<string>();\n const scenes: Scene[] = [];\n collectCompositionIdScenes(ctx, seen, scenes);\n return scenes;\n}\n\nexport const slideshowRules: LintRule<LintContext>[] = [\n (ctx) => {\n const findings: HyperframeLintFinding[] = [];\n\n let manifest;\n try {\n manifest = parseSlideshowManifest(ctx.source);\n } catch (e) {\n findings.push({\n code: \"slideshow_invalid\",\n severity: \"error\",\n message: `Slideshow island contains invalid JSON or structure: ${e instanceof Error ? e.message : String(e)}`,\n fixHint:\n 'Ensure the <script type=\"application/hyperframes-slideshow+json\"> block contains valid JSON matching the SlideshowManifest schema.',\n });\n return findings;\n }\n\n if (!manifest) return findings;\n\n const scenes = extractScenesFromClips(ctx);\n const { errors } = resolveSlideshow(manifest, scenes);\n\n for (const error of errors) {\n findings.push({\n code: \"slideshow_unresolved_ref\",\n severity: \"error\",\n message: `Slideshow manifest error: ${error}`,\n fixHint:\n \"Ensure every sceneId in the slideshow island matches the data-composition-id of a scene element in the composition, or provide explicit startTime/endTime.\",\n });\n }\n\n return findings;\n },\n];\n","import type { HyperframeLintFinding, HyperframeLintResult, HyperframeLinterOptions } from \"./types\";\nimport { buildLintContext } from \"./context\";\nimport { readAttr, truncateSnippet } from \"./utils\";\nimport { coreRules } from \"./rules/core\";\nimport { mediaRules } from \"./rules/media\";\nimport { gsapRules } from \"./rules/gsap\";\nimport { captionRules } from \"./rules/captions\";\nimport { compositionRules } from \"./rules/composition\";\nimport { adapterRules } from \"./rules/adapters\";\nimport { textureRules } from \"./rules/textures\";\nimport { fontRules } from \"./rules/fonts\";\nimport { slideshowRules } from \"./rules/slideshow\";\n\nconst ALL_RULES = [\n ...coreRules,\n ...mediaRules,\n ...gsapRules,\n ...captionRules,\n ...compositionRules,\n ...adapterRules,\n ...textureRules,\n ...fontRules,\n ...slideshowRules,\n];\n\nexport async function lintHyperframeHtml(\n html: string,\n options: HyperframeLinterOptions = {},\n): Promise<HyperframeLintResult> {\n const ctx = buildLintContext(html, options);\n const findings: HyperframeLintFinding[] = [];\n const seen = new Set<string>();\n\n for (const rule of ALL_RULES) {\n for (const finding of await Promise.resolve(rule(ctx))) {\n const dedupeKey = [\n finding.code,\n finding.severity,\n finding.selector || \"\",\n finding.elementId || \"\",\n finding.message,\n ].join(\"|\");\n if (seen.has(dedupeKey)) continue;\n seen.add(dedupeKey);\n findings.push(options.filePath ? { ...finding, file: options.filePath } : finding);\n }\n }\n\n const errorCount = findings.filter((f) => f.severity === \"error\").length;\n const warningCount = findings.filter((f) => f.severity === \"warning\").length;\n const infoCount = findings.filter((f) => f.severity === \"info\").length;\n\n return {\n ok: errorCount === 0,\n errorCount,\n warningCount,\n infoCount,\n findings,\n };\n}\n\n// ── Async media URL accessibility checker ─────────────────────────────────\n\nfunction extractMediaUrls(html: string): Array<{\n url: string;\n tagName: string;\n elementId?: string;\n snippet: string;\n}> {\n const results: Array<{\n url: string;\n tagName: string;\n elementId?: string;\n snippet: string;\n }> = [];\n const tagRe = /<(video|audio|img|source)\\b[^>]*>/gi;\n let match: RegExpExecArray | null;\n while ((match = tagRe.exec(html)) !== null) {\n const tagName = (match[1] ?? \"\").toLowerCase();\n const raw = match[0];\n const src = readAttr(raw, \"src\");\n if (!src) continue;\n if (/^https?:\\/\\//i.test(src)) {\n results.push({\n url: src,\n tagName,\n elementId: readAttr(raw, \"id\") || undefined,\n snippet: truncateSnippet(raw) ?? \"\",\n });\n }\n }\n return results;\n}\n\n/**\n * Async lint pass: HEAD-checks every remote media URL in the HTML.\n * Returns findings for URLs that are unreachable (non-2xx status or network error).\n *\n * Call this after `lintHyperframeHtml()` and merge the findings.\n *\n * @param timeoutMs - per-request timeout (default 8000ms)\n */\nexport async function lintMediaUrls(\n html: string,\n options: { timeoutMs?: number } = {},\n): Promise<HyperframeLintFinding[]> {\n const urls = extractMediaUrls(html);\n if (urls.length === 0) return [];\n\n const timeout = options.timeoutMs ?? 8000;\n const findings: HyperframeLintFinding[] = [];\n\n const seen = new Set<string>();\n const unique = urls.filter((u) => {\n if (seen.has(u.url)) return false;\n seen.add(u.url);\n return true;\n });\n\n const checks = unique.map(async ({ url, tagName, elementId, snippet }) => {\n try {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeout);\n const resp = await fetch(url, {\n method: \"HEAD\",\n signal: controller.signal,\n redirect: \"follow\",\n });\n clearTimeout(timer);\n if (!resp.ok) {\n findings.push({\n code: \"inaccessible_media_url\",\n severity: \"error\",\n message: `<${tagName}${elementId ? ` id=\"${elementId}\"` : \"\"}> references a URL that returned HTTP ${resp.status}: ${url.slice(0, 100)}`,\n elementId,\n fixHint: \"This URL is not accessible. Replace with a valid, reachable media URL.\",\n snippet,\n });\n }\n } catch (err) {\n const reason = err instanceof Error ? err.name : \"unknown\";\n findings.push({\n code: \"inaccessible_media_url\",\n severity: \"error\",\n message: `<${tagName}${elementId ? ` id=\"${elementId}\"` : \"\"}> references an unreachable URL (${reason}): ${url.slice(0, 100)}`,\n elementId,\n fixHint: \"This URL is not accessible. Replace with a valid, reachable media URL.\",\n snippet,\n });\n }\n });\n\n await Promise.all(checks);\n return findings;\n}\n","import { existsSync, readFileSync, readdirSync } from \"node:fs\";\nimport { dirname, extname, isAbsolute, join, posix, relative, resolve } from \"node:path\";\nimport { decodeUrlPathVariants, rewriteAssetPath } from \"@hyperframes/core\";\nimport { lintHyperframeHtml } from \"./hyperframeLinter.js\";\nimport type { HyperframeLintFinding, HyperframeLintResult } from \"./types.js\";\n\ninterface HtmlSource {\n html: string;\n compSrcPath?: string;\n}\n\ninterface CssSource {\n content: string;\n rootRelativePath?: string;\n}\n\nexport interface ProjectLintResult {\n results: Array<{ file: string; result: HyperframeLintResult }>;\n totalErrors: number;\n totalWarnings: number;\n totalInfos: number;\n}\n\nconst AUDIO_EXTENSIONS = new Set([\".mp3\", \".wav\", \".aac\", \".ogg\", \".m4a\", \".flac\", \".opus\"]);\nconst STYLE_BLOCK_RE = /<style\\b[^>]*>([\\s\\S]*?)<\\/style>/gi;\nconst OPEN_TAG_RE = /<([a-z][\\w:-]*)(\\s[^<>]*?)?>/gi;\nconst MASK_IMAGE_URL_RE =\n /\\b(?:-webkit-)?mask-image\\s*:\\s*[^;{}]*url\\(\\s*(?:\"([^\"]+)\"|'([^']+)'|([^\"')\\s]+))\\s*\\)/gi;\n\nfunction readHtmlAttr(tag: string, name: string): string | null {\n const escaped = name.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n const match = tag.match(new RegExp(`\\\\b${escaped}\\\\s*=\\\\s*(?:\"([^\"]*)\"|'([^']*)')`, \"i\"));\n return match?.[1] ?? match?.[2] ?? null;\n}\n\nfunction isLocalStylesheetHref(href: string): boolean {\n return !!href && !/^(https?:|data:|blob:|\\/\\/)/i.test(href);\n}\n\nfunction collectExternalStyles(\n projectDir: string,\n html: string,\n compSrcPath?: string,\n): Array<{ href: string; content: string }> {\n const styles: Array<{ href: string; content: string }> = [];\n const linkRe = /<link\\b[^>]*>/gi;\n let match: RegExpExecArray | null;\n while ((match = linkRe.exec(html)) !== null) {\n const tag = match[0];\n const rel = tag.match(/\\brel\\s*=\\s*[\"']([^\"']+)[\"']/i)?.[1] ?? \"\";\n if (!rel.split(/\\s+/).some((part) => part.toLowerCase() === \"stylesheet\")) continue;\n const href = tag.match(/\\bhref\\s*=\\s*[\"']([^\"']+)[\"']/i)?.[1] ?? \"\";\n if (!isLocalStylesheetHref(href)) continue;\n const rootRelative = compSrcPath ? join(dirname(compSrcPath), href) : href;\n const stylesheet = resolveExistingLocalAsset(projectDir, rootRelative);\n if (!stylesheet) continue;\n styles.push({ href, content: readFileSync(stylesheet.resolved, \"utf-8\") });\n }\n return styles;\n}\n\nfunction collectCssSources(projectDir: string, html: string, compSrcPath?: string): CssSource[] {\n const sources: CssSource[] = [];\n\n let styleMatch: RegExpExecArray | null;\n const stylePattern = new RegExp(STYLE_BLOCK_RE.source, STYLE_BLOCK_RE.flags);\n while ((styleMatch = stylePattern.exec(html)) !== null) {\n sources.push({ content: styleMatch[1] ?? \"\" });\n }\n\n const linkRe = /<link\\b[^>]*>/gi;\n let linkMatch: RegExpExecArray | null;\n while ((linkMatch = linkRe.exec(html)) !== null) {\n const tag = linkMatch[0];\n const rel = readHtmlAttr(tag, \"rel\") ?? \"\";\n if (!rel.split(/\\s+/).some((part) => part.toLowerCase() === \"stylesheet\")) continue;\n const href = readHtmlAttr(tag, \"href\") ?? \"\";\n if (!isLocalStylesheetHref(href)) continue;\n\n const rootRelativePath = compSrcPath ? join(dirname(compSrcPath), href) : href;\n const stylesheet = resolveExistingLocalAsset(projectDir, rootRelativePath);\n if (!stylesheet) continue;\n sources.push({\n content: readFileSync(stylesheet.resolved, \"utf-8\"),\n rootRelativePath: stylesheet.rootRelativePath,\n });\n }\n\n let tagMatch: RegExpExecArray | null;\n const tagPattern = new RegExp(OPEN_TAG_RE.source, OPEN_TAG_RE.flags);\n while ((tagMatch = tagPattern.exec(html)) !== null) {\n const tag = tagMatch[0];\n const style = readHtmlAttr(tag, \"style\");\n if (!style) continue;\n sources.push({ content: style });\n }\n\n return sources;\n}\n\nfunction isRemoteOrInlineUrl(url: string): boolean {\n return /^(https?:|data:|blob:|\\/\\/|#)/i.test(url);\n}\n\nfunction cleanAssetUrl(url: string): string {\n return url.trim().split(/[?#]/, 1)[0] ?? \"\";\n}\n\nfunction isWithinProjectRoot(projectDir: string, candidate: string): boolean {\n const projectRoot = resolve(projectDir);\n const relativePath = relative(projectRoot, candidate);\n return relativePath === \"\" || (!relativePath.startsWith(\"..\") && !isAbsolute(relativePath));\n}\n\nfunction addCandidate(candidates: string[], candidate: string): void {\n if (!candidates.includes(candidate)) candidates.push(candidate);\n}\n\nfunction resolveLocalAssetCandidates(projectDir: string, url: string): string[] {\n const cleanUrl = cleanAssetUrl(url);\n const projectRoot = resolve(projectDir);\n const candidates: string[] = [];\n\n for (const variant of decodeUrlPathVariants(cleanUrl)) {\n const projectRelative = variant.startsWith(\"/\") ? variant.slice(1) : variant;\n const resolved = resolve(projectRoot, projectRelative);\n if (isWithinProjectRoot(projectRoot, resolved)) {\n addCandidate(candidates, resolved);\n continue;\n }\n\n const normalized = posix.normalize(projectRelative.replace(/\\\\/g, \"/\"));\n const clamped = normalized.replace(/^(\\.\\.\\/)+/, \"\");\n if (clamped && !clamped.startsWith(\"..\")) {\n addCandidate(candidates, resolve(projectRoot, clamped));\n }\n }\n\n return candidates;\n}\n\nfunction resolveExistingLocalAsset(\n projectDir: string,\n url: string,\n): { resolved: string; rootRelativePath: string } | null {\n const projectRoot = resolve(projectDir);\n const resolved = resolveLocalAssetCandidates(projectRoot, url).find(existsSync);\n if (!resolved) return null;\n return { resolved, rootRelativePath: relative(projectRoot, resolved) };\n}\n\nfunction resolveCssAssetCandidates(\n projectDir: string,\n url: string,\n htmlCompSrcPath?: string,\n cssRootRelativePath?: string,\n): string[] {\n if (url.startsWith(\"/\")) return resolveLocalAssetCandidates(projectDir, url);\n if (cssRootRelativePath) {\n return resolveLocalAssetCandidates(projectDir, join(dirname(cssRootRelativePath), url));\n }\n if (htmlCompSrcPath) {\n return resolveLocalAssetCandidates(projectDir, rewriteAssetPath(htmlCompSrcPath, url));\n }\n return resolveLocalAssetCandidates(projectDir, url);\n}\n\nexport async function lintProject(projectDir: string): Promise<ProjectLintResult> {\n const indexPath = resolve(projectDir, \"index.html\");\n const results: Array<{ file: string; result: HyperframeLintResult }> = [];\n let totalErrors = 0;\n let totalWarnings = 0;\n let totalInfos = 0;\n\n const rootHtml = readFileSync(indexPath, \"utf-8\");\n const rootResult = await lintHyperframeHtml(rootHtml, {\n filePath: indexPath,\n externalStyles: collectExternalStyles(projectDir, rootHtml),\n });\n results.push({ file: \"index.html\", result: rootResult });\n totalErrors += rootResult.errorCount;\n totalWarnings += rootResult.warningCount;\n totalInfos += rootResult.infoCount;\n\n const allHtmlSources: HtmlSource[] = [{ html: rootHtml }];\n const compositionsDir = resolve(projectDir, \"compositions\");\n if (existsSync(compositionsDir)) {\n const collectHtmlFiles = (dir: string, rel: string): string[] => {\n const out: string[] = [];\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n const relPath = rel ? `${rel}/${entry.name}` : entry.name;\n if (entry.isDirectory()) out.push(...collectHtmlFiles(join(dir, entry.name), relPath));\n else if (entry.isFile() && entry.name.endsWith(\".html\")) out.push(relPath);\n }\n return out;\n };\n const files = collectHtmlFiles(compositionsDir, \"\").sort();\n for (const file of files) {\n const filePath = join(compositionsDir, file);\n const html = readFileSync(filePath, \"utf-8\");\n const compSrcPath = `compositions/${file}`;\n allHtmlSources.push({ html, compSrcPath });\n const result = await lintHyperframeHtml(html, {\n filePath,\n isSubComposition: true,\n externalStyles: collectExternalStyles(projectDir, html, compSrcPath),\n });\n results.push({ file: `compositions/${file}`, result });\n totalErrors += result.errorCount;\n totalWarnings += result.warningCount;\n totalInfos += result.infoCount;\n }\n }\n\n const projectFindings = [\n ...lintProjectAudioFiles(projectDir, allHtmlSources),\n ...lintAudioSrcNotFound(projectDir, allHtmlSources),\n ...lintMissingLocalAsset(projectDir, allHtmlSources),\n ...lintTextureMaskAssetNotFound(projectDir, allHtmlSources),\n ...lintMultipleRootCompositions(projectDir),\n ...lintDuplicateAudioTracks(allHtmlSources),\n ];\n if (projectFindings.length > 0) {\n for (const finding of projectFindings) {\n rootResult.findings.push(finding);\n if (finding.severity === \"error\") {\n rootResult.errorCount++;\n rootResult.ok = false;\n totalErrors++;\n } else if (finding.severity === \"warning\") {\n rootResult.warningCount++;\n totalWarnings++;\n } else {\n rootResult.infoCount++;\n totalInfos++;\n }\n }\n }\n\n return { results, totalErrors, totalWarnings, totalInfos };\n}\n\nexport function shouldBlockRender(\n strictErrors: boolean,\n strictAll: boolean,\n totalErrors: number,\n totalWarnings: number,\n): boolean {\n return (strictErrors && totalErrors > 0) || (strictAll && (totalErrors > 0 || totalWarnings > 0));\n}\n\nfunction lintProjectAudioFiles(\n projectDir: string,\n htmlSources: HtmlSource[],\n): HyperframeLintFinding[] {\n const findings: HyperframeLintFinding[] = [];\n\n let audioFiles: string[];\n try {\n audioFiles = readdirSync(projectDir).filter((f) =>\n AUDIO_EXTENSIONS.has(extname(f).toLowerCase()),\n );\n } catch {\n return findings;\n }\n\n if (audioFiles.length === 0) return findings;\n\n const hasAudioElement = htmlSources.some(({ html }) => /<audio\\b/i.test(html));\n\n if (!hasAudioElement) {\n findings.push({\n code: \"audio_file_without_element\",\n severity: \"warning\",\n message: `Found audio file(s) in project (${audioFiles.join(\", \")}) but no <audio> element in any composition. The rendered video will be silent.`,\n fixHint:\n 'Add an <audio id=\"my-audio\" src=\"' +\n audioFiles[0] +\n '\" data-start=\"0\" data-duration=\"__DURATION__\" data-track-index=\"0\" data-volume=\"1\"></audio> element inside the composition root. Replace __DURATION__ with the audio length in seconds.',\n });\n }\n\n return findings;\n}\n\nfunction lintAudioSrcNotFound(\n projectDir: string,\n htmlSources: HtmlSource[],\n): HyperframeLintFinding[] {\n const findings: HyperframeLintFinding[] = [];\n\n const audioSrcRe = /<audio\\b[^>]*\\bsrc\\s*=\\s*[\"']([^\"']+)[\"'][^>]*>/gi;\n\n const missingSrcs: string[] = [];\n for (const { html, compSrcPath } of htmlSources) {\n let match: RegExpExecArray | null;\n while ((match = audioSrcRe.exec(html)) !== null) {\n const src = match[1]!;\n if (/^(https?:|data:|blob:)/i.test(src)) continue;\n if (/^__[A-Z_]+__$/.test(src)) continue;\n const rootRelative = compSrcPath ? rewriteAssetPath(compSrcPath, src) : src;\n if (!resolveLocalAssetCandidates(projectDir, rootRelative).some(existsSync)) {\n missingSrcs.push(src);\n }\n }\n }\n\n if (missingSrcs.length > 0) {\n const unique = [...new Set(missingSrcs)];\n findings.push({\n code: \"audio_src_not_found\",\n severity: \"error\",\n message: `<audio> element references file(s) not found in the project: ${unique.join(\", \")}. The rendered video will be silent.`,\n fixHint:\n unique.length === 1\n ? `Add the file \"${unique[0]}\" to the project directory, or update the src attribute to point to an existing file.`\n : `Add the missing files to the project directory, or update the src attributes to point to existing files.`,\n });\n }\n\n return findings;\n}\n\nfunction maskRange(src: string, pattern: RegExp): string {\n return src.replace(pattern, (m) => \" \".repeat(m.length));\n}\n\nfunction maskNonScannableRanges(html: string): string {\n let out = maskRange(html, /<!--[\\s\\S]*?-->/g);\n out = maskRange(out, /<style\\b[^>]*>[\\s\\S]*?<\\/style\\b[^>]*>/gi);\n out = maskRange(out, /<script\\b[^>]*>[\\s\\S]*?<\\/script\\b[^>]*>/gi);\n return out;\n}\n\n// fallow-ignore-next-line complexity\nfunction lintMissingLocalAsset(\n projectDir: string,\n htmlSources: HtmlSource[],\n): HyperframeLintFinding[] {\n const findings: HyperframeLintFinding[] = [];\n\n const localAssetSrcRe = /<(video|img|source)\\b[^>]*\\bsrc\\s*=\\s*[\"']([^\"']+)[\"'][^>]*>/gi;\n\n const missingByTag = new Map<string, Map<string, string>>();\n\n for (const { html, compSrcPath } of htmlSources) {\n const scannable = maskNonScannableRanges(html);\n const re = new RegExp(localAssetSrcRe.source, localAssetSrcRe.flags);\n let match: RegExpExecArray | null;\n while ((match = re.exec(scannable)) !== null) {\n const tagName = (match[1] ?? \"\").toLowerCase();\n const rawSrc = match[2] ?? \"\";\n const src = cleanAssetUrl(rawSrc);\n if (!src) continue;\n if (isRemoteOrInlineUrl(src)) continue;\n if (/^__[A-Z_]+__$/.test(src)) continue;\n const rootRelative = compSrcPath ? rewriteAssetPath(compSrcPath, src) : src;\n const resolvedAsset = resolveExistingLocalAsset(projectDir, rootRelative);\n if (resolvedAsset) continue;\n\n const resolvedKey = resolve(projectDir, rootRelative);\n let bucket = missingByTag.get(tagName);\n if (!bucket) {\n bucket = new Map<string, string>();\n missingByTag.set(tagName, bucket);\n }\n if (!bucket.has(resolvedKey)) bucket.set(resolvedKey, src);\n }\n }\n\n for (const [tagName, byResolved] of missingByTag) {\n const unique = [...byResolved.values()];\n findings.push({\n code: \"missing_local_asset\",\n severity: \"error\",\n message:\n `<${tagName}> element references local file(s) not found in the project: ${unique.join(\", \")}. ` +\n \"The renderer will silently skip these and produce a video with missing visuals.\",\n fixHint:\n unique.length === 1\n ? `Add \"${unique[0]}\" to the project directory, or update the src attribute to point to an existing file. ` +\n \"Common cause: captured asset filenames are unreliable (heygen-logo.svg often contains Google, nvidia-logo.svg may contain Autodesk, etc.). \" +\n \"Open the contact sheets and verify the file actually exists at this path before referencing it.\"\n : \"Add the missing files to the project directory, or update the src attributes to point to existing files. \" +\n \"Captured asset filenames are unreliable — verify against capture/contact-sheets/ and capture/extracted/asset-descriptions.md.\",\n });\n }\n\n return findings;\n}\n\nfunction lintTextureMaskAssetNotFound(\n projectDir: string,\n htmlSources: HtmlSource[],\n): HyperframeLintFinding[] {\n const missing = new Map<string, string>();\n\n for (const { html, compSrcPath } of htmlSources) {\n for (const cssSource of collectCssSources(projectDir, html, compSrcPath)) {\n let match: RegExpExecArray | null;\n const pattern = new RegExp(MASK_IMAGE_URL_RE.source, MASK_IMAGE_URL_RE.flags);\n while ((match = pattern.exec(cssSource.content)) !== null) {\n const rawUrl = match[1] ?? match[2] ?? match[3] ?? \"\";\n const url = cleanAssetUrl(rawUrl);\n if (!url || isRemoteOrInlineUrl(url)) continue;\n if (/^__[A-Z_]+__$/.test(url)) continue;\n\n const candidates = resolveCssAssetCandidates(\n projectDir,\n url,\n compSrcPath,\n cssSource.rootRelativePath,\n );\n if (candidates.some(existsSync)) continue;\n missing.set(url, candidates[0] ?? resolve(projectDir, url));\n }\n }\n }\n\n if (missing.size === 0) return [];\n const urls = [...missing.keys()];\n return [\n {\n code: \"texture_mask_asset_not_found\",\n severity: \"error\",\n message: `CSS mask-image references file(s) not found in the project: ${urls.join(\", \")}.`,\n fixHint:\n urls.length === 1\n ? `Add \"${urls[0]}\" to the project, or update the mask-image URL to point to an existing texture mask.`\n : \"Add the missing texture mask files to the project, or update the mask-image URLs to point to existing files.\",\n },\n ];\n}\n\nfunction lintMultipleRootCompositions(projectDir: string): HyperframeLintFinding[] {\n const findings: HyperframeLintFinding[] = [];\n try {\n const rootHtmlFiles = readdirSync(projectDir).filter((f) => f.endsWith(\".html\"));\n const rootCompositions: string[] = [];\n for (const file of rootHtmlFiles) {\n if (file === \"caption-skin.html\") continue;\n const content = readFileSync(join(projectDir, file), \"utf-8\");\n if (/data-composition-id/i.test(content)) {\n rootCompositions.push(file);\n }\n }\n if (rootCompositions.length > 1) {\n findings.push({\n code: \"multiple_root_compositions\",\n severity: \"error\",\n message: `Multiple root-level HTML files with data-composition-id: ${rootCompositions.join(\", \")}. The runtime may discover both as entry points, causing duplicate audio playback.`,\n fixHint:\n \"A project should have exactly one root index.html with data-composition-id. Remove or rename extra files.\",\n });\n }\n } catch {\n /* directory read failed — skip */\n }\n return findings;\n}\n\nfunction lintDuplicateAudioTracks(htmlSources: HtmlSource[]): HyperframeLintFinding[] {\n const findings: HyperframeLintFinding[] = [];\n function extractAttr(tag: string, name: string): string | null {\n const re = new RegExp(`\\\\b${name}\\\\s*=\\\\s*[\"']([^\"']+)[\"']`, \"i\");\n const m = tag.match(re);\n return m?.[1] ?? null;\n }\n\n const tracks: Array<{ trackIndex: number; start: number; end: number; src: string }> = [];\n const seen = new Set<string>();\n\n for (const { html } of htmlSources) {\n const audioTagRe = /<audio\\b[^>]*>/gi;\n let match: RegExpExecArray | null;\n while ((match = audioTagRe.exec(html)) !== null) {\n const tag = match[0];\n const trackStr = extractAttr(tag, \"data-track-index\");\n const startStr = extractAttr(tag, \"data-start\");\n const durStr = extractAttr(tag, \"data-duration\");\n const src = extractAttr(tag, \"src\") ?? \"unknown\";\n if (!trackStr || !startStr) continue;\n\n const trackIndex = parseInt(trackStr, 10);\n const start = parseFloat(startStr);\n const duration = durStr ? parseFloat(durStr) : Infinity;\n const key = `${src}:${start}:${duration}:${trackIndex}`;\n if (seen.has(key)) continue;\n seen.add(key);\n\n tracks.push({ trackIndex, start, end: start + duration, src });\n }\n }\n\n for (let i = 0; i < tracks.length; i++) {\n for (let j = i + 1; j < tracks.length; j++) {\n const a = tracks[i]!;\n const b = tracks[j]!;\n if (a.trackIndex !== b.trackIndex) continue;\n if (a.start < b.end && b.start < a.end) {\n findings.push({\n code: \"duplicate_audio_track\",\n severity: \"warning\",\n message: `Multiple <audio> elements on track ${a.trackIndex} overlap (${a.src} at ${a.start}-${Number.isFinite(a.end) ? a.end.toFixed(1) : \"end\"}s, ${b.src} at ${b.start}-${Number.isFinite(b.end) ? b.end.toFixed(1) : \"end\"}s). This causes layered audio playback.`,\n fixHint: \"Use non-overlapping time windows or different track indices.\",\n });\n }\n }\n }\n return findings;\n}\n"],"mappings":"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","names":["escapeRegExp","selector","postcss","postcss"]}
1
+ {"version":3,"sources":["../src/utils.ts","../src/context.ts","../src/rules/core.ts","../src/rules/media.ts","../src/rules/gsap.ts","../src/rules/captions.ts","../src/rules/composition.ts","../src/rules/adapters.ts","../src/rules/textures.ts","../src/rules/fonts.ts","../src/rules/slideshow.ts","../src/hyperframeLinter.ts","../src/shouldBlockRender.ts","../src/project.ts"],"sourcesContent":["// Shared types, regex constants, and utility functions used across lint rule modules.\n// Nothing in this file should emit findings — it only parses and extracts.\n\nexport type OpenTag = {\n raw: string;\n name: string;\n attrs: string;\n index: number;\n};\n\nexport type ExtractedBlock = {\n attrs: string;\n content: string;\n raw: string;\n index: number;\n};\n\nconst TAG_PATTERN = /<([a-z][\\w:-]*)(\\s[^<>]*?)?>/gi;\nexport const STYLE_BLOCK_PATTERN = /<style\\b([^>]*)>([\\s\\S]*?)<\\/style>/gi;\nexport const SCRIPT_BLOCK_PATTERN = /<script\\b([^>]*)>([\\s\\S]*?)<\\/script>/gi;\nconst COMPOSITION_ID_IN_CSS_PATTERN = /\\[data-composition-id=[\"']([^\"']+)[\"']\\]/g;\nexport const TIMELINE_REGISTRY_INIT_PATTERN =\n /window\\.__timelines\\s*=\\s*window\\.__timelines\\s*\\|\\|\\s*\\{\\}|window\\.__timelines\\s*=\\s*\\{\\}|window\\.__timelines\\s*\\?\\?=\\s*\\{\\}/i;\nexport const TIMELINE_REGISTRY_ASSIGN_PATTERN =\n /window\\.__timelines(?:\\[[^\\]]+\\]|\\.[A-Za-z_$][\\w$]*)\\s*=/i;\nexport const WINDOW_TIMELINE_ASSIGN_PATTERN =\n /window\\.__timelines(?:\\[\\s*[\"']([^\"']+)[\"']\\s*\\]|\\.\\s*([A-Za-z_$][\\w$]*))\\s*=\\s*([A-Za-z_$][\\w$]*)/i;\nexport const INVALID_SCRIPT_CLOSE_PATTERN = /<script[^>]*>[\\s\\S]*?<\\s*\\/\\s*script(?!>)/i;\n\nconst TIMELINE_REGISTRY_KEY_PATTERN =\n /window\\.__timelines(?:\\[\\s*[\"']([^\"']+)[\"']\\s*\\]|\\.\\s*([A-Za-z_$][\\w$]*))\\s*=/g;\n\nexport function extractOpenTags(source: string): OpenTag[] {\n const tags: OpenTag[] = [];\n let match: RegExpExecArray | null;\n const pattern = new RegExp(TAG_PATTERN.source, TAG_PATTERN.flags);\n while ((match = pattern.exec(source)) !== null) {\n const raw = match[0];\n if (raw.startsWith(\"</\") || raw.startsWith(\"<!\")) continue;\n tags.push({\n raw,\n name: (match[1] || \"\").toLowerCase(),\n attrs: match[2] || \"\",\n index: match.index,\n });\n }\n return tags;\n}\n\nexport function extractBlocks(source: string, pattern: RegExp): ExtractedBlock[] {\n const blocks: ExtractedBlock[] = [];\n let match: RegExpExecArray | null;\n const p = new RegExp(pattern.source, pattern.flags);\n while ((match = p.exec(source)) !== null) {\n blocks.push({\n attrs: match[1] || \"\",\n content: match[2] || \"\",\n raw: match[0],\n index: match.index,\n });\n }\n return blocks;\n}\n\n/**\n * Find the `<html>` open tag in the source. Distinct from `findRootTag`,\n * which returns the first element inside `<body>` — the latter is \"the\n * composition's visible root\", whereas `<html>` is where document-level\n * metadata like `data-composition-variables` lives.\n */\nexport function findHtmlTag(source: string): OpenTag | null {\n const match = /<html\\b([^<>]*)>/i.exec(source);\n if (!match) return null;\n return {\n raw: match[0],\n name: \"html\",\n attrs: match[1] ?? \"\",\n index: match.index,\n };\n}\n\nexport function findRootTag(source: string): OpenTag | null {\n const bodyOpenMatch = /<body\\b([^>]*)>/i.exec(source);\n const bodyCloseMatch = /<\\/body>/i.exec(source);\n if (\n bodyOpenMatch &&\n (readAttr(bodyOpenMatch[0], \"data-composition-id\") ||\n readAttr(bodyOpenMatch[0], \"data-width\") ||\n readAttr(bodyOpenMatch[0], \"data-height\"))\n ) {\n return {\n raw: bodyOpenMatch[0],\n name: \"body\",\n attrs: bodyOpenMatch[1] ?? \"\",\n index: bodyOpenMatch.index,\n };\n }\n const bodyStart = bodyOpenMatch ? bodyOpenMatch.index + bodyOpenMatch[0].length : 0;\n const bodyEnd =\n bodyOpenMatch && bodyCloseMatch && bodyCloseMatch.index > bodyStart\n ? bodyCloseMatch.index\n : source.length;\n const bodyContent = bodyOpenMatch ? source.slice(bodyStart, bodyEnd) : source;\n const bodyTags = extractOpenTags(bodyContent);\n for (const tag of bodyTags) {\n if ([\"script\", \"style\", \"meta\", \"link\", \"title\"].includes(tag.name)) continue;\n return { ...tag, index: tag.index + bodyStart };\n }\n return null;\n}\n\nexport function readAttr(tagSource: string, attr: string): string | null {\n if (!tagSource) return null;\n const escaped = attr.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n const match = tagSource.match(new RegExp(`\\\\b${escaped}\\\\s*=\\\\s*[\"']([^\"']+)[\"']`, \"i\"));\n return match?.[1] || null;\n}\n\n/**\n * Read an attribute that may legitimately contain the opposite quote\n * character. `readAttr` truncates `data-variable-values='{\"title\":\"Hello\"}'`\n * at the first internal `\"` because its `[^\"']+` class excludes both quote\n * types. This variant alternates: a double-quoted value never contains an\n * unescaped `\"`, and a single-quoted value never contains an unescaped `'`,\n * so each branch can use a quote-specific class.\n *\n * Use for attributes whose values are JSON or otherwise carry the opposite\n * quote character. Existing single-token attributes (`id`, `class`, etc.)\n * stick with `readAttr` for consistency with the rest of the lint code.\n */\nexport function readJsonAttr(tagSource: string, attr: string): string | null {\n if (!tagSource) return null;\n const escaped = attr.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n const match = tagSource.match(new RegExp(`\\\\b${escaped}\\\\s*=\\\\s*(?:\"([^\"]*)\"|'([^']*)')`, \"i\"));\n if (!match) return null;\n return match[1] ?? match[2] ?? null;\n}\n\nexport function collectCompositionIds(tags: OpenTag[]): Set<string> {\n const ids = new Set<string>();\n for (const tag of tags) {\n const compId = readAttr(tag.raw, \"data-composition-id\");\n if (compId) ids.add(compId);\n }\n return ids;\n}\n\nexport function extractCompositionIdsFromCss(css: string): string[] {\n const ids = new Set<string>();\n let match: RegExpExecArray | null;\n const pattern = new RegExp(\n COMPOSITION_ID_IN_CSS_PATTERN.source,\n COMPOSITION_ID_IN_CSS_PATTERN.flags,\n );\n while ((match = pattern.exec(css)) !== null) {\n if (match[1]) ids.add(match[1]);\n }\n return [...ids];\n}\n\nexport function extractTimelineRegistryKeys(source: string): string[] {\n const keys = new Set<string>();\n let match: RegExpExecArray | null;\n const pattern = new RegExp(\n TIMELINE_REGISTRY_KEY_PATTERN.source,\n TIMELINE_REGISTRY_KEY_PATTERN.flags,\n );\n while ((match = pattern.exec(source)) !== null) {\n const key = match[1] ?? match[2];\n if (key) keys.add(key);\n }\n return [...keys];\n}\n\nexport function getInlineScriptSyntaxError(source: string): string | null {\n if (!source.trim()) return null;\n try {\n // eslint-disable-next-line no-new-func\n new Function(source);\n return null;\n } catch (error) {\n if (error instanceof Error) return error.message;\n return String(error);\n }\n}\n\n// fallow-ignore-next-line complexity\nexport function stripJsComments(source: string): string {\n let out = \"\";\n let i = 0;\n let quote: \"'\" | '\"' | \"`\" | null = null;\n let escaped = false;\n\n while (i < source.length) {\n const ch = source[i] ?? \"\";\n const next = source[i + 1] ?? \"\";\n\n if (quote) {\n out += ch;\n if (escaped) {\n escaped = false;\n } else if (ch === \"\\\\\") {\n escaped = true;\n } else if (ch === quote) {\n quote = null;\n }\n i += 1;\n continue;\n }\n\n if (ch === \"'\" || ch === '\"' || ch === \"`\") {\n quote = ch;\n out += ch;\n i += 1;\n continue;\n }\n\n if (ch === \"/\" && next === \"/\") {\n out += \" \";\n i += 2;\n while (i < source.length && source[i] !== \"\\n\" && source[i] !== \"\\r\") {\n out += \" \";\n i += 1;\n }\n continue;\n }\n\n if (ch === \"/\" && next === \"*\") {\n out += \" \";\n i += 2;\n while (i < source.length) {\n const blockCh = source[i] ?? \"\";\n const blockNext = source[i + 1] ?? \"\";\n if (blockCh === \"*\" && blockNext === \"/\") {\n out += \" \";\n i += 2;\n break;\n }\n out += blockCh === \"\\n\" || blockCh === \"\\r\" ? blockCh : \" \";\n i += 1;\n }\n continue;\n }\n\n out += ch;\n i += 1;\n }\n\n return out;\n}\n\n// One linear pass that drops every `<!-- … -->` region. Uses indexOf, not a\n// `/<!--[\\s\\S]*?-->/` regex: that pattern backtracks O(n²) on inputs with many\n// unterminated \"<!--\" (CodeQL js/polynomial-redos). An unterminated \"<!--\" with\n// no closing \"-->\" is kept verbatim, matching the prior regex's no-match behavior.\nfunction stripHtmlCommentsOnce(source: string): string {\n let out = \"\";\n let i = 0;\n for (;;) {\n const start = source.indexOf(\"<!--\", i);\n if (start < 0) return out + source.slice(i);\n const end = source.indexOf(\"-->\", start + 4);\n if (end < 0) return out + source.slice(i);\n out += source.slice(i, start);\n i = end + 3;\n }\n}\n\n// Strip HTML comments to a fixpoint. A single pass is not enough: deleting one\n// comment can splice adjacent markers into a fresh, complete <!-- … --> (e.g.\n// \"<<!-- -->!-- … -->\" → \"<!-- … -->\"), which would otherwise survive and let a\n// commented-out <template>/tag hijack the linter's tag scan.\nexport function stripHtmlComments(source: string): string {\n let out = source;\n for (let prev = \"\"; prev !== out; ) {\n prev = out;\n out = stripHtmlCommentsOnce(out);\n }\n return out;\n}\n\nexport function extractScriptTextsAndSrcs(scripts: ExtractedBlock[]): {\n texts: string[];\n srcs: string[];\n} {\n const texts = scripts.filter((s) => !/\\bsrc\\s*=/.test(s.attrs)).map((s) => s.content);\n const srcs = scripts.map((s) => readAttr(`<script ${s.attrs}>`, \"src\") || \"\").filter(Boolean);\n return { texts, srcs };\n}\n\nexport function isMediaTag(tagName: string): boolean {\n return tagName === \"video\" || tagName === \"audio\" || tagName === \"img\";\n}\n\nexport function truncateSnippet(value: string, maxLength = 220): string | undefined {\n const normalized = value.replace(/\\s+/g, \" \").trim();\n if (!normalized) return undefined;\n if (normalized.length <= maxLength) return normalized;\n return `${normalized.slice(0, maxLength - 3)}...`;\n}\n","import type { HyperframeLintFinding, HyperframeLinterOptions } from \"./types\";\nimport {\n extractBlocks,\n extractOpenTags,\n findRootTag,\n collectCompositionIds,\n readAttr,\n stripHtmlComments,\n STYLE_BLOCK_PATTERN,\n SCRIPT_BLOCK_PATTERN,\n} from \"./utils\";\nimport type { OpenTag, ExtractedBlock } from \"./utils\";\n\nexport type { OpenTag, ExtractedBlock };\n\nexport type LintContext = {\n source: string;\n rawSource: string;\n tags: OpenTag[];\n styles: ExtractedBlock[];\n scripts: ExtractedBlock[];\n compositionIds: Set<string>;\n rootTag: OpenTag | null;\n rootCompositionId: string | null;\n options: HyperframeLinterOptions;\n};\n\n// Re-export for convenience so rule modules only need one import for the finding type\nexport type { HyperframeLintFinding };\n\nexport function buildLintContext(html: string, options: HyperframeLinterOptions = {}): LintContext {\n const rawSource = html || \"\";\n // Strip HTML comments before scanning so a commented-out <template> or tag can't\n // hijack the boundary match below. Linear + fixpoint (see stripHtmlComments) to\n // stay ReDoS-free and catch markers that re-form when a comment is removed.\n let source = stripHtmlComments(rawSource);\n const templateMatch = source.match(/<template[^>]*>([\\s\\S]*)<\\/template>/i);\n if (templateMatch?.[1]) source = templateMatch[1];\n\n const tags = extractOpenTags(source);\n const styles = [\n ...extractBlocks(source, STYLE_BLOCK_PATTERN),\n ...(options.externalStyles ?? []).map((style) => ({\n attrs: `href=\"${style.href}\"`,\n content: style.content,\n raw: style.content,\n index: -1,\n })),\n ];\n const scripts = extractBlocks(source, SCRIPT_BLOCK_PATTERN);\n const compositionIds = collectCompositionIds(tags);\n const rootTag = findRootTag(source);\n const rootCompositionId = readAttr(rootTag?.raw || \"\", \"data-composition-id\");\n\n return {\n source,\n rawSource,\n tags,\n styles,\n scripts,\n compositionIds,\n rootTag,\n rootCompositionId,\n options,\n };\n}\n","import type { LintContext, HyperframeLintFinding } from \"../context\";\nimport postcss from \"postcss\";\nimport {\n readAttr,\n truncateSnippet,\n stripJsComments,\n extractCompositionIdsFromCss,\n extractTimelineRegistryKeys,\n getInlineScriptSyntaxError,\n TIMELINE_REGISTRY_INIT_PATTERN,\n TIMELINE_REGISTRY_ASSIGN_PATTERN,\n INVALID_SCRIPT_CLOSE_PATTERN,\n} from \"../utils\";\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\nfunction selectorTargetsCompositionId(selector: string, compositionId: string): boolean {\n const escaped = escapeRegExp(compositionId);\n return new RegExp(\n String.raw`\\[\\s*data-composition-id\\s*=\\s*(?:\"${escaped}\"|'${escaped}')\\s*\\]`,\n ).test(selector);\n}\n\nfunction isStudioTimelineElement(tag: { raw: string; name: string }): boolean {\n if ([\"script\", \"style\", \"link\", \"meta\", \"template\", \"noscript\"].includes(tag.name)) {\n return false;\n }\n return Boolean(\n readAttr(tag.raw, \"data-start\") ||\n readAttr(tag.raw, \"data-track-index\") ||\n readAttr(tag.raw, \"data-track\") ||\n readAttr(tag.raw, \"data-composition-src\") ||\n readAttr(tag.raw, \"data-composition-file\"),\n );\n}\n\nfunction describeStudioElement(tag: { raw: string; name: string }): string {\n const parts = [`<${tag.name}`];\n const className = readAttr(tag.raw, \"class\");\n const compositionId = readAttr(tag.raw, \"data-composition-id\");\n const dataStart = readAttr(tag.raw, \"data-start\");\n const dataTrack = readAttr(tag.raw, \"data-track-index\") ?? readAttr(tag.raw, \"data-track\");\n\n if (className) {\n const primaryClass = className\n .split(/\\s+/)\n .map((value) => value.trim())\n .find((value) => value && value !== \"clip\");\n if (primaryClass) parts.push(` class=\"${primaryClass}\"`);\n }\n if (compositionId) parts.push(` data-composition-id=\"${compositionId}\"`);\n if (dataStart) parts.push(` data-start=\"${dataStart}\"`);\n if (dataTrack) parts.push(` data-track-index=\"${dataTrack}\"`);\n parts.push(\">\");\n return parts.join(\"\");\n}\n\nconst HEAD_BLOCKS_TO_IGNORE_PATTERN =\n /<(?:style|script|template|title|noscript)\\b[^>]*>[\\s\\S]*?<\\/(?:style|script|template|title|noscript)(?:\\s[^>]*)?>/gi;\nconst HTML_TAG_PATTERN = /<[^>]+>/g;\nconst HEAD_CONTENT_PATTERN = /<head\\b[^>]*>([\\s\\S]*?)(?:<\\/head>|<body\\b|$)/gi;\nconst AFTER_HEAD_BEFORE_BODY_PATTERN = /<\\/head(?:\\s[^>]*)?>([\\s\\S]*?)(?=<body\\b|$)/gi;\nconst STRAY_HEAD_CLOSE_PATTERN = /<\\/(?:style|script)(?:\\s[^>]*)?>/i;\nconst MARKDOWN_CODE_FENCE_PATTERN = /```[^\\r\\n`]*(?:\\r?\\n|$)[\\s\\S]*?```/i;\nconst ORPHAN_CSS_AT_RULE_PATTERN =\n /(?:^|\\s)@(?:container|font-face|keyframes|layer|media|page|property|scope|supports)[^{<]*\\{[\\s\\S]*?:[\\s\\S]*?\\}/i;\nconst ORPHAN_CSS_RULE_PATTERN =\n /(?:^|\\s)(?:\\/\\*[\\s\\S]*?\\*\\/\\s*)?(?:@[a-z-]+[^{}<]*|[.#][\\w-]+[^{}<]*|[a-z][\\w-]*(?:\\s+[.#:[\\w-][^{}<]*)?)\\s*\\{[^{}]*:[^{}]*\\}/i;\n\nfunction findCodeFenceLeak(headWithoutValidBlocks: string): string | null {\n return MARKDOWN_CODE_FENCE_PATTERN.exec(headWithoutValidBlocks)?.[0] ?? null;\n}\n\nfunction findOrphanCssLeak(headContent: string): string | null {\n const residualText = headContent\n .replace(HEAD_BLOCKS_TO_IGNORE_PATTERN, \" \")\n .replace(HTML_TAG_PATTERN, \" \");\n return (\n ORPHAN_CSS_AT_RULE_PATTERN.exec(residualText)?.[0] ??\n ORPHAN_CSS_RULE_PATTERN.exec(residualText)?.[0] ??\n null\n );\n}\n\nfunction findStrayCloseLeak(headWithoutValidBlocks: string): string | null {\n return STRAY_HEAD_CLOSE_PATTERN.exec(headWithoutValidBlocks)?.[0] ?? null;\n}\n\nfunction findLeakedTextInHeadContent(headContent: string): string | null {\n const withoutValidBlocks = headContent.replace(HEAD_BLOCKS_TO_IGNORE_PATTERN, \" \");\n return (\n findCodeFenceLeak(withoutValidBlocks) ??\n findOrphanCssLeak(headContent) ??\n findStrayCloseLeak(withoutValidBlocks)\n );\n}\n\nfunction findLeakedTextInHead(rawSource: string): string | null {\n const headMatches = [...rawSource.matchAll(HEAD_CONTENT_PATTERN)];\n for (const match of headMatches) {\n const leakedText = findLeakedTextInHeadContent(match[1] ?? \"\");\n if (leakedText) return leakedText;\n }\n return null;\n}\n\nfunction findLeakedTextBetweenHeadAndBody(rawSource: string): string | null {\n const boundaryMatches = [...rawSource.matchAll(AFTER_HEAD_BEFORE_BODY_PATTERN)];\n for (const match of boundaryMatches) {\n const leakedText = findLeakedTextInHeadContent(match[1] ?? \"\");\n if (leakedText) return leakedText;\n }\n return null;\n}\n\nfunction findLeakedTextBeforeCompositionRoot(\n source: string,\n rootTag: LintContext[\"rootTag\"],\n): string | null {\n if (!rootTag || rootTag.name === \"body\") return null;\n const bodyOpenMatch = /<body\\b[^>]*>/i.exec(source);\n const prefixStart = bodyOpenMatch ? bodyOpenMatch.index + bodyOpenMatch[0].length : 0;\n const prefixEnd = rootTag.index;\n if (prefixEnd <= prefixStart) return null;\n return findLeakedTextInHeadContent(source.slice(prefixStart, prefixEnd));\n}\n\nexport const coreRules: Array<(ctx: LintContext) => HyperframeLintFinding[]> = [\n // root_missing_composition_id + root_missing_dimensions\n ({ rootTag }) => {\n const findings: HyperframeLintFinding[] = [];\n if (!rootTag || !readAttr(rootTag.raw, \"data-composition-id\")) {\n findings.push({\n code: \"root_missing_composition_id\",\n severity: \"error\",\n message: \"Root composition is missing `data-composition-id`.\",\n elementId: rootTag ? readAttr(rootTag.raw, \"id\") || undefined : undefined,\n fixHint: \"Add a stable `data-composition-id` to the entry composition wrapper.\",\n snippet: truncateSnippet(rootTag?.raw || \"\"),\n });\n }\n if (!rootTag || !readAttr(rootTag.raw, \"data-width\") || !readAttr(rootTag.raw, \"data-height\")) {\n findings.push({\n code: \"root_missing_dimensions\",\n severity: \"error\",\n message: \"Root composition is missing `data-width` or `data-height`.\",\n elementId: rootTag ? readAttr(rootTag.raw, \"id\") || undefined : undefined,\n fixHint: \"Set numeric `data-width` and `data-height` on the entry composition root.\",\n snippet: truncateSnippet(rootTag?.raw || \"\"),\n });\n }\n return findings;\n },\n\n // head_leaked_text\n ({ source, rootTag }) => {\n const snippet =\n findLeakedTextInHead(source) ??\n findLeakedTextBetweenHeadAndBody(source) ??\n findLeakedTextBeforeCompositionRoot(source, rootTag);\n if (!snippet) return [];\n return [\n {\n code: \"head_leaked_text\",\n severity: \"error\",\n message:\n \"Detected leaked code or CSS text around the document `<head>` or before the composition root. Browsers render this as visible text in the video.\",\n fixHint:\n \"Move CSS into a single `<style>...</style>` block and remove stray close tags, markdown fences, or code text from `<head>`, the `</head>`/`<body>` boundary, or the pre-root body prefix.\",\n snippet: truncateSnippet(snippet),\n },\n ];\n },\n\n // missing_timeline_registry + timeline_registry_missing_init\n ({ source, rawSource, options }) => {\n // Sub-compositions inherit window.__timelines from the host composition\n if (options.isSubComposition || rawSource.trimStart().toLowerCase().startsWith(\"<template\")) {\n return [];\n }\n const findings: HyperframeLintFinding[] = [];\n if (\n !TIMELINE_REGISTRY_INIT_PATTERN.test(source) &&\n !TIMELINE_REGISTRY_ASSIGN_PATTERN.test(source)\n ) {\n findings.push({\n code: \"missing_timeline_registry\",\n severity: \"error\",\n message: \"Missing `window.__timelines` registration.\",\n fixHint: \"Register each composition timeline on `window.__timelines[compositionId]`.\",\n });\n }\n if (\n TIMELINE_REGISTRY_ASSIGN_PATTERN.test(source) &&\n !TIMELINE_REGISTRY_INIT_PATTERN.test(source)\n ) {\n findings.push({\n code: \"timeline_registry_missing_init\",\n severity: \"error\",\n message:\n \"`window.__timelines[…] = …` is used without initializing `window.__timelines` first.\",\n fixHint:\n \"Add `window.__timelines = window.__timelines || {};` before any timeline assignment.\",\n });\n }\n return findings;\n },\n\n // timeline_id_mismatch\n ({ source }) => {\n const findings: HyperframeLintFinding[] = [];\n const htmlCompIds = new Set<string>();\n const timelineRegKeys = new Set<string>();\n const compIdRe = /data-composition-id\\s*=\\s*[\"']([^\"']+)[\"']/gi;\n let m: RegExpExecArray | null;\n while ((m = compIdRe.exec(source)) !== null) {\n if (m[1]) htmlCompIds.add(m[1]);\n }\n for (const key of extractTimelineRegistryKeys(source)) {\n timelineRegKeys.add(key);\n }\n for (const key of timelineRegKeys) {\n if (!htmlCompIds.has(key)) {\n findings.push({\n code: \"timeline_id_mismatch\",\n severity: \"error\",\n message: `Timeline registered as \"${key}\" but no element has data-composition-id=\"${key}\". The runtime cannot auto-nest this timeline.`,\n fixHint: `Change window.__timelines[\"${key}\"] to match the data-composition-id attribute, or vice versa.`,\n });\n }\n }\n return findings;\n },\n\n // invalid_inline_script_syntax (malformed close tag)\n ({ source }) => {\n if (!INVALID_SCRIPT_CLOSE_PATTERN.test(source)) return [];\n return [\n {\n code: \"invalid_inline_script_syntax\",\n severity: \"error\",\n message: \"Detected malformed inline `<script>` closing syntax.\",\n fixHint: \"Close inline scripts with a valid `</script>` tag.\",\n },\n ];\n },\n\n // invalid_inline_script_syntax (JS parse error)\n ({ scripts }) => {\n const findings: HyperframeLintFinding[] = [];\n for (const script of scripts) {\n const attrs = script.attrs || \"\";\n if (\n /\\bsrc\\s*=/.test(attrs) ||\n /\\btype\\s*=\\s*[\"'](?:application\\/json|application\\/hyperframes-slideshow\\+json|importmap|module)[\"']/.test(\n attrs,\n )\n )\n continue;\n const syntaxError = getInlineScriptSyntaxError(script.content);\n if (!syntaxError) continue;\n findings.push({\n code: \"invalid_inline_script_syntax\",\n severity: \"error\",\n message: `Inline script has invalid syntax: ${syntaxError}`,\n fixHint: \"Fix the inline script syntax before render verification.\",\n snippet: truncateSnippet(script.content),\n });\n }\n return findings;\n },\n\n // host_missing_composition_id\n ({ tags }) => {\n const findings: HyperframeLintFinding[] = [];\n for (const tag of tags) {\n const src = readAttr(tag.raw, \"data-composition-src\");\n if (!src) continue;\n if (readAttr(tag.raw, \"data-composition-id\")) continue;\n findings.push({\n code: \"host_missing_composition_id\",\n severity: \"error\",\n message: `Composition host for \"${src}\" is missing \\`data-composition-id\\`.`,\n elementId: readAttr(tag.raw, \"id\") || undefined,\n fixHint: \"Set `data-composition-id` on every `data-composition-src` host element.\",\n snippet: truncateSnippet(tag.raw),\n });\n }\n return findings;\n },\n\n // scoped_css_missing_wrapper\n ({ styles, compositionIds }) => {\n const findings: HyperframeLintFinding[] = [];\n const scopedCssCompositionIds = new Set<string>();\n for (const style of styles) {\n for (const compId of extractCompositionIdsFromCss(style.content)) {\n scopedCssCompositionIds.add(compId);\n }\n }\n for (const compId of scopedCssCompositionIds) {\n if (compositionIds.has(compId)) continue;\n findings.push({\n code: \"scoped_css_missing_wrapper\",\n severity: \"warning\",\n message: `Scoped CSS targets composition \"${compId}\" but no matching wrapper exists in this HTML.`,\n selector: `[data-composition-id=\"${compId}\"]`,\n fixHint:\n \"Preserve the matching composition wrapper or align the CSS scope to an existing wrapper.\",\n });\n }\n return findings;\n },\n\n // composition_self_attribute_selector\n ({ styles, rootCompositionId, rootTag }) => {\n const findings: HyperframeLintFinding[] = [];\n if (!rootCompositionId) return findings;\n const seenSelectors = new Set<string>();\n const rootId = readAttr(rootTag?.raw || \"\", \"id\");\n for (const style of styles) {\n let root: postcss.Root;\n try {\n root = postcss.parse(style.content);\n } catch {\n continue;\n }\n root.walkRules((rule) => {\n for (const selector of rule.selectors) {\n if (!selectorTargetsCompositionId(selector, rootCompositionId)) continue;\n if (seenSelectors.has(selector)) continue;\n seenSelectors.add(selector);\n findings.push({\n code: \"composition_self_attribute_selector\",\n severity: \"warning\",\n message:\n \"Selector matches the block's own id; will leak to sibling instances when the block is embedded twice.\",\n selector,\n fixHint: rootId\n ? `Use #${rootId} for clearer authoring intent and instance-isolated styling.`\n : \"Add a stable id to the composition root and use that id selector for clearer authoring intent and instance-isolated styling.\",\n });\n }\n });\n }\n return findings;\n },\n\n // studio_missing_editable_id\n ({ tags, rootTag }) => {\n const findings: HyperframeLintFinding[] = [];\n for (const tag of tags) {\n if (rootTag && tag.index === rootTag.index) continue;\n if (!isStudioTimelineElement(tag)) continue;\n if (readAttr(tag.raw, \"id\")) continue;\n\n const descriptor = describeStudioElement(tag);\n findings.push({\n code: \"studio_missing_editable_id\",\n severity: \"warning\",\n message: `${descriptor} has no id, so Studio cannot use a stable edit target for its timeline and canvas controls.`,\n selector: readAttr(tag.raw, \"data-composition-id\")\n ? `[data-composition-id=\"${readAttr(tag.raw, \"data-composition-id\")}\"]`\n : undefined,\n fixHint:\n 'Add a stable, human-readable id such as id=\"hero-title\" or id=\"scene-1-card\" to every timeline-visible element you want agents or Studio to edit.',\n snippet: truncateSnippet(tag.raw),\n });\n }\n return findings;\n },\n\n // non_deterministic_code\n ({ scripts }) => {\n const findings: HyperframeLintFinding[] = [];\n const patterns: Array<{ pattern: RegExp; label: string; hint: string }> = [\n {\n pattern: /Math\\.random\\s*\\(/,\n label: \"Math.random()\",\n hint: \"Use a seeded PRNG (e.g. a simple mulberry32) so renders are deterministic across frames.\",\n },\n {\n pattern: /Date\\.now\\s*\\(/,\n label: \"Date.now()\",\n hint: \"Remove time-dependent code. Use GSAP timeline position instead of wall-clock time.\",\n },\n {\n pattern: /new\\s+Date\\s*\\(/,\n label: \"new Date()\",\n hint: \"Remove time-dependent code. Use GSAP timeline position instead of wall-clock time.\",\n },\n {\n pattern: /performance\\.now\\s*\\(/,\n label: \"performance.now()\",\n hint: \"Remove time-dependent code. Use GSAP timeline position instead of wall-clock time.\",\n },\n {\n pattern: /crypto\\.getRandomValues\\s*\\(/,\n label: \"crypto.getRandomValues()\",\n hint: \"Remove time-dependent code. Use a seeded PRNG for deterministic renders.\",\n },\n ];\n\n for (const script of scripts) {\n const stripped = stripJsComments(script.content);\n for (const { pattern, label, hint } of patterns) {\n if (pattern.test(stripped)) {\n findings.push({\n code: \"non_deterministic_code\",\n severity: \"error\",\n message: `Script contains \\`${label}\\` which produces non-deterministic output. Renders may differ between frames or runs.`,\n fixHint: hint,\n snippet: truncateSnippet(script.content),\n });\n }\n }\n }\n return findings;\n },\n\n // pointer_events_none\n // fallow-ignore-next-line complexity\n ({ tags, styles }) => {\n const findings: HyperframeLintFinding[] = [];\n const reported = new Set<string>();\n\n for (const tag of tags) {\n if ([\"script\", \"style\", \"link\", \"meta\", \"template\", \"noscript\"].includes(tag.name)) continue;\n const inlineStyle = readAttr(tag.raw, \"style\") ?? \"\";\n if (!/pointer-events\\s*:\\s*none/i.test(inlineStyle)) continue;\n const id = readAttr(tag.raw, \"id\");\n const key = id ?? tag.raw;\n if (reported.has(key)) continue;\n reported.add(key);\n findings.push({\n code: \"pointer_events_none\",\n severity: \"info\",\n message: `<${tag.name}${id ? ` id=\"${id}\"` : \"\"}> has \\`pointer-events: none\\` in its inline style. Elements with this property are harder to select in the Studio preview.`,\n elementId: id || undefined,\n fixHint:\n \"If this element should be selectable in the Studio, remove `pointer-events: none` or move it to a wrapper that doesn't contain editable content.\",\n snippet: truncateSnippet(tag.raw),\n });\n }\n\n for (const style of styles) {\n let root: postcss.Root;\n try {\n root = postcss.parse(style.content);\n } catch {\n continue;\n }\n root.walkDecls(\"pointer-events\", (decl) => {\n if (decl.value.trim().toLowerCase() !== \"none\") return;\n const rule = decl.parent;\n if (!rule || rule.type !== \"rule\") return;\n const selector = (rule as postcss.Rule).selector;\n if (reported.has(selector)) return;\n reported.add(selector);\n findings.push({\n code: \"pointer_events_none\",\n severity: \"info\",\n message: `\\`${selector}\\` sets \\`pointer-events: none\\`. Elements matching this selector are harder to select in the Studio preview.`,\n selector,\n fixHint:\n \"If these elements should be selectable in the Studio, remove `pointer-events: none` or move it to a wrapper that doesn't contain editable content.\",\n });\n });\n }\n\n return findings;\n },\n];\n","import type { LintContext, HyperframeLintFinding } from \"../context\";\nimport { readAttr, truncateSnippet, isMediaTag } from \"../utils\";\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\nfunction hasAttrName(tagSource: string, attr: string): boolean {\n const escaped = escapeRegExp(attr);\n const attrs = tagSource.replace(/^<\\s*[a-z][\\w:-]*/i, \"\");\n return new RegExp(`(?:^|\\\\s)${escaped}(?:\\\\s*=|\\\\s|/?>)`, \"i\").test(attrs);\n}\n\nfunction classNamesFromAttr(classAttr: string | null): string[] {\n if (!classAttr) return [];\n return classAttr.split(/\\s+/).filter(Boolean);\n}\n\ntype MediaSelectorIndex = {\n ids: Set<string>;\n classes: Set<string>;\n hasVideo: boolean;\n hasAudio: boolean;\n};\n\nfunction selectorTargetsManagedMedia(selector: string, mediaIndex: MediaSelectorIndex): boolean {\n const normalized = selector.trim();\n if (!normalized) return false;\n if (mediaIndex.hasVideo && /\\bvideo\\b/i.test(normalized)) return true;\n if (mediaIndex.hasAudio && /\\baudio\\b/i.test(normalized)) return true;\n for (const mediaId of mediaIndex.ids) {\n const escapedId = escapeRegExp(mediaId);\n if (\n new RegExp(`#${escapedId}(?![\\\\w-])`).test(normalized) ||\n normalized.includes(`[id=\"${mediaId}\"]`) ||\n normalized.includes(`[id='${mediaId}']`)\n ) {\n return true;\n }\n }\n for (const className of mediaIndex.classes) {\n if (new RegExp(`\\\\.${escapeRegExp(className)}(?![\\\\w-])`).test(normalized)) {\n return true;\n }\n }\n return false;\n}\n\nfunction findImperativeMediaControlFindings(ctx: LintContext): HyperframeLintFinding[] {\n const findings: HyperframeLintFinding[] = [];\n const mediaTags = ctx.tags.filter((tag) => tag.name === \"video\" || tag.name === \"audio\");\n const mediaIndex: MediaSelectorIndex = {\n ids: new Set(\n mediaTags.map((tag) => readAttr(tag.raw, \"id\")).filter((id): id is string => Boolean(id)),\n ),\n classes: new Set(mediaTags.flatMap((tag) => classNamesFromAttr(readAttr(tag.raw, \"class\")))),\n hasVideo: mediaTags.some((tag) => tag.name === \"video\"),\n hasAudio: mediaTags.some((tag) => tag.name === \"audio\"),\n };\n\n if (mediaTags.length === 0 || ctx.scripts.length === 0) return findings;\n\n for (const script of ctx.scripts) {\n const mediaVars = new Map<string, string | undefined>();\n const assignmentPatterns = [\n {\n pattern:\n /\\b(?:const|let|var)\\s+([A-Za-z_$][\\w$]*)\\s*=\\s*(?:document|window\\.document)\\.getElementById\\(\\s*[\"']([^\"']+)[\"']\\s*\\)/g,\n variableIndex: 1,\n targetIndex: 2,\n },\n {\n pattern:\n /\\b(?:const|let|var)\\s+([A-Za-z_$][\\w$]*)\\s*=\\s*(?:document|window\\.document)\\.querySelector\\(\\s*([\"'])([\\s\\S]*?)\\2\\s*\\)/g,\n variableIndex: 1,\n targetIndex: 3,\n },\n ];\n\n for (const { pattern, variableIndex, targetIndex } of assignmentPatterns) {\n let match: RegExpExecArray | null;\n while ((match = pattern.exec(script.content)) !== null) {\n const variableName = match[variableIndex];\n const target = match[targetIndex];\n if (!variableName || !target) continue;\n if (mediaIndex.ids.has(target) || selectorTargetsManagedMedia(target, mediaIndex)) {\n mediaVars.set(variableName, mediaIndex.ids.has(target) ? target : undefined);\n }\n }\n }\n\n const directIdPatterns = [\n {\n pattern:\n /\\b(?:document|window\\.document)\\.getElementById\\(\\s*[\"']([^\"']+)[\"']\\s*\\)\\.play\\s*\\(/g,\n kind: \"play()\",\n targetIndex: 1,\n },\n {\n pattern:\n /\\b(?:document|window\\.document)\\.getElementById\\(\\s*[\"']([^\"']+)[\"']\\s*\\)\\.pause\\s*\\(/g,\n kind: \"pause()\",\n targetIndex: 1,\n },\n {\n pattern:\n /\\b(?:document|window\\.document)\\.getElementById\\(\\s*[\"']([^\"']+)[\"']\\s*\\)\\.currentTime\\s*=/g,\n kind: \"currentTime\",\n targetIndex: 1,\n },\n {\n pattern:\n /\\b(?:document|window\\.document)\\.getElementById\\(\\s*[\"']([^\"']+)[\"']\\s*\\)\\.muted\\s*=/g,\n kind: \"muted assignment\",\n targetIndex: 1,\n },\n {\n pattern:\n /\\b(?:document|window\\.document)\\.querySelector\\(\\s*([\"'])([\\s\\S]*?)\\1\\s*\\)\\.play\\s*\\(/g,\n kind: \"play()\",\n targetIndex: 2,\n },\n {\n pattern:\n /\\b(?:document|window\\.document)\\.querySelector\\(\\s*([\"'])([\\s\\S]*?)\\1\\s*\\)\\.pause\\s*\\(/g,\n kind: \"pause()\",\n targetIndex: 2,\n },\n {\n pattern:\n /\\b(?:document|window\\.document)\\.querySelector\\(\\s*([\"'])([\\s\\S]*?)\\1\\s*\\)\\.currentTime\\s*=/g,\n kind: \"currentTime\",\n targetIndex: 2,\n },\n {\n pattern:\n /\\b(?:document|window\\.document)\\.querySelector\\(\\s*([\"'])([\\s\\S]*?)\\1\\s*\\)\\.muted\\s*=/g,\n kind: \"muted assignment\",\n targetIndex: 2,\n },\n ];\n\n for (const { pattern, kind, targetIndex } of directIdPatterns) {\n let match: RegExpExecArray | null;\n while ((match = pattern.exec(script.content)) !== null) {\n const target = match[targetIndex];\n if (!target) continue;\n const elementId = mediaIndex.ids.has(target)\n ? target\n : selectorTargetsManagedMedia(target, mediaIndex)\n ? undefined\n : null;\n if (elementId === null) continue;\n findings.push({\n code: \"imperative_media_control\",\n severity: \"error\",\n message: `Inline <script> imperatively controls managed media via ${kind}. HyperFrames must own media play/pause/seek to keep preview, timeline, and renders deterministic.`,\n elementId: elementId || undefined,\n fixHint:\n \"Remove imperative media play/pause/currentTime/muted control. Express timing with data-start/data-duration and media offsets like data-media-start or data-playback-start instead.\",\n snippet: truncateSnippet(match[0]),\n });\n }\n }\n\n for (const [variableName, elementId] of mediaVars) {\n const escapedVar = escapeRegExp(variableName);\n const variablePatterns = [\n { pattern: new RegExp(`\\\\b${escapedVar}\\\\.play\\\\s*\\\\(`, \"g\"), kind: \"play()\" },\n { pattern: new RegExp(`\\\\b${escapedVar}\\\\.pause\\\\s*\\\\(`, \"g\"), kind: \"pause()\" },\n { pattern: new RegExp(`\\\\b${escapedVar}\\\\.currentTime\\\\s*=`, \"g\"), kind: \"currentTime\" },\n {\n pattern: new RegExp(`\\\\b${escapedVar}\\\\.muted\\\\s*=`, \"g\"),\n kind: \"muted assignment\",\n },\n ];\n for (const { pattern, kind } of variablePatterns) {\n let match: RegExpExecArray | null;\n while ((match = pattern.exec(script.content)) !== null) {\n findings.push({\n code: \"imperative_media_control\",\n severity: \"error\",\n message: `Inline <script> imperatively controls managed media via ${kind}. HyperFrames must own media play/pause/seek to keep preview, timeline, and renders deterministic.`,\n elementId,\n fixHint:\n \"Remove imperative media play/pause/currentTime/muted control. Express timing with data-start/data-duration and media offsets like data-media-start or data-playback-start instead.\",\n snippet: truncateSnippet(match[0]),\n });\n }\n }\n }\n }\n\n return findings;\n}\n\nexport const mediaRules: Array<(ctx: LintContext) => HyperframeLintFinding[]> = [\n // duplicate_media_id + duplicate_media_discovery_risk\n ({ tags }) => {\n const findings: HyperframeLintFinding[] = [];\n const mediaById = new Map<string, typeof tags>();\n const mediaFingerprintCounts = new Map<string, number>();\n\n for (const tag of tags) {\n if (!isMediaTag(tag.name)) continue;\n const elementId = readAttr(tag.raw, \"id\");\n if (elementId) {\n const existing = mediaById.get(elementId) || [];\n existing.push(tag);\n mediaById.set(elementId, existing);\n }\n const fingerprint = [\n tag.name,\n readAttr(tag.raw, \"src\") || \"\",\n readAttr(tag.raw, \"data-start\") || \"\",\n readAttr(tag.raw, \"data-duration\") || \"\",\n ].join(\"|\");\n mediaFingerprintCounts.set(fingerprint, (mediaFingerprintCounts.get(fingerprint) || 0) + 1);\n }\n\n for (const [elementId, mediaTags] of mediaById) {\n if (mediaTags.length < 2) continue;\n findings.push({\n code: \"duplicate_media_id\",\n severity: \"error\",\n message: `Media id \"${elementId}\" is defined multiple times.`,\n elementId,\n fixHint:\n \"Give each media element a unique id so preview and producer discover the same media graph.\",\n snippet: truncateSnippet(mediaTags[0]?.raw || \"\"),\n });\n }\n\n for (const [fingerprint, count] of mediaFingerprintCounts) {\n if (count < 2) continue;\n const [tagName, src, dataStart, dataDuration] = fingerprint.split(\"|\");\n findings.push({\n code: \"duplicate_media_discovery_risk\",\n severity: \"warning\",\n message: `Detected ${count} matching ${tagName} entries with the same source/start/duration.`,\n fixHint: \"Avoid duplicated media nodes that can be discovered twice during compilation.\",\n snippet: truncateSnippet(\n `${tagName} src=${src} data-start=${dataStart} data-duration=${dataDuration}`,\n ),\n });\n }\n return findings;\n },\n\n // video_missing_muted\n ({ tags }) => {\n const findings: HyperframeLintFinding[] = [];\n for (const tag of tags) {\n if (tag.name !== \"video\") continue;\n const hasMuted = hasAttrName(tag.raw, \"muted\");\n const hasDeclaredAudio = readAttr(tag.raw, \"data-has-audio\") === \"true\";\n if (!hasMuted && !hasDeclaredAudio && readAttr(tag.raw, \"data-start\")) {\n const elementId = readAttr(tag.raw, \"id\") || undefined;\n findings.push({\n code: \"video_missing_muted\",\n severity: \"error\",\n message: `<video${elementId ? ` id=\"${elementId}\"` : \"\"}> has data-start but is not muted. Mark audible videos with data-has-audio=\"true\"; otherwise keep video muted and use a separate <audio> element for sound.`,\n elementId,\n fixHint:\n 'Add the `muted` attribute for silent video, or add data-has-audio=\"true\" when the video track should contribute audio.',\n snippet: truncateSnippet(tag.raw),\n });\n }\n if (hasMuted && hasDeclaredAudio) {\n const elementId = readAttr(tag.raw, \"id\") || undefined;\n findings.push({\n code: \"video_muted_with_declared_audio\",\n severity: \"error\",\n message: `<video${elementId ? ` id=\"${elementId}\"` : \"\"}> declares data-has-audio=\"true\" but also has muted. Studio preview will silence the video audio.`,\n elementId,\n fixHint:\n 'Remove the `muted` attribute if this video should be audible, or remove data-has-audio=\"true\" and use data-volume=\"0\" for silent visual video.',\n snippet: truncateSnippet(tag.raw),\n });\n }\n }\n return findings;\n },\n\n // video_nested_in_timed_element\n ({ source, tags }) => {\n const findings: HyperframeLintFinding[] = [];\n // HTML5 void elements cannot contain children, so they can never be a\n // parent of a nested <video>. Skipping them avoids false positives where\n // the linter looks for `</img>` and never finds it.\n const voidElements = new Set([\n \"area\",\n \"base\",\n \"br\",\n \"col\",\n \"embed\",\n \"hr\",\n \"img\",\n \"input\",\n \"link\",\n \"meta\",\n \"source\",\n \"track\",\n \"wbr\",\n ]);\n const timedTagPositions: Array<{ name: string; start: number; id?: string }> = [];\n for (const tag of tags) {\n if (tag.name === \"video\" || tag.name === \"audio\") continue;\n if (voidElements.has(tag.name)) continue;\n // Skip the composition root — it uses data-start as a playback anchor, not as a clip timer\n if (readAttr(tag.raw, \"data-composition-id\")) continue;\n if (readAttr(tag.raw, \"data-start\")) {\n timedTagPositions.push({\n name: tag.name,\n start: tag.index,\n id: readAttr(tag.raw, \"id\") || undefined,\n });\n }\n }\n for (const tag of tags) {\n if (tag.name !== \"video\") continue;\n if (!readAttr(tag.raw, \"data-start\")) continue;\n for (const parent of timedTagPositions) {\n if (parent.start < tag.index) {\n const parentClosePattern = new RegExp(`</${parent.name}>`, \"gi\");\n const between = source.substring(parent.start, tag.index);\n if (!parentClosePattern.test(between)) {\n findings.push({\n code: \"video_nested_in_timed_element\",\n severity: \"error\",\n message: `<video> with data-start is nested inside <${parent.name}${parent.id ? ` id=\"${parent.id}\"` : \"\"}> which also has data-start. The framework cannot manage playback of nested media — video will be FROZEN in renders.`,\n elementId: readAttr(tag.raw, \"id\") || undefined,\n fixHint:\n \"Move the <video> to be a direct child of the stage, or remove data-start from the wrapper div (use it as a non-timed visual container).\",\n snippet: truncateSnippet(tag.raw),\n });\n break;\n }\n }\n }\n }\n return findings;\n },\n\n // media_in_subcomposition — <video>/<audio> only render as a DIRECT child of the host\n // root (index.html). Inside a sub-composition <template> the runtime never seeks/decodes\n // them, so they render BLANK/black in preview and renders — and the other lint/validate\n // passes otherwise miss it (only a per-frame snapshot reveals the blank panel).\n ({ tags, options }) => {\n const findings: HyperframeLintFinding[] = [];\n if (!options.isSubComposition) return findings;\n for (const tag of tags) {\n if (tag.name !== \"video\" && tag.name !== \"audio\") continue;\n const elementId = readAttr(tag.raw, \"id\") || undefined;\n findings.push({\n code: \"media_in_subcomposition\",\n severity: \"error\",\n message: `<${tag.name}${elementId ? ` id=\"${elementId}\"` : \"\"}> is inside a sub-composition. The runtime only drives media that is a DIRECT child of the host root (index.html); media inside a sub-comp <template> is never seeked/decoded and renders BLANK/black in preview and renders.`,\n elementId,\n fixHint:\n \"Move the media OUT of the sub-composition: place the <video>/<audio> as a direct child of #root in index.html, positioned over the scene, and drive any per-scene motion on the MAIN timeline at global time (a sub-comp timeline cannot reach host elements). See composition-patterns.md archetype B.\",\n snippet: truncateSnippet(tag.raw),\n });\n }\n return findings;\n },\n\n // self_closing_media_tag\n ({ source }) => {\n const findings: HyperframeLintFinding[] = [];\n const selfClosingMediaRe = /<(audio|video)\\b[^>]*\\/>/gi;\n let scMatch: RegExpExecArray | null;\n while ((scMatch = selfClosingMediaRe.exec(source)) !== null) {\n const tagName = scMatch[1] || \"audio\";\n const elementId = readAttr(scMatch[0], \"id\") || undefined;\n findings.push({\n code: \"self_closing_media_tag\",\n severity: \"error\",\n 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.`,\n elementId,\n fixHint: `Change <${tagName} .../> to <${tagName} ...></${tagName}> — media elements MUST have explicit closing tags.`,\n snippet: truncateSnippet(scMatch[0]),\n });\n }\n return findings;\n },\n\n // placeholder_media_url\n ({ tags }) => {\n const findings: HyperframeLintFinding[] = [];\n const PLACEHOLDER_DOMAINS =\n /\\b(placehold\\.co|placeholder\\.com|placekitten\\.com|picsum\\.photos|example\\.com|via\\.placeholder\\.com|dummyimage\\.com)\\b/i;\n for (const tag of tags) {\n if (!isMediaTag(tag.name)) continue;\n const src = readAttr(tag.raw, \"src\");\n if (!src) continue;\n if (PLACEHOLDER_DOMAINS.test(src)) {\n const elementId = readAttr(tag.raw, \"id\") || undefined;\n findings.push({\n code: \"placeholder_media_url\",\n severity: \"error\",\n message: `<${tag.name}${elementId ? ` id=\"${elementId}\"` : \"\"}> uses a placeholder URL that will 404 at render time: ${src.slice(0, 80)}`,\n elementId,\n fixHint: \"Replace with a real media URL. Placeholder domains will 404 at render time.\",\n snippet: truncateSnippet(tag.raw),\n });\n }\n }\n return findings;\n },\n\n // base64_media_prohibited\n ({ source }) => {\n const findings: HyperframeLintFinding[] = [];\n const base64MediaRe =\n /src\\s*=\\s*[\"'](data:(?:audio|video)\\/[^;]+;base64,([A-Za-z0-9+/=]{20,}))[\"']/gi;\n let b64Match: RegExpExecArray | null;\n while ((b64Match = base64MediaRe.exec(source)) !== null) {\n const sample = (b64Match[2] || \"\").slice(0, 200);\n const uniqueChars = new Set(sample.replace(/[A-Za-z0-9+/=]/g, (c) => c)).size;\n const dataSize = Math.round(((b64Match[2] || \"\").length * 3) / 4);\n const isSuspicious = uniqueChars < 15 || (dataSize > 1000 && dataSize < 50000);\n findings.push({\n code: \"base64_media_prohibited\",\n severity: \"error\",\n message: `Inline base64 audio/video detected (${(dataSize / 1024).toFixed(0)} KB)${isSuspicious ? \" — likely fabricated data\" : \"\"}. Base64 media is prohibited — it bloats file size and breaks rendering.`,\n fixHint:\n \"Use a relative path (assets/music.mp3) or HTTPS URL for the audio/video src. Never embed media as base64.\",\n snippet: truncateSnippet((b64Match[1] ?? \"\").slice(0, 80) + \"...\"),\n });\n }\n return findings;\n },\n\n // media_missing_data_start + media_missing_id + media_missing_src + media_preload_none\n ({ tags }) => {\n const findings: HyperframeLintFinding[] = [];\n for (const tag of tags) {\n if (tag.name !== \"video\" && tag.name !== \"audio\") continue;\n const hasDataStart = readAttr(tag.raw, \"data-start\");\n const hasId = readAttr(tag.raw, \"id\");\n const hasSrc = readAttr(tag.raw, \"src\");\n if (hasSrc && !hasDataStart) {\n findings.push({\n code: \"media_missing_data_start\",\n severity: \"error\",\n message: `<${tag.name}${hasId ? ` id=\"${hasId}\"` : \"\"}> has src but no data-start. HyperFrames cannot own playback for untimed media, so preview and render behavior can diverge.`,\n elementId: hasId || undefined,\n fixHint: `Add data-start=\"0\" (or the intended start time) and data-duration if the clip should stop before the source ends.`,\n snippet: truncateSnippet(tag.raw),\n });\n }\n if (hasDataStart && !hasId) {\n findings.push({\n code: \"media_missing_id\",\n severity: \"error\",\n message: `<${tag.name}> has data-start but no id attribute. The renderer requires id to discover media elements — this ${tag.name === \"audio\" ? \"audio will be SILENT\" : \"video will be FROZEN\"} in renders.`,\n fixHint: `Add a unique id attribute: <${tag.name} id=\"my-${tag.name}\" ...>`,\n snippet: truncateSnippet(tag.raw),\n });\n }\n if (hasDataStart && hasId && !hasSrc) {\n findings.push({\n code: \"media_missing_src\",\n severity: \"error\",\n message: `<${tag.name} id=\"${hasId}\"> has data-start but no src attribute. The renderer cannot load this media.`,\n elementId: hasId,\n fixHint: `Add a src attribute to the <${tag.name}> element directly. If using <source> children, the renderer still requires src on the parent element.`,\n snippet: truncateSnippet(tag.raw),\n });\n }\n if (readAttr(tag.raw, \"preload\") === \"none\") {\n findings.push({\n code: \"media_preload_none\",\n severity: \"warning\",\n message: `<${tag.name}${hasId ? ` id=\"${hasId}\"` : \"\"}> has preload=\"none\" which prevents the renderer from loading this media. The compiler strips it for renders, but preview may also have issues.`,\n elementId: hasId || undefined,\n fixHint: `Remove preload=\"none\" or change to preload=\"auto\". The framework manages media loading.`,\n snippet: truncateSnippet(tag.raw),\n });\n }\n }\n return findings;\n },\n\n // video_audio_double_source — catches audible <video> paired with a separate\n // <audio> pointing to the same file, which causes double playback at runtime\n ({ tags }) => {\n const findings: HyperframeLintFinding[] = [];\n const videoSources = new Map<string, { id?: string; raw: string }>();\n const audioSources = new Map<string, { id?: string; raw: string }>();\n\n for (const tag of tags) {\n if (!readAttr(tag.raw, \"data-start\")) continue;\n const src = readAttr(tag.raw, \"src\");\n if (!src) continue;\n const elementId = readAttr(tag.raw, \"id\") || undefined;\n if (tag.name === \"video\") {\n const isMuted = hasAttrName(tag.raw, \"muted\");\n if (!isMuted) {\n videoSources.set(src, { id: elementId, raw: tag.raw });\n }\n } else if (tag.name === \"audio\") {\n audioSources.set(src, { id: elementId, raw: tag.raw });\n }\n }\n\n for (const [src, audioInfo] of audioSources) {\n const videoInfo = videoSources.get(src);\n if (!videoInfo) continue;\n findings.push({\n code: \"video_audio_double_source\",\n severity: \"error\",\n message: `<audio${audioInfo.id ? ` id=\"${audioInfo.id}\"` : \"\"}> and <video${videoInfo.id ? ` id=\"${videoInfo.id}\"` : \"\"}> both point to the same source. The unmuted video already provides audio — the duplicate <audio> will cause double playback and echo.`,\n elementId: audioInfo.id,\n fixHint:\n \"Either mute the video (add `muted` attribute) and keep the separate <audio>, or remove the <audio> element and let the video provide its own audio track.\",\n snippet: truncateSnippet(audioInfo.raw),\n });\n }\n return findings;\n },\n\n // imperative_media_control\n findImperativeMediaControlFindings,\n];\n","interface LintParsedGsap {\n animations: Array<{\n targetSelector: string;\n method: string;\n position: number | string;\n properties: Record<string, number | string>;\n duration?: number;\n ease?: string;\n extras?: Record<string, unknown>;\n }>;\n timelineVar: string;\n}\n\n// Use the acorn read parser: it resolves computed timelines (helpers, bounded\n// loops) so lint findings like overlapping_gsap_tweens reflect true positions\n// instead of all-collapsed-at-0. It's also browser-safe, so this keeps recast\n// out of the lint graph entirely. Dynamic import preserves the lazy load.\nasync function loadParseGsapScript(): Promise<(script: string) => LintParsedGsap> {\n const mod = await import(\"@hyperframes/parsers/gsap-parser-acorn\");\n return mod.parseGsapScriptAcorn as unknown as (script: string) => LintParsedGsap;\n}\nimport type { LintContext } from \"../context\";\nimport type { HyperframeLintFinding, LintRule } from \"../types\";\nimport type { OpenTag } from \"../utils\";\nimport {\n readAttr,\n truncateSnippet,\n stripJsComments,\n WINDOW_TIMELINE_ASSIGN_PATTERN,\n} from \"../utils\";\n\n// ── GSAP-specific types ────────────────────────────────────────────────────\n\ntype GsapWindow = {\n targetSelector: string;\n position: number;\n end: number;\n properties: string[];\n propertyValues: Record<string, string | number>;\n overwriteAuto: boolean;\n method: string;\n raw: string;\n};\n\ntype CompositionRange = {\n id: string;\n start: number;\n end: number;\n};\n\nconst SCENE_BOUNDARY_EPSILON_SECONDS = 0.05;\n\n// ── GSAP parsing utilities ─────────────────────────────────────────────────\n\nfunction countClassUsage(tags: OpenTag[]): Map<string, number> {\n const counts = new Map<string, number>();\n for (const tag of tags) {\n const classAttr = readAttr(tag.raw, \"class\");\n if (!classAttr) continue;\n for (const className of classAttr.split(/\\s+/).filter(Boolean)) {\n counts.set(className, (counts.get(className) || 0) + 1);\n }\n }\n return counts;\n}\n\nfunction readRegisteredTimelineCompositionId(script: string): string | null {\n const match = script.match(WINDOW_TIMELINE_ASSIGN_PATTERN);\n return match?.[1] || match?.[2] || null;\n}\n\n/** Strip a `__raw:` prefix the parser adds to unresolvable values. */\nfunction unwrapRaw(value: unknown): string | number | undefined {\n if (typeof value === \"number\") return value;\n if (typeof value !== \"string\") return undefined;\n const code = value.startsWith(\"__raw:\") ? value.slice(6) : value;\n return code.replace(/^\\s*[\"']|[\"']\\s*$/g, \"\");\n}\n\nfunction extrasNumber(value: unknown): number {\n const unwrapped = unwrapRaw(value);\n const numeric = typeof unwrapped === \"number\" ? unwrapped : Number(unwrapped);\n return Number.isFinite(numeric) ? numeric : 0;\n}\n\n/** A readable single-line snippet of a tween for finding messages. */\nfunction synthesizeWindowRaw(\n timelineVar: string,\n anim: LintParsedGsap[\"animations\"][number],\n): string {\n const entries = Object.entries(anim.properties).map(([k, v]) => {\n if (typeof v === \"string\" && v.startsWith(\"__raw:\")) return `${k}: ${v.slice(6)}`;\n return `${k}: ${typeof v === \"string\" ? JSON.stringify(v) : v}`;\n });\n if (anim.duration !== undefined) entries.push(`duration: ${anim.duration}`);\n if (anim.ease) entries.push(`ease: ${JSON.stringify(anim.ease)}`);\n const pos = typeof anim.position === \"number\" ? anim.position : JSON.stringify(anim.position);\n return `${timelineVar}.${anim.method}(\"${anim.targetSelector}\", { ${entries.join(\", \")} }, ${pos})`;\n}\n\nconst gsapWindowsCache = new Map<string, GsapWindow[]>();\n\nasync function cachedExtractGsapWindows(scriptContent: string): Promise<GsapWindow[]> {\n const cached = gsapWindowsCache.get(scriptContent);\n if (cached) return cached;\n const windows = await extractGsapWindows(scriptContent);\n gsapWindowsCache.set(scriptContent, windows);\n return windows;\n}\n\n// fallow-ignore-next-line complexity\nasync function extractGsapWindows(script: string): Promise<GsapWindow[]> {\n if (!/gsap\\.timeline/.test(script)) return [];\n const parseGsapScript = await loadParseGsapScript();\n const parsed = parseGsapScript(script);\n if (parsed.animations.length === 0) return [];\n\n const windows: GsapWindow[] = [];\n for (const animation of parsed.animations) {\n // Skip animations with string positions (e.g. \"+=1\", \"<\") — their absolute\n // timing depends on runtime evaluation and can't be statically linted.\n if (typeof animation.position !== \"number\") continue;\n const repeat = extrasNumber(animation.extras?.repeat);\n const cycleCount = repeat > 0 ? repeat + 1 : 1;\n const effectiveDuration =\n animation.method === \"set\" ? 0 : (animation.duration ?? 0) * cycleCount;\n windows.push({\n targetSelector: animation.targetSelector,\n position: animation.position,\n end: animation.position + effectiveDuration,\n properties: Object.keys(animation.properties),\n propertyValues: animation.properties,\n overwriteAuto: unwrapRaw(animation.extras?.overwrite) === \"auto\",\n method: animation.method,\n raw: synthesizeWindowRaw(parsed.timelineVar, animation),\n });\n }\n return windows;\n}\n\nfunction numberValue(value: string | number | undefined): number | null {\n if (typeof value === \"number\") return value;\n if (typeof value === \"string\" && value.trim()) {\n const numeric = Number(value);\n return Number.isFinite(numeric) ? numeric : null;\n }\n return null;\n}\n\nfunction stringValue(value: string | number | undefined): string | null {\n if (typeof value === \"string\") return value;\n if (typeof value === \"number\") return String(value);\n return null;\n}\n\nfunction zeroValue(value: string | number | undefined): boolean {\n if (typeof value === \"number\") return value === 0;\n if (typeof value !== \"string\") return false;\n return Number(value.trim()) === 0;\n}\n\nfunction isHiddenGsapState(values: Record<string, string | number>): boolean {\n const visibility = stringValue(values.visibility)?.toLowerCase();\n const display = stringValue(values.display)?.toLowerCase();\n return (\n zeroValue(values.opacity) ||\n zeroValue(values.autoAlpha) ||\n visibility === \"hidden\" ||\n display === \"none\"\n );\n}\n\nfunction oneValue(\n values: Record<string, string | number>,\n keys: string[],\n): string | number | undefined {\n for (const key of keys) {\n const value = values[key];\n if (value !== undefined) return value;\n }\n return undefined;\n}\n\nfunction isVisibleGsapState(values: Record<string, string | number>): boolean {\n const opacity = oneValue(values, [\"opacity\", \"autoAlpha\"]);\n if (typeof opacity === \"number\") return opacity > 0;\n if (typeof opacity === \"string\" && opacity.trim()) {\n const numeric = Number(opacity);\n if (Number.isFinite(numeric)) return numeric > 0;\n }\n\n const visibility = stringValue(values.visibility)?.toLowerCase();\n if (visibility === \"visible\" || visibility === \"inherit\") return true;\n\n const display = stringValue(values.display)?.toLowerCase();\n if (display && display !== \"none\") return true;\n\n return false;\n}\n\nfunction makesOverlayVisible(win: GsapWindow): boolean {\n if (win.method === \"from\" && isHiddenGsapState(win.propertyValues)) return true;\n return isVisibleGsapState(win.propertyValues);\n}\n\nfunction isSceneBoundaryExit(win: GsapWindow): boolean {\n if (win.end <= win.position) return false;\n if (win.method !== \"to\" && win.method !== \"fromTo\") return false;\n return isHiddenGsapState(win.propertyValues);\n}\n\nfunction isHardKillSet(win: GsapWindow, selector: string, boundary: number): boolean {\n return (\n win.method === \"set\" &&\n win.targetSelector === selector &&\n Math.abs(win.position - boundary) <= SCENE_BOUNDARY_EPSILON_SECONDS &&\n isHiddenGsapState(win.propertyValues)\n );\n}\n\nfunction hiddenStateLiteral(values: Record<string, string | number>): string {\n if (zeroValue(values.autoAlpha)) return \"{ autoAlpha: 0 }\";\n if (zeroValue(values.opacity)) return \"{ opacity: 0 }\";\n if (stringValue(values.visibility)?.toLowerCase() === \"hidden\") return '{ visibility: \"hidden\" }';\n if (stringValue(values.display)?.toLowerCase() === \"none\") return '{ display: \"none\" }';\n return \"{ opacity: 0 }\";\n}\n\nfunction findTagEnd(source: string, tag: OpenTag): number {\n const escapedTagName = tag.name.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n const pattern = new RegExp(`<\\\\/?${escapedTagName}\\\\b[^>]*>`, \"gi\");\n pattern.lastIndex = tag.index;\n\n let depth = 0;\n let match: RegExpExecArray | null;\n while ((match = pattern.exec(source)) !== null) {\n const raw = match[0];\n const isClosing = /^<\\s*\\//.test(raw);\n const isSelfClosing = /\\/\\s*>$/.test(raw);\n if (!isClosing && !isSelfClosing) depth += 1;\n if (isClosing) depth -= 1;\n if (depth === 0) return pattern.lastIndex;\n }\n\n return source.length;\n}\n\nfunction collectCompositionRanges(source: string, tags: OpenTag[]): CompositionRange[] {\n return tags\n .map((tag) => {\n const id = readAttr(tag.raw, \"data-composition-id\");\n if (!id) return null;\n return {\n id,\n start: tag.index,\n end: findTagEnd(source, tag),\n };\n })\n .filter((range) => range !== null);\n}\n\nfunction findContainingCompositionId(tag: OpenTag, ranges: CompositionRange[]): string | null {\n let match: CompositionRange | null = null;\n for (const range of ranges) {\n if (tag.index < range.start || tag.index >= range.end) continue;\n if (!match || range.start >= match.start) match = range;\n }\n return match?.id || null;\n}\n\nfunction collectClipStartBoundariesByComposition(\n source: string,\n tags: OpenTag[],\n): Map<string, number[]> {\n const ranges = collectCompositionRanges(source, tags);\n const boundaries = new Map<string, Set<number>>();\n\n for (const tag of tags) {\n const classAttr = readAttr(tag.raw, \"class\") || \"\";\n const classes = classAttr.split(/\\s+/).filter(Boolean);\n if (!classes.includes(\"clip\")) continue;\n const compositionId = findContainingCompositionId(tag, ranges);\n if (!compositionId) continue;\n const start = numberValue(readAttr(tag.raw, \"data-start\") ?? undefined);\n if (start == null || start <= 0) continue;\n const compositionBoundaries = boundaries.get(compositionId) ?? new Set<number>();\n compositionBoundaries.add(start);\n boundaries.set(compositionId, compositionBoundaries);\n }\n\n return new Map(\n [...boundaries.entries()].map(([compositionId, values]) => [\n compositionId,\n [...values].sort((a, b) => a - b),\n ]),\n );\n}\n\nfunction findMatchingSceneBoundary(time: number, boundaries: number[]): number | null {\n for (const boundary of boundaries) {\n if (Math.abs(time - boundary) <= SCENE_BOUNDARY_EPSILON_SECONDS) return boundary;\n }\n return null;\n}\n\nfunction isSuspiciousGlobalSelector(selector: string): boolean {\n if (!selector) return false;\n if (selector.includes(\"[data-composition-id=\")) return false;\n if (selector.startsWith(\"#\")) return false;\n return selector.startsWith(\".\") || /^[a-z]/i.test(selector);\n}\n\nfunction getSingleClassSelector(selector: string): string | null {\n const match = selector.trim().match(/^\\.(?<name>[A-Za-z0-9_-]+)$/);\n return match?.groups?.name || null;\n}\n\nfunction readStyleProperty(style: string, property: string): string | null {\n const escapedProperty = property.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n const match = style.match(new RegExp(`(?:^|;)\\\\s*${escapedProperty}\\\\s*:\\\\s*([^;]+)`, \"i\"));\n return match?.[1]?.trim() || null;\n}\n\nfunction cssZero(value: string | null): boolean {\n if (!value) return false;\n return /^0(?:\\.0+)?(?:px|%|vw|vh|rem|em)?$/i.test(value.trim());\n}\n\nfunction styleHasHiddenInitialState(style: string): boolean {\n const opacity = readStyleProperty(style, \"opacity\");\n if (opacity && Number(opacity) === 0) return true;\n if (readStyleProperty(style, \"visibility\")?.toLowerCase() === \"hidden\") return true;\n if (readStyleProperty(style, \"display\")?.toLowerCase() === \"none\") return true;\n return false;\n}\n\nfunction styleHasOpaqueBackground(style: string): boolean {\n const background =\n readStyleProperty(style, \"background\") || readStyleProperty(style, \"background-color\");\n if (!background) return false;\n const normalized = background.toLowerCase().replace(/\\s+/g, \"\");\n if (normalized === \"transparent\" || normalized === \"none\") return false;\n if (/rgba?\\([^)]*,0(?:\\.0+)?\\)$/.test(normalized)) return false;\n if (/hsla?\\([^)]*,0(?:\\.0+)?\\)$/.test(normalized)) return false;\n return true;\n}\n\nfunction styleLooksFullFrameOverlay(style: string): boolean {\n const position = readStyleProperty(style, \"position\")?.toLowerCase();\n if (position !== \"fixed\" && position !== \"absolute\") return false;\n const coversFrame =\n cssZero(readStyleProperty(style, \"inset\")) ||\n (cssZero(readStyleProperty(style, \"top\")) &&\n cssZero(readStyleProperty(style, \"right\")) &&\n cssZero(readStyleProperty(style, \"bottom\")) &&\n cssZero(readStyleProperty(style, \"left\")));\n return coversFrame && styleHasOpaqueBackground(style);\n}\n\nfunction collectSimpleStyleRules(styles: LintContext[\"styles\"]): Map<string, string> {\n const rules = new Map<string, string>();\n for (const style of styles) {\n for (const [, selectorList, body] of style.content.matchAll(/([^{}]+)\\{([^}]+)\\}/g)) {\n if (!selectorList || !body) continue;\n for (const selector of selectorList.split(\",\")) {\n const token = selector.trim();\n if (!/^[#.][A-Za-z0-9_-]+$/.test(token)) continue;\n rules.set(token, `${rules.get(token) || \"\"};${body}`);\n }\n }\n }\n return rules;\n}\n\nfunction tagSimpleSelectors(tag: OpenTag): string[] {\n const selectors: string[] = [];\n const id = readAttr(tag.raw, \"id\");\n if (id) selectors.push(`#${id}`);\n const classes = readAttr(tag.raw, \"class\")?.split(/\\s+/).filter(Boolean) ?? [];\n for (const className of classes) selectors.push(`.${className}`);\n return selectors;\n}\n\nfunction combinedTagStyle(tag: OpenTag, styleRules: Map<string, string>): string {\n const styles = [readAttr(tag.raw, \"style\") || \"\"];\n for (const selector of tagSimpleSelectors(tag)) {\n const ruleStyle = styleRules.get(selector);\n if (ruleStyle) styles.push(ruleStyle);\n }\n return styles.filter(Boolean).join(\";\");\n}\n\n// fallow-ignore-next-line complexity\nfunction cssTransformToGsapProps(cssTransform: string): string | null {\n const parts: string[] = [];\n\n // translate(-50%, -50%) or translate(X, Y)\n const translateMatch = cssTransform.match(\n /translate\\(\\s*(-?[\\d.]+)(%|px)?\\s*,\\s*(-?[\\d.]+)(%|px)?\\s*\\)/,\n );\n if (translateMatch) {\n const [, xVal, xUnit, yVal, yUnit] = translateMatch;\n if (xUnit === \"%\") parts.push(`xPercent: ${xVal}`);\n else parts.push(`x: ${xVal}`);\n if (yUnit === \"%\") parts.push(`yPercent: ${yVal}`);\n else parts.push(`y: ${yVal}`);\n }\n\n // translateX(-50%) or translateX(px)\n const txMatch = cssTransform.match(/translateX\\(\\s*(-?[\\d.]+)(%|px)?\\s*\\)/);\n if (txMatch) {\n const [, val, unit] = txMatch;\n parts.push(unit === \"%\" ? `xPercent: ${val}` : `x: ${val}`);\n }\n\n // translateY(-50%) or translateY(px)\n const tyMatch = cssTransform.match(/translateY\\(\\s*(-?[\\d.]+)(%|px)?\\s*\\)/);\n if (tyMatch) {\n const [, val, unit] = tyMatch;\n parts.push(unit === \"%\" ? `yPercent: ${val}` : `y: ${val}`);\n }\n\n // scale(N)\n const scaleMatch = cssTransform.match(/scale\\(\\s*([\\d.]+)\\s*\\)/);\n if (scaleMatch) {\n parts.push(`scale: ${scaleMatch[1]}`);\n }\n\n return parts.length > 0 ? parts.join(\", \") : null;\n}\n\n// ── CSS-transform ↔ GSAP-transform conflict matching ─────────────────────────\n\n// Transform components that COMBINE with a CSS translate/scale on the same\n// element. GSAP bakes the element's existing CSS transform in when it seeks, so\n// these stack rather than override in the capture path (e.g. CSS translateX(-50%)\n// + xPercent:-50 renders as -100% — off-centre). `rotation` is excluded: it maps\n// to CSS rotate(), which this rule treats separately (no false positive on spin).\nconst CONFLICTING_TRANSLATE_PROPS = [\"x\", \"y\", \"xPercent\", \"yPercent\"];\nconst CONFLICTING_SCALE_PROPS = [\"scale\", \"scaleX\", \"scaleY\"];\n\ntype GsapTransformCall = {\n method: string;\n selector: string;\n properties: string[];\n raw: string;\n};\n\n// Decompose a (possibly grouped / descendant / compound) GSAP target selector\n// into the simple `#id` / `.class` tokens of the elements it actually targets —\n// the RIGHTMOST compound of each comma group is the targeted element. This lets a\n// CSS rule keyed by a simple selector (`.m04-label`) match a scoped GSAP selector\n// (`\"#root .m04-label, #root .m04-sub\"`), which the prior exact-string lookup\n// missed — so every scoped/grouped selector slipped past the rule entirely.\nfunction targetedSelectorTokens(selector: string): Set<string> {\n const tokens = new Set<string>();\n for (const group of selector.split(\",\")) {\n const compounds = group\n .trim()\n .split(/[\\s>+~]+/)\n .filter(Boolean);\n const last = compounds[compounds.length - 1];\n if (!last) continue;\n const simple = last.match(/[#.][A-Za-z0-9_-]+/g);\n if (simple) for (const token of simple) tokens.add(token);\n }\n return tokens;\n}\n\n// Find a CSS transform conflicting with a GSAP target selector: exact-string\n// match first (fast path + back-compat with the original behaviour), then a\n// token match so scoped/grouped/descendant selectors resolve to their class/id.\nfunction matchCssTransform(gsapSelector: string, cssMap: Map<string, string>): string | undefined {\n if (cssMap.size === 0) return undefined;\n const direct = cssMap.get(gsapSelector);\n if (direct) return direct;\n const tokens = targetedSelectorTokens(gsapSelector);\n for (const [cssSelector, value] of cssMap) {\n if (tokens.has(cssSelector)) return value;\n }\n return undefined;\n}\n\n// Scan for STANDALONE `gsap.set/to/from/fromTo(\"selector\", { ...props })` calls.\n// The acorn timeline parser only captures calls rooted on the timeline var\n// (`tl.to`, `tl.set`, …); a top-level `gsap.set(\"#root .label\", { xPercent: -50 })`\n// — a common way to seat shared base transforms before the timeline runs — is\n// invisible to it, so the conflict rule never saw it. Variable selectors\n// (`gsap.set(kicker, …)`) can't be resolved statically and are skipped.\nfunction extractStandaloneGsapTransformCalls(script: string): GsapTransformCall[] {\n const calls: GsapTransformCall[] = [];\n const pattern = /gsap\\.(set|to|from|fromTo)\\s*\\(\\s*([\"'])([^\"']+)\\2\\s*,\\s*\\{([^{}]*)\\}/g;\n let match: RegExpExecArray | null;\n while ((match = pattern.exec(script)) !== null) {\n const method = match[1] ?? \"set\";\n const selector = match[3] ?? \"\";\n const propsBody = match[4] ?? \"\";\n const properties = [...propsBody.matchAll(/([A-Za-z_$][\\w$]*)\\s*:/g)].map((m) => m[1] ?? \"\");\n calls.push({ method, selector, properties, raw: truncateSnippet(match[0]) ?? match[0] });\n }\n return calls;\n}\n\n// ── GSAP rules ─────────────────────────────────────────────────────────────\n\n// fallow-ignore-next-line complexity\nexport const gsapRules: LintRule<LintContext>[] = [\n // overlapping_gsap_tweens + gsap_animates_clip_element + unscoped_gsap_selector\n // fallow-ignore-next-line complexity\n async ({ source, tags, scripts, styles, rootCompositionId }) => {\n const findings: HyperframeLintFinding[] = [];\n\n // Build clip element selector map\n type ClipInfo = { tag: string; id: string; classes: string };\n const clipIds = new Map<string, ClipInfo>();\n const clipClasses = new Map<string, ClipInfo>();\n for (const tag of tags) {\n const classAttr = readAttr(tag.raw, \"class\") || \"\";\n const classes = classAttr.split(/\\s+/).filter(Boolean);\n if (!classes.includes(\"clip\")) continue;\n const id = readAttr(tag.raw, \"id\");\n const info: ClipInfo = {\n tag: tag.name,\n id: id || \"\",\n classes: classAttr,\n };\n if (id) clipIds.set(`#${id}`, info);\n for (const cls of classes) {\n if (cls !== \"clip\") clipClasses.set(`.${cls}`, info);\n }\n }\n\n const classUsage = countClassUsage(tags);\n const clipStartBoundariesByComposition = collectClipStartBoundariesByComposition(source, tags);\n const styleRules = collectSimpleStyleRules(styles);\n const reportedVisibleOverlayKeys = new Set<string>();\n\n for (const script of scripts) {\n const localTimelineCompId = readRegisteredTimelineCompositionId(script.content);\n const gsapWindows = await cachedExtractGsapWindows(script.content);\n const clipStartBoundaries =\n clipStartBoundariesByComposition.get(localTimelineCompId || rootCompositionId || \"\") ?? [];\n\n // overlapping_gsap_tweens\n for (let i = 0; i < gsapWindows.length; i++) {\n const left = gsapWindows[i];\n if (!left) continue;\n if (left.end <= left.position) continue;\n for (let j = i + 1; j < gsapWindows.length; j++) {\n const right = gsapWindows[j];\n if (!right) continue;\n if (right.end <= right.position) continue;\n if (left.targetSelector !== right.targetSelector) continue;\n const overlapStart = Math.max(left.position, right.position);\n const overlapEnd = Math.min(left.end, right.end);\n if (overlapEnd <= overlapStart) continue;\n if (left.overwriteAuto || right.overwriteAuto) continue;\n const sharedProperties = left.properties.filter((prop) =>\n right.properties.includes(prop),\n );\n if (sharedProperties.length === 0) continue;\n findings.push({\n code: \"overlapping_gsap_tweens\",\n severity: \"warning\",\n message: `GSAP tweens overlap on \"${left.targetSelector}\" for ${sharedProperties.join(\", \")} between ${overlapStart.toFixed(2)}s and ${overlapEnd.toFixed(2)}s.`,\n selector: left.targetSelector,\n fixHint: 'Shorten the earlier tween, move the later tween, or add `overwrite: \"auto\"`.',\n snippet: truncateSnippet(`${left.raw}\\n${right.raw}`),\n });\n }\n }\n\n // gsap_exit_missing_hard_kill\n if (clipStartBoundaries.length > 0) {\n for (const win of gsapWindows) {\n if (!isSceneBoundaryExit(win)) continue;\n const boundary = findMatchingSceneBoundary(win.end, clipStartBoundaries);\n if (boundary == null) continue;\n const hasHardKill = gsapWindows.some((candidate) =>\n isHardKillSet(candidate, win.targetSelector, boundary),\n );\n if (hasHardKill) continue;\n\n findings.push({\n code: \"gsap_exit_missing_hard_kill\",\n severity: \"error\",\n message:\n `GSAP exit on \"${win.targetSelector}\" ends at the ${boundary.toFixed(2)}s clip start boundary ` +\n \"without a matching tl.set hard kill. Non-linear seeking can land after the fade and leave stale visibility state.\",\n selector: win.targetSelector,\n fixHint:\n `Add \\`tl.set(\"${win.targetSelector}\", ${hiddenStateLiteral(win.propertyValues)}, ${boundary.toFixed(2)})\\` ` +\n \"after the exit tween.\",\n snippet: truncateSnippet(win.raw),\n });\n }\n }\n\n // gsap_fullscreen_overlay_starts_visible\n for (const tag of tags) {\n const selectors = tagSimpleSelectors(tag);\n if (selectors.length === 0) continue;\n const overlayKey = readAttr(tag.raw, \"id\") || String(tag.index);\n if (reportedVisibleOverlayKeys.has(overlayKey)) continue;\n const authoredStyle = combinedTagStyle(tag, styleRules);\n if (!authoredStyle || !styleLooksFullFrameOverlay(authoredStyle)) continue;\n if (styleHasHiddenInitialState(authoredStyle)) continue;\n\n const visibilityWindows = gsapWindows\n .filter((win) => {\n const tokens = targetedSelectorTokens(win.targetSelector);\n if (!selectors.some((selector) => tokens.has(selector))) return false;\n return win.properties.some((prop) =>\n [\"opacity\", \"autoAlpha\", \"visibility\", \"display\"].includes(prop),\n );\n })\n .sort((a, b) => a.position - b.position);\n const startsHiddenAtZero = visibilityWindows.some(\n (win) =>\n win.position <= SCENE_BOUNDARY_EPSILON_SECONDS && isHiddenGsapState(win.propertyValues),\n );\n if (startsHiddenAtZero) continue;\n const firstVisible = visibilityWindows.find((win) => makesOverlayVisible(win));\n if (!firstVisible) continue;\n const selector =\n selectors.find((candidate) =>\n targetedSelectorTokens(firstVisible.targetSelector).has(candidate),\n ) ||\n selectors[0] ||\n tag.name;\n const laterHidden = visibilityWindows.some(\n (win) => win.position >= firstVisible.position && isHiddenGsapState(win.propertyValues),\n );\n if (firstVisible.method !== \"from\" && !laterHidden) continue;\n\n reportedVisibleOverlayKeys.add(overlayKey);\n findings.push({\n code: \"gsap_fullscreen_overlay_starts_visible\",\n severity: \"error\",\n message:\n `Full-frame overlay \"${selector}\" starts visible before its first GSAP opacity tween at ` +\n `${firstVisible.position.toFixed(2)}s. It will cover earlier render frames, often as a blank/white video.`,\n selector,\n elementId: readAttr(tag.raw, \"id\") || undefined,\n fixHint:\n `Add \\`opacity: 0\\` to \"${selector}\" in CSS/inline styles, or add ` +\n `\\`tl.set(\"${selector}\", { opacity: 0 }, 0)\\` before the reveal tween.`,\n snippet: truncateSnippet(firstVisible.raw),\n });\n }\n\n // gsap_animates_clip_element — only error when GSAP animates visibility/display\n for (const win of gsapWindows) {\n const sel = win.targetSelector;\n const clipInfo = clipIds.get(sel) || clipClasses.get(sel);\n if (!clipInfo) continue;\n const conflictingProps = win.properties.filter(\n (p) => p === \"visibility\" || p === \"display\",\n );\n if (conflictingProps.length === 0) continue;\n const elDesc = `<${clipInfo.tag}${clipInfo.id ? ` id=\"${clipInfo.id}\"` : \"\"} class=\"${clipInfo.classes}\">`;\n findings.push({\n code: \"gsap_animates_clip_element\",\n severity: \"error\",\n message: `GSAP animation sets ${conflictingProps.join(\", \")} on a clip element. Selector \"${sel}\" resolves to element ${elDesc}. The framework manages clip visibility via ${conflictingProps.join(\"/\")} — do not animate these properties on clip elements.`,\n selector: sel,\n elementId: clipInfo.id || undefined,\n fixHint:\n \"Remove the visibility/display tween, or move the content into a child <div> and target that instead.\",\n snippet: truncateSnippet(win.raw),\n });\n }\n\n // unscoped_gsap_selector\n if (!localTimelineCompId || localTimelineCompId === rootCompositionId) continue;\n for (const win of gsapWindows) {\n if (!isSuspiciousGlobalSelector(win.targetSelector)) continue;\n const className = getSingleClassSelector(win.targetSelector);\n if (className && (classUsage.get(className) || 0) < 2) continue;\n findings.push({\n code: \"unscoped_gsap_selector\",\n severity: \"error\",\n message: `Timeline \"${localTimelineCompId}\" uses unscoped selector \"${win.targetSelector}\" that will target elements in ALL compositions when bundled, causing data loss (opacity, transforms, etc.).`,\n selector: win.targetSelector,\n fixHint: `Scope the selector: \\`[data-composition-id=\"${localTimelineCompId}\"] ${win.targetSelector}\\` or use a unique id.`,\n snippet: truncateSnippet(win.raw),\n });\n }\n }\n return findings;\n },\n\n // gsap_css_transform_conflict\n // fallow-ignore-next-line complexity\n async ({ styles, scripts, tags }) => {\n const findings: HyperframeLintFinding[] = [];\n const cssTranslateSelectors = new Map<string, string>();\n const cssScaleSelectors = new Map<string, string>();\n\n // Check <style> blocks for transform rules\n for (const style of styles) {\n for (const [, selector, body] of style.content.matchAll(\n /([#.][a-zA-Z0-9_-]+)\\s*\\{([^}]+)\\}/g,\n )) {\n const tMatch = body?.match(/transform\\s*:\\s*([^;]+)/);\n if (!tMatch || !tMatch[1]) continue;\n const transformVal = tMatch[1].trim();\n if (/translate/i.test(transformVal))\n cssTranslateSelectors.set((selector ?? \"\").trim(), transformVal);\n if (/scale/i.test(transformVal))\n cssScaleSelectors.set((selector ?? \"\").trim(), transformVal);\n }\n }\n\n // Also check inline style=\"...\" attributes on tags\n for (const tag of tags) {\n const inlineStyle = readAttr(tag.raw, \"style\");\n if (!inlineStyle) continue;\n const tMatch = inlineStyle.match(/transform\\s*:\\s*([^;]+)/);\n if (!tMatch || !tMatch[1]) continue;\n const transformVal = tMatch[1].trim();\n // Derive selectors from the tag's id and all classes\n const id = readAttr(tag.raw, \"id\");\n const classes = readAttr(tag.raw, \"class\")?.split(/\\s+/).filter(Boolean) ?? [];\n const selectors: string[] = [];\n if (id) selectors.push(`#${id}`);\n for (const cls of classes) selectors.push(`.${cls}`);\n if (selectors.length === 0) continue;\n for (const sel of selectors) {\n if (/translate/i.test(transformVal) && !cssTranslateSelectors.has(sel))\n cssTranslateSelectors.set(sel, transformVal);\n if (/scale/i.test(transformVal) && !cssScaleSelectors.has(sel))\n cssScaleSelectors.set(sel, transformVal);\n }\n }\n\n if (cssTranslateSelectors.size === 0 && cssScaleSelectors.size === 0) return findings;\n\n for (const script of scripts) {\n if (!/gsap\\.timeline/.test(script.content)) continue;\n const windows = await cachedExtractGsapWindows(script.content);\n\n // Two sources of transform-setting calls: timeline-rooted tweens (from the\n // acorn parser) and standalone gsap.* calls (regex — the parser ignores\n // these). Normalize both into one shape and run the same conflict check.\n const calls: GsapTransformCall[] = [\n ...windows.map((win) => ({\n method: win.method,\n selector: win.targetSelector,\n properties: win.properties,\n raw: win.raw,\n })),\n ...extractStandaloneGsapTransformCalls(stripJsComments(script.content)),\n ];\n\n type Conflict = { cssTransform: string; props: Set<string>; raw: string };\n const conflicts = new Map<string, Conflict>();\n\n for (const call of calls) {\n // from() and fromTo() both supply explicit start values so GSAP owns\n // the full transform from t=0, making the CSS conflict moot\n if (call.method === \"fromTo\" || call.method === \"from\") continue;\n const sel = call.selector;\n const translateProps = call.properties.filter((p) =>\n CONFLICTING_TRANSLATE_PROPS.includes(p),\n );\n const scaleProps = call.properties.filter((p) => CONFLICTING_SCALE_PROPS.includes(p));\n const cssFromTranslate =\n translateProps.length > 0 ? matchCssTransform(sel, cssTranslateSelectors) : undefined;\n const cssFromScale =\n scaleProps.length > 0 ? matchCssTransform(sel, cssScaleSelectors) : undefined;\n if (!cssFromTranslate && !cssFromScale) continue;\n const existing = conflicts.get(sel) ?? {\n cssTransform: [cssFromTranslate, cssFromScale].filter(Boolean).join(\" \"),\n props: new Set<string>(),\n raw: call.raw,\n };\n for (const p of [...translateProps, ...scaleProps]) existing.props.add(p);\n conflicts.set(sel, existing);\n }\n\n for (const [sel, { cssTransform, props, raw }] of conflicts) {\n const propList = [...props].join(\"/\");\n const gsapEquivalent = cssTransformToGsapProps(cssTransform);\n const fixHint = gsapEquivalent\n ? `Remove \\`transform: ${cssTransform}\\` from CSS and replace with GSAP properties: ${gsapEquivalent}. ` +\n `Example: tl.fromTo('${sel}', { ${gsapEquivalent} }, { ${gsapEquivalent}, ...yourAnimation }). ` +\n `tl.fromTo is exempt from this rule.`\n : `Remove the transform from CSS and use tl.fromTo('${sel}', ` +\n `{ xPercent: -50, x: -1000 }, { xPercent: -50, x: 0 }) so GSAP owns ` +\n `the full transform state. tl.fromTo is exempt from this rule.`;\n findings.push({\n code: \"gsap_css_transform_conflict\",\n severity: \"error\",\n message:\n `\"${sel}\" has CSS \\`transform: ${cssTransform}\\` and a GSAP tween animates ` +\n `${propList}. GSAP will overwrite the full CSS transform, discarding any ` +\n `translateX(-50%) centering or CSS scale value.`,\n selector: sel,\n fixHint,\n snippet: truncateSnippet(raw),\n });\n }\n }\n return findings;\n },\n\n // missing_gsap_script\n ({ scripts, rawSource, options }) => {\n const allScriptTexts = scripts.filter((s) => !/\\bsrc\\s*=/.test(s.attrs)).map((s) => s.content);\n const allScriptSrcs = scripts\n .map((s) => readAttr(`<script ${s.attrs}>`, \"src\") || \"\")\n .filter(Boolean);\n const canInheritGsapFromHost =\n options.isSubComposition || rawSource.trimStart().toLowerCase().startsWith(\"<template\");\n\n const usesGsap = allScriptTexts.some((t) =>\n /gsap\\.(to|from|fromTo|timeline|set|registerPlugin)\\b/.test(t),\n );\n const hasGsapScript = allScriptSrcs.some((src) => /gsap/i.test(src));\n // Detect GSAP bundled inline (no src attribute). Match:\n // - Producer's CDN-inlining comment: /* inlined: ...gsap... */\n // - GSAP library internals: _gsScope, GreenSock, gsap.config\n // - Large inline scripts (>5KB) that reference gsap (likely bundled library)\n const hasInlineGsap = allScriptTexts.some(\n (t) =>\n /\\/\\*\\s*inlined:.*gsap/i.test(t) ||\n /\\b_gsScope\\b/.test(t) ||\n /\\bGreenSock\\b/.test(t) ||\n /\\bgsap\\.(config|defaults|version)\\b/.test(t) ||\n (t.length > 5000 && /\\bgsap\\b/i.test(t)),\n );\n\n if (!usesGsap || hasGsapScript || hasInlineGsap || canInheritGsapFromHost) return [];\n return [\n {\n code: \"missing_gsap_script\",\n severity: \"error\",\n message: \"Composition uses GSAP but no GSAP script is loaded. The animation will not run.\",\n fixHint:\n 'Add <script src=\"https://cdn.jsdelivr.net/npm/gsap@3/dist/gsap.min.js\"></script> before your animation script.',\n },\n ];\n },\n\n // audio_reactive_single_tween_per_group\n // fallow-ignore-next-line complexity\n ({ scripts, styles }) => {\n const findings: HyperframeLintFinding[] = [];\n const isCaptionFile = styles.some((s) => /\\.caption[-_]?(?:group|word)/i.test(s.content));\n if (!isCaptionFile) return findings;\n\n for (const script of scripts) {\n const content = script.content;\n // Detect audio data loading\n const hasAudioData = /AUDIO|audio[-_]?data|bands\\[/.test(content);\n if (!hasAudioData) continue;\n\n // Detect caption group loop\n const hasCaptionLoop = /forEach/.test(content) && /caption|group|cg-/.test(content);\n if (!hasCaptionLoop) continue;\n\n // Check if audio-reactive tweens are created at intervals (loop inside the group loop)\n // vs a single tween per group (no inner time-sampling loop)\n const hasInnerSamplingLoop =\n /for\\s*\\(\\s*var\\s+\\w+\\s*=\\s*group\\.start/.test(content) ||\n /for\\s*\\(\\s*var\\s+at\\s*=/.test(content) ||\n /while\\s*\\(\\s*\\w+\\s*<\\s*group\\.end/.test(content);\n\n if (!hasInnerSamplingLoop) {\n // Check if there's at least a peak-based single tween (the minimal pattern)\n const hasPeakTween =\n /peak(?:Bass|Treble|Energy)/.test(content) && /group\\.start/.test(content);\n if (hasPeakTween) {\n findings.push({\n code: \"audio_reactive_single_tween_per_group\",\n severity: \"warning\",\n message:\n \"Audio-reactive captions use a single tween per group based on peak values. \" +\n \"This sets one static value at group.start — not perceptible as audio reactivity.\",\n fixHint:\n \"Sample audio data at 100-200ms intervals throughout each group's lifetime \" +\n \"(for loop from group.start to group.end) and create a tween at each sample \" +\n \"point for visible pulsing.\",\n });\n }\n }\n }\n return findings;\n },\n\n // gsap_infinite_repeat\n ({ scripts }) => {\n const findings: HyperframeLintFinding[] = [];\n for (const script of scripts) {\n const content = stripJsComments(script.content);\n // Match repeat: -1 in GSAP tweens or timeline configs\n const pattern = /repeat\\s*:\\s*-1(?!\\d)/g;\n let match: RegExpExecArray | null;\n while ((match = pattern.exec(content)) !== null) {\n const contextStart = Math.max(0, match.index - 60);\n const contextEnd = Math.min(content.length, match.index + match[0].length + 60);\n const snippet = content.slice(contextStart, contextEnd).trim();\n findings.push({\n code: \"gsap_infinite_repeat\",\n severity: \"error\",\n message:\n \"GSAP tween uses `repeat: -1` (infinite). Infinite repeats break the deterministic \" +\n \"capture engine which seeks to exact frame times. Use a finite repeat count calculated \" +\n \"from the composition duration: `repeat: Math.floor(duration / cycleDuration) - 1`.\",\n fixHint:\n \"Replace `repeat: -1` with a finite count, e.g. `repeat: Math.floor(totalDuration / singleCycleDuration) - 1`. \" +\n \"Use Math.floor (not Math.ceil) to ensure the animation fits within the total duration.\",\n snippet: truncateSnippet(snippet),\n });\n }\n }\n return findings;\n },\n\n // gsap_repeat_ceil_overshoot\n ({ scripts }) => {\n const findings: HyperframeLintFinding[] = [];\n for (const script of scripts) {\n const content = script.content;\n // Match patterns like: repeat: Math.ceil(duration / X) - 1\n // or repeat: Math.ceil(totalDuration / cycleDuration) - 1\n const pattern = /repeat\\s*:\\s*Math\\.ceil\\s*\\([^)]+\\)\\s*-\\s*1/g;\n let match: RegExpExecArray | null;\n while ((match = pattern.exec(content)) !== null) {\n const contextStart = Math.max(0, match.index - 40);\n const contextEnd = Math.min(content.length, match.index + match[0].length + 40);\n const snippet = content.slice(contextStart, contextEnd).trim();\n findings.push({\n code: \"gsap_repeat_ceil_overshoot\",\n severity: \"warning\",\n message:\n \"GSAP repeat calculation uses `Math.ceil` which can overshoot the composition duration. \" +\n \"For example, Math.ceil(10.5 / 2) - 1 = 5 repeats → 6 cycles × 2s = 12s, exceeding 10.5s.\",\n fixHint:\n \"Use `Math.floor` instead of `Math.ceil` to ensure the animation fits within the duration: \" +\n \"`repeat: Math.floor(totalDuration / cycleDuration) - 1`. \" +\n \"Math.floor(10.5 / 2) - 1 = 4 repeats → 5 cycles × 2s = 10s ✓\",\n snippet: truncateSnippet(snippet),\n });\n }\n }\n return findings;\n },\n\n // scene_layer_missing_visibility_kill\n ({ scripts, tags }) => {\n const findings: HyperframeLintFinding[] = [];\n\n // Detect multi-scene compositions: multiple elements with \"scene\" in their id\n const sceneElements = tags.filter((t) => {\n const id = readAttr(t.raw, \"id\") || \"\";\n return /^scene\\d+$/i.test(id);\n });\n if (sceneElements.length < 2) return findings;\n\n for (const script of scripts) {\n const content = stripJsComments(script.content);\n // For each scene, check if there's a visibility:hidden set after exit tweens\n for (const tag of sceneElements) {\n const id = readAttr(tag.raw, \"id\") || \"\";\n // Check if this scene has exit tweens (opacity: 0)\n const exitPattern = new RegExp(`[\"']#${id}[\"'][^)]*opacity\\\\s*:\\\\s*0`);\n const hasExit = exitPattern.test(content);\n if (!hasExit) continue;\n\n // Check if there's a hard visibility kill\n const killPattern = new RegExp(`[\"']#${id}[\"'][^)]*visibility\\\\s*:\\\\s*[\"']hidden[\"']`);\n const hasKill = killPattern.test(content);\n if (!hasKill) {\n findings.push({\n code: \"scene_layer_missing_visibility_kill\",\n severity: \"error\",\n elementId: id,\n message:\n `Scene layer \"#${id}\" exits via opacity tween but has no visibility: hidden hard kill. ` +\n \"When scrubbing or when tweens conflict, the scene may remain partially visible and overlap the next scene.\",\n fixHint: `Add \\`tl.set(\"#${id}\", { visibility: \"hidden\" }, <exit-end-time>)\\` after the scene's exit tweens.`,\n });\n }\n }\n }\n return findings;\n },\n\n // gsap_timeline_not_registered\n ({ scripts, rawSource, options }) => {\n const findings: HyperframeLintFinding[] = [];\n const canInheritFromHost =\n options.isSubComposition || rawSource.trimStart().toLowerCase().startsWith(\"<template\");\n\n for (const script of scripts) {\n const content = script.content;\n if (!/gsap\\.timeline/.test(content)) continue;\n const hasRegistration = WINDOW_TIMELINE_ASSIGN_PATTERN.test(content);\n if (hasRegistration || canInheritFromHost) continue;\n findings.push({\n code: \"gsap_timeline_not_registered\",\n severity: \"error\",\n message:\n \"GSAP timeline is created but never registered in window.__timelines. \" +\n \"The runtime discovers timelines from this registry — without registration, \" +\n \"animations will not play during preview or render.\",\n fixHint:\n \"Add `window.__timelines = window.__timelines || {};` and \" +\n '`window.__timelines[\"root\"] = tl;` after creating the timeline (use the ' +\n \"composition's data-composition-id as the key).\",\n });\n }\n return findings;\n },\n\n // gsap_timeline_registered_before_async_build — registering window.__timelines[id]\n // BEFORE the timeline is built inside document.fonts.ready (or any async callback)\n // leaves an EMPTY timeline registered. The runtime's sub-composition readiness gate\n // treats \"key present\" as \"ready\" and nests the child ONCE, while still empty — so the\n // animation never renders when this composition is mounted as a sub-composition.\n // Register only AFTER the build completes (the documented async-setup contract).\n ({ scripts }) => {\n const findings: HyperframeLintFinding[] = [];\n for (const script of scripts) {\n const content = stripJsComments(script.content);\n const regIdx = content.search(/window\\s*\\.\\s*__timelines\\s*\\[/);\n if (regIdx < 0) continue;\n const fontsReadyIdx = content.search(/document\\s*\\.\\s*fonts\\s*\\.\\s*ready/);\n if (fontsReadyIdx < 0) continue;\n // Registering after the async boundary is the correct pattern — skip it.\n if (regIdx >= fontsReadyIdx) continue;\n // Confirm the build is actually deferred past the boundary (a tween/build call\n // appears after document.fonts.ready), i.e. the registered timeline starts empty.\n const tail = content.slice(fontsReadyIdx);\n if (!/\\.(?:to|from|fromTo)\\s*\\(|buildEffect\\s*\\(/.test(tail)) continue;\n findings.push({\n code: \"gsap_timeline_registered_before_async_build\",\n severity: \"error\",\n message:\n \"window.__timelines is assigned BEFORE the timeline is built inside \" +\n \"document.fonts.ready. An empty timeline registered early gets nested empty \" +\n \"when this composition is used as a sub-composition (the readiness gate treats \" +\n '\"key present\" as \"ready\" and never re-nests), so the animation renders blank.',\n fixHint:\n \"Move the `window.__timelines[id] = tl;` assignment to the END of the \" +\n \"document.fonts.ready callback, after the tweens are added. Optionally call \" +\n \"window.__hfForceTimelineRebind() right after, to re-nest the populated timeline.\",\n });\n }\n return findings;\n },\n\n // gsap_from_opacity_noop — CSS opacity:0 + gsap.from({opacity:0}) = invisible forever\n // fallow-ignore-next-line complexity\n async ({ styles, scripts, tags }) => {\n const findings: HyperframeLintFinding[] = [];\n const cssOpacityZeroSelectors = new Set<string>();\n\n for (const style of styles) {\n for (const [, selector, body] of style.content.matchAll(\n /([#.][a-zA-Z0-9_-]+)\\s*\\{([^}]+)\\}/g,\n )) {\n if (body && /opacity\\s*:\\s*0\\s*[;}]/.test(body)) {\n cssOpacityZeroSelectors.add((selector ?? \"\").trim());\n }\n }\n }\n\n for (const tag of tags) {\n const inlineStyle = readAttr(tag.raw, \"style\");\n if (!inlineStyle || !/opacity\\s*:\\s*0/.test(inlineStyle)) continue;\n const id = readAttr(tag.raw, \"id\");\n const classes = readAttr(tag.raw, \"class\")?.split(/\\s+/).filter(Boolean) ?? [];\n if (id) cssOpacityZeroSelectors.add(`#${id}`);\n for (const cls of classes) cssOpacityZeroSelectors.add(`.${cls}`);\n }\n\n if (cssOpacityZeroSelectors.size === 0) return findings;\n\n for (const script of scripts) {\n if (!/gsap\\.timeline/.test(script.content)) continue;\n const windows = await cachedExtractGsapWindows(script.content);\n\n for (const win of windows) {\n if (win.method !== \"from\") continue;\n if (!win.properties.includes(\"opacity\")) continue;\n // Only a noop when the tween animates FROM 0 (same as the CSS value)\n if (win.propertyValues[\"opacity\"] !== 0) continue;\n const sel = win.targetSelector;\n const cssKey = sel.startsWith(\"#\") || sel.startsWith(\".\") ? sel : `#${sel}`;\n if (!cssOpacityZeroSelectors.has(cssKey)) continue;\n\n findings.push({\n code: \"gsap_from_opacity_noop\",\n severity: \"error\",\n message:\n `\"${sel}\" has CSS \\`opacity: 0\\` and a gsap.${win.method}() that also sets opacity to 0. ` +\n `gsap.from() animates FROM the specified value TO the current CSS value — ` +\n `since CSS is already 0, the element animates from 0→0 and never becomes visible.`,\n selector: sel,\n fixHint:\n `Remove \\`opacity: 0\\` from the CSS/inline style on \"${sel}\". ` +\n `Let gsap.from({opacity: 0}) handle the initial hidden state — ` +\n `it will animate FROM 0 TO the CSS value (1 by default).`,\n snippet: truncateSnippet(win.raw),\n });\n }\n }\n return findings;\n },\n\n // gsap_group_selector_keyframes\n ({ scripts }) => {\n const findings: HyperframeLintFinding[] = [];\n for (const script of scripts) {\n const content = stripJsComments(script.content);\n const pattern = /\\.(?:to|from|fromTo)\\(\\s*[\"']([^\"']+,\\s*[^\"']+)[\"']\\s*,\\s*\\{[^}]*keyframes/g;\n let match: RegExpExecArray | null;\n while ((match = pattern.exec(content)) !== null) {\n const selector = match[1]!;\n const count = selector.split(\",\").length;\n const contextStart = Math.max(0, match.index - 20);\n const contextEnd = Math.min(content.length, match.index + match[0].length + 40);\n findings.push({\n code: \"gsap_group_selector_keyframes\",\n severity: \"warning\",\n message:\n `GSAP tween targets ${count} elements with shared keyframes (\"${truncateSnippet(selector, 60)}\"). ` +\n `Editing one element's keyframes in Studio will affect all ${count} elements. ` +\n `Split into individual tweens for per-element keyframe control.`,\n fixHint:\n `Replace the group selector with individual tl.to() calls per element, ` +\n `each with their own keyframes object.`,\n snippet: truncateSnippet(content.slice(contextStart, contextEnd)),\n });\n }\n }\n return findings;\n },\n];\n","import type { LintContext, HyperframeLintFinding } from \"../context\";\n\n/** Extract a bracket-balanced array literal starting at the `[` found by `varMatch`. */\n// fallow-ignore-next-line complexity\nfunction extractArrayLiteral(src: string, varMatch: RegExpExecArray): string | null {\n const openIdx = varMatch.index + varMatch[0].length - 1;\n let depth = 0;\n let inStr = false;\n let strChar = \"\";\n for (let i = openIdx; i < src.length; i++) {\n const c = src[i]!;\n if (inStr) {\n if (c === \"\\\\\") {\n i++;\n continue;\n }\n if (c === strChar) inStr = false;\n } else if (c === '\"' || c === \"'\") {\n inStr = true;\n strChar = c;\n } else if (c === \"[\") {\n depth++;\n } else if (c === \"]\") {\n depth--;\n if (depth === 0) return src.slice(openIdx, i + 1);\n }\n }\n return null;\n}\n\nexport const captionRules: Array<(ctx: LintContext) => HyperframeLintFinding[]> = [\n // caption_exit_missing_hard_kill\n ({ scripts, styles, options, rootCompositionId }) => {\n const findings: HyperframeLintFinding[] = [];\n // Only the ACTUAL captions composition. A content frame that merely mentions\n // \"karaoke\" / \"caption-*\" in a comment (or uses an unrelated forEach + opacity:0\n // screen-swap) is NOT captions — gating here prevents the false positive that fired\n // on a content frame whose only caption signal was a descriptive comment.\n const isCaptionComposition =\n Boolean(options.filePath && /caption/i.test(options.filePath)) ||\n rootCompositionId === \"captions\" ||\n styles.some((s) => /\\.caption[-_]?(?:group|word|line|block)\\b|\\.cg-/.test(s.content));\n if (!isCaptionComposition) return findings;\n for (const script of scripts) {\n const content = script.content;\n const hasExitTween = /\\.to\\s*\\([^,]+,\\s*\\{[^}]*opacity\\s*:\\s*0/.test(content);\n const hasHardKill =\n /\\.set\\s*\\([^,]+,\\s*\\{[^}]*(?:visibility\\s*:\\s*[\"']hidden[\"']|opacity\\s*:\\s*0)/.test(\n content,\n );\n const hasCaptionLoop =\n /forEach|\\.forEach\\s*\\(/.test(content) &&\n /karaoke|caption[-_]?(?:group|word|line|block)|cg-/.test(content);\n if (hasCaptionLoop && hasExitTween && !hasHardKill) {\n findings.push({\n code: \"caption_exit_missing_hard_kill\",\n severity: \"error\",\n message:\n \"Caption exit animations (tl.to with opacity: 0) detected without a hard tl.set kill. \" +\n \"Exit tweens can fail when karaoke word-level tweens conflict, leaving captions stuck on screen.\",\n fixHint:\n 'Add `tl.set(groupEl, { opacity: 0, visibility: \"hidden\" }, group.end)` after every ' +\n \"exit tl.to animation as a deterministic kill.\",\n });\n }\n }\n return findings;\n },\n\n // caption_text_overflow_risk\n ({ styles }) => {\n const findings: HyperframeLintFinding[] = [];\n for (const style of styles) {\n const captionBlocks = style.content.matchAll(\n /(\\.caption[-_]?(?:group|container|text|line|word)|#caption[-_]?container)\\s*\\{([^}]+)\\}/gi,\n );\n for (const [, selector, body] of captionBlocks) {\n if (!body) continue;\n const hasNowrap = /white-space\\s*:\\s*nowrap/i.test(body);\n const hasMaxWidth = /max-width/i.test(body);\n if (hasNowrap && !hasMaxWidth) {\n findings.push({\n code: \"caption_text_overflow_risk\",\n severity: \"warning\",\n selector: (selector ?? \"\").trim(),\n message: `Caption selector \"${(selector ?? \"\").trim()}\" has white-space: nowrap but no max-width. Long phrases will clip off-screen.`,\n fixHint:\n \"Add max-width: 1600px (landscape) or max-width: 900px (portrait) and overflow: hidden.\",\n });\n }\n }\n }\n return findings;\n },\n\n // caption_transcript_not_inline\n // fallow-ignore-next-line complexity\n ({ scripts, styles, options }) => {\n const findings: HyperframeLintFinding[] = [];\n // Only check files that look like caption compositions\n const isCaptionFile =\n (options.filePath && /caption/i.test(options.filePath)) ||\n styles.some((s) => /\\.caption[-_]?(?:group|word)/i.test(s.content));\n if (!isCaptionFile) return findings;\n\n const allScript = scripts.map((s) => s.content).join(\"\\n\");\n const hasInlineTranscript = /(?:const|let|var)\\s+(?:TRANSCRIPT|script)\\s*=\\s*\\[/.test(\n allScript,\n );\n const hasFetchTranscript = /fetch\\s*\\(\\s*[\"'][^\"']*transcript/i.test(allScript);\n\n if (!hasInlineTranscript && hasFetchTranscript) {\n findings.push({\n code: \"caption_transcript_not_inline\",\n severity: \"error\",\n message:\n \"Captions composition loads transcript via fetch(). The studio caption editor \" +\n \"requires an inline `var TRANSCRIPT = [...]` array to detect and edit captions.\",\n fixHint:\n 'Embed the transcript as `var TRANSCRIPT = [{ \"text\": \"...\", \"start\": 0, \"end\": 1 }, ...]` ' +\n \"with JSON-quoted property keys. See the captions skill for details.\",\n });\n }\n\n if (hasInlineTranscript) {\n // Verify the inline transcript can be parsed.\n // Use a balanced-bracket scan instead of a regex to correctly handle\n // nested arrays (e.g. word-level timing arrays inside each entry).\n const varStart = /(?:const|let|var)\\s+(?:TRANSCRIPT|script)\\s*=\\s*\\[/.exec(allScript);\n const transcriptJson = varStart ? extractArrayLiteral(allScript, varStart) : null;\n if (transcriptJson) {\n try {\n JSON.parse(transcriptJson);\n } catch {\n findings.push({\n code: \"caption_transcript_parse_error\",\n severity: \"error\",\n message:\n \"Inline TRANSCRIPT array is not valid JSON. The studio caption editor may fail \" +\n \"to parse it. Common cause: unquoted property keys with apostrophes in text.\",\n fixHint:\n 'Use JSON-quoted keys: { \"text\": \"don\\'t\", \"start\": 0, \"end\": 1 } instead of ' +\n '{ text: \"don\\'t\", start: 0, end: 1 }.',\n });\n }\n }\n }\n\n return findings;\n },\n\n // caption_container_relative_position\n ({ styles }) => {\n const findings: HyperframeLintFinding[] = [];\n for (const style of styles) {\n const captionBlocks = style.content.matchAll(\n /(\\.caption[-_]?(?:group|container|text|line)|#caption[-_]?container)\\s*\\{([^}]+)\\}/gi,\n );\n for (const [, selector, body] of captionBlocks) {\n if (!body) continue;\n if (/position\\s*:\\s*relative/i.test(body)) {\n findings.push({\n code: \"caption_container_relative_position\",\n severity: \"error\",\n selector: (selector ?? \"\").trim(),\n message: `Caption selector \"${(selector ?? \"\").trim()}\" uses position: relative which causes overflow and breaks caption stacking.`,\n fixHint: \"Use position: absolute for all caption elements.\",\n });\n }\n }\n }\n return findings;\n },\n\n // caption_overflow_clips_scaled_words\n ({ styles, scripts }) => {\n const findings: HyperframeLintFinding[] = [];\n const hasScaledWords = scripts.some(\n (s) => /scale\\s*:\\s*1\\.[2-9]/.test(s.content) && /caption|word|cg-/.test(s.content),\n );\n if (!hasScaledWords) return findings;\n\n for (const style of styles) {\n const captionBlocks = style.content.matchAll(\n /(\\.caption[-_]?(?:group|container)|#caption[-_]?(?:layer|container))\\s*\\{([^}]+)\\}/gi,\n );\n for (const [, selector, body] of captionBlocks) {\n if (!body) continue;\n if (/overflow\\s*:\\s*hidden/i.test(body)) {\n findings.push({\n code: \"caption_overflow_clips_scaled_words\",\n severity: \"error\",\n selector: (selector ?? \"\").trim(),\n message: `\"${(selector ?? \"\").trim()}\" has overflow: hidden but GSAP scales caption words above 1.0x. Scaled emphasis words and their glow effects will be clipped.`,\n fixHint:\n \"Use overflow: visible on caption containers. Rely on fitTextFontSize with reduced maxWidth to prevent overflow instead.\",\n });\n }\n }\n }\n return findings;\n },\n\n // caption_textshadow_on_group_container\n ({ scripts, styles }) => {\n const findings: HyperframeLintFinding[] = [];\n const isCaptionFile = styles.some((s) => /\\.caption[-_]?(?:group|word)/i.test(s.content));\n if (!isCaptionFile) return findings;\n\n for (const script of scripts) {\n // Detect textShadow tweened on a group container (div with child word spans)\n const groupShadowPattern =\n /\\.to\\s*\\(\\s*(?:div|groupEl|el|captionEl|document\\.getElementById\\s*\\(\\s*[\"']cg-)\\s*[^,]*,\\s*\\{[^}]*textShadow/g;\n // Also catch selector-based targeting of group containers\n const selectorShadowPattern =\n /\\.to\\s*\\(\\s*[\"'](?:#cg-\\d+|\\.caption[-_]?group)[\"']\\s*,\\s*\\{[^}]*textShadow/g;\n if (groupShadowPattern.test(script.content) || selectorShadowPattern.test(script.content)) {\n findings.push({\n code: \"caption_textshadow_on_group_container\",\n severity: \"warning\",\n message:\n \"textShadow is tweened on a caption group container. When children have semi-transparent \" +\n \"color (e.g., inactive karaoke words at rgba opacity), the glow renders as a visible \" +\n \"rectangle behind the entire group.\",\n fixHint:\n \"Apply textShadow to individual active word elements instead of the group container. \" +\n \"Use scale on the group for bass-reactive pulsing.\",\n });\n }\n }\n return findings;\n },\n\n // caption_fittext_scale_mismatch\n // fallow-ignore-next-line complexity\n ({ scripts }) => {\n const findings: HyperframeLintFinding[] = [];\n for (const script of scripts) {\n const content = script.content;\n const fitTextMatch = content.match(/fitTextFontSize\\s*\\([^)]*maxWidth\\s*:\\s*(\\d+)/);\n if (!fitTextMatch) continue;\n const maxWidth = parseInt(fitTextMatch[1] ?? \"0\", 10);\n if (!maxWidth) continue;\n\n // Find max scale on caption words\n const scaleMatches = [...content.matchAll(/scale\\s*:\\s*(1\\.\\d+)/g)];\n const captionContext = /caption|word|cg-|karaoke/i.test(content);\n if (!captionContext || scaleMatches.length === 0) continue;\n\n let maxScale = 1;\n for (const m of scaleMatches) {\n const val = parseFloat(m[1] ?? \"1\");\n if (val > maxScale) maxScale = val;\n }\n\n // Check if maxWidth * maxScale exceeds safe bounds (1920 - reasonable margins)\n const effectiveWidth = maxWidth * maxScale;\n if (effectiveWidth > 1760) {\n findings.push({\n code: \"caption_fittext_scale_mismatch\",\n severity: \"warning\",\n message:\n `fitTextFontSize uses maxWidth: ${maxWidth}px but emphasis words scale up to ${maxScale}x. ` +\n `Effective width ${Math.round(effectiveWidth)}px may overflow the composition (1920px minus margins).`,\n fixHint: `Reduce maxWidth to ${Math.floor(1700 / maxScale)}px to leave headroom for scaled emphasis words.`,\n });\n }\n }\n return findings;\n },\n];\n","import type { LintContext, HyperframeLintFinding, ExtractedBlock } from \"../context\";\nimport { findHtmlTag, readAttr, readJsonAttr, stripJsComments, truncateSnippet } from \"../utils\";\nimport { COMPOSITION_VARIABLE_TYPES } from \"@hyperframes/parsers/composition\";\n\n// Agent guidance thresholds: warning-only nudges for files/tracks that become hard\n// to inspect and revise reliably in a single composition.\nconst MAX_COMPOSITION_LINES = 300;\nconst MAX_TIMED_ELEMENTS_PER_TRACK = 3;\nconst TRACK_DENSITY_EXEMPT_TAGS = new Set([\"audio\", \"script\", \"style\", \"video\"]);\n\nfunction countPhysicalLines(source: string): number {\n if (source.length === 0) return 0;\n\n const normalized = source.replace(/\\r\\n/g, \"\\n\").replace(/\\r/g, \"\\n\");\n const withoutFinalNewline = normalized.endsWith(\"\\n\") ? normalized.slice(0, -1) : normalized;\n return withoutFinalNewline.split(\"\\n\").length;\n}\n\nfunction countStructuralLines(source: string): number {\n return countPhysicalLines(source.replace(/<style\\b[^>]*>[\\s\\S]*?<\\/style>/gi, \"<style></style>\"));\n}\n\nexport function isRegistrySourceFile(filePath?: string): boolean {\n if (!filePath) return false;\n\n const normalized = filePath.replace(/\\\\/g, \"/\");\n return /(?:^|\\/)registry\\/blocks\\/([^/]+)\\/\\1\\.html$/i.test(normalized);\n}\n\nexport function isRegistryInstalledFile(rawSource: string): boolean {\n return /^\\s*<!--\\s*hyperframes-registry-item:[^>]*-->/i.test(rawSource.slice(0, 512));\n}\n\nfunction isCompositionRootOrMount(rawTag: string): boolean {\n return Boolean(\n readAttr(rawTag, \"data-composition-id\") || readAttr(rawTag, \"data-composition-src\"),\n );\n}\n\n// Asset references inside CSS `url(...)`/`url(\"...\")`/`url('...')` functions.\n// Returns the inner path without quotes; comments are stripped first so\n// `/* url(foo) */` is ignored. Bare `url()` and `data:` are excluded by the\n// rules that consume this — the helper just yields raw URL values.\nfunction extractCssUrlReferences(css: string): string[] {\n const out: string[] = [];\n const noComments = css.replace(/\\/\\*[\\s\\S]*?\\*\\//g, \"\");\n const urlPattern = /\\burl\\(\\s*([\"']?)([^)\"']+)\\1\\s*\\)/g;\n let m: RegExpExecArray | null;\n while ((m = urlPattern.exec(noComments)) !== null) {\n const raw = (m[2] ?? \"\").trim();\n if (raw) out.push(raw);\n }\n return out;\n}\n\n// Top-level CSS selectors (comma-split) in a stylesheet, skipping at-rule headers\n// (@media/@keyframes/...) and keyframe stops. Heuristic — the lint layer has no\n// full CSS parser, and rules elsewhere in this file scan CSS the same way.\nfunction extractCssSelectors(css: string): string[] {\n const out: string[] = [];\n const noComments = css.replace(/\\/\\*[\\s\\S]*?\\*\\//g, \"\");\n const ruleHeader = /([^{}]+)\\{/g;\n let m: RegExpExecArray | null;\n while ((m = ruleHeader.exec(noComments)) !== null) {\n const header = (m[1] ?? \"\").trim();\n if (!header || header.startsWith(\"@\")) continue;\n for (const sel of header.split(\",\")) {\n const s = sel.trim();\n if (s) out.push(s);\n }\n }\n return out;\n}\n\n// Class tokens in a selector's leftmost compound (before the first descendant /\n// child / sibling combinator). `.frame .title` → [\"frame\"]; `.a.b > .c` → [\"a\",\"b\"].\nfunction leftmostCompoundClasses(selector: string): string[] {\n const leftmost = selector.trim().split(/[\\s>+~]+/)[0] ?? \"\";\n return (leftmost.match(/\\.([\\w-]+)/g) ?? []).map((c) => c.slice(1));\n}\n\n// Distinct selectors across all <style> blocks whose leftmost compound keys off one\n// of the root element's own classes — the ones that break under id-scoping.\nfunction rootClassStyledSelectors(styles: ExtractedBlock[], rootClasses: string[]): string[] {\n const offenders: string[] = [];\n for (const style of styles) {\n for (const selector of extractCssSelectors(style.content)) {\n const hitsRoot = leftmostCompoundClasses(selector).some((c) => rootClasses.includes(c));\n if (hitsRoot && !offenders.includes(selector)) offenders.push(selector);\n }\n }\n return offenders;\n}\n\nexport const compositionRules: Array<(ctx: LintContext) => HyperframeLintFinding[]> = [\n // invalid_parent_traversal_in_asset_path — catches `../` traversal in src,\n // href, inline-style url(), and <style> url() asset references on\n // compositions. Sub-compositions live under compositions/ but are served\n // with the project root as their base URL, so any `../`-traversing path\n // climbs above the project root and 404s in Studio preview. Renders\n // tolerate it because the server-side bundler rewrites `../foo` against\n // each sub-composition's source path; the runtime now mirrors that fallback\n // (see rewriteSubCompositionAssetPaths in runtime/compositionLoader.ts), but\n // the authoring-time signal is still wrong — flag it at lint time so the\n // baked path is plain root-relative and matches what the bundler emits.\n //\n // Mirrors the runtime fallback's surface: `[src]` / `[href]` attribute\n // values, `[style]` inline url(), and `<style>` block url() references.\n // Skips absolute URLs (http(s)://, //, data:, /-prefixed root-relative),\n // hash anchors, and plain relative paths (`assets/x.mp4`) — only `../`\n // traversal is flagged. Subsumes the older `../capture/`-specific rule.\n // fallow-ignore-next-line complexity\n ({ tags, styles, rawSource, options }) => {\n if (isRegistrySourceFile(options.filePath) || isRegistryInstalledFile(rawSource)) return [];\n\n const offenders: string[] = [];\n const collect = (value: string | null) => {\n if (!value) return;\n const trimmed = value.trim();\n if (!trimmed.startsWith(\"../\") && trimmed !== \"..\") return;\n offenders.push(trimmed);\n };\n\n for (const tag of tags) {\n collect(readAttr(tag.raw, \"src\"));\n collect(readAttr(tag.raw, \"href\"));\n // Use readJsonAttr for `style` — inline url('...') values contain the\n // opposite quote, which readAttr's [^\"']+ class would truncate.\n const styleAttr = readJsonAttr(tag.raw, \"style\");\n if (styleAttr) {\n for (const url of extractCssUrlReferences(styleAttr)) collect(url);\n }\n }\n for (const style of styles) {\n for (const url of extractCssUrlReferences(style.content)) collect(url);\n }\n\n if (offenders.length === 0) return [];\n\n // Group counts by leading path token (e.g. ../capture/, ../assets/, ../../assets/)\n // so the message names the offending prefixes instead of a bare count.\n const prefixCounts = new Map<string, number>();\n for (const path of offenders) {\n const prefix = path.match(/^(?:\\.\\.\\/)+[^/]+\\//)?.[0] ?? path;\n prefixCounts.set(prefix, (prefixCounts.get(prefix) ?? 0) + 1);\n }\n const prefixSummary = Array.from(prefixCounts.entries())\n .sort(([, a], [, b]) => b - a)\n .map(([prefix, count]) => (count > 1 ? `${prefix} (${count})` : prefix))\n .join(\", \");\n\n return [\n {\n code: \"invalid_parent_traversal_in_asset_path\",\n severity: \"error\",\n message:\n `Found ${offenders.length} asset path(s) traversing above the project root with \"../\" ` +\n `(${prefixSummary}). Renders rewrite this against each sub-composition's source path, but Studio preview and other live consumers resolve against the project root and 404.`,\n fixHint:\n 'Use plain root-relative paths (e.g. \"assets/...\", \"capture/...\", \"fonts/...\") — compositions are served with the project root as their base URL, so paths must be root-relative, not relative to the compositions/ directory.',\n },\n ];\n },\n\n // composition_file_too_large\n ({ rawSource, options }) => {\n if (isRegistrySourceFile(options.filePath) || isRegistryInstalledFile(rawSource)) return [];\n\n const lineCount = countStructuralLines(rawSource);\n if (lineCount <= MAX_COMPOSITION_LINES) return [];\n\n const splitTarget = options.isSubComposition\n ? \"Split this sub-composition further into smaller .html files\"\n : \"Split coherent scenes or layers into separate .html files under compositions/\";\n\n return [\n {\n code: \"composition_file_too_large\",\n severity: \"warning\",\n message: `This HTML composition file has ${lineCount} lines. Smaller sub-compositions are easier to read, iterate on, and diff.`,\n fixHint: `${splitTarget}, then mount them from the parent with data-composition-src so each file stays small enough to inspect, revise, and validate independently.`,\n },\n ];\n },\n\n // timeline_track_too_dense\n // fallow-ignore-next-line complexity\n ({ tags, options }) => {\n const trackCounts = new Map<string, number>();\n for (const tag of tags) {\n if (TRACK_DENSITY_EXEMPT_TAGS.has(tag.name)) continue;\n if (isCompositionRootOrMount(tag.raw)) continue;\n if (!readAttr(tag.raw, \"data-start\")) continue;\n\n const track = readAttr(tag.raw, \"data-track-index\");\n if (!track) continue;\n trackCounts.set(track, (trackCounts.get(track) ?? 0) + 1);\n }\n\n const findings: HyperframeLintFinding[] = [];\n for (const [track, count] of trackCounts) {\n if (count <= MAX_TIMED_ELEMENTS_PER_TRACK) continue;\n const splitTarget = options.isSubComposition\n ? \"Move coherent scene groups into smaller .html files\"\n : \"Move coherent scene groups into separate .html files under compositions/\";\n findings.push({\n code: \"timeline_track_too_dense\",\n severity: \"warning\",\n message: `Track ${track} has ${count} timed elements in this HTML file. Smaller sub-compositions keep timelines easier to read, iterate on, and diff.`,\n fixHint: `${splitTarget} and mount them from the parent with data-composition-src so the timeline stays easier to inspect, revise, and validate.`,\n });\n }\n\n return findings;\n },\n\n // timed_element_missing_visibility_hidden\n // fallow-ignore-next-line complexity\n ({ tags }) => {\n const findings: HyperframeLintFinding[] = [];\n for (const tag of tags) {\n if (tag.name === \"audio\" || tag.name === \"script\" || tag.name === \"style\") continue;\n if (!readAttr(tag.raw, \"data-start\")) continue;\n if (readAttr(tag.raw, \"data-composition-id\")) continue;\n if (readAttr(tag.raw, \"data-composition-src\")) continue;\n const classAttr = readAttr(tag.raw, \"class\") || \"\";\n const styleAttr = readAttr(tag.raw, \"style\") || \"\";\n const hasClip = classAttr.split(/\\s+/).includes(\"clip\");\n const hasHiddenStyle =\n /visibility\\s*:\\s*hidden/i.test(styleAttr) || /opacity\\s*:\\s*0/i.test(styleAttr);\n if (!hasClip && !hasHiddenStyle) {\n const elementId = readAttr(tag.raw, \"id\") || undefined;\n findings.push({\n code: \"timed_element_missing_visibility_hidden\",\n severity: \"info\",\n message: `<${tag.name}${elementId ? ` id=\"${elementId}\"` : \"\"}> has data-start but no class=\"clip\", visibility:hidden, or opacity:0. Consider adding initial hidden state if the element should not be visible before its start time.`,\n elementId,\n fixHint:\n 'Add class=\"clip\" (with CSS: .clip { visibility: hidden; }) or style=\"opacity:0\" if the element should start hidden.',\n snippet: truncateSnippet(tag.raw),\n });\n }\n }\n return findings;\n },\n\n // deprecated_data_layer + deprecated_data_end\n // fallow-ignore-next-line complexity\n ({ tags }) => {\n const findings: HyperframeLintFinding[] = [];\n for (const tag of tags) {\n if (readAttr(tag.raw, \"data-layer\") && !readAttr(tag.raw, \"data-track-index\")) {\n const elementId = readAttr(tag.raw, \"id\") || undefined;\n findings.push({\n code: \"deprecated_data_layer\",\n severity: \"error\",\n message: `<${tag.name}${elementId ? ` id=\"${elementId}\"` : \"\"}> uses data-layer instead of data-track-index.`,\n elementId,\n fixHint: \"Replace data-layer with data-track-index. The runtime reads data-track-index.\",\n snippet: truncateSnippet(tag.raw),\n });\n }\n if (readAttr(tag.raw, \"data-end\") && !readAttr(tag.raw, \"data-duration\")) {\n const elementId = readAttr(tag.raw, \"id\") || undefined;\n findings.push({\n code: \"deprecated_data_end\",\n severity: \"error\",\n message: `<${tag.name}${elementId ? ` id=\"${elementId}\"` : \"\"}> uses data-end without data-duration. Use data-duration in source HTML.`,\n elementId,\n fixHint:\n \"Replace data-end with data-duration. The compiler generates data-end from data-duration automatically.\",\n snippet: truncateSnippet(tag.raw),\n });\n }\n }\n return findings;\n },\n\n // split_data_attribute_selector\n ({ scripts, styles }) => {\n const findings: HyperframeLintFinding[] = [];\n const splitDataAttrSelectorPattern =\n /\\[data-composition-id=([\"'])([^\"'\\]]+)\\1\\s+(data-[\\w:-]+)=([\"'])([^\"'\\]]*)\\4\\]/g;\n const scan = (content: string) => {\n splitDataAttrSelectorPattern.lastIndex = 0;\n let match: RegExpExecArray | null;\n while ((match = splitDataAttrSelectorPattern.exec(content)) !== null) {\n const compId = match[2] ?? \"\";\n const attrName = match[3] ?? \"\";\n const attrValue = match[5] ?? \"\";\n findings.push({\n code: \"split_data_attribute_selector\",\n severity: \"error\",\n message:\n `Selector \"${match[0]}\" combines two attributes inside one CSS attribute selector. ` +\n \"Browsers reject it, so GSAP timelines or querySelector calls will fail before registering.\",\n selector: match[0],\n fixHint: `Use separate attribute selectors: [data-composition-id=\"${compId}\"][${attrName}=\"${attrValue}\"].`,\n snippet: truncateSnippet(match[0]),\n });\n }\n };\n for (const style of styles) scan(style.content);\n for (const script of scripts) scan(script.content);\n return findings;\n },\n\n // template_literal_selector\n ({ scripts }) => {\n const findings: HyperframeLintFinding[] = [];\n for (const script of scripts) {\n const templateLiteralSelectorPattern =\n /(?:querySelector|querySelectorAll)\\s*\\(\\s*`[^`]*\\$\\{[^}]+\\}[^`]*`\\s*\\)/g;\n let tlMatch: RegExpExecArray | null;\n while ((tlMatch = templateLiteralSelectorPattern.exec(script.content)) !== null) {\n findings.push({\n code: \"template_literal_selector\",\n severity: \"error\",\n message:\n \"querySelector uses a template literal variable (e.g. `${compId}`). \" +\n \"The HTML bundler's CSS parser crashes on these. Use a hardcoded string instead.\",\n fixHint:\n \"Replace the template literal variable with a hardcoded string. The bundler's CSS parser cannot handle interpolated variables in script content.\",\n snippet: truncateSnippet(tlMatch[0]),\n });\n }\n }\n return findings;\n },\n\n // timed_element_missing_clip_class\n // fallow-ignore-next-line complexity\n ({ tags }) => {\n const findings: HyperframeLintFinding[] = [];\n const skipTags = new Set([\"audio\", \"video\", \"script\", \"style\", \"template\"]);\n for (const tag of tags) {\n if (skipTags.has(tag.name)) continue;\n // Skip composition hosts\n if (readAttr(tag.raw, \"data-composition-id\")) continue;\n if (readAttr(tag.raw, \"data-composition-src\")) continue;\n\n const hasStart = readAttr(tag.raw, \"data-start\") !== null;\n const hasDuration = readAttr(tag.raw, \"data-duration\") !== null;\n // data-track-index alone marks a layer container, not a time-bounded clip\n if (!hasStart && !hasDuration) continue;\n\n const classAttr = readAttr(tag.raw, \"class\") || \"\";\n const hasClip = classAttr.split(/\\s+/).includes(\"clip\");\n if (hasClip) continue;\n\n const elementId = readAttr(tag.raw, \"id\") || undefined;\n findings.push({\n code: \"timed_element_missing_clip_class\",\n severity: \"error\",\n message: `<${tag.name}${elementId ? ` id=\"${elementId}\"` : \"\"}> has timing attributes but no class=\"clip\". The element will be visible for the entire composition instead of only during its scheduled time range.`,\n elementId,\n fixHint:\n 'Add class=\"clip\" to the element. The HyperFrames runtime uses .clip to control visibility based on data-start/data-duration.',\n snippet: truncateSnippet(tag.raw),\n });\n }\n return findings;\n },\n\n // overlapping_clips_same_track\n // fallow-ignore-next-line complexity\n ({ tags }) => {\n const findings: HyperframeLintFinding[] = [];\n\n type ClipInfo = { start: number; end: number; elementId?: string; snippet: string };\n const trackMap = new Map<string, ClipInfo[]>();\n\n for (const tag of tags) {\n const startStr = readAttr(tag.raw, \"data-start\");\n const durationStr = readAttr(tag.raw, \"data-duration\");\n const trackStr = readAttr(tag.raw, \"data-track-index\");\n if (!startStr || !durationStr || !trackStr) continue;\n\n const start = Number(startStr);\n const duration = Number(durationStr);\n const track = trackStr;\n\n // Skip non-numeric (relative timing references like \"intro-comp\")\n if (Number.isNaN(start) || Number.isNaN(duration)) continue;\n\n const clips = trackMap.get(track) || [];\n clips.push({\n start,\n end: start + duration,\n elementId: readAttr(tag.raw, \"id\") || undefined,\n snippet: truncateSnippet(tag.raw) || \"\",\n });\n trackMap.set(track, clips);\n }\n\n for (const [track, clips] of trackMap) {\n clips.sort((a, b) => a.start - b.start);\n for (let i = 0; i < clips.length - 1; i++) {\n const current = clips[i];\n const next = clips[i + 1];\n if (!current || !next) continue;\n if (current.end > next.start) {\n findings.push({\n code: \"overlapping_clips_same_track\",\n severity: \"error\",\n message: `Track ${track}: clip ending at ${current.end}s overlaps with clip starting at ${next.start}s. Overlapping clips on the same track cause rendering conflicts.`,\n fixHint:\n \"Adjust data-start or data-duration so clips on the same track do not overlap, or move one clip to a different data-track-index.\",\n });\n }\n }\n }\n\n return findings;\n },\n\n // root_composition_missing_data_start\n ({ rootTag, options }) => {\n const findings: HyperframeLintFinding[] = [];\n if (options.isSubComposition) return findings;\n if (!rootTag) return findings;\n const compId = readAttr(rootTag.raw, \"data-composition-id\");\n if (!compId) return findings;\n const hasStart = readAttr(rootTag.raw, \"data-start\") !== null;\n if (!hasStart) {\n findings.push({\n code: \"root_composition_missing_data_start\",\n severity: \"error\",\n message: `Root composition \"${compId}\" is missing data-start. The runtime needs data-start=\"0\" on the root element to begin playback.`,\n fixHint: 'Add data-start=\"0\" to the root composition element.',\n snippet: truncateSnippet(rootTag.raw),\n });\n }\n return findings;\n },\n\n // standalone_composition_wrapped_in_template\n ({ rawSource, options }) => {\n const findings: HyperframeLintFinding[] = [];\n if (options.isSubComposition) return findings;\n const trimmed = rawSource.trimStart().toLowerCase();\n if (trimmed.startsWith(\"<template\")) {\n findings.push({\n code: \"standalone_composition_wrapped_in_template\",\n severity: \"error\",\n message:\n \"Root index.html is wrapped in a <template> tag. \" +\n \"Only sub-compositions loaded via data-composition-src should use <template> wrappers. \" +\n \"The runtime cannot play a standalone composition inside a template.\",\n fixHint:\n \"Remove the <template> wrapper. Use <!DOCTYPE html><html>...<div data-composition-id>...</div>...</html> instead.\",\n });\n }\n return findings;\n },\n\n // root_composition_missing_html_wrapper\n ({ rawSource, rootTag, options }) => {\n const findings: HyperframeLintFinding[] = [];\n if (options.isSubComposition) return findings;\n const trimmed = rawSource.trimStart().toLowerCase();\n // Compositions inside <template> are caught by standalone_composition_wrapped_in_template\n if (trimmed.startsWith(\"<template\")) return findings;\n const hasDoctype = trimmed.startsWith(\"<!doctype\") || trimmed.startsWith(\"<html\");\n const hasComposition = rawSource.includes(\"data-composition-id\");\n if (hasComposition && !hasDoctype) {\n findings.push({\n code: \"root_composition_missing_html_wrapper\",\n severity: \"error\",\n message:\n \"Composition starts with a bare element instead of a proper HTML document. \" +\n \"An index.html that contains data-composition-id but no <!DOCTYPE html>, <html>, or <body> \" +\n \"is a fragment — browsers quirks-mode it, the preview server cannot load it, and \" +\n \"the bundler will fail to inject runtime scripts.\",\n fixHint:\n 'Wrap the composition in <!DOCTYPE html><html><head><meta charset=\"UTF-8\"></head><body>...</body></html>.',\n snippet: rootTag ? truncateSnippet(rootTag.raw) : undefined,\n });\n }\n return findings;\n },\n\n // requestanimationframe_in_composition\n ({ scripts, rawSource, options }) => {\n if (isRegistrySourceFile(options.filePath) || isRegistryInstalledFile(rawSource)) return [];\n const findings: HyperframeLintFinding[] = [];\n for (const script of scripts) {\n const stripped = stripJsComments(script.content);\n if (/requestAnimationFrame\\s*\\(/.test(stripped)) {\n findings.push({\n code: \"requestanimationframe_in_composition\",\n severity: \"error\",\n message:\n \"`requestAnimationFrame` runs on wall-clock time, not the GSAP timeline. It will not sync with frame capture and may cause flickering or missed frames during rendering.\",\n fixHint:\n \"Use GSAP tweens or onUpdate callbacks instead of requestAnimationFrame for animation logic.\",\n snippet: truncateSnippet(script.content),\n });\n }\n }\n return findings;\n },\n\n // invalid_variable_values_json\n // Host elements (`[data-composition-src]`) carry per-instance values via\n // `data-variable-values`. The runtime swallows JSON errors silently and\n // falls back to declared defaults, which masks typos. This rule surfaces\n // the parse failure so authors notice before render time.\n // fallow-ignore-next-line complexity\n ({ tags }) => {\n const findings: HyperframeLintFinding[] = [];\n for (const tag of tags) {\n const raw = readJsonAttr(tag.raw, \"data-variable-values\");\n if (!raw) continue;\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (err) {\n const reason = err instanceof Error ? err.message : \"unknown\";\n findings.push({\n code: \"invalid_variable_values_json\",\n severity: \"error\",\n message: `data-variable-values is not valid JSON (${reason}).`,\n fixHint:\n 'Wrap the attribute value in single quotes and the JSON keys/values in double quotes, e.g. data-variable-values=\\'{\"title\":\"Hello\"}\\'.',\n elementId: readAttr(tag.raw, \"id\") || undefined,\n snippet: truncateSnippet(tag.raw),\n });\n continue;\n }\n\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n findings.push({\n code: \"invalid_variable_values_json\",\n severity: \"error\",\n message:\n 'data-variable-values must be a JSON object keyed by variable id (e.g. {\"title\":\"Hello\"}).',\n fixHint:\n \"Replace the value with a JSON object whose keys are variable ids declared in the sub-composition's data-composition-variables.\",\n elementId: readAttr(tag.raw, \"id\") || undefined,\n snippet: truncateSnippet(tag.raw),\n });\n }\n }\n return findings;\n },\n\n // invalid_composition_variables_declaration\n // The runtime parses `data-composition-variables` and silently returns []\n // on any structural problem. Surface JSON / shape failures so authors\n // catch them at lint time rather than wondering why their `getVariables()`\n // defaults aren't applied.\n // fallow-ignore-next-line complexity\n ({ source }) => {\n const htmlTag = findHtmlTag(source);\n if (!htmlTag) return [];\n const raw = readJsonAttr(htmlTag.raw, \"data-composition-variables\");\n if (!raw) return [];\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (err) {\n const reason = err instanceof Error ? err.message : \"unknown\";\n return [\n {\n code: \"invalid_composition_variables_declaration\",\n severity: \"error\",\n message: `data-composition-variables is not valid JSON (${reason}).`,\n fixHint:\n 'Provide a JSON array of variable declarations: data-composition-variables=\\'[{\"id\":\"title\",\"type\":\"string\",\"label\":\"Title\",\"default\":\"Hello\"}]\\'.',\n snippet: truncateSnippet(htmlTag.raw),\n },\n ];\n }\n\n if (!Array.isArray(parsed)) {\n return [\n {\n code: \"invalid_composition_variables_declaration\",\n severity: \"error\",\n message: \"data-composition-variables must be a JSON array of variable declarations.\",\n fixHint:\n 'Wrap declarations in [] and give each an id, type, label, and default: \\'[{\"id\":\"title\",\"type\":\"string\",\"label\":\"Title\",\"default\":\"Hello\"}]\\'.',\n snippet: truncateSnippet(htmlTag.raw),\n },\n ];\n }\n\n const findings: HyperframeLintFinding[] = [];\n const knownTypes = new Set<string>(COMPOSITION_VARIABLE_TYPES);\n for (let i = 0; i < parsed.length; i += 1) {\n const entry = parsed[i];\n if (!entry || typeof entry !== \"object\" || Array.isArray(entry)) {\n findings.push({\n code: \"invalid_composition_variables_declaration\",\n severity: \"error\",\n message: `data-composition-variables entry [${i}] must be an object with id, type, label, and default.`,\n snippet: truncateSnippet(htmlTag.raw),\n });\n continue;\n }\n const e = entry as Record<string, unknown>;\n const missing: string[] = [];\n if (typeof e.id !== \"string\") missing.push(\"id\");\n if (typeof e.type !== \"string\" || !knownTypes.has(e.type)) missing.push(\"type\");\n if (typeof e.label !== \"string\") missing.push(\"label\");\n if (!(\"default\" in e)) missing.push(\"default\");\n if (missing.length > 0) {\n findings.push({\n code: \"invalid_composition_variables_declaration\",\n severity: \"error\",\n message: `data-composition-variables entry [${i}] is missing or has invalid: ${missing.join(\", \")}. Type must be one of string, number, color, boolean, enum, font, image.`,\n snippet: truncateSnippet(htmlTag.raw),\n });\n }\n }\n return findings;\n },\n\n // subcomposition_blanks_before_host\n // Warns when a full-bleed sub-composition slot ends before the host composition\n // does, leaving the slot blank for the remainder (issue #1540). Scoped narrowly to\n // the high-signal shape — a sole/dominant external mount starting at ~0 — so it\n // stays silent on intentional short clips (an intro followed by other clips that\n // carry the timeline forward).\n // fallow-ignore-next-line complexity\n ({ tags, rootTag }) => {\n if (!rootTag) return [];\n const rootDuration = Number(readAttr(rootTag.raw, \"data-duration\"));\n if (!Number.isFinite(rootDuration) || rootDuration <= 0) return [];\n\n // Two independent knobs that happen to share a 0.5s magnitude. Tuned for\n // real hosts (tens to hundreds of seconds); on a very short host (~6s) the\n // EPSILON slack would let a ~10% blank tail pass unflagged — acceptable\n // because the silent-blank trap this rule targets only matters at scale.\n const EPSILON = 0.5; // seconds; tolerance for \"ends/covers near the host end\"\n const START_TOLERANCE = 0.5; // seconds; \"starts at the composition start\"\n const round3 = (n: number) => Math.round(n * 1000) / 1000;\n\n // Timed children of the root. An element with data-start but no usable\n // data-duration is treated as covering the tail (end = Infinity), so an\n // unknown-length sibling suppresses the warning rather than triggering it.\n const timed = tags\n .filter((tag) => tag.index !== rootTag.index && readAttr(tag.raw, \"data-start\") !== null)\n .map((tag) => {\n const start = Number(readAttr(tag.raw, \"data-start\")) || 0;\n const dur = Number(readAttr(tag.raw, \"data-duration\"));\n const end = Number.isFinite(dur) && dur > 0 ? start + dur : Infinity;\n return { tag, start, end };\n });\n\n // `tags` is a flat list (no nesting depth), so a timed element nested\n // *inside* a candidate slot is treated as a tail-covering sibling rather\n // than a descendant. Acceptable: external src mounts are empty by\n // convention (content is loaded from the linked file), so the only\n // false-negative path is rare and matches the flat-tag scope of the\n // sibling rules in this file.\n const tailCovered = (exceptIndex: number) =>\n timed.some((t) => t.tag.index !== exceptIndex && t.end >= rootDuration - EPSILON);\n\n const findings: HyperframeLintFinding[] = [];\n for (const t of timed) {\n if (readAttr(t.tag.raw, \"data-composition-src\") === null) continue; // external slot only\n if (t.start > START_TOLERANCE) continue; // must start at the composition start\n if (!Number.isFinite(t.end)) continue; // known, finite slot length\n if (t.end >= rootDuration - EPSILON) continue; // already fills the host window\n if (tailCovered(t.tag.index)) continue; // another clip covers the tail — not full-bleed\n const elementId = readAttr(t.tag.raw, \"id\") || undefined;\n const gap = round3(rootDuration - t.end);\n findings.push({\n code: \"subcomposition_blanks_before_host\",\n severity: \"warning\",\n message: `<${t.tag.name}${elementId ? ` id=\"${elementId}\"` : \"\"}> sub-composition ends at ${round3(t.end)}s but the composition runs to ${round3(rootDuration)}s — its slot will be blank for ~${gap}s.`,\n elementId,\n fixHint: `data-duration is the slot's visible window. Set this sub-composition's data-duration to ${round3(rootDuration - t.start)} to fill the host window, or add another clip to cover the remaining ~${gap}s.`,\n snippet: truncateSnippet(t.tag.raw),\n });\n }\n return findings;\n },\n\n // subcomposition_root_styled_by_class\n // A sub-composition's <style> is scoped at render time to\n // `[data-composition-id=\"<id>\"] <selector>` so scenes inlined into one document\n // can't leak styles into each other. A rule whose LEFTMOST selector is the ROOT\n // element's own class (e.g. `.frame { ... }` on the same element that carries\n // data-composition-id) therefore becomes a DESCENDANT selector that can never\n // match the root — the whole scene renders unstyled (tiny text top-left, images\n // at natural size). lint/validate/inspect evaluate the file in isolation (no\n // scoping) and Studio previews each scene in its own iframe (no scoping), so the\n // break is invisible until the composited MP4 render. Style the root via `#root`\n // (the scoper special-cases the root id) and descendants via plain selectors,\n // like the registry blocks — the runtime already scopes each scene by id, so a\n // class namespace on the root is redundant.\n ({ rootTag, rootCompositionId, styles, options }) => {\n if (!options.isSubComposition) return [];\n if (isRegistrySourceFile(options.filePath)) return [];\n if (!rootTag || !rootCompositionId) return [];\n\n const rootClasses = (readAttr(rootTag.raw, \"class\") || \"\").split(/\\s+/).filter(Boolean);\n if (rootClasses.length === 0) return [];\n\n const offenders = rootClassStyledSelectors(styles, rootClasses);\n if (offenders.length === 0) return [];\n\n const example = offenders.slice(0, 3).join(\", \");\n return [\n {\n code: \"subcomposition_root_styled_by_class\",\n severity: \"error\",\n message:\n `Root element has class=\"${rootClasses.join(\" \")}\" and is styled by ${offenders.length} rule(s) keyed off that class (e.g. ${example}). ` +\n `At render, every sub-composition rule is scoped to [data-composition-id=\"${rootCompositionId}\"] <selector>, so a selector whose leftmost part is the ROOT's own class becomes a descendant selector that cannot match the root — the scene renders unstyled (tiny text top-left, full-size images). ` +\n `lint/validate/inspect and Studio's per-frame iframe preview do not scope, so this passes every static check and looks correct in preview.`,\n selector: example,\n fixHint: `Give the root id=\"root\" and style it with \\`#root { ... }\\` plus plain descendant selectors (\\`.kicker\\`, \\`#hero\\`) — the runtime already scopes each sub-composition by data-composition-id, so a class namespace on the root is redundant and breaks under scoping.`,\n snippet: truncateSnippet(rootTag.raw),\n },\n ];\n },\n];\n","import type { LintContext, HyperframeLintFinding } from \"../context\";\nimport { readAttr, extractScriptTextsAndSrcs } from \"../utils\";\n\nexport const adapterRules: Array<(ctx: LintContext) => HyperframeLintFinding[]> = [\n // missing_lottie_script\n ({ tags, scripts }) => {\n const { texts, srcs } = extractScriptTextsAndSrcs(scripts);\n\n const hasLottieAttr = tags.some((t) => readAttr(t.raw, \"data-lottie-src\") !== null);\n const usesLottieApi = texts.some((t) =>\n /lottie\\.(loadAnimation|setSpeed|play|stop|destroy)\\b/.test(t),\n );\n const hasLottieScript = srcs.some((src) => /lottie/i.test(src));\n\n if (!(hasLottieAttr || usesLottieApi) || hasLottieScript) return [];\n return [\n {\n code: \"missing_lottie_script\",\n severity: \"error\",\n message:\n \"Composition uses Lottie but no Lottie script is loaded. The animation will not render.\",\n fixHint:\n 'Add <script src=\"https://cdn.jsdelivr.net/npm/lottie-web@5/build/player/lottie.min.js\"></script> before your Lottie code.',\n },\n ];\n },\n\n // missing_three_script\n ({ scripts }) => {\n const { texts, srcs } = extractScriptTextsAndSrcs(scripts);\n\n const usesThree = texts.some((t) => /\\bTHREE\\./.test(t));\n const hasThreeScript = srcs.some((src) => /three/i.test(src));\n const hasThreeImportMap = texts.some(\n (t) =>\n /[\"']three[\"']/.test(t) &&\n /importmap/.test(scripts.find((s) => s.content === t)?.attrs || \"\"),\n );\n const hasThreeModuleImport = texts.some(\n (t) => /\\bimport\\b.*['\"]three['\"]/.test(t) || /\\bfrom\\s+['\"]three['\"]/.test(t),\n );\n\n if (!usesThree || hasThreeScript || hasThreeImportMap || hasThreeModuleImport) return [];\n return [\n {\n code: \"missing_three_script\",\n severity: \"error\",\n message:\n \"Composition uses Three.js but no Three.js script is loaded. The 3D scene will not render.\",\n fixHint:\n 'Add <script src=\"https://cdn.jsdelivr.net/npm/three@0.160/build/three.min.js\"></script> before your Three.js code.',\n },\n ];\n },\n];\n","import postcss from \"postcss\";\nimport type { LintContext, HyperframeLintFinding, OpenTag } from \"../context\";\nimport { readAttr, truncateSnippet } from \"../utils\";\n\nconst TEXTURE_BASE_CLASS = \"hf-texture-text\";\nconst TEXTURE_CLASS_PREFIX = \"hf-texture-\";\n\ntype DropShadowRule = {\n selector: string;\n directlyTargetsTexture: boolean;\n};\n\nfunction classNames(tag: OpenTag): string[] {\n return (readAttr(tag.raw, \"class\") ?? \"\").split(/\\s+/).filter(Boolean);\n}\n\nfunction isTextureMaterialClass(className: string): boolean {\n return className.startsWith(TEXTURE_CLASS_PREFIX) && className !== TEXTURE_BASE_CLASS;\n}\n\nfunction hasInlineMaskImage(tag: OpenTag): boolean {\n const style = readAttr(tag.raw, \"style\") ?? \"\";\n return /\\b(?:-webkit-)?mask-image\\s*:/i.test(style);\n}\n\nfunction hasInlineDropShadow(tag: OpenTag): boolean {\n const style = readAttr(tag.raw, \"style\") ?? \"\";\n return /\\bfilter\\s*:\\s*[^;]*\\bdrop-shadow\\s*\\(/i.test(style);\n}\n\nfunction classNamesInSelector(selector: string): string[] {\n const classes = new Set<string>();\n const pattern = /\\.([A-Za-z_][\\w-]*)/g;\n let match: RegExpExecArray | null;\n while ((match = pattern.exec(selector)) !== null) {\n const className = match[1];\n if (!className) continue;\n classes.add(className);\n }\n return [...classes];\n}\n\nfunction textureClassesInSelector(selector: string): string[] {\n return classNamesInSelector(selector).filter(isTextureMaterialClass);\n}\n\nfunction simpleSelectorMatchesTag(selector: string, tag: OpenTag, tagClasses: string[]): boolean {\n const trimmed = selector.trim();\n const simpleSelectorPattern = /^(?:[A-Za-z][\\w-]*)?(?:\\.[A-Za-z_][\\w-]*)+$/;\n if (!simpleSelectorPattern.test(trimmed)) return false;\n\n const typeMatch = /^([A-Za-z][\\w-]*)/.exec(trimmed);\n if (typeMatch && typeMatch[1]!.toLowerCase() !== tag.name) return false;\n\n const selectorClasses = classNamesInSelector(trimmed);\n return (\n selectorClasses.length > 0 &&\n selectorClasses.every((className) => tagClasses.includes(className))\n );\n}\n\nfunction collectTextureCss(styles: LintContext[\"styles\"]): {\n definedTextureClasses: Set<string>;\n dropShadowRules: DropShadowRule[];\n} {\n const definedTextureClasses = new Set<string>();\n const dropShadowRules: DropShadowRule[] = [];\n const roots: postcss.Root[] = [];\n\n for (const style of styles) {\n let root: postcss.Root;\n try {\n root = postcss.parse(style.content);\n } catch {\n continue;\n }\n roots.push(root);\n\n // fallow-ignore-next-line complexity\n root.walkRules((rule) => {\n const selectors = rule.selectors ?? [];\n let hasMaskImage = false;\n\n for (const node of rule.nodes ?? []) {\n if (node.type !== \"decl\") continue;\n const prop = node.prop.toLowerCase();\n if (prop === \"mask-image\" || prop === \"-webkit-mask-image\") hasMaskImage = true;\n }\n\n if (hasMaskImage) {\n for (const selector of selectors) {\n for (const className of textureClassesInSelector(selector)) {\n definedTextureClasses.add(className);\n }\n }\n }\n });\n }\n\n for (const root of roots) {\n // fallow-ignore-next-line complexity\n root.walkRules((rule) => {\n const selectors = rule.selectors ?? [];\n let hasDropShadow = false;\n\n for (const node of rule.nodes ?? []) {\n if (node.type !== \"decl\") continue;\n if (node.prop.toLowerCase() === \"filter\" && /\\bdrop-shadow\\s*\\(/i.test(node.value)) {\n hasDropShadow = true;\n }\n }\n\n if (hasDropShadow) {\n for (const selector of selectors) {\n const targetsBaseClass = /\\.hf-texture-text\\b/.test(selector);\n const targetsDefinedTextureClass = textureClassesInSelector(selector).some((className) =>\n definedTextureClasses.has(className),\n );\n dropShadowRules.push({\n selector,\n directlyTargetsTexture: targetsBaseClass || targetsDefinedTextureClass,\n });\n }\n }\n });\n }\n\n return { definedTextureClasses, dropShadowRules };\n}\n\n// fallow-ignore-next-line complexity\nexport const textureRules: Array<(ctx: LintContext) => HyperframeLintFinding[]> = [\n ({ tags, styles }) => {\n const findings: HyperframeLintFinding[] = [];\n const { definedTextureClasses, dropShadowRules } = collectTextureCss(styles);\n\n for (const { selector, directlyTargetsTexture } of dropShadowRules) {\n if (!directlyTargetsTexture) continue;\n findings.push({\n code: \"texture_drop_shadow_on_text\",\n severity: \"warning\",\n message: \"Drop shadow is applied directly to textured text.\",\n selector,\n fixHint:\n \"Wrap the textured text and apply `filter: drop-shadow(...)` to the wrapper, not the `hf-texture-text` element.\",\n });\n }\n\n for (const tag of tags) {\n if (tag.name === \"style\" || tag.name === \"script\") continue;\n\n const classes = classNames(tag);\n if (classes.length === 0) continue;\n\n const hasBaseClass = classes.includes(TEXTURE_BASE_CLASS);\n const textureClasses = classes.filter(isTextureMaterialClass);\n\n if (textureClasses.length > 0 && !hasBaseClass) {\n findings.push({\n code: \"texture_class_missing_base\",\n severity: \"warning\",\n message: `Texture material class \\`${textureClasses[0]}\\` is used without \\`${TEXTURE_BASE_CLASS}\\`.`,\n elementId: readAttr(tag.raw, \"id\") || undefined,\n fixHint: `Add \\`${TEXTURE_BASE_CLASS}\\` alongside the material class, for example \\`class=\"${TEXTURE_BASE_CLASS} ${textureClasses[0]}\"\\`.`,\n snippet: truncateSnippet(tag.raw),\n });\n }\n\n if (hasBaseClass && textureClasses.length === 0 && !hasInlineMaskImage(tag)) {\n findings.push({\n code: \"texture_text_missing_mask\",\n severity: \"warning\",\n message: `\\`${TEXTURE_BASE_CLASS}\\` is used without a texture material class or custom mask image.`,\n elementId: readAttr(tag.raw, \"id\") || undefined,\n fixHint:\n \"Add a material class such as `hf-texture-lava`, or set `mask-image` and `-webkit-mask-image` on the element.\",\n snippet: truncateSnippet(tag.raw),\n });\n }\n\n for (const textureClass of textureClasses) {\n if (definedTextureClasses.has(textureClass)) continue;\n findings.push({\n code: \"texture_class_unknown\",\n severity: \"error\",\n message: `Texture material class \\`${textureClass}\\` is not defined by local CSS.`,\n elementId: readAttr(tag.raw, \"id\") || undefined,\n fixHint:\n \"Paste the Texture Mask Text component `<style>...</style>` block into the composition, or fix the texture class typo.\",\n snippet: truncateSnippet(tag.raw),\n });\n }\n\n if (hasBaseClass) {\n for (const rule of dropShadowRules) {\n if (rule.directlyTargetsTexture) continue;\n if (!simpleSelectorMatchesTag(rule.selector, tag, classes)) continue;\n findings.push({\n code: \"texture_drop_shadow_on_text\",\n severity: \"warning\",\n message: \"Drop shadow is applied directly to textured text.\",\n selector: rule.selector,\n elementId: readAttr(tag.raw, \"id\") || undefined,\n fixHint:\n \"Wrap the textured text and apply `filter: drop-shadow(...)` to the wrapper, not the `hf-texture-text` element.\",\n snippet: truncateSnippet(tag.raw),\n });\n }\n }\n\n if (hasBaseClass && hasInlineDropShadow(tag)) {\n findings.push({\n code: \"texture_drop_shadow_on_text\",\n severity: \"warning\",\n message: \"Drop shadow is applied directly to textured text.\",\n elementId: readAttr(tag.raw, \"id\") || undefined,\n fixHint:\n \"Wrap the textured text and apply `filter: drop-shadow(...)` to the wrapper, not the `hf-texture-text` element.\",\n snippet: truncateSnippet(tag.raw),\n });\n }\n }\n\n return findings;\n },\n];\n","import { FONT_ALIAS_KEYS, resolveAliasDisplayName } from \"@hyperframes/parsers/composition\";\nimport type { LintContext, HyperframeLintFinding } from \"../context\";\nimport { isRegistrySourceFile, isRegistryInstalledFile } from \"./composition\";\n\nconst GENERIC_FAMILIES = new Set([\n \"serif\",\n \"sans-serif\",\n \"monospace\",\n \"cursive\",\n \"fantasy\",\n \"system-ui\",\n \"ui-serif\",\n \"ui-sans-serif\",\n \"ui-monospace\",\n \"ui-rounded\",\n \"math\",\n \"emoji\",\n \"fangsong\",\n \"inherit\",\n \"initial\",\n \"unset\",\n \"revert\",\n]);\n\n// A CSS comment can contain a `}` (e.g. `@font-face { /* 400 } regular */\n// font-family: 'X'; ... }`), which truncates the naive `@font-face\\s*\\{[^}]*\\}`\n// block match at the comment's brace — so the rule never sees the real\n// `font-family` and reports a false-positive font_family_without_font_face.\n// Large/\"framework\" stylesheets hit this far more often than minimal ones,\n// which is why a simple <style> passes while a complex one fails. Strip\n// comments before scanning so a brace inside one cannot split a block. See #1534.\nfunction stripCssComments(css: string): string {\n return css.replace(/\\/\\*[\\s\\S]*?\\*\\//g, \" \");\n}\n\nfunction extractFontFaceFamilies(styles: Array<{ content: string }>): Set<string> {\n const families = new Set<string>();\n const fontFaceRe = /@font-face\\s*\\{[^}]*\\}/gi;\n const familyRe = /font-family\\s*:\\s*(['\"]?)([^;'\"]+)\\1/i;\n for (const style of styles) {\n const content = stripCssComments(style.content);\n let match: RegExpExecArray | null;\n while ((match = fontFaceRe.exec(content)) !== null) {\n const familyMatch = match[0].match(familyRe);\n if (familyMatch?.[2]) {\n families.add(familyMatch[2].trim().toLowerCase());\n }\n }\n }\n return families;\n}\n\nfunction extractUsedFontFamilies(styles: Array<{ content: string }>): string[] {\n const used: string[] = [];\n const seen = new Set<string>();\n const propRe = /font-family\\s*:\\s*([^;}{]+)/gi;\n for (const style of styles) {\n const withoutFontFace = stripCssComments(style.content).replace(/@font-face\\s*\\{[^}]*\\}/gi, \"\");\n let match: RegExpExecArray | null;\n while ((match = propRe.exec(withoutFontFace)) !== null) {\n const stack = match[1]!;\n for (const part of stack.split(\",\")) {\n const name = part\n .trim()\n .replace(/^['\"]|['\"]$/g, \"\")\n .trim()\n .toLowerCase();\n if (name && !GENERIC_FAMILIES.has(name) && !seen.has(name)) {\n seen.add(name);\n used.push(name);\n }\n }\n }\n }\n return used;\n}\n\nfunction collectAliasedFonts(used: string[], declared: Set<string>): string[] {\n const aliased: string[] = [];\n for (const name of used) {\n if (declared.has(name)) continue;\n const displayName = resolveAliasDisplayName(name);\n if (!displayName) continue;\n if (displayName.toLowerCase() === name) continue;\n aliased.push(`'${name}' → ${displayName}`);\n }\n return aliased;\n}\n\nfunction normalizeFontFamily(name: string): string | null {\n const decoded = name.replace(/\\+/g, \" \").trim();\n if (!decoded) return null;\n try {\n return decodeURIComponent(decoded).trim().toLowerCase() || null;\n } catch {\n return decoded.toLowerCase();\n }\n}\n\nfunction extractGoogleFontFamiliesFromUrl(rawUrl: string): string[] {\n const url = rawUrl.replace(/&amp;/gi, \"&\");\n let parsed: URL;\n try {\n parsed = new URL(url, \"https://fonts.googleapis.com\");\n } catch {\n return [];\n }\n\n if (parsed.hostname.toLowerCase() !== \"fonts.googleapis.com\") return [];\n const families: string[] = [];\n for (const value of parsed.searchParams.getAll(\"family\")) {\n for (const familySpec of value.split(\"|\")) {\n const family = normalizeFontFamily(familySpec.split(\":\")[0] || \"\");\n if (family) families.push(family);\n }\n }\n return families;\n}\n\nfunction collectGoogleFontFamilies(\n source: string,\n styles: Array<{ content: string }>,\n): Set<string> {\n const families = new Set<string>();\n const addUrl = (url: string) => {\n for (const family of extractGoogleFontFamiliesFromUrl(url)) families.add(family);\n };\n\n const linkHrefRe =\n /<link\\b[^>]*\\bhref\\s*=\\s*(?:([\"'])([^\"']*fonts\\.googleapis\\.com[^\"']*)\\1|([^\\s>]*fonts\\.googleapis\\.com[^\\s>]*))[^>]*>/gi;\n for (const match of source.matchAll(linkHrefRe)) {\n const href = match[2] || match[3];\n if (href) addUrl(href);\n }\n\n const importUrlRe =\n /@import\\s+(?:url\\(\\s*)?([\"']?)([^\"')\\s]*fonts\\.googleapis\\.com[^\"')\\s]*)\\1\\s*\\)?/gi;\n for (const style of styles) {\n for (const match of style.content.matchAll(importUrlRe)) {\n if (match[2]) addUrl(match[2]);\n }\n }\n\n return families;\n}\n\nexport const fontRules: Array<(ctx: LintContext) => HyperframeLintFinding[]> = [\n // google_fonts_import\n ({ styles, source, rawSource, options }) => {\n if (isRegistrySourceFile(options.filePath) || isRegistryInstalledFile(rawSource)) return [];\n const findings: HyperframeLintFinding[] = [];\n const googleFontsInLink = /<link\\b[^>]*fonts\\.googleapis\\.com[^>]*>/i.test(source);\n const googleFontsInImport = styles.some((s) =>\n /@import\\s+url\\s*\\(\\s*['\"]?[^)]*fonts\\.googleapis\\.com/i.test(s.content),\n );\n\n if (googleFontsInLink || googleFontsInImport) {\n findings.push({\n code: \"google_fonts_import\",\n severity: \"warning\",\n message:\n \"Composition loads fonts from fonts.googleapis.com. The producer resolves Google Fonts \" +\n \"during compile/render, but raw external font requests add latency and can fail before \" +\n \"canonicalization. Prefer mapped family names or local @font-face declarations when possible.\",\n fixHint:\n \"For bundled fonts, remove the Google Fonts <link> or @import and keep the font-family \" +\n \"declaration. For custom fonts, use @font-face { font-family: '...'; src: url('...woff2'); }.\",\n });\n }\n return findings;\n },\n\n // system_font_will_alias — inform when a font will be silently substituted\n ({ styles, options }) => {\n const declared = extractFontFaceFamilies(styles);\n const used = extractUsedFontFamilies(styles);\n const aliased = collectAliasedFonts(used, declared);\n if (aliased.length === 0) return [];\n // In distributed / Lambda renders system-font capture is disabled, so\n // the alias substitution does NOT happen — elevate to a warning.\n const severity = options.distributed ? (\"warning\" as const) : (\"info\" as const);\n return [\n {\n code: \"system_font_will_alias\",\n severity,\n message:\n `Font ${aliased.length === 1 ? \"family\" : \"families\"} will be substituted at render time: ${aliased.join(\", \")}. ` +\n (options.distributed\n ? \"In distributed/Lambda rendering system-font capture is disabled — these fonts will fall back to OS defaults. Embed explicit @font-face declarations instead.\"\n : \"The renderer maps these to bundled fonts for cross-platform consistency. \" +\n \"Use the target font name directly for consistent preview and render results.\"),\n },\n ];\n },\n\n // font_family_without_font_face\n ({ styles, source, rawSource, options }) => {\n if (isRegistrySourceFile(options.filePath) || isRegistryInstalledFile(rawSource)) return [];\n const findings: HyperframeLintFinding[] = [];\n const declared = extractFontFaceFamilies(styles);\n const used = extractUsedFontFamilies(styles);\n const googleFonts = collectGoogleFontFamilies(source, styles);\n\n const undeclared = used.filter(\n (name) => !declared.has(name) && !FONT_ALIAS_KEYS.has(name) && !googleFonts.has(name),\n );\n if (undeclared.length === 0) return findings;\n\n findings.push({\n code: \"font_family_without_font_face\",\n severity: \"error\",\n message:\n `Font ${undeclared.length === 1 ? \"family\" : \"families\"} used without @font-face declaration: ${undeclared.join(\", \")}. ` +\n \"These are not in the auto-resolved font list, so the renderer cannot supply them automatically. \" +\n \"Text will fall back to a generic font, producing incorrect typography in the video.\",\n fixHint:\n \"Add @font-face { font-family: '...'; src: url('capture/assets/fonts/...woff2'); } \" +\n \"for each font family, pointing to the captured .woff2 files.\",\n });\n return findings;\n },\n];\n","import type { LintContext, HyperframeLintFinding } from \"../context\";\nimport type { LintRule } from \"../types\";\nimport { readAttr } from \"../utils\";\nimport {\n parseSlideshowManifest,\n resolveSlideshow,\n isSceneLikeCompositionId,\n} from \"@hyperframes/parsers/slideshow\";\n\ntype Scene = { id: string; start: number; duration: number };\n\nfunction parseTiming(raw: string): { start: number; duration: number } | null {\n const startStr = readAttr(raw, \"data-start\");\n if (startStr === null) return null;\n const start = Number(startStr);\n if (!Number.isFinite(start)) return null;\n\n const durationStr = readAttr(raw, \"data-duration\");\n if (durationStr !== null) {\n const duration = Number(durationStr);\n if (Number.isFinite(duration)) return { start, duration };\n }\n const endStr = readAttr(raw, \"data-end\") ?? readAttr(raw, \"data-hf-authored-end\");\n if (endStr !== null) {\n const end = Number(endStr);\n if (Number.isFinite(end) && end > start) return { start, duration: end - start };\n }\n return null;\n}\n\nfunction collectCompositionIdScenes(ctx: LintContext, seen: Set<string>, out: Scene[]): void {\n for (const tag of ctx.tags) {\n const compositionId = readAttr(tag.raw, \"data-composition-id\");\n if (!compositionId || !isSceneLikeCompositionId(compositionId) || seen.has(compositionId))\n continue;\n const timing = parseTiming(tag.raw);\n if (!timing || timing.duration <= 0) continue;\n seen.add(compositionId);\n out.push({ id: compositionId, ...timing });\n }\n}\n\nfunction extractScenesFromClips(ctx: LintContext): Scene[] {\n const seen = new Set<string>();\n const scenes: Scene[] = [];\n collectCompositionIdScenes(ctx, seen, scenes);\n return scenes;\n}\n\nexport const slideshowRules: LintRule<LintContext>[] = [\n (ctx) => {\n const findings: HyperframeLintFinding[] = [];\n\n let manifest;\n try {\n manifest = parseSlideshowManifest(ctx.source);\n } catch (e) {\n findings.push({\n code: \"slideshow_invalid\",\n severity: \"error\",\n message: `Slideshow island contains invalid JSON or structure: ${e instanceof Error ? e.message : String(e)}`,\n fixHint:\n 'Ensure the <script type=\"application/hyperframes-slideshow+json\"> block contains valid JSON matching the SlideshowManifest schema.',\n });\n return findings;\n }\n\n if (!manifest) return findings;\n\n const scenes = extractScenesFromClips(ctx);\n const { errors } = resolveSlideshow(manifest, scenes);\n\n for (const error of errors) {\n findings.push({\n code: \"slideshow_unresolved_ref\",\n severity: \"error\",\n message: `Slideshow manifest error: ${error}`,\n fixHint:\n \"Ensure every sceneId in the slideshow island matches the data-composition-id of a scene element in the composition, or provide explicit startTime/endTime.\",\n });\n }\n\n return findings;\n },\n];\n","import type { HyperframeLintFinding, HyperframeLintResult, HyperframeLinterOptions } from \"./types\";\nimport { buildLintContext } from \"./context\";\nimport { readAttr, truncateSnippet } from \"./utils\";\nimport { coreRules } from \"./rules/core\";\nimport { mediaRules } from \"./rules/media\";\nimport { gsapRules } from \"./rules/gsap\";\nimport { captionRules } from \"./rules/captions\";\nimport { compositionRules } from \"./rules/composition\";\nimport { adapterRules } from \"./rules/adapters\";\nimport { textureRules } from \"./rules/textures\";\nimport { fontRules } from \"./rules/fonts\";\nimport { slideshowRules } from \"./rules/slideshow\";\n\nconst ALL_RULES = [\n ...coreRules,\n ...mediaRules,\n ...gsapRules,\n ...captionRules,\n ...compositionRules,\n ...adapterRules,\n ...textureRules,\n ...fontRules,\n ...slideshowRules,\n];\n\nexport async function lintHyperframeHtml(\n html: string,\n options: HyperframeLinterOptions = {},\n): Promise<HyperframeLintResult> {\n const ctx = buildLintContext(html, options);\n const findings: HyperframeLintFinding[] = [];\n const seen = new Set<string>();\n\n for (const rule of ALL_RULES) {\n for (const finding of await Promise.resolve(rule(ctx))) {\n const dedupeKey = [\n finding.code,\n finding.severity,\n finding.selector || \"\",\n finding.elementId || \"\",\n finding.message,\n ].join(\"|\");\n if (seen.has(dedupeKey)) continue;\n seen.add(dedupeKey);\n findings.push(options.filePath ? { ...finding, file: options.filePath } : finding);\n }\n }\n\n const errorCount = findings.filter((f) => f.severity === \"error\").length;\n const warningCount = findings.filter((f) => f.severity === \"warning\").length;\n const infoCount = findings.filter((f) => f.severity === \"info\").length;\n\n return {\n ok: errorCount === 0,\n errorCount,\n warningCount,\n infoCount,\n findings,\n };\n}\n\n// ── Async media URL accessibility checker ─────────────────────────────────\n\nfunction extractMediaUrls(html: string): Array<{\n url: string;\n tagName: string;\n elementId?: string;\n snippet: string;\n}> {\n const results: Array<{\n url: string;\n tagName: string;\n elementId?: string;\n snippet: string;\n }> = [];\n const tagRe = /<(video|audio|img|source)\\b[^>]*>/gi;\n let match: RegExpExecArray | null;\n while ((match = tagRe.exec(html)) !== null) {\n const tagName = (match[1] ?? \"\").toLowerCase();\n const raw = match[0];\n const src = readAttr(raw, \"src\");\n if (!src) continue;\n if (/^https?:\\/\\//i.test(src)) {\n results.push({\n url: src,\n tagName,\n elementId: readAttr(raw, \"id\") || undefined,\n snippet: truncateSnippet(raw) ?? \"\",\n });\n }\n }\n return results;\n}\n\n/**\n * Async lint pass: HEAD-checks every remote media URL in the HTML.\n * Returns findings for URLs that are unreachable (non-2xx status or network error).\n *\n * Call this after `lintHyperframeHtml()` and merge the findings.\n *\n * @param timeoutMs - per-request timeout (default 8000ms)\n */\nexport async function lintMediaUrls(\n html: string,\n options: { timeoutMs?: number } = {},\n): Promise<HyperframeLintFinding[]> {\n const urls = extractMediaUrls(html);\n if (urls.length === 0) return [];\n\n const timeout = options.timeoutMs ?? 8000;\n const findings: HyperframeLintFinding[] = [];\n\n const seen = new Set<string>();\n const unique = urls.filter((u) => {\n if (seen.has(u.url)) return false;\n seen.add(u.url);\n return true;\n });\n\n const checks = unique.map(async ({ url, tagName, elementId, snippet }) => {\n try {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeout);\n const resp = await fetch(url, {\n method: \"HEAD\",\n signal: controller.signal,\n redirect: \"follow\",\n });\n clearTimeout(timer);\n if (!resp.ok) {\n findings.push({\n code: \"inaccessible_media_url\",\n severity: \"error\",\n message: `<${tagName}${elementId ? ` id=\"${elementId}\"` : \"\"}> references a URL that returned HTTP ${resp.status}: ${url.slice(0, 100)}`,\n elementId,\n fixHint: \"This URL is not accessible. Replace with a valid, reachable media URL.\",\n snippet,\n });\n }\n } catch (err) {\n const reason = err instanceof Error ? err.name : \"unknown\";\n findings.push({\n code: \"inaccessible_media_url\",\n severity: \"error\",\n message: `<${tagName}${elementId ? ` id=\"${elementId}\"` : \"\"}> references an unreachable URL (${reason}): ${url.slice(0, 100)}`,\n elementId,\n fixHint: \"This URL is not accessible. Replace with a valid, reachable media URL.\",\n snippet,\n });\n }\n });\n\n await Promise.all(checks);\n return findings;\n}\n","/**\n * Pure render-gate decision — no Node.js dependencies, so it is safe to import\n * from the browser entry alongside the rule engine.\n */\nexport function shouldBlockRender(\n strictErrors: boolean,\n strictAll: boolean,\n totalErrors: number,\n totalWarnings: number,\n): boolean {\n return (strictErrors && totalErrors > 0) || (strictAll && (totalErrors > 0 || totalWarnings > 0));\n}\n","export { shouldBlockRender } from \"./shouldBlockRender.js\";\nimport { existsSync, readFileSync, readdirSync } from \"node:fs\";\nimport { dirname, extname, isAbsolute, join, posix, relative, resolve } from \"node:path\";\nimport { decodeUrlPathVariants } from \"@hyperframes/parsers/composition\";\nimport { rewriteAssetPath } from \"@hyperframes/parsers/asset-paths\";\nimport { lintHyperframeHtml } from \"./hyperframeLinter.js\";\nimport type { HyperframeLintFinding, HyperframeLintResult } from \"./types.js\";\n\ninterface HtmlSource {\n html: string;\n compSrcPath?: string;\n}\n\ninterface CssSource {\n content: string;\n rootRelativePath?: string;\n}\n\nexport interface ProjectLintResult {\n results: Array<{ file: string; result: HyperframeLintResult }>;\n totalErrors: number;\n totalWarnings: number;\n totalInfos: number;\n}\n\nconst AUDIO_EXTENSIONS = new Set([\".mp3\", \".wav\", \".aac\", \".ogg\", \".m4a\", \".flac\", \".opus\"]);\nconst STYLE_BLOCK_RE = /<style\\b[^>]*>([\\s\\S]*?)<\\/style>/gi;\nconst OPEN_TAG_RE = /<([a-z][\\w:-]*)(\\s[^<>]*?)?>/gi;\nconst MASK_IMAGE_URL_RE =\n /\\b(?:-webkit-)?mask-image\\s*:\\s*[^;{}]*url\\(\\s*(?:\"([^\"]+)\"|'([^']+)'|([^\"')\\s]+))\\s*\\)/gi;\n\nfunction readHtmlAttr(tag: string, name: string): string | null {\n const escaped = name.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n const match = tag.match(new RegExp(`\\\\b${escaped}\\\\s*=\\\\s*(?:\"([^\"]*)\"|'([^']*)')`, \"i\"));\n return match?.[1] ?? match?.[2] ?? null;\n}\n\nfunction isLocalStylesheetHref(href: string): boolean {\n return !!href && !/^(https?:|data:|blob:|\\/\\/)/i.test(href);\n}\n\nfunction collectExternalStyles(\n projectDir: string,\n html: string,\n compSrcPath?: string,\n): Array<{ href: string; content: string }> {\n const styles: Array<{ href: string; content: string }> = [];\n const linkRe = /<link\\b[^>]*>/gi;\n let match: RegExpExecArray | null;\n while ((match = linkRe.exec(html)) !== null) {\n const tag = match[0];\n const rel = tag.match(/\\brel\\s*=\\s*[\"']([^\"']+)[\"']/i)?.[1] ?? \"\";\n if (!rel.split(/\\s+/).some((part) => part.toLowerCase() === \"stylesheet\")) continue;\n const href = tag.match(/\\bhref\\s*=\\s*[\"']([^\"']+)[\"']/i)?.[1] ?? \"\";\n if (!isLocalStylesheetHref(href)) continue;\n const rootRelative = compSrcPath ? join(dirname(compSrcPath), href) : href;\n const stylesheet = resolveExistingLocalAsset(projectDir, rootRelative);\n if (!stylesheet) continue;\n styles.push({ href, content: readFileSync(stylesheet.resolved, \"utf-8\") });\n }\n return styles;\n}\n\nfunction collectCssSources(projectDir: string, html: string, compSrcPath?: string): CssSource[] {\n const sources: CssSource[] = [];\n\n let styleMatch: RegExpExecArray | null;\n const stylePattern = new RegExp(STYLE_BLOCK_RE.source, STYLE_BLOCK_RE.flags);\n while ((styleMatch = stylePattern.exec(html)) !== null) {\n sources.push({ content: styleMatch[1] ?? \"\" });\n }\n\n const linkRe = /<link\\b[^>]*>/gi;\n let linkMatch: RegExpExecArray | null;\n while ((linkMatch = linkRe.exec(html)) !== null) {\n const tag = linkMatch[0];\n const rel = readHtmlAttr(tag, \"rel\") ?? \"\";\n if (!rel.split(/\\s+/).some((part) => part.toLowerCase() === \"stylesheet\")) continue;\n const href = readHtmlAttr(tag, \"href\") ?? \"\";\n if (!isLocalStylesheetHref(href)) continue;\n\n const rootRelativePath = compSrcPath ? join(dirname(compSrcPath), href) : href;\n const stylesheet = resolveExistingLocalAsset(projectDir, rootRelativePath);\n if (!stylesheet) continue;\n sources.push({\n content: readFileSync(stylesheet.resolved, \"utf-8\"),\n rootRelativePath: stylesheet.rootRelativePath,\n });\n }\n\n let tagMatch: RegExpExecArray | null;\n const tagPattern = new RegExp(OPEN_TAG_RE.source, OPEN_TAG_RE.flags);\n while ((tagMatch = tagPattern.exec(html)) !== null) {\n const tag = tagMatch[0];\n const style = readHtmlAttr(tag, \"style\");\n if (!style) continue;\n sources.push({ content: style });\n }\n\n return sources;\n}\n\nfunction isRemoteOrInlineUrl(url: string): boolean {\n return /^(https?:|data:|blob:|\\/\\/|#)/i.test(url);\n}\n\nfunction cleanAssetUrl(url: string): string {\n return url.trim().split(/[?#]/, 1)[0] ?? \"\";\n}\n\nfunction isWithinProjectRoot(projectDir: string, candidate: string): boolean {\n const projectRoot = resolve(projectDir);\n const relativePath = relative(projectRoot, candidate);\n return relativePath === \"\" || (!relativePath.startsWith(\"..\") && !isAbsolute(relativePath));\n}\n\nfunction addCandidate(candidates: string[], candidate: string): void {\n if (!candidates.includes(candidate)) candidates.push(candidate);\n}\n\nfunction resolveLocalAssetCandidates(projectDir: string, url: string): string[] {\n const cleanUrl = cleanAssetUrl(url);\n const projectRoot = resolve(projectDir);\n const candidates: string[] = [];\n\n for (const variant of decodeUrlPathVariants(cleanUrl)) {\n const projectRelative = variant.startsWith(\"/\") ? variant.slice(1) : variant;\n const resolved = resolve(projectRoot, projectRelative);\n if (isWithinProjectRoot(projectRoot, resolved)) {\n addCandidate(candidates, resolved);\n continue;\n }\n\n const normalized = posix.normalize(projectRelative.replace(/\\\\/g, \"/\"));\n const clamped = normalized.replace(/^(\\.\\.\\/)+/, \"\");\n if (clamped && !clamped.startsWith(\"..\")) {\n addCandidate(candidates, resolve(projectRoot, clamped));\n }\n }\n\n return candidates;\n}\n\nfunction resolveExistingLocalAsset(\n projectDir: string,\n url: string,\n): { resolved: string; rootRelativePath: string } | null {\n const projectRoot = resolve(projectDir);\n const resolved = resolveLocalAssetCandidates(projectRoot, url).find(existsSync);\n if (!resolved) return null;\n return { resolved, rootRelativePath: relative(projectRoot, resolved) };\n}\n\nfunction resolveCssAssetCandidates(\n projectDir: string,\n url: string,\n htmlCompSrcPath?: string,\n cssRootRelativePath?: string,\n): string[] {\n if (url.startsWith(\"/\")) return resolveLocalAssetCandidates(projectDir, url);\n if (cssRootRelativePath) {\n return resolveLocalAssetCandidates(projectDir, join(dirname(cssRootRelativePath), url));\n }\n if (htmlCompSrcPath) {\n return resolveLocalAssetCandidates(projectDir, rewriteAssetPath(htmlCompSrcPath, url));\n }\n return resolveLocalAssetCandidates(projectDir, url);\n}\n\nexport async function lintProject(projectDir: string): Promise<ProjectLintResult> {\n const indexPath = resolve(projectDir, \"index.html\");\n const results: Array<{ file: string; result: HyperframeLintResult }> = [];\n let totalErrors = 0;\n let totalWarnings = 0;\n let totalInfos = 0;\n\n const rootHtml = readFileSync(indexPath, \"utf-8\");\n const rootResult = await lintHyperframeHtml(rootHtml, {\n filePath: indexPath,\n externalStyles: collectExternalStyles(projectDir, rootHtml),\n });\n results.push({ file: \"index.html\", result: rootResult });\n totalErrors += rootResult.errorCount;\n totalWarnings += rootResult.warningCount;\n totalInfos += rootResult.infoCount;\n\n const allHtmlSources: HtmlSource[] = [{ html: rootHtml }];\n const compositionsDir = resolve(projectDir, \"compositions\");\n if (existsSync(compositionsDir)) {\n const collectHtmlFiles = (dir: string, rel: string): string[] => {\n const out: string[] = [];\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n const relPath = rel ? `${rel}/${entry.name}` : entry.name;\n if (entry.isDirectory()) out.push(...collectHtmlFiles(join(dir, entry.name), relPath));\n else if (entry.isFile() && entry.name.endsWith(\".html\")) out.push(relPath);\n }\n return out;\n };\n const files = collectHtmlFiles(compositionsDir, \"\").sort();\n for (const file of files) {\n const filePath = join(compositionsDir, file);\n const html = readFileSync(filePath, \"utf-8\");\n const compSrcPath = `compositions/${file}`;\n allHtmlSources.push({ html, compSrcPath });\n const result = await lintHyperframeHtml(html, {\n filePath,\n isSubComposition: true,\n externalStyles: collectExternalStyles(projectDir, html, compSrcPath),\n });\n results.push({ file: `compositions/${file}`, result });\n totalErrors += result.errorCount;\n totalWarnings += result.warningCount;\n totalInfos += result.infoCount;\n }\n }\n\n const projectFindings = [\n ...lintProjectAudioFiles(projectDir, allHtmlSources),\n ...lintAudioSrcNotFound(projectDir, allHtmlSources),\n ...lintMissingLocalAsset(projectDir, allHtmlSources),\n ...lintTextureMaskAssetNotFound(projectDir, allHtmlSources),\n ...lintMultipleRootCompositions(projectDir),\n ...lintDuplicateAudioTracks(allHtmlSources),\n ];\n if (projectFindings.length > 0) {\n for (const finding of projectFindings) {\n rootResult.findings.push(finding);\n if (finding.severity === \"error\") {\n rootResult.errorCount++;\n rootResult.ok = false;\n totalErrors++;\n } else if (finding.severity === \"warning\") {\n rootResult.warningCount++;\n totalWarnings++;\n } else {\n rootResult.infoCount++;\n totalInfos++;\n }\n }\n }\n\n return { results, totalErrors, totalWarnings, totalInfos };\n}\n\nfunction lintProjectAudioFiles(\n projectDir: string,\n htmlSources: HtmlSource[],\n): HyperframeLintFinding[] {\n const findings: HyperframeLintFinding[] = [];\n\n let audioFiles: string[];\n try {\n audioFiles = readdirSync(projectDir).filter((f) =>\n AUDIO_EXTENSIONS.has(extname(f).toLowerCase()),\n );\n } catch {\n return findings;\n }\n\n if (audioFiles.length === 0) return findings;\n\n const hasAudioElement = htmlSources.some(({ html }) => /<audio\\b/i.test(html));\n\n if (!hasAudioElement) {\n findings.push({\n code: \"audio_file_without_element\",\n severity: \"warning\",\n message: `Found audio file(s) in project (${audioFiles.join(\", \")}) but no <audio> element in any composition. The rendered video will be silent.`,\n fixHint:\n 'Add an <audio id=\"my-audio\" src=\"' +\n audioFiles[0] +\n '\" data-start=\"0\" data-duration=\"__DURATION__\" data-track-index=\"0\" data-volume=\"1\"></audio> element inside the composition root. Replace __DURATION__ with the audio length in seconds.',\n });\n }\n\n return findings;\n}\n\nfunction lintAudioSrcNotFound(\n projectDir: string,\n htmlSources: HtmlSource[],\n): HyperframeLintFinding[] {\n const findings: HyperframeLintFinding[] = [];\n\n const audioSrcRe = /<audio\\b[^>]*\\bsrc\\s*=\\s*[\"']([^\"']+)[\"'][^>]*>/gi;\n\n const missingSrcs: string[] = [];\n for (const { html, compSrcPath } of htmlSources) {\n let match: RegExpExecArray | null;\n while ((match = audioSrcRe.exec(html)) !== null) {\n const src = match[1]!;\n if (/^(https?:|data:|blob:)/i.test(src)) continue;\n if (/^__[A-Z_]+__$/.test(src)) continue;\n const rootRelative = compSrcPath ? rewriteAssetPath(compSrcPath, src) : src;\n if (!resolveLocalAssetCandidates(projectDir, rootRelative).some(existsSync)) {\n missingSrcs.push(src);\n }\n }\n }\n\n if (missingSrcs.length > 0) {\n const unique = [...new Set(missingSrcs)];\n findings.push({\n code: \"audio_src_not_found\",\n severity: \"error\",\n message: `<audio> element references file(s) not found in the project: ${unique.join(\", \")}. The rendered video will be silent.`,\n fixHint:\n unique.length === 1\n ? `Add the file \"${unique[0]}\" to the project directory, or update the src attribute to point to an existing file.`\n : `Add the missing files to the project directory, or update the src attributes to point to existing files.`,\n });\n }\n\n return findings;\n}\n\nfunction maskRange(src: string, pattern: RegExp): string {\n return src.replace(pattern, (m) => \" \".repeat(m.length));\n}\n\nfunction maskNonScannableRanges(html: string): string {\n let out = maskRange(html, /<!--[\\s\\S]*?-->/g);\n out = maskRange(out, /<style\\b[^>]*>[\\s\\S]*?<\\/style\\b[^>]*>/gi);\n out = maskRange(out, /<script\\b[^>]*>[\\s\\S]*?<\\/script\\b[^>]*>/gi);\n return out;\n}\n\n// fallow-ignore-next-line complexity\nfunction lintMissingLocalAsset(\n projectDir: string,\n htmlSources: HtmlSource[],\n): HyperframeLintFinding[] {\n const findings: HyperframeLintFinding[] = [];\n\n const localAssetSrcRe = /<(video|img|source)\\b[^>]*\\bsrc\\s*=\\s*[\"']([^\"']+)[\"'][^>]*>/gi;\n\n const missingByTag = new Map<string, Map<string, string>>();\n\n for (const { html, compSrcPath } of htmlSources) {\n const scannable = maskNonScannableRanges(html);\n const re = new RegExp(localAssetSrcRe.source, localAssetSrcRe.flags);\n let match: RegExpExecArray | null;\n while ((match = re.exec(scannable)) !== null) {\n const tagName = (match[1] ?? \"\").toLowerCase();\n const rawSrc = match[2] ?? \"\";\n const src = cleanAssetUrl(rawSrc);\n if (!src) continue;\n if (isRemoteOrInlineUrl(src)) continue;\n if (/^__[A-Z_]+__$/.test(src)) continue;\n const rootRelative = compSrcPath ? rewriteAssetPath(compSrcPath, src) : src;\n const resolvedAsset = resolveExistingLocalAsset(projectDir, rootRelative);\n if (resolvedAsset) continue;\n\n const resolvedKey = resolve(projectDir, rootRelative);\n let bucket = missingByTag.get(tagName);\n if (!bucket) {\n bucket = new Map<string, string>();\n missingByTag.set(tagName, bucket);\n }\n if (!bucket.has(resolvedKey)) bucket.set(resolvedKey, src);\n }\n }\n\n for (const [tagName, byResolved] of missingByTag) {\n const unique = [...byResolved.values()];\n findings.push({\n code: \"missing_local_asset\",\n severity: \"error\",\n message:\n `<${tagName}> element references local file(s) not found in the project: ${unique.join(\", \")}. ` +\n \"The renderer will silently skip these and produce a video with missing visuals.\",\n fixHint:\n unique.length === 1\n ? `Add \"${unique[0]}\" to the project directory, or update the src attribute to point to an existing file. ` +\n \"Common cause: captured asset filenames are unreliable (heygen-logo.svg often contains Google, nvidia-logo.svg may contain Autodesk, etc.). \" +\n \"Open the contact sheets and verify the file actually exists at this path before referencing it.\"\n : \"Add the missing files to the project directory, or update the src attributes to point to existing files. \" +\n \"Captured asset filenames are unreliable — verify against capture/contact-sheets/ and capture/extracted/asset-descriptions.md.\",\n });\n }\n\n return findings;\n}\n\nfunction lintTextureMaskAssetNotFound(\n projectDir: string,\n htmlSources: HtmlSource[],\n): HyperframeLintFinding[] {\n const missing = new Map<string, string>();\n\n for (const { html, compSrcPath } of htmlSources) {\n for (const cssSource of collectCssSources(projectDir, html, compSrcPath)) {\n let match: RegExpExecArray | null;\n const pattern = new RegExp(MASK_IMAGE_URL_RE.source, MASK_IMAGE_URL_RE.flags);\n while ((match = pattern.exec(cssSource.content)) !== null) {\n const rawUrl = match[1] ?? match[2] ?? match[3] ?? \"\";\n const url = cleanAssetUrl(rawUrl);\n if (!url || isRemoteOrInlineUrl(url)) continue;\n if (/^__[A-Z_]+__$/.test(url)) continue;\n\n const candidates = resolveCssAssetCandidates(\n projectDir,\n url,\n compSrcPath,\n cssSource.rootRelativePath,\n );\n if (candidates.some(existsSync)) continue;\n missing.set(url, candidates[0] ?? resolve(projectDir, url));\n }\n }\n }\n\n if (missing.size === 0) return [];\n const urls = [...missing.keys()];\n return [\n {\n code: \"texture_mask_asset_not_found\",\n severity: \"error\",\n message: `CSS mask-image references file(s) not found in the project: ${urls.join(\", \")}.`,\n fixHint:\n urls.length === 1\n ? `Add \"${urls[0]}\" to the project, or update the mask-image URL to point to an existing texture mask.`\n : \"Add the missing texture mask files to the project, or update the mask-image URLs to point to existing files.\",\n },\n ];\n}\n\nfunction lintMultipleRootCompositions(projectDir: string): HyperframeLintFinding[] {\n const findings: HyperframeLintFinding[] = [];\n try {\n const rootHtmlFiles = readdirSync(projectDir).filter((f) => f.endsWith(\".html\"));\n const rootCompositions: string[] = [];\n for (const file of rootHtmlFiles) {\n if (file === \"caption-skin.html\") continue;\n const content = readFileSync(join(projectDir, file), \"utf-8\");\n if (/data-composition-id/i.test(content)) {\n rootCompositions.push(file);\n }\n }\n if (rootCompositions.length > 1) {\n findings.push({\n code: \"multiple_root_compositions\",\n severity: \"error\",\n message: `Multiple root-level HTML files with data-composition-id: ${rootCompositions.join(\", \")}. The runtime may discover both as entry points, causing duplicate audio playback.`,\n fixHint:\n \"A project should have exactly one root index.html with data-composition-id. Remove or rename extra files.\",\n });\n }\n } catch {\n /* directory read failed — skip */\n }\n return findings;\n}\n\nfunction lintDuplicateAudioTracks(htmlSources: HtmlSource[]): HyperframeLintFinding[] {\n const findings: HyperframeLintFinding[] = [];\n function extractAttr(tag: string, name: string): string | null {\n const re = new RegExp(`\\\\b${name}\\\\s*=\\\\s*[\"']([^\"']+)[\"']`, \"i\");\n const m = tag.match(re);\n return m?.[1] ?? null;\n }\n\n const tracks: Array<{ trackIndex: number; start: number; end: number; src: string }> = [];\n const seen = new Set<string>();\n\n for (const { html } of htmlSources) {\n const audioTagRe = /<audio\\b[^>]*>/gi;\n let match: RegExpExecArray | null;\n while ((match = audioTagRe.exec(html)) !== null) {\n const tag = match[0];\n const trackStr = extractAttr(tag, \"data-track-index\");\n const startStr = extractAttr(tag, \"data-start\");\n const durStr = extractAttr(tag, \"data-duration\");\n const src = extractAttr(tag, \"src\") ?? \"unknown\";\n if (!trackStr || !startStr) continue;\n\n const trackIndex = parseInt(trackStr, 10);\n const start = parseFloat(startStr);\n const duration = durStr ? parseFloat(durStr) : Infinity;\n const key = `${src}:${start}:${duration}:${trackIndex}`;\n if (seen.has(key)) continue;\n seen.add(key);\n\n tracks.push({ trackIndex, start, end: start + duration, src });\n }\n }\n\n for (let i = 0; i < tracks.length; i++) {\n for (let j = i + 1; j < tracks.length; j++) {\n const a = tracks[i]!;\n const b = tracks[j]!;\n if (a.trackIndex !== b.trackIndex) continue;\n if (a.start < b.end && b.start < a.end) {\n findings.push({\n code: \"duplicate_audio_track\",\n severity: \"warning\",\n message: `Multiple <audio> elements on track ${a.trackIndex} overlap (${a.src} at ${a.start}-${Number.isFinite(a.end) ? a.end.toFixed(1) : \"end\"}s, ${b.src} at ${b.start}-${Number.isFinite(b.end) ? b.end.toFixed(1) : \"end\"}s). This causes layered audio playback.`,\n fixHint: \"Use non-overlapping time windows or different track indices.\",\n });\n }\n }\n }\n return findings;\n}\n"],"mappings":"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","names":["escapeRegExp","selector","postcss","postcss"]}