Files
hyperframes/packages/cli/src/utils/compositionViewport.ts
T
JamesandClaude Opus 4.7 ec1b7e1eff feat(cli): warn when lambda --width/--height conflicts with composition
`--width 3840 --height 2160` against a composition with
`data-width="1920"` silently produces a 1080p output because the
runtime lays out the page at the composition's authored dimensions —
real footgun we hit during a cost-analysis sweep. Warn early and point
at `--output-resolution` (the supersampling escape hatch) so the user
doesn't burn a 30-minute render learning the override rule.

Skipped when `--output-resolution` is set (the supported supersampling
path — the user is opting in), when `--json` is set (machine consumers),
or when `index.html` isn't on disk (typical with `--site-id`).

Helper lives in a shared module so render + render-batch agree on the
parse + message. Tests cover both attribute orders, single/double
quotes, the silent paths, and the warning path. Best-effort regex over
the canonical attr shape — malformed HTML falls through to no warning
rather than blocking the render.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 16:41:56 -04:00

37 lines
1.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { ensureDOMParser } from "./dom.js";
const DEFAULT_VIEWPORT = { width: 1920, height: 1080 } as const;
const MAX_VIEWPORT_DIMENSION = 4096;
function parseViewportDimension(value: string | null): number | null {
if (!value) return null;
const parsed = Number.parseInt(value, 10);
if (!Number.isFinite(parsed) || parsed <= 0) return null;
return Math.min(parsed, MAX_VIEWPORT_DIMENSION);
}
/**
* Pull `data-width` + `data-height` from the document's first composition
* root (the element with `data-composition-id` plus both dimension attrs
* — the same selector the producer uses to lay out the page). Returns
* `null` when no such root exists or either attr is invalid, so callers
* can distinguish "no declared dimensions" from "declared 1920×1080".
*/
export function findCompositionDimensions(html: string): { width: number; height: number } | null {
ensureDOMParser();
const doc = new DOMParser().parseFromString(html, "text/html");
const root = doc.querySelector("[data-composition-id][data-width][data-height]");
if (!root) return null;
const width = parseViewportDimension(root.getAttribute("data-width"));
const height = parseViewportDimension(root.getAttribute("data-height"));
if (width === null || height === null) return null;
return { width, height };
}
export function resolveCompositionViewportFromHtml(html: string): {
width: number;
height: number;
} {
return findCompositionDimensions(html) ?? DEFAULT_VIEWPORT;
}