Files
site-builder/craft/scripts/e2e-legacy-grid-entry.ts
shadowdaoandClaude Opus 5.5 96670b94f8 Legacy grids: published head stacks pre-hook card grids on phones (no re-save)
Stored pages (generated at editor-save time) from before release 2026.11.5 carry
FeaturesGrid / Testimonials / NumberCounter grids without data-wsb-grid, so a
republish kept repeat(N,1fr) on phones (OLS home: body 594px wide at 360).
The <=767px block now matches the exact inline styles those emitters stored
(whole-attribute signatures; no spaces, as in git history and every stored
OLS/TTM page). Gallery shares the prefix with a free gap and keeps its columns:
the two colliding signatures carry :not(:has(> * > Gallery thumbnail)) in their
own rule (a browser without :has drops only that rule). Customer grids never
match. Mirrored byte-for-byte by WHP generateCompiledHTML (fix/legacy-grid-backend).

Tests: vitest selector contract (legacy shapes match, == current emitters minus
the hook, Gallery and customer grids never match, pretty == minified); head
parity pins updated; new real-browser suite test:browser:legacy-grid (Chromium +
Firefox, 360/390/768/1280) on the stored OLS home page + synthetic legacy grids;
colors suite folds the new rules back like the mobile-guard ones.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 16:26:11 -08:00

52 lines
3.5 KiB
TypeScript

// Bundled (browser IIFE) by scripts/e2e-legacy-grid.mjs. Builds published documents from LEGACY stored HTML
// (pages saved before the data-wsb-grid hook existed) wrapped in the REAL Preview/publish head
// (exportComposedPreviewHtml: header + page + footer, as WHP handlePublish composes them; the head is byte-identical
// to WHP generateCompiledHTML, pinned on both sides by the head-parity tests).
import { exportBodyHtml, exportComposedPreviewHtml, RESPONSIVE_CSS_MINIFIED } from '../src/utils/html-export';
import { componentResolver } from '../src/components/resolver';
import olsHeader from '../tests/fixtures/legacy-grid/ols.header.html';
import olsIndex from '../tests/fixtures/legacy-grid/ols.index.html';
import olsFooter from '../tests/fixtures/legacy-grid/ols.footer.html';
import olsDesign from '../tests/fixtures/legacy-grid/ols.design.json';
type N = Record<string, any>;
const EMPTY = JSON.stringify({ ROOT: { type: { resolvedName: 'Container' }, isCanvas: true, props: { tag: 'div', style: {} }, displayName: 'Container', custom: {}, hidden: false, nodes: [], linkedNodes: {} } });
const defaults = (type: string): Record<string, unknown> => {
const c = (componentResolver as any)[type];
return c?.craft?.props ? JSON.parse(JSON.stringify(c.craft.props)) : {};
};
const node = (type: string, props: Record<string, unknown>, extra: N = {}) => ({
type: { resolvedName: type }, isCanvas: type === 'Container', props: { ...defaults(type), ...props }, displayName: type,
custom: {}, hidden: false, nodes: [], linkedNodes: {}, ...extra,
});
const stripHook = (html: string) => html.replace(/ data-wsb-grid(="")?/g, '');
const doc = (body: string, title: string) => exportComposedPreviewHtml(EMPTY, body, { title, design: olsDesign as any });
/** Every card-grid emitter in its stored (pre-hook) form, Galleries whose gap collides with a card-grid
* signature, and an unwrapped customer grid (legacy HtmlBlock content has no data-wsb-html wrapper). */
function synthetic(): string {
const nodes: N = {};
const kids: string[] = [];
const add = (id: string, type: string, props: Record<string, unknown> = {}) => { nodes[id] = node(type, props, { parent: 'ROOT' }); kids.push(id); };
add('features', 'FeaturesGrid');
add('t2', 'Testimonials', { columns: 2 });
add('t3', 'Testimonials');
add('t4', 'Testimonials', { columns: 4 });
add('counter', 'NumberCounter', { columns: 4 });
add('gal', 'Gallery');
add('gal32', 'Gallery', { columns: 3, gap: '32px', lightbox: true });
add('gal24', 'Gallery', { columns: 4, gap: '24px' });
nodes.ROOT = node('Container', { tag: 'div', style: {} }, { nodes: kids });
const body = stripHook(exportBodyHtml(JSON.stringify(nodes)).html);
const customer = '<div id="customer" style="padding:16px"><div style="display:grid;grid-template-columns:repeat(3,1fr);gap:32px"><div>One</div><div>Two</div><div>Three</div></div></div>';
return olsHeader + '\n' + body + customer + '\n' + olsFooter;
}
(window as any).wsbLegacyGridDocs = (): Record<string, string> => ({
ols: doc(olsHeader + '\n' + olsIndex + '\n' + olsFooter, 'Home'),
// The same page as a re-save in 2026.11.5 would store it (hook added): phones must look identical.
olsResaved: doc(olsHeader + '\n' + olsIndex.replace('<div style="max-width:1100px;margin:0 auto;display:grid;', '<div data-wsb-grid style="max-width:1100px;margin:0 auto;display:grid;') + '\n' + olsFooter, 'Home'),
synthetic: doc(synthetic(), 'Legacy grids'),
});
(window as any).wsbResponsiveCss = RESPONSIVE_CSS_MINIFIED;