Skip to content

Instantly share code, notes, and snippets.

@mukeshpanchal27
Last active August 23, 2024 08:41
Show Gist options
  • Save mukeshpanchal27/f92bf08c4a0db919c6f50873a7ac3cc3 to your computer and use it in GitHub Desktop.
Save mukeshpanchal27/f92bf08c4a0db919c6f50873a7ac3cc3 to your computer and use it in GitHub Desktop.
WPP Column Image Sizes is a proof of concept WordPress plugin that provides a better calculation for nested image block in columns.

WPP Column Image Sizes

This is a WordPress Plugin that improves the default sizes attribute calculation for nested image block in columns.

<?php
/**
* Plugin Name: WPP Column Image Sizes
* Description: This is a WordPress Plugin that improves the default sizes attribute calculation for for nested image block in columns.
* Version: 0.1
* Author: Mukesh Panchal
* License: GPL2
*/
/**
* Filter the sizes attribute for images to improve the default calculation.
*
* @since 1.1.0
*
* @param string $content The block content about to be rendered.
* @param array{ attrs?: array{ align?: string, width?: string } } $parsed_block The parsed block.
* @return string The updated block content.
*/
function auto_sizes_filter_image_tag( string $content, array $parsed_block ): string {
$processor = new WP_HTML_Tag_Processor( $content );
$has_image = $processor->next_tag( array( 'tag_name' => 'img' ) );
// Only update the markup if an image is found.
if ( $has_image ) {
$processor->set_attribute( 'data-needs-sizes-update', true );
if ( isset( $parsed_block['attrs']['data-columns-align'] ) ) {
$processor->set_attribute( 'data-columns-align', $parsed_block['attrs']['data-columns-align'] );
}
if ( isset( $parsed_block['attrs']['data-column-width'] ) ) {
$processor->set_attribute( 'data-column-width', $parsed_block['attrs']['data-column-width'] );
}
$content = $processor->get_updated_html();
}
return $content;
}
add_filter( 'render_block_core/image', 'auto_sizes_filter_image_tag', 10, 2 );
/**
* Filter the sizes attribute for images to improve the default calculation.
*
* @since 1.1.0
*
* @param string $content The block content about to be rendered.
* @return string The updated block content.
*/
function auto_sizes_improve_image_sizes_attributes( string $content ): string {
$processor = new WP_HTML_Tag_Processor( $content );
if ( ! $processor->next_tag( array( 'tag_name' => 'img' ) ) ) {
return $content;
}
$remove_data_attributes = static function () use ( $processor ): void {
$processor->remove_attribute( 'data-needs-sizes-update' );
$processor->remove_attribute( 'data-columns-align' );
$processor->remove_attribute( 'data-column-width' );
};
// Bail early if the responsive images are disabled.
if ( null === $processor->get_attribute( 'sizes' ) ) {
$remove_data_attributes();
return $processor->get_updated_html();
}
// Skips second time parsing if already processed.
if ( null === $processor->get_attribute( 'data-needs-sizes-update' ) ) {
return $content;
}
$column_align = $processor->get_attribute( 'data-columns-align' );
$layout = wp_get_global_settings( array( 'layout' ) );
$sizes = null;
switch ( $column_align ) {
case 'full':
$column_width = $processor->get_attribute( 'data-column-width' );
$column_width = (float) $column_width / 100;
$sizes = sprintf( '(max-width: calc(%1$s * %2$s)) 100vw, calc(%1$s * %2$s)', '100vw', $column_width );
break;
case 'wide':
if ( array_key_exists( 'wideSize', $layout ) ) {
$column_width = $processor->get_attribute( 'data-column-width' );
$column_width = (float) $column_width / 100;
$sizes = sprintf( '(max-width: calc(%1$s * %2$s)) 100vw, calc(%1$s * %2$s)', $layout['wideSize'], $column_width );
}
break;
default:
if ( array_key_exists( 'contentSize', $layout ) ) {
$column_width = $processor->get_attribute( 'data-column-width' );
$column_width = (float) $column_width / 100;
$sizes = sprintf( '(max-width: calc(%1$s * %2$s)) 100vw, calc(%1$s * %2$s)', $layout['contentSize'], $column_width );
}
break;
}
if ( is_string( $sizes ) ) {
$processor->set_attribute( 'sizes', $sizes );
}
$remove_data_attributes();
return $processor->get_updated_html();
}
// Run filter prior to auto sizes "auto_sizes_update_content_img_tag" filter.
add_filter( 'wp_content_img_tag', 'auto_sizes_improve_image_sizes_attributes', 9 );
/**
* Filters the columns block data attribute and supply it to nested image block.
*
* @param array $parsed_block The parsed block.
* @return array The updated parsed block.
*/
function auto_sizes_modify_render_block_data( $parsed_block ) {
if ( ! empty( $parsed_block['blockName'] ) && 'core/columns' === $parsed_block['blockName'] ) {
$columns_align = $parsed_block['attrs']['align'] ?? '';
$column_count = count( $parsed_block['innerBlocks'] );
$column_width = array();
foreach ( $parsed_block['innerBlocks'] as $column_key => $column_inner_block ) {
if ( 'core/column' === $column_inner_block['blockName'] ) {
$column_width[] =
isset( $parsed_block['innerBlocks'][ $column_key ]['attrs']['width'] ) && $parsed_block['innerBlocks'][ $column_key ]['attrs']['width'] ?
(float) $parsed_block['innerBlocks'][ $column_key ]['attrs']['width'] :
'auto';
}
}
$actual_column_width = calculate_column_widths( $column_width );
foreach ( $parsed_block['innerBlocks'] as $column_key => $column_inner_block ) {
foreach ( $parsed_block['innerBlocks'][ $column_key ]['innerBlocks'] as $key => $inner_block ) {
if ( 'core/image' === $inner_block['blockName'] ) {
$parsed_block['innerBlocks'][ $column_key ]['innerBlocks'][ $key ]['attrs']['data-columns-align'] = esc_attr( $columns_align );
$parsed_block['innerBlocks'][ $column_key ]['innerBlocks'][ $key ]['attrs']['data-column-width'] = esc_attr( $actual_column_width[ $key ] );
}
}
}
}
return $parsed_block;
}
add_filter( 'render_block_data', 'auto_sizes_modify_render_block_data' );
function calculate_column_widths( $columns ) {
$total_percentage = 100;
$auto_columns = 0;
$fixed_percentage = 0;
// First, calculate the total fixed width and count the auto columns.
foreach ( $columns as $column ) {
if ( $column === 'auto' ) {
$auto_columns++;
} else {
$fixed_percentage += $column;
}
}
// Calculate the width for auto columns.
if ( $auto_columns > 0 ) {
$auto_width = ( $total_percentage - $fixed_percentage ) / $auto_columns;
} else {
$auto_width = 0; // No auto columns, no need to calculate.
}
// Generate the final widths array.
$final_widths = [];
foreach ( $columns as $column ) {
if ( $column === 'auto' ) {
$final_widths[] = $auto_width . '%';
} else {
$final_widths[] = $column . '%';
}
}
return $final_widths;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment