- 기둥·말뚝 입력을 한 카드로 통합(공통 입력, 구간별 예외 보존, 횡철근 표) - 현장타설 실배근 · 삽도 · 수량을 화면에 연결하고 프로젝트 저장 · 복원 - 상단 헤더를 한 줄로 축약(상태 축약, 파일 메뉴, 말줄임) - 디자인 검토 반영(가져오기 범위, ③ 모델 높이 · 접기, 검토 항목 이동) - 화면 검증 스크립트(verify-unified-input · verify-design-fixes 등) 보관 Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
53 lines
3.0 KiB
JavaScript
53 lines
3.0 KiB
JavaScript
// Read the user's linked artifact in an isolated browser profile, without changing its content.
|
|
const fs = require('node:fs');
|
|
const path = require('node:path');
|
|
const out = path.resolve(__dirname, '../.verify/design-system-artifact-20261105');
|
|
fs.mkdirSync(out, { recursive: true });
|
|
async function inspect(target, name, screenshot) {
|
|
const ws = new WebSocket(target.webSocketDebuggerUrl);
|
|
await new Promise((resolve, reject) => { ws.onopen = resolve; ws.onerror = reject; });
|
|
let seq = 0;
|
|
const pending = new Map();
|
|
ws.onmessage = ({ data }) => {
|
|
const message = JSON.parse(data);
|
|
const wait = pending.get(message.id);
|
|
if (!wait) return;
|
|
clearTimeout(wait.timer); pending.delete(message.id);
|
|
if (message.error) wait.reject(new Error(JSON.stringify(message.error))); else wait.resolve(message.result);
|
|
};
|
|
const send = (method, params = {}) => new Promise((resolve, reject) => {
|
|
const id = ++seq;
|
|
const timer = setTimeout(() => { pending.delete(id); reject(new Error(`Timeout ${method}`)); }, 15000);
|
|
pending.set(id, { resolve, reject, timer });
|
|
ws.send(JSON.stringify({ id, method, params }));
|
|
});
|
|
try {
|
|
await send('Runtime.enable');
|
|
if (screenshot) {
|
|
await send('Page.enable');
|
|
await send('Emulation.setDeviceMetricsOverride', { width: 1600, height: 1000, deviceScaleFactor: 1, mobile: false });
|
|
await new Promise((resolve) => setTimeout(resolve, 6000));
|
|
}
|
|
const text = await send('Runtime.evaluate', { expression: 'document.body.innerText', returnByValue: true });
|
|
const html = await send('Runtime.evaluate', { expression: 'document.documentElement.outerHTML', returnByValue: true });
|
|
const frames = await send('Runtime.evaluate', { expression: '[...document.querySelectorAll("iframe")].map(f=>({src:f.src,title:f.title,srcdocLength:f.srcdoc.length}))', returnByValue: true });
|
|
fs.writeFileSync(path.join(out, `${name}.txt`), text.result?.value || '');
|
|
fs.writeFileSync(path.join(out, `${name}.html`), html.result?.value || '');
|
|
fs.writeFileSync(path.join(out, `${name}-frames.json`), JSON.stringify(frames.result?.value, null, 2));
|
|
console.log(JSON.stringify({ name, title: target.title, url: target.url, text: (text.result?.value || '').slice(0, 10000), frames: frames.result?.value }));
|
|
if (screenshot) {
|
|
const shot = await send('Page.captureScreenshot', { format: 'png' });
|
|
fs.writeFileSync(path.join(out, 'overview.png'), Buffer.from(shot.data, 'base64'));
|
|
}
|
|
} finally { ws.close(); }
|
|
}
|
|
(async () => {
|
|
let targets = await (await fetch('http://127.0.0.1:9444/json')).json();
|
|
const page = targets.find((target) => target.type === 'page' && target.url.includes('9LPwY9MMugHfvF5auhpVW2'));
|
|
if (!page) throw new Error('Linked artifact page not found');
|
|
await inspect(page, 'page', true);
|
|
targets = await (await fetch('http://127.0.0.1:9444/json')).json();
|
|
let index = 0;
|
|
for (const target of targets.filter((target) => target.type === 'iframe')) await inspect(target, `frame-${++index}`, false);
|
|
})().catch((error) => { console.error(error); process.exitCode = 1; });
|