From 6beebe3e73f2bf79595b804a9c101482608cb76b Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Fri, 30 Jan 2026 17:34:24 +1000 Subject: [PATCH] Block Supports: Add text indent support --- src/wp-includes/block-supports/typography.php | 10 ++++ src/wp-includes/class-wp-theme-json.php | 54 +++++++++++++++++++ .../style-engine/class-wp-style-engine.php | 7 +++ 3 files changed, 71 insertions(+) diff --git a/src/wp-includes/block-supports/typography.php b/src/wp-includes/block-supports/typography.php index b79738f757e1e..4f8e32571af73 100644 --- a/src/wp-includes/block-supports/typography.php +++ b/src/wp-includes/block-supports/typography.php @@ -11,6 +11,7 @@ * * @since 5.6.0 * @since 6.3.0 Added support for text-columns. + * @since 7.0.0 Added support for text-indent. * @access private * * @param WP_Block_Type $block_type Block Type. @@ -35,6 +36,7 @@ function wp_register_typography_support( $block_type ) { $has_text_columns_support = $typography_supports['textColumns'] ?? false; $has_text_decoration_support = $typography_supports['__experimentalTextDecoration'] ?? false; $has_text_transform_support = $typography_supports['__experimentalTextTransform'] ?? false; + $has_text_indent_support = $typography_supports['textIndent'] ?? false; $has_writing_mode_support = $typography_supports['__experimentalWritingMode'] ?? false; $has_typography_support = $has_font_family_support @@ -47,6 +49,7 @@ function wp_register_typography_support( $block_type ) { || $has_text_columns_support || $has_text_decoration_support || $has_text_transform_support + || $has_text_indent_support || $has_writing_mode_support; if ( ! $block_type->attributes ) { @@ -80,6 +83,7 @@ function wp_register_typography_support( $block_type ) { * @since 5.6.0 * @since 6.1.0 Used the style engine to generate CSS and classnames. * @since 6.3.0 Added support for text-columns. + * @since 7.0.0 Added support for text-indent. * @access private * * @param WP_Block_Type $block_type Block type. @@ -110,6 +114,7 @@ function wp_apply_typography_support( $block_type, $block_attributes ) { $has_text_columns_support = $typography_supports['textColumns'] ?? false; $has_text_decoration_support = $typography_supports['__experimentalTextDecoration'] ?? false; $has_text_transform_support = $typography_supports['__experimentalTextTransform'] ?? false; + $has_text_indent_support = $typography_supports['textIndent'] ?? false; $has_writing_mode_support = $typography_supports['__experimentalWritingMode'] ?? false; // Whether to skip individual block support features. @@ -123,6 +128,7 @@ function wp_apply_typography_support( $block_type, $block_attributes ) { $should_skip_text_decoration = wp_should_skip_block_supports_serialization( $block_type, 'typography', 'textDecoration' ); $should_skip_text_transform = wp_should_skip_block_supports_serialization( $block_type, 'typography', 'textTransform' ); $should_skip_letter_spacing = wp_should_skip_block_supports_serialization( $block_type, 'typography', 'letterSpacing' ); + $should_skip_text_indent = wp_should_skip_block_supports_serialization( $block_type, 'typography', 'textIndent' ); $should_skip_writing_mode = wp_should_skip_block_supports_serialization( $block_type, 'typography', 'writingMode' ); $typography_block_styles = array(); @@ -222,6 +228,10 @@ function wp_apply_typography_support( $block_type, $block_attributes ) { $typography_block_styles['writingMode'] = $block_attributes['style']['typography']['writingMode'] ?? null; } + if ( $has_text_indent_support && ! $should_skip_text_indent && isset( $block_attributes['style']['typography']['textIndent'] ) ) { + $typography_block_styles['textIndent'] = $block_attributes['style']['typography']['textIndent'] ?? null; + } + $attributes = array(); $classnames = array(); $styles = wp_style_engine_get_styles( diff --git a/src/wp-includes/class-wp-theme-json.php b/src/wp-includes/class-wp-theme-json.php index 61d2c2f71b88a..03b857d3c999e 100644 --- a/src/wp-includes/class-wp-theme-json.php +++ b/src/wp-includes/class-wp-theme-json.php @@ -237,6 +237,7 @@ class WP_Theme_JSON { * @since 6.5.0 Added `aspect-ratio` property. * @since 6.6.0 Added `background-[image|position|repeat|size]` properties. * @since 6.7.0 Added `background-attachment` property. + * @since 7.0.0 Added `text-indent` property. * @var array */ const PROPERTIES_METADATA = array( @@ -299,6 +300,7 @@ class WP_Theme_JSON { '--wp--style--root--padding-left' => array( 'spacing', 'padding', 'left' ), 'text-decoration' => array( 'typography', 'textDecoration' ), 'text-transform' => array( 'typography', 'textTransform' ), + 'text-indent' => array( 'typography', 'textIndent' ), 'filter' => array( 'filter', 'duotone' ), 'box-shadow' => array( 'shadow' ), 'writing-mode' => array( 'typography', 'writingMode' ), @@ -395,6 +397,7 @@ class WP_Theme_JSON { * @since 6.6.0 Added support for 'dimensions.aspectRatios', 'dimensions.defaultAspectRatios', * 'typography.defaultFontSizes', and 'spacing.defaultSpacingSizes'. * @since 6.9.0 Added support for `border.radiusSizes`. + * @since 7.0.0 Added support for `typography.textIndent`. * @var array */ const VALID_SETTINGS = array( @@ -477,6 +480,7 @@ class WP_Theme_JSON { 'textAlign' => null, 'textColumns' => null, 'textDecoration' => null, + 'textIndent' => null, 'textTransform' => null, 'writingMode' => null, ), @@ -581,6 +585,7 @@ class WP_Theme_JSON { 'textAlign' => null, 'textColumns' => null, 'textDecoration' => null, + 'textIndent' => null, 'textTransform' => null, 'writingMode' => null, ), @@ -2654,6 +2659,48 @@ private static function update_separator_declarations( $declarations ) { return $declarations; } + /** + * Updates the text indent selector for paragraph blocks based on the textIndent setting. + * + * The textIndent setting can be 'subsequent' (default), 'all', or false. + * When set to 'all', the selector should be '.wp-block-paragraph' instead of + * '.wp-block-paragraph + .wp-block-paragraph' to apply indent to all paragraphs. + * + * @since 7.0.0 + * + * @param array $feature_declarations The feature declarations keyed by selector. + * @param array $settings The theme.json settings. + * @param string $block_name The block name being processed. + * @return array The updated feature declarations. + */ + private static function update_paragraph_text_indent_selector( $feature_declarations, $settings, $block_name ) { + if ( 'core/paragraph' !== $block_name ) { + return $feature_declarations; + } + + // Check block-level settings first, then fall back to global settings. + $block_settings = $settings['blocks']['core/paragraph'] ?? null; + $text_indent_setting = $block_settings['typography']['textIndent'] + ?? $settings['typography']['textIndent'] + ?? 'subsequent'; + + if ( 'all' !== $text_indent_setting ) { + return $feature_declarations; + } + + // Look for the text indent selector and replace it. + $old_selector = '.wp-block-paragraph + .wp-block-paragraph'; + $new_selector = '.wp-block-paragraph'; + + if ( isset( $feature_declarations[ $old_selector ] ) ) { + $declarations = $feature_declarations[ $old_selector ]; + unset( $feature_declarations[ $old_selector ] ); + $feature_declarations[ $new_selector ] = $declarations; + } + + return $feature_declarations; + } + /** * An internal method to get the block nodes from a theme.json file. * @@ -2798,6 +2845,10 @@ public function get_styles_for_block( $block_metadata ) { $feature_declarations = static::get_feature_declarations_for_node( $block_metadata, $node ); $is_root_selector = static::ROOT_BLOCK_SELECTOR === $selector; + // Update text indent selector for paragraph blocks based on the textIndent setting. + $block_name = $block_metadata['name'] ?? null; + $feature_declarations = static::update_paragraph_text_indent_selector( $feature_declarations, $settings, $block_name ); + // If there are style variations, generate the declarations for them, including any feature selectors the block may have. $style_variation_declarations = array(); $style_variation_custom_css = array(); @@ -2810,6 +2861,9 @@ public function get_styles_for_block( $block_metadata ) { // Generate any feature/subfeature style declarations for the current style variation. $variation_declarations = static::get_feature_declarations_for_node( $block_metadata, $style_variation_node ); + // Update text indent selector for paragraph blocks based on the textIndent setting. + $variation_declarations = static::update_paragraph_text_indent_selector( $variation_declarations, $settings, $block_name ); + // Combine selectors with style variation's selector and add to overall style variation declarations. foreach ( $variation_declarations as $current_selector => $new_declarations ) { /* diff --git a/src/wp-includes/style-engine/class-wp-style-engine.php b/src/wp-includes/style-engine/class-wp-style-engine.php index f47c349aecbe3..beab8e7818441 100644 --- a/src/wp-includes/style-engine/class-wp-style-engine.php +++ b/src/wp-includes/style-engine/class-wp-style-engine.php @@ -26,6 +26,7 @@ * @since 6.5.0 Added support for background.backgroundPosition, * background.backgroundRepeat and dimensions.aspectRatio. * @since 6.7.0 Added support for typography.writingMode. + * @since 7.0.0 Added support for typography.textIndent. */ #[AllowDynamicProperties] final class WP_Style_Engine { @@ -297,6 +298,12 @@ final class WP_Style_Engine { ), 'path' => array( 'typography', 'textDecoration' ), ), + 'textIndent' => array( + 'property_keys' => array( + 'default' => 'text-indent', + ), + 'path' => array( 'typography', 'textIndent' ), + ), 'textTransform' => array( 'property_keys' => array( 'default' => 'text-transform',