// Normalize + sanitize a validated blocks array before persisting. Runs AFTER // validateBlocks (which guarantees the envelope/prop shape), so this can assume // well-formed input and focus on: applying each block's registry `sanitize` // normalizer (e.g. rich_text runs its html through the allowlist), stamping the // registry `version`, defaulting `visible` to true, and recursing one level into // container slots. Returns a new array; never mutates the input. // // Parameterized by a registry lookup for the same reason validateBlocks is // (engagement Phase 5a): the `email.*` family is a separate registry and must get // the same validate-then-sanitize order, not a second implementation of it. const { getBlock } = require('./registry') /** * Build a blocks sanitizer bound to one registry. * @param {(type: string) => object|null} lookup registry `getBlock` * @returns {(blocks: unknown) => object[]} */ function makeSanitizeBlocks(lookup) { function sanitizeOne(block) { const def = lookup(block.type) if (!def) return block // unreachable after validation, but stay defensive let props = block.props && typeof block.props === 'object' ? { ...block.props } : {} // Recurse into container slots first (leaf sub-blocks get sanitized too). if (def.container) { for (const slot of def.containerSlots) { if (Array.isArray(props[slot])) props[slot] = props[slot].map(sanitizeOne) } } // Apply the block's own normalizer last (operates on its scalar props). if (def.sanitize) { try { props = def.sanitize(props) } catch { // Leave props as-is; validation already passed, a sanitize throw shouldn't // block the save. } } return { id: block.id, type: block.type, version: Number.isInteger(block.version) ? block.version : def.version, visible: block.visible !== false, props, } } return function sanitizeBlocks(blocks) { if (!Array.isArray(blocks)) return [] return blocks.map(sanitizeOne) } } // The page-registry binding — the export every existing caller already uses. const sanitizeBlocks = makeSanitizeBlocks(getBlock) module.exports = { sanitizeBlocks, makeSanitizeBlocks }