36 lines
2.5 KiB
JavaScript
36 lines
2.5 KiB
JavaScript
// Recover only the avatar SVG from an already archived REA DOM observation.
|
|
import fs from 'node:fs/promises'
|
|
import crypto from 'node:crypto'
|
|
const sourceFile = '.tmp/rea-assessment-initial/layout.json'
|
|
const source = JSON.parse(await fs.readFile(sourceFile, 'utf8'))
|
|
const document = source.layout.documents[0]
|
|
const nodes = document.nodes, svg = document.svg_nodes
|
|
const logo = nodes.find(node => /\bcr-agent__logo\b/.test(node.attributes?.class ?? ''))
|
|
const root = svg.find(node => node.parent_index === logo?.node_index && node.node_name === 'svg')
|
|
if (!root || root.attributes.viewBox !== '0 0 24 24') throw Error('Expected REA avatar SVG missing')
|
|
const tree = node => ({ tag: node.node_name, attrs: node.attributes, children: svg.filter(child => child.parent_index === node.node_index).map(tree) })
|
|
const payload = tree(root), serialized = JSON.stringify(payload)
|
|
const payloadSha = crypto.createHash('sha256').update(serialized).digest('hex')
|
|
const code = `// Generated from WorkBuddy 5.8.2 REA ${source.evidenceId}.
|
|
// Avatar payload SHA256 ${payloadSha}; runtime SVG observation, not guessed artwork.
|
|
import { createElement, useId, type ReactNode } from 'react'
|
|
interface SvgNode { tag: string; attrs: Record<string, string>; children: SvgNode[] }
|
|
const sourceSvg: SvgNode = ${JSON.stringify(payload, null, 2)}
|
|
export default function SourceAgentAvatar(): React.JSX.Element {
|
|
const clipId = 'cr-agent-logo-clip-' + useId().replace(/[^a-zA-Z0-9_-]/g, '')
|
|
const render = (node: SvgNode, key = 'root'): ReactNode => {
|
|
const attrs = Object.fromEntries(Object.entries(node.attrs).map(([name, value]) => [
|
|
name === 'clip-path' ? 'clipPath' : name === 'fill-rule' ? 'fillRule' : name,
|
|
name === 'id' ? clipId : name === 'clip-path' ? 'url(#' + clipId + ')' : value
|
|
]))
|
|
return createElement(node.tag, { ...attrs, key, ...(key === 'root' ? { 'aria-hidden': true, style: { display: 'block' } } : {}) }, ...node.children.map((child, index) => render(child, key + ':' + index)))
|
|
}
|
|
return render(sourceSvg) as React.JSX.Element
|
|
}
|
|
`
|
|
const output = 'src/renderer/src/components/SourceAgentAvatar.tsx'
|
|
if (process.argv.includes('--check')) {
|
|
if (await fs.readFile(output, 'utf8') !== code) throw Error('Recovered avatar differs from fixed REA SVG')
|
|
} else await fs.writeFile(output, code)
|
|
console.log(JSON.stringify({ evidenceId: source.evidenceId, nodes: svg.filter(node => node.node_index >= root.node_index && node.node_index < root.node_index + 10).length, payloadSha, output, check: process.argv.includes('--check') }))
|