Skip to content

Conversation

@andrewserong
Copy link
Contributor

@andrewserong andrewserong commented Nov 13, 2025

What?

Part of: #72612

Update the Attachment type to more accurately reflect the properties found in actual API responses.

A Claude-generated overview of what's changed

MediaDetails interface

  • Made core properties optional (width?, height?, file?, filesize?, image_meta?)
  • Added support for audio/video/file metadata (bitrate, channels, codec, length, sample_rate, etc.) — this is based on data found in REST API responses

caption field (add support for handling rich text)

  • Now uses RenderedText< C > instead of a plain string
  • Makes it structured with raw and rendered properties

meta field

  • Changed from Record< string, unknown > to Record< string, unknown > | []
  • More precise typing

post field (previously this expected the media item to always be attached to a post)

  • Updated to allow null (number | null) instead of just number

New fields (these are always present in API responses)

  • Added featured_media
  • Added class_list
  • Added optional _links

These changes broaden the attachment type definition to properly support all (I hope!) attachment media types (images, audio, video, files) and their specific metadata properties.

Why?

While hacking around on support for media as part of dedicated media fields over in #73071, I kept running into issues where properties weren't typed in a way that actually matched the API responses I was working with.

This PR seeks to better match the typing to actual responses, which should (hopefully) make it easier to work with attachment types in TypeScript.

How?

  • Update the types with the additional fields for different media types, and make many of the properties optional as if we have an arbitrary media item, we won't necessarily know ahead of time whether we're dealing with an image, a video, or a file.
  • Add some test fixtures with example JSON files of API responses for attachments.
  • Add a few tests — these are very simple tests, and the main reason they exist is really so that we have some code in this package that is using the types.

Testing Instructions

  • Make sure the tests and linting jobs pass
  • Take a look over the types — do these changes make sense? The main thing that kicked this off for me was while working on a field for caption and I noticed our types didn't allow for rich text to be handled, and then the rest of this PR came about because I thought if I'm going to update one property, I'd better check the whole thing against real API responses.

@andrewserong andrewserong self-assigned this Nov 13, 2025
@andrewserong andrewserong added [Package] Core data /packages/core-data [Type] Code Quality Issues or PRs that relate to code quality labels Nov 13, 2025
@andrewserong andrewserong marked this pull request as ready for review November 13, 2025 04:04
@andrewserong andrewserong requested a review from nerrad as a code owner November 13, 2025 04:04
@github-actions
Copy link

github-actions bot commented Nov 13, 2025

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: andrewserong <[email protected]>
Co-authored-by: ramonjd <[email protected]>
Co-authored-by: tellthemachines <[email protected]>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@github-actions
Copy link

Flaky tests detected in 5a80c7f.
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/19319945010
📝 Reported issues:

Copy link
Member

@ramonjd ramonjd left a comment

Choose a reason for hiding this comment

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

Makes sense to me. Here are the responses from an audio/video file:

Screenshot 2025-11-13 at 3 34 36 pm Screenshot 2025-11-13 at 3 34 22 pm

Copy link
Contributor

@tellthemachines tellthemachines left a comment

Choose a reason for hiding this comment

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

Changes LGTM!

width?: number;
height?: number;
file?: string;
filesize?: number;
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't file and filesize always exist? Or are there circumstances in which we don't have access to them through the API?

Copy link
Contributor Author

@andrewserong andrewserong Nov 13, 2025

Choose a reason for hiding this comment

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

As strange as it might seem, MediaDetails can actually be an empty object! The REST API gets the attachment metadata (which can be filtered) and if it's empty it'll return an empty object:

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

In practice and normal usage (and in the included fixtures) filesize is always present, but file isn't always. This is what Claude tells me across these fixtures:

Fixture Results:

Fixture file filesize
Image ✅ Present ✅ Present
Zip ❌ Missing ✅ Present
Audio ❌ Missing ✅ Present
Video ❌ Missing ✅ Present

Because we're technically displaying what's in the metadata in this interface (and an empty object is a valid response), I'm leaning toward keeping these optional.

Copy link
Contributor

Choose a reason for hiding this comment

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

Sure! If they don't always exist they should be optional.

date?: string;
comment?: string;
band?: string;
year?: string;
Copy link
Contributor

Choose a reason for hiding this comment

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

Interesting that these metadata are specific to audio! Some of them would be useful for video too. Very much not a problem for this PR though 😁

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, totally! I believe most of these are from id3 tags from my quick skim of wordpress-develop

};
}
interface ImageMeta {
aperture: string;
Copy link
Contributor

Choose a reason for hiding this comment

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

I would have thought aperture would be optional but apparently when we don't have the info we just set it to "0" 😅

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There's a few things like that!

@andrewserong
Copy link
Contributor Author

Thanks for reviewing, folks! I'll merge this in, but happy to do any follow-ups if any of these types look off. I believe this update will help us quite a bit when it comes to building out media library interfaces and fields using all these properties.

@andrewserong andrewserong merged commit b93097b into trunk Nov 13, 2025
52 of 55 checks passed
@andrewserong andrewserong deleted the update/attachment-types-to-reflect-api-responses branch November 13, 2025 05:26
@github-actions github-actions bot added this to the Gutenberg 22.2 milestone Nov 13, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Package] Core data /packages/core-data [Type] Code Quality Issues or PRs that relate to code quality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants