This commit is contained in:
seb
2026-10-11 13:44:34 +02:00
parent e8b2ead83f
commit 1e2f57e941
37 changed files with 386 additions and 584 deletions

View File

@@ -161,7 +161,7 @@ async function httpJson(url, options = {}) {
* Opens a new page target on the browser, navigates, waits for the app root
* to contain content + network to quiet down, captures a PNG.
*/
export async function capturePage(debugPort, url, file, { width, height, settleMs = 6000, dialog }) {
export async function capturePage(debugPort, url, file, { width, height, settleMs = 6000, dialog, icons }) {
// Chrome ≥136 requires PUT for /json/new.
const target = await httpJson(`http://127.0.0.1:${debugPort}/json/new?${encodeURIComponent(url)}`, {
method: 'PUT',
@@ -257,6 +257,55 @@ export async function capturePage(debugPort, url, file, { width, height, settleM
}
}
// Icon sheet: replace the page by a white sheet with every distinct icon
// (inline SVG) found on it, drawn in black.
if (icons) {
await session.send('Runtime.evaluate', {
expression: `(() => {
const seen = new Map();
for (const svg of document.querySelectorAll('svg')) {
const r = svg.getBoundingClientRect();
if (r.width > 64 || r.height > 64) continue; // skip illustrations / spinners
if (svg.closest('[role="progressbar"]')) continue;
const key = svg.getAttribute('data-testid') || svg.innerHTML;
if (!svg.innerHTML || seen.has(key)) continue;
seen.set(key, svg);
}
const style = document.createElement('style');
style.textContent = \`
#icon-sheet{position:absolute;inset:0;background:#fff;color:#000;padding:24px;
display:flex;flex-wrap:wrap;gap:20px;align-content:flex-start;font:11px sans-serif}
#icon-sheet .cell{width:144px;display:flex;flex-direction:column;align-items:center;gap:6px;text-align:center;word-break:break-all}
#icon-sheet svg{width:144px;height:144px;color:#000;fill:#000}
#icon-sheet svg *{fill:#000;color:#000}
#icon-sheet svg [stroke]:not([stroke=none]){stroke:#000}
\`;
document.head.appendChild(style);
document.getElementById('root').style.display = 'none';
const sheet = document.createElement('div');
sheet.id = 'icon-sheet';
const sorted = [...seen.entries()].sort((a, b) => String(a[0]).localeCompare(String(b[0])));
for (const [key, svg] of sorted) {
const cell = document.createElement('div');
cell.className = 'cell';
const clone = svg.cloneNode(true);
clone.removeAttribute('class');
clone.removeAttribute('style');
clone.removeAttribute('width');
clone.removeAttribute('height');
cell.appendChild(clone);
const label = document.createElement('span');
label.textContent = svg.getAttribute('data-testid') || '';
cell.appendChild(label);
sheet.appendChild(cell);
}
document.body.style.background = '#fff';
document.body.appendChild(sheet);
})()`,
});
await wait(300);
}
// Determinism: hide carets and scrollbars.
await session.send('Runtime.evaluate', {
expression: `(() => { const s = document.createElement('style');