Files
site-builder/craft/scripts/e2e-capture-fidelity-entry.ts
T
shadowdaoandClaude Opus 5.5 4177e5015a fix(sitesmith): summarize nested (linkedNodes) nodes, explain dropped review ops, truly label-free bg placeholders
1. summarizeCanvas() walked only node.nodes, so everything inside Section/ColumnLayout/forms
   (linkedNodes) was missing and live self-reviews could only name top-level sections. It now
   walks nodes + linked slots (stable key order) and lists id, type and key props (text first,
   links, main style values as style.<key>, colour-like props) as key="value", within a
   documented budget (150 nodes, 6000 chars, 300 chars of props per line; detail is dropped
   before nodes; cuts happen at line boundaries -- a mid-line cut used to make the server
   refuse the whole review). HtmlBlock code is no longer summarised.
   applyPatch no longer counts an op with nothing left to set as a change; ops that did nothing
   are counted per reason. The self-review note and console say why ops were dropped (server
   and editor reasons, counts only). Real-browser test 8n builds a nested page, sends the real
   summary through the real WHP review lockdown (php) and checks the nested edit takes effect
   while link/text edits, unknown ids and deletes are dropped.
3. Background placeholders use ?text=%E2%80%8B (measured: placehold.co then draws no glyphs;
   the same-colour label left a 4-colour ghost in its PNG); the capture draws no <text> for a
   zero-width or same-colour label. Pixel test on the case-4 hero markup in both browsers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0185ukXgk6UunFCKyXqLe2Cq
2026-11-01 20:40:09 -08:00

26 lines
1.6 KiB
TypeScript

// Bundled by scripts/e2e-capture-fidelity.mjs and run in real Firefox + Chromium.
import { captureHtml } from '../src/utils/self-review-capture';
import { sanitizeCaptureHtml } from '../src/utils/sanitize-capture-html';
import { cleanAiProps } from '../src/sitesmith/clean-ai-response';
/** Round 6: the background URL the editor really stores for an AI hero placeholder (apply-time cleaner). */
(window as any).cleanedBgImage = (url: string) => cleanAiProps({ bgImage: url }, 'BackgroundSection').bgImage;
(window as any).sanitizeCaptureHtml = sanitizeCaptureHtml;
/** Capture through the real path, then decode the JPEG and return RGB samples at the given points. */
(window as any).captureAndSample = async (html: string, points: Array<[number, number]>) => {
const t0 = performance.now();
const r = await captureHtml(html, { settleMs: 200, injectFontAwesome: false });
const ms = Math.round(performance.now() - t0);
if (!r.ok) return { ok: false, reason: r.reason };
const url = URL.createObjectURL(r.blob);
const img = new Image();
await new Promise<void>((res, rej) => { img.onload = () => res(); img.onerror = () => rej(new Error('decode')); img.src = url; });
const c = document.createElement('canvas');
c.width = img.naturalWidth; c.height = img.naturalHeight;
const ctx = c.getContext('2d')!;
ctx.drawImage(img, 0, 0);
URL.revokeObjectURL(url);
return { ok: true, w: c.width, h: c.height, strips: r.strips, cropped: r.cropped, pageHeight: r.pageHeight, bytes: r.blob.size, ms, samples: points.map(([x, y]) => Array.from(ctx.getImageData(x, y, 1, 1).data.slice(0, 3))) };
};