Files
blog/blog-admin/tools/probe-editor-detail.mjs
T
zqlit a74b3c7127
Deploy to Production / pre-check (push) Successful in 58s
Deploy to Production / build (push) Successful in 4m3s
Deploy to Production / deploy-edgeone (push) Successful in 3m48s
Deploy to Production / finalize (push) Successful in 26s
Deploy to Production / notify-failure (push) Skipped
归档 artalk-cf 评论后端 + rss-robot 到 blog-admin(含技术选型/模块分布 README)
2026-10-04 08:45:40 +08:00

68 lines
3.1 KiB
JavaScript

// 探查 svc-down 状态下编辑器内部的渲染细节
import { spawn } from 'node:child_process';
import { mkdtempSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
const CHROME = 'C:/Users/QunLIn/.agent-browser/browsers/chrome-154.0.8037.92/chrome.exe';
const PORT = 9404;
const URL_ = 'http://127.0.0.1:1313/comment.html';
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
const userDir = mkdtempSync(join(tmpdir(), 'cdp-probe-'));
const chrome = spawn(CHROME, [
'--headless=new', `--remote-debugging-port=${PORT}`, `--user-data-dir=${userDir}`,
'--no-first-run', '--disable-gpu', '--window-size=1280,1400', 'about:blank',
], { stdio: 'ignore' });
try {
for (let i = 0; i < 40; i++) {
try { const r = await fetch(`http://127.0.0.1:${PORT}/json/version`); if (r.ok) break; } catch { /* */ }
await sleep(300);
}
const tab = await (await fetch(`http://127.0.0.1:${PORT}/json/new?${encodeURIComponent(URL_)}`, { method: 'PUT' })).json();
const ws = new WebSocket(tab.webSocketDebuggerUrl);
let id = 0; const pending = new Map();
ws.addEventListener('message', (ev) => { const m = JSON.parse(ev.data); if (m.id && pending.has(m.id)) { pending.get(m.id)(m); pending.delete(m.id); } });
await new Promise((res) => ws.addEventListener('open', res));
const send = (method, params = {}) => new Promise((res) => { const mid = ++id; pending.set(mid, res); ws.send(JSON.stringify({ id: mid, method, params })); });
const ev = async (expr) => {
const r = await send('Runtime.evaluate', { expression: expr, returnByValue: true, awaitPromise: true });
return r.result?.result?.value ?? r.result?.value ?? null;
};
await send('Runtime.enable');
await sleep(9000);
console.log(await ev(`JSON.stringify((() => {
const ed = document.querySelector('.atk-main-editor');
if (!ed) return { err: 'no editor' };
const btn = ed.querySelector('.atk-send-btn, [class*=send]');
const ta = ed.querySelector('.atk-textarea');
const cs = (el) => {
if (!el) return null;
const s = getComputedStyle(el);
return { color: s.color, bg: s.backgroundColor, opacity: s.opacity, fontSize: s.fontSize,
filter: s.filter, visibility: s.visibility, display: s.display, content: (el.innerText||'').slice(0,20) };
};
return {
btnHtml: btn ? btn.outerHTML.slice(0, 200) : null,
btnStyle: cs(btn),
btnChildren: btn ? btn.children.length : 0,
taStyle: cs(ta),
placeholder: ta ? ta.getAttribute('placeholder') : null,
headerInputs: [...ed.querySelectorAll('input')].map(i => ({ cls: i.className, ph: i.placeholder, val: i.value.slice(0,10), display: getComputedStyle(i).display })),
editorChildren: [...ed.children].map(c => c.className),
mainEditorOpacity: getComputedStyle(ed).opacity,
mainEditorFilter: getComputedStyle(ed).filter,
artalkRootOpacity: getComputedStyle(document.querySelector('.artalk') || ed.closest('.artalk-container') || ed).opacity,
};
})())`, ));
ws.close();
} catch (e) {
console.error('ERROR', e.message);
} finally {
chrome.kill();
}