// Recover the Grid drawer classes, not the unrelated wb-drawer component. import { readFile, writeFile } from 'node:fs/promises' import { createHash } from 'node:crypto' import { resolve } from 'node:path' import postcss from 'postcss' const runtimeEvidenceId = 'ev_717fa5e846e64d67ac19c8925d121bff632c0d3aefb3603b10858559cabb2dcb' const runtimeFile = 'src-0FGg1seX.js' const runtimeSha256 = 'f2c6dbae949041b4e2bb456e8a23ae2837f2d7893ac24bf471485f77c7b15178' const cssEvidenceId = 'ev_377c8790468b3c67dad8577aabb327f98d3140659f0fffdbabfcff5a40cc9e94' const cssFile = 'src-CBaV_A3S.css' const cssSha256 = '2090ed21045c8f8b0fc388d76424c8751bf18fcd065cbbd5d0ef485163a2e36c' const hash = value => createHash('sha256').update(value).digest('hex') const runtime = JSON.parse(await readFile(resolve('.tmp/rea-runtime-scripts.json'), 'utf8')) if (runtime.evidence_id !== runtimeEvidenceId) throw new Error('Fixed runtime Evidence changed') const matching = runtime.items.filter(item => item.file_path?.replaceAll('\\', '/').endsWith(`/renderer/assets/${runtimeFile}`)) if (matching.length !== 1 || hash(matching[0].source.artifact.text) !== runtimeSha256 || matching[0].source.artifact.sha256 !== runtimeSha256) throw new Error('Grid drawer runtime SHA-256 mismatch') const runtimeText = matching[0].source.artifact.text for (const marker of ['drawerBackdrop:', 'gridViewDrawerItem:', 'drawerItemFullScreen:', 'showBackdrop!==!1', '--drawer-animation-duration', 'animationDuration??300']) { if (!runtimeText.includes(marker)) throw new Error(`Missing Grid drawer source marker ${marker}`) } const directory = resolve('.tmp/rea-css-recovered') const manifest = JSON.parse(await readFile(resolve(directory, 'manifest.json'), 'utf8')) if (manifest.sourceEvidenceId !== cssEvidenceId || manifest.files.find(file => file.file === cssFile)?.sha256 !== cssSha256) throw new Error('Fixed Grid CSS manifest changed') const sourceText = await readFile(resolve(directory, cssFile), 'utf8') if (hash(sourceText) !== cssSha256) throw new Error('Grid drawer CSS SHA-256 mismatch') const source = postcss.parse(sourceText) const result = postcss.root() let count = 0 const declarations = [] function selected(selector) { return /\._(?:drawer|gridViewDrawer)[\w]*_11lon_/.test(selector) } function project(node) { if (node.type === 'rule') { const selectors = node.selectors.filter(selected) if (!selectors.length) return null for (const selector of selectors) for (const match of selector.matchAll(/\.([\w]+_11lon_\d+)/g)) { if (!runtimeText.includes(match[1])) throw new Error(`CSS class absent from fixed runtime: ${match[1]}`) } const conditions = [] let ancestor = node.parent while (ancestor) { if (ancestor.type === 'atrule') conditions.unshift(`@${ancestor.name} ${ancestor.params}`); ancestor = ancestor.parent } declarations.push({ selectors, bodySha256: hash(node.nodes.map(child => child.toString()).join(';')), conditions }) count++ return node.clone({ selector: selectors.map(selector => `.source-detail-layout ${selector}`).join(',') }) } if (node.type === 'atrule' && node.nodes && !/keyframes$/.test(node.name)) { const children = node.nodes.map(project).filter(Boolean) return children.length ? node.clone({ nodes: children }) : null } return null } for (const node of source.nodes) { const projected = project(node); if (projected) result.append(projected) } if (count !== 15) throw new Error(`Expected 15 source Grid drawer rules, found ${count}`) if (declarations.some(rule => rule.conditions.length)) throw new Error('Grid drawer source conditions changed; review before adapting') const text = `/* Generated by scripts/rea/recover-drawer-motion.mjs from fixed WorkBuddy 5.8.2 REA Evidence. * JSX: ${runtimeEvidenceId}; ${runtimeFile} sha256=${runtimeSha256}. * CSS: ${cssEvidenceId}; ${cssFile} sha256=${cssSha256}. * Original 15 Grid drawer rule bodies/order preserved; scope is .source-detail-layout. * Drawer/backdrop: var(--drawer-animation-duration,.3s) ease-out; source has no reduced-motion media override. * The host can set --drawer-animation-duration:0ms for reduced-motion without modifying these source declarations. * This file intentionally contains Grid classes; wb-drawer is a different component. */\n${result.toString()}\n` const target = resolve('src/renderer/src/workbuddy/workbench/drawer-motion-source.css') if (process.argv.includes('--check')) { if (await readFile(target, 'utf8') !== text) throw new Error('Grid drawer CSS differs from fixed source recovery') } else await writeFile(target, text) const report = { version: '5.8.2', runtimeEvidenceId, runtimeFile, runtimeSha256, cssEvidenceId, cssFile, cssSha256, rules: count, sourceDeclarations: declarations, outputSha256: hash(text), reducedMotionOverrideInSource: false, check: process.argv.includes('--check') } if (!process.argv.includes('--check')) await writeFile(resolve('.tmp/drawer-motion-source-report.json'), JSON.stringify(report, null, 2)) console.log(JSON.stringify({ ...report, sourceDeclarations: undefined }))