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>
This commit is contained in:
James
2026-05-22 16:41:56 -04:00
committed by James Russo
co-authored by Claude Opus 4.7
parent d4384722e8
commit ec1b7e1eff
5 changed files with 189 additions and 9 deletions
+19 -9
View File
@@ -10,17 +10,27 @@ function parseViewportDimension(value: string | null): number | 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;
} {
ensureDOMParser();
const doc = new DOMParser().parseFromString(html, "text/html");
const root = doc.querySelector("[data-composition-id][data-width][data-height]");
const width = parseViewportDimension(root?.getAttribute("data-width") ?? null);
const height = parseViewportDimension(root?.getAttribute("data-height") ?? null);
return {
width: width ?? DEFAULT_VIEWPORT.width,
height: height ?? DEFAULT_VIEWPORT.height,
};
return findCompositionDimensions(html) ?? DEFAULT_VIEWPORT;
}