#!/usr/bin/env node /** * Layout guard for the CMS bottom bar (MITHOME-69): the bar items must not * shift while saving/publishing. Asserts the invariants that keep the layout * stable: * - the status slot reserves constant space (flex + visibility, not display) * - no auto margins redistribute free space between bar items * - the publish handler locks the button width and restores its label * - save refreshes the optimistic-lock fingerprint (MITHOME-68) */ const assert = require('assert/strict'); const fs = require('fs'); const path = require('path'); const pages = fs.readFileSync(path.join(__dirname, '../scripts/cms-pages.js'), 'utf8'); const client = fs.readFileSync(path.join(__dirname, '../scripts/cms-editor-client.js'), 'utf8'); const statusRule = pages.match(/\.save-status \{[^}]*\}/)[0]; assert.match(statusRule, /flex: 1 1 0/, 'status slot must reserve constant space'); assert.match(statusRule, /visibility: hidden/, 'status must hide via visibility (keeps layout slot)'); assert.doesNotMatch(statusRule, /display: none/, 'display:none would collapse the slot and shift items'); const previewRule = pages.match(/\.preview-link \{[^}]*\}/)[0]; assert.doesNotMatch(previewRule, /margin-left: auto/, 'auto margins redistribute space on width changes'); const logoutRule = pages.match(/\.btn-logout \{[^}]*\}/)[0]; assert.doesNotMatch(logoutRule, /margin-left: auto/, 'auto margins redistribute space on width changes'); assert.match(client, /btn\.style\.minWidth = btn\.offsetWidth \+ 'px'/, 'publish must lock the button width'); assert.match(client, /const originalLabel = btn\.textContent/, 'publish must restore the env-specific label'); assert.match(client, /if \(json\.contentHash\) CONTENT_HASH = json\.contentHash/, 'save must refresh the lock fingerprint'); console.log('Content Editor bottom bar layout guard: OK');