Skip to content

[Release] Version packages#4948

Merged
zbeyens merged 1 commit intomainfrom
changeset-release/main
Apr 23, 2026
Merged

[Release] Version packages#4948
zbeyens merged 1 commit intomainfrom
changeset-release/main

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot commented Apr 12, 2026

This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.

Releases

@platejs/autoformat@53.0.0

Major Changes

  • #4941 by @zbeyens – 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.

    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 createSlatePlugin.
    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 rule New 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 rule New rule Owning 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 rule New rule
    { match: '```', mode: 'block', type: KEYS.codeBlock, format: insertEmptyCodeBlock } CodeBlockPlugin.configure({ inputRules: [CodeBlockRules.markdown({ on: 'match' })] })

    Lists — @platejs/list and @platejs/list-classic

    Old rule New 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 }),
      ],
    });

    Replace @platejs/list with @platejs/list-classic imports when using the classic list model. The factory names are identical.

    Math — @platejs/math

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

    Link — @platejs/link

    Old behavior New rule
    [text](url) markdown LinkRules.markdown()
    Autolink on paste LinkRules.autolink({ variant: 'paste' })
    Autolink on space LinkRules.autolink({ variant: 'space' })
    Autolink on Enter LinkRules.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 createSlatePlugin with createTextSubstitutionInputRule:

    import {
      createSlatePlugin,
      createTextSubstitutionInputRule,
      KEYS,
    } from "platejs";
    
    const isTextSubstitutionBlocked = (editor) =>
      editor.api.some({ match: { type: [editor.getType(KEYS.codeBlock)] } });
    
    const ShortcutsPlugin = createSlatePlugin({
      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@53.0.0

Major Changes

  • #4941 by @zbeyens – 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.

    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@53.0.0

Major Changes

  • #4941 by @zbeyens – 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.

@platejs/markdown@53.0.0

Major Changes

  • #4941 by @zbeyens – 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.

    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' }] },
      ],
    }

Patch Changes

  • #4941 by @zbeyens – Write canonical date nodes as <date value="..."/> and round-trip normalized media embed metadata

  • #4941 by @zbeyens – Preserve unknown MDX and raw HTML block source more faithfully during markdown deserialization fallback

@platejs/table@53.0.0

Major Changes

  • #4941 by @zbeyens – Escalate the second selectAll from the current table to the whole document.

@platejs/core@53.0.0

Minor Changes

  • #4941 by @zbeyens – 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.

Patch Changes

  • #4941 by @zbeyens – Add createRuleFactory for building input rule families with overridable defaults and required options

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

@platejs/footnote@53.0.0

Minor Changes

  • #4941 by @zbeyens – Add FootnoteReferencePlugin, FootnoteDefinitionPlugin, and
    FootnoteInputPlugin for real footnote nodes and inline [^ combobox
    insertion in Plate editors.

@platejs/date@53.0.0

Patch Changes

  • #4941 by @zbeyens – Store date nodes as canonical YYYY-MM-DD values and preserve unparseable legacy text as fallback data

@platejs/link@53.0.0

Patch Changes

  • #4941 by @zbeyens – Keep pasted URLs literal inside markdown link source entry by default

@platejs/list@53.0.0

Patch Changes

  • #4941 by @zbeyens – Allow list markdown rule families to override shared runtime rule fields while keeping semantic variant and checked options

@platejs/list-classic@53.0.0

Patch Changes

  • #4941 by @zbeyens – Allow classic list markdown rule families to override shared runtime rule fields while keeping semantic variant and checked options

@platejs/media@53.0.0

Patch Changes

  • #4941 by @zbeyens – Support allowlisted Twitter/X embed snippet extraction in media embed URL transforms

  • #4941 by @zbeyens – Normalize supported media embeds into canonical provider metadata and preserve source URLs for embed editing

@platejs/slate@53.0.0

Patch Changes

@platejs/toc@53.0.0

Patch Changes

  • #4941 by @zbeyens – Add active section state to useTocElementState so TOC elements can mark the current heading while the document scrolls

  • #4941 by @zbeyens – Fix TOC activation to navigate without entering block-selection mode

@platejs/utils@53.0.0

Patch Changes

  • #4941 by @zbeyens – Add KEYS.footnoteDefinition, KEYS.footnoteReference, and KEYS.footnoteInput

@platejs/ai@53.0.0

@platejs/basic-styles@53.0.0

@platejs/callout@53.0.0

@platejs/caption@53.0.0

@platejs/code-drawing@53.0.0

@platejs/combobox@53.0.0

@platejs/comment@53.0.0

@platejs/csv@53.0.0

@platejs/cursor@53.0.0

@platejs/diff@53.0.0

@platejs/dnd@53.0.0

@platejs/docx@53.0.0

@platejs/docx-io@53.0.0

@platejs/emoji@53.0.0

@platejs/excalidraw@53.0.0

@platejs/find-replace@53.0.0

@platejs/floating@53.0.0

@platejs/indent@53.0.0

@platejs/juice@53.0.0

@platejs/layout@53.0.0

@platejs/math@53.0.0

@platejs/mention@53.0.0

platejs@53.0.0

@platejs/playwright@53.0.0

@platejs/resizable@53.0.0

@platejs/selection@53.0.0

@platejs/slash-command@53.0.0

@platejs/suggestion@53.0.0

@platejs/tabbable@53.0.0

@platejs/tag@53.0.0

@platejs/test-utils@53.0.0

@platejs/toggle@53.0.0

@platejs/yjs@53.0.0

@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 12, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
plate Ignored Ignored Preview Apr 23, 2026 0:26am

Request Review

@github-actions github-actions Bot requested a review from a team April 12, 2026 06:38
@codesandbox
Copy link
Copy Markdown

codesandbox Bot commented Apr 12, 2026

Review or Edit in CodeSandbox

Open the branch in Web EditorVS CodeInsiders

Open Preview

@dosubot dosubot Bot added size:S This PR changes 10-29 lines, ignoring generated files. release labels Apr 12, 2026
@github-actions github-actions Bot force-pushed the changeset-release/main branch from 878f1a4 to 2924a54 Compare April 23, 2026 12:26
@dosubot dosubot Bot added size:XL This PR changes 500-999 lines, ignoring generated files. and removed size:S This PR changes 10-29 lines, ignoring generated files. labels Apr 23, 2026
@zbeyens zbeyens merged commit 7b9b204 into main Apr 23, 2026
2 checks passed
@zbeyens zbeyens deleted the changeset-release/main branch April 23, 2026 12:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release size:XL This PR changes 500-999 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant