Skip to content

Store the default block width of every top-level block - #190

Merged
sneridagh merged 2 commits into
mainfrom
persist-default-block-width
Oct 6, 2026
Merged

sneridagh merged 2 commits into
mainfrom
persist-default-block-width

Conversation

@sneridagh

Copy link
Copy Markdown
Member

Problem

When a document is loaded, the editor gives every top-level block a width (normalizeInitialValue). Blocks created while editing didn't always store theirs, so saving a page and loading it again changed it. A history diff then showed "Width: not set → Default" on blocks nobody touched. This was found in a volto-plate wiki (kitconcept/volto-plate#83) on a code block.

Causes:

  1. Dead overrides. BaseBlockWidthPlugin and BaseStyleFieldsPlugin override editor.tf.insertNodes, setNodes and wrapNodes by assignment inside extendEditor. Plate 53 ignores that: verified with createSlateEditor, where only the api.create.block and normalizeNode overrides run. Their unit tests passed because they called extendEditor on mock editors.
  2. Normalization only covered registered types. While editing, the width was only filled in for types in plateBlocksConfig; on load it's filled in for every top-level block. Aurora registers nearly every type, which hides this, but hr isn't registered. volto-plate registered only title and p, so pasted, wrapped and inserted blocks (code blocks, callouts, tables…) were saved without a width.
  3. Load-time normalization never reached the form. It happens before <Plate> mounts, so onChange doesn't fire. Saving a page without editing it stored the raw value, and the next real edit showed every width as a change.

Fix

  • block-width-plugin.ts
    • Removed the dead tf overrides.
    • normalizeNode now fills in the width of every top-level native block, registered or not.
    • normalizeInitialValue uses the same resolution (getEffectiveBlockWidth), so a saved value loads unchanged.
    • Width stays a top-level concern: nested blocks don't get one, as before.
  • style-fields-plugin.ts: removed the dead insertNodes override. Top-level Plone blocks now get their style-field defaults in normalizeNode.
  • components/editor/index.tsx: if loading changed the value, PlateEditor calls onChange once on mount. The form then saves what the editor shows. This is a behaviour change: opening a page stored without widths now updates the form data immediately.

Shipped behaviour is otherwise unchanged. The removed overrides never ran; turning them on instead would have added widths to nested nodes such as table rows and code lines.

Tests

  • Unit (block-width-plugin.test.ts): new real-editor tests cover insert, paste (insertFragment), wrap, unwrap, type changes, non-default widths, reset, invalid widths and Plone blocks (inserted and created), each checked through save → reload. The old mock tests for the dead overrides are gone. pnpm --filter @plone/plate test --run passes (68 tests), and check:ts and lint are clean.
  • Acceptance (acceptance/tests/block-width-persistence.test.ts, 14 tests): each saves through the UI, reads the stored value from the REST API, and checks the page reopens unchanged.
    • Native blocks: every block from the slash menu, typed and pasted blocks (including hr), a page stored without widths saved untouched, and a non-default TOC width that is stored, kept and rendered.
    • Plone blocks: an image from the slash menu, an image stored without a width, and a non-default width set from the sidebar, which is stored, kept and rendered.
    • Without the fix, the paste (hr) and untouched-save tests fail. The Plone-block case can't be reproduced through Aurora's UI, so the unit tests cover it.
  • The plate and cmsui acceptance suites pass locally (149 tests), except title-block-sync › "Reloading edit view with no stored title block does not trigger hydration mismatch", which fails the same way on main.

A document loaded into the editor gets the default width on every top-level
block, but blocks created while editing did not always store it, so saving
and loading the same page changed it. History diffs showed those widths as
changes nobody made.

- The block width and style field plugins overrode `editor.tf.insertNodes`,
  `setNodes` and `wrapNodes` by assignment in `extendEditor`, which Plate 53
  ignores. Removed those dead overrides.
- The editor now normalizes the width of every top-level native block, not
  only of the types in `plateBlocksConfig`, with the same rules as loading a
  document. Top-level Plone blocks get their style field defaults the same
  way.
- `PlateEditor` reports the value it normalized on load through `onChange`,
  so saving a page without editing it stores what the editor shows.
…-width

* origin/main: (67 commits)
  Releasing @plone/aurora 1.0.0-alpha.19
  Release @plone/cmsui 1.0.0-alpha.12
  Release @plone/agave 1.0.0-alpha.9
  Release @plone/theming 1.0.0-alpha.9
  Release @plone/layout 1.0.0-alpha.14
  Release @plone/blocks 1.0.0-alpha.18
  Release @plone/plate 1.0.0-alpha.25
  Release @plone/registry 4.0.0-alpha.5
  Release @plone/quanta 1.0.0-alpha.2
  Content CSS Phase 11: theming guide for blocks and cleanup (#219)
  Rename the Plone blocks' classnames to the content contract (#218)
  Share the block spacing between the Public UI and the editor (#217)
  Content CSS Phase 8: structural blocks and content root to styles/content.css (#216)
  Remove the Plate media nodes from Aurora's presets (#215)
  Move the table styles to styles/content.css (#214)
  Move the code block styles to styles/content.css (#213)
  Move the list styles to styles/content.css (#211)
  Move the inline mark styles to styles/content.css (#210)
  Move the text block styles to styles/content.css (#209)
  Add h1 and hr to the Plate block anatomy (#208)
  ...

# Conflicts:
#	packages/plate/components/editor/index.tsx
@sneridagh
sneridagh merged commit 2d04d11 into main Oct 6, 2026
41 checks passed
@sneridagh
sneridagh deleted the persist-default-block-width branch October 6, 2026 16:36
sneridagh added a commit that referenced this pull request Oct 8, 2026
* origin/main: (190 commits)
  Make control panels saveable (#220)
  Public UI: render a single .content-area root (#230) (#234)
  Remove tsconfig test/spec/story excludes that never matched any file (#222)
  Add PloneClient.extend() and clientEndpoints utility for custom endpoints (#221)
  Store the default block width of every top-level block (#190)
  Releasing @plone/aurora 1.0.0-alpha.19
  Release @plone/cmsui 1.0.0-alpha.12
  Release @plone/agave 1.0.0-alpha.9
  Release @plone/theming 1.0.0-alpha.9
  Release @plone/layout 1.0.0-alpha.14
  Release @plone/blocks 1.0.0-alpha.18
  Release @plone/plate 1.0.0-alpha.25
  Release @plone/registry 4.0.0-alpha.5
  Release @plone/quanta 1.0.0-alpha.2
  Content CSS Phase 11: theming guide for blocks and cleanup (#219)
  Rename the Plone blocks' classnames to the content contract (#218)
  Share the block spacing between the Public UI and the editor (#217)
  Content CSS Phase 8: structural blocks and content root to styles/content.css (#216)
  Remove the Plate media nodes from Aurora's presets (#215)
  Move the table styles to styles/content.css (#214)
  ...

# Conflicts:
#	packages/cmsui/components/BooleanWidget/BooleanWidget.stories.tsx
#	packages/cmsui/components/BooleanWidget/BooleanWidget.test.tsx
#	packages/cmsui/components/BooleanWidget/BooleanWidget.tsx
#	packages/cmsui/news/+boolean-widget-adapter.bugfix
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.

1 participant