Releases

RSS

Latest updates and announcements.

v54.0.0-beta.0

@platejs/core

Breaking Changes

  • Prepare v54 beta prerelease versioning. (#5031)

plitejs

Breaking Changes

  • Prepare v54 beta prerelease versioning for Plite. (#5031)

CHANGELOG · v53.2.0...v54.0.0-beta.0 · By @felixfeng33

behavior
comment-toolbar-buttoncommentdiscussionfixed-toolbar

Discover open, resolved, and unavailable conversations through All comments; remove stale block placement and preserve in-progress conversation actions.

wiring
comment-democomment-overlap-democomment-persistence-democomment-review-demosuggestion-demosuggestion-format-demosuggestion-persistence-demo

Include document-level comment discovery in editable, read-only, persistence, and suggestion examples.

behavior
editor-dropdown-menumore-toolbar-buttonmode-toolbar-buttonlist-toolbar-buttonalign-toolbar-buttonline-height-toolbar-buttoninsert-toolbar-buttonslash

Run final focus from the selected menu item and call typed block `insert` or `upsert` operations directly.

behavior
insert-toolbar-buttonslashturn-into-toolbar-buttonblock-menu

Call installed feature operations directly, preserve exact block selections, and disable unsupported structural actions.

wiring
alignline-heighteditor-plugins-static

Share the same server-safe formatting kits between editable and static editor compositions.

fix
plateplate-ui

Install package requirements derived from copied source and serve production and development payloads from one generated registry state.

fix
ai-menu

Publish generated feedback as ordinary comment threads. Keep completed comments when generation stops or fails, and show failed requests with retry and dismissal controls.

behavior
ai-api

Limit comment prompts to the selected content while preserving its formatting and inline structure.

behavior
commentdiscussion

Await comment actions before clearing input, retain failed replies for retry, reopen resolved conversations independently of document undo, and keep suggestion conversations replyable after decisions.

behavior
use-chat

Let completed AI comments finish saving when the chat menu closes; discard pending drafts on cancellation.

behavior
comment-persistence-demosuggestion-persistence-demoeditor-ai

Save comments and opaque attachments with the matching document revision and restore them into a fresh editor.

behavior
discussion-demo

Load three authored suggestions and their conversations together while keeping direct editing as the default.

new
diff

Inspect two-way and three-way comparisons with grouped effects, evidence, conflict choices, filters, and navigation.

behavior
version-history-demo

Save document revisions and compare the two latest snapshots.

behavior
suggestionsuggestion-style

Use green for the current user's suggestions and stable distinct colors for collaborators, with underlines for insertions and strikethroughs for deletions.

new
suggestion-format-demosuggestion-view-demosuggestion-persistence-demo

Review formatting and block proposals, compare document projections, and save proposals with their discussion threads.

fix
suggestion

Keep discussion buttons available when switching a saved document between accepted content and markup.

wiring
editor-ai

Load the multi-author suggestion example and linked discussions from its included saved document, with suggesting mode configured on `EditorRoot`.

fix
findfind-demo

Find opens independently in each editor view. Custom opening controls use `useFind` inside Editable slots, while `BaseFindPlugin` supplies shared queries and results. The demo includes a second view of the same document.

behavior
use-chat

Bind the shared SDK transport with `useAIChat`. Share one session across mounted views and keep streaming while a writable view remains. Keep endpoint configuration and comment persistence in the application.

behavior
ai-menu

Render the session preview through a read-only editor view and size the menu within the viewport.

behavior
copilot

Render ghost text without changing the accepted completion. Keep demo responses in the application route.

behavior
copilot-api

Return completion text and pass the configured gateway key to the provider.

fix
transforms

Insert blocks with owned construction, empty-source replacement and selection. Preserve source content while media URL input resolves and keep each action in one history step.

behavior
block-menu

Convert the selected blocks with one feature command, including disjoint selections and structural wrappers.

behavior
excalidraw

Use `useExcalidrawSync` to apply document changes and undo to the canvas, save referenced images, and exclude transient canvas state from document writes. Keep lazy loading and presentation in the copied element.

fix
find

Search through `BaseFindPlugin` while keeping the search bar, deferred input, focus and scroll behavior local. Preserve IME confirmation and opening before the first query.

behavior
editor

Style the current match separately from other matches using the feature’s transient data attributes.

behavior
suggestiondiscussion

Read semantic groups with `useSuggestionReviews` and accept or reject by ID. Keep labels, dates and card activation in the copied view.

behavior
suggestion-static

Use the feature's inline suggestion projection for consistent inherited text styling.

fix
font-size-toolbar-button

Derive the default size from the heading level and keep input, presets and step buttons within 1–100 pixels. Reject empty and nonnumeric input.

behavior
mode-toolbar-button

Display Viewing and select its menu option whenever the editor is read-only, including when the suggestion preference is enabled.

wiring
docx

Install the paste and import plugins; call `exportToDocx` with a document snapshot from the export action.

wiring
docx-exportheading-statictoc

Emit ordinary HTML anchors and let the converter assign unique bookmark names within each DOCX document.

fix
markdown-streaming-demo

Stop pending chunks when resetting, changing scenarios, navigating, switching editor modes, or leaving the demo.

behavior
code-block

Confirm copying after the clipboard write succeeds and allow retry after a failure.

behavior
comment

Preserve stored timestamps when callers reuse or mutate input dates.

behavior
select-editorcontrolled-demo

Release pending layout measurements and loading timers on unmount.

behavior
media

Clarify file-size and minimum-file-count errors.

wiring
export-toolbar-button

Avoid adding an empty stylesheet during image and PDF export.

wiring
aidndeditor-aieditor-plugins

Use `AIKit` and `DndKit` to enable AI commands and drag and drop with ordinary `Plate` and `Editor` composition. Share one AI stream across editor views and retain custom transports and drag managers.

behavior
editor-aidnd

Provide tooltips in standalone installs.

behavior
date

Focus the calendar when opening the date picker.

behavior
emoji-pickerfont-size-toolbar-button

Preserve server rendering and input semantics in Base UI editors.

remove
code-blockcode-block-staticcode-block-demo

Store multiline code in one text child and remove the code-line component and virtualization dependency.

  • Remove the code-line plugin and component when updating copied editor code.
fix
commentdiscussiondiscussion-demo

Keep comments reachable after complete text deletion, and restore exact highlights through undo and redo.

fix
comment

Render thread message bodies with the static Plate view so replies do not mount nested editable runtimes.

behavior
commentcomment-toolbar-buttondiscussiondiscussion-demoeditoreditor-static

Open each block's combined comments and suggestions in Floating Discussion, including exact overlaps, block-caret creation, and static or read-only highlights.

  • Install `DiscussionKit` for Floating Discussion and per-block affordances.
  • Replace `block-discussion` with `discussion`.
behavior
discussionsuggestion

Show suggestion authors, changes, attached comment threads, and Accept or Reject actions beside ordinary comments.

wiring
commentdiscussionuse-chateditor-ai

Stage AI comments for Accept or Reject before publishing their thread records.

fix
editor-ai

Keep the toolbar above the editor and use Floating Discussion on narrow screens without collapsing the editing surface.

behavior
commentdiscussiondiscussion-demoeditor-ai

Load fetched thread records through `CommentsPlugin.configure({ initialState: { initialThreads } })`, preserving ranges, authors and timestamps. Read records for saving through `api.getThreads`.

fix
plate-to-htmlsuggestion

Preserve inserted and removed suggestion markup in static HTML exports.

fix
code-block-staticdocx-exportexport-toolbar-buttondocx-demo

Preserve code token colors and indentation through the copied DOCX export preset.

wiring
context-menudropdown-menufloating-popovertoolbarmdx-plate-componentsblock-list-staticblock-listcode-block-staticcode-blockdndeditoremoji-pickerfloating-toolbarheading-staticinline-comboboxmark-toolbar-buttonselect-commandversion-history-demo

Define component-owned prop shapes at their component signatures and reserve named prop contracts for exported reuse.

new
findfind-demoeditor-plugins

Search documents with a visible Find bar and transient, keyboard-navigable matches.

new
inactive-selection-demo

Demonstrate native inactive-selection paint for expanded ranges and collapsed carets without an editor plugin.

behavior
editorai-menufont-size-toolbar-buttonlink-toolbar-buttonlink

Keep the canonical selection visible while marked editor controls own focus, and clear it on every unmarked focus transition.

behavior
use-widget-floatingfloating-toolbarlink

Position floating controls from the exact mounted editor selection, reveal them only after placement resolves, and mount complete toolbar components with only the Editable ref. `FloatingToolbar` accepts optional custom children.

wiring
remote-cursor-overlaycollaboration-demo

Render remote Yjs selections and carets through `YjsPlugin` slots with per-cursor updates.

fix
link

Focus the URL input when the floating form opens, including from an empty paragraph, and preserve keyboard navigation between its fields.

rename
detailsdetails-staticdetails-toolbar-buttondetails-demo

Use nested semantic Details and Summary nodes with transient disclosure state.

rename
dndinline-comboboxblock-discussionuse-chataiai-menucommentselect-editorfind-replace-democode-blockfont-size-toolbar-buttonmathmedia-preview-dialoghuge-document-demo

Use `useCreateEditor` for React editor creation. `use-chat` exports `useEditorChat`, block discussion exports `BlockResolvedSuggestion`, and missing required values report contextual errors.

remove
expect-defineddndinline-comboboxblock-discussionuse-chat

Keep required-value checks in each component with contextual errors and no shared registry dependency.

wiring
columnfloating-toolbarfont-color-toolbar-buttonlinkmedia-preview-dialogselect-editoruse-on-click-outside

Install with `platejs` and copied helper source; `select-editor` includes its controlled command implementation.

behavior
block-selectiontable

Select custom Plate block content from its schema and let tables render their own selection geometry.

behavior
plate-uitoolbarfloating-popovereditor-dropdown-menueditor-context-menu

Install Base UI source with `base-nova` by default. Explicit Radix styles select the matching interaction adapters.

behavior
plate-uitoolbarfloating-popover

Install Nova, Vega, Maia, Lyra, Mira, Luma, Sera, or Rhea code styles without duplicating the complete editor registry.

fix
block-menucode-blockcode-drawingcommentemoji-pickerfont-color-toolbar-buttonfont-size-toolbar-buttonfootnotemathtabletable-toolbar-buttonturn-into-toolbar-button

Compose popovers, dropdowns, and context menus through the selected provider without provider-specific trigger, focus, delay, or value props in consumer code.

fix
fumadocs

Install the docs block with Base or Radix without fixed Radix primitive packages.

fix
editor-basicaidatelinksuggestion-style

Create a fresh Next project with a complete dependency graph, collision-free inline-suggestion imports, and current copied-source types.

remove
editor-plugins

Install the authored editor kit without generated TypeScript or schema snapshots. Generate exact contracts from the application's customized plugin module and enforce `plate generate --check <entry>` in CI.

  • Delete unused plugins.generated.ts and plugins.schema.json files. If the app needs exact contracts, install @platejs/cli, regenerate from its local plugin module, and enforce plate generate --check <entry> in CI.
fix
font-color-toolbar-buttonmath

Preserve the active editor value while focus moves into a control, and reopen inline equations only after selection returns.

behavior
media-placeholderplate-to-htmluse-object-url

Give each browser object URL one source lifetime and revoke it when that source is replaced or unmounted.

behavior
tableuse-chat

Render the selected-cell drag handle at its cell owner and keep fake-stream cancellation inside its transport.

behavior
ai-menucolumndndeditoremoji-pickerinline-combobox

Use named React Compiler components without manual memo wrappers or display-name assignments.

remove
editorblock-menudndtableai-menucursor-overlay

The copied editor renders a Pointer Events marquee while exact one-or-many membership stays in editor selection. No selection plugin, area abstraction, or selection package is required.

fix
toolbarmedia-preview-dialogmedia-placeholder

Use native, keyboard-accessible controls for split toolbars, media upload, and image preview actions.

behavior
media-embedmedia-embed-staticpotion-iframe-demopro-iframe-demo

Restrict embedded content with explicit sandbox and referrer policies.

rename
datedate-staticmentionmention-staticfootnotefootnote-staticblock-discussion

Store dates under one `value` and persisted associations under `ref`.

rename
code-drawingcode-drawing-staticmathmath-static

Use flat lowercase drawing fields and store equation source under `latex`.

rename
columnmediatablelisteditor-pluginseditor-ai

Apply the v54 migration, field ownership, and numeric-domain contracts.

wiring
uploadthingmedia-placeholder

Keep UploadThing server routing in `uploadthing` and colocate client upload state in `media-placeholder`.

  • Keep custom upload state in your media placeholder component; `uploadthing` installs only the server router.
wiring
block-discussionemoji-picker

Keep single-consumer subscription and picker state inside their owning component families.

wiring
editor-pluginseditor-defaultdocument-migration-demo

Keep reusable editor composition migration-free and teach named lineage only in the dedicated migration example.

  • Define your named schema and migration chain in the application persistence owner; `editor-plugins` exports only `EditorKit`.
wiring
emojiemoji-pickeremoji-toolbar-buttoncalloutinline-comboboxfloating-toolbarlinktabletable-toolbar-buttonblock-menumentionmediamedia-videoblock-placeholderresize-handleblock-selectioncopilotplate-to-html

Install self-contained families with product copy, limits, styling, endpoints, and interaction policy in copied source; `table` composes renderer layout and pointer behavior directly.

behavior
basic-blocksbasic-blocks-staticheadingheading-staticlistlist-staticblock-listblock-list-statictabletable-staticmedia-videomedia-placeholdercode-blockeditor-plugins

Use one semantic Heading, boundary-only list numbering, semantic Table fields, intrinsic Media dimensions, and the generated v54 editor contract.

rename
align-staticbasic-blocks-staticbasic-marks-staticcallout-staticcode-block-staticcode-drawing-staticcolumn-staticcomment-staticdate-staticfootnote-staticexcalidrawfont-staticindent-staticline-height-staticlink-staticlist-staticmath-staticmedia-staticmention-staticsuggestion-statictable-statictoc-statictoggle-staticeditor-plugins-staticaialignautoformatbasic-blocksbasic-marksbasic-nodesblock-menublock-placeholderblock-selectioncalloutcode-blockcode-drawingcolumncommentcopilotcursor-overlaydatediscussiondnddocxdocx-exporteditor-pluginsemojiexit-breakfixed-toolbarfloating-toolbarfootnotefontindentline-heightlinklistmarkdownmathmediamedia-uploadthingmentionslashsuggestiontabbabletabletoctoggleeditoreditor-staticai-menuai-toolbar-buttonalign-toolbar-buttonimport-toolbar-buttonexport-toolbar-buttoncaptioncaption-staticfont-color-toolbar-buttoncomment-toolbar-buttonblock-discussionselect-editoremoji-toolbar-buttonhistory-toolbar-buttonlist-toolbar-buttonindent-toolbar-buttoninline-comboboxinsert-toolbar-buttonline-height-toolbar-buttonlink-toolbar-buttonmark-toolbar-buttonmedia-toolbarmedia-toolbar-buttonmode-toolbar-buttonmore-toolbar-buttonresize-handletable-toolbar-buttontoggle-toolbar-buttonturn-into-toolbar-buttonremote-cursor-overlaytoolbarsuggestion-toolbar-buttonblock-listblock-list-staticblockquoteblockquote-staticcodecode-staticequation-toolbar-buttonfont-size-toolbar-buttonheadingheading-statichighlighthighlight-statichorizontal-rulehorizontal-rule-staticmedia-imagemedia-image-staticmedia-preview-dialogkbdkbd-staticmedia-audiomedia-audio-staticmedia-embedmedia-embed-staticmedia-filemedia-file-staticmedia-placeholdermedia-videomedia-video-staticparagraphparagraph-staticsearch-highlighttag

Install copied editor features from one flat editor namespace

  • Move copied Plate imports from @/components/ui and @/components/editor/plugins to @/components/editor.
  • Install feature items without -kit or -base-kit suffixes; FooKit remains the exported plugin tuple.
  • Import feature-owned renderers and family-only components from the owning feature file, such as @/components/editor/footnote and @plate/footnote.
  • Use semantic renderer item names such as blockquote and media-image instead of *-node; install static renderers from their matching *-static items.
behavior
ai-menublock-draggableblock-listcallout-nodecaptioncode-drawing-nodecolumn-nodecommentemoji-nodeemoji-toolbar-buttonequation-nodeexcalidraw-nodeexport-toolbar-buttonfloating-toolbarfont-color-toolbar-buttonimport-toolbar-buttonindent-toolbar-buttoninline-comboboxlink-toolbar-buttonlink-toolbarlist-toolbar-buttonmedia-audio-nodemedia-embed-nodemedia-file-nodemedia-image-nodemedia-placeholder-nodemedia-preview-dialogmedia-toolbarmedia-upload-toastmedia-video-noderemote-cursor-overlayresize-handleselect-editortable-nodetable-toolbar-buttontoc-nodetoggle-nodetoggle-toolbar-buttontoolbar

Keep interaction state and behavior inside direct React 19 component families.

  • Rename the FloatingToolbar state prop to options.
wiring
emoji-kitlink-kitmedia-kit

Install the exact app-local descriptors owned by their copied UI families.

wiring
editor-kiteditor-aicopilot-demomarkdown-streaming-demoplayground-demo

Reuse the primary editor composition directly, compose Copilot only in its demo, and install `ElementIdPlugin` only when persisted IDs are required.

  • Import the primary editor composition directly outside the Copilot demo. Append CopilotKit only in copilot-demo.
  • Install ElementIdPlugin explicitly when persisted element IDs or Markdown withBlockId are required.
  • Install CodeDrawingPlugin or ExcalidrawPlugin explicitly in editors that use those specialized nodes.
  • Remove schema: EditorSchema from copied editor setup. Add an application-owned schema id and version only for persisted schema lineage, migrations, history serialization, or collaboration.
behavior
editor-kitcode-drawing-demoexcalidraw-demoplayground-demo

Keep code drawing and Excalidraw explicit in the demos that use them.

behavior
editor-kit

Derive schema identity from the installed plugin composition instead of publishing application lineage from copied registry code.

fix
ai-apiai-kitai-menuai-nodeautoformat-kitblock-context-menublock-discussionblock-draggableblock-selectionblock-selection-kitblock-suggestionblockquote-nodecallout-nodecode-block-nodecode-drawing-nodecode-nodecolumn-nodecomment-nodecomment-toolbar-buttoncopilot-democopilot-kitcursor-overlaydate-nodedocx-export-kiteditor-aieditor-base-kiteditor-basiceditor-kitemoji-nodeemoji-toolbar-buttonequation-nodeexcalidraw-kitexcalidraw-nodeexport-toolbar-buttonfloating-toolbarfont-base-kitfont-color-toolbar-buttonfont-kitheading-nodehighlight-nodehr-nodehuge-document-demohundreds-editors-demoimport-toolbar-buttoninline-comboboxinstallation-next-demokbd-nodelink-toolbarlist-toolbar-buttonmarkdown-streaming-demomarkdown-to-plite-demomedia-audio-nodemedia-base-kitmedia-embed-nodemedia-file-nodemedia-image-nodemedia-toolbarmedia-video-nodemode-toolbar-buttonmore-toolbar-buttonmultiple-editors-demoplate-to-htmlpreview-markdown-demoresize-handlesearch-highlight-nodeselect-editorselect-editor-demosettings-dialogslash-nodesuggestion-nodetabbable-demotable-nodetag-nodetoc-nodetransformsturn-into-toolbar-buttonuse-chatversion-history-demo

Install every required package and copied registry file without redundant declarations.

behavior
docx-export-kitheading-node-statictoc-nodetoc-node-static

Build live TOC navigation and DOCX-local bookmarks from runtime node keys.

wiring
editor-kiteditor-ai

Install persisted element IDs explicitly as editor product policy.

rename
ai-nodebasic-marks-base-kitblockquote-nodecallout-nodecode-block-nodecode-nodeeditable-voids-demoemoji-nodefootnote-nodeheading-nodehighlight-nodehr-nodekbd-nodelink-nodelink-node-staticparagraph-nodesearch-highlight-nodesuggestion-nodetabbable-demotoc-nodetoggle-nodeversion-history-demo

Infer copied renderer props from their plugin descriptors.

wiring
callout-nodecallout-node-staticcode-block-nodecode-block-node-staticcode-drawing-nodecode-drawing-node-staticcolumn-nodecolumn-node-staticdate-nodedate-node-staticequation-nodeequation-node-staticexcalidraw-nodefootnote-nodefootnote-node-staticlink-nodelink-node-staticmedia-audio-nodemedia-audio-node-staticmedia-embed-nodemedia-embed-node-staticmedia-file-nodemedia-file-node-staticmedia-image-nodemedia-image-node-staticmedia-placeholder-nodemedia-toolbarmedia-video-nodemedia-video-node-staticmention-nodemention-node-staticslash-nodetable-nodetable-node-statictag-node

Infer node component props from plugin descriptors

remove
table-nodetable-base-kittable-kit

Use one table cell plugin and component for data and header cells.

  • Use TableCellElement for data and header cells. Header nodes use type: 'tableCell' with header: true.
fix
code-drawing-demoexcalidraw-demo

Configure feature renderers explicitly while installing each plugin name once.

fix
cursor-overlayghost-text

Read cursor geometry and schema-configured node ids from their package owners.

fix
media-image-nodemedia-video-node

Let resize handles derive read-only state from the editor.

fix
table-node

Use the DnD block selection-and-focus controller after row drops.

wiring
ai-kitblock-placeholder-kitblock-selection-kitcode-block-base-kitcode-block-kitcomment-kitcopilot-kitdiscussion-kitdnd-kitemoji-kitindent-base-kitindent-kitmarkdown-kitmedia-kitmention-kitslash-kitsuggestion-kittabbable-kittoc-kit

Seed editor-local plugin stores with `initialState`.

behavior
ai-menuai-nodeblock-context-menublock-discussionblock-draggableblock-selectionblock-suggestioncolumn-nodecomment-nodecursor-overlayemoji-nodefloating-toolbarghost-textlink-toolbarmedia-placeholder-nodemedia-upload-toastmode-toolbar-buttonsettings-dialogsuggestion-nodesuggestion-toolbar-buttontable-nodeuse-chat

Read, update, and subscribe to plugin state through the typed store API.

behavior
collaboration-demomarkdown-streaming-demo

Configure and update plugin store state through the same API used by copied registry code.

behavior
basic-marks-kitbasic-marks-base-kitmark-toolbar-buttonmore-toolbar-buttonbasic-marks-valueplugin-rules-value

Use one script mark for subscript and superscript

  • For persisted v53 script marks, add migrateV54 to the app's defineDocumentMigrations chain.
wiring
basic-blocks-base-kitbasic-marks-base-kitcallout-base-kitcode-block-base-kitcode-drawing-base-kitcolumn-base-kitcomment-base-kitdate-base-kitfootnote-base-kitlink-base-kitmath-base-kitmedia-base-kitmention-base-kitsuggestion-base-kittable-base-kittoc-base-kittoggle-base-kit

Bind static components without React plugin imports

wiring
markdown-kit

Configure Markdown parsing without installing a renderer-specific Footnote preset.

wiring
editor-kiteditor-aieditor-base-kit

Compose the shared Markdown parser with the matching live or static Footnote renderers exactly once.

wiring
align-kitbasic-blocks-kitbasic-marks-kitcallout-kitcode-block-kitcode-drawing-kitcolumn-kitcomment-kitdate-kiteditor-aieditor-base-kiteditor-kitfont-kitline-height-kitlink-kitlist-kitmarkdown-kitmath-kitmedia-kitmention-kitsuggestion-kittable-kittoc-kittoggle-kit

Install only the presets their copied source composes, without unrelated static/base counterparts.

behavior
tabbable-kit

Preserve Indent support while reserving Tab and Shift+Tab navigation for tabbable elements.

behavior
font-color-toolbar-buttontoolbarfixed-toolbar-buttonstable-node

Configure text color palettes, optionally control recent colors, and navigate color grids with the keyboard.

wiring
mark-toolbar-buttonfont-color-toolbar-buttonfont-size-toolbar-buttonmedia-toolbar-buttonmore-toolbar-buttonfixed-toolbar-buttonsfloating-toolbar-buttonsinstallation-next-02-marks-demoinstallation-next-03-elements-demoinstallation-next-demo

Use installed feature plugins instead of raw type dispatch in toolbar controls.

behavior
captionmedia-base-kitmedia-kitmedia-image-nodemedia-video-nodemedia-audio-nodemedia-file-nodemedia-embed-nodemedia-placeholder-nodemedia-toolbar-buttonplate-to-html

Render direct media caption children, keep an empty caption hidden until asset focus, and separate asset selection from caption editing.

  • Remove CaptionPlugin from media kits and render each media element's direct children as its caption; use [{ text: '' }] when the caption is absent.
  • For persisted v53 media captions, add migrateV54 to the app's defineDocumentMigrations chain.
wiring
footnote-nodetable-nodetable-node-static

Use the installed plugin's typed editor APIs with Plate v54.

behavior
transformseditor-kitdnd-kit

Insert code blocks, drawings, Excalidraw canvases, tables, and dropped media through their installed commands with explicit relational or path placement.

v53.2.2

@platejs/ai

Bug Fixes

  • Preserve streaming trailing whitespace with markdown hard breaks. (#5026)

@platejs/markdown

Bug Fixes

  • Serialize hard line breaks inside paragraph text nodes. (#5026)

v53.2.1...v53.2.2 · By @zbeyens

v53.2.1

@platejs/core

Bug Fixes

  • Add node.isMetadataProp and editor.api.isElementStateEmpty for element state checks. (#5029)

platejs

Bug Fixes

  • Updated @platejs/core, @platejs/utils.

@platejs/utils

Bug Fixes

  • Fix block placeholders on single empty list items. (#5029)

v53.2.0...v53.2.1 · By @zbeyens

v53.1.6

@platejs/ai

Bug Fixes

  • Updated @platejs/selection.

@platejs/selection

Bug Fixes

  • Fix block selection copy and cut in Safari by writing selected blocks to the native clipboard event. (#5018)

v53.1.5...v53.1.6 · By @zbeyens

v53.1.5

@platejs/ai

Bug Fixes

  • Updated @platejs/markdown.

@platejs/markdown

Bug Fixes

  • Fix markdown deserialization from crashing on malformed HTML-like MDX input. (#5016)

v53.1.4...v53.1.5 · By @zbeyens

v53.1.2

@platejs/core

Bug Fixes

  • Fix complex leaf and text renderers triggering React hook-order warnings when marks change. (#5009)

platejs

Bug Fixes

  • Updated @platejs/core, @platejs/utils.

@platejs/utils

Bug Fixes

  • Updated @platejs/core.

v53.1.1...v53.1.2 · By @zbeyens

v53.1.1

@platejs/ai

Bug Fixes

  • Updated @platejs/markdown.

@platejs/markdown

Bug Fixes

  • Fix MDX fallback deserialization for GFM tables containing plain less-than text. (#5007)

v53.1.0...v53.1.1 · By @kiranmagic7

v53.1.0

@platejs/docx-io

Features

  • Forward two dropped options in exportToDocx: (#4997)

    • pageSize — the html-to-docx engine accepts a page size, but exportToDocx only forwarded margins and orientation, so the document was always the default (US Letter). You can now pass e.g. pageSize: { width: 11906, height: 16838 } to export A4.
    • fontFamily — it was only applied to the serialized HTML (and only when an EditorStaticComponent was provided), so the document default font was never set and Word fell back to Times New Roman. It now also sets the document default font (documentOptions.font).

@platejs/dnd

Bug Fixes

  • Clear stale DnD drop indicators when dragging from a block into editor whitespace. (#5002)

v53.0.9...v53.1.0 · By @WilliamPeralta, @kiranmagic7

v53.0.8

@platejs/docx-io

Bug Fixes

  • Fix exportToDocx adding blank paragraphs at the top of the document. wrapHtmlForDocx emitted a <!DOCTYPE html> and indented the template; html-to-docx (html-to-vdom) keeps the DOCTYPE and the whitespace-only text nodes between tags and renders each as a blank paragraph. The wrapper now emits tight markup with no DOCTYPE. (#4991)

v53.0.7...v53.0.8 · By @WilliamPeralta

v53.0.7

@platejs/ai

Bug Fixes

  • Updated @platejs/table.

@platejs/core

Bug Fixes

  • Add transformInitialValue and nodeId.initialValueIds while keeping normalizeInitialValue as a deprecated alias (#4987)

  • Improve large-document mount and render performance across core element, mark, and nodeId paths (#4987)

    • Cut 10k mixed-document core mount time from 1240.60 ms to 468.26 ms without nodeId (62.3%, 2.65x faster)
    • Cut 10k mixed-document core mount time from 1290.66 ms to 477.73 ms with nodeId (63.0%, 2.70x faster)
    • Cut mixed-document nodeId overhead over core from +50.06 ms to +9.46 ms (81.1% smaller)
    • Cut duplicate-id paste cost from 20.06 ms to 13.79 ms (31.2%, 1.45x faster)
    • Cut 10k code-only mount time from 1500.30 ms to 496.47 ms (66.9%, 3.02x faster) and shrink the code-only tax over core from +280.75 ms to +27.89 ms (90.1% smaller)
    • Bring the current 10k core and basic large-document mount lanes to Plite parity or better (core -3.5%, core + nodeId -1.6%, basic -1.2%)
    • Preserve Plite children for void render.as tags and Plite attributes on simple leaf/text render paths

platejs

Bug Fixes

  • Updated @platejs/core, plitejs, @platejs/utils.

plitejs

Bug Fixes

  • Add experimental editor.tf.setNodesBatch for exact-path node prop updates on large documents (#4987)

    • Cut the large-document set_node hot path from 18.56 ms to 2.63 ms at 1k blocks (7.05x faster)
    • Cut the same path from 118.54 ms to 4.92 ms at 5k blocks (24.10x faster)
    • Let @platejs/core batch live nodeId normalization instead of paying one setNodes call per missing id
    • Keep editor.tf.setNodesBatch explicitly temporary. It is experimental and will be removed in a future release
  • Updated plite-hyperscript. (231b986)

@platejs/table

Bug Fixes

  • Speed up unmerged table range selection while preserving merged-cell handling (#4987)

@platejs/utils

Bug Fixes

  • Updated @platejs/core, plitejs.

v53.0.6...v53.0.7 · By @zbeyens, @github-actions[bot]

v53.0.6

@platejs/core

Bug Fixes

  • Fix .configure({ inputRules }) losing rules on subsequent editor instances (#4983)

    The user's config object was shared across resolutions via closure; clearing inputRules on the first resolve left later editors (StrictMode remounts, HMR, multi-editor pages) with no configured rules.

  • Fix createTextSubstitutionInputRule not firing on the final character of flat matches (e.g. ->, (c)©) (#4983)

platejs

Bug Fixes

  • Updated @platejs/core, @platejs/utils.

@platejs/utils

Bug Fixes

  • Updated @platejs/core.

v53.0.5...v53.0.6 · By @bbyiringiro

v53.0.3

@platejs/ai

Bug Fixes

  • Clear block streaming state when aiChat.stop() stops generation (#4945)

@platejs/link

Bug Fixes

  • Fix empty link normalization when suggestion acceptance removes the last link character (#4945)

platejs

Bug Fixes

  • Updated @platejs/utils.

@platejs/suggestion

Bug Fixes

  • Fix inline-void delete and replace suggestions around mentions and paragraph boundaries (#4945)

@platejs/utils

Bug Fixes

  • Add a trailing-block insert hook for normalization-driven insert behavior (#4945)

CHANGELOG · v53.0.2...v53.0.3 · By @felixfeng33

behavior
block-discussiondiscussion-kitcomment-kit

Rebuild discussion indexes from editor state so accept and reject updates, inline text summaries, and deleted comments stay current.

fix
suggestionsuggestion-base-kitsuggestion-kitsuggestion-node

Fix block and inline suggestion regressions around inline voids, links, line breaks, block voids, and trailing-block normalization.

behavior
block-listcode-drawing-nodedate-nodeequation-nodeexcalidraw-nodemedia-audio-nodemedia-embed-nodemedia-file-nodemedia-image-nodemedia-video-nodemention-nodelink-node

Keep Plite children mount points and suggestion wrappers stable for static and media-style nodes.

v53.0.0

@platejs/autoformat

Breaking Changes

  • Deprecate @platejs/autoformat. Markdown shortcuts and text substitutions are now authored as inputRules on each feature plugin, and AutoformatPlugin remains only as an inert compatibility export. (#4941)

    Migration:

    1. Remove AutoformatPlugin from your plugins and replace @platejs/autoformat after migrating rules.
    2. Replace each old AutoformatRule with the matching rule factory on the plugin that owns the feature. See the table below.
    3. Replace symbol substitutions (arrows, fractions, smart quotes, legal, math operators) with createTextSubstitutionInputRule registered on a local createBasePlugin.
    4. Replace rules[].query with enabled on the rule factory call. Replace the global code-block guard with a per-plugin enabled check.
    5. Drop enableUndoOnDelete — undo-on-delete is the built-in behavior.
    6. Replace custom AutoformatRule definitions with createRuleFactory from platejs.
    // Before
    import { AutoformatPlugin } from "@platejs/autoformat";
     
    const editor = createPlateEditor({
      plugins: [
        AutoformatPlugin.configure({
          options: {
            enableUndoOnDelete: true,
            rules: [
              { match: "# ", mode: "block", type: KEYS.h1 },
              { match: "**", mode: "mark", type: KEYS.bold },
              {
                match: "* ",
                mode: "block",
                type: "list",
                format: (editor) =>
                  toggleList(editor, { listStyleType: KEYS.ul }),
              },
            ],
          },
        }),
      ],
    });
     
    // After
    import { BoldRules } from "@platejs/basic-nodes";
    import { BoldPlugin } from "@platejs/basic-nodes/react";
    import { HeadingRules } from "@platejs/basic-nodes";
    import { H1Plugin } from "@platejs/basic-nodes/react";
    import { BulletedListRules } from "@platejs/list";
    import { ListPlugin } from "@platejs/list/react";
     
    const editor = createPlateEditor({
      plugins: [
        H1Plugin.configure({ inputRules: [HeadingRules.markdown()] }),
        BoldPlugin.configure({
          inputRules: [BoldRules.markdown({ variant: "*" })],
        }),
        ListPlugin.configure({
          inputRules: [BulletedListRules.markdown({ variant: "-" })],
        }),
      ],
    });

    Rule Map

    Basic blocks — @platejs/basic-nodes

    Old ruleNew rule
    { match: '# '..'###### ', mode: 'block', type: KEYS.h1..h6 }HxPlugin.configure({ inputRules: [HeadingRules.markdown()] }) — register on each H1Plugin..H6Plugin
    { match: '> ', mode: 'block', type: KEYS.blockquote }BlockquotePlugin.configure({ inputRules: [BlockquoteRules.markdown()] })
    { match: ['---', '—-', '___ '], mode: 'block', type: KEYS.hr }HorizontalRulePlugin.configure({ inputRules: [HorizontalRuleRules.markdown({ variant: '-' }), HorizontalRuleRules.markdown({ variant: '_' })] })

    Basic marks — @platejs/basic-nodes

    Old ruleNew ruleOwning plugin
    { match: '**', mode: 'mark', type: KEYS.bold }BoldRules.markdown({ variant: '*' })BoldPlugin
    { match: '__', mode: 'mark', type: KEYS.underline }UnderlineRules.markdown()UnderlinePlugin
    { match: '*', mode: 'mark', type: KEYS.italic }ItalicRules.markdown({ variant: '*' })ItalicPlugin
    { match: '_', mode: 'mark', type: KEYS.italic }ItalicRules.markdown({ variant: '_' })ItalicPlugin
    { match: '`', mode: 'mark', type: KEYS.code }CodeRules.markdown()CodePlugin
    { match: '~~', mode: 'mark', type: KEYS.strikethrough }StrikethroughRules.markdown()StrikethroughPlugin
    { match: '~', mode: 'mark', type: KEYS.sub }SubscriptRules.markdown()SubscriptPlugin
    { match: '^', mode: 'mark', type: KEYS.sup }SuperscriptRules.markdown()SuperscriptPlugin
    { match: '==', mode: 'mark', type: KEYS.highlight }HighlightRules.markdown({ variant: '==' })HighlightPlugin
    { match: '≡', mode: 'mark', type: KEYS.highlight }HighlightRules.markdown({ variant: '≡' })HighlightPlugin
    { match: '***', mode: 'mark', type: [bold, italic] }MarkComboRules.markdown({ variant: 'boldItalic' })BoldPlugin
    { match: '__*', mode: 'mark', type: [underline, italic] }MarkComboRules.markdown({ variant: 'italicUnderline' })BoldPlugin
    { match: '__**', mode: 'mark', type: [underline, bold] }MarkComboRules.markdown({ variant: 'boldUnderline' })BoldPlugin
    { match: '___***', mode: 'mark', type: [underline, bold, italic] }MarkComboRules.markdown({ variant: 'boldItalicUnderline' })BoldPlugin

    Register each family on its owning plugin:

    BoldPlugin.configure({
      inputRules: [
        BoldRules.markdown({ variant: "*" }),
        BoldRules.markdown({ variant: "_" }),
        MarkComboRules.markdown({ variant: "boldItalic" }),
        MarkComboRules.markdown({ variant: "boldUnderline" }),
        MarkComboRules.markdown({ variant: "boldItalicUnderline" }),
        MarkComboRules.markdown({ variant: "italicUnderline" }),
      ],
    });

    Code block — @platejs/code-block

    Old ruleNew rule
    { match: '```', mode: 'block', type: KEYS.codeBlock, format: insertEmptyCodeBlock }CodeBlockPlugin.configure({ inputRules: [CodeBlockRules.markdown({ on: 'match' })] })
    Old ruleNew rule
    { match: ['- ', '* '], mode: 'block', format: toggleList(..., { listStyleType: KEYS.ul }) }BulletedListRules.markdown({ variant: '-' }), BulletedListRules.markdown({ variant: '*' })
    { match: /^\d+\.$ |^\d+\)$ /, matchByRegex: true, format: toggleList(..., { listStyleType: KEYS.ol }) }OrderedListRules.markdown({ variant: '.' }), OrderedListRules.markdown({ variant: ')' })
    { match: '[] ', mode: 'block', format: toggleList(..., { listStyleType: KEYS.listTodo }) }TaskListRules.markdown({ checked: false })
    { match: '[x] ', mode: 'block', format: toggleList + setNodes({ checked: true }) }TaskListRules.markdown({ checked: true })
    ListPlugin.configure({
      inputRules: [
        BulletedListRules.markdown({ variant: "-" }),
        BulletedListRules.markdown({ variant: "*" }),
        OrderedListRules.markdown({ variant: "." }),
        OrderedListRules.markdown({ variant: ")" }),
        TaskListRules.markdown({ checked: false }),
        TaskListRules.markdown({ checked: true }),
      ],
    });

    Math — @platejs/math

    Old ruleNew rule
    Inline equation $…$InlineEquationPlugin.configure({ inputRules: [MathRules.markdown({ variant: '$' })] })
    Block equation $$…$$EquationPlugin.configure({ inputRules: [MathRules.markdown({ on: 'break', variant: '$$' })] })

    Link — @platejs/link

    Old behaviorNew rule
    [text](url) markdownLinkRules.markdown()
    Autolink on pasteLinkRules.autolink({ variant: 'paste' })
    Autolink on spaceLinkRules.autolink({ variant: 'space' })
    Autolink on EnterLinkRules.autolink({ variant: 'break' })
    LinkPlugin.configure({
      inputRules: [
        LinkRules.markdown(),
        LinkRules.autolink({ variant: "paste" }),
        LinkRules.autolink({ variant: "space" }),
        LinkRules.autolink({ variant: "break" }),
      ],
    });

    Text substitutions (arrows, fractions, legal, math operators, smart quotes)

    Move these to a local createBasePlugin with createTextSubstitutionInputRule:

    import {
      createBasePlugin,
      createTextSubstitutionInputRule,
      KEYS,
    } from "platejs";
     
    const isTextSubstitutionBlocked = (editor) =>
      editor.api.some({ match: { type: [editor.getType(KEYS.codeBlock)] } });
     
    const ShortcutsPlugin = createBasePlugin({
      key: "shortcuts",
      inputRules: [
        createTextSubstitutionInputRule({
          enabled: ({ editor }) => !isTextSubstitutionBlocked(editor),
          patterns: [
            { format: "→", match: "->" },
            { format: "⇒", match: "=>" },
            { format: "½", match: "1/2" },
            { format: "™", match: ["(tm)", "(TM)"] },
            { format: ["“", "”"], match: '"' },
          ],
        }),
      ],
    });

    Each pattern set is just data — autoformatArrow, autoformatLegal, autoformatMath, autoformatPunctuation, autoformatSmartQuotes, and autoformatLegalHtml from the old package map 1:1 onto patterns arrays. AutoformatKit in the Plate registry is pre-built with all of them.

    Custom rules

    Old AutoformatRule objects have no direct replacement. Build a rule family with createRuleFactory:

    import { createRuleFactory } from "platejs";
     
    const MyRules = {
      markdown: createRuleFactory({
        type: "blockMatch",
        match: "!! ",
        format: "my-block",
      }),
    };
     
    MyPlugin.configure({ inputRules: [MyRules.markdown()] });

    Option removals

    • enableUndoOnDelete — removed. Backspace on a rule-inserted node restores the source text by default.
    • rules[].query — replaced by enabled on the rule factory call.
    • rules[].preFormat / rules[].format — replaced by rule-family format and resolve callbacks inside createRuleFactory.
    • rules[].trigger — rule families set their own trigger. Override it with the trigger option on a custom createRuleFactory call.

    See the Autoformat doc for the kit path and the Plugin Input Rules guide for the full runtime.

@platejs/basic-nodes

Breaking Changes

  • Store blockquotes as container blocks with block children. Lift every selected nested quoted block one level on Shift+Tab. Reset headings to paragraphs on Backspace at block start before any merge. (#4941)

    Migration:

    1. Update persisted values, fixtures, and tests to use block children instead of direct text children.
    2. Expect editor.tf.blockquote.toggle() to wrap or unwrap blocks instead of retagging one text block in place.
    3. Empty later quoted paragraphs delete in place on Backspace instead of jumping out of the quote.
    4. Backspace at the start of a heading now resets the heading to a paragraph before any merge.
    5. Legacy flat blockquote values still normalize on load, but persisted snapshots and fixtures should move to the new shape.
    // Before
    { type: 'blockquote', children: [{ text: 'Quote' }] }
     
    // After
    {
      type: 'blockquote',
      children: [{ type: 'p', children: [{ text: 'Quote' }] }],
    }

@platejs/code-block

Breaking Changes

  • Keep Backspace at the start of a non-empty first code line inside the code block. Merge an empty inner code line into the previous code line instead of unwrapping the block. (#4941)

@platejs/markdown

Breaking Changes

  • Round-trip blockquotes as nested block content instead of flat newline-packed text. Serialize image titles from node.title instead of copying the caption into the markdown title slot. Preserve MDX media attribute expressions during markdown serialization instead of stringifying them into JSON text. Serialize plain URL links back to bare URL markdown instead of bracket-link form. Round-trip footnote references and definitions as dedicated footnote nodes instead of collapsing them to plain-text fallback. (#4941)

    Migration:

    1. Update snapshots and direct value assertions to expect blockquote.children to contain block nodes such as paragraphs and lists.
    2. If you generate initial editor values from markdown, hydrate blockquotes with paragraph children instead of flat text.
    3. If you want markdown output like ![alt](url "title"), set node.title. Images without a title now serialize as ![alt](url).
    4. If you serialize MDX media nodes with expression attributes like width={640}, expect those expressions to stay as expressions instead of turning into quoted JSON.
    5. Plain URL links such as https://platejs.org now serialize as bare URLs instead of [https://platejs.org](https://platejs.org).
    6. If you enable footnote-aware markdown input, install @platejs/footnote and include BaseFootnoteReferencePlugin and BaseFootnoteDefinitionPlugin so footnote nodes have real editor semantics instead of falling back to unknown node types.
    // Before
    { type: 'blockquote', children: [{ text: 'Quote\\nNext line' }] }
     
    // After
    {
      type: 'blockquote',
      children: [
        { type: 'p', children: [{ text: 'Quote' }] },
        { type: 'p', children: [{ text: 'Next line' }] },
      ],
    }

Bug Fixes

  • Write canonical date nodes as <date value="..."/> and round-trip normalized media embed metadata (#4941)

  • Preserve unknown MDX and raw HTML block source more faithfully during markdown deserialization fallback (#4941)

@platejs/table

Breaking Changes

  • Escalate the second selectAll from the current table to the whole document. (#4941)

@platejs/core

Features

  • Add lift as a break and delete rule action for blocks that should leave one ancestor level instead of resetting or exiting. Reset the trailing block to a paragraph when splitReset handles selected heading text. (#4941)

Bug Fixes

  • Add createRuleFactory for building input rule families with overridable defaults and required options (#4941)

  • Add useNavigationHighlight(path) for React node components that need the current navigation-feedback target without reading plugin options directly (#4941)

@platejs/footnote

Features

  • Add FootnoteReferencePlugin, FootnoteDefinitionPlugin, and FootnoteInputPlugin for real footnote nodes and inline [^ combobox insertion in Plate editors. (#4941)

@platejs/date

Bug Fixes

  • Store date nodes as canonical YYYY-MM-DD values and preserve unparseable legacy text as fallback data (#4941)

@platejs/link

Bug Fixes

  • Keep pasted URLs literal inside markdown link source entry by default (#4941)

@platejs/list

Bug Fixes

  • Allow list markdown rule families to override shared runtime rule fields while keeping semantic variant and checked options (#4941)

@platejs/media

Bug Fixes

  • Support allowlisted Twitter/X embed snippet extraction in media embed URL transforms (#4941)

  • Normalize supported media embeds into canonical provider metadata and preserve source URLs for embed editing (#4941)

plitejs

Bug Fixes

  • Updated slate, plite-dom. (081cbe9)

@platejs/toc

Bug Fixes

  • Add active section state to useTocElementState so TOC elements can mark the current heading while the document scrolls (#4941)

  • Fix TOC activation to navigate without entering block-selection mode (#4941)

@platejs/utils

Bug Fixes

  • Add KEYS.footnoteDefinition, KEYS.footnoteReference, and KEYS.footnoteInput (#4941)

CHANGELOG · v52.3.22...v53.0.0 · By @zbeyens, @github-actions[bot]

new
footnote-kit

Add GFM footnotes with reference, definition, and input plugins plus UI — hover preview, navigation flash, multi-reference picker, and duplicate-definition recovery.

new
footnote-base-kit

Add static footnote rendering for SSR and markdown pipelines.

new
editor-kiteditor-base-kit

Register the new footnote kits.

wiring
markdown-kit

Register the base footnote plugins and add `remark-emoji` so GFM footnotes and emoji shortcodes round-trip.

behavior

Add a Footnote insert entry wired to `action_footnote`.

wiring
transforms

Map `action_footnote` to `insertFootnote(editor, { select: true })`.

behavior
autoformat-kit

Reduce to symbol substitutions (arrows, fractions, legal, punctuation, smart quotes, sub/superscript). Markdown shortcuts move to the feature kits below. Add link automd so `[text](url)` closing on `)` resolves to a structured link.

Older releases