chore: establish YCode replication baseline and TODO
This commit is contained in:
commit
6dc59f89ba
1118 files changed
+196002
No files matched your search
@@ -0,0 +1,83 @@
|
||||
// Project rules from already-exported REA CSS. Never accesses WorkBuddy.
|
||||
import fs from 'node:fs/promises'
|
||||
import path from 'node:path'
|
||||
import crypto from 'node:crypto'
|
||||
import postcss from 'postcss'
|
||||
|
||||
const directory = path.resolve('.tmp/rea-css-recovered')
|
||||
const manifest = JSON.parse(await fs.readFile(path.join(directory, 'manifest.json'), 'utf8'))
|
||||
const destination = path.resolve('src/renderer/src/workbuddy/conversation/source-styles.css')
|
||||
const families = /\.(?:cr-(?:frame|agent|self-|user-content|collapse|reasoning|tool-exp|tool-head|message-list|document|toolbar|icon-button|text-block)|cb-plan-|cb-exploration-status|conversation-timeline|conversation-high-credit-approval)/
|
||||
const output = postcss.root()
|
||||
const selected = []
|
||||
for (const filename of ['src-CBaV_A3S.css', 'src-CyXHA0IC.css', 'contexts-BkjwYSZT.css']) {
|
||||
const metadata = manifest.files.find(file => file.file === filename)
|
||||
if (!metadata) throw new Error(`REA CSS not captured: ${filename}`)
|
||||
const bytes = await fs.readFile(path.join(directory, filename))
|
||||
if (crypto.createHash('sha256').update(bytes).digest('hex') !== metadata.sha256) throw new Error(`REA CSS digest mismatch: ${filename}`)
|
||||
const source = postcss.parse(bytes, { from: filename })
|
||||
let rules = 0
|
||||
function project(node) {
|
||||
if (node.type === 'rule') {
|
||||
const selectors = node.selectors ?? []
|
||||
const actionMap = { '._assistantFeedback_1jhpu_1': '.msg--assistant .wb-message-actions', '._copyButton_1ncbp_1': '.wb-message-action[data-action=copy]', '._ratingButton_13zum_7': '.wb-message-action[aria-pressed]', '._actionButton_jnle9_7': '.wb-message-action[data-action=regenerate]', '._iconOnly_jnle9_27': '.wb-message-action' }
|
||||
const actionSelectors = selectors.filter(selector => /\._(?:assistantFeedback_1jhpu_1|copyButton_1ncbp_1|ratingButton_13zum_7|actionButton_jnle9_7)/.test(selector)).map(selector => {
|
||||
for (const [from, to] of Object.entries(actionMap)) selector = selector.replaceAll(from, to)
|
||||
return selector
|
||||
})
|
||||
if (actionSelectors.length) { rules++; return node.clone({ selector: actionSelectors.join(',') }) }
|
||||
const userProjection = {
|
||||
'._editable_1cxd2_1': '.chat-pane .yc-user-editable',
|
||||
'._editable_1cxd2_1 *': '.chat-pane .yc-user-editable *',
|
||||
'._editable_1cxd2_1 p': '.chat-pane .yc-user-editable p',
|
||||
'._editable_1cxd2_1 span': '.chat-pane .yc-user-editable span',
|
||||
'._editable_1cxd2_1 [data-slate-node=text]': '.chat-pane .yc-user-leaf',
|
||||
'._editable_1cxd2_1[contenteditable=false] p': '.chat-pane .yc-user-editable p',
|
||||
'._editable_1cxd2_1[contenteditable=false] [data-slate-node=text]': '.chat-pane .yc-user-leaf',
|
||||
'._editable_1cxd2_1[contenteditable=false] [data-slate-leaf=true]': '.chat-pane .yc-user-leaf > span',
|
||||
'._editable_1cxd2_1[contenteditable=false] [data-slate-string=true]': '.chat-pane .yc-user-leaf > span',
|
||||
}
|
||||
const projected = selectors.filter(selector => userProjection[selector]).map(selector => userProjection[selector])
|
||||
if (projected.length) { rules++; return node.clone({ selector: [...new Set(projected)].join(',') }) }
|
||||
let theme
|
||||
if (selectors.includes(':root')) theme = '.chat-pane.cr-theme'
|
||||
else if (selectors.includes('.light') || selectors.includes(':root.light') || selectors.includes('.cr-theme[data-cr-theme=light]')) theme = '.chat-pane.cr-theme[data-cr-theme=light]'
|
||||
else if (selectors.includes('.dark') || selectors.includes(':root.dark') || selectors.includes('.cr-theme[data-cr-theme=dark]')) theme = '.chat-pane.cr-theme[data-cr-theme=dark]'
|
||||
if (theme) {
|
||||
const declarations = node.nodes.filter(d => d.type === 'decl' && d.prop.startsWith('--') && !/^--(?:wb-font-(?:size|line-height)-|cb-md-root$)/.test(d.prop))
|
||||
if (!declarations.length) return
|
||||
rules++
|
||||
return postcss.rule({ selector: theme, nodes: declarations.map(d => d.clone()) })
|
||||
}
|
||||
const relevant = selectors.filter(selector => families.test(selector) && !/hydration|virtual-|share-mode|loading-more/.test(selector))
|
||||
if (!relevant.length) return
|
||||
rules++
|
||||
return node.clone({ selector: relevant.join(',') })
|
||||
}
|
||||
if (node.type === 'atrule' && /keyframes$/.test(node.name)) return
|
||||
if (node.type === 'atrule' && node.nodes) {
|
||||
const children = node.nodes.map(project).filter(Boolean)
|
||||
if (children.length) return node.clone({ nodes: children })
|
||||
}
|
||||
}
|
||||
for (const node of source.nodes) {
|
||||
const result = project(node)
|
||||
if (result) output.append(result)
|
||||
}
|
||||
const animations = []
|
||||
output.walkDecls(d => { if (/^animation(?:-name)?$/.test(d.prop)) animations.push(d.value) })
|
||||
source.walkAtRules(/keyframes$/, node => {
|
||||
if (animations.some(value => value.split(/[\s,]+/).includes(node.params))) output.append(node.clone())
|
||||
})
|
||||
selected.push({ file: filename, sha256: metadata.sha256, asarComparison: metadata.asarComparison?.status ?? 'not-compared', rules })
|
||||
}
|
||||
const header = `/* Generated by recover-conversation-styles.mjs from REA ${manifest.sourceEvidenceId}.
|
||||
* Original selected rule bodies and conditional ancestors are preserved.
|
||||
* Readonly user-editor selectors are projected onto static paragraph/leaf wrappers.
|
||||
* Global theme declarations are scoped to .chat-pane; font-size controls remain inherited.
|
||||
* Runtime/ASAR mismatches remain recorded in the source manifest.
|
||||
*/\n`
|
||||
await fs.writeFile(destination, header + output.toString() + '\n')
|
||||
const record = { evidenceId: manifest.sourceEvidenceId, selected, destination, transformations: ['Theme selector scope only; custom-property values preserved.', 'Only listed conversation families selected; unimplemented virtualization excluded.', 'Conditional at-rule ancestors and animation keyframes retained.'] }
|
||||
await fs.writeFile(path.join(directory, 'conversation-projection.json'), JSON.stringify(record, null, 2) + '\n')
|
||||
console.log(JSON.stringify(record, null, 2))
|
||||
Reference in new issue
Block a user