Skip to content

Media: track the original attachment id for edited images - #81803

Merged
ramonjd merged 13 commits into
trunkfrom
add/attachment-original-lineage
Oct 5, 2026
Merged

ramonjd merged 13 commits into
trunkfrom
add/attachment-original-lineage

Conversation

@ramonjd

@ramonjd ramonjd commented Aug 19, 2026 •

Copy link
Copy Markdown
Member

What?

Adds lineage tracking for attachments created by editing an image via /wp/v2/media/{id}/edit. Records the root/original attachment id on each derivative and exposes it in the REST response.

Part of #78077. Supersedes #78458.

Why?

When Gutenberg crops an image, Core's /edit creates an entirely new attachment with no stable pointer back to the image the lineage started from.

parent_image records only the immediate source; there is no root/original reference across crop-of-crop chains.

That means we can't navigate a crop back to its original in a performant way, that is, without getting each post up the change where parent_image exists.

How?

  • A dedicated postmeta key _wp_attachment_edit_root_id stores the root id, written once at edit time on the wp_edited_image_metadata hook. The new child inherits its parent's root, or the parent itself when the parent has no lineage, so reads are a single meta lookup, no chain walking.
  • gutenberg_get_edit_root_attachment_id( $id ) resolves the root, or returns $id when there's no lineage
  • A rest_prepare_attachment filter adds a root-level edit_root field holding the original's id, with an embeddable wp:edit-root link (mirrors featured_media), edit context only, and omits it when the original is unreachable (deleted/missing file). Root level because it describes a relationship between attachments, like post.
  • delete_attachment clears the pointer from descendants via a meta_key-indexed query

Scope / forward-only

Applies to every edit that goes through /edit — including the image block's crop tools in the post editor — on any site running the plugin; the media editor modal is the first consumer of the read side. No backfill: attachments edited before this lands are intentionally untracked.

Test plan

npm run test:unit:php:setup
npm run test:unit:php:base -- --filter Gutenberg_Original_Attachment_Filter_Test

No manual tests here — to test in the browser, use the follow-up UI PR: #81805

Summary by CodeRabbit

  • New Features

    • Media edited through the REST API now retains a link to its original attachment.
    • The original attachment is available in edit-context responses, including an embeddable REST link.
    • Original-attachment relationships are cleaned up when source media is permanently deleted.
  • Documentation

    • Added documentation for the new attachment metadata and REST response field.
  • Tests

    • Added coverage for lineage tracking, REST responses, editing, deletion cleanup, and visibility by context.

@github-actions github-actions Bot added the [Package] Core data /packages/core-data label Aug 19, 2026
@github-actions

github-actions Bot commented Aug 19, 2026 •

Copy link
Copy Markdown

Size Change: 0 B

Total Size: 7.92 MB

compressed-size-action

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@ramonjd
ramonjd force-pushed the add/attachment-original-lineage branch from c0aadcb to f99043d Compare August 27, 2026 05:58
@github-actions

github-actions Bot commented Aug 27, 2026 •

Copy link
Copy Markdown

Flaky tests detected in d01832e.
Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/33146216658
📝 Reported tests:

Should save the changes in /test/e2e/specs/editor/plugins/wp-editor-meta-box.spec.js, passed after 2 failed attempts.
TimeoutError: page.waitForFunction: Timeout 10000ms exceeded.
    at /home/runner/work/gutenberg/gutenberg/test/e2e/specs/editor/plugins/wp-editor-meta-box.spec.js:34:14
TimeoutError: locator.click: Timeout 10000ms exceeded.
Call log:
  - waiting for locator('role=button[name="Visual"i]')

    at /home/runner/work/gutenberg/gutenberg/test/e2e/specs/editor/plugins/wp-editor-meta-box.spec.js:33:55

@ramonjd

ramonjd commented Aug 27, 2026

Copy link
Copy Markdown
Member Author

Notes on the path to WordPress Core

The implementation here is hook-driven, but the sequence maps to Core in the following way:

  • The write happens on wp_edited_image_metadata. Core fires this inside WP_REST_Attachments_Controller::edit_media_item() at the same point where it already records parent_image.
  • gutenberg_get_original_attachment_id() becomes wp_get_original_attachment_id().
  • The rest_prepare_attachment filter becomes part of prepare_item_for_response() plus a registered schema property.

Because the plugin records lineage on every edit that goes through /edit, including the image block's crop tools, real lineage data will already exist on sites by the time a Core sync lands.

Two editing paradigms: editor vs. media library

It's worth noting the two image-editing models.

Media library (in-place)      Editor /edit (immutable + lineage)

 +--------------------+                +----------+     +----------+
 | attachment #42     |                | #42 root |<----| #57 crop |
 | file mutates       |                +----------+     +----------+
 | _backup_sizes      |                     ^
 |   full-orig, ...   |                     |           +----------+
 +--------------------+                     +-----------| #63 crop |
  restore: swap metadata back                           +----------+
  same id, all consumers change         restore: repoint consumer to #42
  • The Media library edits in place: one attachment, the file changes on disk, _wp_attachment_backup_sizes remembers the old files, and wp_restore_image() swaps them back. The id is stable, so every consumer of that id changes at once.
  • The /edit endpoint is immutable: each edit creates a new attachment and leaves the source untouched. Restore is not a file operation. Rather, it's repointing the consumer to the original attachment (this PR)

The two paradigm work in their own contexts, and shouldn't conflict:

  • edits in the media library create no attachments, so there's no lineage. Any id-based pointer created by /edit endpoint will survive an in-place file swap on the attachment.
  • wp_restore_image() remains the right restore mechanism for the media library, where "restore" means putting the old file back. It also acts universally, so wherever the attachment is used.
  • In the editor model, where every edit creates a new attachment, "restore" instead means pointing the block back at the original attachment. The meta in this PR makes that original findable. That model, where originals are never overwritten, is also the more natural base for a future media library view that groups crops under the image they came from.

@ramonjd ramonjd self-assigned this Aug 27, 2026
@ramonjd ramonjd added [Type] Enhancement A suggestion for improvement. [Feature] Media Anything that impacts the experience of managing media labels Aug 27, 2026
ramonjd added a commit that referenced this pull request Aug 27, 2026
Add a "Restore original image" button to the Crop sidebar tab. It appears
when the edited attachment exposes media_details.original_attachment (the
lineage root from the backend primitive). Clicking loads the original into
the cropper as a dirty preview:

- Save with no further crop repoints the block at the original attachment —
  no /edit request, no new attachment.
- Save after cropping the restored original runs /edit against the
  original's id, creating a fresh child off the root.
- Cancel discards the restore via the existing discard-confirm.

The canvas takes an optional srcOverride so the cropper can show the
original; swapping the source resets the cropper's dirty baseline, so a bare
restore is tracked by a separate isOriginalRestored flag OR'd into
hasChanges. The original's natural dimensions come from a cached
getEntityRecord on its id (the field itself carries only id + url).

Based on #81803 (the original_attachment lineage primitive).
@ramonjd
ramonjd force-pushed the add/attachment-original-lineage branch from 40b51f8 to 75c1d2e Compare August 27, 2026 07:13
ramonjd added a commit that referenced this pull request Aug 27, 2026
Add a "Restore original image" button to the Crop sidebar tab. It appears
when the edited attachment exposes media_details.original_attachment (the
lineage root from the backend primitive). Clicking loads the original into
the cropper as a dirty preview:

- Save with no further crop repoints the block at the original attachment —
  no /edit request, no new attachment.
- Save after cropping the restored original runs /edit against the
  original's id, creating a fresh child off the root.
- Cancel discards the restore via the existing discard-confirm.

The canvas takes an optional srcOverride so the cropper can show the
original; swapping the source resets the cropper's dirty baseline, so a bare
restore is tracked by a separate isOriginalRestored flag OR'd into
hasChanges. The original's natural dimensions come from a cached
getEntityRecord on its id (the field itself carries only id + url).

Based on #81803 (the original_attachment lineage primitive).
@ramonjd
ramonjd requested a balanced review from Copilot August 28, 2026 05:52

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@ramonjd
ramonjd requested a review from andrewserong August 28, 2026 05:52
@ramonjd
ramonjd force-pushed the add/attachment-original-lineage branch from 75c1d2e to d01832e Compare August 28, 2026 05:54
@ramonjd
ramonjd marked this pull request as ready for review August 28, 2026 05:55
@ramonjd
ramonjd requested a review from spacedmonkey as a code owner August 28, 2026 05:55
return $response;
}

$data['media_details']['original_attachment'] = array(

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See this comment over the in core patch: https://github.com/WordPress/wordpress-develop/pull/13303/changes#r3878648433

I don't believe there's a precedent for media_details with registered context.

The original_attachment sub-property has context: edit.

media_details is usually treated as a bare, typeless object with no properties at all.

The alternative is a top-level property.

@andrewserong andrewserong Aug 31, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hrm, this is an interesting one! What's the trade-off between placing this value in media_details versus making it a root-level property in the output, i.e. so that it's effectively a field just like alt_text, post or source_url? Would it simplify things if were a separate field, so that we don't bump into the other data in media_details?

I'm always wondering if we'll want to be able to query by "give my all the derivates / crops for attachment id 10" which might be easier if it's a field 🤔

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the trade-off between placing this value in media_details versus making it a root-level property in the output, i.e. so that it's effectively a field just like alt_text, post or source_url?

You know what, the only reason I chucked it in media_details was because parent_image was already in the post meta and I reasoned the two belonged together 😄 But "post" is top level in the REST response.

Also media_details in the REST response, from what i can gather, is filled with props that describe the image, e.g., width/height.

Our original_attachment describes relationship to a different post.

I don't see any cost to moving it up. Let's do it. Thanks for raising it.

I'm always wondering if we'll want to be able to query by "give my all the derivates / crops for attachment id 10" which might be easier if it's a field 🤔

Maybe the query would be easier to build, if we make it queryable by original_attachment, that is, a new collection param on /wp/v2/media but it'd still have to translate to a meta_query on _wp_attachment_original_id. Would be a good follow up in any way.

ramonjd added a commit that referenced this pull request Aug 31, 2026
Add a "Restore original image" button to the Crop sidebar tab. It appears
when the edited attachment exposes media_details.original_attachment (the
lineage root from the backend primitive). Clicking loads the original into
the cropper as a dirty preview:

- Save with no further crop repoints the block at the original attachment —
  no /edit request, no new attachment.
- Save after cropping the restored original runs /edit against the
  original's id, creating a fresh child off the root.
- Cancel discards the restore via the existing discard-confirm.

The canvas takes an optional srcOverride so the cropper can show the
original; swapping the source resets the cropper's dirty baseline, so a bare
restore is tracked by a separate isOriginalRestored flag OR'd into
hasChanges. The original's natural dimensions come from a cached
getEntityRecord on its id (the field itself carries only id + url).

Based on #81803 (the original_attachment lineage primitive).

@andrewserong andrewserong left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the update, I like it at the root level 👍

Just left a small comment about the shape of the data: could it be a simple integer, or do we need source_url embedded?

Another question re: naming is, in terms of REST API shape, would original_media feel more consistent with the endpoint? I.e. since the endpoint is called media and we have media_type rather than attachment_type and so on 🤔

Comment on lines +129 to +133
$data['original_attachment'] = array(
'attachment_id' => $original_id,
'source_url' => $source_url,
);
$response->set_data( $data );

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need both the attachment_id and the source_url? I.e could this be a simple integer field and it's up to the client to request the other attachment if they want to?

One other benefit if we register this as a field, is that I think we might be able to use links / embed the linked item in the response if consumers wish to.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need both the attachment_id and the source_url?

Yes and no. 😆

So it's terrifically convenient for loading the image into the editor. See: https://github.com/WordPress/gutenberg/pull/81805/changes#diff-6742eddff5146f6b37df0497c25f09e886dfa83a40d41e91e0d3d217cf806e0dR120

But yeah, the alternative is to enable embed like you say. It's a great idea, and I guess it would be consistent with the parent post id?

https://github.com/WordPress/wordpress-develop/blob/trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php#L1698

What do you think?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think?
So it's terrifically convenient for loading the image into the editor. See:

Ah, I see! Yes for that use case it's very convenient. In principle, though, I think the consumer probably should be doing a little more work there. Either via an embedded response in the original request, or a subsequent request to grab the full attachment via a second API call either before or after someone clicks the restore button.

My thinking is this: if we're making changes to the REST API to accommodate the feature, it's worth it to build it out as a field and how we think it should work in the long run. That leans me toward a simple integer value because eventually we might want to query by it, and it seems neater if its an integer in all cases (as a query param and in the response object).

All that said, we don't need to build the full field right now, we just need the data to be in a shape we want to commit to. And that points me toward a simple integer value, just as we have for post, as it seems the most consistent with how we shape the API endpoints.

A caveat, though: this is not a strongly held opinion, just my thoughts as I think about the change here. I can be easily swayed 😄

@andrewserong andrewserong Aug 31, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, edit to add: one of the reasons this is on my mind is that once you've got your button feature in, I'd love to have a play with the idea of a dropdown that shows all available existing crops, so that's why the query idea resonates for me!

I.e. you open the cropper and it requests to see if a parent crop exists, or if the current image is a parent of other crops and it lists them all so you can navigate between them.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My thinking is this: if we're making changes to the REST API to accommodate the feature, it's worth it to build it out as a field and how we think it should work in the long run. That leans me toward a simple integer value because eventually we might want to query by it, and it seems neater if its an integer in all cases (as a query param and in the response object).

I'm sold. I'm going to do it! Thank you!

I'd love to have a play with the idea of a dropdown that shows all available existing crops, so that's why the query idea resonates for me!

💯 Great idea

@ramonjd

ramonjd commented Aug 31, 2026

Copy link
Copy Markdown
Member Author

Another question re: naming is, in terms of REST API shape, would original_media feel more consistent with the endpoint? I.e. since the endpoint is called media and we have media_type rather than attachment_type

Nothing against changing it. You're right it definitely sounds more consistent in terms of the route, but I made it attachment on purpose to disambiguate between a post object and a "media" file and to correspond with the value of the type field ("attachment").

So we have media_details.original_image that points to an image path, and a bunch of media_*- terms to describe the "properties of the file."

original_attachment: 42" seemed to avoid all the wondering.

@andrewserong

Copy link
Copy Markdown
Contributor

to disambiguate between a post object and a "media" file and to correspond with the value of the type field ("attachment").
original_attachment: 42" seemed to avoid all the wondering.

Ah good point! I'd been thinking of existing keys used elsewhere like featured_media in posts so original_media felt a bit more consistent to me there, but I also see the value of ensuring it matches the type field and doesn't get confused with media as in image urls. So, this sounds good to me as a naming idea 👍

For a tiny bit of extra context: the reason I'm nitpicking the naming here is that I wound up having to rename the attached-to field and relation a bit when trying to get that change into the REST API last year in core, so I imagine these sorts of questions will get asked at the core merge stage.

But I think you've argued well for original_attachment and that works for me! Plus, this is Gutenberg code, so we can also rename in follow-ups if we need to.

@ramonjd

ramonjd commented Aug 31, 2026

Copy link
Copy Markdown
Member Author

the reason I'm nitpicking the naming here is that I wound up having to rename the attached-to field and relation a bit when trying to get that change into the REST API WordPress/wordpress-develop#10163, so I imagine these sorts of questions will get asked at the core merge stage.

Worth thinking about it now. Thanks for raising it.

As said, happy to change it whatever makes sense. I think the more folks we ask, the more opinions we'll get 😄 Core might be a ripe place to poke at it.

Cheers!

ramonjd added a commit that referenced this pull request Aug 31, 2026
Add a "Restore original image" button to the Crop sidebar tab. It appears
when the edited attachment exposes media_details.original_attachment (the
lineage root from the backend primitive). Clicking loads the original into
the cropper as a dirty preview:

- Save with no further crop repoints the block at the original attachment —
  no /edit request, no new attachment.
- Save after cropping the restored original runs /edit against the
  original's id, creating a fresh child off the root.
- Cancel discards the restore via the existing discard-confirm.

The canvas takes an optional srcOverride so the cropper can show the
original; swapping the source resets the cropper's dirty baseline, so a bare
restore is tracked by a separate isOriginalRestored flag OR'd into
hasChanges. The original's natural dimensions come from a cached
getEntityRecord on its id (the field itself carries only id + url).

Based on #81803 (the original_attachment lineage primitive).
Mirror featured_media: the field is the original attachment's id, with
an embeddable wp:original-attachment link for hydrating the full
record via _embed, instead of an { attachment_id, source_url } object.
rest_prepare_attachment fires twice per attachment (once from the
posts controller, again from the attachments controller wrapping it),
so add_link() appended a duplicate wp:original-attachment link; only
add it when absent. Drop the wp_get_attachment_url() reachability
check: it cost an uncached meta query per derivative, delete_attachment
cleanup keeps the meta accurate, and a consumer fetching a dangling id
simply gets no record.
The feature targets the WordPress 7.2 release (wordpress-develop PR
13303), so it belongs in the compat directory rather than
lib/experimental. Move the test to the phpunit root alongside the
other compat feature tests.
The field now carries a schema (integer, edit context, readonly), so
it appears in the OPTIONS /wp/v2/media response, works with _fields
filtering, and core strips it outside the edit context automatically.
A registered field is always present in its contexts, so attachments
with no lineage now return 0 (matching featured_media) instead of
omitting the key. The rest_prepare_attachment filter remains only to
add the embeddable wp:original-attachment link, which
register_rest_field cannot do.
The 8.0.0 release moved trunk's Unreleased section to a published
heading, and the rebase merged the #81803 entry into it. The PR is
unmerged, so its entry belongs under Unreleased.
Rename the lineage helpers, postmeta key, REST field and link relation so
they no longer read like core's original_image / wp_get_original_image_*
APIs, which describe the unscaled upload of the same attachment:

- gutenberg_get_original_attachment_id() -> gutenberg_get_edit_root_attachment_id()
- gutenberg_record_original_attachment_id() -> gutenberg_record_edit_root_attachment_id()
- _wp_attachment_original_id -> _wp_attachment_edit_root_id
- REST field original_attachment -> edit_root
- Link relation wp:original-attachment -> wp:edit-root

The remaining helpers, the meta key constant, the compat and test file
names and the test class follow suit. No behaviour change.
@ramonjd
ramonjd force-pushed the add/attachment-original-lineage branch from 360784e to c803dfb Compare October 2, 2026 02:31
ramonjd added a commit that referenced this pull request Oct 2, 2026
Adds a Restore original image action to the media editor's More
options menu, shown when the attachment exposes the edit_root field
recorded by its lineage (#81803).

- Restore loads the root attachment and its editable details, and
  discards pending edits to the derivative.
- Saving an untouched restore repoints the block without writing an
  attachment; transforming first runs /edit against the root.
- Metadata fields are disabled while a restore is pending; detail
  saves retarget the root.
- Image and Cover restore the previous attachment with snackbar Undo.

Squashed end state of the restore-original branch, ported onto the
session cropper engine after the snapshot-history refactors landed on
trunk.
$rel = 'https://api.w.org/edit-root';
$links = $response->get_links();
if ( ! isset( $links[ $rel ] ) ) {
$response->add_link(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a very minor nitpicky question as I re-test this: do we need to handle skipping adding the link for requests that specify specific fields they want in the response (i.e. limiting the response)?

Here's a couple of examples from core, in case it helps!

The Posts controller: https://github.com/WordPress/wordpress-develop/blob/5aac49a2d6bf28944a3c9ed5827a622e02696649/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php#L2150-L2152

This might be an example we could copy from the REST server class: https://github.com/WordPress/wordpress-develop/blob/5aac49a2d6bf28944a3c9ed5827a622e02696649/src/wp-includes/rest-api/class-wp-rest-server.php#L1404-L1414

(And as always, apologies if I'm overthinking this one!)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yes, very probably. Thanks for flagging that. I'll take a look.

Makes sense that we'd only want it when folks explicitly call for embed or the links field.

Core builds its own links only when a field-limited request includes
_links or _embedded, so adding ours unconditionally handed a
_fields-limited response a _links member core intended to omit. Bail
before add_link() using the same rest_is_field_included() idiom as
core, treating a present _embed parameter as a request for links.
ramonjd added a commit that referenced this pull request Oct 2, 2026
Adds a Restore original image action to the media editor's More
options menu, shown when the attachment exposes the edit_root field
recorded by its lineage (#81803).

- Restore loads the root attachment and its editable details, and
  discards pending edits to the derivative.
- Saving an untouched restore repoints the block without writing an
  attachment; transforming first runs /edit against the root.
- Metadata fields are disabled while a restore is pending; detail
  saves retarget the root.
- Image and Cover restore the previous attachment with snackbar Undo.

Squashed end state of the restore-original branch, ported onto the
session cropper engine after the snapshot-history refactors landed on
trunk.
ramonjd added a commit to ramonjd/wordpress-develop that referenced this pull request Oct 2, 2026
A response limited with `_fields` carries no `_links` member unless the
request asks for `_links` or `_embedded`, because the posts controller
builds no links at all in that case. The edit root link was added outside
that check and keyed off the response field, so `_fields=id,edit_root`
came back with a `_links` member holding this one link alone, and
`_fields=id,_links` came back without it while every other link was there.

The link is now gated on the same check the parent controller uses for its
own links, and reads the edit root itself rather than the prepared field,
so asking for links no longer depends on asking for the field.

Follows WordPress/gutenberg#81803. The plugin also
treats a bare `_embed` parameter as a request for links. Core does not:
`get_fields_for_response()` drops `_embedded` from a `_fields` list that
omits it, and core's own links stay out of that response too.

See #65987.

@andrewserong andrewserong left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-testing and this is working nicely for me!

✅ edit_root key is correctly populated with the root attachment id
✅ links appear when expected (and the relevant url is correct)
✅ On an attachment that has no edit_root its value is 0
✅ Confirmed that deleting an attachment also clears out the post meta in the db

I reckon this is a good place to get it in, we've had a few rounds of discussing naming and I think we've landed on a decent structure here and we haven't changed our minds over the past few days 😄

LGTM!

Tiny nit from another round with Claude (non-blocking): Should we guard registration behind a check to ensure we don't run all this twice if core's backport is present?

@ramonjd

ramonjd commented Oct 2, 2026

Copy link
Copy Markdown
Member Author

Should we guard registration behind a check to ensure we don't run all this twice if core's backport is present

Oh boy, excellent point. I'll do that. E.g., function_exists( 'wp_get_edit_root_attachment_id' ) and so on .

Core's backport (wordpress-develop PR 13303) defines
wp_get_edit_root_attachment_id() in post.php, loaded before any
plugin, so its presence means core already records the meta, exposes
the field and link, and cleans up on delete. Consolidate the four
registrations under that check. The functions stay defined either
way, since the test suite calls them directly.
ramonjd added a commit that referenced this pull request Oct 2, 2026
Adds a Restore original image action to the media editor's More
options menu, shown when the attachment exposes the edit_root field
recorded by its lineage (#81803).

- Restore loads the root attachment and its editable details, and
  discards pending edits to the derivative.
- Saving an untouched restore repoints the block without writing an
  attachment; transforming first runs /edit against the root.
- Metadata fields are disabled while a restore is pending; detail
  saves retarget the root.
- Image and Cover restore the previous attachment with snackbar Undo.

Squashed end state of the restore-original branch, ported onto the
session cropper engine after the snapshot-history refactors landed on
trunk.
Match core's guard on the featured_media link: only advertise the
wp:edit-root link when the root attachment is published or the
requester can read it. A stale meta id (the root deleted out of band,
or the id recycled) resolves to do_not_allow and the link is skipped;
the edit_root field itself still carries the stored id, since the
link is a promise that ?_embed can hydrate it and the field is not.
ramonjd added a commit to ramonjd/wordpress-develop that referenced this pull request Oct 2, 2026
The `wp:edit-root` link promises that `_embed` can fetch the edit root, but
the recorded ID is not checked, so an edit root that no longer exists, or
one the user cannot read, was still offered as a link.

The link now uses the same check as the `featured_media` link: it is added
only when the edit root is published or the user can read it. The
`edit_root` field still reports the recorded ID as is.

Follows WordPress/gutenberg#81803.

See #65987.
@ramonjd
ramonjd merged commit 68dff0d into trunk Oct 5, 2026
114 checks passed
@ramonjd
ramonjd deleted the add/attachment-original-lineage branch October 5, 2026 11:10
@github-actions github-actions Bot added this to the Gutenberg 24.2 milestone Oct 5, 2026
ramonjd added a commit that referenced this pull request Oct 5, 2026
Adds a Restore original image action to the media editor's More
options menu, shown when the attachment exposes the edit_root field
recorded by its lineage (#81803).

- Restore loads the root attachment and its editable details, and
  discards pending edits to the derivative.
- Saving an untouched restore repoints the block without writing an
  attachment; transforming first runs /edit against the root.
- Metadata fields are disabled while a restore is pending; detail
  saves retarget the root.
- Image and Cover restore the previous attachment with snackbar Undo.

Squashed end state of the restore-original branch, ported onto the
session cropper engine after the snapshot-history refactors landed on
trunk.
ramonjd added a commit that referenced this pull request Oct 5, 2026
Adds a Restore original image action to the media editor's More
options menu, shown when the attachment exposes the edit_root field
recorded by its lineage (#81803).

- Restore loads the root attachment and its editable details, and
  discards pending edits to the derivative.
- Saving an untouched restore repoints the block without writing an
  attachment; transforming first runs /edit against the root.
- Metadata fields are disabled while a restore is pending; detail
  saves retarget the root.
- Image and Cover restore the previous attachment with snackbar Undo.

Squashed end state of the restore-original branch, ported onto the
session cropper engine after the snapshot-history refactors landed on
trunk.
ramonjd added a commit that referenced this pull request Oct 6, 2026
Adds a Restore original image action to the media editor's More
options menu, shown when the attachment exposes the edit_root field
recorded by its lineage (#81803).

- Restore loads the root attachment and its editable details, and
  discards pending edits to the derivative.
- Saving an untouched restore repoints the block without writing an
  attachment; transforming first runs /edit against the root.
- Metadata fields are disabled while a restore is pending; detail
  saves retarget the root.
- Image and Cover restore the previous attachment with snackbar Undo.

Squashed end state of the restore-original branch, ported onto the
session cropper engine after the snapshot-history refactors landed on
trunk.
@ramonjd

ramonjd commented Oct 19, 2026

Copy link
Copy Markdown
Member Author

Dev note (draft until reviewed):

Edited images now record the image they started from

Editing an image through POST /wp/v2/media/<id>/edit, which the image block's crop tools use, leaves the source image alone and saves the result as a new attachment.

Until now the only link back was parent_image in the new attachment's metadata. It names the immediate source, so finding the first image of a crop-of-a-crop chain meant loading each attachment up the chain.

WordPress 7.2 records the top of the chain, called the edit root, on every attachment that endpoint creates.

Storage. The ID goes in the _wp_attachment_edit_root_id post meta. A new attachment copies the edit root of the image being edited, or uses that image itself when it was uploaded rather than edited. Every image in a chain points at the same root, so one meta lookup finds it.

PHP. wp_get_edit_root_attachment_id( $attachment_id ) returns the edit root's ID, or 0 when none is recorded, as for an uploaded image.

$edit_root_id = wp_get_edit_root_attachment_id( $attachment_id );

if ( $edit_root_id ) {
	$original_url = wp_get_attachment_url( $edit_root_id );
}

REST API. Attachment responses have a new read-only integer field, edit_root, in the edit context only. It is 0 when there is no edit root. The response also carries an embeddable https://api.w.org/edit-root link, so a request with context=edit and _embed returns the root attachment under _embedded['wp:edit-root']. WordPress omits the link when the root is unpublished and the current user can't read it. The field still reports the ID in that case.

The 201 response from /edit does not include edit_root, because that route has no context parameter. Fetch the new attachment with context=edit to read it.

Things to know.

  • There is no backfill. Images edited before 7.2 have no edit root.
  • WordPress does not check the ID when reading it. Permanently deleting an attachment clears the meta from every image that points at it. With MEDIA_TRASH enabled, trashing the root does not, so those images keep pointing at the trashed root until it is deleted.
  • WXR exports include the meta like any other post meta. Attachment IDs change on import, so an imported value can point at the wrong attachment. A WordPress Importer change proposes skipping the key. Until something like it ships, import and migration tools should drop or remap _wp_attachment_edit_root_id.

See #65987, r64118, and Gutenberg #81803.

wporg-sync pushed a commit to WordPress/wordpress-develop that referenced this pull request Oct 20, 2026
This updates the pinned commit hash of the Gutenberg repository from 954fe7f9e04631c41aec4552acd627a7203a2aad to 7b95ee96b54de2e35886971ccf7eb449c324c830 (version 24.2.0).

A full list of changes included in this commit can be found on GitHub: WordPress/gutenberg@954fe7f...7b95ee9

- useServerSideRender: parse messages from caught errors (WordPress/gutenberg#83365)
- Docs: Fix published Vitest migration-guide links (WordPress/gutenberg#83449)
- Fix: Whitespace changes are not shown in the Resolve Block diff. (WordPress/gutenberg#82397)
- Editor: Use SearchableSelect for the post author field (WordPress/gutenberg#83323)
- Docs: Note that block attributes and global styles values are untrusted at render time (WordPress/gutenberg#83473)
- RichText: Remove dead exports and consolidate deprecations (WordPress/gutenberg#83461)
- Inserter: Manage roving tab index to skip re-rendering every item (WordPress/gutenberg#83437)
- SearchableSelectControl: Add to @wordpress/ui (WordPress/gutenberg#80979)
- Try: Bolder "B" icon (WordPress/gutenberg#83321)
- Ignore composer vendor files from top-level gitignore. (WordPress/gutenberg#22283)
- Tests: Add floating notes e2e coverage (WordPress/gutenberg#83477)
- Block Editor: Check the inserter's fallback containers unmemoized (WordPress/gutenberg#83446)
- Packages: Update Ariakit to 0.4.40 (WordPress/gutenberg#83278)
- Tests: Enforce per-call Vitest console expectations (WordPress/gutenberg#83095)
- Theme: Fix virtual modules, root styles, and seed validation (WordPress/gutenberg#83355)
- DataViews: Fix README to describe sort() as receiving field values, not items (WordPress/gutenberg#83483)
- Budugbox: Label popup dialogs in stories (WordPress/gutenberg#83476)
- Block editor: Isolate mutable test fixtures (WordPress/gutenberg#83098)
- Blocks: Isolate registration state in tests (WordPress/gutenberg#83099)
- UI: Remove automatic Notice announcements (WordPress/gutenberg#82737)
- Text: Migrate Emotion styles to an SCSS Module (WordPress/gutenberg#82573)
- Block library: Isolate order-sensitive test interactions (WordPress/gutenberg#83101)
- Format Library: unify FormatEditProps to one type, move private types (WordPress/gutenberg#83487)
- UI: Announce selected chips in SearchableChipSelect (WordPress/gutenberg#82863)
- Card: Migrate from Emotion to SCSS modules (WordPress/gutenberg#82577)
- Components: Deprecate the private Menu API (WordPress/gutenberg#82947)
- CustomGradientPicker: Migrate control wrappers to an SCSS module (WordPress/gutenberg#82576)
- Components: Isolate order-sensitive UI tests (WordPress/gutenberg#83103)
- Tests: Isolate mutable configuration fixtures (WordPress/gutenberg#83104)
- Core data: Finish deferred selection updates in RTC test (WordPress/gutenberg#83366)
- Block editor: Wait for final keyboard link suggestions (WordPress/gutenberg#83489)
- Data: Assert and silence resolution error in useSuspenseSelect test (WordPress/gutenberg#83491)
- Tests: Isolate deprecation warning state (WordPress/gutenberg#83107)
- UI: Align selection popup checkmarks with the first label line (WordPress/gutenberg#82942)
- Tests: Resolve Browser Mode commands against the live iframe (WordPress/gutenberg#83495)
- Ensure position type is a string (WordPress/gutenberg#83500)
- MediaUpload: Fix console error when reopening Gallery media library (WordPress/gutenberg#76749)
- Refactor stylelint config detection in lint-style.js (WordPress/gutenberg#79280)
- Docs: Recommend UI Tabs for switching views (WordPress/gutenberg#83516)
- Popover: Close non-modal popovers on iframe interaction (WordPress/gutenberg#83509)
- Typography: List only the weights inside a variable font's range (WordPress/gutenberg#83128)
- Style book: Add link to example text. (WordPress/gutenberg#83448)
- Tests: Add Vitest Browser Mode failure artifacts (WordPress/gutenberg#83093)
- Theme: Make JavaScript token fallback transforms syntax-aware (WordPress/gutenberg#83356)
- Editor: Fix new posts being published with the `auto-draft` slug (WordPress/gutenberg#83518)
- Editor: Gather the View group of the Options menu into submenus (WordPress/gutenberg#82976)
- Tests: Fix PostCSS browser-externalized warnings in Vitest (WordPress/gutenberg#83091)
- Tests: Shuffle test cases in CI (WordPress/gutenberg#83111)
- Update Styles > Blocks description. (WordPress/gutenberg#83515)
- Columns: Remove the column count slider (WordPress/gutenberg#83262)
- BorderControl: Remove `%` from the border width units (WordPress/gutenberg#83492)
- Fields: Fix AuthorView for users who can't edit users (WordPress/gutenberg#83498)
- Update and add justify icons. (WordPress/gutenberg#83519)
- RichText: Refactor useMarkPersistent, fix StrictMode mount mark (WordPress/gutenberg#83463)
- Theme: Improve accessibility, API documentation, and compatibility checks (WordPress/gutenberg#83358)
- Theme: Preserve global token references in Lightning CSS (WordPress/gutenberg#83359)
- Tests: Migrate internal linting to Vitest and remove unused Jest dependencies (WordPress/gutenberg#83502)
- Improve specificity of lightbox button selector (WordPress/gutenberg#70800)
- TextControl: Use design system colors when disabled (WordPress/gutenberg#83307)
- Fix: Image lightbox: overlay becomes unusable (can't close) when it isn't a direct child of `<body>` (WordPress/gutenberg#83480)
- Notes: Extract note selection sync into useNoteSelection hook (WordPress/gutenberg#83528)
- Block Parser: Document `\WP_Block_Parser::$stack` as a list (WordPress/gutenberg#82695)
- CollapsibleCard: Scope the header focus ring to its own trigger (WordPress/gutenberg#81314)
- Fix broken links in docs (WordPress/gutenberg#83545)
- Icons: Use assertEqualHTML() in icons registry tests (WordPress/gutenberg#83544)
- Editor: Merge adjacent revision inline diffs (WordPress/gutenberg#80579)
- Date: Ignore trailing format backslash instead of printing undefined (WordPress/gutenberg#81528)
- Block Supports: Add background-clip block support infrastructure (WordPress/gutenberg#77141)
- Block Editor: Fix translator comments for block count announcements (WordPress/gutenberg#83555)
- Paste: replace non-breaking spaces at the edges of text with regular spaces (WordPress/gutenberg#83464)
- Media Editor: Fix pan drag flooding undo history after wheel zoom (WordPress/gutenberg#83558)
- Rich text: fix iOS double tap selection, preventing focus capture under editable host (WordPress/gutenberg#81042)
- Block editor: migrate state-control badges to UI Badge (WordPress/gutenberg#82608)
- Gallery: Add Order By controls for static gallery, consolidate controls in settings sidebar (WordPress/gutenberg#83438)
- Media editor: show an error when saving attachment details fails (WordPress/gutenberg#83560)
- Position controls: Fix useSelect warning for selected state viewports (WordPress/gutenberg#83570)
- Inserter: Use design system focus ring for previews (WordPress/gutenberg#83126)
- Image: Fix lightbox using thumbnail aspect ratio instead of original image ratio (WordPress/gutenberg#79058)
- Docs: Clarify @wordpress/ui icon color requirements (WordPress/gutenberg#83564)
- docker compose -T if stdin is not a tty (WordPress/gutenberg#78374)
- Storybook: Add new contributing page. (WordPress/gutenberg#83345)
- Widget Primitives: Avoid Vite warnings for runtime widget modules (WordPress/gutenberg#83602)
- Build: Update Vite to 8.3.1 and simplify Storybook tooling (WordPress/gutenberg#83569)
- doc(wp-env) Change core branch from trunk to master in doc (WordPress/gutenberg#83566)
- wp-build: Remove the unused boot, private-apis, and route optional peer dependencies (WordPress/gutenberg#83601)
- CI: Check CHANGELOG presence for published tooling and config packages (WordPress/gutenberg#83577)
- Tests: Enforce Vitest assertion coverage (WordPress/gutenberg#83572)
- Icons: Update heading level icons for optical balance (WordPress/gutenberg#83268)
- ESLint: Add allowUseWithCaution option to use-recommended-components (WordPress/gutenberg#83536)
- Notes: Refactor floating board measurement (WordPress/gutenberg#83485)
- Inserter: Stop re-rendering the block list on block selection change (WordPress/gutenberg#83284)
- Paste: Give each pasted data-URI image unique filename to avoid upload collisions. (WordPress/gutenberg#79480)
- Changelog validator: ignore markdown & configs d46223 (WordPress/gutenberg#83618)
- Font Library: Use UI Menu for collection actions (WordPress/gutenberg#82965)
- Storybook: Show prop descriptions in Canvas controls (WordPress/gutenberg#83581)
- test: Link upstream warning fixes in config (WordPress/gutenberg#83632)
- Storybook: Use one block-editor store module (WordPress/gutenberg#83636)
- Tests: Use strict assertions synced from Core changeset 63934. (WordPress/gutenberg#83619)
- Math: Store cell alignment in the MathML and polyfill alignment and overlines in Chromium (WordPress/gutenberg#83164)
- Storybook: Reuse PostCSS browser resolver in smoke tests (WordPress/gutenberg#83635)
- Editor: Use UI Menu for template options (WordPress/gutenberg#82964)
- RTC: Add a EntitySyncManager interface in core-data (WordPress/gutenberg#83410)
- Term Count: Add margin support (WordPress/gutenberg#83608)
- Archives: Add minimum height support (WordPress/gutenberg#83573)
- Media Editor: Stop the crop pixel snap from recording undo history (WordPress/gutenberg#83571)
- Term Name: Add margin support (WordPress/gutenberg#83606)
- Post Author Biography: Add text indent support (WordPress/gutenberg#83614)
- Code: Add minimum width and height support (WordPress/gutenberg#83574)
- Details: Add minimum width support (WordPress/gutenberg#83576)
- Post Content: Add minimum width support (WordPress/gutenberg#83575)
- Post Excerpt: Add minimum width and height support (WordPress/gutenberg#83578)
- Post Title: Add minimum width and height support (WordPress/gutenberg#83600)
- Footnotes: Add minimum width and height support (WordPress/gutenberg#83579)
- Storybook: Place Notice announcements under Components (WordPress/gutenberg#83617)
- InputControl: Darken the field border on hover (WordPress/gutenberg#83306)
- npm: Switch from legacy-peer-deps to strict-peer-deps (WordPress/gutenberg#81029)
- Term Name: Add minimum width and height support (WordPress/gutenberg#83599)
- Columns: Allow dropping a column at the outer edges (WordPress/gutenberg#83274)
- E2E: Pin the site title in the Interactivity API router specs and give the E2E Storybook build more heap. (WordPress/gutenberg#83474)
- Heading: Add minimum width and height support (WordPress/gutenberg#83580)
- Login/out: Add minimum width and height support (WordPress/gutenberg#83583)
- Verse: Add minimum width support (WordPress/gutenberg#83609)
- Video, Cover: Don't autoplay in the editor when reduced motion is preferred (WordPress/gutenberg#83337)
- Media & Text: Lower the specificity of the content padding (WordPress/gutenberg#83563)
- Pagination: Add padding, margin, and block gap support (WordPress/gutenberg#83743)
- Fix peer dependency conflicts left in the lockfile (WordPress/gutenberg#83754)
- Comments Pagination: Add padding, margin, and block gap support (WordPress/gutenberg#83744)
- Term Count: Add minimum width and height support (WordPress/gutenberg#83596)
- Read More: Add border style support (WordPress/gutenberg#83735)
- Cover: Don't autoplay embedded background videos when reduced motion is preferred (WordPress/gutenberg#83452)
- No Results: Add minimum width and height support (WordPress/gutenberg#83584)
- RichText: Rename utils.jsx to utils.js (WordPress/gutenberg#83758)
- Quote: Add minimum width support (WordPress/gutenberg#83592)
- Upgrade typescript-eslint to v8.70.1 (WordPress/gutenberg#83760)
- Tabs: Add minimum width support (WordPress/gutenberg#83595)
- Site Tagline: Add minimum width and height support (WordPress/gutenberg#83589)
- Heading: Add text indent support (WordPress/gutenberg#83615)
- Site Title: Add minimum width and height support (WordPress/gutenberg#83593)
- Home Link: Add padding and margin support (WordPress/gutenberg#83607)
- Preformatted: Add minimum width and height support (WordPress/gutenberg#83587)
- Include E2E Storybook sources in docgen (WordPress/gutenberg#83634)
- Extensible Site Editor: Pass custom block categories to the blocks store (WordPress/gutenberg#83762)
- Packages: Declare missing peer dependencies and check them in CI (WordPress/gutenberg#83765)
- Post Terms: Add minimum width and height support (WordPress/gutenberg#83586)
- Group, Cover: Track drop zone element in state (WordPress/gutenberg#83756)
- Global Styles: Add pseudo-state controls for Navigation Link (WordPress/gutenberg#83451)
- storybook: Register playground core blocks once (WordPress/gutenberg#83637)
- Document Outline: Show the design system focus ring instead of legacy box-shadow (WordPress/gutenberg#83755)
- storybook: Update BlockPopover fixture to API version 3 (WordPress/gutenberg#83642)
- Add typing to iAPI's getConfig() (WordPress/gutenberg#71692)
- Components: deprecate Badge (WordPress/gutenberg#82379)
- Block Editor: Fix style / nested attribute overwrite during multi-selection (WordPress/gutenberg#80070)
- Notes: Restrict menu actions for resolution notes and resolved threads (WordPress/gutenberg#73243)
- UI: Add change actions to form primitive stories (WordPress/gutenberg#83591)
- Icons: Support keyword-based search in the icons registry (WordPress/gutenberg#82367)
- Avatar: Explain that avatars use the Gravatar service (WordPress/gutenberg#83567)
- UI: Add item labels and descriptions to remaining popups (WordPress/gutenberg#83493)
- PaletteEdit: Stop changing the slug when renaming a preset (WordPress/gutenberg#83750)
- Storybook: Fix missing block styles in BlockCanvas playground stories (WordPress/gutenberg#81070)
- Tests: Enforce Vitest callback, promise, and title rules (WordPress/gutenberg#83620)
- ItemGroup: Use design system focus ring (WordPress/gutenberg#83764)
- Keep the legacy CheckboxControl visually consistent across viewports (WordPress/gutenberg#83612)
- Media editor: Use UI Menu for crop aspect ratio (WordPress/gutenberg#82968)
- Use strict assertions in override script tests (WordPress/gutenberg#83782)
- Home Link: Add minimum width and height support (WordPress/gutenberg#83582)
- Tab Panels: Add minimum height support (WordPress/gutenberg#83594)
- Post Time to Read: Add minimum width and height support (WordPress/gutenberg#83598)
- Term Description: Add minimum width and height support (WordPress/gutenberg#83597)
- UI: Keep InputLayout chrome at md on small viewports (WordPress/gutenberg#82764)
- Math: Add minimum width and height support (WordPress/gutenberg#83585)
- Tests: Bump undici in the AI development test lockfile (WordPress/gutenberg#83799)
- Bump brace-expansion in /test/ai-development (WordPress/gutenberg#83807)
- Bump js-yaml and promptfoo in /test/ai-development (WordPress/gutenberg#83797)
- Bump fast-uri from 3.1.7 to 3.1.8 (WordPress/gutenberg#83829)
- Update AI Development package versions after npm audit (WordPress/gutenberg#83830)
- Notes: Add show and hide options for floating notes (WordPress/gutenberg#83768)
- Add separators to item popup components (WordPress/gutenberg#83776)
- Components: Align RadioControl colors with UI Radio (WordPress/gutenberg#83270)
- E2E: Mock Openverse in image drag-and-drop inserter test (WordPress/gutenberg#83842)
- FormToggle: Match Switch colors across states (WordPress/gutenberg#83773)
- Bump `@react-spring/web` from 9.4.5 to 10.1.2 (WordPress/gutenberg#83796)
- ColorPalette: Show design system focus ring on custom color button (WordPress/gutenberg#83841)
- Docs: Remove CheckboxControl heading from InspectorControls example (WordPress/gutenberg#83844)
- Base Styles: Default the admin theme color to Blueberry (WordPress/gutenberg#83749)
- Menu: Guard against nesting Group and RadioGroup (WordPress/gutenberg#83792)
- Template Part: Fall back to rendering a template part from the theme file if the db version is unavailable (WordPress/gutenberg#83809)
- Tests: Reset deprecation history in shared Vitest setup (WordPress/gutenberg#83849)
- Menu: Disable triggers instead of roots in consumers (WordPress/gutenberg#83791)
- Playlist: Replace the waveform player patch with its no-autoinit entry (WordPress/gutenberg#83132)
- Update UI Spinner appearance and add a color prop (WordPress/gutenberg#83775)
- UI: Align component names with their semantics (WordPress/gutenberg#83789)
- Checkbox: Prevent rounded themes from making checkboxes circular (WordPress/gutenberg#83526)
- Storybook: Update manifest snapshot for Spinner color prop (WordPress/gutenberg#83856)
- Button: Only open the link popover on explicit user action (WordPress/gutenberg#30166)
- Gallery Lightbox: Prevent image click from closing the dialog when navigation is enabled (WordPress/gutenberg#78898)
- UI: Recommend Checkbox family components (WordPress/gutenberg#83771)
- RadioControl: Keep a 16px visual with a larger hit target (WordPress/gutenberg#83840)
- Table: replace deprecated word-break with overflow-wrap: anywhere (WordPress/gutenberg#82480)
- Tag Cloud: Update styles and add `!important` (WordPress/gutenberg#70224)
- Correctly document the `blockName` property as being nullable (WordPress/gutenberg#70900)
- Add inertValue helper and use it for setting inert attribute (WordPress/gutenberg#83871)
- Enable editableRoot for the list item block for multi-selection on mobile (WordPress/gutenberg#82816)
- Verify localized data retention in override script test (WordPress/gutenberg#83845)
- Tests: Bump ibm-cloud-sdk-core in the AI development test lockfile (WordPress/gutenberg#83887)
- UI: Recommend Notice component (WordPress/gutenberg#82685)
- Fix: MediaUpload `gallery` prop ignores `allowedTypes` (WordPress/gutenberg#78257)
- Media editor: Add a session boundary above the cropper (WordPress/gutenberg#83550)
- DataViews: Measure the container as the data view mounts to avoid a single column flash (WordPress/gutenberg#83752)
- Pullquote: Add minimum width support (WordPress/gutenberg#83588)
- Media editor: Remove initial state seeding from the session (WordPress/gutenberg#83893)
- UI: Add e2e Storybook popup item layout fixtures (WordPress/gutenberg#83488)
- Storybook: Give CI job a distinct name (WordPress/gutenberg#83869)
- Coding standards: Skip anonymous class methods in block library function name sniff (WordPress/gutenberg#83900)
- Pagination: Add border support (WordPress/gutenberg#83745)
- PR meta: Move the props list into the shared comment (WordPress/gutenberg#82302)
- Comments Pagination: Add border support (WordPress/gutenberg#83746)
- Scripts: Resolve default configs without hoisted dependencies (WordPress/gutenberg#83902)
- Image: Fix invalid CSS url() value in circle-mask style (WordPress/gutenberg#82333)
- Query Total: Add minimum width and height support (WordPress/gutenberg#83590)
- Scripts: Treat files passed after --fix as file arguments (WordPress/gutenberg#83521)
- Editor: Remove icon for 'Export' more menu item (WordPress/gutenberg#83901)
- Dashboard Widgets: let a mounted widget declare actions at runtime (WordPress/gutenberg#83877)
- Framework: Switch from hoisted to isolated dependencies (WordPress/gutenberg#83847)
- Test: Run Vitest type graph validation in process (WordPress/gutenberg#83851)
- Remove use-memo-one usage (missing React 19 compat) (WordPress/gutenberg#83952)
- Fix Post Featured Image crash when isLink is enabled (WordPress/gutenberg#81584)
- Experiment: restyle classic wp-admin controls from design system tokens (WordPress/gutenberg#82425)
- Tests: Lint JavaScript Vitest mock imports (WordPress/gutenberg#83783)
- Build: Remove patch-package (WordPress/gutenberg#83982)
- Docs: Update deprecation testing guidance for shared reset (WordPress/gutenberg#83989)
- DataViews: list hideable fields alphabetically in the view config (WordPress/gutenberg#83947)
- Core Data: Rank link suggestions by type, and stop discarding merged results (WordPress/gutenberg#83407)
- Add new react-inert-value package with inertValue helper (WordPress/gutenberg#83987)
- Connectors: Keep a stored API key read-only when it can't be verified (WordPress/gutenberg#83889)
- Navigation: Search every entity type from the link UI (WordPress/gutenberg#83408)
- Tests: Cover translation setup in override script tests (WordPress/gutenberg#83886)
- Build: Update Vite to 8.3.2 and remove the PostCSS browser resolver (WordPress/gutenberg#83992)
- Update readme title to match block name (WordPress/gutenberg#83999)
- RTC: Fix undo breaking for non-synced entities (WordPress/gutenberg#83888)
- CI: Cover the AI development lockfile with Dependabot instead of npm audit (WordPress/gutenberg#83997)
- Latest Posts: Add minimum width and height support (WordPress/gutenberg#83905)
- Avatar: Add shadow support (WordPress/gutenberg#83929)
- Tab List: Add shadow support (WordPress/gutenberg#83922)
- Buttons: Add minimum width and height support (WordPress/gutenberg#83894)
- Social Icons: Add shadow support (WordPress/gutenberg#83920)
- Columns: Add minimum width and height support (WordPress/gutenberg#83895)
- Gallery: Add shadow support (WordPress/gutenberg#83919)
- File: Add shadow support (WordPress/gutenberg#83918)
- Page List: Add minimum width and height support (WordPress/gutenberg#83908)
- Build Tooling: Read npm v12 pack --json output (WordPress/gutenberg#84011)
- Accordion Heading: Add line height support (WordPress/gutenberg#83958)
- Paragraph: Add shadow support (WordPress/gutenberg#83926)
- Media & Text: Add minimum width and height support (WordPress/gutenberg#83906)
- Tests: Patch basic-ftp in AI development dependencies (WordPress/gutenberg#84000)
- Env, E2E: Update dependencies that ran native install scripts (WordPress/gutenberg#84012)
- Tests: Update Vitest to 5.0.3 and Storybook to 10.6.1 (WordPress/gutenberg#83996)
- Search: Add padding support (WordPress/gutenberg#83984)
- Block editor: Honour background skip serialization in the editor (WordPress/gutenberg#83943)
- Framework: Declare React types in the workspaces that use them (WordPress/gutenberg#84013)
- Fit text: Size each block instance in a loop independently (WordPress/gutenberg#83985)
- FocalPointPicker: end a drag released over the editor canvas (WordPress/gutenberg#83348)
- Tests: Cover Menu scroll lock and LinkControl protocols in browsers (WordPress/gutenberg#83991)
- List: Add shadow support (WordPress/gutenberg#83923)
- UI: Add Progress with custom color support (WordPress/gutenberg#83781)
- ESLint: Allow non-module stylesheet imports in unit tests (WordPress/gutenberg#84019)
- Canvas loader: Use UI Progress and pass color via the indicator prop (WordPress/gutenberg#83860)
- Menu: Align group labels and separators with indented item labels. (WordPress/gutenberg#83993)
- react-inert-value: add missing types/react peer dep (WordPress/gutenberg#84024)
- Docs: Refine design system agent guidance (WordPress/gutenberg#84007)
- Navigation: List allowed blocks in the link UI search results + add transformSuggestions to Link Control (WordPress/gutenberg#83652)
- Sync: Remove exposed wp.sync package (WordPress/gutenberg#81999)
- Style: Update color to use CSS variable in edit-site (WordPress/gutenberg#79002)
- Popover: drop the will-change hint once the popover stops moving (WordPress/gutenberg#77359)
- MediaEdit: Show a checkerboard background behind image previews (WordPress/gutenberg#83846)
- Quote: Add button colour support (WordPress/gutenberg#83983)
- Media & Text: Add duotone support (WordPress/gutenberg#83981)
- Gallery: Add duotone support (WordPress/gutenberg#83978)
- Interactivity API Router: Add reactive navigation lifecycle and initiator API (WordPress/gutenberg#83280)
- Notes: Move floating notes into a canvas margin (WordPress/gutenberg#83786)
- Verse: Add text columns and indent support (WordPress/gutenberg#83962)
- Notes: Scroll floating notes with the canvas (WordPress/gutenberg#83852)
- Notes: Add Undo to deleted note snackbar (WordPress/gutenberg#83988)
- Framework: Move @typescript/native from the root to the workspaces that use it (WordPress/gutenberg#84027)
- Repair invalid peer dependencies in the lockfile (WordPress/gutenberg#84062)
- Term Template: Add minimum width and height support (WordPress/gutenberg#83914)
- Fix check type declarations (WordPress/gutenberg#84070)
- Media: track the original attachment id for edited images (WordPress/gutenberg#81803)
- Post Comments Form: Add font family support (WordPress/gutenberg#83967)
- Media Utils: Add `MediaEdit` as a private API (WordPress/gutenberg#84046)
- Build Tools: Fix flaky ESM package types test timeout (WordPress/gutenberg#84068)
- Embed: Add padding support (WordPress/gutenberg#83963)
- Interactivity API: Add a data-wp-html directive (WordPress/gutenberg#83092)
- Typography and "block-default icon polish. (WordPress/gutenberg#84073)
- Release Tooling: Read the npm v12 JSON output shapes (WordPress/gutenberg#84075)
- Menu: Align submenu labels and highlight open parents (WordPress/gutenberg#84031)
- Props Bot: Skip bare reviews that duplicate their review comment runs (WordPress/gutenberg#84076)
- Dataviews: use inertValue in CompositeGrid (WordPress/gutenberg#84072)
- UI: Add Meter (WordPress/gutenberg#83855)
- Media & Text: Add shadow support (WordPress/gutenberg#83976)
- Media editor: restore original image in modal (WordPress/gutenberg#81805)
- List: Add background image, size, and gradient support (WordPress/gutenberg#83935)
- List Item: Add background image, size, and gradient support (WordPress/gutenberg#83936)
- Block Editor: Fix 'Manage allowed blocks' not shown when its the only 'Advanced' control (WordPress/gutenberg#84067)
- Design System: Clarify tooltip labeling and UI review guidance (WordPress/gutenberg#83898)
- Gallery: Add minimum width and height support (WordPress/gutenberg#83897)
- File: Add minimum width and height support (WordPress/gutenberg#83896)
- Media: Return 0 from the edit root lookup when there is no edit root (WordPress/gutenberg#84096)
- Read More: Add minimum width and height support (WordPress/gutenberg#83912)
- UI: Recommend Radio family components (WordPress/gutenberg#83872)
- Latest Comments: Add minimum width and height support (WordPress/gutenberg#83904)
- chore: Use v24 in .nvmrc (WordPress/gutenberg#84061)
- Embed: Add minimum width and height support (WordPress/gutenberg#83903)
- Post Comments Form: Add minimum width and height support (WordPress/gutenberg#83910)
- Post Featured Image: Add border style support (WordPress/gutenberg#83956)
- Buttons: Add shadow support (WordPress/gutenberg#83916)
- Poetry: Add fit text support (WordPress/gutenberg#83980)
- Video: Add duotone support (WordPress/gutenberg#83979)
- Notes: Keep anchor writes out of undo history (WordPress/gutenberg#84079)
- ProgressBar: Use WPDS color tokens (WordPress/gutenberg#83779)
- REST API: Add action-trash link to posts and comments (WordPress/gutenberg#84045)
- RSS: Add minimum width and height support (WordPress/gutenberg#83913)
- Notes: Reset paragraph top margin in floating notes (WordPress/gutenberg#84101)
- Global Styles: Fix popover position in Styles screen (WordPress/gutenberg#84048)
- Block Switcher: Show design system focus ring on pattern previews (WordPress/gutenberg#83933)
- MediaEdit: Use design system focus ring (WordPress/gutenberg#83854)
- Notes: Delete permanently when the trash is disabled (WordPress/gutenberg#84102)
- Release: Rewrite SVN publication scripts in Node.js (WordPress/gutenberg#84034)
- ContentEditableControl: Keep a disabled field focusable (WordPress/gutenberg#84083)
- States: Scope per-instance rules to the block's root element (WordPress/gutenberg#83986)
- List Item: Add shadow support (WordPress/gutenberg#83925)
- DataViews: Truncate filter chips instead of wrapping them (WordPress/gutenberg#83879)
- Experiments: Turn the React 19 experiment on by default (WordPress/gutenberg#83784)
- Notes: Extract NoteReply and lift AddNote gating (WordPress/gutenberg#84106)
- Interactivity API: Remove expired deprecated behaviors (WordPress/gutenberg#84098)
- Breadcrumbs: Fix typo in aria label translation context (WordPress/gutenberg#84112)
- ESLint: Allow generated test titles (WordPress/gutenberg#83995)
- Icons: Add keywords to icon manifest (WordPress/gutenberg#83884)
- Tooltip: Control the hover delay cancellation test clock (WordPress/gutenberg#84113)
- VS Code: Add managed workspace config (WordPress/gutenberg#84025)
- Breadcrumb: fix getMeasurementRender for React 19 (WordPress/gutenberg#84069)
- Notes: Fix flaky thread scroll e2e test (WordPress/gutenberg#84118)
- Detect the database client in the unit test debug step. (WordPress/gutenberg#84089)
- UI: Preserve Autocomplete item type inference (WordPress/gutenberg#84095)
- UI: Recommend Switch family components (WordPress/gutenberg#84097)
- Env: Add an option to choose the MariaDB version (WordPress/gutenberg#83751)
- UI: Preserve Budugbox source item generics (WordPress/gutenberg#84094)
- Menu: Tighten spacing, use 16px prefix icons, and cap width at 320px (WordPress/gutenberg#84028)
- Notes: Preserve unsent note and reply drafts (WordPress/gutenberg#84110)
- Theme: Add integration test coverage for seed colors in artifacts (WordPress/gutenberg#81161)
- Progress: Migrate remaining ProgressBar usages and recommend UI Progress (WordPress/gutenberg#84021)
- Components: Fix polymorphism typings leaking `as` prop (WordPress/gutenberg#82704)
- Media & Text: Add background image, size, and gradient support (WordPress/gutenberg#83927)
- Experiments: Use a mock plugin slug that no WordPress build ships in the unrelated-plugin test (WordPress/gutenberg#84133)
- Button: Add background image, size, and gradient support (WordPress/gutenberg#83950)
- Tests: Isolate Ajv per test in wp-env schema tests to avoid order dependence (WordPress/gutenberg#84139)
- Storybook: Read icon keywords from the manifest (WordPress/gutenberg#84127)
- SandBox: Fix embed previews that require a referrer in Safari (WordPress/gutenberg#84014)
- Notes: Restore child notes trashed along with their parent note (WordPress/gutenberg#84100)
- Style states: fix exception when there's no selected block (WordPress/gutenberg#84140)
- Chore: Use v24.20 in  `.nvmrc` config file. (WordPress/gutenberg#84138)
- Security: Opt in to the npm v12 supply-chain defaults (WordPress/gutenberg#82689)
- Docs: Describe isolated dependencies for agents and contributors (WordPress/gutenberg#84141)
- Upgrade code and types to React 19 (WordPress/gutenberg#83941)
- Latest Comments: Add border support (WordPress/gutenberg#84148)
- Add prettier, eslint and stylelint to the root package.json (WordPress/gutenberg#84017)
- FontSizePicker: Migrate Emotion styles to SCSS Modules (WordPress/gutenberg#84126)
- Fields API: Add the server-side registry and REST route (WordPress/gutenberg#84078)
- Block bindings: add support to `icon` attribute of `core/icon` (WordPress/gutenberg#80730)
- VisuallyHidden: Move hiding styles outside CSS cascade layers (WordPress/gutenberg#84114)
- Theme: Generate complete border token modes for Figma testing (WordPress/gutenberg#84035)
- Developer tools: Simplify editor setup and add Zed settings (WordPress/gutenberg#84143)
- Consolidate wp-admin container radiuses onto the design system scale (WordPress/gutenberg#82427)
- CustomGradientPicker: Extend control point targets to the bar height (WordPress/gutenberg#84124)
- Notes: Draw the canvas divider from body so it uses the theme text color (WordPress/gutenberg#84158)
- Icons: Experiment with proportional stroke scaling (WordPress/gutenberg#84081)
- Global Styles: Ignore theme.json values of unexpected types (WordPress/gutenberg#84523)
- React 19 codemod: apply defaultProps when rendering a memo component (WordPress/gutenberg#84568)
- React 19: add new incompatible plugins (WordPress/gutenberg#84607)
- Tests: Fix HTML comparison tests (WordPress/gutenberg#84294)
- Tests: Fix list item unsafe markup test on older WordPress versions (WordPress/gutenberg#84302)
- Experiments: don't invalidate saved option with a legacy key (WordPress/gutenberg#84619)
- Tests: Scope Classic block media checkbox locator (WordPress/gutenberg#84524)

Props mamaduka.
See #66340



git-svn-id: https://develop.svn.wordpress.org/trunk@64587 602fd350-edb4-49c9-b593-d223f7449a82
wporg-sync pushed a commit to WordPress/WordPress that referenced this pull request Oct 20, 2026
This updates the pinned commit hash of the Gutenberg repository from 954fe7f9e04631c41aec4552acd627a7203a2aad to 7b95ee96b54de2e35886971ccf7eb449c324c830 (version 24.2.0).

A full list of changes included in this commit can be found on GitHub: WordPress/gutenberg@954fe7f...7b95ee9

- useServerSideRender: parse messages from caught errors (WordPress/gutenberg#83365)
- Docs: Fix published Vitest migration-guide links (WordPress/gutenberg#83449)
- Fix: Whitespace changes are not shown in the Resolve Block diff. (WordPress/gutenberg#82397)
- Editor: Use SearchableSelect for the post author field (WordPress/gutenberg#83323)
- Docs: Note that block attributes and global styles values are untrusted at render time (WordPress/gutenberg#83473)
- RichText: Remove dead exports and consolidate deprecations (WordPress/gutenberg#83461)
- Inserter: Manage roving tab index to skip re-rendering every item (WordPress/gutenberg#83437)
- SearchableSelectControl: Add to @wordpress/ui (WordPress/gutenberg#80979)
- Try: Bolder "B" icon (WordPress/gutenberg#83321)
- Ignore composer vendor files from top-level gitignore. (WordPress/gutenberg#22283)
- Tests: Add floating notes e2e coverage (WordPress/gutenberg#83477)
- Block Editor: Check the inserter's fallback containers unmemoized (WordPress/gutenberg#83446)
- Packages: Update Ariakit to 0.4.40 (WordPress/gutenberg#83278)
- Tests: Enforce per-call Vitest console expectations (WordPress/gutenberg#83095)
- Theme: Fix virtual modules, root styles, and seed validation (WordPress/gutenberg#83355)
- DataViews: Fix README to describe sort() as receiving field values, not items (WordPress/gutenberg#83483)
- Budugbox: Label popup dialogs in stories (WordPress/gutenberg#83476)
- Block editor: Isolate mutable test fixtures (WordPress/gutenberg#83098)
- Blocks: Isolate registration state in tests (WordPress/gutenberg#83099)
- UI: Remove automatic Notice announcements (WordPress/gutenberg#82737)
- Text: Migrate Emotion styles to an SCSS Module (WordPress/gutenberg#82573)
- Block library: Isolate order-sensitive test interactions (WordPress/gutenberg#83101)
- Format Library: unify FormatEditProps to one type, move private types (WordPress/gutenberg#83487)
- UI: Announce selected chips in SearchableChipSelect (WordPress/gutenberg#82863)
- Card: Migrate from Emotion to SCSS modules (WordPress/gutenberg#82577)
- Components: Deprecate the private Menu API (WordPress/gutenberg#82947)
- CustomGradientPicker: Migrate control wrappers to an SCSS module (WordPress/gutenberg#82576)
- Components: Isolate order-sensitive UI tests (WordPress/gutenberg#83103)
- Tests: Isolate mutable configuration fixtures (WordPress/gutenberg#83104)
- Core data: Finish deferred selection updates in RTC test (WordPress/gutenberg#83366)
- Block editor: Wait for final keyboard link suggestions (WordPress/gutenberg#83489)
- Data: Assert and silence resolution error in useSuspenseSelect test (WordPress/gutenberg#83491)
- Tests: Isolate deprecation warning state (WordPress/gutenberg#83107)
- UI: Align selection popup checkmarks with the first label line (WordPress/gutenberg#82942)
- Tests: Resolve Browser Mode commands against the live iframe (WordPress/gutenberg#83495)
- Ensure position type is a string (WordPress/gutenberg#83500)
- MediaUpload: Fix console error when reopening Gallery media library (WordPress/gutenberg#76749)
- Refactor stylelint config detection in lint-style.js (WordPress/gutenberg#79280)
- Docs: Recommend UI Tabs for switching views (WordPress/gutenberg#83516)
- Popover: Close non-modal popovers on iframe interaction (WordPress/gutenberg#83509)
- Typography: List only the weights inside a variable font's range (WordPress/gutenberg#83128)
- Style book: Add link to example text. (WordPress/gutenberg#83448)
- Tests: Add Vitest Browser Mode failure artifacts (WordPress/gutenberg#83093)
- Theme: Make JavaScript token fallback transforms syntax-aware (WordPress/gutenberg#83356)
- Editor: Fix new posts being published with the `auto-draft` slug (WordPress/gutenberg#83518)
- Editor: Gather the View group of the Options menu into submenus (WordPress/gutenberg#82976)
- Tests: Fix PostCSS browser-externalized warnings in Vitest (WordPress/gutenberg#83091)
- Tests: Shuffle test cases in CI (WordPress/gutenberg#83111)
- Update Styles > Blocks description. (WordPress/gutenberg#83515)
- Columns: Remove the column count slider (WordPress/gutenberg#83262)
- BorderControl: Remove `%` from the border width units (WordPress/gutenberg#83492)
- Fields: Fix AuthorView for users who can't edit users (WordPress/gutenberg#83498)
- Update and add justify icons. (WordPress/gutenberg#83519)
- RichText: Refactor useMarkPersistent, fix StrictMode mount mark (WordPress/gutenberg#83463)
- Theme: Improve accessibility, API documentation, and compatibility checks (WordPress/gutenberg#83358)
- Theme: Preserve global token references in Lightning CSS (WordPress/gutenberg#83359)
- Tests: Migrate internal linting to Vitest and remove unused Jest dependencies (WordPress/gutenberg#83502)
- Improve specificity of lightbox button selector (WordPress/gutenberg#70800)
- TextControl: Use design system colors when disabled (WordPress/gutenberg#83307)
- Fix: Image lightbox: overlay becomes unusable (can't close) when it isn't a direct child of `<body>` (WordPress/gutenberg#83480)
- Notes: Extract note selection sync into useNoteSelection hook (WordPress/gutenberg#83528)
- Block Parser: Document `\WP_Block_Parser::$stack` as a list (WordPress/gutenberg#82695)
- CollapsibleCard: Scope the header focus ring to its own trigger (WordPress/gutenberg#81314)
- Fix broken links in docs (WordPress/gutenberg#83545)
- Icons: Use assertEqualHTML() in icons registry tests (WordPress/gutenberg#83544)
- Editor: Merge adjacent revision inline diffs (WordPress/gutenberg#80579)
- Date: Ignore trailing format backslash instead of printing undefined (WordPress/gutenberg#81528)
- Block Supports: Add background-clip block support infrastructure (WordPress/gutenberg#77141)
- Block Editor: Fix translator comments for block count announcements (WordPress/gutenberg#83555)
- Paste: replace non-breaking spaces at the edges of text with regular spaces (WordPress/gutenberg#83464)
- Media Editor: Fix pan drag flooding undo history after wheel zoom (WordPress/gutenberg#83558)
- Rich text: fix iOS double tap selection, preventing focus capture under editable host (WordPress/gutenberg#81042)
- Block editor: migrate state-control badges to UI Badge (WordPress/gutenberg#82608)
- Gallery: Add Order By controls for static gallery, consolidate controls in settings sidebar (WordPress/gutenberg#83438)
- Media editor: show an error when saving attachment details fails (WordPress/gutenberg#83560)
- Position controls: Fix useSelect warning for selected state viewports (WordPress/gutenberg#83570)
- Inserter: Use design system focus ring for previews (WordPress/gutenberg#83126)
- Image: Fix lightbox using thumbnail aspect ratio instead of original image ratio (WordPress/gutenberg#79058)
- Docs: Clarify @wordpress/ui icon color requirements (WordPress/gutenberg#83564)
- docker compose -T if stdin is not a tty (WordPress/gutenberg#78374)
- Storybook: Add new contributing page. (WordPress/gutenberg#83345)
- Widget Primitives: Avoid Vite warnings for runtime widget modules (WordPress/gutenberg#83602)
- Build: Update Vite to 8.3.1 and simplify Storybook tooling (WordPress/gutenberg#83569)
- doc(wp-env) Change core branch from trunk to master in doc (WordPress/gutenberg#83566)
- wp-build: Remove the unused boot, private-apis, and route optional peer dependencies (WordPress/gutenberg#83601)
- CI: Check CHANGELOG presence for published tooling and config packages (WordPress/gutenberg#83577)
- Tests: Enforce Vitest assertion coverage (WordPress/gutenberg#83572)
- Icons: Update heading level icons for optical balance (WordPress/gutenberg#83268)
- ESLint: Add allowUseWithCaution option to use-recommended-components (WordPress/gutenberg#83536)
- Notes: Refactor floating board measurement (WordPress/gutenberg#83485)
- Inserter: Stop re-rendering the block list on block selection change (WordPress/gutenberg#83284)
- Paste: Give each pasted data-URI image unique filename to avoid upload collisions. (WordPress/gutenberg#79480)
- Changelog validator: ignore markdown & configs d46223 (WordPress/gutenberg#83618)
- Font Library: Use UI Menu for collection actions (WordPress/gutenberg#82965)
- Storybook: Show prop descriptions in Canvas controls (WordPress/gutenberg#83581)
- test: Link upstream warning fixes in config (WordPress/gutenberg#83632)
- Storybook: Use one block-editor store module (WordPress/gutenberg#83636)
- Tests: Use strict assertions synced from Core changeset 63934. (WordPress/gutenberg#83619)
- Math: Store cell alignment in the MathML and polyfill alignment and overlines in Chromium (WordPress/gutenberg#83164)
- Storybook: Reuse PostCSS browser resolver in smoke tests (WordPress/gutenberg#83635)
- Editor: Use UI Menu for template options (WordPress/gutenberg#82964)
- RTC: Add a EntitySyncManager interface in core-data (WordPress/gutenberg#83410)
- Term Count: Add margin support (WordPress/gutenberg#83608)
- Archives: Add minimum height support (WordPress/gutenberg#83573)
- Media Editor: Stop the crop pixel snap from recording undo history (WordPress/gutenberg#83571)
- Term Name: Add margin support (WordPress/gutenberg#83606)
- Post Author Biography: Add text indent support (WordPress/gutenberg#83614)
- Code: Add minimum width and height support (WordPress/gutenberg#83574)
- Details: Add minimum width support (WordPress/gutenberg#83576)
- Post Content: Add minimum width support (WordPress/gutenberg#83575)
- Post Excerpt: Add minimum width and height support (WordPress/gutenberg#83578)
- Post Title: Add minimum width and height support (WordPress/gutenberg#83600)
- Footnotes: Add minimum width and height support (WordPress/gutenberg#83579)
- Storybook: Place Notice announcements under Components (WordPress/gutenberg#83617)
- InputControl: Darken the field border on hover (WordPress/gutenberg#83306)
- npm: Switch from legacy-peer-deps to strict-peer-deps (WordPress/gutenberg#81029)
- Term Name: Add minimum width and height support (WordPress/gutenberg#83599)
- Columns: Allow dropping a column at the outer edges (WordPress/gutenberg#83274)
- E2E: Pin the site title in the Interactivity API router specs and give the E2E Storybook build more heap. (WordPress/gutenberg#83474)
- Heading: Add minimum width and height support (WordPress/gutenberg#83580)
- Login/out: Add minimum width and height support (WordPress/gutenberg#83583)
- Verse: Add minimum width support (WordPress/gutenberg#83609)
- Video, Cover: Don't autoplay in the editor when reduced motion is preferred (WordPress/gutenberg#83337)
- Media & Text: Lower the specificity of the content padding (WordPress/gutenberg#83563)
- Pagination: Add padding, margin, and block gap support (WordPress/gutenberg#83743)
- Fix peer dependency conflicts left in the lockfile (WordPress/gutenberg#83754)
- Comments Pagination: Add padding, margin, and block gap support (WordPress/gutenberg#83744)
- Term Count: Add minimum width and height support (WordPress/gutenberg#83596)
- Read More: Add border style support (WordPress/gutenberg#83735)
- Cover: Don't autoplay embedded background videos when reduced motion is preferred (WordPress/gutenberg#83452)
- No Results: Add minimum width and height support (WordPress/gutenberg#83584)
- RichText: Rename utils.jsx to utils.js (WordPress/gutenberg#83758)
- Quote: Add minimum width support (WordPress/gutenberg#83592)
- Upgrade typescript-eslint to v8.70.1 (WordPress/gutenberg#83760)
- Tabs: Add minimum width support (WordPress/gutenberg#83595)
- Site Tagline: Add minimum width and height support (WordPress/gutenberg#83589)
- Heading: Add text indent support (WordPress/gutenberg#83615)
- Site Title: Add minimum width and height support (WordPress/gutenberg#83593)
- Home Link: Add padding and margin support (WordPress/gutenberg#83607)
- Preformatted: Add minimum width and height support (WordPress/gutenberg#83587)
- Include E2E Storybook sources in docgen (WordPress/gutenberg#83634)
- Extensible Site Editor: Pass custom block categories to the blocks store (WordPress/gutenberg#83762)
- Packages: Declare missing peer dependencies and check them in CI (WordPress/gutenberg#83765)
- Post Terms: Add minimum width and height support (WordPress/gutenberg#83586)
- Group, Cover: Track drop zone element in state (WordPress/gutenberg#83756)
- Global Styles: Add pseudo-state controls for Navigation Link (WordPress/gutenberg#83451)
- storybook: Register playground core blocks once (WordPress/gutenberg#83637)
- Document Outline: Show the design system focus ring instead of legacy box-shadow (WordPress/gutenberg#83755)
- storybook: Update BlockPopover fixture to API version 3 (WordPress/gutenberg#83642)
- Add typing to iAPI's getConfig() (WordPress/gutenberg#71692)
- Components: deprecate Badge (WordPress/gutenberg#82379)
- Block Editor: Fix style / nested attribute overwrite during multi-selection (WordPress/gutenberg#80070)
- Notes: Restrict menu actions for resolution notes and resolved threads (WordPress/gutenberg#73243)
- UI: Add change actions to form primitive stories (WordPress/gutenberg#83591)
- Icons: Support keyword-based search in the icons registry (WordPress/gutenberg#82367)
- Avatar: Explain that avatars use the Gravatar service (WordPress/gutenberg#83567)
- UI: Add item labels and descriptions to remaining popups (WordPress/gutenberg#83493)
- PaletteEdit: Stop changing the slug when renaming a preset (WordPress/gutenberg#83750)
- Storybook: Fix missing block styles in BlockCanvas playground stories (WordPress/gutenberg#81070)
- Tests: Enforce Vitest callback, promise, and title rules (WordPress/gutenberg#83620)
- ItemGroup: Use design system focus ring (WordPress/gutenberg#83764)
- Keep the legacy CheckboxControl visually consistent across viewports (WordPress/gutenberg#83612)
- Media editor: Use UI Menu for crop aspect ratio (WordPress/gutenberg#82968)
- Use strict assertions in override script tests (WordPress/gutenberg#83782)
- Home Link: Add minimum width and height support (WordPress/gutenberg#83582)
- Tab Panels: Add minimum height support (WordPress/gutenberg#83594)
- Post Time to Read: Add minimum width and height support (WordPress/gutenberg#83598)
- Term Description: Add minimum width and height support (WordPress/gutenberg#83597)
- UI: Keep InputLayout chrome at md on small viewports (WordPress/gutenberg#82764)
- Math: Add minimum width and height support (WordPress/gutenberg#83585)
- Tests: Bump undici in the AI development test lockfile (WordPress/gutenberg#83799)
- Bump brace-expansion in /test/ai-development (WordPress/gutenberg#83807)
- Bump js-yaml and promptfoo in /test/ai-development (WordPress/gutenberg#83797)
- Bump fast-uri from 3.1.7 to 3.1.8 (WordPress/gutenberg#83829)
- Update AI Development package versions after npm audit (WordPress/gutenberg#83830)
- Notes: Add show and hide options for floating notes (WordPress/gutenberg#83768)
- Add separators to item popup components (WordPress/gutenberg#83776)
- Components: Align RadioControl colors with UI Radio (WordPress/gutenberg#83270)
- E2E: Mock Openverse in image drag-and-drop inserter test (WordPress/gutenberg#83842)
- FormToggle: Match Switch colors across states (WordPress/gutenberg#83773)
- Bump `@react-spring/web` from 9.4.5 to 10.1.2 (WordPress/gutenberg#83796)
- ColorPalette: Show design system focus ring on custom color button (WordPress/gutenberg#83841)
- Docs: Remove CheckboxControl heading from InspectorControls example (WordPress/gutenberg#83844)
- Base Styles: Default the admin theme color to Blueberry (WordPress/gutenberg#83749)
- Menu: Guard against nesting Group and RadioGroup (WordPress/gutenberg#83792)
- Template Part: Fall back to rendering a template part from the theme file if the db version is unavailable (WordPress/gutenberg#83809)
- Tests: Reset deprecation history in shared Vitest setup (WordPress/gutenberg#83849)
- Menu: Disable triggers instead of roots in consumers (WordPress/gutenberg#83791)
- Playlist: Replace the waveform player patch with its no-autoinit entry (WordPress/gutenberg#83132)
- Update UI Spinner appearance and add a color prop (WordPress/gutenberg#83775)
- UI: Align component names with their semantics (WordPress/gutenberg#83789)
- Checkbox: Prevent rounded themes from making checkboxes circular (WordPress/gutenberg#83526)
- Storybook: Update manifest snapshot for Spinner color prop (WordPress/gutenberg#83856)
- Button: Only open the link popover on explicit user action (WordPress/gutenberg#30166)
- Gallery Lightbox: Prevent image click from closing the dialog when navigation is enabled (WordPress/gutenberg#78898)
- UI: Recommend Checkbox family components (WordPress/gutenberg#83771)
- RadioControl: Keep a 16px visual with a larger hit target (WordPress/gutenberg#83840)
- Table: replace deprecated word-break with overflow-wrap: anywhere (WordPress/gutenberg#82480)
- Tag Cloud: Update styles and add `!important` (WordPress/gutenberg#70224)
- Correctly document the `blockName` property as being nullable (WordPress/gutenberg#70900)
- Add inertValue helper and use it for setting inert attribute (WordPress/gutenberg#83871)
- Enable editableRoot for the list item block for multi-selection on mobile (WordPress/gutenberg#82816)
- Verify localized data retention in override script test (WordPress/gutenberg#83845)
- Tests: Bump ibm-cloud-sdk-core in the AI development test lockfile (WordPress/gutenberg#83887)
- UI: Recommend Notice component (WordPress/gutenberg#82685)
- Fix: MediaUpload `gallery` prop ignores `allowedTypes` (WordPress/gutenberg#78257)
- Media editor: Add a session boundary above the cropper (WordPress/gutenberg#83550)
- DataViews: Measure the container as the data view mounts to avoid a single column flash (WordPress/gutenberg#83752)
- Pullquote: Add minimum width support (WordPress/gutenberg#83588)
- Media editor: Remove initial state seeding from the session (WordPress/gutenberg#83893)
- UI: Add e2e Storybook popup item layout fixtures (WordPress/gutenberg#83488)
- Storybook: Give CI job a distinct name (WordPress/gutenberg#83869)
- Coding standards: Skip anonymous class methods in block library function name sniff (WordPress/gutenberg#83900)
- Pagination: Add border support (WordPress/gutenberg#83745)
- PR meta: Move the props list into the shared comment (WordPress/gutenberg#82302)
- Comments Pagination: Add border support (WordPress/gutenberg#83746)
- Scripts: Resolve default configs without hoisted dependencies (WordPress/gutenberg#83902)
- Image: Fix invalid CSS url() value in circle-mask style (WordPress/gutenberg#82333)
- Query Total: Add minimum width and height support (WordPress/gutenberg#83590)
- Scripts: Treat files passed after --fix as file arguments (WordPress/gutenberg#83521)
- Editor: Remove icon for 'Export' more menu item (WordPress/gutenberg#83901)
- Dashboard Widgets: let a mounted widget declare actions at runtime (WordPress/gutenberg#83877)
- Framework: Switch from hoisted to isolated dependencies (WordPress/gutenberg#83847)
- Test: Run Vitest type graph validation in process (WordPress/gutenberg#83851)
- Remove use-memo-one usage (missing React 19 compat) (WordPress/gutenberg#83952)
- Fix Post Featured Image crash when isLink is enabled (WordPress/gutenberg#81584)
- Experiment: restyle classic wp-admin controls from design system tokens (WordPress/gutenberg#82425)
- Tests: Lint JavaScript Vitest mock imports (WordPress/gutenberg#83783)
- Build: Remove patch-package (WordPress/gutenberg#83982)
- Docs: Update deprecation testing guidance for shared reset (WordPress/gutenberg#83989)
- DataViews: list hideable fields alphabetically in the view config (WordPress/gutenberg#83947)
- Core Data: Rank link suggestions by type, and stop discarding merged results (WordPress/gutenberg#83407)
- Add new react-inert-value package with inertValue helper (WordPress/gutenberg#83987)
- Connectors: Keep a stored API key read-only when it can't be verified (WordPress/gutenberg#83889)
- Navigation: Search every entity type from the link UI (WordPress/gutenberg#83408)
- Tests: Cover translation setup in override script tests (WordPress/gutenberg#83886)
- Build: Update Vite to 8.3.2 and remove the PostCSS browser resolver (WordPress/gutenberg#83992)
- Update readme title to match block name (WordPress/gutenberg#83999)
- RTC: Fix undo breaking for non-synced entities (WordPress/gutenberg#83888)
- CI: Cover the AI development lockfile with Dependabot instead of npm audit (WordPress/gutenberg#83997)
- Latest Posts: Add minimum width and height support (WordPress/gutenberg#83905)
- Avatar: Add shadow support (WordPress/gutenberg#83929)
- Tab List: Add shadow support (WordPress/gutenberg#83922)
- Buttons: Add minimum width and height support (WordPress/gutenberg#83894)
- Social Icons: Add shadow support (WordPress/gutenberg#83920)
- Columns: Add minimum width and height support (WordPress/gutenberg#83895)
- Gallery: Add shadow support (WordPress/gutenberg#83919)
- File: Add shadow support (WordPress/gutenberg#83918)
- Page List: Add minimum width and height support (WordPress/gutenberg#83908)
- Build Tooling: Read npm v12 pack --json output (WordPress/gutenberg#84011)
- Accordion Heading: Add line height support (WordPress/gutenberg#83958)
- Paragraph: Add shadow support (WordPress/gutenberg#83926)
- Media & Text: Add minimum width and height support (WordPress/gutenberg#83906)
- Tests: Patch basic-ftp in AI development dependencies (WordPress/gutenberg#84000)
- Env, E2E: Update dependencies that ran native install scripts (WordPress/gutenberg#84012)
- Tests: Update Vitest to 5.0.3 and Storybook to 10.6.1 (WordPress/gutenberg#83996)
- Search: Add padding support (WordPress/gutenberg#83984)
- Block editor: Honour background skip serialization in the editor (WordPress/gutenberg#83943)
- Framework: Declare React types in the workspaces that use them (WordPress/gutenberg#84013)
- Fit text: Size each block instance in a loop independently (WordPress/gutenberg#83985)
- FocalPointPicker: end a drag released over the editor canvas (WordPress/gutenberg#83348)
- Tests: Cover Menu scroll lock and LinkControl protocols in browsers (WordPress/gutenberg#83991)
- List: Add shadow support (WordPress/gutenberg#83923)
- UI: Add Progress with custom color support (WordPress/gutenberg#83781)
- ESLint: Allow non-module stylesheet imports in unit tests (WordPress/gutenberg#84019)
- Canvas loader: Use UI Progress and pass color via the indicator prop (WordPress/gutenberg#83860)
- Menu: Align group labels and separators with indented item labels. (WordPress/gutenberg#83993)
- react-inert-value: add missing types/react peer dep (WordPress/gutenberg#84024)
- Docs: Refine design system agent guidance (WordPress/gutenberg#84007)
- Navigation: List allowed blocks in the link UI search results + add transformSuggestions to Link Control (WordPress/gutenberg#83652)
- Sync: Remove exposed wp.sync package (WordPress/gutenberg#81999)
- Style: Update color to use CSS variable in edit-site (WordPress/gutenberg#79002)
- Popover: drop the will-change hint once the popover stops moving (WordPress/gutenberg#77359)
- MediaEdit: Show a checkerboard background behind image previews (WordPress/gutenberg#83846)
- Quote: Add button colour support (WordPress/gutenberg#83983)
- Media & Text: Add duotone support (WordPress/gutenberg#83981)
- Gallery: Add duotone support (WordPress/gutenberg#83978)
- Interactivity API Router: Add reactive navigation lifecycle and initiator API (WordPress/gutenberg#83280)
- Notes: Move floating notes into a canvas margin (WordPress/gutenberg#83786)
- Verse: Add text columns and indent support (WordPress/gutenberg#83962)
- Notes: Scroll floating notes with the canvas (WordPress/gutenberg#83852)
- Notes: Add Undo to deleted note snackbar (WordPress/gutenberg#83988)
- Framework: Move @typescript/native from the root to the workspaces that use it (WordPress/gutenberg#84027)
- Repair invalid peer dependencies in the lockfile (WordPress/gutenberg#84062)
- Term Template: Add minimum width and height support (WordPress/gutenberg#83914)
- Fix check type declarations (WordPress/gutenberg#84070)
- Media: track the original attachment id for edited images (WordPress/gutenberg#81803)
- Post Comments Form: Add font family support (WordPress/gutenberg#83967)
- Media Utils: Add `MediaEdit` as a private API (WordPress/gutenberg#84046)
- Build Tools: Fix flaky ESM package types test timeout (WordPress/gutenberg#84068)
- Embed: Add padding support (WordPress/gutenberg#83963)
- Interactivity API: Add a data-wp-html directive (WordPress/gutenberg#83092)
- Typography and "block-default icon polish. (WordPress/gutenberg#84073)
- Release Tooling: Read the npm v12 JSON output shapes (WordPress/gutenberg#84075)
- Menu: Align submenu labels and highlight open parents (WordPress/gutenberg#84031)
- Props Bot: Skip bare reviews that duplicate their review comment runs (WordPress/gutenberg#84076)
- Dataviews: use inertValue in CompositeGrid (WordPress/gutenberg#84072)
- UI: Add Meter (WordPress/gutenberg#83855)
- Media & Text: Add shadow support (WordPress/gutenberg#83976)
- Media editor: restore original image in modal (WordPress/gutenberg#81805)
- List: Add background image, size, and gradient support (WordPress/gutenberg#83935)
- List Item: Add background image, size, and gradient support (WordPress/gutenberg#83936)
- Block Editor: Fix 'Manage allowed blocks' not shown when its the only 'Advanced' control (WordPress/gutenberg#84067)
- Design System: Clarify tooltip labeling and UI review guidance (WordPress/gutenberg#83898)
- Gallery: Add minimum width and height support (WordPress/gutenberg#83897)
- File: Add minimum width and height support (WordPress/gutenberg#83896)
- Media: Return 0 from the edit root lookup when there is no edit root (WordPress/gutenberg#84096)
- Read More: Add minimum width and height support (WordPress/gutenberg#83912)
- UI: Recommend Radio family components (WordPress/gutenberg#83872)
- Latest Comments: Add minimum width and height support (WordPress/gutenberg#83904)
- chore: Use v24 in .nvmrc (WordPress/gutenberg#84061)
- Embed: Add minimum width and height support (WordPress/gutenberg#83903)
- Post Comments Form: Add minimum width and height support (WordPress/gutenberg#83910)
- Post Featured Image: Add border style support (WordPress/gutenberg#83956)
- Buttons: Add shadow support (WordPress/gutenberg#83916)
- Poetry: Add fit text support (WordPress/gutenberg#83980)
- Video: Add duotone support (WordPress/gutenberg#83979)
- Notes: Keep anchor writes out of undo history (WordPress/gutenberg#84079)
- ProgressBar: Use WPDS color tokens (WordPress/gutenberg#83779)
- REST API: Add action-trash link to posts and comments (WordPress/gutenberg#84045)
- RSS: Add minimum width and height support (WordPress/gutenberg#83913)
- Notes: Reset paragraph top margin in floating notes (WordPress/gutenberg#84101)
- Global Styles: Fix popover position in Styles screen (WordPress/gutenberg#84048)
- Block Switcher: Show design system focus ring on pattern previews (WordPress/gutenberg#83933)
- MediaEdit: Use design system focus ring (WordPress/gutenberg#83854)
- Notes: Delete permanently when the trash is disabled (WordPress/gutenberg#84102)
- Release: Rewrite SVN publication scripts in Node.js (WordPress/gutenberg#84034)
- ContentEditableControl: Keep a disabled field focusable (WordPress/gutenberg#84083)
- States: Scope per-instance rules to the block's root element (WordPress/gutenberg#83986)
- List Item: Add shadow support (WordPress/gutenberg#83925)
- DataViews: Truncate filter chips instead of wrapping them (WordPress/gutenberg#83879)
- Experiments: Turn the React 19 experiment on by default (WordPress/gutenberg#83784)
- Notes: Extract NoteReply and lift AddNote gating (WordPress/gutenberg#84106)
- Interactivity API: Remove expired deprecated behaviors (WordPress/gutenberg#84098)
- Breadcrumbs: Fix typo in aria label translation context (WordPress/gutenberg#84112)
- ESLint: Allow generated test titles (WordPress/gutenberg#83995)
- Icons: Add keywords to icon manifest (WordPress/gutenberg#83884)
- Tooltip: Control the hover delay cancellation test clock (WordPress/gutenberg#84113)
- VS Code: Add managed workspace config (WordPress/gutenberg#84025)
- Breadcrumb: fix getMeasurementRender for React 19 (WordPress/gutenberg#84069)
- Notes: Fix flaky thread scroll e2e test (WordPress/gutenberg#84118)
- Detect the database client in the unit test debug step. (WordPress/gutenberg#84089)
- UI: Preserve Autocomplete item type inference (WordPress/gutenberg#84095)
- UI: Recommend Switch family components (WordPress/gutenberg#84097)
- Env: Add an option to choose the MariaDB version (WordPress/gutenberg#83751)
- UI: Preserve Budugbox source item generics (WordPress/gutenberg#84094)
- Menu: Tighten spacing, use 16px prefix icons, and cap width at 320px (WordPress/gutenberg#84028)
- Notes: Preserve unsent note and reply drafts (WordPress/gutenberg#84110)
- Theme: Add integration test coverage for seed colors in artifacts (WordPress/gutenberg#81161)
- Progress: Migrate remaining ProgressBar usages and recommend UI Progress (WordPress/gutenberg#84021)
- Components: Fix polymorphism typings leaking `as` prop (WordPress/gutenberg#82704)
- Media & Text: Add background image, size, and gradient support (WordPress/gutenberg#83927)
- Experiments: Use a mock plugin slug that no WordPress build ships in the unrelated-plugin test (WordPress/gutenberg#84133)
- Button: Add background image, size, and gradient support (WordPress/gutenberg#83950)
- Tests: Isolate Ajv per test in wp-env schema tests to avoid order dependence (WordPress/gutenberg#84139)
- Storybook: Read icon keywords from the manifest (WordPress/gutenberg#84127)
- SandBox: Fix embed previews that require a referrer in Safari (WordPress/gutenberg#84014)
- Notes: Restore child notes trashed along with their parent note (WordPress/gutenberg#84100)
- Style states: fix exception when there's no selected block (WordPress/gutenberg#84140)
- Chore: Use v24.20 in  `.nvmrc` config file. (WordPress/gutenberg#84138)
- Security: Opt in to the npm v12 supply-chain defaults (WordPress/gutenberg#82689)
- Docs: Describe isolated dependencies for agents and contributors (WordPress/gutenberg#84141)
- Upgrade code and types to React 19 (WordPress/gutenberg#83941)
- Latest Comments: Add border support (WordPress/gutenberg#84148)
- Add prettier, eslint and stylelint to the root package.json (WordPress/gutenberg#84017)
- FontSizePicker: Migrate Emotion styles to SCSS Modules (WordPress/gutenberg#84126)
- Fields API: Add the server-side registry and REST route (WordPress/gutenberg#84078)
- Block bindings: add support to `icon` attribute of `core/icon` (WordPress/gutenberg#80730)
- VisuallyHidden: Move hiding styles outside CSS cascade layers (WordPress/gutenberg#84114)
- Theme: Generate complete border token modes for Figma testing (WordPress/gutenberg#84035)
- Developer tools: Simplify editor setup and add Zed settings (WordPress/gutenberg#84143)
- Consolidate wp-admin container radiuses onto the design system scale (WordPress/gutenberg#82427)
- CustomGradientPicker: Extend control point targets to the bar height (WordPress/gutenberg#84124)
- Notes: Draw the canvas divider from body so it uses the theme text color (WordPress/gutenberg#84158)
- Icons: Experiment with proportional stroke scaling (WordPress/gutenberg#84081)
- Global Styles: Ignore theme.json values of unexpected types (WordPress/gutenberg#84523)
- React 19 codemod: apply defaultProps when rendering a memo component (WordPress/gutenberg#84568)
- React 19: add new incompatible plugins (WordPress/gutenberg#84607)
- Tests: Fix HTML comparison tests (WordPress/gutenberg#84294)
- Tests: Fix list item unsafe markup test on older WordPress versions (WordPress/gutenberg#84302)
- Experiments: don't invalidate saved option with a legacy key (WordPress/gutenberg#84619)
- Tests: Scope Classic block media checkbox locator (WordPress/gutenberg#84524)

Props mamaduka.
See #66340


Built from https://develop.svn.wordpress.org/trunk@64587


git-svn-id: http://core.svn.wordpress.org/trunk@63737 1a063a9b-81f0-0310-95a4-ce76da25c4cd
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Feature] Media Anything that impacts the experience of managing media [Package] Core data /packages/core-data [Type] Enhancement A suggestion for improvement.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants