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

Plate UI

Remove CsvPlugin from the editor kit
remove
editor-plugins

Remove CsvPlugin and its platejs/csv import from the editor kit, and remove the csv-demo example. Spreadsheet copies still paste as tables through HTML, and tab-separated text pasted onto selected table cells fills them field by field.

Plate UI

Preserve Details titles when applying heading formats
fix
detailsdetails-staticheadingheading-static

Render a Details title that has a heading level with that heading's style, and center its toggle on the title's first line at the heading's own font size

fix
turn-into-toolbar-buttonblock-menuslash

Format a Details title in place when choosing Text or a heading, instead of breaking the title or inserting into its hidden body, with or without the Heading plugin

fix
turn-into-toolbar-buttonblock-menu

Keep list formatting when the schema refuses a block format, drop the bullet when a bulleted heading takes its own level, and show an H4 to H6 as a heading instead of Text in the block menu

fix
font-size-toolbar-button

Show the heading size of a Details title that has a heading level

Plate UI

Size editor side padding to the editor's own width
fix
editoreditor-static

Size the side padding of the default, demo and fullWidth variants to the editor's own width instead of the viewport. Padding shrinks to 24 px in a narrow editor, so a 180 px editor gets a 132 px text column instead of 52 px. Editors at least 512 px wide, or 640 px for fullWidth, keep their current padding.

fix
comment-democomment-overlap-democomment-persistence-democomment-review-demosuggestion-demosuggestion-format-demosuggestion-persistence-demosuggestion-view-demo

Size the editor's side padding to its own width instead of the viewport. Padding shrinks to 24 px in a narrow editor, and editors at least 600 px wide keep 48 px.

Plate UI

Lint text blocks with your own rules and fix findings from a caret popover
new
lint

Add LintKit, which configures BaseLintPlugin with two example rules that skip code blocks, wavy underlines by severity, and F8 and Shift+F8 to select the next and previous finding. LintPopover shows the finding under the caret with its fixes and Fix and next. useLintFindings and useLintFindingAt read the findings for your own UI.

fix
lint-demo

Add a lint example with a findings panel that runs, clears and applies the first fix, and a Check with server button backed by a stand-in rule that answers after 600 ms.

Plate UI

Keep empty media captions hidden on select, restore image preview and add the media toolbar to file, audio and video
behavior
captionmedia-imagemedia-audiomedia-embedmedia-filemedia-video

Keep an empty caption hidden while its media is selected, so selecting media no longer shifts the page. The caption shows once the caret enters it, such as through the media toolbar's Caption button, and Caption no longer takes an active prop.

  • Remove the active prop from Caption; it shows an empty caption only while the caret is inside it.
fix
media-imagemedia-preview-dialog

Open the image preview on double-click again; api.preview.open takes the image's path and URL. The preview renders above the page, centers the image, and closes on a backdrop click or Escape.

  • Call imagePlugin api.preview.open with the image's path and URL instead of the element.
behavior
media-filemedia-audiomedia-videomedia-imagemedia-toolbar

Select a file on click in an editable editor and open it on double-click. Show the media toolbar with Preview, Caption and delete while a file, audio or video node is selected. The image toolbar also gets Preview, which opens the image preview. The file and audio toolbars sit above their block, so neither covers the next block, and the audio selection ring fits the player. File and audio blocks get vertical padding so a selection ring does not overlap the block next to it, and a click in that padding selects the block instead of opening its caption. A click on an audio or video player selects that node and returns the keyboard to the editor, and Preview no longer keeps focus, so arrow keys keep moving the selection.

Plate UI

Read-only previews and HTML export create their editor with createEditor or useCreateEditor
wiring
commentcomment-review-demomarkdown-streaming-demo

Create each read-only preview editor with useCreateEditor from platejs/react, with the same plugins and dependencies as before.

wiring
html-export

Create the server page's export editor with createEditor from platejs and the client preview's editor with useCreateEditor from platejs/react, and keep rendering both through EditorStatic.

Plate UI

Suggestions paint each change in its own color and mark whole-block changes
behavior
suggestion

Paint every part of one change in one color, and each change in its own color, even when one person made them all.

new
suggestion

Mark a suggested line break, a removed line break, or a whole-block change such as a paragraph turned into a heading, in the left margin in its change's color.

behavior
suggestionmode-toolbar-button

Show a toast when Suggesting refuses a change that touches a code block, a table or a list item, and leave the document as it was. The mode menu switches to Suggesting only when the switch takes.

behavior
discussion

Accept and Reject on a suggestion card decide the change that card shows.

behavior
suggestion-demosuggestion-format-demosuggestion-view-demosuggestion-persistence-demo

Pass only authored={{ intent: 'propose' }} to a suggesting view.

  • Pass only the intent to a suggesting view: replace authored={{ intent: 'propose', projection: 'markup' }} with authored={{ intent: 'propose' }}.
behavior
version-history-demo

Restore a saved revision with its Restore button, as one edit you can undo. The per-author revert is removed.

Plate UI

Fix bullets and import warnings
fix
block-list-staticlist-static

Draw a bulleted item as a disc list inside its block, like numbered and to-do items, so saved HTML reads it back as a list and Word export writes a Word bullet list; bullets on toggles and images keep the root marker.

fix
import-toolbar-button

Show one "Imported with N warnings" toast that leaves out lossless cleanups, such as a removed <style>.

Plate UI

Refuse link form drafts that do not read as an address
behavior
link

Remove the forceSubmit state. The form saves a new or changed address that starts with http:// or https://, has another scheme such as mailto:, or starts with /, ./, ../, # or ?. It stays open on any other draft, such as www.example.com, and when allowedSchemes refuses the address. Editing only the link text keeps the stored address.

Plate UI

Open the link form with Cmd+K
fix
link

Fix Cmd+K, which did not open the link form. api.trigger() reads the editor's focus when focused is omitted, and returns false when the form stays closed.

Plate UI

Use neutral names for stored keys, exported files and comments data
rename
emoji-pickeremoji-data

Store frequent emojis under emoji-frequent:v1 and cached shortcodes under emoji-shortcodes:v1:<url>.

  • The picker no longer reads frequent emojis saved under the old key, so the list starts empty.
rename
export-toolbar-button

Name exported files document.html, document.md and document.docx.

rename
import-toolbar-buttoncomment-demo

Write comments data with kind: 'comments', the value platejs/comments reads.

rename
collaboration-demo

Use collaboration-demo as the demo's Yjs root and room id.

Plate UI

Rebuild the select editor as one field
behavior
select-editor

Replace SelectEditorContent, SelectEditorInput, SelectEditorCombobox and select-command.tsx with one SelectEditor. It keeps the chips as the only value, writes the form's value back whenever it differs from the chips, and passes ref, onBlur and ARIA props to the editable.

  • Replace SelectEditorContent, SelectEditorInput and SelectEditorCombobox with one SelectEditor that takes items, value or defaultValue, onValueChange and the editable's props.
fix
select-editor

Move the active option with ArrowUp and ArrowDown wherever the caret is, close the menu and clear the search on Escape and mod+Enter, and link a read-only chip to its url only when getLinkHref accepts it, so a chip with a script or malformed url shows without a link instead of breaking the field.

remove
select-editor

Ship tag.tsx, with the tag element plugin and its chip, in this item, and remove the separate tag item and the Radix dependencies.

  • Install select-editor instead of tag; it copies tag.tsx with the tag element plugin.

Plate UI

Name icon-only toolbar buttons for assistive tech
fix
toolbar

ToolbarButton uses a string tooltip as the button's accessible name when you pass no aria-label. Screen readers announce icon-only buttons such as Link by that name, and getByRole('button', { name: 'Link' }) finds them.

fix
turn-into-toolbar-buttonmode-toolbar-button

Name the button with its label and current value, such as "Turn into: Text" and "Editing mode: Editing". The mode button keeps its name when narrow screens hide its text.

fix
list-toolbar-buttonmedia-toolbar-button

Name both halves of each split button, such as "Bulleted list" and "Bulleted list styles", or "Image" and "Image options".

wiring
history-toolbar-buttonimport-toolbar-buttonexport-toolbar-buttontable-toolbar-buttoncomment-toolbar-buttonmore-toolbar-buttonemoji-toolbar-buttontable

Remove each aria-label that repeated the button's tooltip. The accessible names stay the same.

Plate UI

Fix demos whose starting document did not load
fix
editable-voids-demo

Use the demo plugin's element type, so the page loads.

fix
hundreds-editors-demo

Install BasicBlocksKit, so each editor loads its heading.

fix
plugin-rules-demo

Fix the code block's content and use the horizontalRule type, so the page loads.

fix
align-demo

Load the alignment document instead of an empty editor.

Plate UI

Let Tab nest list items with TabbableKit installed
fix
tabbable

Read the caret from the view's editor, so Tab and Shift+Tab nest and un-nest list items and stay in code blocks and tables. Tab at a paragraph's start or end moves focus, as it does mid-paragraph.

fix
tabbable-demo

Install TabbableKit and use the demo plugin's element type, so the page loads and shows the kit.

Plate UI

Restart and continue list numbering from the numbered list menu
new
list-toolbar-button

Add Restart numbering and Continue numbering to the numbered list menu.

wiring
block-listblock-list-static

Name each list with data-list-id and its level rules with data-list-levels, so HTML and DOCX export keep each list and its levels.

behavior
block-list-static

Write each item's indent, list id, level rules, restart, start, type and checked state on its li, so pasting the static HTML keeps them.

Plate UI

Export every block through the static kit
fix
export-toolbar-button

Fix HTML and Word export throwing on tables, task lists, callouts, columns, code blocks and images by drawing the file with BaseEditorKit as presentation.

fix
block-list-static

Drop the per-level margin-left on numbered and task lists, so static HTML indents a nested list once and Word takes its level from the block's indent.

fix
export-toolbar-button

Show an error toast when HTML or Word export throws, instead of failing with no message.

fix
docx-export

Move the Word look of callouts, code blocks, and empty equation and table of contents placeholders into DOCX_EXPORT_STYLES, because the package's DOCX drawings leave colors, fonts and sizes to the stylesheet.

fix
block-list-static

Draw the task checkbox inside its li and mark the li with data-checked, so Word export gives each task one paragraph with a ☑ or ☐ list marker.

fix
indent-static

Target images like IndentKit does, so a static editor loads and indents an image the live editor indented instead of throwing a schema error.

fix
list-static

Target images like ListKit does, so a static editor loads an image in a list and draws it as a list item.

Plate UI

Rebuild the emoji popup and picker on frimousse and Emojibase
new
emoji-data

Add a shared Emojibase catalog with GitHub shortcodes, loaded on first use from a pinned CDN release, cached in the browser, and ranked by shortcode before label and tag matches.

behavior
emoji

Define EmojiPlugin in the copied file, search emoji-data, insert the emoji as text, show a loading row that keeps Enter from splitting the block, and keep the popup closed inside code blocks.

  • Replace emojiPlugin with EmojiPlugin from the copied emoji file.
behavior
emoji-picker

Build the picker on frimousse with keyboard navigation, the ranked emoji-data search, a frequent row and an unavailable message, and take the trigger as the child with a required onEmojiSelect(emoji).

  • Pass the trigger as the picker's child and handle onEmojiSelect(emoji); the data, settings, closeOnSelect and disabled props and EmojiPickerTrigger are gone.
behavior
emoji-toolbar-buttoncallout

Insert the picked emoji at the selection as its own undo step and return focus to the editor; the callout sets its icon from the picker.

behavior
inline-combobox

Highlight the top result after each query until an arrow key or a scroll moves away, let Enter pick a result in the frame it appears, and take a loading prop that keeps Enter and Tab from editing while options load.

Plate UI

Install the package versions Plate declares and skip unused files
fix
export-toolbar-buttondocxexcalidrawcode-blockcode-block-codemirrorremote-cursor-overlaycollaboration-demo

Request the version range Plate declares for each npm package, such as juice@^11.0.1, xmlbuilder2@^3.1.1 and yjs@>=13.6.30, instead of the latest version.

fix
date-staticlink-staticmath-staticmention-staticdndeditor-aiaiai-apiai-menusettings-dialogexport-toolbar-buttoneditor-plugins-staticblock-menu

Stop installing files nothing imports: lib/inline-suggestion.ts, hooks/use-mobile.ts and the shadcn button. The four static items also stop requesting class-variance-authority.

Plate UI

Read the current user from the editor's userId
behavior
commentsuggestionimport-toolbar-button

Read the current user from editor.userId, so comments, replies and suggestion colors follow the editor's user.

  • Remove currentUserId from CommentsPlugin initialState and pass the same user as createEditor({ userId }).
behavior
mode-toolbar-button

Offer Suggestion mode whenever SuggestionPlugin is installed, including editors without a userId.

behavior
comment-democomment-overlap-democomment-persistence-democomment-review-demodiscussion-demosuggestion-demosuggestion-format-demosuggestion-persistence-demoplayground-demoversion-history-demoai-demoeditor-ai

Name the user once with the editor's userId, or run as the local user without one.

Plate UI

Give every selectable block a drag handle
behavior
dnd

Every selectable block gets a handle at any depth, such as blocks inside blockquotes, details, columns and table cells, and only the innermost hovered block shows its handle. The handle reads its blocks from editor.read.transfer.nodes, and a selected table no longer hides the editor's handles.

behavior
block-menu

Cut takes the blocks editor.read.transfer.nodes() returns, such as a list item with its nested items.

Plate UI

Move blocks, columns and table rows without dragging
behavior
dnd

Clicking a block's drag handle opens Move up, Move down and Cut, and Mod+Shift+ArrowUp / Mod+Shift+ArrowDown move the blocks around the caret. Dropping a block into another editor copies it, and Alt (Apple) or Ctrl copies inside one editor.

behavior
column

Clicking a column's drag handle opens Move left and Move right.

behavior
table

Clicking a row's drag handle opens Select row, Move up and Move down; the handle's label is "Drag row or open row actions".

behavior
block-menu

The right-click menu offers Move up, Move down and Cut.

Plate UI

Drag blocks natively, without React DnD
behavior
dnd

Drag handles start a native drag with editor.api.dom.drag.start, and DropIndicator paints useDropIndicator() in each view. DndKit needs no DndProvider, and the react-dnd dependencies are gone.

remove
column

The column handle drags its column natively; the vertical drop line comes from DndKit.

remove
table

The row handle drags its row natively; the drop line comes from DndKit.

behavior
media-imagemedia-video

Dragging media starts the same native block drag.

behavior
upload

Dropped files land at the edge under the pointer.

Plate UI

Open autocomplete popups over typed text instead of an inline input
behavior
inline-comboboxmentionslashemojifootnote

Open the popup when the trigger is typed and filter on the text after it, keeping the editor focused. Enter or Tab completes the active option in one undo step, Escape keeps the typed text, and IME preedit filters without selecting.

  • Mount MentionCombobox, SlashCombobox, EmojiCombobox and FootnoteCombobox through each plugin's slots.afterEditable; the input elements are gone.

Plate UI

Render streamed previews from the latest draft
behavior
ai-menumarkdown-streaming-demo

Render streamed previews from the latest draft, skipping drafts that were never shown when rendering falls behind the stream. The streaming demo's static output shows its status and parse error with the parse it renders. Both previews render only when their document changes, not on every streamed update. The AI draft's purple text is styled by its container instead of a decoration on every text, its end marker is read from the last block only, the fallback end marker stays mounted so the preview is not restyled whenever it appears or disappears, and the inline draft scrolls when it resizes instead of measuring layout after every render.

Plate UI

Remove the Markdown joiner transform
remove
markdown-joiner-transformai-api

Remove the Markdown joiner transform. The AI command route streams model text without buffering or added delays.

  • Remove experimental_transform: markdownJoinerTransform() from the AI command route and delete lib/markdown-joiner-transform.ts.

Plate UI

Parse Markdown as CommonMark with Plate tags
wiring
markdown

Configure MarkdownPlugin with remark-math, remark-gfm and remark-emoji only; Plate tags such as <callout> read without remark-mdx, and mentions read as [label](mention:ref) links.

  • Remove remarkMdx and remarkMention from MarkdownPlugin remarkPlugins; Plate tags are built in and mentions are [label](mention:ref) links.
wiring
markdown-to-editor-demo

Parse through the kit's MarkdownPlugin configuration instead of passing per-call remark plugins.

behavior
ai-api

Refer to Plate's Markdown tags instead of MDX in the generate, comment and common prompts.

Plate UI

Stream Markdown previews without AI chat and update only changed preview blocks
behavior
markdown-streaming-demo

Stream Markdown with editor.api.markdown.parseSlice instead of the AI chat preview: previews hide an unfinished trailing tag, Finish and Stop parse the draft strictly once, every parse continues the latest preview, and reset cancels without a final parse. The static preview renders each parse as the document of EditorView without editing its editor; the editable preview installs content plugins only and replaces only the changed blocks. The Markdown source, chunk size and delay are editable.

behavior
ai-menu

Render the AI draft as the document of the static preview editor instead of copying it into that editor on every chunk. The streaming end marker covers only the draft's last character, so it appears once when code highlighting splits the last line.

Plate UI

Use direct conversion contracts and preserve imported review data
wiring
import-toolbar-button

Parse HTML and Markdown through their installed format APIs, show successful conversion warnings, and prepare a replacement editor with imported Word comments through CommentsPlugin when available.

  • Pass the editor plugin list and an onImport editor-owner callback to ImportToolbarButton; the button prepares a complete detached replacement before the application swaps editors.
rename
export-toolbar-button

Use diagnosed HTML and Markdown serializers plus exportDocx, preserve one chosen accepted, proposed, or review projection, and export attached comment threads as Word comments.

  • Use exportDocx from platejs/docx/export; the exportToDocx alias does not exist on next.

Plate UI

Export one chosen document projection as HTML, Markdown, or Word
behavior
export-toolbar-button

Export HTML, Markdown, and Word from the same captured document revision. With unresolved suggestions, choose Include suggested changes or Exclude suggested changes. Export as Word with tracked changes preserves pending suggestions as Word revisions and reports conflicts that require resolution.

remove
export-toolbar-button

Remove Export as PDF and Export as Image, along with the html2canvas-pro and pdf-lib dependencies.

  • Remove html2canvas-pro and pdf-lib from your app when no other code uses them.
fix
export-toolbar-button

Inline the app's own stylesheets in HTML exports instead of linking the platejs.org stylesheet.

fix
editor-dropdown-menu

Complete close focus and dismissal before another trigger press so toolbar menus reopen on the first click after selecting an item.

fix
docx-demo

Set a current user so Suggestion mode records suggestions, and group contiguous typing into one visible suggestion and Word revision.

fix
import-toolbar-button

Link its DOCX registry metadata to the DOCX documentation page.

wiring
export-toolbar-button

Use the current editor's document-first HTML, Markdown, and DOCX exporters directly, with one captured projection and shared diagnostics.

wiring
docx-export

Keep the dependency-free copied presentation stylesheet while platejs/docx/export supplies semantic mappings for code blocks, columns, equations, callouts, headings, and tables of contents.

  • Keep DOCX_EXPORT_STYLES in copied app code; DOCX semantic mappings come from platejs/docx/export.

Plate UI

Choose an explicit upload provider
wiring
uploadupload-browserupload-r2upload-s3files-api

Install provider-neutral upload UI with an explicit browser-local, Cloudflare R2, or Amazon S3 provider; persistent providers share one gateway policy and install only their own adapter dependencies.

Plate UI

Install Files SDK uploads with a complete upload kit and private gateway
wiring
uploadfiles-apieditor-plugins

Install the Files SDK client and private document-scoped gateway together through the upload kit; the route requires application access policy and storage credentials.

wiring
mediaeditor-plugins-static

Render completed media separately while the upload schema owner omits unresolved drafts from static output.

Plate UI

Keep conversations discoverable when their document target is unavailable
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.

Plate UI

Own selected-item focus and typed block actions
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.

Plate UI

Use direct editor actions and complete generated installs
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.

Plate UI

AI Comment selection and recovery
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.

Plate UI

Save comment attachments with document revisions and preserve input when comment actions fail
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.

Plate UI

Compare saved revisions structurally
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.

Plate UI

Distinguish suggestion authors by color
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.

Plate UI

Explore formatting, projections, and saved proposals in the Suggestions examples
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.

Plate UI

Find opens and focuses the requested editor view
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.

Plate UI

Bind AI streams to the editor session
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.

Plate UI

Insert and convert blocks through their feature commands.
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.

Plate UI

Synchronize drawing scenes with document changes
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.

Plate UI

Use the editor-owned Find query with local search controls.
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.

Plate UI

Read current suggestion groups from the feature
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.

Plate UI

Display the current heading size and editing mode accurately.
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.

Plate UI

Keep DOCX bookmark names inside each document conversion
wiring
docx

Install the paste and import plugins; call exportDocx 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.

Plate UI

Keep media upload tasks active across draft view remounts
fix
mediamedia-upload

Admit picker, paste, and drop batches through one draft-slot protocol. Upload tasks survive view remounts, cancel when their keyed draft loses authority, expose local progress and retry state, and report each failure once through MediaKit.

Plate UI

Preserve editor state across streaming controls and clipboard failures
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.

Plate UI

Install AI and drag-and-drop integration with feature kits
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.

Plate UI

Use one text child for code blocks
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.

Plate UI

Keep comments attached through destructive edits and history
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.

Plate UI

Review comments and suggestions in application-owned Floating Discussion
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.

Plate UI

Inline local registry component prop shapes
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.

Plate UI

Use exact editor geometry for transient UI
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.

Plate UI

Use semantic Details blocks
rename
detailsdetails-staticdetails-toolbar-buttondetails-demo

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

Plate UI

Use canonical editor API names
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.

Plate UI

Inline required-value checks
remove
expect-defineddndinline-comboboxblock-discussionuse-chat

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

Plate UI

Select schema-defined blocks
behavior
block-selectiontable

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

Plate UI

Install Base-first registry code with eight shadcn styles
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.

Plate UI

Keep exact editor contracts application-owned
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.

Plate UI

Keep copied editor state compatible with React Compiler
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.

Plate UI

Select one or many nodes through the editor model
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.

Plate UI

Improve editor control accessibility and iframe security
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.

Plate UI

Complete the v54 editor document profile
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.

Plate UI

Colocate registry component state
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.

Plate UI

Keep default editor composition migration-free
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.

Plate UI

Localize editor UI policy
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.

Plate UI

Use the final Plate v54 document model
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.

Plate UI

Install copied editor features from one flat editor namespace
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.

Plate UI

Keep component behavior locally owned
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.

Plate UI

Keep optional editor features explicit
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.

Plate UI

Fix registry install dependencies
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.

Plate UI

Use runtime keys for TOC and DOCX navigation
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.

Plate UI

Use canonical node renderer props
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.

Plate UI

Infer node component props from 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

Plate UI

Use one table cell plugin and component
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.

Plate UI

Keep feature wiring explicit and package-owned
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.

Plate UI

Use plugin stores for editor-local state
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.

Plate UI

Use one script mark for subscript and superscript
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.

Plate UI

Bind static components without React plugin imports
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

Plate UI

Compose runtime-neutral Markdown, editor-owned footnotes, and Tabbable shortcuts
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.

Plate UI

Configure color palettes and recent colors
behavior
font-color-toolbar-buttontoolbarfixed-toolbar-buttonstable-node

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

Plate UI

Use installed feature plugins in toolbar controls
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.

Plate UI

Render media captions from direct inline children
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.

Plate UI

Use typed plugin portals
wiring
footnote-nodetable-nodetable-node-static

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

Plate UI

Use installed block insertion commands
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

Plate UI

PR 4945 · [codex] Fix discussion and suggestion regressions
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]

Plate UI

PR 4941 · fix: redesign blockquotes as container blocks
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