Files
ycode/scripts/capture-ycode-live.mjs

32 lines
3.4 KiB
JavaScript

// YCode-only live DOM/screenshot inspection. Original WorkBuddy must use REA instead.
import fs from 'node:fs/promises'
const targets = await (await fetch('http://127.0.0.1:9237/json/list')).json()
const setting = process.argv.includes('--settings')
const target = targets.find(item => item.type === 'page' && item.url.includes('window=settings') === setting)
if (!target) throw new Error('Requested YCode window not found')
const socket = new WebSocket(target.webSocketDebuggerUrl)
await new Promise(resolve => { socket.onopen = resolve })
let sequence = 0
const pending = new Map()
socket.onmessage = event => { const message = JSON.parse(event.data); const task = pending.get(message.id); if (task) { pending.delete(message.id); message.error ? task.reject(message.error) : task.resolve(message.result) } }
const send = (method, params = {}) => new Promise((resolve, reject) => { const id = ++sequence; pending.set(id, { resolve, reject }); socket.send(JSON.stringify({ id, method, params })) })
const evaluate = async expression => { const response = await send('Runtime.evaluate', { expression, returnByValue: true, awaitPromise: true }); if (response.exceptionDetails) throw new Error(response.exceptionDetails.text); return response.result.value }
const out = '.tmp/ycode-live-' + (setting ? 'settings' : 'main')
try {
await fs.mkdir(out, { recursive: true })
const viewportArgument = process.argv.find(value => value.startsWith('--viewport='))
if (viewportArgument) {
const match = /^--viewport=(\d+)x(\d+)$/.exec(viewportArgument)
if (!match || Number(match[1]) < 160 || Number(match[2]) < 160) throw new Error('Invalid viewport')
await send('Emulation.setDeviceMetricsOverride', { width: Number(match[1]), height: Number(match[2]), deviceScaleFactor: 1, mobile: false })
}
if (process.argv.includes('--home')) await evaluate(`Array.from(document.querySelectorAll('.sidebar__tab')).find(button=>button.textContent.includes('新建任务'))?.click()`)
await evaluate('document.fonts.ready.then(()=>true)')
await evaluate('new Promise(resolve=>setTimeout(resolve,1200))')
const layout = await evaluate(`(()=>{const selectors=['.sidebar','.chat-pane','.source-home','.wb-home-page','.wb-home-page__main-content','.wb-home-header','.wb-scene-tabs','.wb-home-composer','.wb-home-composer__chips','.wb-home-composer__input-slot','.wb-home-composer__below-input','.wb-composer','.cr-input-container','.wb-composer__workspace-footer','.cr-input-toolbar','.cr-permission-setting','.settings-modal','.settings-modal__nav','.settings-modal__content','.models-settings-panel','.models-settings-panel__editor','.sidebar-next'];return{viewport:{width:innerWidth,height:innerHeight},nodes:selectors.flatMap(selector=>Array.from(document.querySelectorAll(selector)).map(node=>{const box=node.getBoundingClientRect(),style=getComputedStyle(node);return{selector,bounds:[box.x,box.y,box.width,box.height],font:style.fontFamily,fontSize:style.fontSize,lineHeight:style.lineHeight,padding:style.padding,margin:style.margin,gap:style.gap,background:style.backgroundColor,display:style.display}}))}})()`)
await fs.writeFile(out + '/layout.json', JSON.stringify(layout, null, 2))
const screenshot = await send('Page.captureScreenshot', { format: 'png', fromSurface: true })
await fs.writeFile(out + '/screen.png', Buffer.from(screenshot.data, 'base64'))
console.log(JSON.stringify({ targetId: target.id, output: out, viewport: layout.viewport }))
} finally { socket.close() }