| [ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Typography block support flag. 4 * 5 * @package WordPress 6 * @since 5.6.0 7 */ 8 9 /** 10 * Registers the style and typography block attributes for block types that support it. 11 * 12 * @since 5.6.0 13 * @since 6.3.0 Added support for text-columns. 14 * @access private 15 * 16 * @param WP_Block_Type $block_type Block Type. 17 */ 18 function wp_register_typography_support( $block_type ) { 19 if ( ! ( $block_type instanceof WP_Block_Type ) ) { 20 return; 21 } 22 23 $typography_supports = $block_type->supports['typography'] ?? false; 24 if ( ! $typography_supports ) { 25 return; 26 } 27 28 $has_font_family_support = $typography_supports['__experimentalFontFamily'] ?? false; 29 $has_font_size_support = $typography_supports['fontSize'] ?? false; 30 $has_font_style_support = $typography_supports['__experimentalFontStyle'] ?? false; 31 $has_font_weight_support = $typography_supports['__experimentalFontWeight'] ?? false; 32 $has_letter_spacing_support = $typography_supports['__experimentalLetterSpacing'] ?? false; 33 $has_line_height_support = $typography_supports['lineHeight'] ?? false; 34 $has_text_align_support = $typography_supports['textAlign'] ?? false; 35 $has_text_columns_support = $typography_supports['textColumns'] ?? false; 36 $has_text_decoration_support = $typography_supports['__experimentalTextDecoration'] ?? false; 37 $has_text_transform_support = $typography_supports['__experimentalTextTransform'] ?? false; 38 $has_writing_mode_support = $typography_supports['__experimentalWritingMode'] ?? false; 39 40 $has_typography_support = $has_font_family_support 41 || $has_font_size_support 42 || $has_font_style_support 43 || $has_font_weight_support 44 || $has_letter_spacing_support 45 || $has_line_height_support 46 || $has_text_align_support 47 || $has_text_columns_support 48 || $has_text_decoration_support 49 || $has_text_transform_support 50 || $has_writing_mode_support; 51 52 if ( ! $block_type->attributes ) { 53 $block_type->attributes = array(); 54 } 55 56 if ( $has_typography_support && ! array_key_exists( 'style', $block_type->attributes ) ) { 57 $block_type->attributes['style'] = array( 58 'type' => 'object', 59 ); 60 } 61 62 if ( $has_font_size_support && ! array_key_exists( 'fontSize', $block_type->attributes ) ) { 63 $block_type->attributes['fontSize'] = array( 64 'type' => 'string', 65 ); 66 } 67 68 if ( $has_font_family_support && ! array_key_exists( 'fontFamily', $block_type->attributes ) ) { 69 $block_type->attributes['fontFamily'] = array( 70 'type' => 'string', 71 ); 72 } 73 } 74 75 /** 76 * Adds CSS classes and inline styles for typography features such as font sizes 77 * to the incoming attributes array. This will be applied to the block markup in 78 * the front-end. 79 * 80 * @since 5.6.0 81 * @since 6.1.0 Used the style engine to generate CSS and classnames. 82 * @since 6.3.0 Added support for text-columns. 83 * @access private 84 * 85 * @param WP_Block_Type $block_type Block type. 86 * @param array $block_attributes Block attributes. 87 * @return array Typography CSS classes and inline styles. 88 */ 89 function wp_apply_typography_support( $block_type, $block_attributes ) { 90 if ( ! ( $block_type instanceof WP_Block_Type ) ) { 91 return array(); 92 } 93 94 $typography_supports = $block_type->supports['typography'] ?? false; 95 if ( ! $typography_supports ) { 96 return array(); 97 } 98 99 if ( wp_should_skip_block_supports_serialization( $block_type, 'typography' ) ) { 100 return array(); 101 } 102 103 $has_font_family_support = $typography_supports['__experimentalFontFamily'] ?? false; 104 $has_font_size_support = $typography_supports['fontSize'] ?? false; 105 $has_font_style_support = $typography_supports['__experimentalFontStyle'] ?? false; 106 $has_font_weight_support = $typography_supports['__experimentalFontWeight'] ?? false; 107 $has_letter_spacing_support = $typography_supports['__experimentalLetterSpacing'] ?? false; 108 $has_line_height_support = $typography_supports['lineHeight'] ?? false; 109 $has_text_align_support = $typography_supports['textAlign'] ?? false; 110 $has_text_columns_support = $typography_supports['textColumns'] ?? false; 111 $has_text_decoration_support = $typography_supports['__experimentalTextDecoration'] ?? false; 112 $has_text_transform_support = $typography_supports['__experimentalTextTransform'] ?? false; 113 $has_writing_mode_support = $typography_supports['__experimentalWritingMode'] ?? false; 114 115 // Whether to skip individual block support features. 116 $should_skip_font_size = wp_should_skip_block_supports_serialization( $block_type, 'typography', 'fontSize' ); 117 $should_skip_font_family = wp_should_skip_block_supports_serialization( $block_type, 'typography', 'fontFamily' ); 118 $should_skip_font_style = wp_should_skip_block_supports_serialization( $block_type, 'typography', 'fontStyle' ); 119 $should_skip_font_weight = wp_should_skip_block_supports_serialization( $block_type, 'typography', 'fontWeight' ); 120 $should_skip_line_height = wp_should_skip_block_supports_serialization( $block_type, 'typography', 'lineHeight' ); 121 $should_skip_text_align = wp_should_skip_block_supports_serialization( $block_type, 'typography', 'textAlign' ); 122 $should_skip_text_columns = wp_should_skip_block_supports_serialization( $block_type, 'typography', 'textColumns' ); 123 $should_skip_text_decoration = wp_should_skip_block_supports_serialization( $block_type, 'typography', 'textDecoration' ); 124 $should_skip_text_transform = wp_should_skip_block_supports_serialization( $block_type, 'typography', 'textTransform' ); 125 $should_skip_letter_spacing = wp_should_skip_block_supports_serialization( $block_type, 'typography', 'letterSpacing' ); 126 $should_skip_writing_mode = wp_should_skip_block_supports_serialization( $block_type, 'typography', 'writingMode' ); 127 128 $typography_block_styles = array(); 129 if ( $has_font_size_support && ! $should_skip_font_size ) { 130 $preset_font_size = array_key_exists( 'fontSize', $block_attributes ) 131 ? "var:preset|font-size|{$block_attributes['fontSize']}" 132 : null; 133 $custom_font_size = $block_attributes['style']['typography']['fontSize'] ?? null; 134 $typography_block_styles['fontSize'] = $preset_font_size ? $preset_font_size : wp_get_typography_font_size_value( 135 array( 136 'size' => $custom_font_size, 137 ) 138 ); 139 } 140 141 if ( $has_font_family_support && ! $should_skip_font_family ) { 142 $preset_font_family = array_key_exists( 'fontFamily', $block_attributes ) 143 ? "var:preset|font-family|{$block_attributes['fontFamily']}" 144 : null; 145 $custom_font_family = isset( $block_attributes['style']['typography']['fontFamily'] ) 146 ? wp_typography_get_preset_inline_style_value( $block_attributes['style']['typography']['fontFamily'], 'font-family' ) 147 : null; 148 $typography_block_styles['fontFamily'] = $preset_font_family ? $preset_font_family : $custom_font_family; 149 } 150 151 if ( 152 $has_font_style_support && 153 ! $should_skip_font_style && 154 isset( $block_attributes['style']['typography']['fontStyle'] ) 155 ) { 156 $typography_block_styles['fontStyle'] = wp_typography_get_preset_inline_style_value( 157 $block_attributes['style']['typography']['fontStyle'], 158 'font-style' 159 ); 160 } 161 162 if ( 163 $has_font_weight_support && 164 ! $should_skip_font_weight && 165 isset( $block_attributes['style']['typography']['fontWeight'] ) 166 ) { 167 $typography_block_styles['fontWeight'] = wp_typography_get_preset_inline_style_value( 168 $block_attributes['style']['typography']['fontWeight'], 169 'font-weight' 170 ); 171 } 172 173 if ( $has_line_height_support && ! $should_skip_line_height ) { 174 $typography_block_styles['lineHeight'] = $block_attributes['style']['typography']['lineHeight'] ?? null; 175 } 176 177 if ( $has_text_align_support && ! $should_skip_text_align ) { 178 $typography_block_styles['textAlign'] = $block_attributes['style']['typography']['textAlign'] ?? null; 179 } 180 181 if ( $has_text_columns_support && ! $should_skip_text_columns && isset( $block_attributes['style']['typography']['textColumns'] ) ) { 182 $typography_block_styles['textColumns'] = $block_attributes['style']['typography']['textColumns'] ?? null; 183 } 184 185 if ( 186 $has_text_decoration_support && 187 ! $should_skip_text_decoration && 188 isset( $block_attributes['style']['typography']['textDecoration'] ) 189 ) { 190 $typography_block_styles['textDecoration'] = wp_typography_get_preset_inline_style_value( 191 $block_attributes['style']['typography']['textDecoration'], 192 'text-decoration' 193 ); 194 } 195 196 if ( 197 $has_text_transform_support && 198 ! $should_skip_text_transform && 199 isset( $block_attributes['style']['typography']['textTransform'] ) 200 ) { 201 $typography_block_styles['textTransform'] = wp_typography_get_preset_inline_style_value( 202 $block_attributes['style']['typography']['textTransform'], 203 'text-transform' 204 ); 205 } 206 207 if ( 208 $has_letter_spacing_support && 209 ! $should_skip_letter_spacing && 210 isset( $block_attributes['style']['typography']['letterSpacing'] ) 211 ) { 212 $typography_block_styles['letterSpacing'] = wp_typography_get_preset_inline_style_value( 213 $block_attributes['style']['typography']['letterSpacing'], 214 'letter-spacing' 215 ); 216 } 217 218 if ( $has_writing_mode_support && 219 ! $should_skip_writing_mode && 220 isset( $block_attributes['style']['typography']['writingMode'] ) 221 ) { 222 $typography_block_styles['writingMode'] = $block_attributes['style']['typography']['writingMode'] ?? null; 223 } 224 225 $attributes = array(); 226 $classnames = array(); 227 $styles = wp_style_engine_get_styles( 228 array( 'typography' => $typography_block_styles ), 229 array( 'convert_vars_to_classnames' => true ) 230 ); 231 232 if ( ! empty( $styles['classnames'] ) ) { 233 $classnames[] = $styles['classnames']; 234 } 235 236 if ( $has_text_align_support && ! $should_skip_text_align && isset( $block_attributes['style']['typography']['textAlign'] ) ) { 237 $classnames[] = 'has-text-align-' . $block_attributes['style']['typography']['textAlign']; 238 } 239 240 if ( ! empty( $classnames ) ) { 241 $attributes['class'] = implode( ' ', $classnames ); 242 } 243 244 if ( ! empty( $styles['css'] ) ) { 245 $attributes['style'] = $styles['css']; 246 } 247 248 return $attributes; 249 } 250 251 /** 252 * Generates an inline style value for a typography feature e.g. text decoration, 253 * text transform, and font style. 254 * 255 * Note: This function is for backwards compatibility. 256 * * It is necessary to parse older blocks whose typography styles contain presets. 257 * * It mostly replaces the deprecated `wp_typography_get_css_variable_inline_style()`, 258 * but skips compiling a CSS declaration as the style engine takes over this role. 259 * @link https://github.com/wordpress/gutenberg/pull/27555 260 * 261 * @since 6.1.0 262 * 263 * @param string $style_value A raw style value for a single typography feature from a block's style attribute. 264 * @param string $css_property Slug for the CSS property the inline style sets. 265 * @return string A CSS inline style value. 266 */ 267 function wp_typography_get_preset_inline_style_value( $style_value, $css_property ) { 268 // If the style value is not a preset CSS variable go no further. 269 if ( empty( $style_value ) || ! str_contains( $style_value, "var:preset|{$css_property}|" ) ) { 270 return $style_value; 271 } 272 273 /* 274 * For backwards compatibility. 275 * Presets were removed in WordPress/gutenberg#27555. 276 * A preset CSS variable is the style. 277 * Gets the style value from the string and return CSS style. 278 */ 279 $index_to_splice = strrpos( $style_value, '|' ) + 1; 280 $slug = _wp_to_kebab_case( substr( $style_value, $index_to_splice ) ); 281 282 // Return the actual CSS inline style value, 283 // e.g. `var(--wp--preset--text-decoration--underline);`. 284 return sprintf( 'var(--wp--preset--%s--%s);', $css_property, $slug ); 285 } 286 287 /** 288 * Renders typography styles/content to the block wrapper. 289 * 290 * @since 6.1.0 291 * 292 * @param string $block_content Rendered block content. 293 * @param array $block Block object. 294 * @return string Filtered block content. 295 */ 296 function wp_render_typography_support( $block_content, $block ) { 297 if ( ! empty( $block['attrs']['fitText'] ) && $block['attrs']['fitText'] && ! is_admin() ) { 298 wp_enqueue_script_module( '@wordpress/block-editor/utils/fit-text-frontend' ); 299 300 // Add Interactivity API directives for fit text to work with client-side navigation. 301 if ( ! empty( $block_content ) ) { 302 $processor = new WP_HTML_Tag_Processor( $block_content ); 303 if ( $processor->next_tag() ) { 304 if ( ! $processor->get_attribute( 'data-wp-interactive' ) ) { 305 $processor->set_attribute( 'data-wp-interactive', true ); 306 } 307 $processor->set_attribute( 'data-wp-context---core-fit-text', 'core/fit-text::{"fontSize":""}' ); 308 $processor->set_attribute( 'data-wp-init---core-fit-text', 'core/fit-text::callbacks.init' ); 309 $processor->set_attribute( 'data-wp-style--font-size', 'core/fit-text::context.fontSize' ); 310 $block_content = $processor->get_updated_html(); 311 } 312 } 313 // fitText supersedes any other typography features 314 return $block_content; 315 } 316 if ( ! isset( $block['attrs']['style']['typography']['fontSize'] ) ) { 317 return $block_content; 318 } 319 320 $custom_font_size = $block['attrs']['style']['typography']['fontSize']; 321 $fluid_font_size = wp_get_typography_font_size_value( array( 'size' => $custom_font_size ) ); 322 323 /* 324 * Checks that $fluid_font_size does not match $custom_font_size, 325 * which means it's been mutated by the fluid font size functions. 326 */ 327 if ( ! empty( $fluid_font_size ) && $fluid_font_size !== $custom_font_size ) { 328 // Replaces the first instance of `font-size:$custom_font_size` with `font-size:$fluid_font_size`. 329 return preg_replace( '/font-size\s*:\s*' . preg_quote( $custom_font_size, '/' ) . '\s*;?/', 'font-size:' . esc_attr( $fluid_font_size ) . ';', $block_content, 1 ); 330 } 331 332 return $block_content; 333 } 334 335 /** 336 * Checks a string for a unit and value and returns an array 337 * consisting of `'value'` and `'unit'`, e.g. array( '42', 'rem' ). 338 * 339 * @since 6.1.0 340 * 341 * @param string|int|float $raw_value Raw size value from theme.json. 342 * @param array $options { 343 * Optional. An associative array of options. Default is empty array. 344 * 345 * @type string $coerce_to Coerce the value to rem or px. Default `'rem'`. 346 * @type int $root_size_value Value of root font size for rem|em <-> px conversion. Default `16`. 347 * @type string[] $acceptable_units An array of font size units. Default `array( 'rem', 'px', 'em' )`; 348 * } 349 * @return array|null An array consisting of `'value'` and `'unit'` properties on success. 350 * `null` on failure. 351 */ 352 function wp_get_typography_value_and_unit( $raw_value, $options = array() ) { 353 if ( ! is_string( $raw_value ) && ! is_int( $raw_value ) && ! is_float( $raw_value ) ) { 354 _doing_it_wrong( 355 __FUNCTION__, 356 __( 'Raw size value must be a string, integer, or float.' ), 357 '6.1.0' 358 ); 359 return null; 360 } 361 362 if ( empty( $raw_value ) ) { 363 return null; 364 } 365 366 // Converts numbers to pixel values by default. 367 if ( is_numeric( $raw_value ) ) { 368 $raw_value = $raw_value . 'px'; 369 } 370 371 $defaults = array( 372 'coerce_to' => '', 373 'root_size_value' => 16, 374 'acceptable_units' => array( 'rem', 'px', 'em' ), 375 ); 376 377 $options = wp_parse_args( $options, $defaults ); 378 379 $acceptable_units_group = implode( '|', $options['acceptable_units'] ); 380 $pattern = '/^(\d*\.?\d+)(' . $acceptable_units_group . '){1,1}$/'; 381 382 preg_match( $pattern, $raw_value, $matches ); 383 384 // Bails out if not a number value and a px or rem unit. 385 if ( ! isset( $matches[1] ) || ! isset( $matches[2] ) ) { 386 return null; 387 } 388 389 $value = $matches[1]; 390 $unit = $matches[2]; 391 392 /* 393 * Default browser font size. Later, possibly could inject some JS to 394 * compute this `getComputedStyle( document.querySelector( "html" ) ).fontSize`. 395 */ 396 if ( 'px' === $options['coerce_to'] && ( 'em' === $unit || 'rem' === $unit ) ) { 397 $value = $value * $options['root_size_value']; 398 $unit = $options['coerce_to']; 399 } 400 401 if ( 'px' === $unit && ( 'em' === $options['coerce_to'] || 'rem' === $options['coerce_to'] ) ) { 402 $value = $value / $options['root_size_value']; 403 $unit = $options['coerce_to']; 404 } 405 406 /* 407 * No calculation is required if swapping between em and rem yet, 408 * since we assume a root size value. Later we might like to differentiate between 409 * :root font size (rem) and parent element font size (em) relativity. 410 */ 411 if ( ( 'em' === $options['coerce_to'] || 'rem' === $options['coerce_to'] ) && ( 'em' === $unit || 'rem' === $unit ) ) { 412 $unit = $options['coerce_to']; 413 } 414 415 return array( 416 'value' => round( $value, 3 ), 417 'unit' => $unit, 418 ); 419 } 420 421 /** 422 * Internal implementation of CSS clamp() based on available min/max viewport 423 * width and min/max font sizes. 424 * 425 * @since 6.1.0 426 * @since 6.3.0 Checks for unsupported min/max viewport values that cause invalid clamp values. 427 * @since 6.5.0 Returns early when min and max viewport subtraction is zero to avoid division by zero. 428 * @access private 429 * 430 * @param array $args { 431 * Optional. An associative array of values to calculate a fluid formula 432 * for font size. Default is empty array. 433 * 434 * @type string $maximum_viewport_width Maximum size up to which type will have fluidity. 435 * @type string $minimum_viewport_width Minimum viewport size from which type will have fluidity. 436 * @type string $maximum_font_size Maximum font size for any clamp() calculation. 437 * @type string $minimum_font_size Minimum font size for any clamp() calculation. 438 * @type int $scale_factor A scale factor to determine how fast a font scales within boundaries. 439 * } 440 * @return string|null A font-size value using clamp() on success, otherwise null. 441 */ 442 function wp_get_computed_fluid_typography_value( $args = array() ) { 443 $maximum_viewport_width_raw = $args['maximum_viewport_width'] ?? null; 444 $minimum_viewport_width_raw = $args['minimum_viewport_width'] ?? null; 445 $maximum_font_size_raw = $args['maximum_font_size'] ?? null; 446 $minimum_font_size_raw = $args['minimum_font_size'] ?? null; 447 $scale_factor = $args['scale_factor'] ?? null; 448 449 // Normalizes the minimum font size in order to use the value for calculations. 450 $minimum_font_size = wp_get_typography_value_and_unit( $minimum_font_size_raw ); 451 452 /* 453 * We get a 'preferred' unit to keep units consistent when calculating, 454 * otherwise the result will not be accurate. 455 */ 456 $font_size_unit = $minimum_font_size['unit'] ?? 'rem'; 457 458 // Normalizes the maximum font size in order to use the value for calculations. 459 $maximum_font_size = wp_get_typography_value_and_unit( 460 $maximum_font_size_raw, 461 array( 462 'coerce_to' => $font_size_unit, 463 ) 464 ); 465 466 // Checks for mandatory min and max sizes, and protects against unsupported units. 467 if ( ! $maximum_font_size || ! $minimum_font_size ) { 468 return null; 469 } 470 471 // Uses rem for accessible fluid target font scaling. 472 $minimum_font_size_rem = wp_get_typography_value_and_unit( 473 $minimum_font_size_raw, 474 array( 475 'coerce_to' => 'rem', 476 ) 477 ); 478 479 // Viewport widths defined for fluid typography. Normalize units. 480 $maximum_viewport_width = wp_get_typography_value_and_unit( 481 $maximum_viewport_width_raw, 482 array( 483 'coerce_to' => $font_size_unit, 484 ) 485 ); 486 $minimum_viewport_width = wp_get_typography_value_and_unit( 487 $minimum_viewport_width_raw, 488 array( 489 'coerce_to' => $font_size_unit, 490 ) 491 ); 492 493 // Protects against unsupported units in min and max viewport widths. 494 if ( ! $minimum_viewport_width || ! $maximum_viewport_width ) { 495 return null; 496 } 497 498 // Calculates the linear factor denominator. If it's 0, we cannot calculate a fluid value. 499 $linear_factor_denominator = $maximum_viewport_width['value'] - $minimum_viewport_width['value']; 500 if ( empty( $linear_factor_denominator ) ) { 501 return null; 502 } 503 504 /* 505 * Build CSS rule. 506 * Borrowed from https://websemantics.uk/tools/responsive-font-calculator/. 507 */ 508 $view_port_width_offset = round( $minimum_viewport_width['value'] / 100, 3 ) . $font_size_unit; 509 $linear_factor = 100 * ( ( $maximum_font_size['value'] - $minimum_font_size['value'] ) / ( $linear_factor_denominator ) ); 510 $linear_factor_scaled = round( $linear_factor * $scale_factor, 3 ); 511 $linear_factor_scaled = empty( $linear_factor_scaled ) ? 1 : $linear_factor_scaled; 512 $fluid_target_font_size = implode( '', $minimum_font_size_rem ) . " + ((1vw - $view_port_width_offset) * $linear_factor_scaled)"; 513 514 return "clamp($minimum_font_size_raw, $fluid_target_font_size, $maximum_font_size_raw)"; 515 } 516 517 /** 518 * Returns a font-size value based on a given font-size preset. 519 * Takes into account fluid typography parameters and attempts to return a CSS 520 * formula depending on available, valid values. 521 * 522 * @since 6.1.0 523 * @since 6.1.1 Adjusted rules for min and max font sizes. 524 * @since 6.2.0 Added 'settings.typography.fluid.minFontSize' support. 525 * @since 6.3.0 Using layout.wideSize as max viewport width, and logarithmic scale factor to calculate minimum font scale. 526 * @since 6.4.0 Added configurable min and max viewport width values to the typography.fluid theme.json schema. 527 * @since 6.6.0 Deprecated bool argument $should_use_fluid_typography. 528 * @since 6.7.0 Font size presets can enable fluid typography individually, even if it’s disabled globally. 529 * 530 * @param array $preset { 531 * Required. fontSizes preset value as seen in theme.json. 532 * 533 * @type string $name Name of the font size preset. 534 * @type string $slug Kebab-case, unique identifier for the font size preset. 535 * @type string|int|float $size CSS font-size value, including units if applicable. 536 * } 537 * @param bool|array $settings Optional Theme JSON settings array that overrides any global theme settings. 538 * Default is false. 539 * @return string|null Font-size value or null if a size is not passed in $preset. 540 */ 541 542 543 function wp_get_typography_font_size_value( $preset, $settings = array() ) { 544 if ( ! isset( $preset['size'] ) ) { 545 return null; 546 } 547 548 /* 549 * Catches falsy values and 0/'0'. Fluid calculations cannot be performed on `0`. 550 * Also returns early when a preset font size explicitly disables fluid typography with `false`. 551 */ 552 $fluid_font_size_settings = $preset['fluid'] ?? null; 553 if ( false === $fluid_font_size_settings || empty( $preset['size'] ) ) { 554 return $preset['size']; 555 } 556 557 /* 558 * As a boolean (deprecated since 6.6), $settings acts as an override to switch fluid typography "on" (`true`) or "off" (`false`). 559 */ 560 if ( is_bool( $settings ) ) { 561 _deprecated_argument( __FUNCTION__, '6.6.0', __( '`boolean` type for second argument `$settings` is deprecated. Use `array()` instead.' ) ); 562 $settings = array( 563 'typography' => array( 564 'fluid' => $settings, 565 ), 566 ); 567 } 568 569 // Fallback to global settings as default. 570 $global_settings = wp_get_global_settings(); 571 $settings = wp_parse_args( 572 $settings, 573 $global_settings 574 ); 575 576 $typography_settings = $settings['typography'] ?? array(); 577 578 /* 579 * Return early when fluid typography is disabled in the settings, and there 580 * are no local settings to enable it for the individual preset. 581 * 582 * If this condition isn't met, either the settings or individual preset settings 583 * have enabled fluid typography. 584 */ 585 if ( empty( $typography_settings['fluid'] ) && empty( $fluid_font_size_settings ) ) { 586 return $preset['size']; 587 } 588 589 $fluid_settings = $typography_settings['fluid'] ?? array(); 590 $layout_settings = $settings['layout'] ?? array(); 591 592 // Defaults. 593 $default_maximum_viewport_width = '1600px'; 594 $default_minimum_viewport_width = '320px'; 595 $default_minimum_font_size_factor_max = 0.75; 596 $default_minimum_font_size_factor_min = 0.25; 597 $default_scale_factor = 1; 598 $default_minimum_font_size_limit = '14px'; 599 600 // Defaults overrides. 601 $minimum_viewport_width = $fluid_settings['minViewportWidth'] ?? $default_minimum_viewport_width; 602 $maximum_viewport_width = isset( $layout_settings['wideSize'] ) && ! empty( wp_get_typography_value_and_unit( $layout_settings['wideSize'] ) ) ? $layout_settings['wideSize'] : $default_maximum_viewport_width; 603 if ( isset( $fluid_settings['maxViewportWidth'] ) ) { 604 $maximum_viewport_width = $fluid_settings['maxViewportWidth']; 605 } 606 $has_min_font_size = isset( $fluid_settings['minFontSize'] ) && ! empty( wp_get_typography_value_and_unit( $fluid_settings['minFontSize'] ) ); 607 $minimum_font_size_limit = $has_min_font_size ? $fluid_settings['minFontSize'] : $default_minimum_font_size_limit; 608 609 // Try to grab explicit min and max fluid font sizes. 610 $minimum_font_size_raw = $fluid_font_size_settings['min'] ?? null; 611 $maximum_font_size_raw = $fluid_font_size_settings['max'] ?? null; 612 613 // Font sizes. 614 $preferred_size = wp_get_typography_value_and_unit( $preset['size'] ); 615 616 // Protects against unsupported units. 617 if ( empty( $preferred_size['unit'] ) ) { 618 return $preset['size']; 619 } 620 621 /* 622 * Normalizes the minimum font size limit according to the incoming unit, 623 * in order to perform comparative checks. 624 */ 625 $minimum_font_size_limit = wp_get_typography_value_and_unit( 626 $minimum_font_size_limit, 627 array( 628 'coerce_to' => $preferred_size['unit'], 629 ) 630 ); 631 632 // Don't enforce minimum font size if a font size has explicitly set a min and max value. 633 if ( ! empty( $minimum_font_size_limit ) && ( ! $minimum_font_size_raw && ! $maximum_font_size_raw ) ) { 634 /* 635 * If a minimum size was not passed to this function 636 * and the user-defined font size is lower than $minimum_font_size_limit, 637 * do not calculate a fluid value. 638 */ 639 if ( $preferred_size['value'] <= $minimum_font_size_limit['value'] ) { 640 return $preset['size']; 641 } 642 } 643 644 // If no fluid max font size is available use the incoming value. 645 if ( ! $maximum_font_size_raw ) { 646 $maximum_font_size_raw = $preferred_size['value'] . $preferred_size['unit']; 647 } 648 649 /* 650 * If no minimumFontSize is provided, create one using 651 * the given font size multiplied by the min font size scale factor. 652 */ 653 if ( ! $minimum_font_size_raw ) { 654 $preferred_font_size_in_px = 'px' === $preferred_size['unit'] ? $preferred_size['value'] : $preferred_size['value'] * 16; 655 656 /* 657 * The scale factor is a multiplier that affects how quickly the curve will move towards the minimum, 658 * that is, how quickly the size factor reaches 0 given increasing font size values. 659 * For a - b * log2(), lower values of b will make the curve move towards the minimum faster. 660 * The scale factor is constrained between min and max values. 661 */ 662 $minimum_font_size_factor = min( max( 1 - 0.075 * log( $preferred_font_size_in_px, 2 ), $default_minimum_font_size_factor_min ), $default_minimum_font_size_factor_max ); 663 $calculated_minimum_font_size = round( $preferred_size['value'] * $minimum_font_size_factor, 3 ); 664 665 // Only use calculated min font size if it's > $minimum_font_size_limit value. 666 if ( ! empty( $minimum_font_size_limit ) && $calculated_minimum_font_size <= $minimum_font_size_limit['value'] ) { 667 $minimum_font_size_raw = $minimum_font_size_limit['value'] . $minimum_font_size_limit['unit']; 668 } else { 669 $minimum_font_size_raw = $calculated_minimum_font_size . $preferred_size['unit']; 670 } 671 } 672 673 $fluid_font_size_value = wp_get_computed_fluid_typography_value( 674 array( 675 'minimum_viewport_width' => $minimum_viewport_width, 676 'maximum_viewport_width' => $maximum_viewport_width, 677 'minimum_font_size' => $minimum_font_size_raw, 678 'maximum_font_size' => $maximum_font_size_raw, 679 'scale_factor' => $default_scale_factor, 680 ) 681 ); 682 683 if ( ! empty( $fluid_font_size_value ) ) { 684 return $fluid_font_size_value; 685 } 686 687 return $preset['size']; 688 } 689 690 // Register the block support. 691 WP_Block_Supports::get_instance()->register( 692 'typography', 693 array( 694 'register_attribute' => 'wp_register_typography_support', 695 'apply' => 'wp_apply_typography_support', 696 ) 697 );
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated : Wed Apr 15 08:20:10 2026 | Cross-referenced by PHPXref |