Skip to content

Add a blockSchema to the image, maps, toc, html and leadimage core blocks - #8472

Open
sneridagh wants to merge 4 commits into
mainfrom
claude/core-blocks-blockschema-69ed0e
Open

sneridagh wants to merge 4 commits into
mainfrom
claude/core-blocks-blockschema-69ed0e

Conversation

@sneridagh

@sneridagh sneridagh commented Oct 20, 2026 •

Copy link
Copy Markdown
Member

Some core blocks kept their data schema inside their sidebar or edit component instead of in the block configuration, so config.blocks.blocksConfig[type].blockSchema was missing for them. Consumers of the blocks configuration (for example the /@blocks-schema endpoint proposed in #8023) got schema: null for image, maps, toc, html, title, description and leadimage.

This PR is independent of #8023.

Blocks that now have a blockSchema

Block blockSchema Editor reads it from config
image ImageSchema (Image/schema.jsx, unchanged fields) Yes, ImageSidebar
maps MapsSchema (Maps/schema.js, unchanged) Yes, MapsSidebar
toc ToC/Schema.jsx (exported as ToCSettingsSchema, unchanged fields, variation-aware) Yes, ToC/Edit
html new HTMLBlockSchema (HTML/schema.js), one html field No sidebar form, see below
leadimage new LeadImageBlockSchema (LeadImage/schema.js): align, href, openLinkInNewTab No, see below

The sidebars and the ToC edit form resolve the schema the same way DefaultEdit does: blocksConfig[data['@type']].blockSchema, called with the block props and intl, falling back to the module's schema if an add-on replaced the block config without one. They use the blocksConfig prop, so blocks inside a container (for example the grid, with its gridImageDisableSizeAndPositionHandlersSchema enhancer) keep working as before. Editor behaviour and appearance are unchanged; no snapshots changed.

The schema functions now accept the block data as either data (the blockSchema convention used by DefaultEdit, Teaser, and the endpoint) or formData (what ImageSidebar passed before), so ImageSchema({ formData, intl }) callers in add-ons still work, and calling them without block data no longer throws.

Table of Contents

ToC/Schema.jsx is the block data schema (title, hide title, entries, ordered/sticky depending on the variation), not a block settings schema. It was registered as schema, the key Block/Edit passes to the generic "block settings" sidebar in layout (manage) mode, which expects an object like BlockSettingsSchema, not a schema function. It is now the blockSchema, and toc uses BlockSettingsSchema as its schema like the other blocks. The ToCSettingsSchema export in @plone/volto/components keeps its name for backwards compatibility.

HTML

The HTML block stores a single html field that is edited with the code editor in the block itself, so there is no sidebar to wire. The new schema only describes the block data for consumers of the configuration. Nothing in the editor renders it, since the block has its own edit and view.

Lead image

Contrary to what we assumed, the lead image block does store block data: align, href and openLinkInNewTab. The image and its alt text come from the content item's image and image_caption fields. LeadImageSidebar is a hand-built form with legacy widgets (not BlockDataForm), so porting it to render the schema would change the editor's look. This PR only adds the schema and leaves the sidebar alone. A comment in the schema notes both must stay in sync. Moving the sidebar to BlockDataForm can be a follow-up.

Blocks that still have no blockSchema, on purpose

  • title and description render the content item's title and description fields. They store no block data besides @type, so there is nothing to describe. They keep the generic BlockSettingsSchema as schema.

Notes

  • The image schema shows alt, align, size and the link fieldset only once an image is set (url), as before. Called without block data, its fieldsets are empty but all properties are listed.
  • The locale changes are only new #: source references from pnpm i18n for existing message IDs; no new strings to translate.

Tests

  • New src/config/Blocks.test.js checks that image, leadimage, maps, toc and html have a blockSchema that resolves with endpoint-style arguments and no block data, that title/description have none, that the ToC schema follows the variation, and that toc uses the generic settings schema.
  • pnpm --filter @plone/volto test --run on the Image, Maps, HTML, LeadImage, ToC, Block and config tests passes, with no snapshot changes.

Fix: saving a content type layout

When the form is saved, Form.onSubmit validates every block that has a blockSchema, and passes this.props.content['@type'] to applySchemaEnhancer. The content type layout editor (/controlpanel/dexterity-types/<type>/layout) has no content, so once the image block had a blockSchema, saving a layout with an image block threw Cannot read properties of null (reading '@type'). The Cypress test "ControlPanel: Dexterity Content-Types Layout" caught it. The same would have happened before with any other block that has a blockSchema, like a teaser, in a type layout. It now uses optional chaining (this.props.content?.['@type']).

…ocks

The Image and Maps block sidebars and the ToC block edit form now read
their schema from config.blocks.blocksConfig[type].blockSchema, so the
editor and the block configuration share one source and add-ons can
override it through config. The toc block now uses the generic
BlockSettingsSchema as its schema, like the other blocks.
Form.onSubmit validates blocks with a blockSchema and passes the content
type to applySchemaEnhancer, but the content type layout editor has no
content. Now that the image block has a blockSchema, saving a layout
with an image block threw.

@davisagli davisagli left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sneridagh I agree with the goal here, but I didn't have time to review it yet.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants