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