github facebook/lexical v0.44.0

5 hours ago

v0.44.0 is a monthly release with a few minor breaking changes (deprecations), a notable new experimental DOMRenderExtension API for overriding DOM create/update/export, easier to use priority levels for registering commands, a pagination demonstration and convenient html import/export in the playground, better drag and drop support, automatic inline of CSS for HTML import, consistent CSP-safe style updates, and a wide range of bug fixes and other new features.

Breaking Changes

Deprecation of @lexical/offset OffsetView (#8350)

OffsetView / $createOffsetView never worked correctly, has no documentation, no tests, and no usage in the monorepo. It has been deprecated. The only function still in use, $createChildrenArray, is now exported from lexical itself — import it from lexical rather than @lexical/offset going forward.

Code block escape logic moved to CodeExtension (#8360)

The "press Enter three times to exit a CodeNode" logic has moved from CodeNode.insertNewAfter to a KEY_ENTER_COMMAND listener registered by CodeExtension. This fixes paste-with-blank-lines incorrectly escaping the code block. Using CodeNode without CodeExtension is now deprecated — a backwards-compatible shim with a dev-mode warning is in place, but the node is expected to stop working without CodeExtension in a future version.

New APIs

lexical / @lexical/html — Extensible DOM rendering and export (experimental) (#8353, #8368)

A new DOMRenderExtension (in @lexical/html) and EditorDOMRenderConfig (in lexical) parameterize $createDOM, $updateDOM, $exportDOM, $getDOMSlot, $shouldInclude, and $shouldExclude so that node rendering and export can be overridden via composable middleware. Use domOverride(nodes, config) to target one or more node classes, predicates, or '*' (wildcard), and call $next() from inside an override to delegate to the underlying implementation.

A new $decorateDOM(nextNode, prevNode, dom, editor) hook runs after a node is created/updated and after its children have been reconciled, intended for in-place attribute or DOM tweaks. Override ordering is a well-defined topological sort: wildcards highest, then predicates, then class hierarchy (subclass before superclass), with extension dependency order and registration order as tiebreakers.

Render-context APIs are also exposed: $withRenderContext, $getRenderContextValue, contextValue, contextUpdater, RenderContextRoot, RenderContextExport. New traversal helpers $generateDOMFromNodes and $generateDOMFromRoot populate a container using the configured render config. CreateEditorArgs.dom accepts a Partial<EditorDOMRenderConfig> to override rendering at editor creation. $isLexicalNode is also exported from lexical.

lexicalCOMMAND_PRIORITY_BEFORE_* priorities (#8375)

Five new command priorities — COMMAND_PRIORITY_BEFORE_EDITOR, _BEFORE_LOW, _BEFORE_NORMAL, _BEFORE_HIGH, _BEFORE_CRITICAL — register listeners that run most-recently-registered first, in front of the existing first-registered-first listeners at the same priority. Ordering is: highest priority first, then all BEFORE_* listeners (LIFO), then legacy listeners (FIFO). The new priorities are almost always what you want for new code; legacy priorities are unchanged so this is purely additive. See the new "Priorities and ordering" docs.

@lexical/code-prismCodePrismExtension & @lexical/code-shikiCodeShikiExtension (#8346)

Both packages now export proper extensions (CodePrismExtension, CodeShikiExtension) with {disabled, tokenizer} signal-based configuration that can be toggled and hot-swapped at runtime. The legacy CodeHighlighterShikiExtension is kept as a deprecated backwards-compatible shim.

@lexical/link / @lexical/react — Custom AutoLink punctuation (#8378)

AutoLinkExtension, registerAutoLink, and LexicalAutoLinkPlugin now accept an optional punctuation setting to override the default boundary characters (e.g. to allow colon-delimited matches without breaking URLs that contain colons).

@lexical/utilsremoveEmptyDestination for split-at-caret (#8384)

SplitAtPointCaretNextOptions (used by $insertNodeToNearestRootAtCaret and $splitAtPointCaretNext) gains a removeEmptyDestination option for finer control over whether an empty destination is replaced entirely.

@lexical/clipboard — Shared drop handlers (#8373)

New $handleRichTextDrop and $handlePlainTextDrop helpers implement Lexical-aware text drag-and-drop, including same-block drags, cross-TextNode and cross-block drops, DecoratorNode preservation, and cross-editor drags. registerRichText and registerPlainText now wire these by default.

Stable APIs (no longer @experimental) (#8354)

@lexical/extension (since v0.36.1, Sep 2025) and the NodeState API in lexical (since v0.26.0, Feb 2025) are now formally stable.

Deprecations

  • @lexical/offset OffsetView / $createOffsetView (use $createChildrenArray from lexical) (#8350)
  • @lexical/text $findTextIntersectionFromCharacters — broken, untested, undocumented (#8364)
  • CodeHighlighterShikiExtension / CodeHighlighterShikiConfig (use CodeShikiExtension) (#8346)
  • Using CodeNode without CodeExtension (#8360)

Highlights

Core:

  • ⚠️ #8350 Deprecate OffsetView; export $createChildrenArray from lexical
  • 🆕 #8353 #8368 EditorDOMRenderConfig, DOMRenderExtension, domOverride, $decorateDOM, render context, $generateDOMFromNodes, $generateDOMFromRoot, $isLexicalNode, CreateEditorArgs.dom
  • 🆕 #8375 COMMAND_PRIORITY_BEFORE_* priorities for last-registered-called-first ordering
  • 🧹 #8354 Remove @experimental from Extension and NodeState APIs
  • #8356 Workaround for synchronous Firefox focus edge case where deferred callbacks were silently discarded
  • #8349 Resolve Firefox arrow-key navigation skipping over collapsible content
  • #8361 Fall back to non-shifted key matching for Option+number shortcuts on macOS

Clipboard / Rich Text / Plain Text:

  • #8373 Drag-and-drop within the same block now correctly moves the dragged text; DecoratorNodes and formatting are preserved across drops; cross-editor drags work even with two Lexical versions on the same page

Code:

  • ⚠️ #8360 Move three-Enter code-block escape logic to a KEY_ENTER_COMMAND listener in CodeExtension; fixes blank-line paste escaping the code block
  • 🆕 #8346 Add CodePrismExtension (@lexical/code-prism) and CodeShikiExtension (@lexical/code-shiki)
  • 🧹 #8330 Upgrade shiki to ^4.0.2

Extension:

  • #8328 Remove JSX/react type dependency from DecoratorTextNode
  • #8377 LexicalExtensionEditorComposer no longer disposes the editor on unmount; lifetime is the caller's responsibility (fixes nested/caption editors after remount)

HTML / Table:

  • 🆕 #8326 Inline CSS from <style> tags during HTML import (fixes paste from Excel, Outlook, etc.)
  • #8313 Merge nested lists into the parent <li> during HTML export, eliminating duplicate ordered-list numbering

Link:

  • 🆕 #8378 Allow custom punctuation for AutoLink boundaries

List:

  • #8382 Ensure ListItemNode always has a ListNode parent (orphans are merged or floated to root)
  • #8390 Toggle checklist items on mobile tap (iOS Safari / Android Chrome) via pointerup
  • #8313 Merge nested lists into parent <li> on HTML export

Markdown:

  • #8332 Replace negative lookbehind assertions for Safari < 16.4 compatibility
  • #8365 Add an undo history entry for markdown shortcut transforms so undo no longer also undoes the triggering keystroke
  • #8311 Escape ordered-list pattern (\d+\. ) inside bullet/check list item exports to fix double-escape on round-trip
  • #8381 Code spans take precedence over inline formatting in shortcut transforms (CommonMark behavior)

Playground:

  • 🆕 #8322 New PagesExtension with PageNode, PageContentNode, PageSetupNode for paginated documents and print-friendly output
  • 🆕 #8323 Animations for collapsible section expand/collapse and arrow rotation
  • 🆕 #8379 #8386 "Convert to HTML" toolbar button (round-trips through $generateHtmlFromNodes / $generateNodesFromDOM); HTML view formatted with prettier
  • 🆕 #8346 Migrate eight playground plugins to extensions (PageBreak, Twitter, YouTube, Figma, TabFocus, Collapsible, SpecialText, code-highlight) and remove the dead LinkPlugin and StickyPlugin files
  • #8385 NodeContextMenuPlugin falls back to the root node when the click target has no Lexical node, instead of showing an empty menu
  • #8388 Use @floating-ui/react for FloatingLinkEditorPlugin positioning; correctly handles all viewport boundaries and Firefox focusNode.parentElement quirks
  • #8392 Show floating link editor for single-character links (right-bias adjacent-link lookup)

React:

  • #8329 Prevent error when editorRef is null in LexicalEditorRefPlugin
  • #8366 Add yjs as an optional peer dependency for Yarn PnP compatibility
  • #8377 Don't auto-dispose editor from LexicalExtensionEditorComposer
  • #8385 Root-node fallback in NodeContextMenuPlugin

Text:

  • 🧹 #8364 Add deprecation notice to $findTextIntersectionFromCharacters

Utils:

  • #8384 Clean up and test $insertNodeToNearestRootAtCaret edge cases; add removeEmptyDestination to SplitAtPointCaretNextOptions

Refactor (CSP-safe styles):

  • 🧹 #8372 Replace runtime cssText / setAttribute('style', …) writes with property-based style updates across lexical, @lexical/code-core, @lexical/list, @lexical/table, @lexical/yjs, and the playground

Website:

  • 🆕 #8316 Add more examples to the demos gallery and statically capture screenshots with Playwright (replaces the third-party screenshot service)
  • #8369 Fix tailwindcss docusaurus config regression (sync, not async)
  • #8371 Add a dedicated tsconfig.json for lexical-website so type errors are actually surfaced in CI

Infrastructure:

  • 🧹 #8341 Encourage agents to use extensions and $config in AGENTS.md
  • 🧹 #8355 Refactor CommonJS scripts to ESM modules
  • 🧹 #8357 Cache build + Playwright before running e2e tests
  • 🧹 #8324 Override yaml to >=1.10.3 to fix CVE-2026-33532
  • 🧹 #8358 Address simple-git dependency vulnerability
  • 🧹 #8380 Address follow-redirects dependency vulnerability
  • 🧹 #8334 Remove example/fixture lockfiles from git to reduce Dependabot noise
  • 🧹 #8336 #8347 Update stale dev dependencies to resolve Dependabot alerts

What's Changed

  • v0.43.0 by @etrepum in #8319
  • [lexical-website] Feature: Add more examples to the demos gallery with local screenshot captures by @etrepum in #8316
  • Update examples for v0.43.0 by @etrepum in #8321
  • [lexical-playground]: Collapsible Section Animations by @ivailop7 in #8323
  • [*] Security: Override yaml to >=1.10.3 to fix CVE-2026-33532 by @potatowagon in #8324
  • [lexical-extension] Fix: Remove JSX dependency from DecoratorTextNode by @etrepum in #8328
  • [lexical-react] Bug Fix: Prevent error when editorRef is null by @Jimmy89 in #8329
  • [lexical-code-shiki] Chore: Upgrade shiki to ^4.0.2 by @etrepum in #8330
  • [lexical-markdown] Bug Fix: replace lookbehind assertions for Safari < 16.4 compatibility by @Yahid-Basha in #8332
  • chore: remove example/fixture lockfiles from git to reduce Dependabot noise by @thatmichael85 in #8334
  • chore: update stale dev dependencies to resolve Dependabot alerts by @thatmichael85 in #8336
  • build(deps): bump @docusaurus/faster from 3.9.2 to 3.10.0 by @dependabot[bot] in #8342
  • build(deps): bump semver from 7.7.2 to 7.7.4 by @dependabot[bot] in #8338
  • build(deps): bump y-websocket from 1.5.4 to 3.0.0 by @dependabot[bot] in #8343
  • build(deps): bump @docusaurus/* from 3.9.2 to 3.10.0, update typedoc, react by @dependabot[bot] in #8339
  • [*] Chore: Encourage agents to use extensions and $config in AGENTS.md by @etrepum in #8341
  • [lexical-code-prism][lexical-code-shiki][lexical-playground] Feature: Add CodePrismExtension, CodeShikiExtension, and migrate playground plugins to extensions by @etrepum in #8346
  • build(deps-dev): bump the dev-dependencies group across 1 directory with 42 updates by @dependabot[bot] in #8347
  • build(deps): bump zustand from 4.5.7 to 5.0.12 by @dependabot[bot] in #8340
  • [lexical-playground] Feature: Add PagesExtension by @ibastawisi in #8322
  • [lexical-html][lexical-table] Feature: Inline CSS from <style> tags by @tomsarduy in #8326
  • build(deps): bump pnpm/action-setup from 4 to 6 in the github-actions group across 1 directory by @dependabot[bot] in #8335
  • [Breaking Change][lexical-offset][lexical] Chore: Deprecate the broken/undocumented/untested OffsetView and export $createChildrenArray from lexical by @etrepum in #8350
  • [lexical][lexical-extension] Chore: Remove @experimental flag from Extension and NodeState APIs by @etrepum in #8354
  • [lexical] Bug Fix: Resolve Firefox arrow key navigation issue in collapsible nodes (#8348) by @MohmedIkram in #8349
  • [*] Chore: Cache build + playwright before running e2e tests by @etrepum in #8357
  • [lexical] Bug Fix: Workaround for synchronous firefox focus edge case behavior by @etrepum in #8356
  • address simple-git dependency vulnerability by @potatowagon in #8358
  • [lexical][lexical-playground] Fix: Use the fallback matching for number keys in keyboard shortcuts by @levensta in #8361
  • [Breaking Change][lexical-code] Bug Fix: move code block escape logic to KEY_ENTER_COMMAND listener by @anikakpillai in #8360
  • [*] Chore: Refactor CommonJS scripts to ESM modules by @etrepum in #8355
  • [lexical-text] Chore: Add deprecation notice to $findTextIntersectionFromCharacters by @etrepum in #8364
  • [lexical-markdown] Bug Fix: Add undo history entry for markdown shortcut transforms by @kimseongyu in #8365
  • [lexical-react] Bug Fix: Add 'yjs' as optional peer dependency for Yarn PnP compatibility by @grapgrap in #8366
  • [lexical][lexical-html] Feature: Extensible DOM create/update/export by @etrepum in #8353
  • [lexical-website] Bug Fix: Fix tailwindcss docusaurus config regression by @etrepum in #8369
  • [lexical-website] Bug Fix: Fix type checking for lexical-website package by @etrepum in #8371
  • [lexical-react] Bug Fix: Don't auto-dispose editor from LexicalExtensionEditorComposer by @etrepum in #8377
  • [lexical] Feature: COMMAND_PRIORITY_BEFORE_* priorities for last-registered-called-first order by @etrepum in #8375
  • [lexical-markdown] Bug Fix: Escape ordered-list pattern in bullet list item export by @Sathvik-Chowdary-Veerapaneni in #8311
  • address follow-redirects dependency vulnerability by @vishisht31 in #8380
  • [lexical-playground] Feature: HTML conversion button by @levensta in #8379
  • [lexical-markdown] Bug Fix: Code spans take precedence over inline formatting in shortcuts by @potatowagon in #8381
  • [lexical-list] Bug Fix: Ensure that ListItemNode always has a ListItem parent by @etrepum in #8382
  • [lexical][lexical-code-core][lexical-list][lexical-table][lexical-yjs] Refactor: make runtime style updates CSP-safe by @holly-agyei in #8372
  • [lexical-html][lexical-playground] Feature: Implement a well-defined ordering for DOMRenderExtension overrides and add $decorateDOM by @etrepum in #8368
  • [lexical][lexical-utils][lexical-list] Bug Fix: Clean up and test $insertNodeToNearestRootAtCaret edge cases by @etrepum in #8384
  • [lexical-clipboard][lexical-rich-text][lexical-plain-text] Bug Fix: Drag-and-drop within the same block by @etrepum in #8373
  • [lexical-list] Bug Fix: Merge nested list into parent
  • during HTML export by @Sathvik-Chowdary-Veerapaneni in #8313
  • [lexical-link][lexical-react] Feature: Allow custom punctuation for AutoLink boundaries by @holly-agyei in #8378
  • [lexical-playground] Feature: Format HTML conversion with prettier by @etrepum in #8386
  • [lexical-react] Bug Fix: Fall back to root node in NodeContextMenuPlugin when click target has no Lexical node by @mayrang in #8385
  • build(deps): bump @excalidraw/excalidraw from 0.18.0 to 0.18.1 by @dependabot[bot] in #8389
  • [lexical-playground] Refactor: Use @floating-ui/react for FloatingLinkEditorPlugin positioning by @mayrang in #8388
  • [lexical-list] Bug Fix: Toggle checklist items on mobile tap by @jWA86 in #8390
  • [lexical-playground] Bug Fix: Show floating link editor for single-character links by @mayrang in #8392
  • [lexical-extension] Bug Fix: Use maybeFromEditor in getPeerDependencyFromEditor by @potatowagon in #8398
  • [*] Fix Flow type errors in flow definition files by @potatowagon in #8396
  • [lexical] Chore: Fix uuid dependency vulnerability by @vishisht31 in #8399
  • [lexical-website] Set prettier arrowParens to avoid by @potatowagon in #8397

New Contributors

Full Changelog: v0.43.0...v0.44.0

Don't miss a new lexical release

NewReleases is sending notifications on new releases.