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,156 @@
|
||||
import assert from 'node:assert/strict'
|
||||
import { readFile } from 'node:fs/promises'
|
||||
import { createHash } from 'node:crypto'
|
||||
import { execFileSync } from 'node:child_process'
|
||||
import { parse } from '@babel/parser'
|
||||
import postcss, { type Rule } from 'postcss'
|
||||
import {
|
||||
Rw, zw, Bw, Vw, JQe, DETAIL_NARROW_WIDTH, SIDEBAR_NARROW_WIDTH, DETAIL_PANEL_MOTION, SOURCE_PANEL_LAYOUT_EVIDENCE,
|
||||
normalizeInset, clampSidebarWidth, resolveSidebarDragAction, resolveChatAreaAvailableWidth, resolveChatAreaWidth,
|
||||
resolveDetailDrawerWidth, resolveDetailPanelLayoutWidths, resolveRememberedDetailWidth, resolveLeadingInsetRebalanceWidth,
|
||||
getNarrowState, resolveNarrowState, stickyNarrow
|
||||
} from '../src/renderer/src/workbuddy/workbench/source-panel-layout'
|
||||
|
||||
const hash = (value: string): string => createHash('sha256').update(value).digest('hex')
|
||||
assert.deepEqual(Rw, { EXPANDED_WIDTH: 280, MIN_WIDTH: 240, MAX_WIDTH: 360, COLLAPSE_THRESHOLD: 120, EXPAND_THRESHOLD: 150, COLLAPSED_WIDTH: 48 })
|
||||
assert.deepEqual(zw, { MIN_WIDTH: 360, PREFERRED_WIDTH: 600 })
|
||||
assert.deepEqual(Bw, { BREAKPOINT: 600, CHAT_MIN_WIDTH: 360 })
|
||||
assert.deepEqual(Vw, { MIN_WIDTH: 360, DEFAULT_WIDTH: 500, OVERVIEW_ONLY_WIDTH: 318, MAX_WIDTH: Infinity })
|
||||
assert.deepEqual(JQe, { WIDTH: 2 })
|
||||
assert.equal(DETAIL_NARROW_WIDTH, 1000)
|
||||
assert.equal(SIDEBAR_NARROW_WIDTH, 640)
|
||||
assert.deepEqual(DETAIL_PANEL_MOTION, { openMs: 200, closeMs: 150, openEasing: 'cubic-bezier(0, 0, .2, 1)', closeEasing: 'cubic-bezier(.4, 0, 1, 1)' })
|
||||
|
||||
assert.equal(normalizeInset(Number.NaN), 0)
|
||||
assert.equal(normalizeInset(Infinity), 0)
|
||||
assert.equal(normalizeInset(-1), 0)
|
||||
assert.equal(normalizeInset(31.9), 31)
|
||||
assert.equal(clampSidebarWidth(48), 240)
|
||||
assert.equal(clampSidebarWidth(280), 280)
|
||||
assert.equal(clampSidebarWidth(500), 360)
|
||||
assert.equal(resolveSidebarDragAction(119, false), 'collapse')
|
||||
assert.equal(resolveSidebarDragAction(120, false), 'resize')
|
||||
assert.equal(resolveSidebarDragAction(150, true), 'keep-collapsed')
|
||||
assert.equal(resolveSidebarDragAction(151, true), 'expand')
|
||||
assert.equal(resolveChatAreaAvailableWidth({ containerWidth: 1336, sidebarWidth: 280 }), 1056)
|
||||
assert.equal(resolveChatAreaAvailableWidth({ containerWidth: 1336, sidebarWidth: 280, leadingInset: 100 }), 956)
|
||||
assert.equal(resolveChatAreaAvailableWidth({ containerWidth: 100, sidebarWidth: 280, leadingInset: 100 }), 0)
|
||||
assert.equal(resolveChatAreaWidth(1336, 100), 1236)
|
||||
|
||||
assert.deepEqual(resolveDetailPanelLayoutWidths({ containerWidth: 1336, sidebarWidth: 280, requestedDetailWidth: 528 }), { mainWidth: 528, detailWidth: 528 })
|
||||
assert.deepEqual(resolveDetailPanelLayoutWidths({ containerWidth: 1336, sidebarWidth: 280, requestedDetailWidth: 647 }), { mainWidth: 409, detailWidth: 647 })
|
||||
assert.deepEqual(resolveDetailPanelLayoutWidths({ containerWidth: 1336, sidebarWidth: 280, requestedDetailWidth: 900 }), { mainWidth: 360, detailWidth: 696 })
|
||||
assert.deepEqual(resolveDetailPanelLayoutWidths({ containerWidth: 1336, sidebarWidth: 280, leadingInset: 100, requestedDetailWidth: 900 }), { mainWidth: 460, detailWidth: 596 })
|
||||
assert.equal(resolveDetailPanelLayoutWidths({ containerWidth: 999, sidebarWidth: 280, requestedDetailWidth: 360 }), undefined)
|
||||
assert.deepEqual(resolveDetailPanelLayoutWidths({ containerWidth: 1000, sidebarWidth: 280, requestedDetailWidth: 318 }), { mainWidth: 360, detailWidth: 360 })
|
||||
assert.deepEqual(resolveDetailPanelLayoutWidths({ containerWidth: 1001, sidebarWidth: 280, requestedDetailWidth: 360.9 }), { mainWidth: 361, detailWidth: 360 })
|
||||
|
||||
assert.equal(resolveDetailDrawerWidth({ containerWidth: 1336, sidebarWidth: 280 }), 528)
|
||||
assert.equal(resolveDetailDrawerWidth({ containerWidth: 900, sidebarWidth: 280 }), 360)
|
||||
assert.equal(resolveDetailDrawerWidth({ containerWidth: 900, sidebarWidth: 280, preferredWidth: 500.9 }), 500.9)
|
||||
assert.equal(resolveDetailDrawerWidth({ containerWidth: 900, sidebarWidth: 280, preferredWidth: 1200 }), 900)
|
||||
assert.equal(resolveDetailDrawerWidth({ containerWidth: 599, sidebarWidth: 280, isMobile: true, preferredWidth: 360 }), 599)
|
||||
assert.equal(resolveDetailDrawerWidth({ containerWidth: 300, sidebarWidth: 0 }), 300)
|
||||
assert.equal(resolveDetailDrawerWidth({ containerWidth: 0, sidebarWidth: 280 }), 0)
|
||||
assert.equal(resolveRememberedDetailWidth([undefined, null, 0, 360, 700.9, 800], 1056), 700)
|
||||
assert.equal(resolveRememberedDetailWidth([undefined, null, 360], 1057), 528)
|
||||
assert.equal(resolveRememberedDetailWidth([360.9, 700], 1056), 360, 'source checks >360 before flooring')
|
||||
assert.equal(resolveRememberedDetailWidth([Infinity], 1056), Infinity, 'source behavior is preserved; caller owns finite stored-value validation')
|
||||
|
||||
const rebalance = { previousInset: 0, nextInset: 48, isNarrowForDetail: false, isPanelVisible: true, rememberedDetailWidth: null, chatAreaWidth: 1001 }
|
||||
assert.equal(resolveLeadingInsetRebalanceWidth(rebalance), 500)
|
||||
assert.equal(resolveLeadingInsetRebalanceWidth({ ...rebalance, previousInset: 48 }), undefined)
|
||||
assert.equal(resolveLeadingInsetRebalanceWidth({ ...rebalance, isNarrowForDetail: true }), undefined)
|
||||
assert.equal(resolveLeadingInsetRebalanceWidth({ ...rebalance, isPanelVisible: false }), undefined)
|
||||
assert.equal(resolveLeadingInsetRebalanceWidth({ ...rebalance, rememberedDetailWidth: 500 }), undefined)
|
||||
|
||||
assert.deepEqual(getNarrowState(1000), { isMobile: false, isNarrowForDetail: false, isNarrowForSidebar: false, screenWidth: 1000 })
|
||||
assert.equal(getNarrowState(999).isNarrowForDetail, true)
|
||||
assert.equal(getNarrowState(1047, 48).isNarrowForDetail, true)
|
||||
assert.equal(getNarrowState(1048, 48).isNarrowForDetail, false)
|
||||
assert.equal(getNarrowState(639).isNarrowForSidebar, true)
|
||||
assert.equal(getNarrowState(640).isNarrowForSidebar, false)
|
||||
assert.equal(getNarrowState(599).isMobile, true)
|
||||
assert.equal(getNarrowState(600).isMobile, false)
|
||||
assert.equal(stickyNarrow(false, 1000, 1000), false)
|
||||
assert.equal(stickyNarrow(true, 1023, 1000), true)
|
||||
assert.equal(stickyNarrow(true, 1024, 1000), false)
|
||||
assert.equal(resolveNarrowState(getNarrowState(999), 1023).isNarrowForDetail, true)
|
||||
assert.equal(resolveNarrowState(getNarrowState(999), 1024).isNarrowForDetail, false)
|
||||
assert.equal(resolveNarrowState(getNarrowState(639), 663).isNarrowForSidebar, true)
|
||||
assert.equal(resolveNarrowState(getNarrowState(639), 664).isNarrowForSidebar, false)
|
||||
assert.equal(resolveNarrowState(getNarrowState(599), 623).isMobile, true)
|
||||
assert.equal(resolveNarrowState(getNarrowState(599), 624).isMobile, false)
|
||||
assert.deepEqual(resolveNarrowState(undefined, 1000), getNarrowState(1000))
|
||||
assert.deepEqual(resolveNarrowState(null, 1048, 48), getNarrowState(1048, 48))
|
||||
|
||||
let geometryCases = 0
|
||||
for (let containerWidth = 240; containerWidth <= 1920; containerWidth += 17) {
|
||||
for (const sidebarWidth of [0, 48, 240, 280, 360]) for (const leadingInset of [0, 1, 31, 128]) {
|
||||
let previous = -Infinity
|
||||
for (const requestedDetailWidth of [-100, 0, 318, 360, 500.9, 10_000]) {
|
||||
const result = resolveDetailPanelLayoutWidths({ containerWidth, sidebarWidth, leadingInset, requestedDetailWidth })
|
||||
if (containerWidth - sidebarWidth - leadingInset < 720) assert.equal(result, undefined)
|
||||
else {
|
||||
assert.ok(result)
|
||||
assert.equal(result.mainWidth + result.detailWidth, containerWidth - sidebarWidth, 'space is conserved')
|
||||
assert.ok(result.mainWidth - leadingInset >= 360, 'minimum chat width remains after inset')
|
||||
assert.ok(result.detailWidth >= 360, 'minimum detail width remains')
|
||||
assert.ok(result.detailWidth >= previous, 'increasing requested width never shrinks the panel')
|
||||
assert.ok(Number.isInteger(result.detailWidth) && Number.isInteger(result.mainWidth))
|
||||
previous = result.detailWidth
|
||||
}
|
||||
geometryCases++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const recoveredText = await readFile('src/renderer/src/workbuddy/workbench/source-panel-layout.ts', 'utf8')
|
||||
const recoveredAst = parse(recoveredText, { sourceType: 'module', plugins: ['typescript'] })
|
||||
const expectedBodies = SOURCE_PANEL_LAYOUT_EVIDENCE.functions as Record<string, { bodySha256: string }>
|
||||
let bodyCount = 0, constantCount = 0
|
||||
for (const statement of recoveredAst.program.body) {
|
||||
if (statement.type !== 'ExportNamedDeclaration') continue
|
||||
const declaration = statement.declaration
|
||||
if (declaration?.type === 'FunctionDeclaration' && declaration.id && expectedBodies[declaration.id.name]) {
|
||||
assert.equal(hash(recoveredText.slice(declaration.body.start!, declaration.body.end!)), expectedBodies[declaration.id.name].bodySha256, `source body preserved: ${declaration.id.name}`)
|
||||
bodyCount++
|
||||
}
|
||||
if (declaration?.type === 'VariableDeclaration') for (const variable of declaration.declarations) {
|
||||
if (variable.id.type !== 'Identifier') continue
|
||||
const expected = (SOURCE_PANEL_LAYOUT_EVIDENCE.constants as Record<string, string>)[variable.id.name]
|
||||
if (!expected || !variable.init) continue
|
||||
const expression = variable.init.type === 'TSAsExpression' ? variable.init.expression : variable.init
|
||||
assert.equal(hash(recoveredText.slice(expression.start!, expression.end!)), expected, `source constant preserved: ${variable.id.name}`)
|
||||
constantCount++
|
||||
}
|
||||
}
|
||||
assert.equal(bodyCount, 12)
|
||||
assert.equal(constantCount, 7)
|
||||
|
||||
const sourceCssText = await readFile('.tmp/rea-css-recovered/desktop-sdk-setup-Bh0rg_xP.css', 'utf8')
|
||||
assert.equal(hash(sourceCssText), SOURCE_PANEL_LAYOUT_EVIDENCE.motionSha256)
|
||||
const generatedCssText = await readFile('src/renderer/src/workbuddy/workbench/panel-motion-source.css', 'utf8')
|
||||
const sourceCss = postcss.parse(sourceCssText), generatedCss = postcss.parse(generatedCssText)
|
||||
const selected = (selector: string): boolean => /\.detail-panel-motion-[\w-]+|\.detail-panel-container(?:[\s.:#[]|$)/.test(selector)
|
||||
function describe(rule: Rule, source: boolean): unknown {
|
||||
const conditions: string[] = []
|
||||
let ancestor = rule.parent
|
||||
while (ancestor) { if (ancestor.type === 'atrule') conditions.unshift(`@${ancestor.name} ${ancestor.params}`); ancestor = ancestor.parent }
|
||||
return { selectors: rule.selectors.filter(selector => !source || selected(selector)).map(selector => source ? selector.startsWith('.detail-panel-motion-') ? `.source-detail-layout${selector}` : `.source-detail-layout ${selector}` : selector),
|
||||
declarations: rule.nodes.filter(node => node.type === 'decl').map(node => ({ property: node.prop, value: node.value, important: !!node.important })), conditions }
|
||||
}
|
||||
const expectedRules: unknown[] = [], actualRules: unknown[] = []
|
||||
sourceCss.walkRules(rule => { if (rule.selectors.some(selected)) expectedRules.push(describe(rule, true)) })
|
||||
generatedCss.walkRules(rule => { if (rule.selector !== '.source-detail-layout') actualRules.push(describe(rule, false)) })
|
||||
assert.equal(actualRules.length, 16)
|
||||
assert.deepEqual(actualRules, expectedRules, 'source motion declarations, order, selector membership and media conditions remain intact')
|
||||
const reduced = actualRules.filter(rule => (rule as { conditions: string[] }).conditions.includes('@media (prefers-reduced-motion:reduce)'))
|
||||
assert.equal(reduced.length, 1, 'transition:none must remain conditional on reduced motion')
|
||||
assert.ok(generatedCssText.includes('--wb-motion-duration-medium:.2s'))
|
||||
assert.ok(generatedCssText.includes('--wb-motion-duration-fast:.15s'))
|
||||
assert.ok(generatedCssText.includes('--wb-motion-easing-decelerate:cubic-bezier(0, 0, .2, 1)'))
|
||||
assert.ok(generatedCssText.includes('--wb-motion-easing-accelerate:cubic-bezier(.4, 0, 1, 1)'))
|
||||
execFileSync(process.execPath, ['scripts/rea/recover-panel-layout.mjs', '--check'], { stdio: 'pipe' })
|
||||
console.log(JSON.stringify({ result: 'PASS source panel layout', geometryCases, sourceBodies: bodyCount, sourceConstants: constantCount, sourceCssRules: actualRules.length,
|
||||
checks: ['source SHA/body identity', 'source CSS/media identity', 'finite geometry invariants', 'sidebar drag thresholds', 'drawer/mobile width', 'remembered widths', 'leading inset', 'narrow 24px hysteresis', 'motion token values', 'reproducible generation'] }))
|
||||
Reference in new issue
Block a user