Add Wave 1 block server schemas (page builder step 3, server half)

Register all seven Wave 1 block types with their server-side validation
schemas, self-registering via server/src/blocks/types/*:
heading, rich_text, image, two_column (container), cta, divider, quote.

- propHelpers.js: shared validators (isSafeUrl rejects javascript:/data:/
  protocol-relative, enum/required/optional text, strict key allowlist).
- rich_text carries a `sanitize` normalizer (registry now supports it) that
  runs html through the shared cleanBody allowlist on save.
- Registry entrypoint requires the type modules so all schemas load.

Verified: all 7 register; valid blocks pass; malformed props yield precise
per-path errors; one-level nesting cap enforced; rich_text sanitize strips
script/onerror.

Client renderers + editors (step 3 client half) still to come.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-09 20:30:58 -05:00
parent fcef08e9b6
commit 6d31869ba2
10 changed files with 250 additions and 12 deletions

View File

@@ -4,22 +4,21 @@
// page's blocks or look up a block type should require THIS module, not
// ./registry directly, so the definitions are guaranteed to be loaded.
//
// Wave 1 block definitions are registered below, one require() per block, as
// they are built (spec build order step 3). Until then the registry is empty and
// validateBlocks rejects any block type — which is correct: no page can save a
// block that has no server-side schema yet.
// Wave 1 block definitions are registered below, one require() per block (each
// module self-registers on load). Requiring THIS module guarantees they are all
// present before anything validates a page's blocks.
const registry = require('./registry')
const { validateBlocks, MAX_BLOCKS, MAX_SUBBLOCKS } = require('./validateBlocks')
// ── Wave 1 block definitions ──────────────────────────────────────────
// require('./types/heading').register(registry) // added in step 3
// require('./types/richText').register(registry)
// require('./types/image').register(registry)
// require('./types/twoColumn').register(registry)
// require('./types/cta').register(registry)
// require('./types/divider').register(registry)
// require('./types/quote').register(registry)
// ── Wave 1 block definitions (self-register on require) ────────────────
require('./types/heading')
require('./types/richText')
require('./types/image')
require('./types/twoColumn')
require('./types/cta')
require('./types/divider')
require('./types/quote')
module.exports = {
...registry,