v0.48.0
v0.48.0 is a maintenance release focused on bug fixes across Markdown, tables, lists, links, and selection. It's headlined by a fix for a v0.46.0 regression that broke native text drag-and-drop (#8842) and a couple of notable security hardening fixes. It also adds a handful of new features, including an MdastHtmlExtension with examples for authoring custom Markdown constructs (collapsibles, kbd, alerts, footnotes), a customizable Yjs shared-type root name for collaborative editing, and new table row manipulation helpers.
@lexical/table— Added$moveTableRowfor reordering table rows, plus the previously missing$unmergeCellNodeexport (#8833)@lexical/yjs/@lexical/react— The Yjs shared-type root name is now customizable, so Lexical can share a Yjs document with other content that uses a different root key (#8841)@lexical/extension/@lexical/mdast— AddedMdastHtmlExtensionand Markdown custom-construct examples (collapsible sections,kbd, alerts, footnotes) demonstrating how to extend the Markdown ↔ mdast pipeline. See the Markdown & mdast serialization guide (#8826)
Drag & drop (fix for v0.46.0 regression)
- Don't cancel
dragoverfor text drags, so native drops work again (#8842)
Security
LinkNode.sanitizeUrl()now fails closed on unparseable URLs, preventing a potential XSS vector (#8846)- Fixed a
serialize-javascriptdependency vulnerability (#8803)
Markdown & code
- Roundtrip overlapping inline formats correctly through mdast/Markdown (#8825)
- Force re-tokenization after an async language load so highlighting appears once the grammar is ready (#8830)
Tables
- Auto-scroll while drag-selecting cells past the visible edge (#8822)
- Enable table copy in read-only mode (#8845)
Lists & character limit
- Backspace at the start of a list item now outdents or converts to a paragraph (#8829)
- Merge adjacent
OverflowNodes inuseCharacterLimit(#8831) - Count block separators when wrapping character-limit overflow (#8840)
Links & selection
- Disable link opening for disabled autolinks (#8839)
- Skip
scrollIntoViewIfNeededwhen the selection rect is above the editor, fixing a Safari RTL caret jump (#8848)
- [lexical-mdast][lexical-markdown] Bug Fix: Roundtrip overlapping inline formats by @etrepum in https://github.com/facebook/lexical/pull/8825
- [lexical-table][lexical-playground] Bug Fix: Auto-scroll while drag-selecting cells past the visible edge by @JohnJunior in https://github.com/facebook/lexical/pull/8822
- [lexical-code-shiki] Bug Fix: force re-tokenize after async language load by @ochevallier in https://github.com/facebook/lexical/pull/8830
- [lexical-react] Bug Fix: Merge adjacent OverflowNodes in useCharacterLimit by @mayrang in https://github.com/facebook/lexical/pull/8831
- Open playground links in a new tab by @potatowagon in https://github.com/facebook/lexical/pull/8837
- [lexical-rich-text][lexical-plain-text] Bug Fix: don't cancel dragover for text drags so native drops work again by @etrepum in https://github.com/facebook/lexical/pull/8842
- [lexical-link] Bug Fix: disable link opening for disabled autolink in… by @ochevallier in https://github.com/facebook/lexical/pull/8839
- [lexical-table] Feature: Add $moveTableRow function & Add missing export for $unmergeCellNode by @hamo-o in https://github.com/facebook/lexical/pull/8833
- [lexical-list] Bug Fix: Backspace at start of list item outdents or converts to paragraph by @mayrang in https://github.com/facebook/lexical/pull/8829
- [lexical-yjs][lexical-react] Feature: Customizable Yjs shared-type root name by @mayrang in https://github.com/facebook/lexical/pull/8841
- [lexical] Chore: Fix serialize-javascript package dependency vulnerability by @vijayojha89 in https://github.com/facebook/lexical/pull/8803
- [lexical-react] Bug Fix: Count block separators in character limit overflow wrapping by @mayrang in https://github.com/facebook/lexical/pull/8840
- Fix: fail closed in LinkNode.sanitizeUrl() on unparseable URLs (XSS) by @xiezhenjia-meta in https://github.com/facebook/lexical/pull/8846
- [lexical-extension][lexical-mdast][dev-mdast-editor-example] Feature: Add MdastHtmlExtension and Markdown custom-construct examples (collapsible, kbd, alerts, footnotes) by @etrepum in https://github.com/facebook/lexical/pull/8826
- [lexical-react][lexical-table] Bug Fix: Enable table copy in read-only mode by @mayrang in https://github.com/facebook/lexical/pull/8845
- Skip scrollIntoViewIfNeeded when the selection rect is above the editor (Safari RTL caret jump) by @jeremy in https://github.com/facebook/lexical/pull/8848
- @JohnJunior made their first contribution in https://github.com/facebook/lexical/pull/8822
- @jeremy made their first contribution in https://github.com/facebook/lexical/pull/8848
Full Changelog: https://github.com/facebook/lexical/compare/v0.47.0...v0.48.0
Release 2026-07-16 15:05
Release 2026-07-16 15:05
- benchmarks: client-side CPU benchmark scenario suite (#7732) (208100b7c0) by @Sheraff
- start-plugin-core: support Rsbuild preview SSR middleware (#7372) (e499164c72) by @elecmonkey
- benchmarks: Solid v2 type fixes for new benchmark scenarios (2bb318bdcf) by @brenelz
- benchmarks: adapt new solid benchmarks from main to Solid v2 (26d94d93fc) by @brenelz
- lockfile: restore @rspack/binding@2.0.8 platform binaries (01dbb52d06) by @brenelz
- ci: release workflow OOM increase node max-old-space (#7723) (8bdb21e062) by @Sheraff
- ci: release workflow OOM during update-example-deps lockfile update (#7722) (572fb2b860) by @Sheraff
- router-core: preserve percent-encoded URL-unsafe chars in decodeSegment (#7695) (9809a0619d) by @CDillinger
- start-client-core: zero-copy frame payload extraction (#7662) (ba52d2b8f9) by @anonrig
- router-core: cache lightweight route matches (#7601) (a415471437) by @Sheraff
- @tanstack/react-router@1.170.17
- @tanstack/react-start@1.168.27
- @tanstack/react-start-client@1.168.15
- @tanstack/react-start-rsc@0.1.26
- @tanstack/react-start-server@1.167.21
- @tanstack/router-cli@1.167.18
- @tanstack/router-core@1.171.14
- @tanstack/router-generator@1.167.18
- @tanstack/router-plugin@1.168.19
- @tanstack/router-vite-plugin@1.167.19
- @tanstack/solid-router@2.0.0-beta.24
- @tanstack/solid-router-devtools@2.0.0-beta.19
- @tanstack/solid-router-ssr-query@2.0.0-beta.25
- @tanstack/solid-start@2.0.0-beta.25
- @tanstack/solid-start-client@2.0.0-beta.24
- @tanstack/solid-start-server@2.0.0-beta.24
- @tanstack/start-client-core@1.170.13
- @tanstack/start-plugin-core@1.171.19
- @tanstack/start-server-core@1.169.16
- @tanstack/start-static-server-functions@1.167.18
- @tanstack/start-storage-context@1.167.16
- @tanstack/vue-router@1.170.16
- @tanstack/vue-start@1.168.26
- @tanstack/vue-start-client@1.167.18
- @tanstack/vue-start-server@1.167.21
@tanstack/solid-start@2.0.0-beta.25
-
#7813
ebe104c- Upgradesolid-jsand@solidjs/webto2.0.0-beta.17 -
#7813
ebe104c- Upgradesolid-jsand@solidjs/webto2.0.0-beta.18 -
#7813
ebe104c- Upgradesolid-jsand@solidjs/webto2.0.0-beta.19andvite-plugin-solidto3.0.0-next.11 -
Updated dependencies [
ebe104c,ebe104c,ebe104c,ebe104c]:- @tanstack/solid-router@2.0.0-beta.24
- @tanstack/solid-start-client@2.0.0-beta.24
- @tanstack/solid-start-server@2.0.0-beta.24
@tanstack/solid-router@2.0.0-beta.24
-
#7813
ebe104c- Upgradesolid-jsand@solidjs/webto2.0.0-beta.17 -
#7813
ebe104c- Upgradesolid-jsand@solidjs/webto2.0.0-beta.18 -
#7813
ebe104c- Upgradesolid-jsand@solidjs/webto2.0.0-beta.19andvite-plugin-solidto3.0.0-next.11 -
#7813
ebe104c- Suspend on the matchloadPromiseonly during SSR. On the client, suspending on the pending match kept a live async source in the tree, which sincesolid-js@2.0.0-beta.16routed signal writes into a transition hold and broke synchronous write-then-load flows such asinvalidate()on anotFoundmatch.
@tanstack/solid-start-client@2.0.0-beta.24
-
#7813
ebe104c- Upgradesolid-jsand@solidjs/webto2.0.0-beta.17 -
#7813
ebe104c- Upgradesolid-jsand@solidjs/webto2.0.0-beta.18 -
#7813
ebe104c- Upgradesolid-jsand@solidjs/webto2.0.0-beta.19andvite-plugin-solidto3.0.0-next.11 -
Updated dependencies [
ebe104c,ebe104c,ebe104c,ebe104c]:- @tanstack/solid-router@2.0.0-beta.24
@tanstack/solid-start-server@2.0.0-beta.24
-
#7813
ebe104c- Upgradesolid-jsand@solidjs/webto2.0.0-beta.17 -
#7813
ebe104c- Upgradesolid-jsand@solidjs/webto2.0.0-beta.18 -
#7813
ebe104c- Upgradesolid-jsand@solidjs/webto2.0.0-beta.19andvite-plugin-solidto3.0.0-next.11 -
Updated dependencies [
ebe104c,ebe104c,ebe104c,ebe104c]:- @tanstack/solid-router@2.0.0-beta.24
@tanstack/solid-router-devtools@2.0.0-beta.19
-
#7813
ebe104c- Upgradesolid-jsand@solidjs/webto2.0.0-beta.17 -
#7813
ebe104c- Upgradesolid-jsand@solidjs/webto2.0.0-beta.18 -
#7813
ebe104c- Upgradesolid-jsand@solidjs/webto2.0.0-beta.19andvite-plugin-solidto3.0.0-next.11 -
Updated dependencies [
ebe104c,ebe104c,ebe104c,ebe104c]:- @tanstack/solid-router@2.0.0-beta.24
astro@7.1.0
-
#17302
5f4dc03Thanks @astrobot-houston! - Adds a newdeferRenderoption to theglob()content loaderWhen set to
true, renderable entries (such as Markdown) are not rendered during content sync. Instead, rendering is deferred until the entry is actually rendered in a page, using the same on-demand path that.mdxfiles already use.This reduces memory usage during
astro buildfor large collections whose rendered output is much larger than the source — for example, Markdown that uses heavy rehype plugins likerehype-katex. Such builds could previously run out of memory while storing the eagerly-rendered HTML for every entry.// src/content.config.ts import { defineCollection } from 'astro:content'; import { glob } from 'astro/loaders'; const docs = defineCollection({ loader: glob({ pattern: '**/*.md', base: 'src/content/docs', deferRender: true }), });
By default
deferRenderisfalse, preserving the existing behavior of rendering entries eagerly during sync so their rendered HTML can be cached across builds. -
#17296
30698a2Thanks @ematipico! - Adds a new experimentalcollectionStorageoption for controlling how the content layer persists its data storeBy default, Astro serializes the entire content layer data store to a single file (
.astro/data-store.json). For very large content collections, this file can grow large enough to hit platform file-size limits.Set
experimental.collectionStorage: 'chunked'to instead split the data store across many smaller, content-addressed files inside a.astro/data-store/directory, described by a manifest:// astro.config.mjs import { defineConfig } from 'astro/config'; export default defineConfig({ experimental: { collectionStorage: 'chunked', }, });
Because each part file is named by a hash of its contents, unchanged parts keep the same name across builds and are not rewritten, and identical parts are deduplicated. The default value is
'single-file', which preserves the current behavior. -
#17214
44c4989Thanks @ematipico! - Adds support for the more specific CSP directivesscript-src-elem,script-src-attr,style-src-elem, andstyle-src-attrthrough a newkindoption.Previously,
CSPwas only scoped to genericscript-src/style-srcdirectives. Now each source or hash can be scoped to a narrower directive — for example, to allow inlinestyleattributes (such as those fromdefine:varsor Shiki) without loosening the policy for your<style>and<link>elements.Each entry in
resourcesandhashescan be an object with akindproperty. Depending on whether you usescriptDirectiveorstyleDirective,"element"targetsscript-src-elemorstyle-src-elem,"attribute"targetsscript-src-attrorstyle-src-attr, and"default"(the same as a bare string or hash) targetsscript-srcorstyle-src.// astro.config.mjs import { defineConfig } from 'astro/config'; export default defineConfig({ security: { csp: { scriptDirective: { resources: [{ resource: 'https://cdn.example.com', kind: 'element' }], }, styleDirective: { resources: [{ resource: "'unsafe-inline'", kind: 'attribute' }], }, }, }, });
The same
kindoption is available on the runtime CSP API, where the existing methods now also accept an object:ctx.csp.insertScriptResource({ resource: 'https://cdn.example.com', kind: 'element' }); ctx.csp.insertStyleResource({ resource: "'unsafe-inline'", kind: 'attribute' });
-
#17258
84814d4Thanks @astrobot-houston! - Adds a newformat()option to thepaginateutility. Theformat()option is a function that accepts the current URL of the page, and returns a new URL.For example, when your host only supports URLs using the
.htmlextension, you can useformat()to add it to the generated URLs:--- export async function getStaticPaths({ paginate }) { // Load your data with fetch(), getCollection(), etc. const response = await fetch(`https://pokeapi.co/api/v2/pokemon?limit=150`); const result = await response.json(); const allPokemon = result.results; // Return a paginated collection of paths for all items return paginate(allPokemon, { pageSize: 10, format: (url) => `${url}.html`, }); } const { page } = Astro.props; ---
-
#17331
7db6420Thanks @matthewp! - Adds a--ignore-lockflag toastro devfor starting a dev server without checking or writing the lock file, so it can run alongside an already-running dev server for the same project.The new instance is not tracked by
astro dev stop,astro dev status, orastro dev logs.--ignore-lockcannot be combined with--background(or an auto-detected AI agent environment, which runs dev servers in the background automatically) or--force, since those rely on the lock file.astro dev --ignore-lock
-
#17389
16de021Thanks @florian-lefebvre! - Allows passing URL entrypoints when configuring the loggerMatching other APIs like session drivers or font providers, the logger entrypoint can now be a URL:
import { defineConfig } from 'astro/config'; export default defineConfig({ logger: { entrypoint: new URL('./logger.js', import.meta.url), }, });
-
#17332
4407483Thanks @astrobot-houston! - Fixes the JSON logger crashing withprocess is not definedin non-Node runtimes like Cloudflare's workerd. The JSON logger now usesconsole.log/console.errorinstead ofprocess.stdout/process.stderr, matching the pattern already used by the console logger. -
#17391
186a1e7Thanks @florian-lefebvre! - Fixes a case where an integration could not update the logger withupdateConfig() -
#17394
d9f99e1Thanks @matthewp! - Fixes element-specific CSP directives to preserve the existing behavior of configured script and style resources -
#17374
b2d1b3eThanks @astrobot-houston! - Fixes dev server returning 404 for?urlimported assets when accessed via browser navigation -
#17390
ed71eafThanks @florian-lefebvre! - Removes an unused and undocumented generic from theAstroLoggerDestinationtype -
#17393
092da56Thanks @matthewp! - Hardens generated transition styles, development metadata, and server island URLs when embedding dynamic values