119 lines
3.7 KiB
JavaScript
119 lines
3.7 KiB
JavaScript
import './wb-legacy-disabled.mjs'
|
|
|
|
/**
|
|
* 从真实 WorkBuddy 页面导出图标(SVG)+ 关键按钮的完整标记。
|
|
*
|
|
* 用法:node scripts/wb-icons.mjs <port> [outFile]
|
|
*/
|
|
|
|
import { writeFile } from 'node:fs/promises'
|
|
|
|
const port = Number(process.argv[2] ?? 9223)
|
|
const outFile = process.argv[3] ?? null
|
|
|
|
/** 每个条目:名字 → 定位表达式(点击目标或图标宿主) */
|
|
const TARGETS = [
|
|
// 侧栏顶部
|
|
['brand', '.conversation-list-logo'],
|
|
['templates', '.industry-template-switcher__host button'],
|
|
['newTask', '.conversation-list-tabs .conversation-list-tab-button'],
|
|
// 侧栏顶栏操作
|
|
['topbarBack', '.conversation-list-topbar-actions button'],
|
|
['topbarFilter', '.conversation-list-task-filter-trigger'],
|
|
// 分组操作
|
|
['sectionCompact', '.conversation-section-compact-btn'],
|
|
['sectionAdd', '.conversation-section-add-btn'],
|
|
['sectionChevron', '.conversation-section-chevron'],
|
|
// 对话区
|
|
['artifactActions', '.artifact-slot-panel__actions'],
|
|
// 输入区
|
|
['inputToolbarLeft', '.cr-input-toolbar__left'],
|
|
['inputToolbarRight', '.cr-input-toolbar__right'],
|
|
['sendButton', '.cr-send-button'],
|
|
// 右侧面板
|
|
['tabIcon', '.artifact-tab__icon'],
|
|
['tabClose', '.artifact-tab__close'],
|
|
['tabsAdd', '.artifact-tabs__add'],
|
|
['panelActions', '.sidebar-next-main-header__actions']
|
|
]
|
|
|
|
async function main() {
|
|
const list = await (await fetch(`http://127.0.0.1:${port}/json/list`)).json()
|
|
const page = list.filter((t) => t.type === 'page' && !/windowKind=/.test(t.url))[0]
|
|
if (!page) {
|
|
console.error('未找到主页面目标')
|
|
process.exit(1)
|
|
}
|
|
|
|
const ws = new WebSocket(page.webSocketDebuggerUrl)
|
|
await new Promise((resolve, reject) => {
|
|
const timer = setTimeout(() => reject(new Error('连接超时')), 10000)
|
|
ws.addEventListener('open', () => {
|
|
clearTimeout(timer)
|
|
resolve()
|
|
})
|
|
ws.addEventListener('error', () => {
|
|
clearTimeout(timer)
|
|
reject(new Error('连接失败'))
|
|
})
|
|
})
|
|
|
|
const send = (method, params = {}) =>
|
|
new Promise((resolve, reject) => {
|
|
const id = Math.floor(Math.random() * 1e9)
|
|
const timer = setTimeout(() => reject(new Error(`超时 ${method}`)), 20000)
|
|
const handler = (ev) => {
|
|
const msg = JSON.parse(ev.data)
|
|
if (msg.id === id) {
|
|
clearTimeout(timer)
|
|
ws.removeEventListener('message', handler)
|
|
resolve(msg.result)
|
|
}
|
|
}
|
|
ws.addEventListener('message', handler)
|
|
ws.send(JSON.stringify({ id, method, params }))
|
|
})
|
|
|
|
const expression = `(() => {
|
|
const TARGETS = ${JSON.stringify(TARGETS)};
|
|
const out = {};
|
|
for (const [name, sel] of TARGETS) {
|
|
const el = document.querySelector(sel);
|
|
if (!el) { out[name] = null; continue; }
|
|
const svgs = [...el.querySelectorAll('svg')].map(s => s.outerHTML);
|
|
out[name] = {
|
|
selector: sel,
|
|
text: (el.textContent || '').replace(/\\s+/g, ' ').trim().slice(0, 60),
|
|
svgCount: svgs.length,
|
|
svgs,
|
|
html: el.outerHTML.slice(0, 3000)
|
|
};
|
|
}
|
|
return JSON.stringify(out);
|
|
})()`
|
|
|
|
const res = await send('Runtime.evaluate', { expression, returnByValue: true })
|
|
const data = JSON.parse(res.result.value)
|
|
|
|
for (const [name, info] of Object.entries(data)) {
|
|
if (!info) {
|
|
console.log(`### ${name}: 未找到`)
|
|
continue
|
|
}
|
|
console.log(`### ${name} (svg=${info.svgCount}) "${info.text}"`)
|
|
for (const s of info.svgs) console.log(' ', s.slice(0, 400))
|
|
console.log('')
|
|
}
|
|
|
|
if (outFile) {
|
|
await writeFile(outFile, JSON.stringify(data, null, 2), 'utf8')
|
|
console.log('已写出', outFile)
|
|
}
|
|
ws.close()
|
|
}
|
|
|
|
main().catch((err) => {
|
|
console.error('失败:', err.message)
|
|
process.exit(1)
|
|
})
|