mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-11-01 00:27:20 -05:00
A pasted MD5, CRC32 or SHA256 of scph5501.bin goes through the search box's hash lookup to the card on the PlayStation page. 54 queries.
135 lines
6.5 KiB
JavaScript
135 lines
6.5 KiB
JavaScript
// Page weight and search measurements in a real browser.
|
|
// node measure.mjs weight <base url> <page>...
|
|
// node measure.mjs search <base url> starlight|mkdocs <query>...
|
|
// Transfer sizes are bytes on the wire (gzip from serve.mjs), by type.
|
|
// playwright-core is resolved from website/node_modules, above this file,
|
|
// wherever the command is run from. It is not a dependency of the build:
|
|
// npm install --no-save --prefix website playwright-core
|
|
const { chromium } = await import('playwright-core').catch((error) => {
|
|
console.error(`playwright-core is not in website/node_modules (${error.code}): `
|
|
+ 'npm install --no-save --prefix website playwright-core');
|
|
process.exit(2);
|
|
});
|
|
|
|
const [mode, base, ...rest] = process.argv.slice(2);
|
|
const browser = await chromium.launch({ executablePath: process.env.CHROME_PATH || '/usr/bin/google-chrome' });
|
|
|
|
const track = (page) => {
|
|
const rows = [];
|
|
page.on('response', async (response) => {
|
|
const request = response.request();
|
|
const headers = await response.allHeaders();
|
|
let bytes = Number(headers['content-length'] ?? 0);
|
|
if (!bytes) {
|
|
try { bytes = (await response.body()).length; } catch { bytes = 0; }
|
|
}
|
|
rows.push({ url: response.url(), type: request.resourceType(), bytes });
|
|
});
|
|
return rows;
|
|
};
|
|
|
|
const sum = (rows, test) => rows.filter(test).reduce((total, row) => total + row.bytes, 0);
|
|
|
|
if (mode === 'weight') {
|
|
for (const path of rest) {
|
|
const context = await browser.newContext({ viewport: { width: 390, height: 844 } });
|
|
const page = await context.newPage();
|
|
const rows = track(page);
|
|
await page.goto(new URL(path, base).href, { waitUntil: 'networkidle' });
|
|
await page.waitForTimeout(500);
|
|
const dom = await page.evaluate(() => document.getElementsByTagName('*').length);
|
|
const kb = (n) => (n / 1024).toFixed(1);
|
|
console.log(JSON.stringify({
|
|
page: path,
|
|
html_kb: kb(sum(rows, (r) => r.type === 'document')),
|
|
js_kb: kb(sum(rows, (r) => r.type === 'script')),
|
|
css_kb: kb(sum(rows, (r) => r.type === 'stylesheet')),
|
|
other_kb: kb(sum(rows, (r) => !['document', 'script', 'stylesheet'].includes(r.type))),
|
|
total_kb: kb(sum(rows, () => true)),
|
|
requests: rows.length,
|
|
dom_nodes: dom,
|
|
}));
|
|
await context.close();
|
|
}
|
|
} else if (mode === 'search') {
|
|
const [engine, ...queries] = rest;
|
|
const context = await browser.newContext({ viewport: { width: 1440, height: 900 } });
|
|
const page = await context.newPage();
|
|
const rows = track(page);
|
|
await page.goto(base, { waitUntil: 'networkidle' });
|
|
await page.waitForTimeout(500);
|
|
const before = rows.length;
|
|
const first = [];
|
|
for (const [n, query] of queries.entries()) {
|
|
const mark = rows.length;
|
|
let results;
|
|
if (engine === 'starlight-ui') {
|
|
// The reader's path: open the dialog, type, wait for the result list.
|
|
if (n === 0) await page.click('button[data-open-modal]');
|
|
const input = page.locator('dialog input[type="text"], dialog input[type="search"]').first();
|
|
await input.fill(query);
|
|
if (/^[0-9a-f]+$/.test(query) && [8, 32, 40, 64].includes(query.length)) {
|
|
// A pasted hash: the search offers "Look up this hash" first, and
|
|
// the lookup names the cards that hold the value. Its results
|
|
// are those cards.
|
|
const lookup = await page.waitForSelector('.rb-search-hash a', { timeout: 15000 });
|
|
const found = await context.newPage();
|
|
await found.goto(await lookup.evaluate((a) => a.href), { waitUntil: 'networkidle' });
|
|
await found.waitForFunction(() => /^Found|^No file/.test(document.getElementById('rb-file-lookup-status')?.textContent ?? ''), null, { timeout: 15000 });
|
|
results = await found.evaluate(() => {
|
|
const cards = [...document.querySelectorAll('#rb-file-lookup-result a')].filter((a) => a.textContent === 'Open its card');
|
|
return {
|
|
count: document.getElementById('rb-file-lookup-status')?.textContent ?? '',
|
|
top: cards.slice(0, 5).map((a) => `Open its card | ${new URL(a.href).pathname}${new URL(a.href).hash}`),
|
|
};
|
|
});
|
|
await found.close();
|
|
await page.waitForTimeout(300);
|
|
const transfer = sum(rows.slice(mark), () => true);
|
|
console.log(JSON.stringify({ query, transfer_kb: (transfer / 1024).toFixed(1), ...results }));
|
|
continue;
|
|
}
|
|
await page.waitForSelector('.pagefind-ui__result', { timeout: 15000 });
|
|
await page.waitForTimeout(1200);
|
|
results = await page.evaluate(() => {
|
|
const items = [...document.querySelectorAll('.pagefind-ui__result')];
|
|
return {
|
|
count: document.querySelector('.pagefind-ui__message')?.textContent ?? '',
|
|
top: items.slice(0, 5).map((r) => `${r.querySelector('.pagefind-ui__result-link')?.textContent?.trim()} | ${r.querySelector('.pagefind-ui__result-link')?.getAttribute('href')}`),
|
|
};
|
|
});
|
|
} else if (engine === 'starlight') {
|
|
results = await page.evaluate(async ({ query, root, ranking }) => {
|
|
if (!window.__pf) {
|
|
window.__pf = await import(`${root}pagefind/pagefind.js`);
|
|
if (ranking) await window.__pf.options({ ranking });
|
|
}
|
|
const search = await window.__pf.search(query);
|
|
const top = await Promise.all(search.results.slice(0, 5).map((r) => r.data()));
|
|
return { count: search.results.length, top: top.map((d) => `${d.meta.title} | ${d.url}`) };
|
|
}, { query, root: new URL('/retrobios/', base).href, ranking: process.env.RB_RANKING ? JSON.parse(process.env.RB_RANKING) : null });
|
|
} else {
|
|
// Material: open the search through its share link (?q=) and read the result list.
|
|
await page.goto(`${base}?q=${encodeURIComponent(query)}`, { waitUntil: 'networkidle' });
|
|
await page.waitForFunction(
|
|
(q) => document.querySelector('input[data-md-component="search-query"]')?.value === q
|
|
&& /matching|No matching/.test(document.querySelector('.md-search-result__meta')?.textContent ?? ''),
|
|
query, { timeout: 30000 },
|
|
);
|
|
await page.waitForTimeout(800);
|
|
results = await page.evaluate(() => {
|
|
const items = [...document.querySelectorAll('.md-search-result__item > a')];
|
|
const meta = document.querySelector('.md-search-result__meta')?.textContent ?? '';
|
|
return { count: meta, top: items.slice(0, 5).map((a) => `${a.querySelector('h1,h2')?.textContent?.trim()} | ${a.getAttribute('href')}`) };
|
|
});
|
|
}
|
|
await page.waitForTimeout(300);
|
|
const transfer = sum(rows.slice(mark), () => true);
|
|
if (n === 0) first.push(...rows.slice(before));
|
|
console.log(JSON.stringify({ query, transfer_kb: (transfer / 1024).toFixed(1), ...results }));
|
|
}
|
|
console.log(JSON.stringify({ first_search_kb: (sum(first, () => true) / 1024).toFixed(1), first_search_requests: first.length }));
|
|
await context.close();
|
|
}
|
|
await browser.close();
|