71 lines
5.0 KiB
JavaScript
71 lines
5.0 KiB
JavaScript
// 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 }))
|