Skip to content

Fix incorrect width and height in core/image block #5776

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 16 commits into from
May 30, 2025

Conversation

itsTallulah
Copy link
Contributor

@itsTallulah itsTallulah commented Aug 5, 2024

Description

Addresses incorrect img tag width|height values in core/image blocks by filtering render_block, where it can get the attachment ID and intended size from the classes of the img and figure tags.
From there it looks for the intended size's w|h values in the attachment's postmeta, and add them to the img tag for the return.
Also fixes incorrect srcsets for block images without having to touch them, since it's upstream of them and supplies the values they need.
Returns original safely and silently on failure. Matches narrowly, and can operate on already-filtered blocks as long as they have the required size and ID classes.
Optional switch for resize args can be omitted, but it could be nice to give folks the choice. I defer to plat as to how to make this switchable (or if we should just lose it for simplicity and brevity).

Changelog Description

Fixed

  • Fixed incorrect image sizes and srcsets for core/image blocks on frontend requests

Pre-review checklist

Please make sure the items below have been covered before requesting a review:

  • This change works and has been tested locally or in Codespaces (or has an appropriate fallback).
  • This change works and has been tested on a sandbox.
  • This change has relevant unit tests (if applicable).
  • This change uses a rollout method to ease with deployment (if applicable - especially for large scale actions that require writes).
  • This change has relevant documentation additions / updates (if applicable).
  • I've created a changelog description that aligns with the provided examples.

Pre-deploy checklist

  • VIP staff: Ensure any alerts added/updated conform to internal standards (see internal documentation).

Steps to Test

  1. Check out PR / use relevant file as generic mu-plugin
  2. Examine any page/post with core/image block/s
  3. Examine src of any core/image block (other than size:full)
  4. Its width and height values and srcset should all be congruent with its intended size
  5. It should also visually look the same size in the frontend and the editor
  6. Repeat as required for any/all registered sizes
  7. Optional: register some custom sizes and repeat

@itsTallulah itsTallulah requested a review from a team as a code owner August 5, 2024 22:06
Copy link

codecov bot commented Aug 5, 2024

Codecov Report

Attention: Patch coverage is 96.55172% with 1 line in your changes missing coverage. Please review.

Project coverage is 31.58%. Comparing base (a5b84dc) to head (4ddac9f).
Report is 33 commits behind head on develop.

Files with missing lines Patch % Lines
a8c-files.php 96.55% 1 Missing ⚠️
Additional details and impacted files
@@              Coverage Diff              @@
##             develop    #5776      +/-   ##
=============================================
+ Coverage      31.46%   31.58%   +0.12%     
- Complexity      4970     4982      +12     
=============================================
  Files            298      298              
  Lines          21871    21898      +27     
=============================================
+ Hits            6881     6917      +36     
+ Misses         14990    14981       -9     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

// Add the width and height attributes to the img tag
$block_content = preg_replace(
'/<img ([^>]+)>/',
'<img foo="bar" $1 width="' . esc_attr($width) . '" height="' . esc_attr($height) . '">',
Copy link
Member

Choose a reason for hiding this comment

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

Is this foo="bar" thing really necessary? :-)

Copy link
Member

Choose a reason for hiding this comment

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

Also, can the <img> tag contain other attributes (say, alt)? If so, is it possible to avoid overwriting them?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oops, that foo is a testing leftover! Thanks for the spot. And yeah, the img and figure tags can contain other values and classes too.

Copy link
Contributor Author

@itsTallulah itsTallulah Aug 6, 2024

Choose a reason for hiding this comment

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

See the first commit: it has the now-removed add_block_bits, which I was using for as an informal test for extra values in the tags by filtering a bunch of extra stuff into the block markup just upstream.

$height = $metadata['sizes'][$size_name]['height'];
$new_file = $metadata['sizes'][$size_name]['file'];

if ($resizearg) {
Copy link
Member

Choose a reason for hiding this comment

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

This condition is always false because we don't seem to set $resizearg to true anywhere.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Indeed, we don't set it true anywhere - yet. I'm deferring to y'all as to how we should let the user set this (if we include it at all).

}
return $block_content;
}
add_filter('render_block', 'fix_img_block_sizes', 10, 3);
Copy link
Contributor

Choose a reason for hiding this comment

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

Since we're only handling core/image blocks, perhaps we can hook into render_block_core/image here? https://github.com/WordPress/wordpress-develop/blob/50af37a9083f003f8e98d089091d2cc428797cc5/src/wp-includes/class-wp-block.php#L581

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good point - Should behave exactly the same on that filter, since it's right after the first one and uses the same values. Will give that a try too.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Works well and makes the function smaller. Nice, thx!

@itsTallulah
Copy link
Contributor Author

Looking at the resizearg option I had in here, it would arguably make more sense to have that as a separate filter combo that can hit all contexts where image scaler args would otherwise be w= style, so I'm going to remove it from this. I'll pitch that as a separate PR, since it's far lower prio than this fix.

@itsTallulah
Copy link
Contributor Author

itsTallulah commented Aug 15, 2024

Removed resizearg section, added a skip for fullsize image size, changed filter to render_block_core/image, renamed function to vip_fix_img_block_sizes for specificity and to avoid collisions (since pervious versions of this fix have been shipped to some customers as a stopgap).

Copy link

1 similar comment
Copy link

sonarqubecloud bot commented Oct 8, 2024

Copy link
Contributor

github-actions bot commented Dec 8, 2024

This pull request has been marked stale because it has been open for 60 days with no activity. If there is no activity within 7 days, it will be closed.

This is an automation to keep pull requests manageable and actionable and is not a comment on the quality of this pull request nor on the work done so far. Closed PRs are still valuable to the project and their branches are preserved.

@itsTallulah
Copy link
Contributor Author

Bumping out of stale to discuss

@itsTallulah
Copy link
Contributor Author

Refactored to use HTML API as discussed in Slack. Verbose with comments on purpose, since I haven't used the HTML API much and I wanted to make sure the flow was followable. Thoughts?

Copy link

sonarqubecloud bot commented Jan 8, 2025

Copy link
Contributor

This pull request has been marked stale because it has been open for 60 days with no activity. If there is no activity within 7 days, it will be closed.

This is an automation to keep pull requests manageable and actionable and is not a comment on the quality of this pull request nor on the work done so far. Closed PRs are still valuable to the project and their branches are preserved.

@rinatkhaziev rinatkhaziev changed the title Fix/block img tag sizes Fix incorrect width and height in core/image block Mar 17, 2025
Copy link

a8c-files.php Outdated
@@ -104,6 +104,9 @@ public function __construct() {
$this->schedule_update_job();
}
}

// Add filter to fix image block sizes
add_filter( 'render_block_core/image', array( $this, 'fix_img_block_sizes' ), 10, 3 );
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
add_filter( 'render_block_core/image', array( $this, 'fix_img_block_sizes' ), 10, 3 );
if ( ! is_admin() ) {
add_filter( 'render_block_core/image', array( $this, 'fix_img_block_sizes' ), 10, 3 );
}

and remove is_admin() check in fix_img_block_sizes().

a8c-files.php Outdated
Comment on lines 528 to 532
// Don't fire in wp-admin, image blocks are fine there
if ( is_admin() ) {
return $block_content;
}

Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// Don't fire in wp-admin, image blocks are fine there
if ( is_admin() ) {
return $block_content;
}

a8c-files.php Outdated
Comment on lines 584 to 593
$update_tag_processor = new WP_HTML_Tag_Processor( $block_content );

// Set width/height for img
if ( $update_tag_processor->next_tag( 'img' ) ) {
$update_tag_processor->set_attribute( 'width', esc_attr( $width ) );
$update_tag_processor->set_attribute( 'height', esc_attr( $height ) );
}

// Get the result ready
$block_content = $update_tag_processor->get_updated_html();
Copy link
Member

Choose a reason for hiding this comment

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

Do you think we can reuse $img_tag_processor here?

if ( $is_admin && ! defined( 'WP_ADMIN' ) ) {
define( 'WP_ADMIN', true );
}

Copy link
Member

Choose a reason for hiding this comment

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

I don't like it because it might affect other tests.

I suggest moving the is_admin() check around the add_filter() call.

Comment on lines 100 to 108
if ( $metadata ) {
$this->assertStringContainsString( 'width="300"', $actual, 'Width attribute should be present' );
$this->assertStringContainsString( 'height="200"', $actual, 'Height attribute should be present' );
$this->assertStringContainsString( 'class="wp-image-123"', $actual, 'Image class should be preserved' );
$this->assertStringContainsString( 'class="wp-block-image size-medium"', $actual, 'Figure class should be preserved' );
remove_filter( 'get_post_metadata', $filter, 10 );
} else {
$this->assertEquals( $expected, $actual );
}
Copy link
Member

Choose a reason for hiding this comment

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

Maybe we can make $expected a string or an array? If $expected is a string, we call assertEquals(). Otherwise, we invoke assertStringContainsString() for every array item. This will make the code cleaner.

Copy link
Contributor

Choose a reason for hiding this comment

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

@sjinks there's no guarantee order of arguments will stay in the same order (hence the THIS IS FLAKY comment). With this approach it's less flaky

Copy link
Member

@sjinks sjinks Apr 10, 2025

Choose a reason for hiding this comment

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

@rinatkhaziev we will have [ 'width="300"', 'height="200"', ... ] etc and then

if ( is_array(‌ $expected ) ) {
    foreach ( $expected as $substring ) {
        self::assertStringContainsString( $substring, $actual );
    }
}

This will move all hardcoded checks out of the test into the data.

Copy link
Member

Choose a reason for hiding this comment

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

if ( is_array( $expected ) ) {
foreach ( $expected as $substring => $message ) {
static::assertStringContainsString( $substring, $actual, $message );
}
} else {
static::assertEquals( $expected, $actual );
}

itsTallulah and others added 13 commits May 30, 2025 07:46
remove preamble comment, remove informal test
I'd left a foo=bar in the returned img tag from testing on non-VIP envs, so I took it out.
removed resizearg switch, used render_block_core/image filter, added skip for fullsize, prepended vip to function name to avoid collisions with existing fix_img_block_sizes filters in use
Co-authored-by: Volodymyr Kolesnykov <[email protected]>
@sjinks sjinks force-pushed the fix/block-img-tag-sizes branch from 5c2f42a to 84211cf Compare May 30, 2025 04:57
Copy link

@rinatkhaziev rinatkhaziev merged commit 00a9fff into develop May 30, 2025
34 checks passed
@rinatkhaziev rinatkhaziev deleted the fix/block-img-tag-sizes branch May 30, 2025 15:05
sjinks added a commit that referenced this pull request Jun 10, 2025
* _encloseme cleanup: Roll out to 25% (#6329)

* chore(deps): Bump preact from 10.26.6 to 10.26.7 in /search/search-dev-tools (#6323)

* chore(deps): Bump preact in /search/search-dev-tools

Bumps [preact](https://github.com/preactjs/preact) from 10.26.6 to 10.26.7.
- [Release notes](https://github.com/preactjs/preact/releases)
- [Commits](preactjs/preact@10.26.6...10.26.7)

---
updated-dependencies:
- dependency-name: preact
  dependency-version: 10.26.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>

* Regenerate the bundle

---------

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: WordPress VIP Bot <[email protected]>

* chore(deps-dev): Bump webpack in /search/search-dev-tools (#6322)

Bumps [webpack](https://github.com/webpack/webpack) from 5.99.8 to 5.99.9.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](webpack/webpack@v5.99.8...v5.99.9)

---
updated-dependencies:
- dependency-name: webpack
  dependency-version: 5.99.9
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* fix: add `wpvip.com` to the list of a8c domains (#6331)

* fix: add `wpvip.com` to the list of a8c domains

* test: update and refactor

* Add Security Boost integration

* Adds comment about the version number

* Update version

* Fix require path

* Rename constants to reflect the new integration name

* Rename to match pattern of other files under the same folder

* Use version from configs

* Automatically load the latest available version of the Security Boost integration when version is set to `latest`

* Fix bad copy paste

* Extract `get_available_versions` utility to prevent code duplication

* Add test cases for `get_selected_version`

* Update wp-parsely submodule to version 3.19.2 (#6333)

* fix(security): exclude expired sessions from rate limiting (#6335)

* fix(security): exclude expired sessions from rate limiting

* refactor(security): safer check for expired sessions

* test: add unit tests

* Remove VIP privacy policy (#6330)

* Remove VIP privacy policy

* lint

* Fix incorrect width and height in core/image block (#5776)

* Create fix-block-img-tag-sizes.php

addresses incorrect w/h values in core/image block img tags

* Update fix-block-img-tag-sizes.php

remove preamble comment, remove informal test

* remove testing foobar

I'd left a foo=bar in the returned img tag from testing on non-VIP envs, so I took it out.

* Update fix-block-img-tag-sizes.php

removed resizearg switch, used render_block_core/image filter, added skip for fullsize, prepended vip to function name to avoid collisions with existing fix_img_block_sizes filters in use

* switch to HTML API

* Fix lint issues

* Move the functionality inside a8c-files.php

* Add tests

* Add dataProvider

* Fix tests

* Cleanup

* Fix admin-context tests

* Update a8c-files.php

Co-authored-by: Volodymyr Kolesnykov <[email protected]>

* fix: address my own suggestions

* test: refactor

* test: do not run tests in a separate process

---------

Co-authored-by: Rinat K <[email protected]>
Co-authored-by: Volodymyr Kolesnykov <[email protected]>

* fix(files): memory usage in `filter_wp_read_image_metadata()` (#5554)

* Test larger timeout for get_file operations

* 280s timeout for testing

* Try to get filesize from WP attachment meta

* Dynamically calculate get_file timeout

* Remove debug code

* Code style

* fix(files): memory usage in `filter_wp_read_image_metadata()`

* test: mock `is_file()` call

* style: fix linting issues

---------

Co-authored-by: Angel Alonso <[email protected]>

* Swap FILE_SERVICE_ENDPOINT for FILE_SERVICE_URI that allows a full URI as endpoint (#6195)

* chore(deps): Bump preact from 10.26.7 to 10.26.8 in /search/search-dev-tools (#6339)

* chore(deps): Bump preact in /search/search-dev-tools

Bumps [preact](https://github.com/preactjs/preact) from 10.26.7 to 10.26.8.
- [Release notes](https://github.com/preactjs/preact/releases)
- [Commits](preactjs/preact@10.26.7...10.26.8)

---
updated-dependencies:
- dependency-name: preact
  dependency-version: 10.26.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>

* Regenerate the bundle

---------

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: WordPress VIP Bot <[email protected]>

* chore(deps-dev): Bump sass in /search/search-dev-tools (#6338)

Bumps [sass](https://github.com/sass/dart-sass) from 1.89.0 to 1.89.1.
- [Release notes](https://github.com/sass/dart-sass/releases)
- [Changelog](https://github.com/sass/dart-sass/blob/main/CHANGELOG.md)
- [Commits](sass/dart-sass@1.89.0...1.89.1)

---
updated-dependencies:
- dependency-name: sass
  dependency-version: 1.89.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Add newrelic_ignore_transaction to prometheus endpoint (#6279)

* Update wp-parsely submodule to version 3.19.3 (#6341)

* test: fix incorrect tear down sequence in `Remote_Data_Blocks_Integration_Test` (#6340)

---------

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: Rebecca Hum <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: WordPress VIP Bot <[email protected]>
Co-authored-by: Bruno Basto <[email protected]>
Co-authored-by: Alex Cicovic <[email protected]>
Co-authored-by: Tallulah <[email protected]>
Co-authored-by: Rinat K <[email protected]>
Co-authored-by: Angel Alonso <[email protected]>
Co-authored-by: Michael Chan <[email protected]>
Co-authored-by: Luis Henrique Mulinari <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants