Skip to content

fix(lint): catch visible css before composition root#1751

Merged
miguel-heygen merged 1 commit into
mainfrom
fix/lint-css-between-head-body
Jun 26, 2026
Merged

fix(lint): catch visible css before composition root#1751
miguel-heygen merged 1 commit into
mainfrom
fix/lint-css-between-head-body

Conversation

@miguel-heygen

Copy link
Copy Markdown
Collaborator

Summary

  • extend head_leaked_text so it also scans the </head><body> boundary and the body prefix before the first composition root
  • catch visible CSS/code leaks that browsers render as text when malformed generated HTML places CSS outside <style>
  • add regression coverage for CSS rules, CSS at-rules, markdown fences, stray close tags, missing explicit <body>, and negative cases for valid style/script blocks and in-root code samples

Why

A generated composition can be browser-parseable while still visibly rendering leaked CSS text before the actual HyperFrames composition root. The previous lint rule only inspected content inside <head>...</head>, so CSS emitted after </head> but before <body> was missed and could become visible in preview/render output.

I tested general-purpose validators while investigating:

  • parse5 parses like browsers and returned no parse errors for the malformed boundary case, so it is too permissive for this video-composition contract.
  • html-validate / htmlhint either missed the boundary leak or produced unrelated document-style noise under practical configs.
  • markuplint can catch some orphan-end-tag shapes, but does not catch CSS text before the composition root after <body>.
  • v.Nu is better suited as optional CI/developer validation, but it requires Java or a separate binary and is too heavy for the hot lint path.

The root contract here is HyperFrames-specific: no CSS/code-looking text may be visible before the composition root unless it is inside a non-rendered/valid block.

Verification

  • bun --filter @hyperframes/core test -- src/lint/rules/core.test.ts — 40 tests passed
  • bun --filter @hyperframes/core test -- src/lint/rules — 251 tests passed
  • bun --filter @hyperframes/core test — 2138 passed, 5 skipped, 3 todo
  • verified the real malformed generated HTML now returns one head_leaked_text error with the leaked body { ... } snippet
  • pre-commit: lint, format, fallow, typecheck passed

@miguel-heygen miguel-heygen merged commit c7830b5 into main Jun 26, 2026
49 checks passed
@miguel-heygen miguel-heygen deleted the fix/lint-css-between-head-body branch June 26, 2026 22:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant