Parent: #1076
Problem
StaticHtmlEmitter::emit() and emitSite() independently reset mutable state, normalize assets, extract design-system data, emit nodes, deduplicate CSS classes, resolve fonts, assemble files, and build diagnostics. Tests explicitly exercise fixes in both paths, demonstrating the maintenance burden.
Scope
- Introduce one internal emission lifecycle used by both public methods.
- Keep
emit() and emitSite() as stable public entrypoints.
- Represent single-page emission as input to the shared page/root emission implementation.
- Remove duplicated initialization and finalization code once behavior is shared.
Acceptance criteria
composer test passes.
- Existing single-page and multi-page HTML/CSS/assets/report contracts remain unchanged.
- Inline CSS defaults remain unchanged for each public entrypoint.
- Responsive variants, template aliases, link resolution, font handling, and diagnostic output retain current behavior.
- The parity assertions around both paths no longer require distinct implementation branches.
AI assistance
OpenAI gpt-5.6-sol via OpenCode identified the duplicated lifecycle and drafted this issue. Chris Huber is responsible for the scope and final changes.
Parent: #1076
Problem
StaticHtmlEmitter::emit()andemitSite()independently reset mutable state, normalize assets, extract design-system data, emit nodes, deduplicate CSS classes, resolve fonts, assemble files, and build diagnostics. Tests explicitly exercise fixes in both paths, demonstrating the maintenance burden.Scope
emit()andemitSite()as stable public entrypoints.Acceptance criteria
composer testpasses.AI assistance
OpenAI
gpt-5.6-solvia OpenCode identified the duplicated lifecycle and drafted this issue. Chris Huber is responsible for the scope and final changes.