PluginProbe
Gutenberg / 24.1.0
Gutenberg v24.1.0
24.1.0 24.0.0 23.9.1 23.9.0 23.8.0 23.7.2 23.7.1 23.7.0 23.6.1 23.6.2 23.6.0 23.5.3 23.5.2 23.5.1 23.5.0 23.4.0 23.3.2 23.3.1 23.3.0 23.2.0 23.2.1 23.2.2 23.1.1 23.1.0 23.0.1 All 404 releases
← All changes | build/scripts/block-library/gallery.php +179 -65 24.0.0 → 24.1.0 View file →
@@ -87,8 +87,85 @@
87 87 return '0' === $gap_column ? '0px' : $gap_column;
88 88 }
89 89
90 90 /**
91 + * Returns whether a value can be used as a Gallery aspect ratio.
92 + *
93 + * Aspect ratios are interpolated into a generated stylesheet instead of being
94 + * set as an inline style, so only the numeric forms produced by aspect ratio
95 + * presets (and `auto`) are accepted. A value from saved content that isn't one
96 + * of those is ignored rather than emitted, so it can't close the rule early and
97 + * inject declarations of its own. The editor applies the same restriction in
98 + * `isValidGalleryAspectRatio()`.
99 + *
100 + * @since 7.1.0
101 + *
102 + * @param mixed $value Value to check.
103 + * @return bool Whether the value is a valid aspect ratio.
104 + */
105 +function gutenberg_block_core_gallery_is_valid_aspect_ratio( $value ) {
106 + return is_string( $value ) && 1 === preg_match( '#^(auto|\d+(\.\d+)?(\s*/\s*\d+(\.\d+)?)?)$#', trim( $value ) );
107 +}
108 +
109 +/**
110 + * Returns Gallery-specific responsive aspect ratio rules for a viewport.
111 + *
112 + * Unlike the column and crop rules, these are not scoped to the Flex layout:
113 + * the aspect ratio applies to the images in every Gallery layout. They also
114 + * cover dynamic galleries, whose images are rendered by the Gallery rather than
115 + * carrying their own block attributes.
116 + *
117 + * @since 7.1.0
118 + *
119 + * @param string $selector Gallery block selector.
120 + * @param mixed $viewport_style Viewport style data.
121 + * @param string $media_query Viewport media query.
122 + * @return array[] Gallery responsive aspect ratio rules.
123 + */
124 +function gutenberg_block_core_gallery_get_responsive_aspect_ratio_style_rules( $selector, $viewport_style, $media_query ) {
125 + if ( ! is_array( $viewport_style ) || ! is_string( $media_query ) ) {
126 + return array();
127 + }
128 +
129 + $aspect_ratio = $viewport_style['aspectRatio'] ?? null;
130 + if ( ! gutenberg_block_core_gallery_is_valid_aspect_ratio( $aspect_ratio ) ) {
131 + return array();
132 + }
133 +
134 + $aspect_ratio = trim( $aspect_ratio );
135 +
136 + /*
137 + * The base aspect ratio is an inline style on each image, so these
138 + * declarations have to be important to win for the viewport.
139 + *
140 + * Original cancels the base ratio, which means rolling the declaration out
141 + * of the cascade rather than giving it a value. `auto` - and `initial`,
142 + * `unset` and `revert`, which all compute to it - would override the
143 + * `width`/`height` presentational hint that gives a lazy-loaded image its
144 + * placeholder ratio, collapsing the image to zero height until it loads:
145 + * the Featured Image bug fixed in #80386. `revert-layer` drops the
146 + * declaration instead, so the image falls back to that hint while loading,
147 + * to its natural ratio once loaded, and to any ratio a theme set in a lower
148 + * cascade layer. `object-fit` is left as the base set it, so a cropped
149 + * Gallery still crops.
150 + */
151 + $declarations = 'auto' === $aspect_ratio
152 + ? array( 'aspect-ratio' => 'revert-layer !important' )
153 + : array(
154 + 'aspect-ratio' => "{$aspect_ratio} !important",
155 + 'object-fit' => 'cover !important',
156 + );
157 +
158 + return array(
159 + array(
160 + 'selector' => "{$selector}.wp-block-gallery.has-nested-images figure.wp-block-image:not(#individual-image) img",
161 + 'declarations' => $declarations,
162 + 'rules_group' => $media_query,
163 + ),
164 + );
165 +}
166 +
167 +/**
91 168 * Returns Gallery-specific responsive Flex rules for a viewport.
92 169 *
93 170 * @since 7.1.0
94 171 *
@@ -473,98 +550,135 @@
473 550
474 551 $processed_content = new WP_HTML_Tag_Processor( $content );
475 552 $processed_content->next_tag();
476 553
477 - if ( $is_flex_layout ) {
478 - // Add a style tag for the --wp--style--unstable-gallery-gap var. The
479 - // Gallery's custom Flex layout recalculates Image block widths based on
480 - // the current gap so it can maintain the selected number of columns.
481 - $style_attr = is_array( $attributes['style'] ?? null )
482 - ? $attributes['style']
483 - : array();
554 + $style_attr = is_array( $attributes['style'] ?? null )
555 + ? $attributes['style']
556 + : array();
557 + if (
558 + defined( 'IS_GUTENBERG_PLUGIN' ) &&
559 + IS_GUTENBERG_PLUGIN &&
560 + function_exists( 'gutenberg_resolve_style_state_aliases' )
561 + ) {
562 + $style_attr = gutenberg_resolve_style_state_aliases( $style_attr, 'core/gallery' );
563 + }
564 +
565 + $global_settings = gutenberg_get_global_settings();
566 + $viewport_settings = $global_settings['viewport'] ?? null;
567 + $responsive_media_queries = array();
568 + foreach ( array( 'WP_Theme_JSON_Gutenberg', 'WP_Theme_JSON' ) as $theme_json_class_name ) {
569 + if ( method_exists( $theme_json_class_name, 'get_viewport_media_queries' ) ) {
570 + $responsive_media_queries = $theme_json_class_name::get_viewport_media_queries( $viewport_settings );
571 + break;
572 + }
573 + }
574 +
575 + // Columns and cropping are Flex-only, but the aspect ratio applies in every
576 + // layout, so a Gallery with a viewport aspect ratio needs the per-instance
577 + // stylesheet (and the class scoping it) even when it isn't a Flex Gallery.
578 + $has_viewport_aspect_ratio = false;
579 + foreach ( $responsive_media_queries as $breakpoint => $media_query ) {
580 + $viewport_style = $style_attr[ $breakpoint ] ?? null;
484 581 if (
485 - defined( 'IS_GUTENBERG_PLUGIN' ) &&
486 - IS_GUTENBERG_PLUGIN &&
487 - function_exists( 'gutenberg_resolve_style_state_aliases' )
582 + is_array( $viewport_style ) &&
583 + gutenberg_block_core_gallery_is_valid_aspect_ratio( $viewport_style['aspectRatio'] ?? null )
488 584 ) {
489 - $style_attr = gutenberg_resolve_style_state_aliases( $style_attr, 'core/gallery' );
585 + $has_viewport_aspect_ratio = true;
586 + break;
490 587 }
588 + }
491 589
590 + /*
591 + * Only generate the gap styles — and, when nothing else needs it, the unique
592 + * classname that exists solely to scope them — if the theme has not opted out
593 + * of layout styles. The responsive aspect ratio rules are not layout styles,
594 + * so they keep rendering either way.
595 + */
596 + $should_generate_gap_styles = $is_flex_layout && ! current_theme_supports( 'disable-layout-styles' );
597 +
598 + if ( $should_generate_gap_styles || $has_viewport_aspect_ratio ) {
492 599 $unique_gallery_classname = wp_unique_id( 'wp-block-gallery-' );
493 600 $processed_content->add_class( $unique_gallery_classname );
601 + $gallery_styles = array();
494 602
495 - // --gallery-block--gutter-size is deprecated. --wp--style--gallery-gap-default should be used by themes that want to set a default
496 - // gap on the gallery.
497 - $fallback_gap = 'var( --wp--style--gallery-gap-default, var( --gallery-block--gutter-size, var( --wp--style--block-gap, 0.5em ) ) )';
603 + if ( $should_generate_gap_styles ) {
604 + // Add a style tag for the --wp--style--unstable-gallery-gap var. The
605 + // Gallery's custom Flex layout recalculates Image block widths based on
606 + // the current gap so it can maintain the selected number of columns.
498 607
499 - if ( null === $global_styles ) {
500 - $global_styles = function_exists( 'gutenberg_get_global_styles' ) ? gutenberg_get_global_styles() : array();
501 - }
608 + // --gallery-block--gutter-size is deprecated. --wp--style--gallery-gap-default should be used by themes that want to set a default
609 + // gap on the gallery.
610 + $fallback_gap = 'var( --wp--style--gallery-gap-default, var( --gallery-block--gutter-size, var( --wp--style--block-gap, 0.5em ) ) )';
502 611
503 - $global_gallery_styles = $global_styles['blocks']['core/gallery'] ?? array();
504 - $global_gallery_gap = $global_gallery_styles['spacing']['blockGap'] ?? $fallback_gap;
505 - $has_block_gap = is_array( $style_attr['spacing'] ?? null ) && array_key_exists( 'blockGap', $style_attr['spacing'] );
506 - // Prefer the block's own gap value, then Gallery global styles. Missing
507 - // values fall back to the Gallery blockGap default.
508 - $block_gap = $has_block_gap
509 - ? $style_attr['spacing']['blockGap']
510 - : $global_gallery_gap;
511 - $gap_column = gutenberg_block_core_gallery_get_column_gap_value( $block_gap, $fallback_gap );
612 + if ( null === $global_styles ) {
613 + $global_styles = function_exists( 'gutenberg_get_global_styles' ) ? gutenberg_get_global_styles() : array();
614 + }
512 615
513 - // Set the CSS variable to the column value for Gallery's flex width calculations.
514 - $gallery_styles = array(
515 - array(
616 + $global_gallery_styles = $global_styles['blocks']['core/gallery'] ?? array();
617 + $global_gallery_gap = $global_gallery_styles['spacing']['blockGap'] ?? $fallback_gap;
618 + $has_block_gap = is_array( $style_attr['spacing'] ?? null ) && array_key_exists( 'blockGap', $style_attr['spacing'] );
619 + // Prefer the block's own gap value, then Gallery global styles. Missing
620 + // values fall back to the Gallery blockGap default.
621 + $block_gap = $has_block_gap
622 + ? $style_attr['spacing']['blockGap']
623 + : $global_gallery_gap;
624 + $gap_column = gutenberg_block_core_gallery_get_column_gap_value( $block_gap, $fallback_gap );
625 +
626 + // Set the CSS variable to the column value for Gallery's flex width calculations.
627 + $gallery_styles[] = array(
516 628 'selector' => ".wp-block-gallery.{$unique_gallery_classname}",
517 629 'declarations' => array(
518 630 '--wp--style--unstable-gallery-gap' => $gap_column,
519 631 ),
520 - ),
521 - );
522 -
523 - $global_settings = gutenberg_get_global_settings();
524 - $viewport_settings = $global_settings['viewport'] ?? null;
525 - $responsive_media_queries = array();
526 - foreach ( array( 'WP_Theme_JSON_Gutenberg', 'WP_Theme_JSON' ) as $theme_json_class_name ) {
527 - if ( method_exists( $theme_json_class_name, 'get_viewport_media_queries' ) ) {
528 - $responsive_media_queries = $theme_json_class_name::get_viewport_media_queries( $viewport_settings );
529 - break;
530 - }
632 + );
531 633 }
532 634
533 635 foreach ( $responsive_media_queries as $breakpoint => $media_query ) {
534 - $viewport_style = $style_attr[ $breakpoint ] ?? null;
535 - $has_viewport_block_gap = is_array( $viewport_style ) &&
536 - is_array( $viewport_style['spacing'] ?? null ) &&
537 - array_key_exists( 'blockGap', $viewport_style['spacing'] );
538 - $has_global_viewport_block_gap = is_array( $global_gallery_styles[ $breakpoint ]['spacing'] ?? null ) &&
539 - array_key_exists( 'blockGap', $global_gallery_styles[ $breakpoint ]['spacing'] );
636 + $viewport_style = $style_attr[ $breakpoint ] ?? null;
540 637
541 - // Viewport-specific block values win. Gallery global viewport values
542 - // only apply when the block has no base gap, so they do not override an instance value.
543 - if ( $has_viewport_block_gap ) {
544 - $viewport_gap = $viewport_style['spacing']['blockGap'];
545 - } elseif ( ! $has_block_gap && $has_global_viewport_block_gap ) {
546 - $viewport_gap = $global_gallery_styles[ $breakpoint ]['spacing']['blockGap'];
547 - } else {
548 - $viewport_gap = null;
549 - }
638 + if ( $should_generate_gap_styles ) {
639 + $has_viewport_block_gap = is_array( $viewport_style ) &&
640 + is_array( $viewport_style['spacing'] ?? null ) &&
641 + array_key_exists( 'blockGap', $viewport_style['spacing'] );
642 + $has_global_viewport_block_gap = is_array( $global_gallery_styles[ $breakpoint ]['spacing'] ?? null ) &&
643 + array_key_exists( 'blockGap', $global_gallery_styles[ $breakpoint ]['spacing'] );
550 644
551 - if ( null !== $viewport_gap ) {
552 - $gallery_styles[] = array(
553 - 'selector' => ".wp-block-gallery.{$unique_gallery_classname}",
554 - 'declarations' => array(
555 - '--wp--style--unstable-gallery-gap' => gutenberg_block_core_gallery_get_column_gap_value(
556 - $viewport_gap,
557 - $fallback_gap
645 + // Viewport-specific block values win. Gallery global viewport values
646 + // only apply when the block has no base gap, so they do not override an instance value.
647 + if ( $has_viewport_block_gap ) {
648 + $viewport_gap = $viewport_style['spacing']['blockGap'];
649 + } elseif ( ! $has_block_gap && $has_global_viewport_block_gap ) {
650 + $viewport_gap = $global_gallery_styles[ $breakpoint ]['spacing']['blockGap'];
651 + } else {
652 + $viewport_gap = null;
653 + }
654 +
655 + if ( null !== $viewport_gap ) {
656 + $gallery_styles[] = array(
657 + 'selector' => ".wp-block-gallery.{$unique_gallery_classname}",
658 + 'declarations' => array(
659 + '--wp--style--unstable-gallery-gap' => gutenberg_block_core_gallery_get_column_gap_value(
660 + $viewport_gap,
661 + $fallback_gap
662 + ),
558 663 ),
559 - ),
560 - 'rules_group' => $media_query,
664 + 'rules_group' => $media_query,
665 + );
666 + }
667 +
668 + $gallery_styles = array_merge(
669 + $gallery_styles,
670 + gutenberg_block_core_gallery_get_responsive_flex_style_rules(
671 + ".{$unique_gallery_classname}",
672 + $viewport_style,
673 + $media_query
674 + )
561 675 );
562 676 }
563 677
564 678 $gallery_styles = array_merge(
565 679 $gallery_styles,
566 - gutenberg_block_core_gallery_get_responsive_flex_style_rules(
680 + gutenberg_block_core_gallery_get_responsive_aspect_ratio_style_rules(
567 681 ".{$unique_gallery_classname}",
568 682 $viewport_style,
569 683 $media_query
570 684 )