Block Supports: Add text indent to typography supports

This commit adds CSS text-indent support for paragraph blocks with traditional typography conventions - subsequent paragraphs get first-line indented in LTR languages, with an option to indent all paragraphs (default for RTL languages).

Text indentation is a fundamental typography feature. Traditional print typography conventions dictate that only subsequent paragraphs (not the first) should have their first line indented in LTR languages, while RTL languages typically indent all paragraphs. This feature enables proper typographic styling that matches publishing standards.

Props aaronrobertshaw, ramonopoly, andrewserong, wildworks, matveb, skorasaurus, greenshady, kjellr.

Fixes #64326.


Built from https://develop.svn.wordpress.org/trunk@61632


git-svn-id: http://core.svn.wordpress.org/trunk@60943 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
ramonopoly
2026-02-13 01:52:41 +00:00
parent 1b208a0253
commit 79f00e3f55
4 changed files with 72 additions and 1 deletions
+10
View File
@@ -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(
+54
View File
@@ -247,6 +247,7 @@ class WP_Theme_JSON {
* @since 6.6.0 Added `background-[image|position|repeat|size]` properties.
* @since 6.7.0 Added `background-attachment` property.
* @since 7.0.0 Added `dimensions.width` and `dimensions.height`.
* Added `text-indent` property.
* @var array
*/
const PROPERTIES_METADATA = array(
@@ -309,6 +310,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' ),
'height' => array( 'dimensions', 'height' ),
@@ -409,6 +411,7 @@ class WP_Theme_JSON {
* @since 6.9.0 Added support for `border.radiusSizes`.
* @since 7.0.0 Added type markers to the schema for boolean values.
* Added support for `dimensions.width` and `dimensions.height`.
* Added support for `typography.textIndent`.
* @var array
*/
const VALID_SETTINGS = array(
@@ -494,6 +497,7 @@ class WP_Theme_JSON {
'textAlign' => null,
'textColumns' => null,
'textDecoration' => null,
'textIndent' => null,
'textTransform' => null,
'writingMode' => null,
),
@@ -601,6 +605,7 @@ class WP_Theme_JSON {
'textAlign' => null,
'textColumns' => null,
'textDecoration' => null,
'textIndent' => null,
'textTransform' => null,
'writingMode' => null,
),
@@ -2749,6 +2754,48 @@ class WP_Theme_JSON {
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.
*
@@ -2910,6 +2957,10 @@ class WP_Theme_JSON {
$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();
@@ -2922,6 +2973,9 @@ class WP_Theme_JSON {
// 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 ) {
/*
@@ -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 {
@@ -315,6 +316,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',
+1 -1
View File
@@ -16,7 +16,7 @@
*
* @global string $wp_version
*/
$wp_version = '7.0-alpha-61631';
$wp_version = '7.0-alpha-61632';
/**
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.