@hyperframes/lint 0.7.86 → 0.7.87

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/shouldBlockRender.ts","../src/project.ts","../src/hevcPreviewLint.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\nimport { Parser } from \"htmlparser2\";\n\nexport type OpenTag = {\n raw: string;\n name: string;\n attrs: string;\n index: number;\n closeIndex?: number;\n endIndex?: number;\n};\n\nexport type ExtractedBlock = {\n attrs: string;\n content: string;\n raw: string;\n index: number;\n};\n\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;\n// Object-literal registration that assigns at least one `key: value` entry inline,\n// e.g. `window.__timelines = { main: tl }` or `window.__timelines = { \"comp-1\": tl }`.\n// Distinct from the empty-init form (`= {}`) — requires a key followed by `:`.\nexport const TIMELINE_REGISTRY_OBJECT_LITERAL_PATTERN =\n /window\\.__timelines\\s*=\\s*\\{\\s*(?:[\"'][^\"']+[\"']|[A-Za-z_$][\\w$]*)\\s*:/i;\nexport const TIMELINE_REGISTRY_ASSIGN_PATTERN =\n /window\\.__timelines(?:\\[[^\\]]+\\]|\\.[A-Za-z_$][\\w$]*)\\s*=/i;\n// The bracket branch accepts either a quoted string key (`[\"root\"]`) or a\n// computed key (`[spec.id]`, `[id]`) — a bare-identifier-only bracket branch\n// missed `window.__timelines[spec.id] = tl`, a pattern the shipped\n// code-particle-assemble/code-3d-extrude registry blocks actually use,\n// making gsap_timeline_not_registered false-fire on correctly registered\n// timelines. The computed-key alternative is deliberately non-capturing:\n// its text isn't a literal composition id, so callers reading group 1/2\n// (readRegisteredTimelineCompositionId) must keep falling back to null for it.\nexport const WINDOW_TIMELINE_ASSIGN_PATTERN =\n /window\\.__timelines(?:\\[\\s*(?:[\"']([^\"']+)[\"']|[A-Za-z_$][\\w$.]*)\\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\n// The `window.__timelines = { ... }` object-literal body (group 1), captured so its\n// `key: value` entries can be scanned for registered keys.\nconst TIMELINE_REGISTRY_OBJECT_BODY_PATTERN = /window\\.__timelines\\s*=\\s*\\{([\\s\\S]*?)\\}/i;\n// A single object-literal entry whose value is an identifier (real timeline registration),\n// e.g. `main: tl` or `\"comp-1\": tl`. Captures the key in group 1 (quoted) or 2 (bare).\nconst TIMELINE_REGISTRY_OBJECT_ENTRY_PATTERN =\n /(?:[\"']([^\"']+)[\"']|([A-Za-z_$][\\w$]*))\\s*:\\s*[A-Za-z_$][\\w$]*/g;\n\nexport function parseHtmlStructure(source: string): {\n tags: OpenTag[];\n scripts: ExtractedBlock[];\n styles: ExtractedBlock[];\n} {\n const tags: OpenTag[] = [];\n const blocks = { script: [] as ExtractedBlock[], style: [] as ExtractedBlock[] };\n const openTagsByName = new Map<string, OpenTag[]>();\n const openBlocks: Array<{\n name: \"script\" | \"style\";\n attrs: string;\n contentStart: number;\n index: number;\n }> = [];\n const parser: Parser = new Parser(\n {\n onopentag(name) {\n const index = parser.startIndex;\n const raw = source.slice(index, parser.endIndex + 1);\n const attrs = raw.slice(name.length + 1, -1).replace(/\\s*\\/$/, \"\");\n const tag = { raw, name, attrs, index };\n tags.push(tag);\n const sameNameStack = openTagsByName.get(name) ?? [];\n sameNameStack.push(tag);\n openTagsByName.set(name, sameNameStack);\n if (name === \"script\" || name === \"style\") {\n openBlocks.push({ name, attrs, contentStart: parser.endIndex + 1, index });\n }\n },\n onclosetag(name) {\n const tag = openTagsByName.get(name)?.pop();\n if (tag) {\n tag.closeIndex = parser.startIndex;\n tag.endIndex = parser.endIndex + 1;\n }\n if (name !== \"script\" && name !== \"style\") return;\n const block = openBlocks.pop();\n if (!block || block.name !== name) return;\n blocks[name].push({\n attrs: block.attrs,\n content: source.slice(block.contentStart, parser.startIndex),\n raw: source.slice(block.index, parser.endIndex + 1),\n index: block.index,\n });\n },\n },\n { decodeEntities: false, lowerCaseAttributeNames: false, lowerCaseTags: true },\n );\n parser.end(source);\n\n return { tags, scripts: blocks.script, styles: blocks.style };\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(tags: readonly OpenTag[]): OpenTag | null {\n return tags.find((tag) => tag.name === \"html\") ?? null;\n}\n\n// fallow-ignore-next-line complexity\nexport function findRootTag(source: string, parsedTags?: readonly OpenTag[]): OpenTag | null {\n const tags = parsedTags ?? parseHtmlStructure(source).tags;\n const bodyTag = tags.find((tag) => tag.name === \"body\");\n if (\n bodyTag &&\n (readDecodedAttr(bodyTag.raw, \"data-composition-id\") ||\n readAttr(bodyTag.raw, \"data-width\") ||\n readAttr(bodyTag.raw, \"data-height\"))\n ) {\n return bodyTag;\n }\n const bodyStart = bodyTag ? bodyTag.index + bodyTag.raw.length : 0;\n const bodyEnd = bodyTag?.closeIndex ?? source.length;\n const bodyTags = tags.filter((tag) => tag.index >= bodyStart && tag.index < bodyEnd);\n // Set when a leading <svg> defs block is skipped (see below) — extractOpenTags\n // is a flat, nesting-unaware scan, so without this the very next tag it\n // returns is the svg's own nested child (<defs>, <filter>, ...), not the\n // sibling that follows the closed </svg>.\n let skipBefore = -1;\n for (const tag of bodyTags) {\n if (tag.index < skipBefore) continue;\n if ([\"script\", \"style\", \"meta\", \"link\", \"title\"].includes(tag.name)) continue;\n // A leading <svg> block (icon/gradient/filter <defs>, referenced by url(#id)\n // from elsewhere in the document) is shared visual plumbing, not the\n // composition root — two independent reports of this being mistaken for\n // the root, manufacturing root_missing_composition_id/root_missing_dimensions\n // on an otherwise-correct composition. Only skip it when it carries none of\n // the composition markers itself, so an intentionally SVG-rooted composition\n // (data-composition-id/data-width/data-height directly on the <svg>) is\n // still eligible as the root.\n if (\n tag.name === \"svg\" &&\n !readDecodedAttr(tag.raw, \"data-composition-id\") &&\n !readAttr(tag.raw, \"data-width\") &&\n !readAttr(tag.raw, \"data-height\")\n ) {\n // No closing tag found (malformed HTML) — skip everything rather than\n // risk returning one of the svg's own children as the root.\n skipBefore = tag.endIndex ?? Infinity;\n continue;\n }\n return tag;\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 // `(?<![\\w-])` not `\\b`: a plain `\\b` boundary treats the hyphen in a longer\n // attribute as a word break, so reading \"id\" would wrongly match the trailing\n // `id=\"…\"` inside `data-hf-id=\"…\"` (and \"width\" inside `data-width`, etc.).\n // The lookbehind requires the match to start a fresh attribute name.\n const match = tagSource.match(new RegExp(`(?<![\\\\w-])${escaped}\\\\s*=\\\\s*[\"']([^\"']+)[\"']`, \"i\"));\n return match?.[1] || null;\n}\n\n/** Read an HTML attribute using browser-equivalent character-reference decoding. */\nexport function readDecodedAttr(tagSource: string, attr: string): string | null {\n if (!tagSource) return null;\n let value: string | null = null;\n const parser = new Parser(\n {\n onattribute(name, decodedValue) {\n if (value === null && name.toLowerCase() === attr.toLowerCase()) value = decodedValue;\n },\n },\n { decodeEntities: true, lowerCaseAttributeNames: false, lowerCaseTags: true },\n );\n parser.end(tagSource);\n return value;\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 // See readAttr: `(?<![\\w-])` prevents a short name from matching the tail of a\n // longer hyphenated attribute (e.g. \"id\" inside `data-hf-id`).\n const match = tagSource.match(\n new RegExp(`(?<![\\\\w-])${escaped}\\\\s*=\\\\s*(?:\"([^\"]*)\"|'([^']*)')`, \"i\"),\n );\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 = readDecodedAttr(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 const objectBody = TIMELINE_REGISTRY_OBJECT_BODY_PATTERN.exec(source)?.[1];\n if (objectBody) {\n const entryPattern = new RegExp(\n TIMELINE_REGISTRY_OBJECT_ENTRY_PATTERN.source,\n TIMELINE_REGISTRY_OBJECT_ENTRY_PATTERN.flags,\n );\n while ((match = entryPattern.exec(objectBody)) !== null) {\n const key = match[1] ?? match[2];\n if (key) keys.add(key);\n }\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\n// Whether any <style> block in the composition defines caption group/word\n// classes (`.caption-group`, `.caption_word`, etc.) — the signal several\n// caption-specific rules use to skip non-caption compositions entirely.\nexport function hasCaptionStyles(styles: ExtractedBlock[]): boolean {\n return styles.some((s) => /\\.caption[-_]?(?:group|word)/i.test(s.content));\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 parseHtmlStructure,\n findRootTag,\n collectCompositionIds,\n readDecodedAttr,\n stripHtmlComments,\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 initialStructure = parseHtmlStructure(source);\n const templateTags = initialStructure.tags.filter(\n (tag) => tag.name === \"template\" && tag.closeIndex != null,\n );\n let sourceWithoutTemplates = source;\n for (const template of [...templateTags].reverse()) {\n const end = template.endIndex ?? template.index;\n sourceWithoutTemplates =\n sourceWithoutTemplates.slice(0, template.index) +\n \" \".repeat(end - template.index) +\n sourceWithoutTemplates.slice(end);\n }\n // Some sub-composition files are HTML shells whose real root lives inside a\n // <template>. Keep nested templates intact when the visible document already\n // has a composition root; only unwrap when no root exists outside templates.\n const template = templateTags[0];\n let structure = initialStructure;\n if (template && !findRootTag(sourceWithoutTemplates)) {\n source = source.slice(template.index + template.raw.length, template.closeIndex);\n structure = parseHtmlStructure(source);\n }\n\n const tags = structure.tags;\n const styles = [\n ...structure.styles,\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 = structure.scripts;\n const compositionIds = collectCompositionIds(tags);\n const rootTag = findRootTag(source, tags);\n const rootCompositionId = readDecodedAttr(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 selectorParser from \"postcss-selector-parser\";\nimport {\n readAttr,\n readDecodedAttr,\n truncateSnippet,\n stripJsComments,\n extractCompositionIdsFromCss,\n extractTimelineRegistryKeys,\n getInlineScriptSyntaxError,\n TIMELINE_REGISTRY_INIT_PATTERN,\n TIMELINE_REGISTRY_ASSIGN_PATTERN,\n TIMELINE_REGISTRY_OBJECT_LITERAL_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 repeatedDescendantId(selector: string): string | null {\n let repeated: string | null = null;\n\n const requiredPseudoIds = (pseudo: selectorParser.Pseudo): Set<string> => {\n if (![\":is\", \":where\"].includes(pseudo.value.toLowerCase()) || pseudo.nodes.length === 0) {\n return new Set<string>();\n }\n\n const optionIdSets: Set<string>[] = [];\n for (const option of pseudo.nodes) {\n // Only promote ids from a single compound. For selector-list branches with\n // combinators, determining which compound is the subject requires fuller\n // selector semantics; skipping them avoids false positives.\n if (option.nodes.some((node) => node.type === \"combinator\")) return new Set<string>();\n const optionIds = new Set<string>(\n option.nodes.filter((node) => node.type === \"id\").map((node) => node.value),\n );\n optionIdSets.push(optionIds);\n }\n const [firstOptionIds, ...remainingOptionIds] = optionIdSets;\n return new Set<string>(\n [...(firstOptionIds ?? [])].filter((id) =>\n remainingOptionIds.every((optionIds) => optionIds.has(id)),\n ),\n );\n };\n\n try {\n selectorParser((root) => {\n root.each((selectorNode) => {\n const firstCompoundById = new Map<string, number>();\n let compound = 0;\n selectorNode.each((node) => {\n if (repeated) return;\n if (node.type === \"combinator\") {\n compound += 1;\n return;\n }\n const requiredIds =\n node.type === \"id\"\n ? [node.value]\n : node.type === \"pseudo\"\n ? [...requiredPseudoIds(node)]\n : [];\n for (const id of requiredIds) {\n const firstCompound = firstCompoundById.get(id);\n if (firstCompound !== undefined && firstCompound !== compound) {\n repeated = id;\n return;\n }\n firstCompoundById.set(id, compound);\n }\n });\n });\n }).processSync(selector);\n } catch {\n return null;\n }\n return repeated;\n}\n\nfunction resolvedRuleSelectors(rule: postcss.Rule): string[] {\n let ancestor: postcss.AnyNode | undefined = rule.parent;\n while (ancestor && ancestor.type !== \"rule\") ancestor = ancestor.parent;\n if (!ancestor || ancestor.type !== \"rule\") return rule.selectors;\n\n const parentSelectors = resolvedRuleSelectors(ancestor);\n return parentSelectors.flatMap((parentSelector) =>\n rule.selectors.map((childSelector) => {\n const nestingToken = /(^|[\\s>+~,(])&/g;\n if (nestingToken.test(childSelector)) {\n return childSelector.replace(\n nestingToken,\n (_, separator: string) => separator + parentSelector,\n );\n }\n return `${parentSelector} ${childSelector}`;\n }),\n );\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 = readDecodedAttr(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;\nconst VISIBLE_MARKUP_COMMENT_PATTERN = /\\/\\*[\\s\\S]*?\\*\\//g;\nconst VISIBLE_MARKUP_COMMENT_PROTECTED_BLOCK_PATTERN =\n /<(style|script|template|title|noscript|pre|code|textarea|text)\\b[^>]*>[\\s\\S]*?<\\/\\1(?:\\s[^>]*)?>/gi;\n\ninterface SourceRange {\n start: number;\n end: number;\n}\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\nfunction findProtectedVisibleMarkupRanges(source: string): SourceRange[] {\n const ranges: SourceRange[] = [];\n for (const match of source.matchAll(VISIBLE_MARKUP_COMMENT_PROTECTED_BLOCK_PATTERN)) {\n ranges.push({ start: match.index, end: match.index + match[0].length });\n }\n return ranges;\n}\n\nfunction isInsideSourceRange(index: number, ranges: SourceRange[]): boolean {\n return ranges.some((range) => range.start <= index && index < range.end);\n}\n\nfunction isInsideHtmlTag(source: string, index: number): boolean {\n let inTag = false;\n let quote: '\"' | \"'\" | null = null;\n for (let i = 0; i < index; i++) {\n const char = source[i];\n if (!inTag) {\n if (char === \"<\") inTag = true;\n continue;\n }\n if (quote) {\n if (char === quote) quote = null;\n continue;\n }\n if (char === '\"' || char === \"'\") {\n quote = char;\n } else if (char === \">\") {\n inTag = false;\n }\n }\n return inTag;\n}\n\nfunction findVisibleMarkupCommentLeak(source: string): string | null {\n const protectedRanges = findProtectedVisibleMarkupRanges(source);\n for (const match of source.matchAll(VISIBLE_MARKUP_COMMENT_PATTERN)) {\n if (isInsideHtmlTag(source, match.index)) continue;\n if (isInsideSourceRange(match.index, protectedRanges)) continue;\n return match[0];\n }\n return null;\n}\n\nexport const coreRules: Array<(ctx: LintContext) => HyperframeLintFinding[]> = [\n // id_requires_css_escape\n ({ tags }) => {\n const findings: HyperframeLintFinding[] = [];\n for (const tag of tags) {\n const id = readAttr(tag.raw, \"id\");\n if (!id || !/^\\d/.test(id)) continue;\n findings.push({\n code: \"id_requires_css_escape\",\n severity: \"warning\",\n message: `id=\"${id}\" starts with a digit, so the common selector \\`#${id}\\` throws a SyntaxError in querySelector().`,\n elementId: id,\n fixHint:\n \"Rename the id to start with a letter (recommended), or build selectors with `#${CSS.escape(id)}` at runtime.\",\n snippet: truncateSnippet(tag.raw),\n });\n }\n return findings;\n },\n\n // root_missing_composition_id + root_missing_dimensions\n ({ rootTag }) => {\n const findings: HyperframeLintFinding[] = [];\n if (!rootTag || !readDecodedAttr(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 // visible_markup_comment\n ({ source }) => {\n const snippet = findVisibleMarkupCommentLeak(source);\n if (!snippet) return [];\n return [\n {\n code: \"visible_markup_comment\",\n severity: \"error\",\n message:\n \"CSS/JS block comment syntax (`/* ... */`) appears in visible HTML markup. HTML only treats `<!-- ... -->` as comments, so this renders as on-screen text.\",\n fixHint:\n \"Remove the text or convert it to a real HTML comment (`<!-- ... -->`). Keep CSS comments inside `<style>` and JS comments inside `<script>`.\",\n snippet: truncateSnippet(snippet),\n },\n ];\n },\n\n // missing_timeline_registry + timeline_registry_missing_init\n ({ source, rawSource, rootTag, options }) => {\n // Sub-compositions inherit window.__timelines from the host composition\n if (options.isSubComposition || rawSource.trimStart().toLowerCase().startsWith(\"<template\")) {\n return [];\n }\n if (/(?:^|\\s)data-no-timeline(?=[\\s=/]|$)/i.test(rootTag?.attrs || \"\")) return [];\n const findings: HyperframeLintFinding[] = [];\n if (\n !TIMELINE_REGISTRY_INIT_PATTERN.test(source) &&\n !TIMELINE_REGISTRY_ASSIGN_PATTERN.test(source) &&\n !TIMELINE_REGISTRY_OBJECT_LITERAL_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, compositionIds }) => {\n const findings: HyperframeLintFinding[] = [];\n const htmlCompIds = new Set(compositionIds);\n const timelineRegKeys = new Set<string>();\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 // repeated_id_descendant_selector\n ({ styles }) => {\n const findings: HyperframeLintFinding[] = [];\n const reported = new Set<string>();\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 resolvedRuleSelectors(rule)) {\n const repeatedId = repeatedDescendantId(selector);\n if (!repeatedId || reported.has(repeatedId)) continue;\n reported.add(repeatedId);\n findings.push({\n code: \"repeated_id_descendant_selector\",\n severity: \"error\",\n message: `Selector \"${selector}\" requires #${repeatedId} to be nested inside another #${repeatedId}. IDs must be unique, so this selector cannot match a valid composition.`,\n selector,\n fixHint: `Remove the duplicate ancestor: change \\`#${repeatedId} #${repeatedId}\\` to \\`#${repeatedId}\\`.`,\n });\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 (readDecodedAttr(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: readDecodedAttr(tag.raw, \"data-composition-id\")\n ? `[data-composition-id=\"${readDecodedAttr(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 pattern: /gsap\\.utils\\.random\\s*\\(/,\n label: \"gsap.utils.random()\",\n hint: \"Each render worker initializes independently, so random values diverge across chunks. Use a seeded PRNG or fixed values.\",\n },\n {\n // GSAP string form: \"random(...)\" / \"+=random(...)\" — re-rolls at tween init.\n pattern: /[\"'`](?:[+-]=)?random\\(\\s*[-\\d[]/,\n label: '\"random(...)\" tween value',\n hint: \"GSAP random string values re-roll at tween init and each render worker initializes independently. Use fixed values or precompute with a seeded PRNG.\",\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, readDecodedAttr, truncateSnippet, isMediaTag } from \"../utils\";\nimport { validateColorGradingContract } from \"@hyperframes/parsers/color-grading-contract\";\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 // color_grading_* — grading is a structured media-only contract. Unknown\n // keys are ignored by the runtime, so catch them before an agent can report\n // controls that never actually rendered.\n ({ tags }) => {\n const findings: HyperframeLintFinding[] = [];\n for (const tag of tags) {\n const raw = readDecodedAttr(tag.raw, \"data-color-grading\");\n if (raw === null) continue;\n const elementId = readAttr(tag.raw, \"id\") || undefined;\n const report = (code: string, message: string, fixHint: string) => {\n findings.push({\n code,\n severity: \"error\",\n message,\n elementId,\n fixHint,\n snippet: truncateSnippet(tag.raw),\n });\n };\n if (tag.name !== \"video\" && tag.name !== \"img\") {\n report(\n \"color_grading_non_media\",\n `data-color-grading on <${tag.name}> has no effect. The shader runtime only grades real <video> and <img> elements.`,\n \"Move the grading attribute to the real <video> or <img> media element. Do not attach it to a wrapper or CSS background.\",\n );\n continue;\n }\n\n const trimmed = raw.trim();\n if (!trimmed.startsWith(\"{\") && !trimmed.startsWith(\"[\")) continue;\n let parsed: unknown;\n try {\n parsed = JSON.parse(trimmed);\n } catch {\n report(\n \"color_grading_invalid_json\",\n \"data-color-grading contains malformed JSON and will not render.\",\n 'Use valid JSON, for example {\"preset\":\"skin-soft\",\"intensity\":0.6,\"adjust\":{\"highlights\":-0.08}}.',\n );\n continue;\n }\n for (const issue of validateColorGradingContract(parsed)) {\n report(\n \"color_grading_invalid_structure\",\n `data-color-grading ${issue.path} ${issue.message}.`,\n issue.hint ??\n \"Use the documented media-treatment contract and correct or remove the invalid value.\",\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 (readDecodedAttr(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 // 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 const varSrc = readAttr(tag.raw, \"data-var-src\");\n if (varSrc) {\n // Variable-bound media without a fallback still renders when the\n // variable resolves, but a render without a value can't load the\n // media, and the audio pipeline discovers tracks from the AUTHORED\n // src — warn instead of hard-failing the binding pattern.\n findings.push({\n code: \"media_variable_src_no_fallback\",\n severity: \"warning\",\n message: `<${tag.name} id=\"${hasId}\"> relies on data-var-src=\"${varSrc}\" with no fallback src. Renders without a \"${varSrc}\" value cannot load this media, and audio extraction reads the authored src.`,\n elementId: hasId,\n fixHint: `Add a fallback src the composition can render with when the variable is not provided.`,\n snippet: truncateSnippet(tag.raw),\n });\n } else {\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 }\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 // media_crossorigin_breaks_preview — `crossorigin` on <video>/<audio> forces a\n // CORS-checked fetch. The server-side renderer downloads media directly (no CORS),\n // so it always works there; but Studio preview runs in the browser, where a media\n // host that omits Access-Control-Allow-Origin silently fails the load — the media\n // shows BLANK/black in preview while renders look fine, hiding the bug. Plain\n // displayed media never needs crossorigin; it's only required to read pixels/samples\n // back (canvas/WebGL texture, WebAudio createMediaElementSource) AND only when the\n // host is known CORS-enabled.\n ({ tags }) => {\n const findings: HyperframeLintFinding[] = [];\n for (const tag of tags) {\n if (tag.name !== \"video\" && tag.name !== \"audio\") continue;\n if (!hasAttrName(tag.raw, \"crossorigin\")) continue;\n const elementId = readAttr(tag.raw, \"id\") || undefined;\n findings.push({\n code: \"media_crossorigin_breaks_preview\",\n severity: \"error\",\n message: `<${tag.name}${elementId ? ` id=\"${elementId}\"` : \"\"}> has crossorigin, which forces a CORS-checked fetch. If the media host omits Access-Control-Allow-Origin, the load silently fails in Studio preview (media shows BLANK/black) while server-side renders still work — hiding the bug.`,\n elementId,\n fixHint:\n \"Remove the crossorigin attribute unless you read the media back via canvas/WebGL/WebAudio AND the host is known to send CORS headers. Plain displayed media never needs it.\",\n snippet: truncateSnippet(tag.raw),\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 targetIdentity?: string;\n method: string;\n position: number | string;\n properties: Record<string, number | string>;\n // fromTo() exposes its first (\"from\") vars object separately; a layout/reflow prop\n // that appears only here still animates and must be checked.\n fromProperties?: Record<string, number | string>;\n duration?: number;\n ease?: string;\n extras?: Record<string, unknown>;\n resolvedStart?: number;\n /** True for an off-timeline `gsap.set(...)` (applied once at load). */\n global?: boolean;\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}\n\nasync function loadGsapScriptMotionPathFirstUseIndex(): Promise<(script: string) => number | null> {\n const mod = await import(\"@hyperframes/parsers/gsap-parser-acorn\");\n return mod.gsapScriptMotionPathFirstUseIndex;\n}\nimport type { LintContext } from \"../context\";\nimport type { HyperframeLintFinding, LintRule } from \"../types\";\nimport type { OpenTag } from \"../utils\";\nimport {\n readAttr,\n readDecodedAttr,\n truncateSnippet,\n stripJsComments,\n hasCaptionStyles,\n WINDOW_TIMELINE_ASSIGN_PATTERN,\n TIMELINE_REGISTRY_OBJECT_LITERAL_PATTERN,\n} from \"../utils\";\n\n// ── GSAP-specific types ────────────────────────────────────────────────────\n\ntype GsapWindow = {\n targetSelector: string;\n targetIdentity?: string;\n position: number;\n end: number;\n properties: string[];\n propertyValues: Record<string, string | number>;\n fromPropertyValues?: Record<string, string | number>;\n overwriteAuto: boolean;\n immediateRender: boolean;\n method: string;\n /** True for an off-timeline `gsap.set(...)` (applied once at load). */\n global?: boolean;\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// Sentinel the GSAP parser assigns to a tween whose target it cannot statically\n// resolve to a concrete element (a computed variable, a helper call, etc.). It is\n// NOT an identity: two distinct unresolved selectors are not the same element, so\n// overlap analysis must never treat them as one.\nconst UNRESOLVED_TARGET = \"__unresolved__\";\n\n// Parser labels for object-proxy tweens describe their role, not target\n// identity. Two independent proxies can both be labelled `dwell/hold` (or the\n// same driven DOM channel), so equality cannot prove they conflict.\nfunction targetHasNoStableIdentity(selector: string, identity?: string): boolean {\n if (identity) return false;\n return (\n selector === UNRESOLVED_TARGET || selector === \"dwell/hold\" || selector.startsWith(\"proxy → \")\n );\n}\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 const start =\n animation.resolvedStart ??\n (typeof animation.position === \"number\" ? animation.position : null);\n if (start === null) continue;\n const repeat = extrasNumber(animation.extras?.repeat);\n const infiniteRepeat = repeat < 0;\n const cycleCount = infiniteRepeat ? 1 : 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 targetIdentity: animation.targetIdentity,\n position: start,\n end:\n infiniteRepeat && animation.method !== \"set\"\n ? Number.POSITIVE_INFINITY\n : start + effectiveDuration,\n properties: Object.keys(animation.properties),\n propertyValues: animation.properties,\n fromPropertyValues: animation.fromProperties,\n overwriteAuto: unwrapRaw(animation.extras?.overwrite) === \"auto\",\n immediateRender: unwrapRaw(animation.extras?.immediateRender) === \"true\",\n method: animation.method,\n global: animation.global,\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 extractStandaloneHiddenSelectors(script: string): Set<string> {\n const selectors = new Set<string>();\n const source = stripJsComments(script);\n const functionRanges = collectFunctionBodyRanges(source);\n const aliases = new Map<string, string>();\n for (const match of source.matchAll(\n /(?:const|let|var)\\s+([A-Za-z_$][\\w$]*)\\s*=\\s*([\"'`])([^\"'`]+)\\2\\s*;/g,\n )) {\n aliases.set(match[1] ?? \"\", match[3] ?? \"\");\n }\n const pattern = /gsap\\.set\\s*\\(\\s*([^,]+?)\\s*,\\s*\\{([\\s\\S]*?)\\}\\s*\\)/g;\n let match: RegExpExecArray | null;\n while ((match = pattern.exec(source)) !== null) {\n // Skip callback/handler bodies; keep IIFEs (they run at parse time).\n if (indexInsideNonIifeRange(match.index, source, functionRanges)) continue;\n const target = (match[1] ?? \"\").trim();\n const selector = /^([\"'`])([^\"'`]+)\\1$/.exec(target)?.[2] ?? aliases.get(target);\n if (!selector) continue;\n const body = match[2] ?? \"\";\n if (/(?:opacity|autoAlpha)\\s*:\\s*0(?:\\.0+)?\\s*(?:,|$)/.test(body)) {\n selectors.add(selector);\n }\n }\n return selectors;\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 = readDecodedAttr(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\n// A tag's `class` attribute, split into tokens, but only when it carries the\n// `clip` marker class — the common \"is this a clip element?\" filter used by\n// several rules that walk every tag looking for clips.\ntype ClipTagClasses = { classAttr: string; classes: string[] };\n\nfunction getClipTagClasses(tag: OpenTag): ClipTagClasses | null {\n const classAttr = readAttr(tag.raw, \"class\") || \"\";\n const classes = classAttr.split(/\\s+/).filter(Boolean);\n return classes.includes(\"clip\") ? { classAttr, classes } : 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 if (!getClipTagClasses(tag)) 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// Run a global regex over every script's content, yielding each match plus a\n// context-padded snippet around it. Shared by the repeat-count and\n// group-selector-keyframes rules below, which differ only in the pattern,\n// whether comments are stripped first, and the context window size.\nfunction scanScriptsForRegexMatches(\n scripts: LintContext[\"scripts\"],\n pattern: RegExp,\n options: { stripComments: boolean; contextBefore: number; contextAfter: number },\n): Array<{ match: RegExpExecArray; snippet: string }> {\n const hits: Array<{ match: RegExpExecArray; snippet: string }> = [];\n for (const script of scripts) {\n const content = options.stripComments ? stripJsComments(script.content) : script.content;\n const regex = new RegExp(pattern.source, pattern.flags);\n let match: RegExpExecArray | null;\n while ((match = regex.exec(content)) !== null) {\n const contextStart = Math.max(0, match.index - options.contextBefore);\n const contextEnd = Math.min(\n content.length,\n match.index + match[0].length + options.contextAfter,\n );\n hits.push({ match, snippet: content.slice(contextStart, contextEnd) });\n }\n }\n return hits;\n}\n\n// ── Seek-order safety helpers ───────────────────────────────────────────────\n//\n// The renderer distributes frames across workers; cold render workers seek\n// non-linearly straight into their range instead of playing sequentially from 0.\n// Any state that depends on seek ORDER — relative tween bases, callback-measured\n// geometry, per-init random values — renders differently per worker, visible as\n// position jumps or dead animation at chunk boundaries.\n\nconst RELATIVE_TWEEN_VALUE = /^[+-]=/;\n\nfunction isRelativeTweenValue(value: string | number | undefined): boolean {\n return typeof value === \"string\" && RELATIVE_TWEEN_VALUE.test(value.trim());\n}\n\n// DOM reads split by transform sensitivity. Transform-sensitive reads report\n// live animated geometry, so their result depends on the worker's own seek\n// order. Transform-invariant layout reads (intrinsic size, path geometry) give\n// the same answer on every worker as long as layout itself is not animated.\nconst TRANSFORM_SENSITIVE_READ =\n /\\.getBoundingClientRect\\s*\\(|\\bgetComputedStyle\\s*\\(|\\bgsap\\.getProperty\\s*\\(/;\nconst TRANSFORM_INVARIANT_READ =\n /\\.(?:getTotalLength|getBBox)\\s*\\(|\\.(?:offsetWidth|offsetHeight|clientWidth|clientHeight)\\b/;\n// Measurement set for CALLBACK analysis: gsap.getProperty is deliberately\n// excluded — callbacks that read animated values to drive derived output\n// (scramble text, typewriter cursors) are per-frame deterministic and\n// seek-idempotent, so they render the same on every worker.\nconst CALLBACK_MEASUREMENT_PATTERN =\n /\\.(?:getBoundingClientRect|getTotalLength|getBBox)\\s*\\(|\\bgetComputedStyle\\s*\\(|\\.(?:offsetWidth|offsetHeight|clientWidth|clientHeight)\\b/;\n\nfunction indexTagsByToken(tags: OpenTag[]): Map<string, OpenTag[]> {\n const tagsByToken = new Map<string, OpenTag[]>();\n const addToken = (token: string, tag: OpenTag): void => {\n const list = tagsByToken.get(token);\n if (list) list.push(tag);\n else tagsByToken.set(token, [tag]);\n };\n for (const tag of tags) {\n const id = readAttr(tag.raw, \"id\");\n if (id) addToken(`#${id}`, tag);\n for (const cls of readAttr(tag.raw, \"class\")?.split(/\\s+/).filter(Boolean) ?? [])\n addToken(`.${cls}`, tag);\n }\n return tagsByToken;\n}\n\nfunction resolveSelectorTagIndexes(\n selector: string,\n tagsByToken: Map<string, OpenTag[]>,\n): Set<number> {\n const indexes = new Set<number>();\n for (const token of targetedSelectorTokens(selector)) {\n for (const tag of tagsByToken.get(token) ?? []) indexes.add(tag.index);\n }\n return indexes;\n}\n\n// A selector whose comma groups are each a single simple compound (no\n// combinators, no attribute selectors) — the only shape that resolves\n// faithfully through simple #id/.class tokens. Descendant selectors\n// (\".card-a .icon\") and composition-scoped selectors\n// ('[data-composition-id=\"a\"] .dot') would mis-join across elements or\n// compositions, so token-based matching must bail on them.\nfunction selectorResolvesFaithfully(selector: string): boolean {\n return selector.split(\",\").every((group) => {\n const token = group.trim();\n if (!token || token.includes(\"[\")) return false;\n return !/[\\s>+~]/.test(token);\n });\n}\n\n// Two GSAP targets provably hit the same element when their stable identities\n// are equal, or when their (faithfully resolvable) selectors resolve to\n// intersecting element sets — an id selector and a class selector can name the\n// same node. Selectors with combinators or attribute parts are skipped rather\n// than guessed at.\nfunction targetsShareElement(\n a: { selector: string; identity?: string },\n b: { selector: string; identity?: string },\n tagsByToken: Map<string, OpenTag[]>,\n): boolean {\n if (\n !targetHasNoStableIdentity(a.selector, a.identity) &&\n !targetHasNoStableIdentity(b.selector, b.identity) &&\n (a.identity ?? a.selector) === (b.identity ?? b.selector)\n ) {\n return true;\n }\n if (!selectorResolvesFaithfully(a.selector) || !selectorResolvesFaithfully(b.selector)) {\n return false;\n }\n const aTags = resolveSelectorTagIndexes(a.selector, tagsByToken);\n if (aTags.size === 0) return false;\n const bTags = resolveSelectorTagIndexes(b.selector, tagsByToken);\n for (const index of bTags) if (aTags.has(index)) return true;\n return false;\n}\n\n/** Source from the delimiter at `openIndex` to its matching closer, inclusive. */\nfunction matchBalanced(\n source: string,\n openIndex: number,\n open: string,\n close: string,\n): string | null {\n let depth = 0;\n for (let i = openIndex; i < source.length; i++) {\n const ch = source[i];\n if (ch === open) depth++;\n else if (ch === close) {\n depth--;\n if (depth === 0) return source.slice(openIndex, i + 1);\n }\n }\n return null;\n}\n\n/** The nearest object literal `{...}` enclosing `index` (comment-stripped source). */\nfunction enclosingObjectLiteral(source: string, index: number): string | null {\n let depth = 0;\n for (let i = index; i >= 0; i--) {\n const ch = source[i];\n if (ch === \"}\") depth++;\n else if (ch === \"{\") {\n if (depth === 0) return matchBalanced(source, i, \"{\", \"}\");\n depth--;\n }\n }\n return null;\n}\n\nfunction objectLiteralHasTopLevelRelativeValue(objectLiteral: string): boolean {\n let depth = 0;\n let inString: '\"' | \"'\" | \"`\" | null = null;\n for (let i = 0; i < objectLiteral.length; i++) {\n const ch = objectLiteral[i] ?? \"\";\n const prev = objectLiteral[i - 1] ?? \"\";\n if (inString) {\n if (ch === inString && prev !== \"\\\\\") inString = null;\n continue;\n }\n if (ch === '\"' || ch === \"'\" || ch === \"`\") {\n inString = ch;\n if (depth === 1 && /^[+-]=/.test(objectLiteral.slice(i + 1))) return true;\n continue;\n }\n if (ch === \"{\" || ch === \"(\" || ch === \"[\") depth++;\n else if (ch === \"}\" || ch === \")\" || ch === \"]\") depth--;\n }\n return false;\n}\n\nfunction isInsideGsapTweenVars(source: string, index: number, timelineVars: string[]): boolean {\n let depth = 0;\n for (let i = index; i >= 0; i--) {\n const ch = source[i];\n if (ch === \"}\") depth++;\n else if (ch === \"{\") {\n if (depth === 0) {\n const before = source.slice(Math.max(0, i - 240), i).replace(/\\s+/g, \" \");\n const receivers = [\"gsap\", ...timelineVars].map(escapeRegExp).join(\"|\");\n return new RegExp(`(?:${receivers})\\\\.(?:set|to|from|fromTo|timeline)\\\\b[\\\\s\\\\S]*$`).test(\n before,\n );\n }\n depth--;\n }\n }\n return false;\n}\n\n/** An expression starting at `start`, ending at the first `,` / closer at depth 0. */\nfunction sliceExpression(source: string, start: number): string {\n let depth = 0;\n for (let i = start; i < source.length; i++) {\n const ch = source[i] ?? \"\";\n if (\"({[\".includes(ch)) depth++;\n else if (\")}]\".includes(ch)) {\n if (depth === 0) return source.slice(start, i);\n depth--;\n } else if (ch === \",\" && depth === 0) return source.slice(start, i);\n }\n return source.slice(start);\n}\n\ntype ParsedFunctionValue = { firstParam: string | null; body: string };\n\nfunction normalizeFirstParam(raw: string): string | null {\n let param = raw.trim().replace(/=.*$/, \"\").trim();\n param = param.replace(/\\s*:\\s*[\\w$|<>,\\s[\\].]+$/, \"\").trim();\n if (!param || /^[[{]/.test(param)) return null;\n if (!/^[A-Za-z_$][\\w$]*$/.test(param)) return null;\n return param;\n}\n\n/** Parse a function-shaped source string into its first parameter and body. */\nfunction parseFunctionValueSource(code: string): ParsedFunctionValue | null {\n const src = code.trim();\n const match =\n src.match(/^(?:async\\s+)?function\\s*[\\w$]*\\s*\\(([^)]*)\\)/) ??\n src.match(/^(?:async\\s*)?\\(([^)]*)\\)\\s*=>/) ??\n src.match(/^(?:async\\s*)?([A-Za-z_$][\\w$]*)\\s*=>/);\n if (!match) return null;\n const firstParam = normalizeFirstParam((match[1] ?? \"\").split(\",\")[0] ?? \"\");\n return { firstParam, body: src.slice(match[0].length) };\n}\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\n// Methods that exist on numbers: calling them on the (index) first parameter of\n// a GSAP function value is valid and must not be flagged.\nconst NUMBER_METHODS = new Set([\n \"toFixed\",\n \"toString\",\n \"toPrecision\",\n \"toExponential\",\n \"toLocaleString\",\n \"valueOf\",\n]);\n\n// Index is a NUMBER — non-number member access on the first param throws at init.\nfunction firstParamMemberAccessHazard(fn: ParsedFunctionValue): string | null {\n if (!fn.firstParam) return null;\n const pattern = new RegExp(\n `\\\\b${escapeRegExp(fn.firstParam)}\\\\s*\\\\.\\\\s*([A-Za-z_$][\\\\w$]*)`,\n \"g\",\n );\n let match: RegExpExecArray | null;\n while ((match = pattern.exec(fn.body)) !== null) {\n const member = match[1] ?? \"\";\n const after = fn.body.slice(match.index + match[0].length);\n const isCall = /^\\s*\\(/.test(after);\n if (isCall && NUMBER_METHODS.has(member)) continue;\n return member;\n }\n return null;\n}\n\n/** Names of timeline variables (`const tl = gsap.timeline(...)`) in a script. */\nfunction collectTimelineVarNames(source: string): string[] {\n return [...source.matchAll(/(?:const|let|var)\\s+([A-Za-z_$][\\w$]*)\\s*=\\s*gsap\\.timeline\\b/g)]\n .map((m) => m[1] ?? \"\")\n .filter(Boolean);\n}\n\n// Named function bodies in a script (declarations plus `const f = ...` function\n// expressions and arrows). Expression-bodied arrows keep their single line.\nfunction collectNamedFunctionBodies(source: string): Map<string, string> {\n const bodies = new Map<string, string>();\n const declPattern = /(?:^|[^.\\w$])function\\s+([A-Za-z_$][\\w$]*)\\s*\\(/g;\n let match: RegExpExecArray | null;\n while ((match = declPattern.exec(source)) !== null) {\n const braceIndex = source.indexOf(\"{\", declPattern.lastIndex);\n if (braceIndex < 0) continue;\n const body = matchBalanced(source, braceIndex, \"{\", \"}\");\n if (body) bodies.set(match[1] ?? \"\", body);\n }\n const assignPattern =\n /(?:const|let|var)\\s+([A-Za-z_$][\\w$]*)\\s*=\\s*(?:async\\s*)?(?:function\\b[^{]*|\\([^)]*\\)\\s*=>\\s*|[A-Za-z_$][\\w$]*\\s*=>\\s*)/g;\n while ((match = assignPattern.exec(source)) !== null) {\n const bodyStart = assignPattern.lastIndex;\n const body =\n source[bodyStart] === \"{\"\n ? matchBalanced(source, bodyStart, \"{\", \"}\")\n : sliceExpression(source, bodyStart);\n if (body) bodies.set(match[1] ?? \"\", body);\n }\n return bodies;\n}\n\n// Two-hop closure: functions whose body measures the DOM directly, plus\n// functions that call one of those (bounded fixpoint — no deep recursion).\nfunction collectMeasuringFunctionNames(bodies: Map<string, string>): Set<string> {\n const measuring = new Set<string>();\n for (const [name, body] of bodies) {\n if (CALLBACK_MEASUREMENT_PATTERN.test(body)) measuring.add(name);\n }\n for (let pass = 0; pass < 3; pass++) {\n let grew = false;\n for (const [name, body] of bodies) {\n if (measuring.has(name)) continue;\n for (const measured of measuring) {\n if (new RegExp(`\\\\b${escapeRegExp(measured)}\\\\s*\\\\(`).test(body)) {\n measuring.add(name);\n grew = true;\n break;\n }\n }\n }\n if (!grew) break;\n }\n return measuring;\n}\n\nfunction expressionReachesMeasurement(expression: string, measuring: Set<string>): boolean {\n if (CALLBACK_MEASUREMENT_PATTERN.test(expression)) return true;\n for (const name of measuring) {\n if (new RegExp(`\\\\b${escapeRegExp(name)}\\\\b`).test(expression)) return true;\n }\n return false;\n}\n\n// Resolve script-level element variables to the simple selector tokens they can\n// denote: literal getElementById/querySelector lookups, template-literal ids\n// matched against the document's actual ids, and script-assigned class names\n// (createElementNS + setAttribute(\"class\", ...)). Anything else stays unresolved.\nfunction resolveScriptElementTokens(source: string, tags: OpenTag[]): Map<string, Set<string>> {\n const documentIds = tags.map((tag) => readAttr(tag.raw, \"id\")).filter((id) => id !== null);\n const tokensByVar = new Map<string, Set<string>>();\n const add = (name: string, token: string): void => {\n const tokens = tokensByVar.get(name) ?? new Set<string>();\n tokens.add(token);\n tokensByVar.set(name, tokens);\n };\n\n for (const match of source.matchAll(\n /(?:const|let|var)\\s+([A-Za-z_$][\\w$]*)\\s*=\\s*document\\.getElementById\\(\\s*([\"'])([^\"'`]+)\\2/g,\n )) {\n add(match[1] ?? \"\", `#${match[3] ?? \"\"}`);\n }\n for (const match of source.matchAll(\n /(?:const|let|var)\\s+([A-Za-z_$][\\w$]*)\\s*=\\s*document\\.getElementById\\(\\s*`([^`]*)`/g,\n )) {\n const template = match[2] ?? \"\";\n const staticParts = template.split(/\\$\\{[^}]*\\}/);\n // A template with no literal segments (`getElementById(\\`${name}\\`)`) would\n // match EVERY id in the document — treat it as unresolved instead.\n if (staticParts.every((part) => part === \"\")) continue;\n const idPattern = new RegExp(`^${staticParts.map(escapeRegExp).join(\".*\")}$`);\n for (const id of documentIds) {\n if (idPattern.test(id)) add(match[1] ?? \"\", `#${id}`);\n }\n }\n for (const match of source.matchAll(\n /(?:const|let|var)\\s+([A-Za-z_$][\\w$]*)\\s*=\\s*document\\.querySelector\\(\\s*([\"'])([^\"'`]+)\\2/g,\n )) {\n for (const token of targetedSelectorTokens(match[3] ?? \"\")) add(match[1] ?? \"\", token);\n }\n for (const match of source.matchAll(\n /\\b([A-Za-z_$][\\w$]*)\\.setAttribute\\(\\s*([\"'])class\\2\\s*,\\s*([\"'])([^\"'`]*)\\3/g,\n )) {\n for (const cls of (match[4] ?? \"\").split(/\\s+/).filter(Boolean)) add(match[1] ?? \"\", `.${cls}`);\n }\n for (const match of source.matchAll(/\\b([A-Za-z_$][\\w$]*)\\.className\\s*=\\s*([\"'])([^\"'`]*)\\2/g)) {\n for (const cls of (match[3] ?? \"\").split(/\\s+/).filter(Boolean)) add(match[1] ?? \"\", `.${cls}`);\n }\n return tokensByVar;\n}\n\n/** Expand selector tokens to the FULL token sets of the elements they resolve to. */\nfunction elementLevelTokens(\n tokens: Iterable<string>,\n tagsByToken: Map<string, OpenTag[]>,\n): Set<string> {\n const expanded = new Set<string>(tokens);\n for (const token of [...expanded]) {\n for (const tag of tagsByToken.get(token) ?? []) {\n for (const own of tagSimpleSelectors(tag)) expanded.add(own);\n }\n }\n return expanded;\n}\n\nfunction isMultiComponentDasharray(value: string): boolean {\n const normalized = value.replace(/!important\\s*$/i, \"\").trim();\n if (!normalized || /^none$/i.test(normalized)) return false;\n return normalized.split(/[\\s,]+/).filter(Boolean).length >= 2;\n}\n\n// A GSAP strokeDasharray value that is a static string/template with >= 2\n// components is the explicit \"L L\" fix form — safe. Variables and numbers are\n// the common single-component draw-on form (the pathLength trick).\nfunction gsapDasharrayValueLooksMultiComponent(valueSource: string): boolean {\n const literal = valueSource.trim().match(/^([\"'`])([\\s\\S]*)\\1$/)?.[2];\n if (literal === undefined) return false;\n return isMultiComponentDasharray(literal.replace(/\\$\\{[^}]*\\}/g, \"0\"));\n}\n\n/** Byte ranges of every function body (declarations, expressions, block arrows). */\nfunction collectFunctionBodyRanges(source: string): Array<{ start: number; end: number }> {\n const ranges: Array<{ start: number; end: number }> = [];\n const openerPatterns = [/\\bfunction\\b[^{;()]*\\([^)]*\\)\\s*\\{/g, /=>\\s*\\{/g];\n for (const pattern of openerPatterns) {\n let match: RegExpExecArray | null;\n while ((match = pattern.exec(source)) !== null) {\n const braceIndex = match.index + match[0].length - 1;\n const body = matchBalanced(source, braceIndex, \"{\", \"}\");\n if (body) ranges.push({ start: braceIndex, end: braceIndex + body.length });\n }\n }\n return ranges;\n}\n\nfunction indexInsideAnyRange(\n index: number,\n ranges: Array<{ start: number; end: number }>,\n): boolean {\n return ranges.some((range) => index > range.start && index < range.end);\n}\n\nfunction isIifeBody(source: string, range: { start: number; end: number }): boolean {\n let j = range.end;\n while (j < source.length && /\\s/.test(source[j]!)) j++;\n if (source[j] !== \")\") return false;\n j++;\n while (j < source.length && /\\s/.test(source[j]!)) j++;\n return source[j] === \"(\" || source.startsWith(\".call\", j) || source.startsWith(\".apply\", j);\n}\n\nfunction indexInsideNonIifeRange(\n index: number,\n source: string,\n ranges: Array<{ start: number; end: number }>,\n): boolean {\n return ranges.some(\n (range) => index > range.start && index < range.end && !isIifeBody(source, range),\n );\n}\n\n// Simple selectors whose authored CSS (style blocks or inline styles) sets\n// opacity to EXACTLY zero. The declaration regex is boundary-anchored so\n// `opacity: 0.98` never matches; it ends at `;` or end of input, which also\n// catches a final declaration without a trailing semicolon.\nfunction collectCssOpacityZeroSelectors(\n styles: LintContext[\"styles\"],\n tags: OpenTag[],\n): Set<string> {\n const selectors = new Set<string>();\n const opacityExactlyZero = /opacity\\s*:\\s*0(?:\\.0+)?\\s*(?:;|$)/;\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 && opacityExactlyZero.test(body)) {\n selectors.add((selector ?? \"\").trim());\n }\n }\n }\n\n for (const tag of tags) {\n const inlineStyle = readAttr(tag.raw, \"style\");\n if (!inlineStyle || !opacityExactlyZero.test(inlineStyle)) continue;\n const id = readAttr(tag.raw, \"id\");\n if (id) selectors.add(`#${id}`);\n for (const cls of readAttr(tag.raw, \"class\")?.split(/\\s+/).filter(Boolean) ?? []) {\n selectors.add(`.${cls}`);\n }\n }\n return selectors;\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 clipTag = getClipTagClasses(tag);\n if (!clipTag) continue;\n const id = readAttr(tag.raw, \"id\");\n const info: ClipInfo = {\n tag: tag.name,\n id: id || \"\",\n classes: clipTag.classAttr,\n };\n if (id) clipIds.set(`#${id}`, info);\n for (const cls of clipTag.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 // Unresolved targets are unknown elements: two of them are not provably\n // the same element, so an overlap between them cannot be asserted.\n if (targetHasNoStableIdentity(left.targetSelector, left.targetIdentity)) 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 const leftIdentity = left.targetIdentity ?? left.targetSelector;\n const rightIdentity = right.targetIdentity ?? right.targetSelector;\n if (leftIdentity !== rightIdentity) 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 // Unresolved targets are unknown elements: you cannot assert a missing\n // hard kill on one, and a `tl.set(\"__unresolved__\", ...)` hint is meaningless.\n if (win.targetSelector === UNRESOLVED_TARGET) continue;\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 // A tl.set hard kill on the exiting selector itself is the fix — unless\n // that selector IS a clip element, in which case gsap_animates_clip_element\n // (below) errors on that exact tl.set: the framework already owns\n // visibility/display on clip elements. Point at the inner-wrapper\n // pattern instead so the two rules' advice doesn't contradict.\n const exitClipInfo =\n clipIds.get(win.targetSelector) || clipClasses.get(win.targetSelector);\n const fixHint = exitClipInfo\n ? `\"${win.targetSelector}\" is a clip element — the framework already manages its visibility. ` +\n \"Wrap the scene's content in an inner non-clip <div>, move the exit tween and the hard kill \" +\n `(\\`tl.set(\"<inner-selector>\", ${hiddenStateLiteral(win.propertyValues)}, ${boundary.toFixed(2)})\\`) onto that wrapper instead.`\n : `Add \\`tl.set(\"${win.targetSelector}\", ${hiddenStateLiteral(win.propertyValues)}, ${boundary.toFixed(2)})\\` ` +\n \"after the exit tween.\";\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 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 // gsap_timeline_set_initial_hide warns on `tl.set(..., 0)` initial hides\n // (a zero-duration set at 0 does not render at exactly t=0), so this hint\n // must not recommend that pattern — advise authored CSS or an immediate\n // gsap.set() instead, keeping the two rules' advice consistent.\n fixHint:\n `Add \\`opacity: 0\\` to \"${selector}\" in CSS/inline styles, or add an immediate ` +\n `\\`gsap.set(\"${selector}\", { opacity: 0 })\\` (outside the timeline) 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 // missing_gsap_plugin\n async ({ scripts, rawSource, options }) => {\n const canInheritPluginFromHost =\n options.isSubComposition || rawSource.trimStart().toLowerCase().startsWith(\"<template\");\n if (canInheritPluginFromHost) return [];\n\n const gsapScriptMotionPathFirstUseIndex = await loadGsapScriptMotionPathFirstUseIndex();\n const motionPathUseIndices = scripts.map((script) =>\n gsapScriptMotionPathFirstUseIndex(script.content),\n );\n const firstMotionPathScriptIndex = motionPathUseIndices.findIndex((index) => index !== null);\n const firstMotionPathUseIndex = motionPathUseIndices[firstMotionPathScriptIndex] ?? null;\n const firstUseScript = scripts[firstMotionPathScriptIndex];\n const executionMode = (attrs: string): \"blocking\" | \"defer\" | \"module\" | \"async\" => {\n const tag = `<script ${attrs}>`;\n const isModule = (readDecodedAttr(tag, \"type\") ?? \"\").toLowerCase() === \"module\";\n const hasSrc = readDecodedAttr(tag, \"src\") !== null;\n const hasAsync = readDecodedAttr(tag, \"async\") !== null;\n const hasDefer = readDecodedAttr(tag, \"defer\") !== null;\n if ((isModule || hasSrc) && hasAsync) return \"async\";\n if (isModule) return \"module\";\n if (hasSrc && hasDefer) return \"defer\";\n return \"blocking\";\n };\n const firstUseMode = firstUseScript ? executionMode(firstUseScript.attrs) : \"blocking\";\n const hasMotionPathPlugin = scripts\n .slice(0, firstMotionPathScriptIndex + 1)\n .some((script, candidateIndex) => {\n const candidateMode = executionMode(script.attrs);\n const sameScript = candidateIndex === firstMotionPathScriptIndex;\n const candidateIsPostParse = candidateMode === \"defer\" || candidateMode === \"module\";\n const firstUseIsPostParse = firstUseMode === \"defer\" || firstUseMode === \"module\";\n const executesBeforeFirstUse =\n sameScript ||\n candidateMode === \"blocking\" ||\n (candidateIsPostParse && firstUseIsPostParse);\n if (!executesBeforeFirstUse || (!sameScript && candidateMode === \"async\")) return false;\n const src = readAttr(`<script ${script.attrs}>`, \"src\") ?? \"\";\n const uncommented = stripJsComments(script.content);\n const hasStaticImport =\n /\\bimport\\s+(?:[\\s\\S]*?\\sfrom\\s*)?[\"'][^\"']*\\bMotionPathPlugin\\b[^\"']*[\"']/.test(\n uncommented,\n ) ||\n /\\bimport\\s+(?:[\\w$]+\\s*,\\s*)?\\{[^}]*\\bMotionPathPlugin\\b[^}]*\\}\\s+from\\s*[\"'][^\"']+[\"']/.test(\n uncommented,\n ) ||\n /\\bimport\\s+MotionPathPlugin\\s+from\\s*[\"'][^\"']+[\"']/.test(uncommented);\n const inlinedMarkerIndex = script.content.search(/\\/\\*\\s*inlined:.*MotionPathPlugin/i);\n const definitionIndex = uncommented.search(\n /\\b(?:const|let|var|class|function)\\s+MotionPathPlugin\\b/,\n );\n if (sameScript) {\n if (hasStaticImport) return true;\n if (firstMotionPathUseIndex === null) return false;\n return (\n (inlinedMarkerIndex >= 0 && inlinedMarkerIndex < firstMotionPathUseIndex) ||\n (definitionIndex >= 0 && definitionIndex < firstMotionPathUseIndex)\n );\n }\n return (\n /MotionPathPlugin/i.test(src) ||\n hasStaticImport ||\n inlinedMarkerIndex >= 0 ||\n definitionIndex >= 0\n );\n });\n if (firstMotionPathScriptIndex < 0 || hasMotionPathPlugin) return [];\n return [\n {\n code: \"missing_gsap_plugin\",\n severity: \"error\",\n message:\n \"A GSAP tween uses motionPath, but MotionPathPlugin is not loaded. Core GSAP ignores this plugin-specific property, so the intended motion will not render.\",\n fixHint:\n \"Load MotionPathPlugin before the animation script and register it with gsap.registerPlugin(MotionPathPlugin), or replace motionPath with core GSAP x/y tweens.\",\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 if (!hasCaptionStyles(styles)) 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, rootTag }) => {\n const findings: HyperframeLintFinding[] = [];\n const declaredDuration = Number.parseFloat(\n rootTag ? (readAttr(rootTag.raw, \"data-duration\") ?? \"\") : \"\",\n );\n const hasFiniteCompositionWindow = Number.isFinite(declaredDuration) && declaredDuration > 0;\n // Match repeat: -1 in GSAP tweens or timeline configs\n const pattern = /repeat\\s*:\\s*-1(?!\\d)/g;\n for (const { snippet } of scanScriptsForRegexMatches(scripts, pattern, {\n stripComments: true,\n contextBefore: 60,\n contextAfter: 60,\n })) {\n findings.push({\n code: \"gsap_infinite_repeat\",\n severity: hasFiniteCompositionWindow ? \"warning\" : \"error\",\n message: hasFiniteCompositionWindow\n ? `GSAP tween uses \\`repeat: -1\\` (infinite), but the composition declares a finite ${declaredDuration}s window. ` +\n \"HyperFrames clips deterministic seeking and export to that explicit duration.\"\n : \"GSAP tween uses `repeat: -1` (infinite) without a finite composition `data-duration`. \" +\n \"The timeline can report an unbounded duration and make render planning fail.\",\n fixHint: hasFiniteCompositionWindow\n ? \"Keep the explicit finite composition `data-duration`. Use a finite repeat count only when the loop itself must end before the composition does.\"\n : \"Add a finite composition `data-duration`, or replace `repeat: -1` with \" +\n \"`repeat: Math.max(0, Math.floor(totalDuration / singleCycleDuration) - 1)`.\",\n snippet: truncateSnippet(snippet),\n });\n }\n return findings;\n },\n\n // gsap_repeat_ceil_overshoot\n ({ scripts }) => {\n const findings: HyperframeLintFinding[] = [];\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 for (const { snippet } of scanScriptsForRegexMatches(scripts, pattern, {\n stripComments: false,\n contextBefore: 40,\n contextAfter: 40,\n })) {\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.max(0, 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 return findings;\n },\n\n // gsap_repeat_floor_unclamped\n ({ scripts }) => {\n const findings: HyperframeLintFinding[] = [];\n // A direct floor-minus-one expression becomes GSAP's infinite -1 sentinel when\n // the visible duration is shorter than one full cycle. Math.max-wrapped forms\n // intentionally do not match because `repeat:` is followed by Math.max, not Math.floor.\n const pattern = /repeat\\s*:\\s*Math\\.floor\\s*\\([^)]+\\)\\s*-\\s*1/g;\n for (const { snippet } of scanScriptsForRegexMatches(scripts, pattern, {\n stripComments: false,\n contextBefore: 40,\n contextAfter: 40,\n })) {\n findings.push({\n code: \"gsap_repeat_floor_unclamped\",\n severity: \"warning\",\n message:\n \"GSAP repeat calculation can evaluate to -1 when the composition is shorter than one cycle, \" +\n \"which GSAP interprets as an infinite repeat.\",\n fixHint:\n \"Clamp the finite repeat count at zero: \" +\n \"`repeat: Math.max(0, Math.floor(totalDuration / cycleDuration) - 1)`.\",\n snippet: truncateSnippet(snippet),\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 // A tl.set on \"#id\" is only safe advice when the scene element isn't\n // itself a clip — otherwise gsap_animates_clip_element errors on that\n // exact tl.set, since the framework already owns visibility/display on\n // clip elements. Point at the inner-wrapper pattern instead.\n const classes = (readAttr(tag.raw, \"class\") || \"\").split(/\\s+/).filter(Boolean);\n const isClip = classes.includes(\"clip\");\n const fixHint = isClip\n ? `\"#${id}\" is a clip element — the framework already manages its visibility. ` +\n \"Wrap the scene's content in an inner non-clip <div>, move the exit tween and the hard kill \" +\n '(`tl.set(\"<inner-selector>\", { visibility: \"hidden\" }, <exit-end-time>)`) onto that wrapper instead.'\n : `Add \\`tl.set(\"#${id}\", { visibility: \"hidden\" }, <exit-end-time>)\\` after the scene's exit tweens.`;\n\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,\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 =\n WINDOW_TIMELINE_ASSIGN_PATTERN.test(content) ||\n TIMELINE_REGISTRY_OBJECT_LITERAL_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 // CSS/GSAP-hidden reveal safety. A fromTo() whose from-vars make an element\n // visible but whose destination omits opacity works during sequential seeks,\n // yet cold render workers restore the authored hidden state and encode it\n // permanently invisible.\n // fallow-ignore-next-line complexity\n async ({ styles, scripts, tags }) => {\n const findings: HyperframeLintFinding[] = [];\n const cssOpacityZeroSelectors = collectCssOpacityZeroSelectors(styles, tags);\n\n for (const script of scripts) {\n if (!/gsap\\.timeline/.test(script.content)) continue;\n const windows = await cachedExtractGsapWindows(script.content);\n const hiddenSelectors = new Set([\n ...cssOpacityZeroSelectors,\n ...extractStandaloneHiddenSelectors(script.content),\n ]);\n\n for (const win of windows) {\n const sel = win.targetSelector;\n const cssKey = sel.startsWith(\"#\") || sel.startsWith(\".\") ? sel : `#${sel}`;\n if (!hiddenSelectors.has(cssKey)) continue;\n\n if (\n win.method === \"fromTo\" &&\n win.fromPropertyValues &&\n isVisibleGsapState(win.fromPropertyValues) &&\n !win.properties.some((property) => property === \"opacity\" || property === \"autoAlpha\")\n ) {\n findings.push({\n code: \"gsap_cold_seek_hidden_fromto_missing_reveal\",\n severity: \"error\",\n message:\n `\"${sel}\" starts hidden, but its gsap.fromTo() makes it visible only in the from-vars ` +\n \"and omits opacity/autoAlpha from the destination. Cold render workers restore the hidden authored state, so the encoded element can stay invisible even when sequential snapshots look correct.\",\n selector: sel,\n fixHint: `Add \\`opacity: 1\\` (or \\`autoAlpha: 1\\`) to the destination vars for \"${sel}\" so every seek path establishes the visible end state explicitly.`,\n snippet: truncateSnippet(win.raw),\n });\n continue;\n }\n\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\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_non_transform_motion — animating layout props (left/top/right/bottom/margin*)\n // or using roundProps snaps motion to integer device pixels. On the seek-by-frame\n // capture engine this looks smooth at high per-frame deltas (fast tweens) but visibly\n // stutters at low deltas (slow tweens / ease-out tails): sub-pixel movement rounds to\n // the same pixel for several frames, then jumps a whole pixel. Transforms (x/y/scale)\n // interpolate sub-pixel and stay smooth.\n //\n // EXEMPTION: elements rasterized via the html-in-canvas API — those under a\n // `<canvas layoutsubtree>` ancestor (e.g. the liquid-glass blocks) — are NOT laid out\n // by the browser compositor. The canvas lib reads getComputedStyle().left/top (a\n // sub-pixel value) and draws the element to a bitmap, so animating a layout prop on\n // them does not integer-snap and does not stutter. We resolve each tween's target to\n // its element(s) and skip the finding only when EVERY target is html-in-canvas; a\n // grouped tween that also touches a plain-DOM element (which does stutter) still fires.\n //\n // No suppression by design: there is intentionally no per-line/per-file opt-out (unlike\n // eslint-disable). The stance is fix-the-motion, not silence-the-rule — a plain-DOM\n // layout-prop animation always has a faithful transform equivalent (per-glyph x for\n // spacing, scale for size, x/y for position). An author who has consciously accepted a\n // stutter still has no flag to flip; that is deliberate, not a missing feature.\n async ({ scripts, tags, source }) => {\n const findings: HyperframeLintFinding[] = [];\n\n // Byte-ranges of every <canvas layoutsubtree>. An element whose open-tag index falls\n // inside one of these ranges is html-in-canvas composited.\n const layoutSubtreeRanges = tags\n .filter((t) => t.name.toLowerCase() === \"canvas\" && /\\blayoutsubtree\\b/i.test(t.raw))\n .map((t) => ({ start: t.index, end: findTagEnd(source, t) }));\n const isHtmlInCanvas = (tag: OpenTag): boolean =>\n layoutSubtreeRanges.some((r) => tag.index > r.start && tag.index < r.end);\n\n // Resolve a simple #id / .class token to the element tag(s) it matches.\n const tagsByToken = indexTagsByToken(tags);\n\n // True only when the selector resolves to at least one element AND every resolved\n // element is html-in-canvas. Unresolvable selectors (no match) are NOT exempt — we\n // stay conservative and let the finding fire rather than risk a false negative.\n const allTargetsHtmlInCanvas = (selector: string): boolean => {\n if (layoutSubtreeRanges.length === 0) return false;\n const matched = [...targetedSelectorTokens(selector)].flatMap(\n (token) => tagsByToken.get(token) ?? [],\n );\n return matched.length > 0 && matched.every(isHtmlInCanvas);\n };\n // Positional layout props → each maps to its transform replacement axis (x/y).\n const LAYOUT_FIX: Record<string, string[]> = {\n left: [\"x\"],\n right: [\"x\"],\n top: [\"y\"],\n bottom: [\"y\"],\n margin: [\"x\", \"y\"],\n marginLeft: [\"x\"],\n marginRight: [\"x\"],\n marginTop: [\"y\"],\n marginBottom: [\"y\"],\n };\n // Text-reflow props: animating them reflows text and snaps glyph positions to the\n // pixel grid, stuttering on slow motion exactly like positional props. They have no\n // transform replacement (the fix is to not animate them — settle via scale or hold the\n // value), and the snap happens during browser layout, UPSTREAM of any canvas raster, so\n // they are never html-in-canvas-exempt. (width/height are deliberately omitted: they\n // have legitimate animated uses — progress bars, reveals — and would over-report.)\n const REFLOW_PROPS = [\"letterSpacing\", \"wordSpacing\", \"fontSize\"];\n // Resolve the parser once, above the loop (the other async rules in this file do the\n // same); the dynamic-import cache makes per-iteration calls equivalent, but hoisting\n // keeps the placement from reading as load-bearing.\n const parseGsapScript = await loadParseGsapScript();\n for (const script of scripts) {\n if (!/gsap\\.timeline/.test(script.content)) continue;\n\n // Two sources: timeline-rooted tweens (tl.to/from/fromTo) and standalone\n // gsap.to/from/fromTo calls the acorn parser ignores.\n //\n // Timeline tweens come straight from the acorn parser's animation list — NOT\n // cachedExtractGsapWindows, which drops every tween with a non-numeric timeline\n // position (a string label or `+=`/`-=` offset, e.g. `tl.to(\"#x\",{left:9},\"hold6\")`).\n // Position is irrelevant to whether a tween animates a layout prop, so dropping\n // those would let real stutter-prone tweens escape. The parser also gives real AST\n // keys, so a nested `{}` value (an onComplete body, modifiers) and a layout-prop\n // name appearing inside a string value can't be misread — both hazards of a raw scan.\n const parsed = parseGsapScript(script.content);\n const calls: GsapTransformCall[] = [\n ...parsed.animations.map((anim) => ({\n method: anim.method,\n selector: anim.targetSelector,\n // Union the from-vars: a fromTo() can animate a layout/reflow prop that appears\n // only in its first (\"from\") object, which is just as stutter-prone as the to-vars.\n properties: [\n ...new Set([\n ...Object.keys(anim.properties),\n ...Object.keys(anim.fromProperties ?? {}),\n ]),\n ],\n raw: synthesizeWindowRaw(parsed.timelineVar, anim),\n })),\n ...extractStandaloneGsapTransformCalls(stripJsComments(script.content)),\n ];\n\n for (const call of calls) {\n // set() is instantaneous — it never animates, so it cannot stutter. A set() that\n // seats an integer-snapped layout position (e.g. tl.set(\"#x\",{left:100})) before a\n // later transform tween is a single from-state frame, not motion; intentionally skipped.\n if (call.method === \"set\") continue;\n // Object.hasOwn, not `in`: a tween property named `toString`/`constructor` would\n // match the prototype chain and resolve LAYOUT_FIX[p] to an inherited function.\n let layoutProps = call.properties.filter((p) => Object.hasOwn(LAYOUT_FIX, p));\n const reflowProps = call.properties.filter((p) => REFLOW_PROPS.includes(p));\n const usesRoundProps = call.properties.includes(\"roundProps\");\n // Only positional props are html-in-canvas-exempt: the canvas positions the draw\n // from sub-pixel computed left/top. Reflow props (glyph layout) and roundProps\n // (value rounding) snap upstream of the raster, so they always fire.\n if (layoutProps.length > 0 && allTargetsHtmlInCanvas(call.selector)) layoutProps = [];\n if (layoutProps.length === 0 && reflowProps.length === 0 && !usesRoundProps) continue;\n\n const flagged = [...layoutProps, ...reflowProps, ...(usesRoundProps ? [\"roundProps\"] : [])];\n const message =\n `GSAP tween on \"${call.selector}\" uses motion that snaps to integer device pixels: ` +\n `${flagged.join(\", \")}. Layout and text-reflow properties snap during browser layout; ` +\n \"roundProps rounds the tween value. Slow motion or an ease-out tail then stutters under \" +\n \"the seek-by-frame capture engine — animate transforms (x/y/scale/opacity) instead.\";\n\n const fixes: string[] = [];\n if (layoutProps.length > 0) {\n const tokens = [...new Set(layoutProps.flatMap((p) => LAYOUT_FIX[p] ?? []))];\n fixes.push(\n `replace ${layoutProps.join(\"/\")} with the transform equivalent (${tokens.join(\", \")}) — ` +\n `e.g. tl.fromTo(\"${call.selector}\", { x: -1300 }, { x: 0, ...yourAnimation })`,\n );\n }\n if (reflowProps.length > 0) {\n // Faithful fix differs by property: fontSize maps to scale (same visual), but\n // letterSpacing/wordSpacing do NOT — uniform scale resizes glyphs, it does not\n // change the gaps between them. The smooth equivalent of a spacing tween is a\n // per-glyph split with an x transform per character.\n const sizing = reflowProps.filter((p) => p === \"fontSize\");\n const spacing = reflowProps.filter((p) => p !== \"fontSize\");\n const parts: string[] = [];\n if (sizing.length > 0) {\n parts.push(`replace ${sizing.join(\"/\")} with scale (same visual, no reflow)`);\n }\n if (spacing.length > 0) {\n parts.push(\n `for ${spacing.join(\"/\")}, split the text into per-character elements and animate ` +\n \"each glyph's x (the spread) — uniform scale is NOT equivalent — or hold the final value statically\",\n );\n }\n fixes.push(\n `do not animate ${reflowProps.join(\"/\")} (they reflow text and snap glyph positions): ` +\n parts.join(\"; \"),\n );\n }\n if (usesRoundProps) fixes.push(\"remove roundProps\");\n const fixHint = `${fixes.join(\"; \")}. Transforms interpolate sub-pixel and stay smooth at any speed.`;\n\n findings.push({\n code: \"gsap_non_transform_motion\",\n severity: \"error\",\n message,\n selector: call.selector,\n fixHint,\n snippet: truncateSnippet(call.raw),\n });\n }\n }\n return findings;\n },\n\n // gsap_relative_value_second_writer — a relative tween value (\"+=...\"/\"-=...\") on a\n // property that another writer is still ACTIVE on when the relative tween starts.\n // The relative tween captures its base at tween INIT, which happens on first render:\n // the sequential path inits it mid-flight of the other writer, a cold render worker\n // landing later inits it with the other writer's end state — the same frame then\n // renders at two different positions (a visible snap at chunk boundaries).\n // GSAP renders children in start-time order within a single seek pass, so a writer\n // that completes strictly BEFORE the relative tween's start yields identical bases\n // on every seek path and is never flagged. Single-writer relative values are\n // seek-stable. from()/fromTo() resolve their values at build (immediateRender), so\n // they are exempt. The position PARAMETER (\"+=0.5\") is not a tween value — the\n // parser keeps it out of properties — so it can never be flagged here.\n async ({ scripts, tags }) => {\n const findings: HyperframeLintFinding[] = [];\n const tagsByToken = indexTagsByToken(tags);\n for (const script of scripts) {\n if (!/gsap\\.timeline/.test(script.content)) continue;\n const windows = await cachedExtractGsapWindows(script.content);\n for (const win of windows) {\n if (win.method === \"from\" || win.method === \"fromTo\") continue;\n if (win.overwriteAuto) continue;\n if (targetHasNoStableIdentity(win.targetSelector, win.targetIdentity)) continue;\n const relativeProps = Object.entries(win.propertyValues)\n .filter(([, value]) => isRelativeTweenValue(value))\n .map(([prop]) => prop);\n if (relativeProps.length === 0) continue;\n const target = { selector: win.targetSelector, identity: win.targetIdentity };\n for (const other of windows) {\n if (other === win) continue;\n if (other.position > win.position || other.end <= win.position) continue;\n const sharedProps = relativeProps.filter((prop) => other.properties.includes(prop));\n if (sharedProps.length === 0) continue;\n if (\n !targetsShareElement(\n target,\n { selector: other.targetSelector, identity: other.targetIdentity },\n tagsByToken,\n )\n ) {\n continue;\n }\n const values = sharedProps\n .map((prop) => `${prop}: \"${win.propertyValues[prop]}\"`)\n .join(\", \");\n const overlapEnd = Math.min(win.end, other.end);\n const formatTime = (t: number): string => (Number.isFinite(t) ? `${t.toFixed(2)}s` : \"∞\");\n findings.push({\n code: \"gsap_relative_value_second_writer\",\n severity: \"error\",\n message:\n `Relative value(s) ${values} on \"${win.targetSelector}\" start while another writer for the same ` +\n `propert${sharedProps.length > 1 ? \"ies\" : \"y\"} is active between ${formatTime(win.position)} and ${formatTime(overlapEnd)}. ` +\n \"Relative tweens capture their base at tween init: the sequential path inits mid-flight of the other \" +\n \"writer, a cold render worker landing later inits with its end state — the same frame renders at two \" +\n \"different positions (snap at chunk boundaries).\",\n selector: win.targetSelector,\n fixHint:\n `Use absolute values for ${sharedProps.join(\", \")}, or a fromTo() with explicit endpoints, so every seek ` +\n \"path resolves the same state. Single-writer relative values are safe; the conflict is the second writer.\",\n snippet: truncateSnippet(`${win.raw}\\n${other.raw}`),\n });\n }\n }\n }\n return findings;\n },\n\n // gsap_repeat_refresh_relative_value — repeatRefresh re-resolves the tween's values\n // on every repeat iteration, so a relative value ACCUMULATES per cycle. A cold render\n // worker seeking non-linearly into iteration N skips the accumulation a sequential\n // playhead performed, so workers disagree on where the element is.\n ({ scripts }) => {\n const findings: HyperframeLintFinding[] = [];\n for (const script of scripts) {\n const source = stripJsComments(script.content);\n const pattern = /repeatRefresh\\s*:\\s*true\\b/g;\n let match: RegExpExecArray | null;\n while ((match = pattern.exec(source)) !== null) {\n const objectLiteral = enclosingObjectLiteral(source, match.index);\n if (!objectLiteral || !objectLiteralHasTopLevelRelativeValue(objectLiteral)) continue;\n findings.push({\n code: \"gsap_repeat_refresh_relative_value\",\n severity: \"error\",\n message:\n '`repeatRefresh: true` combined with a relative value (\"+=\"/\"-=\") accumulates per repeat iteration. ' +\n \"A cold render worker seeking non-linearly into iteration N never performed the earlier iterations' \" +\n \"accumulation, so its rendered position diverges from the sequential path.\",\n fixHint:\n \"Remove `repeatRefresh: true`, or replace the relative value with absolute endpoints (e.g. a fromTo()) \" +\n \"so each iteration resolves to the same state on every seek path.\",\n snippet: truncateSnippet(objectLiteral),\n });\n }\n }\n return findings;\n },\n\n // gsap_function_value_hazard — function-valued tween vars re-run at tween INIT,\n // which is seek-order-dependent. A value reading transform-SENSITIVE geometry\n // (getBoundingClientRect/getComputedStyle/gsap.getProperty) captures whatever state\n // the worker's own seek order produced — error. Transform-INVARIANT layout reads\n // (offsetWidth, getTotalLength, ...) are deterministic across cold render workers\n // unless the measured layout itself animates — warning. GSAP function values receive\n // (index, target, targets) — index is a NUMBER, so a method call on the first\n // parameter (assuming it is the element) throws at init — error. Pure-index\n // arithmetic, gsap.utils.wrap/distribute, and closures over constants are statically\n // opaque or safe and are never flagged.\n //\n // Uses the raw parser output instead of the windows machinery: windows drop tweens\n // with string positions (\"+=0.5\", labels), and position is irrelevant to whether a\n // VALUE is hazardous.\n async ({ scripts }) => {\n const findings: HyperframeLintFinding[] = [];\n const parseGsapScript = await loadParseGsapScript();\n for (const script of scripts) {\n if (!/gsap\\.timeline/.test(script.content)) continue;\n const parsed = parseGsapScript(script.content);\n for (const anim of parsed.animations) {\n const raw = synthesizeWindowRaw(parsed.timelineVar, anim);\n const entries = [\n ...Object.entries(anim.properties),\n ...Object.entries(anim.fromProperties ?? {}),\n ];\n for (const [prop, value] of entries) {\n if (typeof value !== \"string\" || !value.startsWith(\"__raw:\")) continue;\n const fn = parseFunctionValueSource(value.slice(6));\n // Non-function raw values (gsap.utils.wrap(...), identifiers, arithmetic)\n // are statically opaque — conservatively skipped.\n if (!fn) continue;\n const readsSensitive = TRANSFORM_SENSITIVE_READ.test(fn.body);\n const readsInvariant = TRANSFORM_INVARIANT_READ.test(fn.body);\n const badMember = firstParamMemberAccessHazard(fn);\n if (!readsSensitive && !readsInvariant && !badMember) continue;\n const reason = readsSensitive\n ? \"reads transform-sensitive geometry, so its result depends on the worker's own seek order\"\n : badMember\n ? `accesses .${badMember} on its first parameter — GSAP function values receive (index, target, targets), ` +\n \"so the first parameter is a NUMBER and this throws at tween init\"\n : \"measures layout at tween init, which is deterministic across cold render workers only while the measured layout never animates\";\n findings.push({\n code: \"gsap_function_value_hazard\",\n severity: readsSensitive || badMember ? \"error\" : \"warning\",\n message: `Function-valued tween var for ${prop} on \"${anim.targetSelector}\" ${reason}. Each render worker initializes tweens independently.`,\n selector: anim.targetSelector,\n fixHint: badMember\n ? \"Use the SECOND parameter for the element: (index, target) => ... — or index arithmetic like (i) => i * 20.\"\n : \"Compute the value once at build time (before the timeline is registered) and pass a constant, or derive it from fixed composition coordinates.\",\n snippet: truncateSnippet(raw),\n });\n }\n }\n }\n return findings;\n },\n\n // gsap_callback_dom_measurement — DOM measurement reachable from timeline callbacks\n // (tl.add(fn) / tl.call(fn) / eventCallback / onStart-style vars). The capture path\n // seeks with suppressEvents=false (core/src/adapters/gsap.ts), so callbacks re-fire\n // on EVERY seek, including rewinds — and a cold render worker executes them against\n // whatever DOM state its own non-linear seek order produced. Geometry measured\n // inside a callback is therefore seek-order-dependent, and anything measured before\n // the callback ran (e.g. a build-time getTotalLength() on a path whose `d` the\n // callback assigns) is stale or zero. Warning, not error: gsap.getProperty-style\n // derived-output callbacks were excluded, but the remaining reads can still be\n // legitimate when the measured layout is static.\n ({ scripts }) => {\n const findings: HyperframeLintFinding[] = [];\n for (const script of scripts) {\n const source = stripJsComments(script.content);\n if (!/gsap\\.timeline/.test(source)) continue;\n const bodies = collectNamedFunctionBodies(source);\n const measuring = collectMeasuringFunctionNames(bodies);\n\n // A callback argument is hazardous when it is an inline function whose body\n // reaches a measurement, or a bare reference to a measuring function. Call\n // expressions (`tl.add(build())`) execute at BUILD time, not as callbacks —\n // conservatively skipped.\n const callbackExpressionHazard = (expression: string): boolean => {\n const trimmed = expression.trim();\n const inline = parseFunctionValueSource(trimmed);\n if (inline) return expressionReachesMeasurement(inline.body, measuring);\n if (/^[A-Za-z_$][\\w$]*$/.test(trimmed)) return measuring.has(trimmed);\n return false;\n };\n // The callback site goes into the structured `selector` field: the linter\n // dedupes on code+selector+message, and a constant message would collapse\n // distinct callback sites into a single finding.\n const report = (site: string, snippet: string): void => {\n findings.push({\n code: \"gsap_callback_dom_measurement\",\n severity: \"warning\",\n message:\n \"Timeline callback reaches DOM measurement (getBoundingClientRect/getTotalLength/getComputedStyle/...). \" +\n \"The renderer seeks with suppressEvents=false, so callbacks re-fire on every seek — and a cold render \" +\n \"worker runs them against whatever DOM state its own non-linear seek order produced. Measured geometry is \" +\n \"seek-order-dependent, and values measured at build time (before the callback ran) are stale or zero.\",\n selector: truncateSnippet(site, 120),\n fixHint:\n \"Do all measurement and DOM setup synchronously at build time, before registering the timeline — \" +\n \"or derive geometry from fixed composition coordinates instead of measuring.\",\n snippet: truncateSnippet(snippet),\n });\n };\n\n const timelineVars = collectTimelineVarNames(source);\n for (const timelineVar of timelineVars) {\n const callPattern = new RegExp(\n `\\\\b${escapeRegExp(timelineVar)}\\\\.(?:add|call)\\\\s*\\\\(`,\n \"g\",\n );\n let match: RegExpExecArray | null;\n while ((match = callPattern.exec(source)) !== null) {\n const parenIndex = match.index + match[0].length - 1;\n const argsWithParens = matchBalanced(source, parenIndex, \"(\", \")\");\n if (!argsWithParens) continue;\n const firstArg = sliceExpression(argsWithParens.slice(1, -1), 0);\n const site = match[0] + firstArg + \", ...)\";\n if (callbackExpressionHazard(firstArg)) report(site, site);\n }\n\n const eventCallbackPattern = new RegExp(\n `\\\\b${escapeRegExp(timelineVar)}\\\\.eventCallback\\\\s*\\\\(\\\\s*[\"']on[A-Za-z]+[\"']\\\\s*,`,\n \"g\",\n );\n while ((match = eventCallbackPattern.exec(source)) !== null) {\n const expression = sliceExpression(source, eventCallbackPattern.lastIndex);\n const site = match[0] + expression + \")\";\n if (callbackExpressionHazard(expression)) report(site, site);\n }\n }\n\n const varsCallbackPattern =\n /\\bon(?:Start|Update|Complete|Repeat|ReverseComplete|Interrupt|Overwrite)\\s*:\\s*/g;\n let match: RegExpExecArray | null;\n while ((match = varsCallbackPattern.exec(source)) !== null) {\n if (!isInsideGsapTweenVars(source, match.index, timelineVars)) continue;\n const expression = sliceExpression(source, varsCallbackPattern.lastIndex);\n const site = match[0] + expression;\n if (callbackExpressionHazard(expression)) report(site, site);\n }\n }\n return findings;\n },\n\n // gsap_group_selector_keyframes\n ({ scripts }) => {\n const findings: HyperframeLintFinding[] = [];\n const pattern = /\\.(?:to|from|fromTo)\\(\\s*[\"']([^\"']+,\\s*[^\"']+)[\"']\\s*,\\s*\\{[^}]*keyframes/g;\n for (const { match, snippet } of scanScriptsForRegexMatches(scripts, pattern, {\n stripComments: true,\n contextBefore: 20,\n contextAfter: 40,\n })) {\n const selector = match[1]!;\n const count = selector.split(\",\").length;\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(snippet),\n });\n }\n return findings;\n },\n\n // svg_drawon_css_dasharray_conflict — GSAP sets/tweens strokeDasharray on an element\n // whose CSS declares a MULTI-component stroke-dasharray (e.g. `10 10`). GSAP merges\n // dash lists per component, so `strokeDasharray: 641.4` over CSS `10 10` computes to\n // \"641.4px, 10px\" — the gap stays 10px and the hide-then-draw-on trick silently\n // fails: the line is visible the whole scene. A static two-component GSAP value is\n // the explicit fix form and is not flagged.\n // fallow-ignore-next-line complexity\n ({ scripts, styles, tags }) => {\n const findings: HyperframeLintFinding[] = [];\n const tagsByToken = indexTagsByToken(tags);\n\n const multiDashTokens = new Set<string>();\n for (const style of styles) {\n for (const [, selectorList, body] of style.content.matchAll(/([^{}]+)\\{([^}]+)\\}/g)) {\n if (!selectorList || !body) continue;\n const value = readStyleProperty(body, \"stroke-dasharray\");\n if (!value || !isMultiComponentDasharray(value)) continue;\n // Skip combinator groups — scope-dependent, unsafe to correlate by leaf token.\n for (const group of selectorList.split(\",\")) {\n const trimmed = group.trim();\n if (!trimmed || /[\\s>+~]/.test(trimmed)) continue;\n for (const token of targetedSelectorTokens(trimmed)) multiDashTokens.add(token);\n }\n }\n }\n for (const tag of tags) {\n const inlineValue = readStyleProperty(readAttr(tag.raw, \"style\") ?? \"\", \"stroke-dasharray\");\n if (!inlineValue || !isMultiComponentDasharray(inlineValue)) continue;\n for (const token of tagSimpleSelectors(tag)) multiDashTokens.add(token);\n }\n if (multiDashTokens.size === 0) return findings;\n\n for (const script of scripts) {\n const source = stripJsComments(script.content);\n const varTokens = resolveScriptElementTokens(source, tags);\n const reported = new Set<string>();\n\n const writerPattern =\n /\\b[\\w$]+\\.(set|to|fromTo)\\s*\\(\\s*(?:([\"'])([^\"'`]+)\\2|([A-Za-z_$][\\w$]*))\\s*,\\s*\\{/g;\n let match: RegExpExecArray | null;\n while ((match = writerPattern.exec(source)) !== null) {\n const method = match[1] ?? \"\";\n const braceIndex = match.index + match[0].length - 1;\n const firstVars = matchBalanced(source, braceIndex, \"{\", \"}\");\n if (!firstVars) continue;\n const varsObjects = [firstVars];\n if (method === \"fromTo\") {\n const afterFirst = source.slice(braceIndex + firstVars.length);\n const secondOpen = /^\\s*,\\s*\\{/.exec(afterFirst);\n if (secondOpen) {\n const secondBrace = braceIndex + firstVars.length + secondOpen[0].length - 1;\n const secondVars = matchBalanced(source, secondBrace, \"{\", \"}\");\n if (secondVars) varsObjects.push(secondVars);\n }\n }\n\n const quotedSelector = match[3];\n const targetTokens = quotedSelector\n ? targetedSelectorTokens(quotedSelector)\n : (varTokens.get(match[4] ?? \"\") ?? new Set<string>());\n if (targetTokens.size === 0) continue;\n const expanded = elementLevelTokens(targetTokens, tagsByToken);\n\n for (const varsObject of varsObjects) {\n const propMatch =\n varsObject.match(/\\bstrokeDasharray\\s*:\\s*/) ??\n varsObject.match(/[\"']stroke-dasharray[\"']\\s*:\\s*/);\n if (!propMatch || propMatch.index === undefined) continue;\n const valueSource = sliceExpression(varsObject, propMatch.index + propMatch[0].length);\n if (gsapDasharrayValueLooksMultiComponent(valueSource)) continue;\n const conflictToken = [...expanded].find((token) => multiDashTokens.has(token));\n if (!conflictToken) continue;\n const targetLabel = quotedSelector ?? match[4] ?? \"\";\n if (reported.has(targetLabel + conflictToken)) continue;\n reported.add(targetLabel + conflictToken);\n findings.push({\n code: \"svg_drawon_css_dasharray_conflict\",\n severity: \"error\",\n message:\n `GSAP writes strokeDasharray on \"${targetLabel}\", but its CSS (\"${conflictToken}\") declares a multi-component ` +\n 'stroke-dasharray. GSAP merges dash lists per component, so the CSS gap survives (e.g. \"641.4px, 10px\") — ' +\n \"the draw-on hide only hides one gap's worth and the line stays visible the whole scene.\",\n selector: quotedSelector ?? undefined,\n fixHint:\n `Remove the CSS stroke-dasharray from \"${conflictToken}\" (decorative dashes belong on a separate element), ` +\n 'or set the full two-component value in GSAP: strokeDasharray: \"${len} ${len}\".',\n snippet: truncateSnippet(match[0] + firstVars.slice(1)),\n });\n }\n }\n }\n return findings;\n },\n\n // gsap_timeline_set_initial_hide — a zero-duration tl.set(...) at position 0 inside\n // the paused timeline does NOT render while the playhead sits exactly at 0 (verified\n // against this repo's GSAP: tl.time(0) leaves the target untouched; only a seek past\n // 0 applies it). Frame 0 therefore shows the UN-hidden state, then the element pops\n // hidden on frame 1 — and only for the worker that renders frame 0. Targets already\n // hidden by authored CSS/inline styles or by a standalone gsap.set are exempt: the\n // tl.set is then a defensive re-assertion and frame 0 is hidden anyway.\n //\n // Only sets that precede every tween in source order qualify: the parser resolves a\n // mutated position variable (`var t = 0; ...; tl.set(sel, vars, t)`) to its INITIAL\n // binding, so late hard-kills can masquerade as position-0 sets. Genuine\n // initial-state hides are authored before the timeline's tweens.\n async ({ scripts, styles, tags }) => {\n const findings: HyperframeLintFinding[] = [];\n const cssHiddenSelectors = collectCssOpacityZeroSelectors(styles, tags);\n const tagsByToken = indexTagsByToken(tags);\n for (const script of scripts) {\n if (!/gsap\\.timeline/.test(script.content)) continue;\n const windows = await cachedExtractGsapWindows(script.content);\n const alreadyHidden = new Set([\n ...cssHiddenSelectors,\n ...extractStandaloneHiddenSelectors(script.content),\n ]);\n const isInstantHold = (win: GsapWindow): boolean =>\n win.method === \"set\" ||\n ((win.method === \"to\" || win.method === \"fromTo\") && win.end === win.position);\n const firstTweenIndex = windows.findIndex((win) => !isInstantHold(win));\n const initialHolds = firstTweenIndex < 0 ? windows : windows.slice(0, firstTweenIndex);\n for (const win of initialHolds) {\n if (!isInstantHold(win) || win.position !== 0) continue;\n if (win.global || win.immediateRender) continue;\n if (targetHasNoStableIdentity(win.targetSelector, win.targetIdentity)) continue;\n const targetTokens = [...targetedSelectorTokens(win.targetSelector)];\n const hiddenByToken =\n targetTokens.length > 0 && targetTokens.every((token) => alreadyHidden.has(token));\n const resolvedTags = targetTokens.flatMap((token) => tagsByToken.get(token) ?? []);\n const hiddenByElement =\n resolvedTags.length > 0 &&\n resolvedTags.every((tag) =>\n tagSimpleSelectors(tag).some((token) => alreadyHidden.has(token)),\n );\n if (hiddenByToken || hiddenByElement) continue;\n const offset = win.propertyValues[\"strokeDashoffset\"];\n const hidesByOffset = numberValue(offset) !== null && !zeroValue(offset);\n const hides =\n isHiddenGsapState(win.propertyValues) ||\n zeroValue(win.propertyValues[\"scale\"]) ||\n hidesByOffset;\n if (!hides) continue;\n findings.push({\n code: \"gsap_timeline_set_initial_hide\",\n severity: \"warning\",\n message:\n `Initial hidden state for \"${win.targetSelector}\" is set via tl.set(...) at position 0 inside the paused ` +\n \"timeline. A zero-duration set at 0 does not render while the playhead sits exactly at 0, so frame 0 \" +\n \"shows the un-hidden state.\",\n selector: win.targetSelector,\n fixHint:\n \"Use gsap.set(...) (immediate, outside the timeline) for initial states, or author the hidden state \" +\n \"directly in CSS/attributes.\",\n snippet: truncateSnippet(win.raw),\n });\n }\n }\n return findings;\n },\n\n // svg_measure_before_path_d — getTotalLength() on a <path> that has no static `d`\n // attribute in the HTML. In Chrome getTotalLength() on a d-less path returns 0,\n // silently killing dash animations (offset 0 == length 0 == nothing to draw). If a\n // d assignment exists but only inside a function body, execution order is statically\n // undecidable — WARNING; if NO d assignment exists anywhere — ERROR. Element\n // identity is resolved conservatively (literal / template getElementById,\n // querySelector); createElementNS-built paths and unresolved variables are skipped.\n // fallow-ignore-next-line complexity\n ({ scripts, styles, tags }) => {\n const findings: HyperframeLintFinding[] = [];\n const tagsByToken = indexTagsByToken(tags);\n // CSS `d: path(...)` supplies geometry statically — treat like a static attribute.\n const cssProvidesD = styles.some((style) => /\\bd\\s*:\\s*path\\(/.test(style.content));\n\n for (const script of scripts) {\n const source = stripJsComments(script.content);\n const varTokens = resolveScriptElementTokens(source, tags);\n const functionRanges = collectFunctionBodyRanges(source);\n const createdVars = new Set(\n [...source.matchAll(/([A-Za-z_$][\\w$]*)\\s*=\\s*document\\.createElementNS\\(/g)].map(\n (m) => m[1] ?? \"\",\n ),\n );\n // `d` assignments come in two forms: direct setAttribute('d', ...) and the\n // GSAP attr plugin (`gsap.set(wire, { attr: { d: \"...\" } })`). Both count,\n // with the same lexical-order semantics.\n const dAssignments = [\n ...[...source.matchAll(/\\b([A-Za-z_$][\\w$]*)\\.setAttribute\\(\\s*[\"']d[\"']\\s*,/g)].map(\n (m) => ({ varName: m[1] ?? \"\", index: m.index ?? 0 }),\n ),\n ...[\n ...source.matchAll(\n /\\.(?:set|to|fromTo)\\s*\\(\\s*([A-Za-z_$][\\w$]*)\\s*,\\s*\\{[^{}]*\\battr\\s*:\\s*\\{[^{}]*\\bd\\s*:/g,\n ),\n ].map((m) => ({ varName: m[1] ?? \"\", index: m.index ?? 0 })),\n ];\n const reported = new Set<string>();\n\n const measurePattern = /\\b([A-Za-z_$][\\w$]*)\\.getTotalLength\\s*\\(/g;\n let match: RegExpExecArray | null;\n while ((match = measurePattern.exec(source)) !== null) {\n const varName = match[1] ?? \"\";\n if (createdVars.has(varName)) continue;\n const tokens = varTokens.get(varName);\n if (!tokens || tokens.size === 0) continue;\n // Only <path> elements without a static d attribute qualify.\n const resolvedTags = [...tokens].flatMap((token) => tagsByToken.get(token) ?? []);\n const dLessPaths = resolvedTags.filter(\n (tag) => tag.name.toLowerCase() === \"path\" && readAttr(tag.raw, \"d\") === null,\n );\n if (dLessPaths.length === 0 || dLessPaths.length !== resolvedTags.length) continue;\n if (cssProvidesD) continue;\n\n // A same-variable d assignment lexically before the measure, in scope of the\n // measure (top-level, or a function body containing the measure), is the\n // legitimate synchronous assign-then-measure pattern.\n const measureIndex = match.index;\n const assignedBeforeInScope = dAssignments.some(\n (assign) =>\n assign.varName === varName &&\n assign.index < measureIndex &&\n (!indexInsideAnyRange(assign.index, functionRanges) ||\n functionRanges.some(\n (range) =>\n assign.index > range.start &&\n assign.index < range.end &&\n measureIndex > range.start &&\n measureIndex < range.end,\n )),\n );\n if (assignedBeforeInScope) continue;\n\n const sameVarAssignmentExists = dAssignments.some((a) => a.varName === varName);\n const tokenLabel = [...tokens].join(\", \");\n if (reported.has(tokenLabel)) continue;\n reported.add(tokenLabel);\n findings.push({\n code: \"svg_measure_before_path_d\",\n severity: sameVarAssignmentExists ? \"warning\" : \"error\",\n message: sameVarAssignmentExists\n ? `getTotalLength() is called on \"${tokenLabel}\", whose \\`d\\` is only assigned inside a function body — ` +\n \"if the measure runs before that function (e.g. the function is a timeline callback), the length is 0 \" +\n \"and the dash animation is dead.\"\n : `getTotalLength() is called on \"${tokenLabel}\", but the path has no static \\`d\\` attribute and no d ` +\n \"assignment exists anywhere — getTotalLength() returns 0 in Chrome, silently killing dash animations.\",\n selector: tokenLabel,\n fixHint:\n \"Assign the path's `d` synchronously at build time (top level, before measuring), or author a static \" +\n \"d attribute in the HTML.\",\n snippet: truncateSnippet(match[0] + \")\"),\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, OpenTag } from \"../context\";\nimport {\n findHtmlTag,\n readAttr,\n readDecodedAttr,\n readJsonAttr,\n stripJsComments,\n truncateSnippet,\n WINDOW_TIMELINE_ASSIGN_PATTERN,\n} from \"../utils\";\nimport { COMPOSITION_VARIABLE_TYPES } from \"@hyperframes/parsers/composition\";\nimport { COMPOSITION_ATTRIBUTES, readClipTiming } from \"@hyperframes/parsers/composition-contract\";\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\"]);\nconst CAPTION_CUE_TOKEN =\n /^(?:caption(?:[-_](?:group|word|line|block|cue|text))?|subtitle(?:[-_](?:group|line|cue|text))?|cg-.+)$/i;\n\n// composition_heavy_overlay_count_high — warn when a composition carries this\n// many or more elements whose CSS uses filter:blur, clip-path (non-none), or\n// radial-gradient. Field signal ts=1784040753 (#hyperframes-cli-feedback):\n// a composition with ~40 such elements captures solid-black for the first\n// ~half of the render, recovering near the end. Presence alone matters —\n// opacity:0 and visibility:hidden overlays still contribute — so the rule\n// counts every one that isn't display:none-hidden. Threshold sits below the\n// observed 40-element repro (25) so authors get lead time; adjust here if\n// noise/signal shifts, since a per-rule config option would also require\n// plumbing through HyperframeLinterOptions across every embedder.\nconst HEAVY_OVERLAY_ELEMENT_COUNT_WARN = 25;\nconst HEAVY_OVERLAY_EXEMPT_TAGS = new Set([\n \"audio\",\n \"body\",\n \"br\",\n \"defs\",\n \"head\",\n \"hr\",\n \"html\",\n \"link\",\n \"meta\",\n \"script\",\n \"source\",\n \"style\",\n \"template\",\n \"title\",\n \"use\",\n \"video\",\n]);\n// Matches any of: `filter: <...>blur(...)`, `clip-path: <non-none-value>`,\n// or `radial-gradient(...)`. Property terminator is `;` or `}`; value class\n// excludes both so we don't over-match into the next declaration. `clip-path`\n// escapes when its value starts with a CSS-wide keyword that leaves the render\n// tree unaffected (none / inherit / initial / unset) — the whitespace-eating\n// `\\s*` lives *inside* the negative lookahead so the engine can't backtrack\n// `\\s*` from outside to 0-width and slip past the keyword guard.\nconst HEAVY_OVERLAY_CSS_PATTERN =\n /(?:filter\\s*:[^;}]*\\bblur\\s*\\()|(?:clip-path\\s*:(?!\\s*(?:none|inherit|initial|unset)\\b)\\s*[^;}]+)|(?:radial-gradient\\s*\\()/i;\nconst INLINE_STYLE_DISPLAY_NONE_PATTERN = /(?:^|;)\\s*display\\s*:\\s*none\\b/i;\n\n// `parseFloat(\"0.1\") + parseFloat(\"0.2\") = 0.30000000000000004`. Sub-second\n// authored adjacencies survive parse + add as a value a few ulps above the\n// next clip's start; a strict `>` fires the overlap rule on adjacencies that\n// are exact in the source HTML. 1μs sits ~11 orders of magnitude above the\n// observed drift (worst ~2e-16s across every realistic decimal pair) and 4\n// below one 60fps frame (~16.67ms), so this only ever swallows float slop.\nconst OVERLAP_EPSILON_SECONDS = 1e-6;\n\nfunction readTagTiming(rawTag: string) {\n return readClipTiming({ getAttribute: (name) => readAttr(rawTag, name) });\n}\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\nfunction isCaptionCue(tag: OpenTag): boolean {\n const classTokens = (readAttr(tag.raw, \"class\") || \"\").split(/\\s+/).filter(Boolean);\n const id = readAttr(tag.raw, \"id\");\n return (\n classTokens.some((token) => CAPTION_CUE_TOKEN.test(token)) ||\n Boolean(id && CAPTION_CUE_TOKEN.test(id))\n );\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 readDecodedAttr(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// Id token in a selector's leftmost compound. `#hero .title` → \"hero\";\n// `.a#b > .c` → \"b\"; `.a .b` → null. Companion to leftmostCompoundClasses;\n// splits on the same combinator set so the two agree on where \"leftmost\" ends.\nfunction leftmostCompoundId(selector: string): string | null {\n const leftmost = selector.trim().split(/[\\s>+~]+/)[0] ?? \"\";\n return leftmost.match(/#([\\w-]+)/)?.[1] ?? null;\n}\n\n// Class tokens + ids whose rule body sets a \"heavy overlay\" property\n// (filter:blur, clip-path non-none, or radial-gradient). Only top-level rules\n// are scanned — the flat `[^{}]*` body class naturally skips @keyframes\n// bodies (which contain nested `{...}` stops) and other @-rules, so keyframe\n// selectors like `0%`/`100%` don't leak in.\nfunction collectHeavyOverlayHooks(styles: ExtractedBlock[]): {\n classes: Set<string>;\n ids: Set<string>;\n} {\n const classes = new Set<string>();\n const ids = new Set<string>();\n for (const style of styles) {\n const noComments = style.content.replace(/\\/\\*[\\s\\S]*?\\*\\//g, \"\");\n const ruleWithBody = /([^{}]+)\\{([^{}]*)\\}/g;\n let m: RegExpExecArray | null;\n while ((m = ruleWithBody.exec(noComments)) !== null) {\n const header = (m[1] ?? \"\").trim();\n const body = m[2] ?? \"\";\n if (!header || header.startsWith(\"@\")) continue;\n if (!HEAVY_OVERLAY_CSS_PATTERN.test(body)) continue;\n for (const sel of header.split(\",\")) {\n const trimmed = sel.trim();\n if (!trimmed) continue;\n for (const cls of leftmostCompoundClasses(trimmed)) classes.add(cls);\n const idToken = leftmostCompoundId(trimmed);\n if (idToken) ids.add(idToken);\n }\n }\n }\n return { classes, ids };\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\n/** Declared variable ids from an <html> tag's raw text; null when the JSON is unparseable. */\nfunction collectDeclaredVariableIds(htmlTagRaw: string): Set<string> | null {\n const declared = new Set<string>();\n const raw = readJsonAttr(htmlTagRaw, \"data-composition-variables\");\n if (!raw) return declared;\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n return null;\n }\n if (!Array.isArray(parsed)) return declared;\n for (const entry of parsed) {\n const id = (entry as { id?: unknown } | null)?.id;\n if (typeof id === \"string\") declared.add(id);\n }\n return declared;\n}\n\n/**\n * Union declared variable ids from every element carrying\n * `data-composition-variables`: full-document comps hold it on `<html>`;\n * template/fragment sub-comps hold it on their composition root div. Returns\n * null if any occurrence has unparseable JSON.\n */\nfunction collectAllDeclaredVariableIds(tags: readonly OpenTag[]): Set<string> | null {\n const all = new Set<string>();\n for (const tag of tags) {\n if (!readAttr(tag.raw, \"data-composition-variables\")) continue;\n const ids = collectDeclaredVariableIds(tag.raw);\n if (ids === null) return null;\n for (const id of ids) all.add(id);\n }\n return all;\n}\n\n/**\n * Declared ids to validate `data-var-*` bindings against, or null to skip the\n * file: unparseable declarations (reported elsewhere), or a fragment with no\n * `<html>` and no declarations of its own (its values come from a host's\n * data-variable-values, which this file can't see).\n */\nfunction declaredIdsForBindingCheck(tags: readonly OpenTag[]): Set<string> | null {\n const declared = collectAllDeclaredVariableIds(tags);\n if (declared === null) return null;\n if (declared.size === 0 && !findHtmlTag(tags)) return null;\n return declared;\n}\n\nfunction isInsideInertTemplate(tag: OpenTag, tags: readonly OpenTag[]): boolean {\n return tags.some(\n (candidate) =>\n candidate.name === \"template\" &&\n candidate.closeIndex != null &&\n tag.index > candidate.index &&\n tag.index < candidate.closeIndex,\n );\n}\n\nexport const compositionRules: Array<(ctx: LintContext) => HyperframeLintFinding[]> = [\n // duplicate_composition_id catches meta-tag/root collisions that create duplicate composition entries.\n ({ tags }) => {\n const tagsByCompositionId = new Map<string, string[]>();\n for (const tag of tags) {\n if (isInsideInertTemplate(tag, tags)) continue;\n const compositionId = readDecodedAttr(tag.raw, \"data-composition-id\");\n if (!compositionId || compositionId.trim().length === 0) continue;\n\n const matchingTags = tagsByCompositionId.get(compositionId) ?? [];\n matchingTags.push(tag.raw);\n tagsByCompositionId.set(compositionId, matchingTags);\n }\n\n const findings: HyperframeLintFinding[] = [];\n for (const [compositionId, matchingTags] of tagsByCompositionId) {\n if (matchingTags.length < 2) continue;\n\n findings.push({\n code: \"duplicate_composition_id\",\n severity: \"error\",\n message: `Composition id \"${compositionId}\" is used by ${matchingTags.length} elements. Each data-composition-id value must be unique within a composition file.`,\n fixHint:\n \"Keep data-composition-id on exactly one element, the composition root. Remove it from metadata or duplicate hosts, especially a <meta> tag carrying the same data-composition-id as the root <div>, which causes a silent duplicate-id collision.\",\n snippet: truncateSnippet(matchingTags[0] ?? \"\"),\n });\n }\n\n return findings;\n },\n\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 (isCaptionCue(tag)) continue;\n if (isCompositionRootOrMount(tag.raw)) continue;\n if (!readAttr(tag.raw, \"data-start\")) continue;\n\n const track = readAttr(tag.raw, COMPOSITION_ATTRIBUTES.trackIndex);\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 (readDecodedAttr(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 const timing = readTagTiming(tag.raw);\n if (timing.diagnostics.some(({ code }) => code === \"deprecated-layer\")) {\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 (timing.diagnostics.some(({ code }) => code === \"deprecated-end\")) {\n const elementId = readAttr(tag.raw, \"id\") || undefined;\n const conflicting = timing.diagnostics.some(({ code }) => code === \"conflicting-end\");\n // Two shapes reach here after the false-positive fix (see\n // compositionContract.ts `diagnoseDerivedEnd`): the truly-legacy shape\n // (no data-duration, data-end alone) and the stale-companion shape\n // (data-duration present but paired with a data-end that disagrees).\n // A consistent data-duration + data-end pair — the shape the compiler\n // emits — is silent and never reaches this branch.\n const message = conflicting\n ? `<${tag.name}${elementId ? ` id=\"${elementId}\"` : \"\"}> has data-end that disagrees with data-duration. Remove the stale data-end; the compiler regenerates it from data-duration.`\n : `<${tag.name}${elementId ? ` id=\"${elementId}\"` : \"\"}> uses data-end without data-duration. Use data-duration in source HTML.`;\n findings.push({\n code: \"deprecated_data_end\",\n severity: \"error\",\n message,\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 (readDecodedAttr(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 trackStr = readAttr(tag.raw, COMPOSITION_ATTRIBUTES.trackIndex);\n if (!trackStr) continue;\n const timing = readTagTiming(tag.raw);\n const { start, duration } = timing;\n const track = trackStr;\n\n // Skip non-numeric (relative timing references like \"intro-comp\")\n if (start == null || duration == null) 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 > OVERLAP_EPSILON_SECONDS) {\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 = readDecodedAttr(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 // missing_data_no_timeline\n // The producer polls window.__timelines[id] with a 45-second timeout waiting\n // for GSAP timeline registration. Compositions that never call\n // window.__timelines[id] = tl stall for 45 s every render. Adding\n // data-no-timeline to the root element tells the producer to skip the poll.\n ({ rootTag, rootCompositionId, scripts, rawSource, options }) => {\n if (options.isSubComposition) return [];\n if (!rootCompositionId || !rootTag) return [];\n // readAttr only matches valued attrs (attr=\"...\"); data-no-timeline is\n // typically boolean (no value). Strip quoted attribute values first to\n // avoid matching attr names that appear inside other values\n // (e.g. title=\"add data-no-timeline here\"), then check with a boundary\n // that rejects hyphenated variants (data-no-timeline-start has '-' next,\n // not a word-break char).\n const tagNoValues = rootTag.raw.replace(/\"[^\"]*\"|'[^']*'/g, '\"\"');\n if (/(?:^|\\s)data-no-timeline(?=[\\s>=/]|$)/i.test(tagNoValues)) return [];\n // Can't scan external script files for timeline registration; skip to avoid\n // false positives on compositions that register via a bundled JS file.\n if (/<script\\b[^>]*\\bsrc\\s*=/i.test(rawSource)) return [];\n const registersTimeline = scripts.some((s) => s.content.includes(\"window.__timelines[\"));\n if (registersTimeline) return [];\n return [\n {\n code: \"missing_data_no_timeline\",\n severity: \"warning\",\n message:\n \"This composition has no `window.__timelines` registration but is missing `data-no-timeline`. \" +\n \"The producer polls for timeline registration for up to 45 seconds before timing out, \" +\n \"adding 45 s to every render.\",\n fixHint:\n 'Add `data-no-timeline` to the root element to skip the poll: `<div data-composition-id=\"...\" data-no-timeline ...>`.',\n snippet: truncateSnippet(rootTag.raw),\n },\n ];\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 // unknown_variable_binding\n // data-var-src / data-var-text bind an element to a declared variable id;\n // the runtime silently keeps the authored fallback when the id resolves to\n // nothing, so a typo'd binding is invisible until a customer's override\n // does nothing. Skipped for fragment files (no <html>): their values come\n // from a host's data-variable-values, which this file can't see.\n ({ tags }) => {\n // Declarations live on <html> (full-document comps) OR the composition root\n // div (template/fragment sub-comps); declaredIdsForBindingCheck unions both\n // and returns null for files this rule should skip.\n const declared = declaredIdsForBindingCheck(tags);\n if (!declared) return [];\n const findings: HyperframeLintFinding[] = [];\n for (const tag of tags) {\n for (const attr of [\"data-var-src\", \"data-var-text\"]) {\n const id = readAttr(tag.raw, attr)?.trim();\n if (!id || declared.has(id)) continue;\n findings.push({\n code: \"unknown_variable_binding\",\n severity: \"warning\",\n message: `<${tag.name}> binds ${attr}=\"${id}\" but no variable \"${id}\" is declared in data-composition-variables — the binding will silently keep the authored fallback.`,\n fixHint: `Declare the variable on the composition root (<html>, or the [data-composition-id] root element for a template/fragment comp): data-composition-variables='[{\"id\":\"${id}\",\"type\":\"${attr === \"data-var-src\" ? \"image\" : \"string\"}\",\"label\":\"${id}\",\"default\":\"...\"}]', or fix the binding id.`,\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 ({ tags }) => {\n const htmlTag = findHtmlTag(tags);\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 // html_dir_attribute_breaks_render — valid non-LTR dir values on\n // <html> renders correctly in preview/snapshot but produces a fully\n // blank/black video from render, with no other lint/validate/inspect\n // check catching it (output file size, far smaller than expected, is the\n // only tell). Confirmed independently by two separate reports, both\n // diagnosing the same exact trigger and the same fix: drop dir from\n // <html>, keep lang, and scope `direction: rtl` to individual\n // text-containing elements via CSS instead (text still bidi-shapes\n // correctly). Advisory-only — this does not attempt to fix the render\n // pipeline's own root cause (suspected to be a capture step that clips a\n // fixed top-left-origin screenshot region, which RTL layout can shift the\n // actual content away from), only surfaces the already-confirmed footgun\n // before someone hits it blind.\n ({ tags }) => {\n const htmlTag = findHtmlTag(tags);\n if (!htmlTag) return [];\n const dir = readAttr(htmlTag.raw, \"dir\");\n if (!dir) return [];\n const normalizedDir = dir.toLowerCase();\n if (normalizedDir !== \"rtl\" && normalizedDir !== \"auto\") return [];\n const scopedDirection = normalizedDir === \"auto\" ? 'dir=\"auto\"' : `direction: ${normalizedDir}`;\n return [\n {\n code: \"html_dir_attribute_breaks_render\",\n severity: \"error\",\n message: `<html dir=\"${dir}\"> renders correctly in preview/snapshot but produces a fully blank/black video from render — a confirmed, silent failure.`,\n fixHint: `Remove dir=\"${dir}\" from <html>. Keep lang, and scope ${scopedDirection} to individual text-containing elements instead — text still shapes correctly via the browser's own bidi algorithm.`,\n snippet: truncateSnippet(htmlTag.raw),\n },\n ];\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 // root_composition_missing_duration_source\n //\n // The render engine (packages/engine/src/services/frameCapture.ts) needs a\n // positive window.__hf.duration to know how many frames to capture. GSAP\n // timelines set this automatically. Non-GSAP runtimes (CSS, WAAPI, Lottie)\n // are now auto-inferred by the runtime too (see\n // packages/core/src/runtime/init.ts resolveAdapterDurationFloorSeconds and\n // the adapters' getInferredDurationSeconds) — so data-duration is optional\n // wherever the runtime can work it out on its own.\n //\n // This rule fires for cases where the total render length is not reliably\n // determinable without an explicit data-duration:\n // - No GSAP timeline AND no data-duration AND no non-GSAP animation\n // signal at all (nothing for any adapter to discover — render fails).\n // - Three.js used with no data-duration (no discoverable AnimationClip\n // duration in this codebase's adapter — see adapters/three.ts).\n // - Any infinite CSS animation-iteration-count with no data-duration,\n // EVEN when a finite CSS animation is present alongside it. An unbounded\n // animation makes the intended total length ambiguous — the runtime will\n // infer a finite sibling's length if one exists, but that's a fallback,\n // not a declaration of intent, so we still require data-duration here.\n // (This is intentionally stricter than the runtime's own inference.)\n // Purely finite CSS/WAAPI animations and Lottie are excluded — the runtime\n // infers those unambiguously, so requiring data-duration there would be a\n // false positive against the runtime's own auto-inference. Note lint is\n // advisory by default (see shouldBlockRender) — it only blocks render under\n // --strict/--strict-all — so a strict flag here nudges toward an explicit,\n // guaranteed-correct value without failing renders that would succeed.\n // fallow-ignore-next-line complexity\n ({ rootTag, scripts, styles, tags, options }) => {\n if (options.isSubComposition) return [];\n if (!rootTag) return [];\n // Not every file linted as a \"root\" HTML document is a video composition\n // — e.g. a slideshow demo.html mounts <hyperframes-player src=\"index.html\">\n // with no data-composition-id of its own. Nothing to capture there, so\n // there's no duration contract to enforce.\n if (readDecodedAttr(rootTag.raw, \"data-composition-id\") === null) return [];\n if (readAttr(rootTag.raw, \"data-duration\") !== null) return [];\n\n // Strip comments before scanning for signals — a commented-out\n // `.animate(...)` call or `/* animation: spin 2s infinite; */` must not\n // satisfy the \"has a duration source\" check, or the composition still\n // fails at render with zero duration despite lint passing.\n const allScriptTexts = scripts.map((s) => stripJsComments(s.content));\n const hasGsapTimeline = allScriptTexts.some((t) => /gsap\\.timeline\\s*\\(/.test(t));\n const hasRegisteredTimeline = allScriptTexts.some((t) =>\n WINDOW_TIMELINE_ASSIGN_PATTERN.test(t),\n );\n // A GSAP timeline drives duration via window.__timelines regardless of\n // data-duration — nothing to flag once one is registered.\n if (hasGsapTimeline && hasRegisteredTimeline) return [];\n\n const allCss = styles.map((s) => s.content).join(\"\\n\");\n const allInlineStyles = tags.map((t) => readAttr(t.raw, \"style\") || \"\").join(\"\\n\");\n const combinedCss = `${allCss}\\n${allInlineStyles}`.replace(/\\/\\*[\\s\\S]*?\\*\\//g, \"\");\n\n const usesLottie =\n tags.some((t) => readAttr(t.raw, \"data-lottie-src\") !== null) ||\n allScriptTexts.some((t) => /lottie\\.(loadAnimation)\\b|__hfLottie\\b/.test(t));\n const usesThree = allScriptTexts.some((t) => /\\bTHREE\\./.test(t));\n // `.animate([...], ...)` catches the array-literal keyframes form;\n // `.animate({...}, ...)` catches the object-literal (PropertyIndexedKeyframes)\n // form; `.animate(someVar, ...)` catches keyframes built up in a variable\n // first.\n const usesWaapi = allScriptTexts.some((t) => /\\.animate\\s*\\(\\s*[[{$A-Za-z_]/.test(t));\n const hasCssAnimationName = /\\banimation(?:-name)?\\s*:/.test(combinedCss);\n const hasInfiniteCssAnimation =\n /\\banimation(?:-iteration-count)?\\s*:[^;{}]*(?<![\\w-])infinite(?![\\w-])/.test(combinedCss);\n\n const hasAnyNonGsapSignal = usesLottie || usesThree || usesWaapi || hasCssAnimationName;\n\n if (!hasAnyNonGsapSignal) {\n // No GSAP timeline, no data-duration, and nothing for any adapter to\n // discover — the composition has no source of truth for duration at\n // all. This is the exact shape of the 27K \"zero duration\" render\n // failures this rule exists to catch before render time.\n return [\n {\n code: \"root_composition_missing_duration_source\",\n severity: \"error\",\n message:\n \"Root composition has no data-duration, no GSAP timeline, and no CSS/WAAPI/Lottie/Three.js \" +\n \"animation for the runtime to infer a duration from. The render engine cannot determine \" +\n 'how long to capture and will fail with \"Composition has zero duration\".',\n fixHint:\n 'Add data-duration=\"<seconds>\" to the root element, or add a paused GSAP timeline registered ' +\n \"on window.__timelines.\",\n snippet: truncateSnippet(rootTag.raw),\n },\n ];\n }\n\n if (usesThree) {\n // No AnimationMixer/AnimationClip discovery in the three.js adapter\n // today (see adapters/three.ts) — genuinely not inferable.\n return [\n {\n code: \"root_composition_missing_duration_source\",\n severity: \"error\",\n message:\n \"Root composition uses Three.js with no data-duration. The runtime cannot discover a \" +\n \"Three.js scene's duration automatically (no AnimationClip/AnimationMixer inspection) — \" +\n 'render will fail with \"Composition has zero duration\".',\n fixHint: 'Add data-duration=\"<seconds>\" to the root element.',\n snippet: truncateSnippet(rootTag.raw),\n },\n ];\n }\n\n if (hasInfiniteCssAnimation && !usesLottie && !usesWaapi) {\n // An infinite/unbounded CSS animation makes the intended total length\n // ambiguous, so we require an explicit data-duration even when a finite\n // CSS animation is present alongside it. This is deliberately stricter\n // than the runtime's own inference: the CSS adapter's\n // getInferredDurationSeconds (see adapters/css.ts) returns the longest\n // finite animation end-time when one exists (so a finite sibling would\n // render at that length) and null when every animation is unbounded (so\n // a render with no finite source fails outright). Either way the author\n // hasn't declared how long the video should be — a decorative infinite\n // spinner next to a 3s fade doesn't tell us the clip is meant to be 3s\n // — so we flag it and let them state intent. The message stays honest\n // about both outcomes rather than claiming the render always fails.\n return [\n {\n code: \"root_composition_missing_duration_source\",\n severity: \"error\",\n message:\n \"Root composition uses a CSS animation with animation-iteration-count: infinite and no \" +\n \"data-duration, so the intended total length is ambiguous. If a finite animation is also \" +\n \"present the runtime infers that length; with no finite source the render fails with \" +\n '\"Composition has zero duration\". Declare the intended length explicitly.',\n fixHint:\n 'Add data-duration=\"<seconds>\" to the root element with the intended total length.',\n snippet: truncateSnippet(rootTag.raw),\n },\n ];\n }\n\n // Finite CSS animation, WAAPI .animate(), or Lottie — the runtime infers\n // duration from these at render time (see resolveAdapterDurationFloorSeconds\n // in runtime/init.ts). Not an error; data-duration is optional here.\n return [];\n },\n\n // composition_heavy_overlay_count_high\n // Field signal ts=1784040753 (#hyperframes-cli-feedback): a composition\n // with ~40 heavy overlay DOM elements — `filter:blur`, oversized\n // `radial-gradient`, and `clip-path` animations — captures solid-black for\n // the first ~half of the render, recovering near the end. Reproduces\n // identically via drawElement AND forced --no-browser-gpu screenshot\n // capture AND `snapshot`, so the offender is the capture layer itself, not\n // encoder/mux. Independent of duration (padding the timeline grows the bad\n // zone proportionally, doesn't shift it). Reporter's workaround was to\n // split into per-transition mini compositions + FFmpeg concat.\n //\n // Presence alone matters: opacity:0 and visibility:hidden overlays still\n // contribute to the capture-layer regression, so they're counted-in. The\n // only escape hatch is `display: none` — an element removed from the render\n // tree can't feed the compositor. Warn at 25, well below the observed\n // 40-element repro, to give authors lead time before hitting the bug.\n // fallow-ignore-next-line complexity\n ({ tags, styles, rawSource, options }) => {\n if (isRegistrySourceFile(options.filePath) || isRegistryInstalledFile(rawSource)) return [];\n\n const { classes: heavyClassTokens, ids: heavyIds } = collectHeavyOverlayHooks(styles);\n\n let heavyCount = 0;\n for (const tag of tags) {\n if (HEAVY_OVERLAY_EXEMPT_TAGS.has(tag.name)) continue;\n // Structural containers (root + mounted sub-compositions) aren't overlay\n // content — the heavy children live inside them, and each such child is\n // its own tag entry that we score directly. Counting the container too\n // would double-attribute the risk to one authoring surface.\n if (isCompositionRootOrMount(tag.raw)) continue;\n\n // readJsonAttr lets a `style` value carry the opposite quote character\n // (inline `background: url(\"x.png\")` etc.), which readAttr would truncate.\n const styleAttr = readJsonAttr(tag.raw, \"style\") ?? \"\";\n // display:none removes the element from the render tree, so the capture\n // layer never sees it — the only reliable way to keep an \"unused\" heavy\n // overlay in the source without paying the compositor cost.\n if (styleAttr && INLINE_STYLE_DISPLAY_NONE_PATTERN.test(styleAttr)) continue;\n\n let heavy = false;\n if (styleAttr && HEAVY_OVERLAY_CSS_PATTERN.test(styleAttr)) heavy = true;\n\n if (!heavy && (heavyClassTokens.size > 0 || heavyIds.size > 0)) {\n const classList = (readAttr(tag.raw, \"class\") || \"\").split(/\\s+/).filter(Boolean);\n if (classList.some((cls) => heavyClassTokens.has(cls))) heavy = true;\n if (!heavy) {\n const idValue = readAttr(tag.raw, \"id\");\n if (idValue && heavyIds.has(idValue)) heavy = true;\n }\n }\n\n if (heavy) heavyCount += 1;\n }\n\n if (heavyCount < HEAVY_OVERLAY_ELEMENT_COUNT_WARN) return [];\n\n const splitTarget = options.isSubComposition\n ? \"Split this sub-composition further into per-transition mini-compositions\"\n : \"Split coherent scenes / transitions into separate .html files under compositions/\";\n\n return [\n {\n code: \"composition_heavy_overlay_count_high\",\n severity: \"warning\",\n message:\n `This composition has ${heavyCount} elements carrying \"heavy overlay\" CSS ` +\n `(filter:blur, radial-gradient, or clip-path). Field signal: a composition with ` +\n `~40 such elements — including opacity:0 / visibility:hidden ones — captures ` +\n `solid-black for the first ~half of the render, recovering near the end. Reproduces ` +\n `identically via drawElement, forced screenshot capture, and snapshot, so the capture ` +\n `layer itself is the offender (not encoder/mux). Independent of duration. Presence ` +\n `alone matters; only display:none elements are excluded here.`,\n fixHint:\n `${splitTarget} and concat the pieces (FFmpeg or the runtime's slideshow) so each ` +\n `capture only sees a small subset of heavy overlays at once. Even hidden overlays ` +\n `(opacity:0 / visibility:hidden) contribute — either remove truly unused ones from ` +\n `the source or scope them into their own per-transition sub-composition. If an ` +\n `overlay is genuinely inert for the whole clip, use display:none so it never enters ` +\n `the render tree. Field ref ts=1784040753 (#hyperframes-cli-feedback).`,\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 // Matches any import/from whose specifier contains \"three\" (bare 'three', or a\n // URL/path like .../+esm, esm.sh/three, three.module.js), mirroring the loose\n // /three/i treatment of <script src>.\n const hasThreeModuleImport = texts.some((t) =>\n /\\b(?:import|from)\\s*[^;\\n]*['\"][^'\"]*three[^'\"]*['\"]/i.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 // Vendor-prefixed system-font keywords. Like `system-ui`, the engine resolves\n // these to the OS UI font — they are never installable files and must not be\n // flagged as a missing @font-face, even when a generic fallback follows them\n // (e.g. `-apple-system, system-ui, sans-serif`).\n \"-apple-system\",\n \"blinkmacsystemfont\",\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\n// Normalize one comma-separated font-family entry to a lowercase family name,\n// or null if it carries no resolvable name. `var(--heading)` (or any function\n// token) is an indirection the linter cannot statically resolve, so the literal\n// `var(...)` is not a font name and flagging it is a false positive. Comma-split\n// fallbacks like `var(--x, 'Inter')` also leave a dangling `)` on the fallback\n// part, so skip anything bearing parentheses.\nfunction normalizeUsedFontName(part: string): string | null {\n const name = part\n .trim()\n .replace(/\\s*!important\\s*$/i, \"\")\n .replace(/^['\"]|['\"]$/g, \"\")\n .trim()\n .toLowerCase();\n if (!name || name.includes(\"(\") || name.includes(\")\")) return null;\n return name;\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 for (const part of match[1]!.split(\",\")) {\n const name = normalizeUsedFontName(part);\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) =>\n !declared.has(name) &&\n !FONT_ALIAS_KEYS.has(name) &&\n !googleFonts.has(name.replace(/\\+/g, \" \")),\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. For an OS-bundled \" +\n \"system font (e.g. Hiragino Sans, Microsoft YaHei) that has no downloadable file, \" +\n \"use src: local('Exact Font Name') instead — the declaration alone satisfies this \" +\n \"check without needing a font file.\",\n });\n return findings;\n },\n];\n","import type { LintContext, HyperframeLintFinding } from \"../context\";\nimport type { LintRule } from \"../types\";\nimport { readAttr, readDecodedAttr } 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 = readDecodedAttr(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 { parseHtmlStructure, 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 for (const { name: tagName, raw } of parseHtmlStructure(html).tags) {\n if (!/^(?:video|audio|img|source)$/.test(tagName)) continue;\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, join, relative, resolve } from \"node:path\";\nimport { rewriteAssetPath } from \"@hyperframes/parsers/asset-paths\";\nimport { checkSubCompositionUsability } from \"@hyperframes/parsers/sub-composition-validity\";\nimport { parseHTML } from \"linkedom\";\nimport {\n cleanAssetUrl,\n hasUnresolvedTemplatingToken,\n isRemoteOrInlineUrl,\n isWithinProjectRoot,\n maskNonScannableRanges,\n resolveExistingLocalAsset,\n resolveLocalAssetCandidates,\n} from \"@hyperframes/parsers/asset-resolution\";\nimport { collectLocalVideoCandidates, lintHevcPreviewCodec } from \"./hevcPreviewLint.js\";\nimport { lintHyperframeHtml } from \"./hyperframeLinter.js\";\nimport type { HyperframeLintFinding, HyperframeLintResult } from \"./types.js\";\nimport type { ParsableDocumentLike } from \"@hyperframes/parsers/sub-composition-validity\";\n\n/** Adapts linkedom's `parseHTML` to the `checkSubCompositionUsability` contract. */\nfunction parseSubCompHtml(html: string): ParsableDocumentLike {\n return parseHTML(html).document as unknown as ParsableDocumentLike;\n}\n\ninterface HtmlSource {\n html: string;\n compSrcPath?: string;\n}\n\ninterface CssSource {\n content: string;\n rootRelativePath?: string;\n}\n\n/** Linkedom keeps template contents in a DocumentFragment that is not part of\n * the document query tree. Lint rules must still see shell styles and links\n * inside templates, so walk each template's content recursively without\n * falling back to regex parsing. */\nfunction querySelectorAllIncludingTemplates(root: ParentNode, selector: string): Element[] {\n const matches: Element[] = [...root.querySelectorAll(selector)];\n for (const template of root.querySelectorAll(\"template\")) {\n const content = (template as HTMLTemplateElement).content;\n if (content) matches.push(...querySelectorAllIncludingTemplates(content, selector));\n }\n return matches;\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 MASK_IMAGE_URL_RE =\n /\\b(?:-webkit-)?mask-image\\s*:\\s*[^;{}]*url\\(\\s*(?:\"([^\"]+)\"|'([^']+)'|([^\"')\\s]+))\\s*\\)/gi;\n\nfunction isLocalStylesheetHref(href: string): boolean {\n return !!href && !/^(https?:|data:|blob:|\\/\\/)/i.test(href);\n}\n\nfunction collectLocalStylesheets(\n projectDir: string,\n document: ParentNode,\n compSrcPath?: string,\n): Array<{ href: string; content: string; rootRelativePath: string }> {\n const styles: Array<{ href: string; content: string; rootRelativePath: string }> = [];\n for (const link of querySelectorAllIncludingTemplates(document, \"link\")) {\n const rel = link.getAttribute(\"rel\") ?? \"\";\n if (!rel.split(/\\s+/).some((part) => part.toLowerCase() === \"stylesheet\")) continue;\n const href = link.getAttribute(\"href\") ?? \"\";\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({\n href,\n content: readFileSync(stylesheet.resolved, \"utf-8\"),\n rootRelativePath: stylesheet.rootRelativePath,\n });\n }\n return styles;\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 { document } = parseHTML(html);\n for (const { href, content } of collectLocalStylesheets(projectDir, document, compSrcPath)) {\n styles.push({ href, content });\n }\n return styles;\n}\n\nfunction collectCssSources(projectDir: string, html: string, compSrcPath?: string): CssSource[] {\n const sources: CssSource[] = [];\n const { document } = parseHTML(html);\n\n for (const style of querySelectorAllIncludingTemplates(document, \"style\")) {\n sources.push({ content: style.textContent ?? \"\" });\n }\n\n for (const { content, rootRelativePath } of collectLocalStylesheets(\n projectDir,\n document,\n compSrcPath,\n )) {\n sources.push({ content, rootRelativePath });\n }\n\n for (const element of querySelectorAllIncludingTemplates(document, \"[style]\")) {\n const style = element.getAttribute(\"style\");\n if (!style) continue;\n sources.push({ content: style });\n }\n\n return sources;\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(\n projectDir: string,\n entryFile?: string,\n): Promise<ProjectLintResult> {\n const indexPath = entryFile ? resolve(entryFile) : resolve(projectDir, \"index.html\");\n if (entryFile && !isWithinProjectRoot(projectDir, indexPath)) {\n throw new Error(`Explicit lint entry is outside the project directory: ${entryFile}`);\n }\n const rootFile = relative(resolve(projectDir), indexPath).replace(/\\\\/g, \"/\") || \"index.html\";\n const rootCompSrcPath = rootFile === \"index.html\" ? undefined : rootFile;\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, rootCompSrcPath),\n });\n results.push({ file: rootFile, result: rootResult });\n totalErrors += rootResult.errorCount;\n totalWarnings += rootResult.warningCount;\n totalInfos += rootResult.infoCount;\n\n const allHtmlSources: HtmlSource[] = [{ html: rootHtml, compSrcPath: rootCompSrcPath }];\n const compositionsDir = resolve(projectDir, \"compositions\");\n if (!entryFile && 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()) {\n // Registry components are source snippets, not independently mounted\n // sub-compositions. Linting every installed template here makes an\n // unused component fail the assembled project check.\n if (!rel && entry.name === \"components\") continue;\n out.push(...collectHtmlFiles(join(dir, entry.name), relPath));\n } else if (entry.isFile() && entry.name.endsWith(\".html\") && !entry.name.startsWith(\"._\")) {\n out.push(relPath);\n }\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 // Mountable fragments (figma component imports, registry snippets) are\n // not standalone compositions — composition-root rules don't apply.\n // Anchored to the file's ROOT element so a real composition that merely\n // inlines snippet markup (or mentions the token in text) is still linted.\n if (isSnippetFragment(html)) continue;\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 ...(!entryFile ? lintMultipleRootCompositions(projectDir) : []),\n ...lintDuplicateAudioTracks(allHtmlSources),\n ...lintMissingOrEmptySubComposition(projectDir, rootHtml),\n ...(await lintHevcPreviewCodec(collectLocalVideoCandidates(projectDir, 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 if (hasUnresolvedTemplatingToken(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\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 // Check the RAW value: cleanAssetUrl() splits on ?/# and would chop inside a ${...} token.\n if (hasUnresolvedTemplatingToken(rawSrc)) continue;\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 // Check the RAW value: cleanAssetUrl() splits on ?/# and would chop inside a ${...} token.\n if (hasUnresolvedTemplatingToken(rawUrl)) continue;\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(\n (file) => file.endsWith(\".html\") && !file.startsWith(\"._\"),\n );\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\n/**\n * Error if a `data-composition-src` reference points at a file that is\n * missing, empty, or does not parse to usable HTML. This is the #1 render\n * failure bucket in production telemetry: a scene-authoring step (an AI\n * agent, most commonly) writes the reference before — or without ever —\n * writing valid content into the scene file.\n *\n * The render pre-flight check (`assertSubCompositionsUsable` in\n * `packages/producer/src/services/htmlCompiler.ts`) now aborts the render\n * loudly and immediately when this happens, rather than silently dropping\n * the scene — so catching it here, before the render even starts, means the\n * failure surfaces at lint/validate time with the same message instead of\n * only at render time.\n *\n * Only follows files actually reachable via `data-composition-src` starting\n * from the root composition — mirroring the reachability semantics of\n * `assertSubCompositionsUsable`. A raw filesystem walk of every `.html`\n * under `compositions/` would flag orphaned/unreferenced files that the\n * renderer never visits, producing false-positive lint/validate failures on\n * projects that actually render fine. Lint, render, and the inliner must\n * never disagree about whether a given file would actually render\n * something.\n */\nfunction lintMissingOrEmptySubComposition(\n projectDir: string,\n rootHtml: string,\n): HyperframeLintFinding[] {\n // Dedup by src path — the same reference can appear from nested sub-comps.\n const checked = new Map<string, { srcPath: string; problem: string }>();\n const visited = new Set<string>();\n\n // fallow-ignore-next-line complexity\n const walk = (html: string): void => {\n const compositionSrcRe = /<[^>]*\\bdata-composition-src\\s*=\\s*[\"']([^\"']+)[\"'][^>]*>/gi;\n const scannable = maskNonScannableRanges(html);\n let match: RegExpExecArray | null;\n while ((match = compositionSrcRe.exec(scannable)) !== null) {\n const srcPath = (match[1] ?? \"\").trim();\n if (!srcPath) continue;\n if (/^__[A-Z_]+__$/.test(srcPath)) continue; // template placeholder\n if (hasUnresolvedTemplatingToken(srcPath)) continue; // late-bound templating token\n\n // data-composition-src is always written root-relative (even from a\n // nested sub-composition) — matches the resolution the renderer uses\n // in packages/producer/src/services/htmlCompiler.ts (parseSubCompositions\n // / assertSubCompositionsUsable).\n const filePath = resolve(projectDir, srcPath);\n\n // Circular reference guard — same as assertSubCompositionsUsable.\n // Already-visited files were already checked (or are mid-walk); skip\n // re-checking/re-recursing but still let a later distinct reference to\n // the same broken file surface (checked is keyed by srcPath, not filePath).\n if (visited.has(filePath)) continue;\n visited.add(filePath);\n\n if (!existsSync(filePath)) {\n if (!checked.has(srcPath)) {\n checked.set(srcPath, { srcPath, problem: \"the file does not exist\" });\n }\n continue;\n }\n\n const fileHtml = readFileSync(filePath, \"utf-8\");\n const validity = checkSubCompositionUsability(fileHtml, parseSubCompHtml);\n if (!validity.ok) {\n if (!checked.has(srcPath)) {\n checked.set(srcPath, {\n srcPath,\n problem: validity.detail ?? \"the file is empty or could not be parsed\",\n });\n }\n continue;\n }\n\n // Usable — recurse into it so nested references are validated too,\n // but only because this file is itself reachable from the root.\n walk(fileHtml);\n }\n };\n\n walk(rootHtml);\n\n const findings: HyperframeLintFinding[] = [];\n for (const { srcPath, problem } of checked.values()) {\n findings.push({\n code: \"missing_or_empty_sub_composition\",\n severity: \"error\",\n message: `data-composition-src references \"${srcPath}\", but ${problem}.`,\n fixHint:\n `Fix this before rendering — the render pre-flight rejects unusable sub-compositions. ` +\n `Write valid HTML into \"${srcPath}\" — it needs a <template> or <body> containing an element with ` +\n `data-composition-id, data-width, and data-height. Preview/studio still tolerates and skips the ` +\n \"scene while you author it. If a scene-authoring step is still running, wait for it to finish \" +\n \"before referencing the file, or re-run the step that generates it.\",\n });\n }\n\n return findings;\n}\n\n/** True when the file's first element carries data-hf-snippet — i.e. the file\n * IS a mountable fragment, not a composition that merely contains one. */\nfunction isSnippetFragment(html: string): boolean {\n const firstTag = html.match(/<[a-zA-Z][^>]*>/);\n if (!firstTag) return false;\n return /\\bdata-hf-snippet\\b/.test(firstTag[0]);\n}\n","import { execFile } from \"node:child_process\";\nimport { rewriteAssetPath } from \"@hyperframes/parsers/asset-paths\";\nimport { findFfBinary } from \"@hyperframes/parsers/ff-binaries\";\nimport {\n cleanAssetUrl,\n hasUnresolvedTemplatingToken,\n isRemoteOrInlineUrl,\n maskNonScannableRanges,\n resolveExistingLocalAsset,\n} from \"@hyperframes/parsers/asset-resolution\";\nimport type { HyperframeLintFinding } from \"./types.js\";\n\n/** Structurally compatible with `project.ts`'s (unexported) `HtmlSource` —\n * duplicated as a shape, not imported, to avoid a circular import between\n * this file and `project.ts` (which imports `lintHevcPreviewCodec` below). */\ninterface HtmlSourceLike {\n html: string;\n compSrcPath?: string;\n}\n\nconst PROBE_TIMEOUT_MS = 4000;\n// Bounds concurrent ffprobe child processes for compositions referencing many videos.\nconst PROBE_CONCURRENCY = 8;\n\nfunction execFileAsync(file: string, args: string[]): Promise<string> {\n return new Promise((resolvePromise, reject) => {\n execFile(file, args, { timeout: PROBE_TIMEOUT_MS }, (error, stdout) => {\n if (error) reject(error);\n else resolvePromise(stdout.toString());\n });\n });\n}\n\nfunction hasHevcStream(json: unknown): boolean {\n if (typeof json !== \"object\" || json === null) return false;\n const streams = Reflect.get(json, \"streams\");\n if (!Array.isArray(streams)) return false;\n return streams.some((stream) => {\n if (typeof stream !== \"object\" || stream === null) return false;\n return Reflect.get(stream, \"codec_name\") === \"hevc\";\n });\n}\n\n// Best-effort: any failure (ffprobe missing, times out, non-video file,\n// unparsable output) resolves to \"not HEVC\" rather than throwing. This rule\n// must never fail lint/check just because ffprobe isn't installed.\nasync function probeIsHevc(ffprobePath: string, filePath: string): Promise<boolean> {\n try {\n const stdout = await execFileAsync(ffprobePath, [\n \"-v\",\n \"error\",\n \"-select_streams\",\n \"v:0\",\n \"-show_entries\",\n \"stream=codec_name\",\n \"-of\",\n \"json\",\n filePath,\n ]);\n return hasHevcStream(JSON.parse(stdout));\n } catch {\n return false;\n }\n}\n\n/**\n * Collects local `<video src>` references, resolved to their absolute path\n * and deduped by that path — this is both the candidate set AND the in-run\n * probe cache for `lintHevcPreviewCodec` below: the same file referenced\n * twice only ends up as one map entry, so it's only probed once.\n *\n * Files that don't resolve to an existing local asset are skipped here —\n * `missing_local_asset` already reports those, and hevc_preview_codec never\n * probes a file that doesn't exist.\n */\n// fallow-ignore-next-line complexity\nexport function collectLocalVideoCandidates(\n projectDir: string,\n htmlSources: HtmlSourceLike[],\n): Map<string, string> {\n const candidates = new Map<string, string>();\n const videoSrcRe = /<video\\b[^>]*\\bsrc\\s*=\\s*[\"']([^\"']+)[\"'][^>]*>/gi;\n\n for (const { html, compSrcPath } of htmlSources) {\n const scannable = maskNonScannableRanges(html);\n const re = new RegExp(videoSrcRe.source, videoSrcRe.flags);\n let match: RegExpExecArray | null;\n while ((match = re.exec(scannable)) !== null) {\n const rawSrc = match[1] ?? \"\";\n // Check the RAW value: cleanAssetUrl() splits on ?/# and would chop inside a ${...} token.\n if (hasUnresolvedTemplatingToken(rawSrc)) continue;\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 if (!candidates.has(resolvedAsset.resolved)) candidates.set(resolvedAsset.resolved, src);\n }\n }\n\n return candidates;\n}\n\n/**\n * INFO-only finding: a locally referenced `<video>` file is encoded as\n * HEVC/H.265. The render pipeline pre-decodes video with FFmpeg (never the\n * browser decoder) so rendering is unaffected, but live preview and the\n * embeddable player play the file directly in-browser, where HEVC support\n * varies. Never escalated beyond \"info\" — this must not fail lint or check.\n *\n * `candidates` maps each unique resolved file path to a display src string\n * (already deduped by the caller, so each file is probed exactly once here);\n * files missing from disk are the caller's responsibility to have excluded —\n * `missing_local_asset` covers those and this rule never probes them.\n */\nexport async function lintHevcPreviewCodec(\n candidates: Map<string, string>,\n): Promise<HyperframeLintFinding[]> {\n if (candidates.size === 0) return [];\n\n const ffprobePath = findFfBinary(\"ffprobe\", { configuredMustExist: true });\n if (!ffprobePath) return [];\n\n const entries = [...candidates.entries()];\n const isHevc = new Array<boolean>(entries.length).fill(false);\n let nextIndex = 0;\n const workerCount = Math.min(PROBE_CONCURRENCY, entries.length);\n await Promise.all(\n Array.from({ length: workerCount }, async () => {\n while (nextIndex < entries.length) {\n const index = nextIndex++;\n const entry = entries[index];\n if (!entry) break;\n isHevc[index] = await probeIsHevc(ffprobePath, entry[0]);\n }\n }),\n );\n\n const hevcSrcs = entries.filter((_, i) => isHevc[i]).map(([, src]) => src);\n if (hevcSrcs.length === 0) return [];\n\n const unique = [...new Set(hevcSrcs)];\n return [\n {\n code: \"hevc_preview_codec\",\n severity: \"info\",\n message:\n `Video file(s) use the HEVC/H.265 codec: ${unique.join(\", \")}. ` +\n \"The render pipeline pre-decodes video with FFmpeg and never uses the browser's video decoder, so these render correctly. \" +\n \"Live preview/player playback automatically uses a cached H.264 proxy when the browser cannot decode HEVC. \" +\n \"If playback still fails, verify ffmpeg/ffprobe are installed and auto-proxying is enabled.\",\n fixHint:\n unique.length === 1\n ? `If \"${unique[0]}\" fails to play in preview, run hyperframes doctor and confirm media.autoProxy is not false.`\n : \"If these files fail to play in preview, run hyperframes doctor and confirm media.autoProxy is not false.\",\n },\n ];\n}\n"],"mappings":"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","names":["template","escapeRegExp","match","escapeRegExp","selector","postcss","postcss","rewriteAssetPath","cleanAssetUrl","hasUnresolvedTemplatingToken","isRemoteOrInlineUrl","maskNonScannableRanges","resolveExistingLocalAsset","resolveExistingLocalAsset","rewriteAssetPath","hasUnresolvedTemplatingToken","maskNonScannableRanges","cleanAssetUrl","isRemoteOrInlineUrl"]}
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","../src/hevcPreviewLint.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\nimport { Parser } from \"htmlparser2\";\n\nexport type OpenTag = {\n raw: string;\n name: string;\n attrs: string;\n index: number;\n closeIndex?: number;\n endIndex?: number;\n};\n\nexport type ExtractedBlock = {\n attrs: string;\n content: string;\n raw: string;\n index: number;\n};\n\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;\n// Object-literal registration that assigns at least one `key: value` entry inline,\n// e.g. `window.__timelines = { main: tl }` or `window.__timelines = { \"comp-1\": tl }`.\n// Distinct from the empty-init form (`= {}`) — requires a key followed by `:`.\nexport const TIMELINE_REGISTRY_OBJECT_LITERAL_PATTERN =\n /window\\.__timelines\\s*=\\s*\\{\\s*(?:[\"'][^\"']+[\"']|[A-Za-z_$][\\w$]*)\\s*:/i;\nexport const TIMELINE_REGISTRY_ASSIGN_PATTERN =\n /window\\.__timelines(?:\\[[^\\]]+\\]|\\.[A-Za-z_$][\\w$]*)\\s*=/i;\n// The bracket branch accepts either a quoted string key (`[\"root\"]`) or a\n// computed key (`[spec.id]`, `[id]`) — a bare-identifier-only bracket branch\n// missed `window.__timelines[spec.id] = tl`, a pattern the shipped\n// code-particle-assemble/code-3d-extrude registry blocks actually use,\n// making gsap_timeline_not_registered false-fire on correctly registered\n// timelines. The computed-key alternative is deliberately non-capturing:\n// its text isn't a literal composition id, so callers reading group 1/2\n// (readRegisteredTimelineCompositionId) must keep falling back to null for it.\nexport const WINDOW_TIMELINE_ASSIGN_PATTERN =\n /window\\.__timelines(?:\\[\\s*(?:[\"']([^\"']+)[\"']|[A-Za-z_$][\\w$.]*)\\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\n// The `window.__timelines = { ... }` object-literal body (group 1), captured so its\n// `key: value` entries can be scanned for registered keys.\nconst TIMELINE_REGISTRY_OBJECT_BODY_PATTERN = /window\\.__timelines\\s*=\\s*\\{([\\s\\S]*?)\\}/i;\n// A single object-literal entry whose value is an identifier (real timeline registration),\n// e.g. `main: tl` or `\"comp-1\": tl`. Captures the key in group 1 (quoted) or 2 (bare).\nconst TIMELINE_REGISTRY_OBJECT_ENTRY_PATTERN =\n /(?:[\"']([^\"']+)[\"']|([A-Za-z_$][\\w$]*))\\s*:\\s*[A-Za-z_$][\\w$]*/g;\n\nexport function parseHtmlStructure(source: string): {\n tags: OpenTag[];\n scripts: ExtractedBlock[];\n styles: ExtractedBlock[];\n} {\n const tags: OpenTag[] = [];\n const blocks = { script: [] as ExtractedBlock[], style: [] as ExtractedBlock[] };\n const openTagsByName = new Map<string, OpenTag[]>();\n const openBlocks: Array<{\n name: \"script\" | \"style\";\n attrs: string;\n contentStart: number;\n index: number;\n }> = [];\n const parser: Parser = new Parser(\n {\n onopentag(name) {\n const index = parser.startIndex;\n const raw = source.slice(index, parser.endIndex + 1);\n const attrs = raw.slice(name.length + 1, -1).replace(/\\s*\\/$/, \"\");\n const tag = { raw, name, attrs, index };\n tags.push(tag);\n const sameNameStack = openTagsByName.get(name) ?? [];\n sameNameStack.push(tag);\n openTagsByName.set(name, sameNameStack);\n if (name === \"script\" || name === \"style\") {\n openBlocks.push({ name, attrs, contentStart: parser.endIndex + 1, index });\n }\n },\n onclosetag(name) {\n const tag = openTagsByName.get(name)?.pop();\n if (tag) {\n tag.closeIndex = parser.startIndex;\n tag.endIndex = parser.endIndex + 1;\n }\n if (name !== \"script\" && name !== \"style\") return;\n const block = openBlocks.pop();\n if (!block || block.name !== name) return;\n blocks[name].push({\n attrs: block.attrs,\n content: source.slice(block.contentStart, parser.startIndex),\n raw: source.slice(block.index, parser.endIndex + 1),\n index: block.index,\n });\n },\n },\n { decodeEntities: false, lowerCaseAttributeNames: false, lowerCaseTags: true },\n );\n parser.end(source);\n\n return { tags, scripts: blocks.script, styles: blocks.style };\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(tags: readonly OpenTag[]): OpenTag | null {\n return tags.find((tag) => tag.name === \"html\") ?? null;\n}\n\n// fallow-ignore-next-line complexity\nexport function findRootTag(source: string, parsedTags?: readonly OpenTag[]): OpenTag | null {\n const tags = parsedTags ?? parseHtmlStructure(source).tags;\n const bodyTag = tags.find((tag) => tag.name === \"body\");\n if (\n bodyTag &&\n (readDecodedAttr(bodyTag.raw, \"data-composition-id\") ||\n readAttr(bodyTag.raw, \"data-width\") ||\n readAttr(bodyTag.raw, \"data-height\"))\n ) {\n return bodyTag;\n }\n const bodyStart = bodyTag ? bodyTag.index + bodyTag.raw.length : 0;\n const bodyEnd = bodyTag?.closeIndex ?? source.length;\n const bodyTags = tags.filter((tag) => tag.index >= bodyStart && tag.index < bodyEnd);\n // Set when a leading <svg> defs block is skipped (see below) — extractOpenTags\n // is a flat, nesting-unaware scan, so without this the very next tag it\n // returns is the svg's own nested child (<defs>, <filter>, ...), not the\n // sibling that follows the closed </svg>.\n let skipBefore = -1;\n for (const tag of bodyTags) {\n if (tag.index < skipBefore) continue;\n if ([\"script\", \"style\", \"meta\", \"link\", \"title\"].includes(tag.name)) continue;\n // A leading <svg> block (icon/gradient/filter <defs>, referenced by url(#id)\n // from elsewhere in the document) is shared visual plumbing, not the\n // composition root — two independent reports of this being mistaken for\n // the root, manufacturing root_missing_composition_id/root_missing_dimensions\n // on an otherwise-correct composition. Only skip it when it carries none of\n // the composition markers itself, so an intentionally SVG-rooted composition\n // (data-composition-id/data-width/data-height directly on the <svg>) is\n // still eligible as the root.\n if (\n tag.name === \"svg\" &&\n !readDecodedAttr(tag.raw, \"data-composition-id\") &&\n !readAttr(tag.raw, \"data-width\") &&\n !readAttr(tag.raw, \"data-height\")\n ) {\n // No closing tag found (malformed HTML) — skip everything rather than\n // risk returning one of the svg's own children as the root.\n skipBefore = tag.endIndex ?? Infinity;\n continue;\n }\n return tag;\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 // `(?<![\\w-])` not `\\b`: a plain `\\b` boundary treats the hyphen in a longer\n // attribute as a word break, so reading \"id\" would wrongly match the trailing\n // `id=\"…\"` inside `data-hf-id=\"…\"` (and \"width\" inside `data-width`, etc.).\n // The lookbehind requires the match to start a fresh attribute name.\n const match = tagSource.match(new RegExp(`(?<![\\\\w-])${escaped}\\\\s*=\\\\s*[\"']([^\"']+)[\"']`, \"i\"));\n return match?.[1] || null;\n}\n\n/** Read an HTML attribute using browser-equivalent character-reference decoding. */\nexport function readDecodedAttr(tagSource: string, attr: string): string | null {\n if (!tagSource) return null;\n let value: string | null = null;\n const parser = new Parser(\n {\n onattribute(name, decodedValue) {\n if (value === null && name.toLowerCase() === attr.toLowerCase()) value = decodedValue;\n },\n },\n { decodeEntities: true, lowerCaseAttributeNames: false, lowerCaseTags: true },\n );\n parser.end(tagSource);\n return value;\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 // See readAttr: `(?<![\\w-])` prevents a short name from matching the tail of a\n // longer hyphenated attribute (e.g. \"id\" inside `data-hf-id`).\n const match = tagSource.match(\n new RegExp(`(?<![\\\\w-])${escaped}\\\\s*=\\\\s*(?:\"([^\"]*)\"|'([^']*)')`, \"i\"),\n );\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 = readDecodedAttr(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 const objectBody = TIMELINE_REGISTRY_OBJECT_BODY_PATTERN.exec(source)?.[1];\n if (objectBody) {\n const entryPattern = new RegExp(\n TIMELINE_REGISTRY_OBJECT_ENTRY_PATTERN.source,\n TIMELINE_REGISTRY_OBJECT_ENTRY_PATTERN.flags,\n );\n while ((match = entryPattern.exec(objectBody)) !== null) {\n const key = match[1] ?? match[2];\n if (key) keys.add(key);\n }\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\n// Whether any <style> block in the composition defines caption group/word\n// classes (`.caption-group`, `.caption_word`, etc.) — the signal several\n// caption-specific rules use to skip non-caption compositions entirely.\nexport function hasCaptionStyles(styles: ExtractedBlock[]): boolean {\n return styles.some((s) => /\\.caption[-_]?(?:group|word)/i.test(s.content));\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 parseHtmlStructure,\n findRootTag,\n collectCompositionIds,\n readDecodedAttr,\n stripHtmlComments,\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 initialStructure = parseHtmlStructure(source);\n const templateTags = initialStructure.tags.filter(\n (tag) => tag.name === \"template\" && tag.closeIndex != null,\n );\n let sourceWithoutTemplates = source;\n for (const template of [...templateTags].reverse()) {\n const end = template.endIndex ?? template.index;\n sourceWithoutTemplates =\n sourceWithoutTemplates.slice(0, template.index) +\n \" \".repeat(end - template.index) +\n sourceWithoutTemplates.slice(end);\n }\n // Some sub-composition files are HTML shells whose real root lives inside a\n // <template>. Keep nested templates intact when the visible document already\n // has a composition root; only unwrap when no root exists outside templates.\n const template = templateTags[0];\n let structure = initialStructure;\n if (template && !findRootTag(sourceWithoutTemplates)) {\n source = source.slice(template.index + template.raw.length, template.closeIndex);\n structure = parseHtmlStructure(source);\n }\n\n const tags = structure.tags;\n const styles = [\n ...structure.styles,\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 = structure.scripts;\n const compositionIds = collectCompositionIds(tags);\n const rootTag = findRootTag(source, tags);\n const rootCompositionId = readDecodedAttr(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 selectorParser from \"postcss-selector-parser\";\nimport {\n readAttr,\n readDecodedAttr,\n truncateSnippet,\n stripJsComments,\n extractCompositionIdsFromCss,\n extractTimelineRegistryKeys,\n getInlineScriptSyntaxError,\n TIMELINE_REGISTRY_INIT_PATTERN,\n TIMELINE_REGISTRY_ASSIGN_PATTERN,\n TIMELINE_REGISTRY_OBJECT_LITERAL_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 repeatedDescendantId(selector: string): string | null {\n let repeated: string | null = null;\n\n const requiredPseudoIds = (pseudo: selectorParser.Pseudo): Set<string> => {\n if (![\":is\", \":where\"].includes(pseudo.value.toLowerCase()) || pseudo.nodes.length === 0) {\n return new Set<string>();\n }\n\n const optionIdSets: Set<string>[] = [];\n for (const option of pseudo.nodes) {\n // Only promote ids from a single compound. For selector-list branches with\n // combinators, determining which compound is the subject requires fuller\n // selector semantics; skipping them avoids false positives.\n if (option.nodes.some((node) => node.type === \"combinator\")) return new Set<string>();\n const optionIds = new Set<string>(\n option.nodes.filter((node) => node.type === \"id\").map((node) => node.value),\n );\n optionIdSets.push(optionIds);\n }\n const [firstOptionIds, ...remainingOptionIds] = optionIdSets;\n return new Set<string>(\n [...(firstOptionIds ?? [])].filter((id) =>\n remainingOptionIds.every((optionIds) => optionIds.has(id)),\n ),\n );\n };\n\n try {\n selectorParser((root) => {\n root.each((selectorNode) => {\n const firstCompoundById = new Map<string, number>();\n let compound = 0;\n selectorNode.each((node) => {\n if (repeated) return;\n if (node.type === \"combinator\") {\n compound += 1;\n return;\n }\n const requiredIds =\n node.type === \"id\"\n ? [node.value]\n : node.type === \"pseudo\"\n ? [...requiredPseudoIds(node)]\n : [];\n for (const id of requiredIds) {\n const firstCompound = firstCompoundById.get(id);\n if (firstCompound !== undefined && firstCompound !== compound) {\n repeated = id;\n return;\n }\n firstCompoundById.set(id, compound);\n }\n });\n });\n }).processSync(selector);\n } catch {\n return null;\n }\n return repeated;\n}\n\nfunction resolvedRuleSelectors(rule: postcss.Rule): string[] {\n let ancestor: postcss.AnyNode | undefined = rule.parent;\n while (ancestor && ancestor.type !== \"rule\") ancestor = ancestor.parent;\n if (!ancestor || ancestor.type !== \"rule\") return rule.selectors;\n\n const parentSelectors = resolvedRuleSelectors(ancestor);\n return parentSelectors.flatMap((parentSelector) =>\n rule.selectors.map((childSelector) => {\n const nestingToken = /(^|[\\s>+~,(])&/g;\n if (nestingToken.test(childSelector)) {\n return childSelector.replace(\n nestingToken,\n (_, separator: string) => separator + parentSelector,\n );\n }\n return `${parentSelector} ${childSelector}`;\n }),\n );\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 = readDecodedAttr(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;\nconst VISIBLE_MARKUP_COMMENT_PATTERN = /\\/\\*[\\s\\S]*?\\*\\//g;\nconst VISIBLE_MARKUP_COMMENT_PROTECTED_BLOCK_PATTERN =\n /<(style|script|template|title|noscript|pre|code|textarea|text)\\b[^>]*>[\\s\\S]*?<\\/\\1(?:\\s[^>]*)?>/gi;\n\ninterface SourceRange {\n start: number;\n end: number;\n}\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\nfunction findProtectedVisibleMarkupRanges(source: string): SourceRange[] {\n const ranges: SourceRange[] = [];\n for (const match of source.matchAll(VISIBLE_MARKUP_COMMENT_PROTECTED_BLOCK_PATTERN)) {\n ranges.push({ start: match.index, end: match.index + match[0].length });\n }\n return ranges;\n}\n\nfunction isInsideSourceRange(index: number, ranges: SourceRange[]): boolean {\n return ranges.some((range) => range.start <= index && index < range.end);\n}\n\nfunction isInsideHtmlTag(source: string, index: number): boolean {\n let inTag = false;\n let quote: '\"' | \"'\" | null = null;\n for (let i = 0; i < index; i++) {\n const char = source[i];\n if (!inTag) {\n if (char === \"<\") inTag = true;\n continue;\n }\n if (quote) {\n if (char === quote) quote = null;\n continue;\n }\n if (char === '\"' || char === \"'\") {\n quote = char;\n } else if (char === \">\") {\n inTag = false;\n }\n }\n return inTag;\n}\n\nfunction findVisibleMarkupCommentLeak(source: string): string | null {\n const protectedRanges = findProtectedVisibleMarkupRanges(source);\n for (const match of source.matchAll(VISIBLE_MARKUP_COMMENT_PATTERN)) {\n if (isInsideHtmlTag(source, match.index)) continue;\n if (isInsideSourceRange(match.index, protectedRanges)) continue;\n return match[0];\n }\n return null;\n}\n\nexport const coreRules: Array<(ctx: LintContext) => HyperframeLintFinding[]> = [\n // id_requires_css_escape\n ({ tags }) => {\n const findings: HyperframeLintFinding[] = [];\n for (const tag of tags) {\n const id = readAttr(tag.raw, \"id\");\n if (!id || !/^\\d/.test(id)) continue;\n findings.push({\n code: \"id_requires_css_escape\",\n severity: \"warning\",\n message: `id=\"${id}\" starts with a digit, so the common selector \\`#${id}\\` throws a SyntaxError in querySelector().`,\n elementId: id,\n fixHint:\n \"Rename the id to start with a letter (recommended), or build selectors with `#${CSS.escape(id)}` at runtime.\",\n snippet: truncateSnippet(tag.raw),\n });\n }\n return findings;\n },\n\n // root_missing_composition_id + root_missing_dimensions\n ({ rootTag }) => {\n const findings: HyperframeLintFinding[] = [];\n if (!rootTag || !readDecodedAttr(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 // visible_markup_comment\n ({ source }) => {\n const snippet = findVisibleMarkupCommentLeak(source);\n if (!snippet) return [];\n return [\n {\n code: \"visible_markup_comment\",\n severity: \"error\",\n message:\n \"CSS/JS block comment syntax (`/* ... */`) appears in visible HTML markup. HTML only treats `<!-- ... -->` as comments, so this renders as on-screen text.\",\n fixHint:\n \"Remove the text or convert it to a real HTML comment (`<!-- ... -->`). Keep CSS comments inside `<style>` and JS comments inside `<script>`.\",\n snippet: truncateSnippet(snippet),\n },\n ];\n },\n\n // missing_timeline_registry + timeline_registry_missing_init\n ({ source, rawSource, rootTag, options }) => {\n // Sub-compositions inherit window.__timelines from the host composition\n if (options.isSubComposition || rawSource.trimStart().toLowerCase().startsWith(\"<template\")) {\n return [];\n }\n if (/(?:^|\\s)data-no-timeline(?=[\\s=/]|$)/i.test(rootTag?.attrs || \"\")) return [];\n const findings: HyperframeLintFinding[] = [];\n if (\n !TIMELINE_REGISTRY_INIT_PATTERN.test(source) &&\n !TIMELINE_REGISTRY_ASSIGN_PATTERN.test(source) &&\n !TIMELINE_REGISTRY_OBJECT_LITERAL_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, compositionIds }) => {\n const findings: HyperframeLintFinding[] = [];\n const htmlCompIds = new Set(compositionIds);\n const timelineRegKeys = new Set<string>();\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 // repeated_id_descendant_selector\n ({ styles }) => {\n const findings: HyperframeLintFinding[] = [];\n const reported = new Set<string>();\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 resolvedRuleSelectors(rule)) {\n const repeatedId = repeatedDescendantId(selector);\n if (!repeatedId || reported.has(repeatedId)) continue;\n reported.add(repeatedId);\n findings.push({\n code: \"repeated_id_descendant_selector\",\n severity: \"error\",\n message: `Selector \"${selector}\" requires #${repeatedId} to be nested inside another #${repeatedId}. IDs must be unique, so this selector cannot match a valid composition.`,\n selector,\n fixHint: `Remove the duplicate ancestor: change \\`#${repeatedId} #${repeatedId}\\` to \\`#${repeatedId}\\`.`,\n });\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 (readDecodedAttr(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: readDecodedAttr(tag.raw, \"data-composition-id\")\n ? `[data-composition-id=\"${readDecodedAttr(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 pattern: /gsap\\.utils\\.random\\s*\\(/,\n label: \"gsap.utils.random()\",\n hint: \"Each render worker initializes independently, so random values diverge across chunks. Use a seeded PRNG or fixed values.\",\n },\n {\n // GSAP string form: \"random(...)\" / \"+=random(...)\" — re-rolls at tween init.\n pattern: /[\"'`](?:[+-]=)?random\\(\\s*[-\\d[]/,\n label: '\"random(...)\" tween value',\n hint: \"GSAP random string values re-roll at tween init and each render worker initializes independently. Use fixed values or precompute with a seeded PRNG.\",\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, readDecodedAttr, truncateSnippet, isMediaTag } from \"../utils\";\nimport { validateColorGradingContract } from \"@hyperframes/parsers/color-grading-contract\";\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 // color_grading_* — grading is a structured media-only contract. Unknown\n // keys are ignored by the runtime, so catch them before an agent can report\n // controls that never actually rendered.\n ({ tags }) => {\n const findings: HyperframeLintFinding[] = [];\n for (const tag of tags) {\n const raw = readDecodedAttr(tag.raw, \"data-color-grading\");\n if (raw === null) continue;\n const elementId = readAttr(tag.raw, \"id\") || undefined;\n const report = (code: string, message: string, fixHint: string) => {\n findings.push({\n code,\n severity: \"error\",\n message,\n elementId,\n fixHint,\n snippet: truncateSnippet(tag.raw),\n });\n };\n if (tag.name !== \"video\" && tag.name !== \"img\") {\n report(\n \"color_grading_non_media\",\n `data-color-grading on <${tag.name}> has no effect. The shader runtime only grades real <video> and <img> elements.`,\n \"Move the grading attribute to the real <video> or <img> media element. Do not attach it to a wrapper or CSS background.\",\n );\n continue;\n }\n\n const trimmed = raw.trim();\n if (!trimmed.startsWith(\"{\") && !trimmed.startsWith(\"[\")) continue;\n let parsed: unknown;\n try {\n parsed = JSON.parse(trimmed);\n } catch {\n report(\n \"color_grading_invalid_json\",\n \"data-color-grading contains malformed JSON and will not render.\",\n 'Use valid JSON, for example {\"preset\":\"skin-soft\",\"intensity\":0.6,\"adjust\":{\"highlights\":-0.08}}.',\n );\n continue;\n }\n for (const issue of validateColorGradingContract(parsed)) {\n report(\n \"color_grading_invalid_structure\",\n `data-color-grading ${issue.path} ${issue.message}.`,\n issue.hint ??\n \"Use the documented media-treatment contract and correct or remove the invalid value.\",\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 (readDecodedAttr(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 // 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 const varSrc = readAttr(tag.raw, \"data-var-src\");\n if (varSrc) {\n // Variable-bound media without a fallback still renders when the\n // variable resolves, but a render without a value can't load the\n // media, and the audio pipeline discovers tracks from the AUTHORED\n // src — warn instead of hard-failing the binding pattern.\n findings.push({\n code: \"media_variable_src_no_fallback\",\n severity: \"warning\",\n message: `<${tag.name} id=\"${hasId}\"> relies on data-var-src=\"${varSrc}\" with no fallback src. Renders without a \"${varSrc}\" value cannot load this media, and audio extraction reads the authored src.`,\n elementId: hasId,\n fixHint: `Add a fallback src the composition can render with when the variable is not provided.`,\n snippet: truncateSnippet(tag.raw),\n });\n } else {\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 }\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 // media_crossorigin_breaks_preview — `crossorigin` on <video>/<audio> forces a\n // CORS-checked fetch. The server-side renderer downloads media directly (no CORS),\n // so it always works there; but Studio preview runs in the browser, where a media\n // host that omits Access-Control-Allow-Origin silently fails the load — the media\n // shows BLANK/black in preview while renders look fine, hiding the bug. Plain\n // displayed media never needs crossorigin; it's only required to read pixels/samples\n // back (canvas/WebGL texture, WebAudio createMediaElementSource) AND only when the\n // host is known CORS-enabled.\n ({ tags }) => {\n const findings: HyperframeLintFinding[] = [];\n for (const tag of tags) {\n if (tag.name !== \"video\" && tag.name !== \"audio\") continue;\n if (!hasAttrName(tag.raw, \"crossorigin\")) continue;\n const elementId = readAttr(tag.raw, \"id\") || undefined;\n findings.push({\n code: \"media_crossorigin_breaks_preview\",\n severity: \"error\",\n message: `<${tag.name}${elementId ? ` id=\"${elementId}\"` : \"\"}> has crossorigin, which forces a CORS-checked fetch. If the media host omits Access-Control-Allow-Origin, the load silently fails in Studio preview (media shows BLANK/black) while server-side renders still work — hiding the bug.`,\n elementId,\n fixHint:\n \"Remove the crossorigin attribute unless you read the media back via canvas/WebGL/WebAudio AND the host is known to send CORS headers. Plain displayed media never needs it.\",\n snippet: truncateSnippet(tag.raw),\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 targetIdentity?: string;\n method: string;\n position: number | string;\n properties: Record<string, number | string>;\n // fromTo() exposes its first (\"from\") vars object separately; a layout/reflow prop\n // that appears only here still animates and must be checked.\n fromProperties?: Record<string, number | string>;\n duration?: number;\n ease?: string;\n extras?: Record<string, unknown>;\n resolvedStart?: number;\n /** True for an off-timeline `gsap.set(...)` (applied once at load). */\n global?: boolean;\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}\n\nasync function loadGsapScriptMotionPathFirstUseIndex(): Promise<(script: string) => number | null> {\n const mod = await import(\"@hyperframes/parsers/gsap-parser-acorn\");\n return mod.gsapScriptMotionPathFirstUseIndex;\n}\nimport type { LintContext } from \"../context\";\nimport type { HyperframeLintFinding, LintRule } from \"../types\";\nimport type { OpenTag } from \"../utils\";\nimport {\n readAttr,\n readDecodedAttr,\n truncateSnippet,\n stripJsComments,\n hasCaptionStyles,\n WINDOW_TIMELINE_ASSIGN_PATTERN,\n TIMELINE_REGISTRY_OBJECT_LITERAL_PATTERN,\n} from \"../utils\";\n\n// ── GSAP-specific types ────────────────────────────────────────────────────\n\ntype GsapWindow = {\n targetSelector: string;\n targetIdentity?: string;\n position: number;\n end: number;\n properties: string[];\n propertyValues: Record<string, string | number>;\n fromPropertyValues?: Record<string, string | number>;\n overwriteAuto: boolean;\n immediateRender: boolean;\n method: string;\n /** True for an off-timeline `gsap.set(...)` (applied once at load). */\n global?: boolean;\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// Sentinel the GSAP parser assigns to a tween whose target it cannot statically\n// resolve to a concrete element (a computed variable, a helper call, etc.). It is\n// NOT an identity: two distinct unresolved selectors are not the same element, so\n// overlap analysis must never treat them as one.\nconst UNRESOLVED_TARGET = \"__unresolved__\";\n\n// Parser labels for object-proxy tweens describe their role, not target\n// identity. Two independent proxies can both be labelled `dwell/hold` (or the\n// same driven DOM channel), so equality cannot prove they conflict.\nfunction targetHasNoStableIdentity(selector: string, identity?: string): boolean {\n if (identity) return false;\n return (\n selector === UNRESOLVED_TARGET || selector === \"dwell/hold\" || selector.startsWith(\"proxy → \")\n );\n}\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 const start =\n animation.resolvedStart ??\n (typeof animation.position === \"number\" ? animation.position : null);\n if (start === null) continue;\n const repeat = extrasNumber(animation.extras?.repeat);\n const infiniteRepeat = repeat < 0;\n const cycleCount = infiniteRepeat ? 1 : 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 targetIdentity: animation.targetIdentity,\n position: start,\n end:\n infiniteRepeat && animation.method !== \"set\"\n ? Number.POSITIVE_INFINITY\n : start + effectiveDuration,\n properties: Object.keys(animation.properties),\n propertyValues: animation.properties,\n fromPropertyValues: animation.fromProperties,\n overwriteAuto: unwrapRaw(animation.extras?.overwrite) === \"auto\",\n immediateRender: unwrapRaw(animation.extras?.immediateRender) === \"true\",\n method: animation.method,\n global: animation.global,\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 extractStandaloneHiddenSelectors(script: string): Set<string> {\n const selectors = new Set<string>();\n const source = stripJsComments(script);\n const functionRanges = collectFunctionBodyRanges(source);\n const aliases = new Map<string, string>();\n for (const match of source.matchAll(\n /(?:const|let|var)\\s+([A-Za-z_$][\\w$]*)\\s*=\\s*([\"'`])([^\"'`]+)\\2\\s*;/g,\n )) {\n aliases.set(match[1] ?? \"\", match[3] ?? \"\");\n }\n const pattern = /gsap\\.set\\s*\\(\\s*([^,]+?)\\s*,\\s*\\{([\\s\\S]*?)\\}\\s*\\)/g;\n let match: RegExpExecArray | null;\n while ((match = pattern.exec(source)) !== null) {\n // Skip callback/handler bodies; keep IIFEs (they run at parse time).\n if (indexInsideNonIifeRange(match.index, source, functionRanges)) continue;\n const target = (match[1] ?? \"\").trim();\n const selector = /^([\"'`])([^\"'`]+)\\1$/.exec(target)?.[2] ?? aliases.get(target);\n if (!selector) continue;\n const body = match[2] ?? \"\";\n if (/(?:opacity|autoAlpha)\\s*:\\s*0(?:\\.0+)?\\s*(?:,|$)/.test(body)) {\n selectors.add(selector);\n }\n }\n return selectors;\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 = readDecodedAttr(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\n// A tag's `class` attribute, split into tokens, but only when it carries the\n// `clip` marker class — the common \"is this a clip element?\" filter used by\n// several rules that walk every tag looking for clips.\ntype ClipTagClasses = { classAttr: string; classes: string[] };\n\nfunction getClipTagClasses(tag: OpenTag): ClipTagClasses | null {\n const classAttr = readAttr(tag.raw, \"class\") || \"\";\n const classes = classAttr.split(/\\s+/).filter(Boolean);\n return classes.includes(\"clip\") ? { classAttr, classes } : 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 if (!getClipTagClasses(tag)) 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// Run a global regex over every script's content, yielding each match plus a\n// context-padded snippet around it. Shared by the repeat-count and\n// group-selector-keyframes rules below, which differ only in the pattern,\n// whether comments are stripped first, and the context window size.\nfunction scanScriptsForRegexMatches(\n scripts: LintContext[\"scripts\"],\n pattern: RegExp,\n options: { stripComments: boolean; contextBefore: number; contextAfter: number },\n): Array<{ match: RegExpExecArray; snippet: string }> {\n const hits: Array<{ match: RegExpExecArray; snippet: string }> = [];\n for (const script of scripts) {\n const content = options.stripComments ? stripJsComments(script.content) : script.content;\n const regex = new RegExp(pattern.source, pattern.flags);\n let match: RegExpExecArray | null;\n while ((match = regex.exec(content)) !== null) {\n const contextStart = Math.max(0, match.index - options.contextBefore);\n const contextEnd = Math.min(\n content.length,\n match.index + match[0].length + options.contextAfter,\n );\n hits.push({ match, snippet: content.slice(contextStart, contextEnd) });\n }\n }\n return hits;\n}\n\n// ── Seek-order safety helpers ───────────────────────────────────────────────\n//\n// The renderer distributes frames across workers; cold render workers seek\n// non-linearly straight into their range instead of playing sequentially from 0.\n// Any state that depends on seek ORDER — relative tween bases, callback-measured\n// geometry, per-init random values — renders differently per worker, visible as\n// position jumps or dead animation at chunk boundaries.\n\nconst RELATIVE_TWEEN_VALUE = /^[+-]=/;\n\nfunction isRelativeTweenValue(value: string | number | undefined): boolean {\n return typeof value === \"string\" && RELATIVE_TWEEN_VALUE.test(value.trim());\n}\n\n// DOM reads split by transform sensitivity. Transform-sensitive reads report\n// live animated geometry, so their result depends on the worker's own seek\n// order. Transform-invariant layout reads (intrinsic size, path geometry) give\n// the same answer on every worker as long as layout itself is not animated.\nconst TRANSFORM_SENSITIVE_READ =\n /\\.getBoundingClientRect\\s*\\(|\\bgetComputedStyle\\s*\\(|\\bgsap\\.getProperty\\s*\\(/;\nconst TRANSFORM_INVARIANT_READ =\n /\\.(?:getTotalLength|getBBox)\\s*\\(|\\.(?:offsetWidth|offsetHeight|clientWidth|clientHeight)\\b/;\n// Measurement set for CALLBACK analysis: gsap.getProperty is deliberately\n// excluded — callbacks that read animated values to drive derived output\n// (scramble text, typewriter cursors) are per-frame deterministic and\n// seek-idempotent, so they render the same on every worker.\nconst CALLBACK_MEASUREMENT_PATTERN =\n /\\.(?:getBoundingClientRect|getTotalLength|getBBox)\\s*\\(|\\bgetComputedStyle\\s*\\(|\\.(?:offsetWidth|offsetHeight|clientWidth|clientHeight)\\b/;\n\nfunction indexTagsByToken(tags: OpenTag[]): Map<string, OpenTag[]> {\n const tagsByToken = new Map<string, OpenTag[]>();\n const addToken = (token: string, tag: OpenTag): void => {\n const list = tagsByToken.get(token);\n if (list) list.push(tag);\n else tagsByToken.set(token, [tag]);\n };\n for (const tag of tags) {\n const id = readAttr(tag.raw, \"id\");\n if (id) addToken(`#${id}`, tag);\n for (const cls of readAttr(tag.raw, \"class\")?.split(/\\s+/).filter(Boolean) ?? [])\n addToken(`.${cls}`, tag);\n }\n return tagsByToken;\n}\n\nfunction resolveSelectorTagIndexes(\n selector: string,\n tagsByToken: Map<string, OpenTag[]>,\n): Set<number> {\n const indexes = new Set<number>();\n for (const token of targetedSelectorTokens(selector)) {\n for (const tag of tagsByToken.get(token) ?? []) indexes.add(tag.index);\n }\n return indexes;\n}\n\n// A selector whose comma groups are each a single simple compound (no\n// combinators, no attribute selectors) — the only shape that resolves\n// faithfully through simple #id/.class tokens. Descendant selectors\n// (\".card-a .icon\") and composition-scoped selectors\n// ('[data-composition-id=\"a\"] .dot') would mis-join across elements or\n// compositions, so token-based matching must bail on them.\nfunction selectorResolvesFaithfully(selector: string): boolean {\n return selector.split(\",\").every((group) => {\n const token = group.trim();\n if (!token || token.includes(\"[\")) return false;\n return !/[\\s>+~]/.test(token);\n });\n}\n\n// Two GSAP targets provably hit the same element when their stable identities\n// are equal, or when their (faithfully resolvable) selectors resolve to\n// intersecting element sets — an id selector and a class selector can name the\n// same node. Selectors with combinators or attribute parts are skipped rather\n// than guessed at.\nfunction targetsShareElement(\n a: { selector: string; identity?: string },\n b: { selector: string; identity?: string },\n tagsByToken: Map<string, OpenTag[]>,\n): boolean {\n if (\n !targetHasNoStableIdentity(a.selector, a.identity) &&\n !targetHasNoStableIdentity(b.selector, b.identity) &&\n (a.identity ?? a.selector) === (b.identity ?? b.selector)\n ) {\n return true;\n }\n if (!selectorResolvesFaithfully(a.selector) || !selectorResolvesFaithfully(b.selector)) {\n return false;\n }\n const aTags = resolveSelectorTagIndexes(a.selector, tagsByToken);\n if (aTags.size === 0) return false;\n const bTags = resolveSelectorTagIndexes(b.selector, tagsByToken);\n for (const index of bTags) if (aTags.has(index)) return true;\n return false;\n}\n\n/** Source from the delimiter at `openIndex` to its matching closer, inclusive. */\nfunction matchBalanced(\n source: string,\n openIndex: number,\n open: string,\n close: string,\n): string | null {\n let depth = 0;\n for (let i = openIndex; i < source.length; i++) {\n const ch = source[i];\n if (ch === open) depth++;\n else if (ch === close) {\n depth--;\n if (depth === 0) return source.slice(openIndex, i + 1);\n }\n }\n return null;\n}\n\n/** The nearest object literal `{...}` enclosing `index` (comment-stripped source). */\nfunction enclosingObjectLiteral(source: string, index: number): string | null {\n let depth = 0;\n for (let i = index; i >= 0; i--) {\n const ch = source[i];\n if (ch === \"}\") depth++;\n else if (ch === \"{\") {\n if (depth === 0) return matchBalanced(source, i, \"{\", \"}\");\n depth--;\n }\n }\n return null;\n}\n\nfunction objectLiteralHasTopLevelRelativeValue(objectLiteral: string): boolean {\n let depth = 0;\n let inString: '\"' | \"'\" | \"`\" | null = null;\n for (let i = 0; i < objectLiteral.length; i++) {\n const ch = objectLiteral[i] ?? \"\";\n const prev = objectLiteral[i - 1] ?? \"\";\n if (inString) {\n if (ch === inString && prev !== \"\\\\\") inString = null;\n continue;\n }\n if (ch === '\"' || ch === \"'\" || ch === \"`\") {\n inString = ch;\n if (depth === 1 && /^[+-]=/.test(objectLiteral.slice(i + 1))) return true;\n continue;\n }\n if (ch === \"{\" || ch === \"(\" || ch === \"[\") depth++;\n else if (ch === \"}\" || ch === \")\" || ch === \"]\") depth--;\n }\n return false;\n}\n\nfunction isInsideGsapTweenVars(source: string, index: number, timelineVars: string[]): boolean {\n let depth = 0;\n for (let i = index; i >= 0; i--) {\n const ch = source[i];\n if (ch === \"}\") depth++;\n else if (ch === \"{\") {\n if (depth === 0) {\n const before = source.slice(Math.max(0, i - 240), i).replace(/\\s+/g, \" \");\n const receivers = [\"gsap\", ...timelineVars].map(escapeRegExp).join(\"|\");\n return new RegExp(`(?:${receivers})\\\\.(?:set|to|from|fromTo|timeline)\\\\b[\\\\s\\\\S]*$`).test(\n before,\n );\n }\n depth--;\n }\n }\n return false;\n}\n\n/** An expression starting at `start`, ending at the first `,` / closer at depth 0. */\nfunction sliceExpression(source: string, start: number): string {\n let depth = 0;\n for (let i = start; i < source.length; i++) {\n const ch = source[i] ?? \"\";\n if (\"({[\".includes(ch)) depth++;\n else if (\")}]\".includes(ch)) {\n if (depth === 0) return source.slice(start, i);\n depth--;\n } else if (ch === \",\" && depth === 0) return source.slice(start, i);\n }\n return source.slice(start);\n}\n\ntype ParsedFunctionValue = { firstParam: string | null; body: string };\n\nfunction normalizeFirstParam(raw: string): string | null {\n let param = raw.trim().replace(/=.*$/, \"\").trim();\n param = param.replace(/\\s*:\\s*[\\w$|<>,\\s[\\].]+$/, \"\").trim();\n if (!param || /^[[{]/.test(param)) return null;\n if (!/^[A-Za-z_$][\\w$]*$/.test(param)) return null;\n return param;\n}\n\n/** Parse a function-shaped source string into its first parameter and body. */\nfunction parseFunctionValueSource(code: string): ParsedFunctionValue | null {\n const src = code.trim();\n const match =\n src.match(/^(?:async\\s+)?function\\s*[\\w$]*\\s*\\(([^)]*)\\)/) ??\n src.match(/^(?:async\\s*)?\\(([^)]*)\\)\\s*=>/) ??\n src.match(/^(?:async\\s*)?([A-Za-z_$][\\w$]*)\\s*=>/);\n if (!match) return null;\n const firstParam = normalizeFirstParam((match[1] ?? \"\").split(\",\")[0] ?? \"\");\n return { firstParam, body: src.slice(match[0].length) };\n}\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\n// Methods that exist on numbers: calling them on the (index) first parameter of\n// a GSAP function value is valid and must not be flagged.\nconst NUMBER_METHODS = new Set([\n \"toFixed\",\n \"toString\",\n \"toPrecision\",\n \"toExponential\",\n \"toLocaleString\",\n \"valueOf\",\n]);\n\n// Index is a NUMBER — non-number member access on the first param throws at init.\nfunction firstParamMemberAccessHazard(fn: ParsedFunctionValue): string | null {\n if (!fn.firstParam) return null;\n const pattern = new RegExp(\n `\\\\b${escapeRegExp(fn.firstParam)}\\\\s*\\\\.\\\\s*([A-Za-z_$][\\\\w$]*)`,\n \"g\",\n );\n let match: RegExpExecArray | null;\n while ((match = pattern.exec(fn.body)) !== null) {\n const member = match[1] ?? \"\";\n const after = fn.body.slice(match.index + match[0].length);\n const isCall = /^\\s*\\(/.test(after);\n if (isCall && NUMBER_METHODS.has(member)) continue;\n return member;\n }\n return null;\n}\n\n/** Names of timeline variables (`const tl = gsap.timeline(...)`) in a script. */\nfunction collectTimelineVarNames(source: string): string[] {\n return [...source.matchAll(/(?:const|let|var)\\s+([A-Za-z_$][\\w$]*)\\s*=\\s*gsap\\.timeline\\b/g)]\n .map((m) => m[1] ?? \"\")\n .filter(Boolean);\n}\n\n// Named function bodies in a script (declarations plus `const f = ...` function\n// expressions and arrows). Expression-bodied arrows keep their single line.\nfunction collectNamedFunctionBodies(source: string): Map<string, string> {\n const bodies = new Map<string, string>();\n const declPattern = /(?:^|[^.\\w$])function\\s+([A-Za-z_$][\\w$]*)\\s*\\(/g;\n let match: RegExpExecArray | null;\n while ((match = declPattern.exec(source)) !== null) {\n const braceIndex = source.indexOf(\"{\", declPattern.lastIndex);\n if (braceIndex < 0) continue;\n const body = matchBalanced(source, braceIndex, \"{\", \"}\");\n if (body) bodies.set(match[1] ?? \"\", body);\n }\n const assignPattern =\n /(?:const|let|var)\\s+([A-Za-z_$][\\w$]*)\\s*=\\s*(?:async\\s*)?(?:function\\b[^{]*|\\([^)]*\\)\\s*=>\\s*|[A-Za-z_$][\\w$]*\\s*=>\\s*)/g;\n while ((match = assignPattern.exec(source)) !== null) {\n const bodyStart = assignPattern.lastIndex;\n const body =\n source[bodyStart] === \"{\"\n ? matchBalanced(source, bodyStart, \"{\", \"}\")\n : sliceExpression(source, bodyStart);\n if (body) bodies.set(match[1] ?? \"\", body);\n }\n return bodies;\n}\n\n// Two-hop closure: functions whose body measures the DOM directly, plus\n// functions that call one of those (bounded fixpoint — no deep recursion).\nfunction collectMeasuringFunctionNames(bodies: Map<string, string>): Set<string> {\n const measuring = new Set<string>();\n for (const [name, body] of bodies) {\n if (CALLBACK_MEASUREMENT_PATTERN.test(body)) measuring.add(name);\n }\n for (let pass = 0; pass < 3; pass++) {\n let grew = false;\n for (const [name, body] of bodies) {\n if (measuring.has(name)) continue;\n for (const measured of measuring) {\n if (new RegExp(`\\\\b${escapeRegExp(measured)}\\\\s*\\\\(`).test(body)) {\n measuring.add(name);\n grew = true;\n break;\n }\n }\n }\n if (!grew) break;\n }\n return measuring;\n}\n\nfunction expressionReachesMeasurement(expression: string, measuring: Set<string>): boolean {\n if (CALLBACK_MEASUREMENT_PATTERN.test(expression)) return true;\n for (const name of measuring) {\n if (new RegExp(`\\\\b${escapeRegExp(name)}\\\\b`).test(expression)) return true;\n }\n return false;\n}\n\n// Resolve script-level element variables to the simple selector tokens they can\n// denote: literal getElementById/querySelector lookups, template-literal ids\n// matched against the document's actual ids, and script-assigned class names\n// (createElementNS + setAttribute(\"class\", ...)). Anything else stays unresolved.\nfunction resolveScriptElementTokens(source: string, tags: OpenTag[]): Map<string, Set<string>> {\n const documentIds = tags.map((tag) => readAttr(tag.raw, \"id\")).filter((id) => id !== null);\n const tokensByVar = new Map<string, Set<string>>();\n const add = (name: string, token: string): void => {\n const tokens = tokensByVar.get(name) ?? new Set<string>();\n tokens.add(token);\n tokensByVar.set(name, tokens);\n };\n\n for (const match of source.matchAll(\n /(?:const|let|var)\\s+([A-Za-z_$][\\w$]*)\\s*=\\s*document\\.getElementById\\(\\s*([\"'])([^\"'`]+)\\2/g,\n )) {\n add(match[1] ?? \"\", `#${match[3] ?? \"\"}`);\n }\n for (const match of source.matchAll(\n /(?:const|let|var)\\s+([A-Za-z_$][\\w$]*)\\s*=\\s*document\\.getElementById\\(\\s*`([^`]*)`/g,\n )) {\n const template = match[2] ?? \"\";\n const staticParts = template.split(/\\$\\{[^}]*\\}/);\n // A template with no literal segments (`getElementById(\\`${name}\\`)`) would\n // match EVERY id in the document — treat it as unresolved instead.\n if (staticParts.every((part) => part === \"\")) continue;\n const idPattern = new RegExp(`^${staticParts.map(escapeRegExp).join(\".*\")}$`);\n for (const id of documentIds) {\n if (idPattern.test(id)) add(match[1] ?? \"\", `#${id}`);\n }\n }\n for (const match of source.matchAll(\n /(?:const|let|var)\\s+([A-Za-z_$][\\w$]*)\\s*=\\s*document\\.querySelector\\(\\s*([\"'])([^\"'`]+)\\2/g,\n )) {\n for (const token of targetedSelectorTokens(match[3] ?? \"\")) add(match[1] ?? \"\", token);\n }\n for (const match of source.matchAll(\n /\\b([A-Za-z_$][\\w$]*)\\.setAttribute\\(\\s*([\"'])class\\2\\s*,\\s*([\"'])([^\"'`]*)\\3/g,\n )) {\n for (const cls of (match[4] ?? \"\").split(/\\s+/).filter(Boolean)) add(match[1] ?? \"\", `.${cls}`);\n }\n for (const match of source.matchAll(/\\b([A-Za-z_$][\\w$]*)\\.className\\s*=\\s*([\"'])([^\"'`]*)\\2/g)) {\n for (const cls of (match[3] ?? \"\").split(/\\s+/).filter(Boolean)) add(match[1] ?? \"\", `.${cls}`);\n }\n return tokensByVar;\n}\n\n/** Expand selector tokens to the FULL token sets of the elements they resolve to. */\nfunction elementLevelTokens(\n tokens: Iterable<string>,\n tagsByToken: Map<string, OpenTag[]>,\n): Set<string> {\n const expanded = new Set<string>(tokens);\n for (const token of [...expanded]) {\n for (const tag of tagsByToken.get(token) ?? []) {\n for (const own of tagSimpleSelectors(tag)) expanded.add(own);\n }\n }\n return expanded;\n}\n\nfunction isMultiComponentDasharray(value: string): boolean {\n const normalized = value.replace(/!important\\s*$/i, \"\").trim();\n if (!normalized || /^none$/i.test(normalized)) return false;\n return normalized.split(/[\\s,]+/).filter(Boolean).length >= 2;\n}\n\n// A GSAP strokeDasharray value that is a static string/template with >= 2\n// components is the explicit \"L L\" fix form — safe. Variables and numbers are\n// the common single-component draw-on form (the pathLength trick).\nfunction gsapDasharrayValueLooksMultiComponent(valueSource: string): boolean {\n const literal = valueSource.trim().match(/^([\"'`])([\\s\\S]*)\\1$/)?.[2];\n if (literal === undefined) return false;\n return isMultiComponentDasharray(literal.replace(/\\$\\{[^}]*\\}/g, \"0\"));\n}\n\n/** Byte ranges of every function body (declarations, expressions, block arrows). */\nfunction collectFunctionBodyRanges(source: string): Array<{ start: number; end: number }> {\n const ranges: Array<{ start: number; end: number }> = [];\n const openerPatterns = [/\\bfunction\\b[^{;()]*\\([^)]*\\)\\s*\\{/g, /=>\\s*\\{/g];\n for (const pattern of openerPatterns) {\n let match: RegExpExecArray | null;\n while ((match = pattern.exec(source)) !== null) {\n const braceIndex = match.index + match[0].length - 1;\n const body = matchBalanced(source, braceIndex, \"{\", \"}\");\n if (body) ranges.push({ start: braceIndex, end: braceIndex + body.length });\n }\n }\n return ranges;\n}\n\nfunction indexInsideAnyRange(\n index: number,\n ranges: Array<{ start: number; end: number }>,\n): boolean {\n return ranges.some((range) => index > range.start && index < range.end);\n}\n\nfunction isIifeBody(source: string, range: { start: number; end: number }): boolean {\n let j = range.end;\n while (j < source.length && /\\s/.test(source[j]!)) j++;\n if (source[j] !== \")\") return false;\n j++;\n while (j < source.length && /\\s/.test(source[j]!)) j++;\n return source[j] === \"(\" || source.startsWith(\".call\", j) || source.startsWith(\".apply\", j);\n}\n\nfunction indexInsideNonIifeRange(\n index: number,\n source: string,\n ranges: Array<{ start: number; end: number }>,\n): boolean {\n return ranges.some(\n (range) => index > range.start && index < range.end && !isIifeBody(source, range),\n );\n}\n\n// Simple selectors whose authored CSS (style blocks or inline styles) sets\n// opacity to EXACTLY zero. The declaration regex is boundary-anchored so\n// `opacity: 0.98` never matches; it ends at `;` or end of input, which also\n// catches a final declaration without a trailing semicolon.\nfunction collectCssOpacityZeroSelectors(\n styles: LintContext[\"styles\"],\n tags: OpenTag[],\n): Set<string> {\n const selectors = new Set<string>();\n const opacityExactlyZero = /opacity\\s*:\\s*0(?:\\.0+)?\\s*(?:;|$)/;\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 && opacityExactlyZero.test(body)) {\n selectors.add((selector ?? \"\").trim());\n }\n }\n }\n\n for (const tag of tags) {\n const inlineStyle = readAttr(tag.raw, \"style\");\n if (!inlineStyle || !opacityExactlyZero.test(inlineStyle)) continue;\n const id = readAttr(tag.raw, \"id\");\n if (id) selectors.add(`#${id}`);\n for (const cls of readAttr(tag.raw, \"class\")?.split(/\\s+/).filter(Boolean) ?? []) {\n selectors.add(`.${cls}`);\n }\n }\n return selectors;\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 clipTag = getClipTagClasses(tag);\n if (!clipTag) continue;\n const id = readAttr(tag.raw, \"id\");\n const info: ClipInfo = {\n tag: tag.name,\n id: id || \"\",\n classes: clipTag.classAttr,\n };\n if (id) clipIds.set(`#${id}`, info);\n for (const cls of clipTag.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 // Unresolved targets are unknown elements: two of them are not provably\n // the same element, so an overlap between them cannot be asserted.\n if (targetHasNoStableIdentity(left.targetSelector, left.targetIdentity)) 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 const leftIdentity = left.targetIdentity ?? left.targetSelector;\n const rightIdentity = right.targetIdentity ?? right.targetSelector;\n if (leftIdentity !== rightIdentity) 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 // Unresolved targets are unknown elements: you cannot assert a missing\n // hard kill on one, and a `tl.set(\"__unresolved__\", ...)` hint is meaningless.\n if (win.targetSelector === UNRESOLVED_TARGET) continue;\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 // A tl.set hard kill on the exiting selector itself is the fix — unless\n // that selector IS a clip element, in which case gsap_animates_clip_element\n // (below) errors on that exact tl.set: the framework already owns\n // visibility/display on clip elements. Point at the inner-wrapper\n // pattern instead so the two rules' advice doesn't contradict.\n const exitClipInfo =\n clipIds.get(win.targetSelector) || clipClasses.get(win.targetSelector);\n const fixHint = exitClipInfo\n ? `\"${win.targetSelector}\" is a clip element — the framework already manages its visibility. ` +\n \"Wrap the scene's content in an inner non-clip <div>, move the exit tween and the hard kill \" +\n `(\\`tl.set(\"<inner-selector>\", ${hiddenStateLiteral(win.propertyValues)}, ${boundary.toFixed(2)})\\`) onto that wrapper instead.`\n : `Add \\`tl.set(\"${win.targetSelector}\", ${hiddenStateLiteral(win.propertyValues)}, ${boundary.toFixed(2)})\\` ` +\n \"after the exit tween.\";\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 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 // gsap_timeline_set_initial_hide warns on `tl.set(..., 0)` initial hides\n // (a zero-duration set at 0 does not render at exactly t=0), so this hint\n // must not recommend that pattern — advise authored CSS or an immediate\n // gsap.set() instead, keeping the two rules' advice consistent.\n fixHint:\n `Add \\`opacity: 0\\` to \"${selector}\" in CSS/inline styles, or add an immediate ` +\n `\\`gsap.set(\"${selector}\", { opacity: 0 })\\` (outside the timeline) 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 // missing_gsap_plugin\n async ({ scripts, rawSource, options }) => {\n const canInheritPluginFromHost =\n options.isSubComposition || rawSource.trimStart().toLowerCase().startsWith(\"<template\");\n if (canInheritPluginFromHost) return [];\n\n const gsapScriptMotionPathFirstUseIndex = await loadGsapScriptMotionPathFirstUseIndex();\n const motionPathUseIndices = scripts.map((script) =>\n gsapScriptMotionPathFirstUseIndex(script.content),\n );\n const firstMotionPathScriptIndex = motionPathUseIndices.findIndex((index) => index !== null);\n const firstMotionPathUseIndex = motionPathUseIndices[firstMotionPathScriptIndex] ?? null;\n const firstUseScript = scripts[firstMotionPathScriptIndex];\n const executionMode = (attrs: string): \"blocking\" | \"defer\" | \"module\" | \"async\" => {\n const tag = `<script ${attrs}>`;\n const isModule = (readDecodedAttr(tag, \"type\") ?? \"\").toLowerCase() === \"module\";\n const hasSrc = readDecodedAttr(tag, \"src\") !== null;\n const hasAsync = readDecodedAttr(tag, \"async\") !== null;\n const hasDefer = readDecodedAttr(tag, \"defer\") !== null;\n if ((isModule || hasSrc) && hasAsync) return \"async\";\n if (isModule) return \"module\";\n if (hasSrc && hasDefer) return \"defer\";\n return \"blocking\";\n };\n const firstUseMode = firstUseScript ? executionMode(firstUseScript.attrs) : \"blocking\";\n const hasMotionPathPlugin = scripts\n .slice(0, firstMotionPathScriptIndex + 1)\n .some((script, candidateIndex) => {\n const candidateMode = executionMode(script.attrs);\n const sameScript = candidateIndex === firstMotionPathScriptIndex;\n const candidateIsPostParse = candidateMode === \"defer\" || candidateMode === \"module\";\n const firstUseIsPostParse = firstUseMode === \"defer\" || firstUseMode === \"module\";\n const executesBeforeFirstUse =\n sameScript ||\n candidateMode === \"blocking\" ||\n (candidateIsPostParse && firstUseIsPostParse);\n if (!executesBeforeFirstUse || (!sameScript && candidateMode === \"async\")) return false;\n const src = readAttr(`<script ${script.attrs}>`, \"src\") ?? \"\";\n const uncommented = stripJsComments(script.content);\n const hasStaticImport =\n /\\bimport\\s+(?:[\\s\\S]*?\\sfrom\\s*)?[\"'][^\"']*\\bMotionPathPlugin\\b[^\"']*[\"']/.test(\n uncommented,\n ) ||\n /\\bimport\\s+(?:[\\w$]+\\s*,\\s*)?\\{[^}]*\\bMotionPathPlugin\\b[^}]*\\}\\s+from\\s*[\"'][^\"']+[\"']/.test(\n uncommented,\n ) ||\n /\\bimport\\s+MotionPathPlugin\\s+from\\s*[\"'][^\"']+[\"']/.test(uncommented);\n const inlinedMarkerIndex = script.content.search(/\\/\\*\\s*inlined:.*MotionPathPlugin/i);\n const definitionIndex = uncommented.search(\n /\\b(?:const|let|var|class|function)\\s+MotionPathPlugin\\b/,\n );\n if (sameScript) {\n if (hasStaticImport) return true;\n if (firstMotionPathUseIndex === null) return false;\n return (\n (inlinedMarkerIndex >= 0 && inlinedMarkerIndex < firstMotionPathUseIndex) ||\n (definitionIndex >= 0 && definitionIndex < firstMotionPathUseIndex)\n );\n }\n return (\n /MotionPathPlugin/i.test(src) ||\n hasStaticImport ||\n inlinedMarkerIndex >= 0 ||\n definitionIndex >= 0\n );\n });\n if (firstMotionPathScriptIndex < 0 || hasMotionPathPlugin) return [];\n return [\n {\n code: \"missing_gsap_plugin\",\n severity: \"error\",\n message:\n \"A GSAP tween uses motionPath, but MotionPathPlugin is not loaded. Core GSAP ignores this plugin-specific property, so the intended motion will not render.\",\n fixHint:\n \"Load MotionPathPlugin before the animation script and register it with gsap.registerPlugin(MotionPathPlugin), or replace motionPath with core GSAP x/y tweens.\",\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 if (!hasCaptionStyles(styles)) 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, rootTag }) => {\n const findings: HyperframeLintFinding[] = [];\n const declaredDuration = Number.parseFloat(\n rootTag ? (readAttr(rootTag.raw, \"data-duration\") ?? \"\") : \"\",\n );\n const hasFiniteCompositionWindow = Number.isFinite(declaredDuration) && declaredDuration > 0;\n // Match repeat: -1 in GSAP tweens or timeline configs\n const pattern = /repeat\\s*:\\s*-1(?!\\d)/g;\n for (const { snippet } of scanScriptsForRegexMatches(scripts, pattern, {\n stripComments: true,\n contextBefore: 60,\n contextAfter: 60,\n })) {\n findings.push({\n code: \"gsap_infinite_repeat\",\n severity: hasFiniteCompositionWindow ? \"warning\" : \"error\",\n message: hasFiniteCompositionWindow\n ? `GSAP tween uses \\`repeat: -1\\` (infinite), but the composition declares a finite ${declaredDuration}s window. ` +\n \"HyperFrames clips deterministic seeking and export to that explicit duration.\"\n : \"GSAP tween uses `repeat: -1` (infinite) without a finite composition `data-duration`. \" +\n \"The timeline can report an unbounded duration and make render planning fail.\",\n fixHint: hasFiniteCompositionWindow\n ? \"Keep the explicit finite composition `data-duration`. Use a finite repeat count only when the loop itself must end before the composition does.\"\n : \"Add a finite composition `data-duration`, or replace `repeat: -1` with \" +\n \"`repeat: Math.max(0, Math.floor(totalDuration / singleCycleDuration) - 1)`.\",\n snippet: truncateSnippet(snippet),\n });\n }\n return findings;\n },\n\n // gsap_repeat_ceil_overshoot\n ({ scripts }) => {\n const findings: HyperframeLintFinding[] = [];\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 for (const { snippet } of scanScriptsForRegexMatches(scripts, pattern, {\n stripComments: false,\n contextBefore: 40,\n contextAfter: 40,\n })) {\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.max(0, 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 return findings;\n },\n\n // gsap_repeat_floor_unclamped\n ({ scripts }) => {\n const findings: HyperframeLintFinding[] = [];\n // A direct floor-minus-one expression becomes GSAP's infinite -1 sentinel when\n // the visible duration is shorter than one full cycle. Math.max-wrapped forms\n // intentionally do not match because `repeat:` is followed by Math.max, not Math.floor.\n const pattern = /repeat\\s*:\\s*Math\\.floor\\s*\\([^)]+\\)\\s*-\\s*1/g;\n for (const { snippet } of scanScriptsForRegexMatches(scripts, pattern, {\n stripComments: false,\n contextBefore: 40,\n contextAfter: 40,\n })) {\n findings.push({\n code: \"gsap_repeat_floor_unclamped\",\n severity: \"warning\",\n message:\n \"GSAP repeat calculation can evaluate to -1 when the composition is shorter than one cycle, \" +\n \"which GSAP interprets as an infinite repeat.\",\n fixHint:\n \"Clamp the finite repeat count at zero: \" +\n \"`repeat: Math.max(0, Math.floor(totalDuration / cycleDuration) - 1)`.\",\n snippet: truncateSnippet(snippet),\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 // A tl.set on \"#id\" is only safe advice when the scene element isn't\n // itself a clip — otherwise gsap_animates_clip_element errors on that\n // exact tl.set, since the framework already owns visibility/display on\n // clip elements. Point at the inner-wrapper pattern instead.\n const classes = (readAttr(tag.raw, \"class\") || \"\").split(/\\s+/).filter(Boolean);\n const isClip = classes.includes(\"clip\");\n const fixHint = isClip\n ? `\"#${id}\" is a clip element — the framework already manages its visibility. ` +\n \"Wrap the scene's content in an inner non-clip <div>, move the exit tween and the hard kill \" +\n '(`tl.set(\"<inner-selector>\", { visibility: \"hidden\" }, <exit-end-time>)`) onto that wrapper instead.'\n : `Add \\`tl.set(\"#${id}\", { visibility: \"hidden\" }, <exit-end-time>)\\` after the scene's exit tweens.`;\n\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,\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 =\n WINDOW_TIMELINE_ASSIGN_PATTERN.test(content) ||\n TIMELINE_REGISTRY_OBJECT_LITERAL_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 // CSS/GSAP-hidden reveal safety. A fromTo() whose from-vars make an element\n // visible but whose destination omits opacity works during sequential seeks,\n // yet cold render workers restore the authored hidden state and encode it\n // permanently invisible.\n // fallow-ignore-next-line complexity\n async ({ styles, scripts, tags }) => {\n const findings: HyperframeLintFinding[] = [];\n const cssOpacityZeroSelectors = collectCssOpacityZeroSelectors(styles, tags);\n\n for (const script of scripts) {\n if (!/gsap\\.timeline/.test(script.content)) continue;\n const windows = await cachedExtractGsapWindows(script.content);\n const hiddenSelectors = new Set([\n ...cssOpacityZeroSelectors,\n ...extractStandaloneHiddenSelectors(script.content),\n ]);\n\n for (const win of windows) {\n const sel = win.targetSelector;\n const cssKey = sel.startsWith(\"#\") || sel.startsWith(\".\") ? sel : `#${sel}`;\n if (!hiddenSelectors.has(cssKey)) continue;\n\n if (\n win.method === \"fromTo\" &&\n win.fromPropertyValues &&\n isVisibleGsapState(win.fromPropertyValues) &&\n !win.properties.some((property) => property === \"opacity\" || property === \"autoAlpha\")\n ) {\n findings.push({\n code: \"gsap_cold_seek_hidden_fromto_missing_reveal\",\n severity: \"error\",\n message:\n `\"${sel}\" starts hidden, but its gsap.fromTo() makes it visible only in the from-vars ` +\n \"and omits opacity/autoAlpha from the destination. Cold render workers restore the hidden authored state, so the encoded element can stay invisible even when sequential snapshots look correct.\",\n selector: sel,\n fixHint: `Add \\`opacity: 1\\` (or \\`autoAlpha: 1\\`) to the destination vars for \"${sel}\" so every seek path establishes the visible end state explicitly.`,\n snippet: truncateSnippet(win.raw),\n });\n continue;\n }\n\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\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_non_transform_motion — animating layout props (left/top/right/bottom/margin*)\n // or using roundProps snaps motion to integer device pixels. On the seek-by-frame\n // capture engine this looks smooth at high per-frame deltas (fast tweens) but visibly\n // stutters at low deltas (slow tweens / ease-out tails): sub-pixel movement rounds to\n // the same pixel for several frames, then jumps a whole pixel. Transforms (x/y/scale)\n // interpolate sub-pixel and stay smooth.\n //\n // EXEMPTION: elements rasterized via the html-in-canvas API — those under a\n // `<canvas layoutsubtree>` ancestor (e.g. the liquid-glass blocks) — are NOT laid out\n // by the browser compositor. The canvas lib reads getComputedStyle().left/top (a\n // sub-pixel value) and draws the element to a bitmap, so animating a layout prop on\n // them does not integer-snap and does not stutter. We resolve each tween's target to\n // its element(s) and skip the finding only when EVERY target is html-in-canvas; a\n // grouped tween that also touches a plain-DOM element (which does stutter) still fires.\n //\n // No suppression by design: there is intentionally no per-line/per-file opt-out (unlike\n // eslint-disable). The stance is fix-the-motion, not silence-the-rule — a plain-DOM\n // layout-prop animation always has a faithful transform equivalent (per-glyph x for\n // spacing, scale for size, x/y for position). An author who has consciously accepted a\n // stutter still has no flag to flip; that is deliberate, not a missing feature.\n async ({ scripts, tags, source }) => {\n const findings: HyperframeLintFinding[] = [];\n\n // Byte-ranges of every <canvas layoutsubtree>. An element whose open-tag index falls\n // inside one of these ranges is html-in-canvas composited.\n const layoutSubtreeRanges = tags\n .filter((t) => t.name.toLowerCase() === \"canvas\" && /\\blayoutsubtree\\b/i.test(t.raw))\n .map((t) => ({ start: t.index, end: findTagEnd(source, t) }));\n const isHtmlInCanvas = (tag: OpenTag): boolean =>\n layoutSubtreeRanges.some((r) => tag.index > r.start && tag.index < r.end);\n\n // Resolve a simple #id / .class token to the element tag(s) it matches.\n const tagsByToken = indexTagsByToken(tags);\n\n // True only when the selector resolves to at least one element AND every resolved\n // element is html-in-canvas. Unresolvable selectors (no match) are NOT exempt — we\n // stay conservative and let the finding fire rather than risk a false negative.\n const allTargetsHtmlInCanvas = (selector: string): boolean => {\n if (layoutSubtreeRanges.length === 0) return false;\n const matched = [...targetedSelectorTokens(selector)].flatMap(\n (token) => tagsByToken.get(token) ?? [],\n );\n return matched.length > 0 && matched.every(isHtmlInCanvas);\n };\n // Positional layout props → each maps to its transform replacement axis (x/y).\n const LAYOUT_FIX: Record<string, string[]> = {\n left: [\"x\"],\n right: [\"x\"],\n top: [\"y\"],\n bottom: [\"y\"],\n margin: [\"x\", \"y\"],\n marginLeft: [\"x\"],\n marginRight: [\"x\"],\n marginTop: [\"y\"],\n marginBottom: [\"y\"],\n };\n // Text-reflow props: animating them reflows text and snaps glyph positions to the\n // pixel grid, stuttering on slow motion exactly like positional props. They have no\n // transform replacement (the fix is to not animate them — settle via scale or hold the\n // value), and the snap happens during browser layout, UPSTREAM of any canvas raster, so\n // they are never html-in-canvas-exempt. (width/height are deliberately omitted: they\n // have legitimate animated uses — progress bars, reveals — and would over-report.)\n const REFLOW_PROPS = [\"letterSpacing\", \"wordSpacing\", \"fontSize\"];\n // Resolve the parser once, above the loop (the other async rules in this file do the\n // same); the dynamic-import cache makes per-iteration calls equivalent, but hoisting\n // keeps the placement from reading as load-bearing.\n const parseGsapScript = await loadParseGsapScript();\n for (const script of scripts) {\n if (!/gsap\\.timeline/.test(script.content)) continue;\n\n // Two sources: timeline-rooted tweens (tl.to/from/fromTo) and standalone\n // gsap.to/from/fromTo calls the acorn parser ignores.\n //\n // Timeline tweens come straight from the acorn parser's animation list — NOT\n // cachedExtractGsapWindows, which drops every tween with a non-numeric timeline\n // position (a string label or `+=`/`-=` offset, e.g. `tl.to(\"#x\",{left:9},\"hold6\")`).\n // Position is irrelevant to whether a tween animates a layout prop, so dropping\n // those would let real stutter-prone tweens escape. The parser also gives real AST\n // keys, so a nested `{}` value (an onComplete body, modifiers) and a layout-prop\n // name appearing inside a string value can't be misread — both hazards of a raw scan.\n const parsed = parseGsapScript(script.content);\n const calls: GsapTransformCall[] = [\n ...parsed.animations.map((anim) => ({\n method: anim.method,\n selector: anim.targetSelector,\n // Union the from-vars: a fromTo() can animate a layout/reflow prop that appears\n // only in its first (\"from\") object, which is just as stutter-prone as the to-vars.\n properties: [\n ...new Set([\n ...Object.keys(anim.properties),\n ...Object.keys(anim.fromProperties ?? {}),\n ]),\n ],\n raw: synthesizeWindowRaw(parsed.timelineVar, anim),\n })),\n ...extractStandaloneGsapTransformCalls(stripJsComments(script.content)),\n ];\n\n for (const call of calls) {\n // set() is instantaneous — it never animates, so it cannot stutter. A set() that\n // seats an integer-snapped layout position (e.g. tl.set(\"#x\",{left:100})) before a\n // later transform tween is a single from-state frame, not motion; intentionally skipped.\n if (call.method === \"set\") continue;\n // Object.hasOwn, not `in`: a tween property named `toString`/`constructor` would\n // match the prototype chain and resolve LAYOUT_FIX[p] to an inherited function.\n let layoutProps = call.properties.filter((p) => Object.hasOwn(LAYOUT_FIX, p));\n const reflowProps = call.properties.filter((p) => REFLOW_PROPS.includes(p));\n const usesRoundProps = call.properties.includes(\"roundProps\");\n // Only positional props are html-in-canvas-exempt: the canvas positions the draw\n // from sub-pixel computed left/top. Reflow props (glyph layout) and roundProps\n // (value rounding) snap upstream of the raster, so they always fire.\n if (layoutProps.length > 0 && allTargetsHtmlInCanvas(call.selector)) layoutProps = [];\n if (layoutProps.length === 0 && reflowProps.length === 0 && !usesRoundProps) continue;\n\n const flagged = [...layoutProps, ...reflowProps, ...(usesRoundProps ? [\"roundProps\"] : [])];\n const message =\n `GSAP tween on \"${call.selector}\" uses motion that snaps to integer device pixels: ` +\n `${flagged.join(\", \")}. Layout and text-reflow properties snap during browser layout; ` +\n \"roundProps rounds the tween value. Slow motion or an ease-out tail then stutters under \" +\n \"the seek-by-frame capture engine — animate transforms (x/y/scale/opacity) instead.\";\n\n const fixes: string[] = [];\n if (layoutProps.length > 0) {\n const tokens = [...new Set(layoutProps.flatMap((p) => LAYOUT_FIX[p] ?? []))];\n fixes.push(\n `replace ${layoutProps.join(\"/\")} with the transform equivalent (${tokens.join(\", \")}) — ` +\n `e.g. tl.fromTo(\"${call.selector}\", { x: -1300 }, { x: 0, ...yourAnimation })`,\n );\n }\n if (reflowProps.length > 0) {\n // Faithful fix differs by property: fontSize maps to scale (same visual), but\n // letterSpacing/wordSpacing do NOT — uniform scale resizes glyphs, it does not\n // change the gaps between them. The smooth equivalent of a spacing tween is a\n // per-glyph split with an x transform per character.\n const sizing = reflowProps.filter((p) => p === \"fontSize\");\n const spacing = reflowProps.filter((p) => p !== \"fontSize\");\n const parts: string[] = [];\n if (sizing.length > 0) {\n parts.push(`replace ${sizing.join(\"/\")} with scale (same visual, no reflow)`);\n }\n if (spacing.length > 0) {\n parts.push(\n `for ${spacing.join(\"/\")}, split the text into per-character elements and animate ` +\n \"each glyph's x (the spread) — uniform scale is NOT equivalent — or hold the final value statically\",\n );\n }\n fixes.push(\n `do not animate ${reflowProps.join(\"/\")} (they reflow text and snap glyph positions): ` +\n parts.join(\"; \"),\n );\n }\n if (usesRoundProps) fixes.push(\"remove roundProps\");\n const fixHint = `${fixes.join(\"; \")}. Transforms interpolate sub-pixel and stay smooth at any speed.`;\n\n findings.push({\n code: \"gsap_non_transform_motion\",\n severity: \"error\",\n message,\n selector: call.selector,\n fixHint,\n snippet: truncateSnippet(call.raw),\n });\n }\n }\n return findings;\n },\n\n // gsap_relative_value_second_writer — a relative tween value (\"+=...\"/\"-=...\") on a\n // property that another writer is still ACTIVE on when the relative tween starts.\n // The relative tween captures its base at tween INIT, which happens on first render:\n // the sequential path inits it mid-flight of the other writer, a cold render worker\n // landing later inits it with the other writer's end state — the same frame then\n // renders at two different positions (a visible snap at chunk boundaries).\n // GSAP renders children in start-time order within a single seek pass, so a writer\n // that completes strictly BEFORE the relative tween's start yields identical bases\n // on every seek path and is never flagged. Single-writer relative values are\n // seek-stable. from()/fromTo() resolve their values at build (immediateRender), so\n // they are exempt. The position PARAMETER (\"+=0.5\") is not a tween value — the\n // parser keeps it out of properties — so it can never be flagged here.\n async ({ scripts, tags }) => {\n const findings: HyperframeLintFinding[] = [];\n const tagsByToken = indexTagsByToken(tags);\n for (const script of scripts) {\n if (!/gsap\\.timeline/.test(script.content)) continue;\n const windows = await cachedExtractGsapWindows(script.content);\n for (const win of windows) {\n if (win.method === \"from\" || win.method === \"fromTo\") continue;\n if (win.overwriteAuto) continue;\n if (targetHasNoStableIdentity(win.targetSelector, win.targetIdentity)) continue;\n const relativeProps = Object.entries(win.propertyValues)\n .filter(([, value]) => isRelativeTweenValue(value))\n .map(([prop]) => prop);\n if (relativeProps.length === 0) continue;\n const target = { selector: win.targetSelector, identity: win.targetIdentity };\n for (const other of windows) {\n if (other === win) continue;\n if (other.position > win.position || other.end <= win.position) continue;\n const sharedProps = relativeProps.filter((prop) => other.properties.includes(prop));\n if (sharedProps.length === 0) continue;\n if (\n !targetsShareElement(\n target,\n { selector: other.targetSelector, identity: other.targetIdentity },\n tagsByToken,\n )\n ) {\n continue;\n }\n const values = sharedProps\n .map((prop) => `${prop}: \"${win.propertyValues[prop]}\"`)\n .join(\", \");\n const overlapEnd = Math.min(win.end, other.end);\n const formatTime = (t: number): string => (Number.isFinite(t) ? `${t.toFixed(2)}s` : \"∞\");\n findings.push({\n code: \"gsap_relative_value_second_writer\",\n severity: \"error\",\n message:\n `Relative value(s) ${values} on \"${win.targetSelector}\" start while another writer for the same ` +\n `propert${sharedProps.length > 1 ? \"ies\" : \"y\"} is active between ${formatTime(win.position)} and ${formatTime(overlapEnd)}. ` +\n \"Relative tweens capture their base at tween init: the sequential path inits mid-flight of the other \" +\n \"writer, a cold render worker landing later inits with its end state — the same frame renders at two \" +\n \"different positions (snap at chunk boundaries).\",\n selector: win.targetSelector,\n fixHint:\n `Use absolute values for ${sharedProps.join(\", \")}, or a fromTo() with explicit endpoints, so every seek ` +\n \"path resolves the same state. Single-writer relative values are safe; the conflict is the second writer.\",\n snippet: truncateSnippet(`${win.raw}\\n${other.raw}`),\n });\n }\n }\n }\n return findings;\n },\n\n // gsap_repeat_refresh_relative_value — repeatRefresh re-resolves the tween's values\n // on every repeat iteration, so a relative value ACCUMULATES per cycle. A cold render\n // worker seeking non-linearly into iteration N skips the accumulation a sequential\n // playhead performed, so workers disagree on where the element is.\n ({ scripts }) => {\n const findings: HyperframeLintFinding[] = [];\n for (const script of scripts) {\n const source = stripJsComments(script.content);\n const pattern = /repeatRefresh\\s*:\\s*true\\b/g;\n let match: RegExpExecArray | null;\n while ((match = pattern.exec(source)) !== null) {\n const objectLiteral = enclosingObjectLiteral(source, match.index);\n if (!objectLiteral || !objectLiteralHasTopLevelRelativeValue(objectLiteral)) continue;\n findings.push({\n code: \"gsap_repeat_refresh_relative_value\",\n severity: \"error\",\n message:\n '`repeatRefresh: true` combined with a relative value (\"+=\"/\"-=\") accumulates per repeat iteration. ' +\n \"A cold render worker seeking non-linearly into iteration N never performed the earlier iterations' \" +\n \"accumulation, so its rendered position diverges from the sequential path.\",\n fixHint:\n \"Remove `repeatRefresh: true`, or replace the relative value with absolute endpoints (e.g. a fromTo()) \" +\n \"so each iteration resolves to the same state on every seek path.\",\n snippet: truncateSnippet(objectLiteral),\n });\n }\n }\n return findings;\n },\n\n // gsap_function_value_hazard — function-valued tween vars re-run at tween INIT,\n // which is seek-order-dependent. A value reading transform-SENSITIVE geometry\n // (getBoundingClientRect/getComputedStyle/gsap.getProperty) captures whatever state\n // the worker's own seek order produced — error. Transform-INVARIANT layout reads\n // (offsetWidth, getTotalLength, ...) are deterministic across cold render workers\n // unless the measured layout itself animates — warning. GSAP function values receive\n // (index, target, targets) — index is a NUMBER, so a method call on the first\n // parameter (assuming it is the element) throws at init — error. Pure-index\n // arithmetic, gsap.utils.wrap/distribute, and closures over constants are statically\n // opaque or safe and are never flagged.\n //\n // Uses the raw parser output instead of the windows machinery: windows drop tweens\n // with string positions (\"+=0.5\", labels), and position is irrelevant to whether a\n // VALUE is hazardous.\n async ({ scripts }) => {\n const findings: HyperframeLintFinding[] = [];\n const parseGsapScript = await loadParseGsapScript();\n for (const script of scripts) {\n if (!/gsap\\.timeline/.test(script.content)) continue;\n const parsed = parseGsapScript(script.content);\n for (const anim of parsed.animations) {\n const raw = synthesizeWindowRaw(parsed.timelineVar, anim);\n const entries = [\n ...Object.entries(anim.properties),\n ...Object.entries(anim.fromProperties ?? {}),\n ];\n for (const [prop, value] of entries) {\n if (typeof value !== \"string\" || !value.startsWith(\"__raw:\")) continue;\n const fn = parseFunctionValueSource(value.slice(6));\n // Non-function raw values (gsap.utils.wrap(...), identifiers, arithmetic)\n // are statically opaque — conservatively skipped.\n if (!fn) continue;\n const readsSensitive = TRANSFORM_SENSITIVE_READ.test(fn.body);\n const readsInvariant = TRANSFORM_INVARIANT_READ.test(fn.body);\n const badMember = firstParamMemberAccessHazard(fn);\n if (!readsSensitive && !readsInvariant && !badMember) continue;\n const reason = readsSensitive\n ? \"reads transform-sensitive geometry, so its result depends on the worker's own seek order\"\n : badMember\n ? `accesses .${badMember} on its first parameter — GSAP function values receive (index, target, targets), ` +\n \"so the first parameter is a NUMBER and this throws at tween init\"\n : \"measures layout at tween init, which is deterministic across cold render workers only while the measured layout never animates\";\n findings.push({\n code: \"gsap_function_value_hazard\",\n severity: readsSensitive || badMember ? \"error\" : \"warning\",\n message: `Function-valued tween var for ${prop} on \"${anim.targetSelector}\" ${reason}. Each render worker initializes tweens independently.`,\n selector: anim.targetSelector,\n fixHint: badMember\n ? \"Use the SECOND parameter for the element: (index, target) => ... — or index arithmetic like (i) => i * 20.\"\n : \"Compute the value once at build time (before the timeline is registered) and pass a constant, or derive it from fixed composition coordinates.\",\n snippet: truncateSnippet(raw),\n });\n }\n }\n }\n return findings;\n },\n\n // gsap_callback_dom_measurement — DOM measurement reachable from timeline callbacks\n // (tl.add(fn) / tl.call(fn) / eventCallback / onStart-style vars). The capture path\n // seeks with suppressEvents=false (core/src/adapters/gsap.ts), so callbacks re-fire\n // on EVERY seek, including rewinds — and a cold render worker executes them against\n // whatever DOM state its own non-linear seek order produced. Geometry measured\n // inside a callback is therefore seek-order-dependent, and anything measured before\n // the callback ran (e.g. a build-time getTotalLength() on a path whose `d` the\n // callback assigns) is stale or zero. Warning, not error: gsap.getProperty-style\n // derived-output callbacks were excluded, but the remaining reads can still be\n // legitimate when the measured layout is static.\n ({ scripts }) => {\n const findings: HyperframeLintFinding[] = [];\n for (const script of scripts) {\n const source = stripJsComments(script.content);\n if (!/gsap\\.timeline/.test(source)) continue;\n const bodies = collectNamedFunctionBodies(source);\n const measuring = collectMeasuringFunctionNames(bodies);\n\n // A callback argument is hazardous when it is an inline function whose body\n // reaches a measurement, or a bare reference to a measuring function. Call\n // expressions (`tl.add(build())`) execute at BUILD time, not as callbacks —\n // conservatively skipped.\n const callbackExpressionHazard = (expression: string): boolean => {\n const trimmed = expression.trim();\n const inline = parseFunctionValueSource(trimmed);\n if (inline) return expressionReachesMeasurement(inline.body, measuring);\n if (/^[A-Za-z_$][\\w$]*$/.test(trimmed)) return measuring.has(trimmed);\n return false;\n };\n // The callback site goes into the structured `selector` field: the linter\n // dedupes on code+selector+message, and a constant message would collapse\n // distinct callback sites into a single finding.\n const report = (site: string, snippet: string): void => {\n findings.push({\n code: \"gsap_callback_dom_measurement\",\n severity: \"warning\",\n message:\n \"Timeline callback reaches DOM measurement (getBoundingClientRect/getTotalLength/getComputedStyle/...). \" +\n \"The renderer seeks with suppressEvents=false, so callbacks re-fire on every seek — and a cold render \" +\n \"worker runs them against whatever DOM state its own non-linear seek order produced. Measured geometry is \" +\n \"seek-order-dependent, and values measured at build time (before the callback ran) are stale or zero.\",\n selector: truncateSnippet(site, 120),\n fixHint:\n \"Do all measurement and DOM setup synchronously at build time, before registering the timeline — \" +\n \"or derive geometry from fixed composition coordinates instead of measuring.\",\n snippet: truncateSnippet(snippet),\n });\n };\n\n const timelineVars = collectTimelineVarNames(source);\n for (const timelineVar of timelineVars) {\n const callPattern = new RegExp(\n `\\\\b${escapeRegExp(timelineVar)}\\\\.(?:add|call)\\\\s*\\\\(`,\n \"g\",\n );\n let match: RegExpExecArray | null;\n while ((match = callPattern.exec(source)) !== null) {\n const parenIndex = match.index + match[0].length - 1;\n const argsWithParens = matchBalanced(source, parenIndex, \"(\", \")\");\n if (!argsWithParens) continue;\n const firstArg = sliceExpression(argsWithParens.slice(1, -1), 0);\n const site = match[0] + firstArg + \", ...)\";\n if (callbackExpressionHazard(firstArg)) report(site, site);\n }\n\n const eventCallbackPattern = new RegExp(\n `\\\\b${escapeRegExp(timelineVar)}\\\\.eventCallback\\\\s*\\\\(\\\\s*[\"']on[A-Za-z]+[\"']\\\\s*,`,\n \"g\",\n );\n while ((match = eventCallbackPattern.exec(source)) !== null) {\n const expression = sliceExpression(source, eventCallbackPattern.lastIndex);\n const site = match[0] + expression + \")\";\n if (callbackExpressionHazard(expression)) report(site, site);\n }\n }\n\n const varsCallbackPattern =\n /\\bon(?:Start|Update|Complete|Repeat|ReverseComplete|Interrupt|Overwrite)\\s*:\\s*/g;\n let match: RegExpExecArray | null;\n while ((match = varsCallbackPattern.exec(source)) !== null) {\n if (!isInsideGsapTweenVars(source, match.index, timelineVars)) continue;\n const expression = sliceExpression(source, varsCallbackPattern.lastIndex);\n const site = match[0] + expression;\n if (callbackExpressionHazard(expression)) report(site, site);\n }\n }\n return findings;\n },\n\n // gsap_group_selector_keyframes\n ({ scripts }) => {\n const findings: HyperframeLintFinding[] = [];\n const pattern = /\\.(?:to|from|fromTo)\\(\\s*[\"']([^\"']+,\\s*[^\"']+)[\"']\\s*,\\s*\\{[^}]*keyframes/g;\n for (const { match, snippet } of scanScriptsForRegexMatches(scripts, pattern, {\n stripComments: true,\n contextBefore: 20,\n contextAfter: 40,\n })) {\n const selector = match[1]!;\n const count = selector.split(\",\").length;\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(snippet),\n });\n }\n return findings;\n },\n\n // svg_drawon_css_dasharray_conflict — GSAP sets/tweens strokeDasharray on an element\n // whose CSS declares a MULTI-component stroke-dasharray (e.g. `10 10`). GSAP merges\n // dash lists per component, so `strokeDasharray: 641.4` over CSS `10 10` computes to\n // \"641.4px, 10px\" — the gap stays 10px and the hide-then-draw-on trick silently\n // fails: the line is visible the whole scene. A static two-component GSAP value is\n // the explicit fix form and is not flagged.\n // fallow-ignore-next-line complexity\n ({ scripts, styles, tags }) => {\n const findings: HyperframeLintFinding[] = [];\n const tagsByToken = indexTagsByToken(tags);\n\n const multiDashTokens = new Set<string>();\n for (const style of styles) {\n for (const [, selectorList, body] of style.content.matchAll(/([^{}]+)\\{([^}]+)\\}/g)) {\n if (!selectorList || !body) continue;\n const value = readStyleProperty(body, \"stroke-dasharray\");\n if (!value || !isMultiComponentDasharray(value)) continue;\n // Skip combinator groups — scope-dependent, unsafe to correlate by leaf token.\n for (const group of selectorList.split(\",\")) {\n const trimmed = group.trim();\n if (!trimmed || /[\\s>+~]/.test(trimmed)) continue;\n for (const token of targetedSelectorTokens(trimmed)) multiDashTokens.add(token);\n }\n }\n }\n for (const tag of tags) {\n const inlineValue = readStyleProperty(readAttr(tag.raw, \"style\") ?? \"\", \"stroke-dasharray\");\n if (!inlineValue || !isMultiComponentDasharray(inlineValue)) continue;\n for (const token of tagSimpleSelectors(tag)) multiDashTokens.add(token);\n }\n if (multiDashTokens.size === 0) return findings;\n\n for (const script of scripts) {\n const source = stripJsComments(script.content);\n const varTokens = resolveScriptElementTokens(source, tags);\n const reported = new Set<string>();\n\n const writerPattern =\n /\\b[\\w$]+\\.(set|to|fromTo)\\s*\\(\\s*(?:([\"'])([^\"'`]+)\\2|([A-Za-z_$][\\w$]*))\\s*,\\s*\\{/g;\n let match: RegExpExecArray | null;\n while ((match = writerPattern.exec(source)) !== null) {\n const method = match[1] ?? \"\";\n const braceIndex = match.index + match[0].length - 1;\n const firstVars = matchBalanced(source, braceIndex, \"{\", \"}\");\n if (!firstVars) continue;\n const varsObjects = [firstVars];\n if (method === \"fromTo\") {\n const afterFirst = source.slice(braceIndex + firstVars.length);\n const secondOpen = /^\\s*,\\s*\\{/.exec(afterFirst);\n if (secondOpen) {\n const secondBrace = braceIndex + firstVars.length + secondOpen[0].length - 1;\n const secondVars = matchBalanced(source, secondBrace, \"{\", \"}\");\n if (secondVars) varsObjects.push(secondVars);\n }\n }\n\n const quotedSelector = match[3];\n const targetTokens = quotedSelector\n ? targetedSelectorTokens(quotedSelector)\n : (varTokens.get(match[4] ?? \"\") ?? new Set<string>());\n if (targetTokens.size === 0) continue;\n const expanded = elementLevelTokens(targetTokens, tagsByToken);\n\n for (const varsObject of varsObjects) {\n const propMatch =\n varsObject.match(/\\bstrokeDasharray\\s*:\\s*/) ??\n varsObject.match(/[\"']stroke-dasharray[\"']\\s*:\\s*/);\n if (!propMatch || propMatch.index === undefined) continue;\n const valueSource = sliceExpression(varsObject, propMatch.index + propMatch[0].length);\n if (gsapDasharrayValueLooksMultiComponent(valueSource)) continue;\n const conflictToken = [...expanded].find((token) => multiDashTokens.has(token));\n if (!conflictToken) continue;\n const targetLabel = quotedSelector ?? match[4] ?? \"\";\n if (reported.has(targetLabel + conflictToken)) continue;\n reported.add(targetLabel + conflictToken);\n findings.push({\n code: \"svg_drawon_css_dasharray_conflict\",\n severity: \"error\",\n message:\n `GSAP writes strokeDasharray on \"${targetLabel}\", but its CSS (\"${conflictToken}\") declares a multi-component ` +\n 'stroke-dasharray. GSAP merges dash lists per component, so the CSS gap survives (e.g. \"641.4px, 10px\") — ' +\n \"the draw-on hide only hides one gap's worth and the line stays visible the whole scene.\",\n selector: quotedSelector ?? undefined,\n fixHint:\n `Remove the CSS stroke-dasharray from \"${conflictToken}\" (decorative dashes belong on a separate element), ` +\n 'or set the full two-component value in GSAP: strokeDasharray: \"${len} ${len}\".',\n snippet: truncateSnippet(match[0] + firstVars.slice(1)),\n });\n }\n }\n }\n return findings;\n },\n\n // gsap_timeline_set_initial_hide — a zero-duration tl.set(...) at position 0 inside\n // the paused timeline does NOT render while the playhead sits exactly at 0 (verified\n // against this repo's GSAP: tl.time(0) leaves the target untouched; only a seek past\n // 0 applies it). Frame 0 therefore shows the UN-hidden state, then the element pops\n // hidden on frame 1 — and only for the worker that renders frame 0. Targets already\n // hidden by authored CSS/inline styles or by a standalone gsap.set are exempt: the\n // tl.set is then a defensive re-assertion and frame 0 is hidden anyway.\n //\n // Only sets that precede every tween in source order qualify: the parser resolves a\n // mutated position variable (`var t = 0; ...; tl.set(sel, vars, t)`) to its INITIAL\n // binding, so late hard-kills can masquerade as position-0 sets. Genuine\n // initial-state hides are authored before the timeline's tweens.\n async ({ scripts, styles, tags }) => {\n const findings: HyperframeLintFinding[] = [];\n const cssHiddenSelectors = collectCssOpacityZeroSelectors(styles, tags);\n const tagsByToken = indexTagsByToken(tags);\n for (const script of scripts) {\n if (!/gsap\\.timeline/.test(script.content)) continue;\n const windows = await cachedExtractGsapWindows(script.content);\n const alreadyHidden = new Set([\n ...cssHiddenSelectors,\n ...extractStandaloneHiddenSelectors(script.content),\n ]);\n const isInstantHold = (win: GsapWindow): boolean =>\n win.method === \"set\" ||\n ((win.method === \"to\" || win.method === \"fromTo\") && win.end === win.position);\n const firstTweenIndex = windows.findIndex((win) => !isInstantHold(win));\n const initialHolds = firstTweenIndex < 0 ? windows : windows.slice(0, firstTweenIndex);\n for (const win of initialHolds) {\n if (!isInstantHold(win) || win.position !== 0) continue;\n if (win.global || win.immediateRender) continue;\n if (targetHasNoStableIdentity(win.targetSelector, win.targetIdentity)) continue;\n const targetTokens = [...targetedSelectorTokens(win.targetSelector)];\n const hiddenByToken =\n targetTokens.length > 0 && targetTokens.every((token) => alreadyHidden.has(token));\n const resolvedTags = targetTokens.flatMap((token) => tagsByToken.get(token) ?? []);\n const hiddenByElement =\n resolvedTags.length > 0 &&\n resolvedTags.every((tag) =>\n tagSimpleSelectors(tag).some((token) => alreadyHidden.has(token)),\n );\n if (hiddenByToken || hiddenByElement) continue;\n const offset = win.propertyValues[\"strokeDashoffset\"];\n const hidesByOffset = numberValue(offset) !== null && !zeroValue(offset);\n const hides =\n isHiddenGsapState(win.propertyValues) ||\n zeroValue(win.propertyValues[\"scale\"]) ||\n hidesByOffset;\n if (!hides) continue;\n findings.push({\n code: \"gsap_timeline_set_initial_hide\",\n severity: \"warning\",\n message:\n `Initial hidden state for \"${win.targetSelector}\" is set via tl.set(...) at position 0 inside the paused ` +\n \"timeline. A zero-duration set at 0 does not render while the playhead sits exactly at 0, so frame 0 \" +\n \"shows the un-hidden state.\",\n selector: win.targetSelector,\n fixHint:\n \"Use gsap.set(...) (immediate, outside the timeline) for initial states, or author the hidden state \" +\n \"directly in CSS/attributes.\",\n snippet: truncateSnippet(win.raw),\n });\n }\n }\n return findings;\n },\n\n // svg_measure_before_path_d — getTotalLength() on a <path> that has no static `d`\n // attribute in the HTML. In Chrome getTotalLength() on a d-less path returns 0,\n // silently killing dash animations (offset 0 == length 0 == nothing to draw). If a\n // d assignment exists but only inside a function body, execution order is statically\n // undecidable — WARNING; if NO d assignment exists anywhere — ERROR. Element\n // identity is resolved conservatively (literal / template getElementById,\n // querySelector); createElementNS-built paths and unresolved variables are skipped.\n // fallow-ignore-next-line complexity\n ({ scripts, styles, tags }) => {\n const findings: HyperframeLintFinding[] = [];\n const tagsByToken = indexTagsByToken(tags);\n // CSS `d: path(...)` supplies geometry statically — treat like a static attribute.\n const cssProvidesD = styles.some((style) => /\\bd\\s*:\\s*path\\(/.test(style.content));\n\n for (const script of scripts) {\n const source = stripJsComments(script.content);\n const varTokens = resolveScriptElementTokens(source, tags);\n const functionRanges = collectFunctionBodyRanges(source);\n const createdVars = new Set(\n [...source.matchAll(/([A-Za-z_$][\\w$]*)\\s*=\\s*document\\.createElementNS\\(/g)].map(\n (m) => m[1] ?? \"\",\n ),\n );\n // `d` assignments come in two forms: direct setAttribute('d', ...) and the\n // GSAP attr plugin (`gsap.set(wire, { attr: { d: \"...\" } })`). Both count,\n // with the same lexical-order semantics.\n const dAssignments = [\n ...[...source.matchAll(/\\b([A-Za-z_$][\\w$]*)\\.setAttribute\\(\\s*[\"']d[\"']\\s*,/g)].map(\n (m) => ({ varName: m[1] ?? \"\", index: m.index ?? 0 }),\n ),\n ...[\n ...source.matchAll(\n /\\.(?:set|to|fromTo)\\s*\\(\\s*([A-Za-z_$][\\w$]*)\\s*,\\s*\\{[^{}]*\\battr\\s*:\\s*\\{[^{}]*\\bd\\s*:/g,\n ),\n ].map((m) => ({ varName: m[1] ?? \"\", index: m.index ?? 0 })),\n ];\n const reported = new Set<string>();\n\n const measurePattern = /\\b([A-Za-z_$][\\w$]*)\\.getTotalLength\\s*\\(/g;\n let match: RegExpExecArray | null;\n while ((match = measurePattern.exec(source)) !== null) {\n const varName = match[1] ?? \"\";\n if (createdVars.has(varName)) continue;\n const tokens = varTokens.get(varName);\n if (!tokens || tokens.size === 0) continue;\n // Only <path> elements without a static d attribute qualify.\n const resolvedTags = [...tokens].flatMap((token) => tagsByToken.get(token) ?? []);\n const dLessPaths = resolvedTags.filter(\n (tag) => tag.name.toLowerCase() === \"path\" && readAttr(tag.raw, \"d\") === null,\n );\n if (dLessPaths.length === 0 || dLessPaths.length !== resolvedTags.length) continue;\n if (cssProvidesD) continue;\n\n // A same-variable d assignment lexically before the measure, in scope of the\n // measure (top-level, or a function body containing the measure), is the\n // legitimate synchronous assign-then-measure pattern.\n const measureIndex = match.index;\n const assignedBeforeInScope = dAssignments.some(\n (assign) =>\n assign.varName === varName &&\n assign.index < measureIndex &&\n (!indexInsideAnyRange(assign.index, functionRanges) ||\n functionRanges.some(\n (range) =>\n assign.index > range.start &&\n assign.index < range.end &&\n measureIndex > range.start &&\n measureIndex < range.end,\n )),\n );\n if (assignedBeforeInScope) continue;\n\n const sameVarAssignmentExists = dAssignments.some((a) => a.varName === varName);\n const tokenLabel = [...tokens].join(\", \");\n if (reported.has(tokenLabel)) continue;\n reported.add(tokenLabel);\n findings.push({\n code: \"svg_measure_before_path_d\",\n severity: sameVarAssignmentExists ? \"warning\" : \"error\",\n message: sameVarAssignmentExists\n ? `getTotalLength() is called on \"${tokenLabel}\", whose \\`d\\` is only assigned inside a function body — ` +\n \"if the measure runs before that function (e.g. the function is a timeline callback), the length is 0 \" +\n \"and the dash animation is dead.\"\n : `getTotalLength() is called on \"${tokenLabel}\", but the path has no static \\`d\\` attribute and no d ` +\n \"assignment exists anywhere — getTotalLength() returns 0 in Chrome, silently killing dash animations.\",\n selector: tokenLabel,\n fixHint:\n \"Assign the path's `d` synchronously at build time (top level, before measuring), or author a static \" +\n \"d attribute in the HTML.\",\n snippet: truncateSnippet(match[0] + \")\"),\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, OpenTag } from \"../context\";\nimport {\n findHtmlTag,\n readAttr,\n readDecodedAttr,\n readJsonAttr,\n stripJsComments,\n truncateSnippet,\n WINDOW_TIMELINE_ASSIGN_PATTERN,\n} from \"../utils\";\nimport { COMPOSITION_VARIABLE_TYPES } from \"@hyperframes/parsers/composition\";\nimport { COMPOSITION_ATTRIBUTES, readClipTiming } from \"@hyperframes/parsers/composition-contract\";\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\"]);\nconst CAPTION_CUE_TOKEN =\n /^(?:caption(?:[-_](?:group|word|line|block|cue|text))?|subtitle(?:[-_](?:group|line|cue|text))?|cg-.+)$/i;\n\n// composition_heavy_overlay_count_high — warn when a composition carries this\n// many or more elements whose CSS uses filter:blur, clip-path (non-none), or\n// radial-gradient. Field signal ts=1784040753 (#hyperframes-cli-feedback):\n// a composition with ~40 such elements captures solid-black for the first\n// ~half of the render, recovering near the end. Presence alone matters —\n// opacity:0 and visibility:hidden overlays still contribute — so the rule\n// counts every one that isn't display:none-hidden. Threshold sits below the\n// observed 40-element repro (25) so authors get lead time; adjust here if\n// noise/signal shifts, since a per-rule config option would also require\n// plumbing through HyperframeLinterOptions across every embedder.\nconst HEAVY_OVERLAY_ELEMENT_COUNT_WARN = 25;\nconst HEAVY_OVERLAY_EXEMPT_TAGS = new Set([\n \"audio\",\n \"body\",\n \"br\",\n \"defs\",\n \"head\",\n \"hr\",\n \"html\",\n \"link\",\n \"meta\",\n \"script\",\n \"source\",\n \"style\",\n \"template\",\n \"title\",\n \"use\",\n \"video\",\n]);\n// Matches any of: `filter: <...>blur(...)`, `clip-path: <non-none-value>`,\n// or `radial-gradient(...)`. Property terminator is `;` or `}`; value class\n// excludes both so we don't over-match into the next declaration. `clip-path`\n// escapes when its value starts with a CSS-wide keyword that leaves the render\n// tree unaffected (none / inherit / initial / unset) — the whitespace-eating\n// `\\s*` lives *inside* the negative lookahead so the engine can't backtrack\n// `\\s*` from outside to 0-width and slip past the keyword guard.\nconst HEAVY_OVERLAY_CSS_PATTERN =\n /(?:filter\\s*:[^;}]*\\bblur\\s*\\()|(?:clip-path\\s*:(?!\\s*(?:none|inherit|initial|unset)\\b)\\s*[^;}]+)|(?:radial-gradient\\s*\\()/i;\nconst INLINE_STYLE_DISPLAY_NONE_PATTERN = /(?:^|;)\\s*display\\s*:\\s*none\\b/i;\n\n// `parseFloat(\"0.1\") + parseFloat(\"0.2\") = 0.30000000000000004`. Sub-second\n// authored adjacencies survive parse + add as a value a few ulps above the\n// next clip's start; a strict `>` fires the overlap rule on adjacencies that\n// are exact in the source HTML. 1μs sits ~11 orders of magnitude above the\n// observed drift (worst ~2e-16s across every realistic decimal pair) and 4\n// below one 60fps frame (~16.67ms), so this only ever swallows float slop.\nconst OVERLAP_EPSILON_SECONDS = 1e-6;\n\nfunction readTagTiming(rawTag: string) {\n return readClipTiming({ getAttribute: (name) => readAttr(rawTag, name) });\n}\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\nfunction isCaptionCue(tag: OpenTag): boolean {\n const classTokens = (readAttr(tag.raw, \"class\") || \"\").split(/\\s+/).filter(Boolean);\n const id = readAttr(tag.raw, \"id\");\n return (\n classTokens.some((token) => CAPTION_CUE_TOKEN.test(token)) ||\n Boolean(id && CAPTION_CUE_TOKEN.test(id))\n );\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 readDecodedAttr(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// Id token in a selector's leftmost compound. `#hero .title` → \"hero\";\n// `.a#b > .c` → \"b\"; `.a .b` → null. Companion to leftmostCompoundClasses;\n// splits on the same combinator set so the two agree on where \"leftmost\" ends.\nfunction leftmostCompoundId(selector: string): string | null {\n const leftmost = selector.trim().split(/[\\s>+~]+/)[0] ?? \"\";\n return leftmost.match(/#([\\w-]+)/)?.[1] ?? null;\n}\n\n// Class tokens + ids whose rule body sets a \"heavy overlay\" property\n// (filter:blur, clip-path non-none, or radial-gradient). Only top-level rules\n// are scanned — the flat `[^{}]*` body class naturally skips @keyframes\n// bodies (which contain nested `{...}` stops) and other @-rules, so keyframe\n// selectors like `0%`/`100%` don't leak in.\nfunction collectHeavyOverlayHooks(styles: ExtractedBlock[]): {\n classes: Set<string>;\n ids: Set<string>;\n} {\n const classes = new Set<string>();\n const ids = new Set<string>();\n for (const style of styles) {\n const noComments = style.content.replace(/\\/\\*[\\s\\S]*?\\*\\//g, \"\");\n const ruleWithBody = /([^{}]+)\\{([^{}]*)\\}/g;\n let m: RegExpExecArray | null;\n while ((m = ruleWithBody.exec(noComments)) !== null) {\n const header = (m[1] ?? \"\").trim();\n const body = m[2] ?? \"\";\n if (!header || header.startsWith(\"@\")) continue;\n if (!HEAVY_OVERLAY_CSS_PATTERN.test(body)) continue;\n for (const sel of header.split(\",\")) {\n const trimmed = sel.trim();\n if (!trimmed) continue;\n for (const cls of leftmostCompoundClasses(trimmed)) classes.add(cls);\n const idToken = leftmostCompoundId(trimmed);\n if (idToken) ids.add(idToken);\n }\n }\n }\n return { classes, ids };\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\n/** Declared variable ids from an <html> tag's raw text; null when the JSON is unparseable. */\nfunction collectDeclaredVariableIds(htmlTagRaw: string): Set<string> | null {\n const declared = new Set<string>();\n const raw = readJsonAttr(htmlTagRaw, \"data-composition-variables\");\n if (!raw) return declared;\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n return null;\n }\n if (!Array.isArray(parsed)) return declared;\n for (const entry of parsed) {\n const id = (entry as { id?: unknown } | null)?.id;\n if (typeof id === \"string\") declared.add(id);\n }\n return declared;\n}\n\n/**\n * Union declared variable ids from every element carrying\n * `data-composition-variables`: full-document comps hold it on `<html>`;\n * template/fragment sub-comps hold it on their composition root div. Returns\n * null if any occurrence has unparseable JSON.\n */\nfunction collectAllDeclaredVariableIds(tags: readonly OpenTag[]): Set<string> | null {\n const all = new Set<string>();\n for (const tag of tags) {\n if (!readAttr(tag.raw, \"data-composition-variables\")) continue;\n const ids = collectDeclaredVariableIds(tag.raw);\n if (ids === null) return null;\n for (const id of ids) all.add(id);\n }\n return all;\n}\n\n/**\n * Declared ids to validate `data-var-*` bindings against, or null to skip the\n * file: unparseable declarations (reported elsewhere), or a fragment with no\n * `<html>` and no declarations of its own (its values come from a host's\n * data-variable-values, which this file can't see).\n */\nfunction declaredIdsForBindingCheck(tags: readonly OpenTag[]): Set<string> | null {\n const declared = collectAllDeclaredVariableIds(tags);\n if (declared === null) return null;\n if (declared.size === 0 && !findHtmlTag(tags)) return null;\n return declared;\n}\n\nfunction isInsideInertTemplate(tag: OpenTag, tags: readonly OpenTag[]): boolean {\n return tags.some(\n (candidate) =>\n candidate.name === \"template\" &&\n candidate.closeIndex != null &&\n tag.index > candidate.index &&\n tag.index < candidate.closeIndex,\n );\n}\n\nexport const compositionRules: Array<(ctx: LintContext) => HyperframeLintFinding[]> = [\n // duplicate_composition_id catches meta-tag/root collisions that create duplicate composition entries.\n ({ tags }) => {\n const tagsByCompositionId = new Map<string, string[]>();\n for (const tag of tags) {\n if (isInsideInertTemplate(tag, tags)) continue;\n const compositionId = readDecodedAttr(tag.raw, \"data-composition-id\");\n if (!compositionId || compositionId.trim().length === 0) continue;\n\n const matchingTags = tagsByCompositionId.get(compositionId) ?? [];\n matchingTags.push(tag.raw);\n tagsByCompositionId.set(compositionId, matchingTags);\n }\n\n const findings: HyperframeLintFinding[] = [];\n for (const [compositionId, matchingTags] of tagsByCompositionId) {\n if (matchingTags.length < 2) continue;\n\n findings.push({\n code: \"duplicate_composition_id\",\n severity: \"error\",\n message: `Composition id \"${compositionId}\" is used by ${matchingTags.length} elements. Each data-composition-id value must be unique within a composition file.`,\n fixHint:\n \"Keep data-composition-id on exactly one element, the composition root. Remove it from metadata or duplicate hosts, especially a <meta> tag carrying the same data-composition-id as the root <div>, which causes a silent duplicate-id collision.\",\n snippet: truncateSnippet(matchingTags[0] ?? \"\"),\n });\n }\n\n return findings;\n },\n\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 (isCaptionCue(tag)) continue;\n if (isCompositionRootOrMount(tag.raw)) continue;\n if (!readAttr(tag.raw, \"data-start\")) continue;\n\n const track = readAttr(tag.raw, COMPOSITION_ATTRIBUTES.trackIndex);\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 (readDecodedAttr(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 const timing = readTagTiming(tag.raw);\n if (timing.diagnostics.some(({ code }) => code === \"deprecated-layer\")) {\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 (timing.diagnostics.some(({ code }) => code === \"deprecated-end\")) {\n const elementId = readAttr(tag.raw, \"id\") || undefined;\n const conflicting = timing.diagnostics.some(({ code }) => code === \"conflicting-end\");\n // Two shapes reach here after the false-positive fix (see\n // compositionContract.ts `diagnoseDerivedEnd`): the truly-legacy shape\n // (no data-duration, data-end alone) and the stale-companion shape\n // (data-duration present but paired with a data-end that disagrees).\n // A consistent data-duration + data-end pair — the shape the compiler\n // emits — is silent and never reaches this branch.\n const message = conflicting\n ? `<${tag.name}${elementId ? ` id=\"${elementId}\"` : \"\"}> has data-end that disagrees with data-duration. Remove the stale data-end; the compiler regenerates it from data-duration.`\n : `<${tag.name}${elementId ? ` id=\"${elementId}\"` : \"\"}> uses data-end without data-duration. Use data-duration in source HTML.`;\n findings.push({\n code: \"deprecated_data_end\",\n severity: \"error\",\n message,\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 (readDecodedAttr(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 trackStr = readAttr(tag.raw, COMPOSITION_ATTRIBUTES.trackIndex);\n if (!trackStr) continue;\n const timing = readTagTiming(tag.raw);\n const { start, duration } = timing;\n const track = trackStr;\n\n // Skip non-numeric (relative timing references like \"intro-comp\")\n if (start == null || duration == null) 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 > OVERLAP_EPSILON_SECONDS) {\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 = readDecodedAttr(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 // missing_data_no_timeline\n // The producer polls window.__timelines[id] with a 45-second timeout waiting\n // for GSAP timeline registration. Compositions that never call\n // window.__timelines[id] = tl stall for 45 s every render. Adding\n // data-no-timeline to the root element tells the producer to skip the poll.\n ({ rootTag, rootCompositionId, scripts, rawSource, options }) => {\n if (options.isSubComposition) return [];\n if (!rootCompositionId || !rootTag) return [];\n // readAttr only matches valued attrs (attr=\"...\"); data-no-timeline is\n // typically boolean (no value). Strip quoted attribute values first to\n // avoid matching attr names that appear inside other values\n // (e.g. title=\"add data-no-timeline here\"), then check with a boundary\n // that rejects hyphenated variants (data-no-timeline-start has '-' next,\n // not a word-break char).\n const tagNoValues = rootTag.raw.replace(/\"[^\"]*\"|'[^']*'/g, '\"\"');\n if (/(?:^|\\s)data-no-timeline(?=[\\s>=/]|$)/i.test(tagNoValues)) return [];\n // Can't scan external script files for timeline registration; skip to avoid\n // false positives on compositions that register via a bundled JS file.\n if (/<script\\b[^>]*\\bsrc\\s*=/i.test(rawSource)) return [];\n const registersTimeline = scripts.some((s) => s.content.includes(\"window.__timelines[\"));\n if (registersTimeline) return [];\n return [\n {\n code: \"missing_data_no_timeline\",\n severity: \"warning\",\n message:\n \"This composition has no `window.__timelines` registration but is missing `data-no-timeline`. \" +\n \"The producer polls for timeline registration for up to 45 seconds before timing out, \" +\n \"adding 45 s to every render.\",\n fixHint:\n 'Add `data-no-timeline` to the root element to skip the poll: `<div data-composition-id=\"...\" data-no-timeline ...>`.',\n snippet: truncateSnippet(rootTag.raw),\n },\n ];\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 // unknown_variable_binding\n // data-var-src / data-var-text bind an element to a declared variable id;\n // the runtime silently keeps the authored fallback when the id resolves to\n // nothing, so a typo'd binding is invisible until a customer's override\n // does nothing. Skipped for fragment files (no <html>): their values come\n // from a host's data-variable-values, which this file can't see.\n ({ tags }) => {\n // Declarations live on <html> (full-document comps) OR the composition root\n // div (template/fragment sub-comps); declaredIdsForBindingCheck unions both\n // and returns null for files this rule should skip.\n const declared = declaredIdsForBindingCheck(tags);\n if (!declared) return [];\n const findings: HyperframeLintFinding[] = [];\n for (const tag of tags) {\n for (const attr of [\"data-var-src\", \"data-var-text\"]) {\n const id = readAttr(tag.raw, attr)?.trim();\n if (!id || declared.has(id)) continue;\n findings.push({\n code: \"unknown_variable_binding\",\n severity: \"warning\",\n message: `<${tag.name}> binds ${attr}=\"${id}\" but no variable \"${id}\" is declared in data-composition-variables — the binding will silently keep the authored fallback.`,\n fixHint: `Declare the variable on the composition root (<html>, or the [data-composition-id] root element for a template/fragment comp): data-composition-variables='[{\"id\":\"${id}\",\"type\":\"${attr === \"data-var-src\" ? \"image\" : \"string\"}\",\"label\":\"${id}\",\"default\":\"...\"}]', or fix the binding id.`,\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 ({ tags }) => {\n const htmlTag = findHtmlTag(tags);\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 // html_dir_attribute_breaks_render — valid non-LTR dir values on\n // <html> renders correctly in preview/snapshot but produces a fully\n // blank/black video from render, with no other lint/validate/inspect\n // check catching it (output file size, far smaller than expected, is the\n // only tell). Confirmed independently by two separate reports, both\n // diagnosing the same exact trigger and the same fix: drop dir from\n // <html>, keep lang, and scope `direction: rtl` to individual\n // text-containing elements via CSS instead (text still bidi-shapes\n // correctly). Advisory-only — this does not attempt to fix the render\n // pipeline's own root cause (suspected to be a capture step that clips a\n // fixed top-left-origin screenshot region, which RTL layout can shift the\n // actual content away from), only surfaces the already-confirmed footgun\n // before someone hits it blind.\n ({ tags }) => {\n const htmlTag = findHtmlTag(tags);\n if (!htmlTag) return [];\n const dir = readAttr(htmlTag.raw, \"dir\");\n if (!dir) return [];\n const normalizedDir = dir.toLowerCase();\n if (normalizedDir !== \"rtl\" && normalizedDir !== \"auto\") return [];\n const scopedDirection = normalizedDir === \"auto\" ? 'dir=\"auto\"' : `direction: ${normalizedDir}`;\n return [\n {\n code: \"html_dir_attribute_breaks_render\",\n severity: \"error\",\n message: `<html dir=\"${dir}\"> renders correctly in preview/snapshot but produces a fully blank/black video from render — a confirmed, silent failure.`,\n fixHint: `Remove dir=\"${dir}\" from <html>. Keep lang, and scope ${scopedDirection} to individual text-containing elements instead — text still shapes correctly via the browser's own bidi algorithm.`,\n snippet: truncateSnippet(htmlTag.raw),\n },\n ];\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 // root_composition_missing_duration_source\n //\n // The render engine (packages/engine/src/services/frameCapture.ts) needs a\n // positive window.__hf.duration to know how many frames to capture. GSAP\n // timelines set this automatically. Non-GSAP runtimes (CSS, WAAPI, Lottie)\n // are now auto-inferred by the runtime too (see\n // packages/core/src/runtime/init.ts resolveAdapterDurationFloorSeconds and\n // the adapters' getInferredDurationSeconds) — so data-duration is optional\n // wherever the runtime can work it out on its own.\n //\n // This rule fires for cases where the total render length is not reliably\n // determinable without an explicit data-duration:\n // - No GSAP timeline AND no data-duration AND no non-GSAP animation\n // signal at all (nothing for any adapter to discover — render fails).\n // - Three.js used with no data-duration (no discoverable AnimationClip\n // duration in this codebase's adapter — see adapters/three.ts).\n // - Any infinite CSS animation-iteration-count with no data-duration,\n // EVEN when a finite CSS animation is present alongside it. An unbounded\n // animation makes the intended total length ambiguous — the runtime will\n // infer a finite sibling's length if one exists, but that's a fallback,\n // not a declaration of intent, so we still require data-duration here.\n // (This is intentionally stricter than the runtime's own inference.)\n // Purely finite CSS/WAAPI animations and Lottie are excluded — the runtime\n // infers those unambiguously, so requiring data-duration there would be a\n // false positive against the runtime's own auto-inference. Note lint is\n // advisory by default (see shouldBlockRender) — it only blocks render under\n // --strict/--strict-all — so a strict flag here nudges toward an explicit,\n // guaranteed-correct value without failing renders that would succeed.\n // fallow-ignore-next-line complexity\n ({ rootTag, scripts, styles, tags, options }) => {\n if (options.isSubComposition) return [];\n if (!rootTag) return [];\n // Not every file linted as a \"root\" HTML document is a video composition\n // — e.g. a slideshow demo.html mounts <hyperframes-player src=\"index.html\">\n // with no data-composition-id of its own. Nothing to capture there, so\n // there's no duration contract to enforce.\n if (readDecodedAttr(rootTag.raw, \"data-composition-id\") === null) return [];\n if (readAttr(rootTag.raw, \"data-duration\") !== null) return [];\n\n // Strip comments before scanning for signals — a commented-out\n // `.animate(...)` call or `/* animation: spin 2s infinite; */` must not\n // satisfy the \"has a duration source\" check, or the composition still\n // fails at render with zero duration despite lint passing.\n const allScriptTexts = scripts.map((s) => stripJsComments(s.content));\n const hasGsapTimeline = allScriptTexts.some((t) => /gsap\\.timeline\\s*\\(/.test(t));\n const hasRegisteredTimeline = allScriptTexts.some((t) =>\n WINDOW_TIMELINE_ASSIGN_PATTERN.test(t),\n );\n // A GSAP timeline drives duration via window.__timelines regardless of\n // data-duration — nothing to flag once one is registered.\n if (hasGsapTimeline && hasRegisteredTimeline) return [];\n\n const allCss = styles.map((s) => s.content).join(\"\\n\");\n const allInlineStyles = tags.map((t) => readAttr(t.raw, \"style\") || \"\").join(\"\\n\");\n const combinedCss = `${allCss}\\n${allInlineStyles}`.replace(/\\/\\*[\\s\\S]*?\\*\\//g, \"\");\n\n const usesLottie =\n tags.some((t) => readAttr(t.raw, \"data-lottie-src\") !== null) ||\n allScriptTexts.some((t) => /lottie\\.(loadAnimation)\\b|__hfLottie\\b/.test(t));\n const usesThree = allScriptTexts.some((t) => /\\bTHREE\\./.test(t));\n // `.animate([...], ...)` catches the array-literal keyframes form;\n // `.animate({...}, ...)` catches the object-literal (PropertyIndexedKeyframes)\n // form; `.animate(someVar, ...)` catches keyframes built up in a variable\n // first.\n const usesWaapi = allScriptTexts.some((t) => /\\.animate\\s*\\(\\s*[[{$A-Za-z_]/.test(t));\n const hasCssAnimationName = /\\banimation(?:-name)?\\s*:/.test(combinedCss);\n const hasInfiniteCssAnimation =\n /\\banimation(?:-iteration-count)?\\s*:[^;{}]*(?<![\\w-])infinite(?![\\w-])/.test(combinedCss);\n\n const hasAnyNonGsapSignal = usesLottie || usesThree || usesWaapi || hasCssAnimationName;\n\n if (!hasAnyNonGsapSignal) {\n // No GSAP timeline, no data-duration, and nothing for any adapter to\n // discover — the composition has no source of truth for duration at\n // all. This is the exact shape of the 27K \"zero duration\" render\n // failures this rule exists to catch before render time.\n return [\n {\n code: \"root_composition_missing_duration_source\",\n severity: \"error\",\n message:\n \"Root composition has no data-duration, no GSAP timeline, and no CSS/WAAPI/Lottie/Three.js \" +\n \"animation for the runtime to infer a duration from. The render engine cannot determine \" +\n 'how long to capture and will fail with \"Composition has zero duration\".',\n fixHint:\n 'Add data-duration=\"<seconds>\" to the root element, or add a paused GSAP timeline registered ' +\n \"on window.__timelines.\",\n snippet: truncateSnippet(rootTag.raw),\n },\n ];\n }\n\n if (usesThree) {\n // No AnimationMixer/AnimationClip discovery in the three.js adapter\n // today (see adapters/three.ts) — genuinely not inferable.\n return [\n {\n code: \"root_composition_missing_duration_source\",\n severity: \"error\",\n message:\n \"Root composition uses Three.js with no data-duration. The runtime cannot discover a \" +\n \"Three.js scene's duration automatically (no AnimationClip/AnimationMixer inspection) — \" +\n 'render will fail with \"Composition has zero duration\".',\n fixHint: 'Add data-duration=\"<seconds>\" to the root element.',\n snippet: truncateSnippet(rootTag.raw),\n },\n ];\n }\n\n if (hasInfiniteCssAnimation && !usesLottie && !usesWaapi) {\n // An infinite/unbounded CSS animation makes the intended total length\n // ambiguous, so we require an explicit data-duration even when a finite\n // CSS animation is present alongside it. This is deliberately stricter\n // than the runtime's own inference: the CSS adapter's\n // getInferredDurationSeconds (see adapters/css.ts) returns the longest\n // finite animation end-time when one exists (so a finite sibling would\n // render at that length) and null when every animation is unbounded (so\n // a render with no finite source fails outright). Either way the author\n // hasn't declared how long the video should be — a decorative infinite\n // spinner next to a 3s fade doesn't tell us the clip is meant to be 3s\n // — so we flag it and let them state intent. The message stays honest\n // about both outcomes rather than claiming the render always fails.\n return [\n {\n code: \"root_composition_missing_duration_source\",\n severity: \"error\",\n message:\n \"Root composition uses a CSS animation with animation-iteration-count: infinite and no \" +\n \"data-duration, so the intended total length is ambiguous. If a finite animation is also \" +\n \"present the runtime infers that length; with no finite source the render fails with \" +\n '\"Composition has zero duration\". Declare the intended length explicitly.',\n fixHint:\n 'Add data-duration=\"<seconds>\" to the root element with the intended total length.',\n snippet: truncateSnippet(rootTag.raw),\n },\n ];\n }\n\n // Finite CSS animation, WAAPI .animate(), or Lottie — the runtime infers\n // duration from these at render time (see resolveAdapterDurationFloorSeconds\n // in runtime/init.ts). Not an error; data-duration is optional here.\n return [];\n },\n\n // composition_heavy_overlay_count_high\n // Field signal ts=1784040753 (#hyperframes-cli-feedback): a composition\n // with ~40 heavy overlay DOM elements — `filter:blur`, oversized\n // `radial-gradient`, and `clip-path` animations — captures solid-black for\n // the first ~half of the render, recovering near the end. Reproduces\n // identically via drawElement AND forced --no-browser-gpu screenshot\n // capture AND `snapshot`, so the offender is the capture layer itself, not\n // encoder/mux. Independent of duration (padding the timeline grows the bad\n // zone proportionally, doesn't shift it). Reporter's workaround was to\n // split into per-transition mini compositions + FFmpeg concat.\n //\n // Presence alone matters: opacity:0 and visibility:hidden overlays still\n // contribute to the capture-layer regression, so they're counted-in. The\n // only escape hatch is `display: none` — an element removed from the render\n // tree can't feed the compositor. Warn at 25, well below the observed\n // 40-element repro, to give authors lead time before hitting the bug.\n // fallow-ignore-next-line complexity\n ({ tags, styles, rawSource, options }) => {\n if (isRegistrySourceFile(options.filePath) || isRegistryInstalledFile(rawSource)) return [];\n\n const { classes: heavyClassTokens, ids: heavyIds } = collectHeavyOverlayHooks(styles);\n\n let heavyCount = 0;\n for (const tag of tags) {\n if (HEAVY_OVERLAY_EXEMPT_TAGS.has(tag.name)) continue;\n // Structural containers (root + mounted sub-compositions) aren't overlay\n // content — the heavy children live inside them, and each such child is\n // its own tag entry that we score directly. Counting the container too\n // would double-attribute the risk to one authoring surface.\n if (isCompositionRootOrMount(tag.raw)) continue;\n\n // readJsonAttr lets a `style` value carry the opposite quote character\n // (inline `background: url(\"x.png\")` etc.), which readAttr would truncate.\n const styleAttr = readJsonAttr(tag.raw, \"style\") ?? \"\";\n // display:none removes the element from the render tree, so the capture\n // layer never sees it — the only reliable way to keep an \"unused\" heavy\n // overlay in the source without paying the compositor cost.\n if (styleAttr && INLINE_STYLE_DISPLAY_NONE_PATTERN.test(styleAttr)) continue;\n\n let heavy = false;\n if (styleAttr && HEAVY_OVERLAY_CSS_PATTERN.test(styleAttr)) heavy = true;\n\n if (!heavy && (heavyClassTokens.size > 0 || heavyIds.size > 0)) {\n const classList = (readAttr(tag.raw, \"class\") || \"\").split(/\\s+/).filter(Boolean);\n if (classList.some((cls) => heavyClassTokens.has(cls))) heavy = true;\n if (!heavy) {\n const idValue = readAttr(tag.raw, \"id\");\n if (idValue && heavyIds.has(idValue)) heavy = true;\n }\n }\n\n if (heavy) heavyCount += 1;\n }\n\n if (heavyCount < HEAVY_OVERLAY_ELEMENT_COUNT_WARN) return [];\n\n const splitTarget = options.isSubComposition\n ? \"Split this sub-composition further into per-transition mini-compositions\"\n : \"Split coherent scenes / transitions into separate .html files under compositions/\";\n\n return [\n {\n code: \"composition_heavy_overlay_count_high\",\n severity: \"warning\",\n message:\n `This composition has ${heavyCount} elements carrying \"heavy overlay\" CSS ` +\n `(filter:blur, radial-gradient, or clip-path). Field signal: a composition with ` +\n `~40 such elements — including opacity:0 / visibility:hidden ones — captures ` +\n `solid-black for the first ~half of the render, recovering near the end. Reproduces ` +\n `identically via drawElement, forced screenshot capture, and snapshot, so the capture ` +\n `layer itself is the offender (not encoder/mux). Independent of duration. Presence ` +\n `alone matters; only display:none elements are excluded here.`,\n fixHint:\n `${splitTarget} and concat the pieces (FFmpeg or the runtime's slideshow) so each ` +\n `capture only sees a small subset of heavy overlays at once. Even hidden overlays ` +\n `(opacity:0 / visibility:hidden) contribute — either remove truly unused ones from ` +\n `the source or scope them into their own per-transition sub-composition. If an ` +\n `overlay is genuinely inert for the whole clip, use display:none so it never enters ` +\n `the render tree. Field ref ts=1784040753 (#hyperframes-cli-feedback).`,\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 // Matches any import/from whose specifier contains \"three\" (bare 'three', or a\n // URL/path like .../+esm, esm.sh/three, three.module.js), mirroring the loose\n // /three/i treatment of <script src>.\n const hasThreeModuleImport = texts.some((t) =>\n /\\b(?:import|from)\\s*[^;\\n]*['\"][^'\"]*three[^'\"]*['\"]/i.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 // Vendor-prefixed system-font keywords. Like `system-ui`, the engine resolves\n // these to the OS UI font — they are never installable files and must not be\n // flagged as a missing @font-face, even when a generic fallback follows them\n // (e.g. `-apple-system, system-ui, sans-serif`).\n \"-apple-system\",\n \"blinkmacsystemfont\",\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\n// Normalize one comma-separated font-family entry to a lowercase family name,\n// or null if it carries no resolvable name. `var(--heading)` (or any function\n// token) is an indirection the linter cannot statically resolve, so the literal\n// `var(...)` is not a font name and flagging it is a false positive. Comma-split\n// fallbacks like `var(--x, 'Inter')` also leave a dangling `)` on the fallback\n// part, so skip anything bearing parentheses.\nfunction normalizeUsedFontName(part: string): string | null {\n const name = part\n .trim()\n .replace(/\\s*!important\\s*$/i, \"\")\n .replace(/^['\"]|['\"]$/g, \"\")\n .trim()\n .toLowerCase();\n if (!name || name.includes(\"(\") || name.includes(\")\")) return null;\n return name;\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 for (const part of match[1]!.split(\",\")) {\n const name = normalizeUsedFontName(part);\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) =>\n !declared.has(name) &&\n !FONT_ALIAS_KEYS.has(name) &&\n !googleFonts.has(name.replace(/\\+/g, \" \")),\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. For an OS-bundled \" +\n \"system font (e.g. Hiragino Sans, Microsoft YaHei) that has no downloadable file, \" +\n \"use src: local('Exact Font Name') instead — the declaration alone satisfies this \" +\n \"check without needing a font file.\",\n });\n return findings;\n },\n];\n","import type { LintContext, HyperframeLintFinding } from \"../context\";\nimport type { LintRule } from \"../types\";\nimport { readAttr, readDecodedAttr } 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 = readDecodedAttr(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 { parseHtmlStructure, 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 for (const { name: tagName, raw } of parseHtmlStructure(html).tags) {\n if (!/^(?:video|audio|img|source)$/.test(tagName)) continue;\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, join, relative, resolve } from \"node:path\";\nimport { rewriteAssetPath } from \"@hyperframes/parsers/asset-paths\";\nimport { checkSubCompositionUsability } from \"@hyperframes/parsers/sub-composition-validity\";\nimport { parseHTML } from \"linkedom\";\nimport {\n cleanAssetUrl,\n isRemoteOrInlineUrl,\n isUnresolvedAssetPlaceholder,\n isWithinProjectRoot,\n maskNonScannableRanges,\n resolveExistingLocalAsset,\n resolveLocalAssetCandidates,\n} from \"@hyperframes/parsers/asset-resolution\";\nimport { collectLocalVideoCandidates, lintHevcPreviewCodec } from \"./hevcPreviewLint.js\";\nimport { lintHyperframeHtml } from \"./hyperframeLinter.js\";\nimport type { HyperframeLintFinding, HyperframeLintResult } from \"./types.js\";\nimport type { ParsableDocumentLike } from \"@hyperframes/parsers/sub-composition-validity\";\n\n/** Adapts linkedom's `parseHTML` to the `checkSubCompositionUsability` contract. */\nfunction parseSubCompHtml(html: string): ParsableDocumentLike {\n return parseHTML(html).document as unknown as ParsableDocumentLike;\n}\n\ninterface HtmlSource {\n html: string;\n compSrcPath?: string;\n}\n\ninterface CssSource {\n content: string;\n rootRelativePath?: string;\n}\n\n/** Linkedom keeps template contents in a DocumentFragment that is not part of\n * the document query tree. Lint rules must still see shell styles and links\n * inside templates, so walk each template's content recursively without\n * falling back to regex parsing. */\nfunction querySelectorAllIncludingTemplates(root: ParentNode, selector: string): Element[] {\n const matches: Element[] = [...root.querySelectorAll(selector)];\n for (const template of root.querySelectorAll(\"template\")) {\n const content = (template as HTMLTemplateElement).content;\n if (content) matches.push(...querySelectorAllIncludingTemplates(content, selector));\n }\n return matches;\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 MASK_IMAGE_URL_RE =\n /\\b(?:-webkit-)?mask-image\\s*:\\s*[^;{}]*url\\(\\s*(?:\"([^\"]+)\"|'([^']+)'|([^\"')\\s]+))\\s*\\)/gi;\n\nfunction isLocalStylesheetHref(href: string): boolean {\n return !!href && !/^(https?:|data:|blob:|\\/\\/)/i.test(href);\n}\n\nfunction collectLocalStylesheets(\n projectDir: string,\n document: ParentNode,\n compSrcPath?: string,\n): Array<{ href: string; content: string; rootRelativePath: string }> {\n const styles: Array<{ href: string; content: string; rootRelativePath: string }> = [];\n for (const link of querySelectorAllIncludingTemplates(document, \"link\")) {\n const rel = link.getAttribute(\"rel\") ?? \"\";\n if (!rel.split(/\\s+/).some((part) => part.toLowerCase() === \"stylesheet\")) continue;\n const href = link.getAttribute(\"href\") ?? \"\";\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({\n href,\n content: readFileSync(stylesheet.resolved, \"utf-8\"),\n rootRelativePath: stylesheet.rootRelativePath,\n });\n }\n return styles;\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 { document } = parseHTML(html);\n for (const { href, content } of collectLocalStylesheets(projectDir, document, compSrcPath)) {\n styles.push({ href, content });\n }\n return styles;\n}\n\nfunction collectCssSources(projectDir: string, html: string, compSrcPath?: string): CssSource[] {\n const sources: CssSource[] = [];\n const { document } = parseHTML(html);\n\n for (const style of querySelectorAllIncludingTemplates(document, \"style\")) {\n sources.push({ content: style.textContent ?? \"\" });\n }\n\n for (const { content, rootRelativePath } of collectLocalStylesheets(\n projectDir,\n document,\n compSrcPath,\n )) {\n sources.push({ content, rootRelativePath });\n }\n\n for (const element of querySelectorAllIncludingTemplates(document, \"[style]\")) {\n const style = element.getAttribute(\"style\");\n if (!style) continue;\n sources.push({ content: style });\n }\n\n return sources;\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(\n projectDir: string,\n entryFile?: string,\n): Promise<ProjectLintResult> {\n const indexPath = entryFile ? resolve(entryFile) : resolve(projectDir, \"index.html\");\n if (entryFile && !isWithinProjectRoot(projectDir, indexPath)) {\n throw new Error(`Explicit lint entry is outside the project directory: ${entryFile}`);\n }\n const rootFile = relative(resolve(projectDir), indexPath).replace(/\\\\/g, \"/\") || \"index.html\";\n const rootCompSrcPath = rootFile === \"index.html\" ? undefined : rootFile;\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, rootCompSrcPath),\n });\n results.push({ file: rootFile, result: rootResult });\n totalErrors += rootResult.errorCount;\n totalWarnings += rootResult.warningCount;\n totalInfos += rootResult.infoCount;\n\n const allHtmlSources: HtmlSource[] = [{ html: rootHtml, compSrcPath: rootCompSrcPath }];\n const compositionsDir = resolve(projectDir, \"compositions\");\n if (!entryFile && 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()) {\n // Registry components are source snippets, not independently mounted\n // sub-compositions. Linting every installed template here makes an\n // unused component fail the assembled project check.\n if (!rel && entry.name === \"components\") continue;\n out.push(...collectHtmlFiles(join(dir, entry.name), relPath));\n } else if (entry.isFile() && entry.name.endsWith(\".html\") && !entry.name.startsWith(\"._\")) {\n out.push(relPath);\n }\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 // Mountable fragments (figma component imports, registry snippets) are\n // not standalone compositions — composition-root rules don't apply.\n // Anchored to the file's ROOT element so a real composition that merely\n // inlines snippet markup (or mentions the token in text) is still linted.\n if (isSnippetFragment(html)) continue;\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 ...(!entryFile ? lintMultipleRootCompositions(projectDir) : []),\n ...lintDuplicateAudioTracks(allHtmlSources),\n ...lintMissingOrEmptySubComposition(projectDir, rootHtml),\n ...(await lintHevcPreviewCodec(collectLocalVideoCandidates(projectDir, 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 (isUnresolvedAssetPlaceholder(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\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 // Placeholder check runs on the RAW value: cleanAssetUrl() splits on ?/# and would chop inside a ${...} token.\n if (isUnresolvedAssetPlaceholder(rawSrc)) continue;\n const src = cleanAssetUrl(rawSrc);\n if (!src) continue;\n if (isRemoteOrInlineUrl(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 // Placeholder check runs on the RAW value: cleanAssetUrl() splits on ?/# and would chop inside a ${...} token.\n if (isUnresolvedAssetPlaceholder(rawUrl)) continue;\n const url = cleanAssetUrl(rawUrl);\n if (!url || isRemoteOrInlineUrl(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(\n (file) => file.endsWith(\".html\") && !file.startsWith(\"._\"),\n );\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\n/**\n * Error if a `data-composition-src` reference points at a file that is\n * missing, empty, or does not parse to usable HTML. This is the #1 render\n * failure bucket in production telemetry: a scene-authoring step (an AI\n * agent, most commonly) writes the reference before — or without ever —\n * writing valid content into the scene file.\n *\n * The render pre-flight check (`assertSubCompositionsUsable` in\n * `packages/producer/src/services/htmlCompiler.ts`) now aborts the render\n * loudly and immediately when this happens, rather than silently dropping\n * the scene — so catching it here, before the render even starts, means the\n * failure surfaces at lint/validate time with the same message instead of\n * only at render time.\n *\n * Only follows files actually reachable via `data-composition-src` starting\n * from the root composition — mirroring the reachability semantics of\n * `assertSubCompositionsUsable`. A raw filesystem walk of every `.html`\n * under `compositions/` would flag orphaned/unreferenced files that the\n * renderer never visits, producing false-positive lint/validate failures on\n * projects that actually render fine. Lint, render, and the inliner must\n * never disagree about whether a given file would actually render\n * something.\n */\nfunction lintMissingOrEmptySubComposition(\n projectDir: string,\n rootHtml: string,\n): HyperframeLintFinding[] {\n // Dedup by src path — the same reference can appear from nested sub-comps.\n const checked = new Map<string, { srcPath: string; problem: string }>();\n const visited = new Set<string>();\n\n // fallow-ignore-next-line complexity\n const walk = (html: string): void => {\n const compositionSrcRe = /<[^>]*\\bdata-composition-src\\s*=\\s*[\"']([^\"']+)[\"'][^>]*>/gi;\n const scannable = maskNonScannableRanges(html);\n let match: RegExpExecArray | null;\n while ((match = compositionSrcRe.exec(scannable)) !== null) {\n const srcPath = (match[1] ?? \"\").trim();\n if (!srcPath) continue;\n if (isUnresolvedAssetPlaceholder(srcPath)) continue; // __UPPER__ placeholder or late-bound templating token\n\n // data-composition-src is always written root-relative (even from a\n // nested sub-composition) — matches the resolution the renderer uses\n // in packages/producer/src/services/htmlCompiler.ts (parseSubCompositions\n // / assertSubCompositionsUsable).\n const filePath = resolve(projectDir, srcPath);\n\n // Circular reference guard — same as assertSubCompositionsUsable.\n // Already-visited files were already checked (or are mid-walk); skip\n // re-checking/re-recursing but still let a later distinct reference to\n // the same broken file surface (checked is keyed by srcPath, not filePath).\n if (visited.has(filePath)) continue;\n visited.add(filePath);\n\n if (!existsSync(filePath)) {\n if (!checked.has(srcPath)) {\n checked.set(srcPath, { srcPath, problem: \"the file does not exist\" });\n }\n continue;\n }\n\n const fileHtml = readFileSync(filePath, \"utf-8\");\n const validity = checkSubCompositionUsability(fileHtml, parseSubCompHtml);\n if (!validity.ok) {\n if (!checked.has(srcPath)) {\n checked.set(srcPath, {\n srcPath,\n problem: validity.detail ?? \"the file is empty or could not be parsed\",\n });\n }\n continue;\n }\n\n // Usable — recurse into it so nested references are validated too,\n // but only because this file is itself reachable from the root.\n walk(fileHtml);\n }\n };\n\n walk(rootHtml);\n\n const findings: HyperframeLintFinding[] = [];\n for (const { srcPath, problem } of checked.values()) {\n findings.push({\n code: \"missing_or_empty_sub_composition\",\n severity: \"error\",\n message: `data-composition-src references \"${srcPath}\", but ${problem}.`,\n fixHint:\n `Fix this before rendering — the render pre-flight rejects unusable sub-compositions. ` +\n `Write valid HTML into \"${srcPath}\" — it needs a <template> or <body> containing an element with ` +\n `data-composition-id, data-width, and data-height. Preview/studio still tolerates and skips the ` +\n \"scene while you author it. If a scene-authoring step is still running, wait for it to finish \" +\n \"before referencing the file, or re-run the step that generates it.\",\n });\n }\n\n return findings;\n}\n\n/** True when the file's first element carries data-hf-snippet — i.e. the file\n * IS a mountable fragment, not a composition that merely contains one. */\nfunction isSnippetFragment(html: string): boolean {\n const firstTag = html.match(/<[a-zA-Z][^>]*>/);\n if (!firstTag) return false;\n return /\\bdata-hf-snippet\\b/.test(firstTag[0]);\n}\n","import { execFile } from \"node:child_process\";\nimport { rewriteAssetPath } from \"@hyperframes/parsers/asset-paths\";\nimport { findFfBinary } from \"@hyperframes/parsers/ff-binaries\";\nimport {\n cleanAssetUrl,\n isRemoteOrInlineUrl,\n isUnresolvedAssetPlaceholder,\n maskNonScannableRanges,\n resolveExistingLocalAsset,\n} from \"@hyperframes/parsers/asset-resolution\";\nimport type { HyperframeLintFinding } from \"./types.js\";\n\n/** Structurally compatible with `project.ts`'s (unexported) `HtmlSource` —\n * duplicated as a shape, not imported, to avoid a circular import between\n * this file and `project.ts` (which imports `lintHevcPreviewCodec` below). */\ninterface HtmlSourceLike {\n html: string;\n compSrcPath?: string;\n}\n\nconst PROBE_TIMEOUT_MS = 4000;\n// Bounds concurrent ffprobe child processes for compositions referencing many videos.\nconst PROBE_CONCURRENCY = 8;\n\nfunction execFileAsync(file: string, args: string[]): Promise<string> {\n return new Promise((resolvePromise, reject) => {\n execFile(file, args, { timeout: PROBE_TIMEOUT_MS }, (error, stdout) => {\n if (error) reject(error);\n else resolvePromise(stdout.toString());\n });\n });\n}\n\nfunction hasHevcStream(json: unknown): boolean {\n if (typeof json !== \"object\" || json === null) return false;\n const streams = Reflect.get(json, \"streams\");\n if (!Array.isArray(streams)) return false;\n return streams.some((stream) => {\n if (typeof stream !== \"object\" || stream === null) return false;\n return Reflect.get(stream, \"codec_name\") === \"hevc\";\n });\n}\n\n// Best-effort: any failure (ffprobe missing, times out, non-video file,\n// unparsable output) resolves to \"not HEVC\" rather than throwing. This rule\n// must never fail lint/check just because ffprobe isn't installed.\nasync function probeIsHevc(ffprobePath: string, filePath: string): Promise<boolean> {\n try {\n const stdout = await execFileAsync(ffprobePath, [\n \"-v\",\n \"error\",\n \"-select_streams\",\n \"v:0\",\n \"-show_entries\",\n \"stream=codec_name\",\n \"-of\",\n \"json\",\n filePath,\n ]);\n return hasHevcStream(JSON.parse(stdout));\n } catch {\n return false;\n }\n}\n\n/**\n * Collects local `<video src>` references, resolved to their absolute path\n * and deduped by that path — this is both the candidate set AND the in-run\n * probe cache for `lintHevcPreviewCodec` below: the same file referenced\n * twice only ends up as one map entry, so it's only probed once.\n *\n * Files that don't resolve to an existing local asset are skipped here —\n * `missing_local_asset` already reports those, and hevc_preview_codec never\n * probes a file that doesn't exist.\n */\n// fallow-ignore-next-line complexity\nexport function collectLocalVideoCandidates(\n projectDir: string,\n htmlSources: HtmlSourceLike[],\n): Map<string, string> {\n const candidates = new Map<string, string>();\n const videoSrcRe = /<video\\b[^>]*\\bsrc\\s*=\\s*[\"']([^\"']+)[\"'][^>]*>/gi;\n\n for (const { html, compSrcPath } of htmlSources) {\n const scannable = maskNonScannableRanges(html);\n const re = new RegExp(videoSrcRe.source, videoSrcRe.flags);\n let match: RegExpExecArray | null;\n while ((match = re.exec(scannable)) !== null) {\n const rawSrc = match[1] ?? \"\";\n // Placeholder check runs on the RAW value: cleanAssetUrl() splits on ?/# and would chop inside a ${...} token.\n if (isUnresolvedAssetPlaceholder(rawSrc)) continue;\n const src = cleanAssetUrl(rawSrc);\n if (!src) continue;\n if (isRemoteOrInlineUrl(src)) continue;\n const rootRelative = compSrcPath ? rewriteAssetPath(compSrcPath, src) : src;\n const resolvedAsset = resolveExistingLocalAsset(projectDir, rootRelative);\n if (!resolvedAsset) continue;\n if (!candidates.has(resolvedAsset.resolved)) candidates.set(resolvedAsset.resolved, src);\n }\n }\n\n return candidates;\n}\n\n/**\n * INFO-only finding: a locally referenced `<video>` file is encoded as\n * HEVC/H.265. The render pipeline pre-decodes video with FFmpeg (never the\n * browser decoder) so rendering is unaffected, but live preview and the\n * embeddable player play the file directly in-browser, where HEVC support\n * varies. Never escalated beyond \"info\" — this must not fail lint or check.\n *\n * `candidates` maps each unique resolved file path to a display src string\n * (already deduped by the caller, so each file is probed exactly once here);\n * files missing from disk are the caller's responsibility to have excluded —\n * `missing_local_asset` covers those and this rule never probes them.\n */\nexport async function lintHevcPreviewCodec(\n candidates: Map<string, string>,\n): Promise<HyperframeLintFinding[]> {\n if (candidates.size === 0) return [];\n\n const ffprobePath = findFfBinary(\"ffprobe\", { configuredMustExist: true });\n if (!ffprobePath) return [];\n\n const entries = [...candidates.entries()];\n const isHevc = new Array<boolean>(entries.length).fill(false);\n let nextIndex = 0;\n const workerCount = Math.min(PROBE_CONCURRENCY, entries.length);\n await Promise.all(\n Array.from({ length: workerCount }, async () => {\n while (nextIndex < entries.length) {\n const index = nextIndex++;\n const entry = entries[index];\n if (!entry) break;\n isHevc[index] = await probeIsHevc(ffprobePath, entry[0]);\n }\n }),\n );\n\n const hevcSrcs = entries.filter((_, i) => isHevc[i]).map(([, src]) => src);\n if (hevcSrcs.length === 0) return [];\n\n const unique = [...new Set(hevcSrcs)];\n return [\n {\n code: \"hevc_preview_codec\",\n severity: \"info\",\n message:\n `Video file(s) use the HEVC/H.265 codec: ${unique.join(\", \")}. ` +\n \"The render pipeline pre-decodes video with FFmpeg and never uses the browser's video decoder, so these render correctly. \" +\n \"Live preview/player playback automatically uses a cached H.264 proxy when the browser cannot decode HEVC. \" +\n \"If playback still fails, verify ffmpeg/ffprobe are installed and auto-proxying is enabled.\",\n fixHint:\n unique.length === 1\n ? `If \"${unique[0]}\" fails to play in preview, run hyperframes doctor and confirm media.autoProxy is not false.`\n : \"If these files fail to play in preview, run hyperframes doctor and confirm media.autoProxy is not false.\",\n },\n ];\n}\n"],"mappings":"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","names":["template","escapeRegExp","match","escapeRegExp","selector","postcss","postcss","rewriteAssetPath","cleanAssetUrl","isRemoteOrInlineUrl","isUnresolvedAssetPlaceholder","maskNonScannableRanges","resolveExistingLocalAsset","resolveExistingLocalAsset","rewriteAssetPath","isUnresolvedAssetPlaceholder","maskNonScannableRanges","cleanAssetUrl","isRemoteOrInlineUrl"]}