// Consume only previously captured REA artifacts; never access the installed original. import { readFile, writeFile, mkdir } from 'node:fs/promises' import { createHash } from 'node:crypto' import { parse } from '@babel/parser' import postcss from 'postcss' const output = 'src/renderer/src/workbuddy/workbench' await mkdir(output, { recursive: true }) const evidence = JSON.parse(await readFile('.tmp/rea-runtime-scripts.json', 'utf8')) if (evidence.evidence_id !== 'ev_717fa5e846e64d67ac19c8925d121bff632c0d3aefb3603b10858559cabb2dcb') throw Error('REA script Evidence changed') const specs = [ ['src-DwHViF_l.js', '1bae5ee8385485c61494aae6f09828a0cb1bb867b761a0761330ceb30aaff60d', ['CloseIcon']], ['src-Cng7axVa.js', '5ce8649e3bfac10aec1e63afee726ab45abaafc5aa7cc372892e20f3eba18c8b', ['FolderEntryIcon', 'ChangesEntryIcon', 'TerminalEntryIcon', 'BrowserEntryIcon']] ] const icons = [] for (const [file, sha, names] of specs) { const source = evidence.items.find(item => item.file_path.endsWith(file))?.source?.artifact?.text if (!source || createHash('sha256').update(source).digest('hex') !== sha) throw Error(`${file} hash changed`) const found = new Map() const visit = node => { if (!node || typeof node !== 'object') return if (node.type === 'FunctionDeclaration' && names.includes(node.id?.name)) found.set(node.id.name, source.slice(node.start, node.end).replace(/\(0,[A-Za-z0-9_$]+\.jsx\)/g, ' jsx')) for (const value of Object.values(node)) if (Array.isArray(value)) value.forEach(visit); else if (value && typeof value === 'object') visit(value) } visit(parse(source, { sourceType: 'module' })) for (const name of names) { const fn = found.get(name) if (!fn || !fn.includes('jsx(`svg`')) throw Error(`Missing pure SVG function ${name}`) icons.push(`export ${fn}`) } } await writeFile(`${output}/SourceWorkbenchIcons.tsx`, `// @ts-nocheck\n// Exact pure SVG functions recovered from REA ${evidence.evidence_id}.\nimport { jsx } from 'react/jsx-runtime'\n${icons.join('\n')}\n`) // Artifact list uses the shared solid file icon family, rather than emoji or extension badges. const fileIconNames = ['ArtifactDocSolidIcon', 'ArtifactSheetSolidIcon', 'ArtifactSlideSolidIcon', 'ArtifactPdfSolidIcon', 'ArtifactMarkdownSolidIcon', 'ArtifactHtmlSolidIcon', 'ArtifactCodeSolidIcon', 'ArtifactTextSolidIcon', 'ArtifactArchiveSolidIcon', 'ArtifactDrawioSolidIcon', 'ArtifactImageSolidIcon', 'ArtifactVideoSolidIcon', 'ArtifactAudioSolidIcon', 'ArtifactFolderSolidIcon', 'ArtifactUnknownSolidIcon'] const iconSource = evidence.items.find(item => item.file_path.endsWith('src-DPDj7_qD.js'))?.source?.artifact?.text if (!iconSource || createHash('sha256').update(iconSource).digest('hex') !== '747e41d215375e1214c366213aea7e077d85421923029c61cbb6e9562be58de0') throw Error('File icon source changed') const fileIcons = new Map() const findFileIcons = node => { if (!node || typeof node !== 'object') return if (node.type === 'AssignmentExpression' && node.left.type === 'Identifier' && fileIconNames.includes(node.left.name) && node.right.type === 'ArrowFunctionExpression') { const text = iconSource.slice(node.right.start, node.right.end).replace(/\(0,[A-Za-z0-9_$]+\.(jsx|jsxs)\)/g, ' $1') if (!/ (jsx|jsxs)\(`svg`/.test(text)) throw Error(`File icon is not a pure SVG ${node.left.name}`) fileIcons.set(node.left.name, `export const ${node.left.name}: (props?: Record) => React.JSX.Element = ${text}`) } for (const value of Object.values(node)) if (Array.isArray(value)) value.forEach(findFileIcons); else if (value && typeof value === 'object') findFileIcons(value) } findFileIcons(parse(iconSource, { sourceType: 'module' })) if (fileIcons.size !== fileIconNames.length) throw Error('File icon family incomplete') await writeFile(`${output}/SourceFileIcons.tsx`, `// @ts-nocheck\n// Pure solid SVGs from pinned REA ${evidence.evidence_id}, src-DPDj7_qD.js.\nimport { jsx, jsxs } from 'react/jsx-runtime'\n${[...fileIcons.values()].join('\n')}\n`) const cssSpecs = [ ['src-BPUOynUo.css', '02a85e652dd1be508ab2bcf1b67880c3673d4c47e50b2caea24ac205bfe8f879'], ['src-DYMqy4oz.css', '420035cb969d5577ca19bf6d7b4e44f670580b51ec8987b6138728eb0416e060'] ] const selected = postcss.root() let count = 0 function filter(node) { if (node.type === 'rule') { if (!/sidebar-next|artifact-tab|detail-new-tab|detail-layout|detail-main|detail-panel|detail-sidebar|fc-sidebar|fc-file|file-tree|cb-overview-artifact/.test(node.selector)) return null count++; return node.clone() } if (node.type !== 'atrule') return null const result = node.clone({ nodes: [] }) for (const child of node.nodes ?? []) { const match = filter(child); if (match) result.append(match) } return result.nodes.length ? result : null } for (const [file, sha] of cssSpecs) { const text = await readFile(`.tmp/rea-css-recovered/${file}`, 'utf8') if (createHash('sha256').update(text).digest('hex') !== sha) throw Error(`${file} hash changed`) for (const node of postcss.parse(text).nodes) { const match = filter(node); if (match) selected.append(match) } } await writeFile(`${output}/workbench-source.css`, `/* Exact rule bodies and parent conditions. REA ev_377c8790468b3c67dad8577aabb327f98d3140659f0fffdbabfcff5a40cc9e94. */\n${selected.toString()}\n`) console.log(`Recovered ${icons.length} entry SVGs, ${fileIcons.size} solid file SVGs and ${count} source rules with at-rule ancestry preserved`)