Conversation
There was a problem hiding this comment.
Pull request overview
Adds configurable image lazy-loading to the Carousel Kit blocks by introducing a carousel-level toggle with a per-slide opt-out, and applying the behavior on render via a WordPress block render filter.
Changes:
- Added
lazyLoadImagesattribute + inspector toggle to the Carousel block (default: enabled). - Added
disableLazyLoadImagesattribute + inspector toggle to the Slide block (default: disabled). - Added a
render_block_carousel-kit/carousel-slidefilter that usesWP_HTML_Tag_Processorto addloading="lazy"to<img>tags when enabled.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
src/blocks/carousel/types.ts |
Extends block attribute types to include carousel/slide lazy-load flags. |
src/blocks/carousel/edit.tsx |
Adds the Carousel inspector toggle wiring for lazyLoadImages. |
src/blocks/carousel/block.json |
Persists lazyLoadImages with default true and exposes it via block context. |
src/blocks/carousel/slide/edit.tsx |
Adds Slide inspector toggle for disableLazyLoadImages. |
src/blocks/carousel/slide/block.json |
Persists disableLazyLoadImages and declares the carousel context dependency. |
src/blocks/carousel/__tests__/types.test.ts |
Updates TS type tests to include lazyLoadImages. |
inc/Plugin.php |
Implements server-side HTML mutation to add loading="lazy" based on context + slide attrs. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 8 out of 8 changed files in this pull request and generated 4 comments.
Comments suppressed due to low confidence (1)
src/blocks/carousel/tests/types.test.ts:66
- In the “should have all required properties” test,
lazyLoadImagesis now a required attribute but it isn’t included in therequiredKeyslist that the test iterates over. This makes the runtime key-presence assertion incomplete; please addlazyLoadImagesto that list so the test actually verifies the new required attribute is present.
lazyLoadImages: false,
};
// Verify all keys exist
const requiredKeys = [
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
@mi5t4n Thank you for the PR for this. I have a few questions. On the need for The case where you'd want a slide's images to not be lazy-loaded seem to be: the first slide — deterministic, could be handled automatically by slide position. Could the feature be simplified by removing Current (hooked per-slide, no position awareness): add_filter( 'render_block_carousel-kit/carousel-slide', [ $this, 'handle_lazy_load_images' ], 10, 3 );
// Fires once per slide — 8 slides = 8 WP_HTML_Tag_Processor instances.
// No way to know if this is the first slide.Suggestion (hooked once at the carousel level, position-aware): add_filter( 'render_block_carousel-kit/carousel', [ $this, 'handle_lazy_load_images' ], 10, 2 );
public function handle_lazy_load_images( string $block_content, array $parsed_block ): string {
if ( is_admin() ) {
return $block_content;
}
$lazy_load = (bool) ( $parsed_block['attrs']['lazyLoadImages'] ?? true );
if ( ! $lazy_load ) {
return $block_content;
}
$processor = new WP_HTML_Tag_Processor( $block_content );
$slide_index = -1;
$in_first_slide = false;
while ( $processor->next_tag() ) {
$tag = $processor->get_tag();
if ( 'DIV' === $tag && $processor->has_class( 'embla__slide' ) ) {
$slide_index++;
$in_first_slide = ( 0 === $slide_index );
}
if ( 'IMG' !== $tag || null !== $processor->get_attribute( 'loading' ) ) {
continue;
}
if ( $in_first_slide ) {
$processor->set_attribute( 'loading', 'eager' );
$processor->set_attribute( 'fetchpriority', 'high' );
} else {
$processor->set_attribute( 'loading', 'lazy' );
}
}
return $processor->get_updated_html();
}This also means the On WordPress core's native lazy loading — is this already handled? Worth checking: The PR checklist marks tests as added, but Suggestions: public function test_handle_lazy_load_images_returns_early_when_disabled(): void {
$instance = \Mockery::mock( \WP_Block::class );
$instance->context = [ 'carousel-kit/carousel/lazyLoadImages' => false ];
$block_content = '<div><img src="test.jpg" /></div>';
$parsed_block = [ 'attrs' => [] ];
$plugin = $this->getPluginInstance();
$result = $this->invokeMethod( $plugin, 'handle_lazy_load_images', [ $block_content, $parsed_block, $instance ] );
$this->assertSame( $block_content, $result );
}
public function test_handle_lazy_load_images_respects_per_slide_disable(): void {
$instance = \Mockery::mock( \WP_Block::class );
$instance->context = [ 'carousel-kit/carousel/lazyLoadImages' => true ];
$block_content = '<div><img src="test.jpg" /></div>';
$parsed_block = [ 'attrs' => [ 'disableLazyLoadImages' => true ] ];
$plugin = $this->getPluginInstance();
$result = $this->invokeMethod( $plugin, 'handle_lazy_load_images', [ $block_content, $parsed_block, $instance ] );
$this->assertSame( $block_content, $result );
}
public function test_handle_lazy_load_images_does_not_override_existing_loading(): void {
$instance = \Mockery::mock( \WP_Block::class );
$instance->context = [ 'carousel-kit/carousel/lazyLoadImages' => true ];
$block_content = '<div><img src="test.jpg" loading="eager" /></div>';
$parsed_block = [ 'attrs' => [] ];
$plugin = $this->getPluginInstance();
$result = $this->invokeMethod( $plugin, 'handle_lazy_load_images', [ $block_content, $parsed_block, $instance ] );
$this->assertStringContainsString( 'loading="eager"', $result );
$this->assertStringNotContainsString( 'loading="lazy"', $result );
} |
| } | ||
|
|
||
| } | ||
|
|
There was a problem hiding this comment.
Minor PHPCS note — there's a trailing blank line before the closing } of the while block that might trigger a sniff:
Suggestion:
while ( $processor->next_tag( 'img' ) ) {
if ( null === $processor->get_attribute( 'loading' ) ) {
$processor->set_attribute( 'loading', 'lazy' );
}
}…yLoadImages for slides
… usage guide and edit component
…e from Edit component from slide block
…improved performance
milindmore22
left a comment
There was a problem hiding this comment.
Overall needs a lint check.
----------------------------------------------------------------------------------------------------------------------------------
FOUND 3 ERRORS AND 2 WARNINGS AFFECTING 4 LINES
----------------------------------------------------------------------------------------------------------------------------------
295 | WARNING | [x] Equals sign not aligned with surrounding assignments; expected 3 spaces but found 1 space
| | (Generic.Formatting.MultipleStatementAlignment.NotSameWarning)
298 | ERROR | [x] Space after opening parenthesis of function call prohibited
| | (PEAR.Functions.FunctionCallSignature.SpaceAfterOpenBracket)
298 | ERROR | [x] Expected 0 spaces before closing parenthesis; 2 found
| | (PEAR.Functions.FunctionCallSignature.SpaceBeforeCloseBracket)
303 | WARNING | [x] Stand-alone post-increment statement found. Use pre-increment instead: ++$slide_index.
| | (Universal.Operators.DisallowStandalonePostIncrementDecrement.PostIncrementFound)
307 | ERROR | [x] Use early exit to reduce code nesting. (SlevomatCodingStandard.ControlStructures.EarlyExit.EarlyExitNotUsed)
----------------------------------------------------------------------------------------------------------------------------------
PHPCBF CAN FIX THE 5 MARKED SNIFF VIOLATIONS AUTOMATICALLY
----------------------------------------------------------------------------------------------------------------------------------
| $processor = new WP_HTML_Tag_Processor( $block_content ); | ||
| $slide_index = 0; | ||
|
|
||
| while ( $processor->next_tag( ) ) { |
|
|
||
| // Keep a track of the slide index to determine if an image is in the first slide or subsequent slides. | ||
| if ( 'DIV' === $tag && $processor->has_class( 'embla__slide' ) ) { | ||
| $slide_index++; |
There was a problem hiding this comment.
Use pre-increment instead: ++$slide_index.
| } | ||
|
|
||
| // If it's the first slide, set loading="lazy". For subsequent slides, set loading="eager" and fetchpriority="high". | ||
| if ( 'IMG' === $tag && null === $processor->get_attribute( 'loading' ) ) { |
Summary
Add LazyLoadImages toggle to Carousel block with per-slide override option
Type of change
Related issue(s)
Closes #93
What changed
loading="lazy" attribute to images inside carousel slides
Breaking changes
Does this introduce a breaking change? If yes, describe the impact and migration path below.
Testing
Test details:
Prerequisites
Test Cases
Verification
View page source to confirm
Screenshots / recordings
If applicable, add screenshots or short recordings.
Checklist