<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[54162] trunk: Editor: Backport foundation for Layout block support refactor (part 1).</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { white-space: pre-line; overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="https://core.trac.wordpress.org/changeset/54162">54162</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"https://core.trac.wordpress.org/changeset/54162","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>hellofromTonya</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2022-09-14 18:42:04 +0000 (Wed, 14 Sep 2022)</dd>
</dl>
<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>Editor: Backport foundation for Layout block support refactor (part 1).
Backports the following changes from the Gutenberg repository:
* [WordPress/gutenberg/40875 gutenberg/40875] Layout: Use semantic classnames, centralize layout definitions, reduce duplication, and fix blockGap in theme.json
* [WordPress/gutenberg/42544 gutenberg/42544] Layout: Add a disable-layout-styles theme supports flag to opt out of all layout styles gutenberg/42544
* [WordPress/gutenberg/42087 gutenberg/42087] Theme.json: Add block support feature level selectors for blocks gutenberg/42087
* [WordPress/gutenberg/43792 gutenberg/43792] Global Styles: Split root layout rules into a different function gutenberg/43792
* [WordPress/gutenberg/42544 gutenberg/42544] Layout: Add a disable-layout-styles theme supports flag to opt out of all layout styles gutenberg/42544
* [WordPress/gutenberg/42665 gutenberg/42665] Layout: Reduce specificity of fallback blockGap styles gutenberg/42665
* [WordPress/gutenberg/42085 gutenberg/42085] Core CSS support for root padding and alignfull blocks gutenberg/42085
Notes:
* It doesn't entirely port over PR 40875 - the remaining PHP changes for that PR will be explored in a separate PR targeting `layout.php`.
* <a href="https://core.trac.wordpress.org/changeset/54159">[54159]</a> was reverted in <a href="https://core.trac.wordpress.org/changeset/54160">[54160]</a> due to PHPUnit test failures for tests added by the commit. Later, tests passed when applied on top of `trunk`. There were various outages today of upstream `wp-env` dependencies, which likely were the root cause of the earlier failures. For historical tracking and to make sure, recommitting <a href="https://core.trac.wordpress.org/changeset/54159">[54159]</a> but instead on top of current `trunk`. See PR 3205 for more details.
* Giving additional props for those who did a deep dive investigation into the failed tests.
Follow-up to <a href="https://core.trac.wordpress.org/changeset/54160">[54160]</a>, <a href="https://core.trac.wordpress.org/changeset/54159">[54159]</a>.
Props andrewserong, aaronrobertshaw, isabel_brison, bernhard-reiter, hellofromTonya.
See <a href="https://core.trac.wordpress.org/ticket/56467">#56467</a>.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunksrcwpincludesblockeditorphp">trunk/src/wp-includes/block-editor.php</a></li>
<li><a href="#trunksrcwpincludesclasswpthemejsonresolverphp">trunk/src/wp-includes/class-wp-theme-json-resolver.php</a></li>
<li><a href="#trunksrcwpincludesclasswpthemejsonphp">trunk/src/wp-includes/class-wp-theme-json.php</a></li>
<li><a href="#trunksrcwpincludesglobalstylesandsettingsphp">trunk/src/wp-includes/global-styles-and-settings.php</a></li>
<li><a href="#trunksrcwpincludesthemejson">trunk/src/wp-includes/theme.json</a></li>
<li><a href="#trunksrcwpincludesthemephp">trunk/src/wp-includes/theme.php</a></li>
<li><a href="#trunktestsphpunittestsblockseditorphp">trunk/tests/phpunit/tests/blocks/editor.php</a></li>
<li><a href="#trunktestsphpunittestsrestapirestthemescontrollerphp">trunk/tests/phpunit/tests/rest-api/rest-themes-controller.php</a></li>
<li><a href="#trunktestsphpunitteststhemewpThemeJsonphp">trunk/tests/phpunit/tests/theme/wpThemeJson.php</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunksrcwpincludesblockeditorphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/block-editor.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/block-editor.php 2022-09-14 17:12:20 UTC (rev 54161)
+++ trunk/src/wp-includes/block-editor.php 2022-09-14 18:42:04 UTC (rev 54162)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -209,6 +209,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 'disableCustomColors' => get_theme_support( 'disable-custom-colors' ),
</span><span class="cx" style="display: block; padding: 0 10px"> 'disableCustomFontSizes' => get_theme_support( 'disable-custom-font-sizes' ),
</span><span class="cx" style="display: block; padding: 0 10px"> 'disableCustomGradients' => get_theme_support( 'disable-custom-gradients' ),
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'disableLayoutStyles' => get_theme_support( 'disable-layout-styles' ),
</ins><span class="cx" style="display: block; padding: 0 10px"> 'enableCustomLineHeight' => get_theme_support( 'custom-line-height' ),
</span><span class="cx" style="display: block; padding: 0 10px"> 'enableCustomSpacing' => get_theme_support( 'custom-spacing' ),
</span><span class="cx" style="display: block; padding: 0 10px"> 'enableCustomUnits' => get_theme_support( 'custom-units' ),
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -417,6 +418,18 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $block_classes['css'] = $actual_css;
</span><span class="cx" style="display: block; padding: 0 10px"> $global_styles[] = $block_classes;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ } else {
+ // If there is no `theme.json` file, ensure base layout styles are still available.
+ $block_classes = array(
+ 'css' => 'base-layout-styles',
+ '__unstableType' => 'base-layout',
+ 'isGlobalStyles' => true,
+ );
+ $actual_css = wp_get_global_stylesheet( array( $block_classes['css'] ) );
+ if ( '' !== $actual_css ) {
+ $block_classes['css'] = $actual_css;
+ $global_styles[] = $block_classes;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $editor_settings['styles'] = array_merge( $global_styles, get_block_editor_theme_styles() );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -474,9 +487,24 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $editor_settings['enableCustomSpacing'] = $editor_settings['__experimentalFeatures']['spacing']['padding'];
</span><span class="cx" style="display: block; padding: 0 10px"> unset( $editor_settings['__experimentalFeatures']['spacing']['padding'] );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( isset( $editor_settings['__experimentalFeatures']['spacing']['customSpacingSize'] ) ) {
+ $editor_settings['disableCustomSpacingSizes'] = ! $editor_ettings['__experimentalFeatures']['spacing']['customSpacingSize'];
+ unset( $editor_settings['__experimentalFeatures']['spacing']['customSpacingSize'] );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( isset( $editor_settings['__experimentalFeatures']['spacing']['spacingSizes'] ) ) {
+ $spacing_sizes_by_origin = $editor_settings['__experimentalFeatures']['spacing']['spacingSizes'];
+ $editor_settings['spacingSizes'] = isset( $spacing_sizes_by_origin['custom'] ) ?
+ $spacing_sizes_by_origin['custom'] : (
+ isset( $spacing_sizes_by_origin['theme'] ) ?
+ $spacing_sizes_by_origin['theme'] :
+ $spacing_sizes_by_origin['default']
+ );
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> $editor_settings['__unstableResolvedAssets'] = _wp_get_iframed_editor_assets();
</span><span class="cx" style="display: block; padding: 0 10px"> $editor_settings['localAutosaveInterval'] = 15;
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $editor_settings['disableLayoutStyles'] = current_theme_supports( 'disable-layout-styles' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $editor_settings['__experimentalDiscussionSettings'] = array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'commentOrder' => get_option( 'comment_order' ),
</span><span class="cx" style="display: block; padding: 0 10px"> 'commentsPerPage' => get_option( 'comments_per_page' ),
</span></span></pre></div>
<a id="trunksrcwpincludesclasswpthemejsonresolverphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/class-wp-theme-json-resolver.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/class-wp-theme-json-resolver.php 2022-09-14 17:12:20 UTC (rev 54161)
+++ trunk/src/wp-includes/class-wp-theme-json-resolver.php 2022-09-14 18:42:04 UTC (rev 54162)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -233,6 +233,54 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Gets the styles for blocks from the block.json file.
+ *
+ * @since 6.1.0
+ *
+ * @return WP_Theme_JSON
+ */
+ public static function get_block_data() {
+ $registry = WP_Block_Type_Registry::get_instance();
+ $blocks = $registry->get_all_registered();
+ $config = array( 'version' => 1 );
+ foreach ( $blocks as $block_name => $block_type ) {
+ if ( isset( $block_type->supports['__experimentalStyle'] ) ) {
+ $config['styles']['blocks'][ $block_name ] = static::remove_json_comments( $block_type->supports['__experimentalStyle'] );
+ }
+
+ if (
+ isset( $block_type->supports['spacing']['blockGap']['__experimentalDefault'] ) &&
+ null === _wp_array_get( $config, array( 'styles', 'blocks', $block_name, 'spacing', 'blockGap' ), null )
+ ) {
+ // Ensure an empty placeholder value exists for the block, if it provides a default blockGap value.
+ // The real blockGap value to be used will be determined when the styles are rendered for output.
+ $config['styles']['blocks'][ $block_name ]['spacing']['blockGap'] = null;
+ }
+ }
+
+ // Core here means it's the lower level part of the styles chain.
+ // It can be a core or a third-party block.
+ return new WP_Theme_JSON( $config, 'core' );
+ }
+
+ /**
+ * When given an array, this will remove any keys with the name `//`.
+ *
+ * @param array $array The array to filter.
+ * @return array The filtered array.
+ */
+ private static function remove_json_comments( $array ) {
+ unset( $array['//'] );
+ foreach ( $array as $k => $v ) {
+ if ( is_array( $v ) ) {
+ $array[ $k ] = static::remove_json_comments( $v );
+ }
+ }
+
+ return $array;
+ }
+
+ /**
</ins><span class="cx" style="display: block; padding: 0 10px"> * Returns the custom post type that contains the user's origin config
</span><span class="cx" style="display: block; padding: 0 10px"> * for the active theme or a void array if none are found.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -370,6 +418,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @since 5.8.0
</span><span class="cx" style="display: block; padding: 0 10px"> * @since 5.9.0 Added user data, removed the `$settings` parameter,
</span><span class="cx" style="display: block; padding: 0 10px"> * added the `$origin` parameter.
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @since 6.1.0 Added block data.
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @param string $origin Optional. To what level should we merge data.
</span><span class="cx" style="display: block; padding: 0 10px"> * Valid values are 'theme' or 'custom'. Default 'custom'.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -382,6 +431,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $result = new WP_Theme_JSON();
</span><span class="cx" style="display: block; padding: 0 10px"> $result->merge( static::get_core_data() );
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $result->merge( static::get_block_data() );
</ins><span class="cx" style="display: block; padding: 0 10px"> $result->merge( static::get_theme_data() );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> if ( 'custom' === $origin ) {
</span></span></pre></div>
<a id="trunksrcwpincludesclasswpthemejsonphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/class-wp-theme-json.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/class-wp-theme-json.php 2022-09-14 17:12:20 UTC (rev 54161)
+++ trunk/src/wp-includes/class-wp-theme-json.php 2022-09-14 18:42:04 UTC (rev 54162)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -177,40 +177,60 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * `letter-spacing`, `margin-*`, `padding-*`, `--wp--style--block-gap`,
</span><span class="cx" style="display: block; padding: 0 10px"> * `text-decoration`, `text-transform`, and `filter` properties,
</span><span class="cx" style="display: block; padding: 0 10px"> * simplified the metadata structure.
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @since 6.1.0 Added the `border-*-color`, `border-*-width`, `border-*-style`,
+ * `--wp--style--root--padding-*`, and `box-shadow` properties,
+ * removed the `--wp--style--block-gap` property.
</ins><span class="cx" style="display: block; padding: 0 10px"> * @var array
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> const PROPERTIES_METADATA = array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'background' => array( 'color', 'gradient' ),
- 'background-color' => array( 'color', 'background' ),
- 'border-radius' => array( 'border', 'radius' ),
- 'border-top-left-radius' => array( 'border', 'radius', 'topLeft' ),
- 'border-top-right-radius' => array( 'border', 'radius', 'topRight' ),
- 'border-bottom-left-radius' => array( 'border', 'radius', 'bottomLeft' ),
- 'border-bottom-right-radius' => array( 'border', 'radius', 'bottomRight' ),
- 'border-color' => array( 'border', 'color' ),
- 'border-width' => array( 'border', 'width' ),
- 'border-style' => array( 'border', 'style' ),
- 'color' => array( 'color', 'text' ),
- 'font-family' => array( 'typography', 'fontFamily' ),
- 'font-size' => array( 'typography', 'fontSize' ),
- 'font-style' => array( 'typography', 'fontStyle' ),
- 'font-weight' => array( 'typography', 'fontWeight' ),
- 'letter-spacing' => array( 'typography', 'letterSpacing' ),
- 'line-height' => array( 'typography', 'lineHeight' ),
- 'margin' => array( 'spacing', 'margin' ),
- 'margin-top' => array( 'spacing', 'margin', 'top' ),
- 'margin-right' => array( 'spacing', 'margin', 'right' ),
- 'margin-bottom' => array( 'spacing', 'margin', 'bottom' ),
- 'margin-left' => array( 'spacing', 'margin', 'left' ),
- 'padding' => array( 'spacing', 'padding' ),
- 'padding-top' => array( 'spacing', 'padding', 'top' ),
- 'padding-right' => array( 'spacing', 'padding', 'right' ),
- 'padding-bottom' => array( 'spacing', 'padding', 'bottom' ),
- 'padding-left' => array( 'spacing', 'padding', 'left' ),
- '--wp--style--block-gap' => array( 'spacing', 'blockGap' ),
- 'text-decoration' => array( 'typography', 'textDecoration' ),
- 'text-transform' => array( 'typography', 'textTransform' ),
- 'filter' => array( 'filter', 'duotone' ),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'background' => array( 'color', 'gradient' ),
+ 'background-color' => array( 'color', 'background' ),
+ 'border-radius' => array( 'border', 'radius' ),
+ 'border-top-left-radius' => array( 'border', 'radius', 'topLeft' ),
+ 'border-top-right-radius' => array( 'border', 'radius', 'topRight' ),
+ 'border-bottom-left-radius' => array( 'border', 'radius', 'bottomLeft' ),
+ 'border-bottom-right-radius' => array( 'border', 'radius', 'bottomRight' ),
+ 'border-color' => array( 'border', 'color' ),
+ 'border-width' => array( 'border', 'width' ),
+ 'border-style' => array( 'border', 'style' ),
+ 'border-top-color' => array( 'border', 'top', 'color' ),
+ 'border-top-width' => array( 'border', 'top', 'width' ),
+ 'border-top-style' => array( 'border', 'top', 'style' ),
+ 'border-right-color' => array( 'border', 'right', 'color' ),
+ 'border-right-width' => array( 'border', 'right', 'width' ),
+ 'border-right-style' => array( 'border', 'right', 'style' ),
+ 'border-bottom-color' => array( 'border', 'bottom', 'color' ),
+ 'border-bottom-width' => array( 'border', 'bottom', 'width' ),
+ 'border-bottom-style' => array( 'border', 'bottom', 'style' ),
+ 'border-left-color' => array( 'border', 'left', 'color' ),
+ 'border-left-width' => array( 'border', 'left', 'width' ),
+ 'border-left-style' => array( 'border', 'left', 'style' ),
+ 'color' => array( 'color', 'text' ),
+ 'font-family' => array( 'typography', 'fontFamily' ),
+ 'font-size' => array( 'typography', 'fontSize' ),
+ 'font-style' => array( 'typography', 'fontStyle' ),
+ 'font-weight' => array( 'typography', 'fontWeight' ),
+ 'letter-spacing' => array( 'typography', 'letterSpacing' ),
+ 'line-height' => array( 'typography', 'lineHeight' ),
+ 'margin' => array( 'spacing', 'margin' ),
+ 'margin-top' => array( 'spacing', 'margin', 'top' ),
+ 'margin-right' => array( 'spacing', 'margin', 'right' ),
+ 'margin-bottom' => array( 'spacing', 'margin', 'bottom' ),
+ 'margin-left' => array( 'spacing', 'margin', 'left' ),
+ 'padding' => array( 'spacing', 'padding' ),
+ 'padding-top' => array( 'spacing', 'padding', 'top' ),
+ 'padding-right' => array( 'spacing', 'padding', 'right' ),
+ 'padding-bottom' => array( 'spacing', 'padding', 'bottom' ),
+ 'padding-left' => array( 'spacing', 'padding', 'left' ),
+ '--wp--style--root--padding' => array( 'spacing', 'padding' ),
+ '--wp--style--root--padding-top' => array( 'spacing', 'padding', 'top' ),
+ '--wp--style--root--padding-right' => array( 'spacing', 'padding', 'right' ),
+ '--wp--style--root--padding-bottom' => array( 'spacing', 'padding', 'bottom' ),
+ '--wp--style--root--padding-left' => array( 'spacing', 'padding', 'left' ),
+ 'text-decoration' => array( 'typography', 'textDecoration' ),
+ 'text-transform' => array( 'typography', 'textTransform' ),
+ 'filter' => array( 'filter', 'duotone' ),
+ 'box-shadow' => array( 'shadow' ),
</ins><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -254,17 +274,19 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * added new properties for `border`, `color`, `spacing`,
</span><span class="cx" style="display: block; padding: 0 10px"> * and `typography`, and renamed others according to the new schema.
</span><span class="cx" style="display: block; padding: 0 10px"> * @since 6.0.0 Added `color.defaultDuotone`.
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @since 6.1.0 Added `layout.definitions` and `useRootPaddingAwareAlignments`.
</ins><span class="cx" style="display: block; padding: 0 10px"> * @var array
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> const VALID_SETTINGS = array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'appearanceTools' => null,
- 'border' => array(
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'appearanceTools' => null,
+ 'useRootPaddingAwareAlignments' => null,
+ 'border' => array(
</ins><span class="cx" style="display: block; padding: 0 10px"> 'color' => null,
</span><span class="cx" style="display: block; padding: 0 10px"> 'radius' => null,
</span><span class="cx" style="display: block; padding: 0 10px"> 'style' => null,
</span><span class="cx" style="display: block; padding: 0 10px"> 'width' => null,
</span><span class="cx" style="display: block; padding: 0 10px"> ),
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'color' => array(
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'color' => array(
</ins><span class="cx" style="display: block; padding: 0 10px"> 'background' => null,
</span><span class="cx" style="display: block; padding: 0 10px"> 'custom' => null,
</span><span class="cx" style="display: block; padding: 0 10px"> 'customDuotone' => null,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -278,18 +300,19 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 'palette' => null,
</span><span class="cx" style="display: block; padding: 0 10px"> 'text' => null,
</span><span class="cx" style="display: block; padding: 0 10px"> ),
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'custom' => null,
- 'layout' => array(
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'custom' => null,
+ 'layout' => array(
</ins><span class="cx" style="display: block; padding: 0 10px"> 'contentSize' => null,
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'definitions' => null,
</ins><span class="cx" style="display: block; padding: 0 10px"> 'wideSize' => null,
</span><span class="cx" style="display: block; padding: 0 10px"> ),
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'spacing' => array(
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'spacing' => array(
</ins><span class="cx" style="display: block; padding: 0 10px"> 'blockGap' => null,
</span><span class="cx" style="display: block; padding: 0 10px"> 'margin' => null,
</span><span class="cx" style="display: block; padding: 0 10px"> 'padding' => null,
</span><span class="cx" style="display: block; padding: 0 10px"> 'units' => null,
</span><span class="cx" style="display: block; padding: 0 10px"> ),
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'typography' => array(
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'typography' => array(
</ins><span class="cx" style="display: block; padding: 0 10px"> 'customFontSize' => null,
</span><span class="cx" style="display: block; padding: 0 10px"> 'dropCap' => null,
</span><span class="cx" style="display: block; padding: 0 10px"> 'fontFamilies' => null,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -310,6 +333,8 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @since 5.9.0 Renamed from `ALLOWED_STYLES` to `VALID_STYLES`,
</span><span class="cx" style="display: block; padding: 0 10px"> * added new properties for `border`, `filter`, `spacing`,
</span><span class="cx" style="display: block; padding: 0 10px"> * and `typography`.
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @since 6.1.0 Added new side properties for `border`,
+ * updated `blockGap` to be allowed at any level.
</ins><span class="cx" style="display: block; padding: 0 10px"> * @var array
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> const VALID_STYLES = array(
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -318,6 +343,10 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 'radius' => null,
</span><span class="cx" style="display: block; padding: 0 10px"> 'style' => null,
</span><span class="cx" style="display: block; padding: 0 10px"> 'width' => null,
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'top' => null,
+ 'right' => null,
+ 'bottom' => null,
+ 'left' => null,
</ins><span class="cx" style="display: block; padding: 0 10px"> ),
</span><span class="cx" style="display: block; padding: 0 10px"> 'color' => array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'background' => null,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -330,7 +359,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 'spacing' => array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'margin' => null,
</span><span class="cx" style="display: block; padding: 0 10px"> 'padding' => null,
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'blockGap' => 'top',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'blockGap' => null,
</ins><span class="cx" style="display: block; padding: 0 10px"> ),
</span><span class="cx" style="display: block; padding: 0 10px"> 'typography' => array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'fontFamily' => null,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -384,6 +413,20 @@
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * List of block support features that can have their related styles
+ * generated under their own feature level selector rather than the block's.
+ *
+ * @since 6.1.0
+ * @var string[]
+ */
+ const BLOCK_SUPPORT_FEATURE_LEVEL_SELECTORS = array(
+ '__experimentalBorder' => 'border',
+ 'color' => 'color',
+ 'spacing' => 'spacing',
+ 'typography' => 'typography',
+ );
+
+ /**
</ins><span class="cx" style="display: block; padding: 0 10px"> * Returns a class name by an element name.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @since 6.1.0
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -656,6 +699,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @since 5.8.0
</span><span class="cx" style="display: block; padding: 0 10px"> * @since 5.9.0 Added `duotone` key with CSS selector.
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @since 6.1.0 Added `features` key with block support feature level selectors.
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @return array Block metadata.
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -685,6 +729,25 @@
</span><span class="cx" style="display: block; padding: 0 10px"> static::$blocks_metadata[ $block_name ]['duotone'] = $block_type->supports['color']['__experimentalDuotone'];
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Generate block support feature level selectors if opted into
+ // for the current block.
+ $features = array();
+ foreach ( static::BLOCK_SUPPORT_FEATURE_LEVEL_SELECTORS as $key => $feature ) {
+ if (
+ isset( $block_type->supports[ $key ]['__experimentalSelector'] ) &&
+ $block_type->supports[ $key ]['__experimentalSelector']
+ ) {
+ $features[ $feature ] = static::scope_selector(
+ static::$blocks_metadata[ $block_name ]['selector'],
+ $block_type->supports[ $key ]['__experimentalSelector']
+ );
+ }
+ }
+
+ if ( ! empty( $features ) ) {
+ static::$blocks_metadata[ $block_name ]['features'] = $features;
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> // Assign defaults, then overwrite those that the block sets by itself.
</span><span class="cx" style="display: block; padding: 0 10px"> // If the block selector is compounded, will append the element to each
</span><span class="cx" style="display: block; padding: 0 10px"> // individual block selector.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -810,7 +873,30 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> if ( in_array( 'styles', $types, true ) ) {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $root_block_key = array_search( static::ROOT_BLOCK_SELECTOR, array_column( $style_nodes, 'selector' ), true );
+
+ if ( false !== $root_block_key ) {
+ $stylesheet .= $this->get_root_layout_rules( static::ROOT_BLOCK_SELECTOR, $style_nodes[ $root_block_key ] );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> $stylesheet .= $this->get_block_classes( $style_nodes );
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ } elseif ( in_array( 'base-layout-styles', $types, true ) ) {
+ // Base layout styles are provided as part of `styles`, so only output separately if explicitly requested.
+ // For backwards compatibility, the Columns block is explicitly included, to support a different default gap value.
+ $base_styles_nodes = array(
+ array(
+ 'path' => array( 'styles' ),
+ 'selector' => static::ROOT_BLOCK_SELECTOR,
+ ),
+ array(
+ 'path' => array( 'styles', 'blocks', 'core/columns' ),
+ 'selector' => '.wp-block-columns',
+ 'name' => 'core/columns',
+ ),
+ );
+
+ foreach ( $base_styles_nodes as $base_style_node ) {
+ $stylesheet .= $this->get_layout_styles( $base_style_node );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> if ( in_array( 'presets', $types, true ) ) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -884,6 +970,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @since 5.9.0 Renamed from `get_block_styles()` to `get_block_classes()`
</span><span class="cx" style="display: block; padding: 0 10px"> * and no longer returns preset classes.
</span><span class="cx" style="display: block; padding: 0 10px"> * Removed the `$setting_nodes` parameter.
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @since 6.1.0 Moved most internal logic to `get_styles_for_block()`.
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @param array $style_nodes Nodes with styles.
</span><span class="cx" style="display: block; padding: 0 10px"> * @return string The new stylesheet.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -902,6 +989,190 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Get the CSS layout rules for a particular block from theme.json layout definitions.
+ *
+ * @since 6.1.0
+ *
+ * @param array $block_metadata Metadata about the block to get styles for.
+ *
+ * @return string Layout styles for the block.
+ */
+ protected function get_layout_styles( $block_metadata ) {
+ $block_rules = '';
+ $block_type = null;
+
+ // Skip outputting layout styles if explicitly disabled.
+ if ( current_theme_supports( 'disable-layout-styles' ) ) {
+ return $block_rules;
+ }
+
+ if ( isset( $block_metadata['name'] ) ) {
+ $block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block_metadata['name'] );
+ if ( ! block_has_support( $block_type, array( '__experimentalLayout' ), false ) ) {
+ return $block_rules;
+ }
+ }
+
+ $selector = isset( $block_metadata['selector'] ) ? $block_metadata['selector'] : '';
+ $has_block_gap_support = _wp_array_get( $this->theme_json, array( 'settings', 'spacing', 'blockGap' ) ) !== null;
+ $has_fallback_gap_support = ! $has_block_gap_support; // This setting isn't useful yet: it exists as a placeholder for a future explicit fallback gap styles support.
+ $node = _wp_array_get( $this->theme_json, $block_metadata['path'], array() );
+ $layout_definitions = _wp_array_get( $this->theme_json, array( 'settings', 'layout', 'definitions' ), array() );
+ $layout_selector_pattern = '/^[a-zA-Z0-9\-\.\ *+>:\(\)]*$/'; // Allow alphanumeric classnames, spaces, wildcard, sibling, child combinator and pseudo class selectors.
+
+ // Gap styles will only be output if the theme has block gap support, or supports a fallback gap.
+ // Default layout gap styles will be skipped for themes that do not explicitly opt-in to blockGap with a `true` or `false` value.
+ if ( $has_block_gap_support || $has_fallback_gap_support ) {
+ $block_gap_value = null;
+ // Use a fallback gap value if block gap support is not available.
+ if ( ! $has_block_gap_support ) {
+ $block_gap_value = static::ROOT_BLOCK_SELECTOR === $selector ? '0.5em' : null;
+ if ( ! empty( $block_type ) ) {
+ $block_gap_value = _wp_array_get( $block_type->supports, array( 'spacing', 'blockGap', '__experimentalDefault' ), null );
+ }
+ } else {
+ $block_gap_value = static::get_property_value( $node, array( 'spacing', 'blockGap' ) );
+ }
+
+ // Support split row / column values and concatenate to a shorthand value.
+ if ( is_array( $block_gap_value ) ) {
+ if ( isset( $block_gap_value['top'] ) && isset( $block_gap_value['left'] ) ) {
+ $gap_row = static::get_property_value( $node, array( 'spacing', 'blockGap', 'top' ) );
+ $gap_column = static::get_property_value( $node, array( 'spacing', 'blockGap', 'left' ) );
+ $block_gap_value = $gap_row === $gap_column ? $gap_row : $gap_row . ' ' . $gap_column;
+ } else {
+ // Skip outputting gap value if not all sides are provided.
+ $block_gap_value = null;
+ }
+ }
+
+ // If the block should have custom gap, add the gap styles.
+ if ( null !== $block_gap_value && false !== $block_gap_value && '' !== $block_gap_value ) {
+ foreach ( $layout_definitions as $layout_definition_key => $layout_definition ) {
+ // Allow outputting fallback gap styles for flex layout type when block gap support isn't available.
+ if ( ! $has_block_gap_support && 'flex' !== $layout_definition_key ) {
+ continue;
+ }
+
+ $class_name = sanitize_title( _wp_array_get( $layout_definition, array( 'className' ), false ) );
+ $spacing_rules = _wp_array_get( $layout_definition, array( 'spacingStyles' ), array() );
+
+ if (
+ ! empty( $class_name ) &&
+ ! empty( $spacing_rules )
+ ) {
+ foreach ( $spacing_rules as $spacing_rule ) {
+ $declarations = array();
+ if (
+ isset( $spacing_rule['selector'] ) &&
+ preg_match( $layout_selector_pattern, $spacing_rule['selector'] ) &&
+ ! empty( $spacing_rule['rules'] )
+ ) {
+ // Iterate over each of the styling rules and substitute non-string values such as `null` with the real `blockGap` value.
+ foreach ( $spacing_rule['rules'] as $css_property => $css_value ) {
+ $current_css_value = is_string( $css_value ) ? $css_value : $block_gap_value;
+ if ( static::is_safe_css_declaration( $css_property, $current_css_value ) ) {
+ $declarations[] = array(
+ 'name' => $css_property,
+ 'value' => $current_css_value,
+ );
+ }
+ }
+
+ if ( ! $has_block_gap_support ) {
+ // For fallback gap styles, use lower specificity, to ensure styles do not unintentionally override theme styles.
+ $format = static::ROOT_BLOCK_SELECTOR === $selector ? ':where(.%2$s%3$s)' : ':where(%1$s.%2$s%3$s)';
+ $layout_selector = sprintf(
+ $format,
+ $selector,
+ $class_name,
+ $spacing_rule['selector']
+ );
+ } else {
+ $format = static::ROOT_BLOCK_SELECTOR === $selector ? '%s .%s%s' : '%s.%s%s';
+ $layout_selector = sprintf(
+ $format,
+ $selector,
+ $class_name,
+ $spacing_rule['selector']
+ );
+ }
+ $block_rules .= static::to_ruleset( $layout_selector, $declarations );
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Output base styles.
+ if (
+ static::ROOT_BLOCK_SELECTOR === $selector
+ ) {
+ $valid_display_modes = array( 'block', 'flex', 'grid' );
+ foreach ( $layout_definitions as $layout_definition ) {
+ $class_name = sanitize_title( _wp_array_get( $layout_definition, array( 'className' ), false ) );
+ $base_style_rules = _wp_array_get( $layout_definition, array( 'baseStyles' ), array() );
+
+ if (
+ ! empty( $class_name ) &&
+ ! empty( $base_style_rules )
+ ) {
+ // Output display mode. This requires special handling as `display` is not exposed in `safe_style_css_filter`.
+ if (
+ ! empty( $layout_definition['displayMode'] ) &&
+ is_string( $layout_definition['displayMode'] ) &&
+ in_array( $layout_definition['displayMode'], $valid_display_modes, true )
+ ) {
+ $layout_selector = sprintf(
+ '%s .%s',
+ $selector,
+ $class_name
+ );
+ $block_rules .= static::to_ruleset(
+ $layout_selector,
+ array(
+ array(
+ 'name' => 'display',
+ 'value' => $layout_definition['displayMode'],
+ ),
+ )
+ );
+ }
+
+ foreach ( $base_style_rules as $base_style_rule ) {
+ $declarations = array();
+
+ if (
+ isset( $base_style_rule['selector'] ) &&
+ preg_match( $layout_selector_pattern, $base_style_rule['selector'] ) &&
+ ! empty( $base_style_rule['rules'] )
+ ) {
+ foreach ( $base_style_rule['rules'] as $css_property => $css_value ) {
+ if ( static::is_safe_css_declaration( $css_property, $css_value ) ) {
+ $declarations[] = array(
+ 'name' => $css_property,
+ 'value' => $css_value,
+ );
+ }
+ }
+
+ $layout_selector = sprintf(
+ '%s .%s%s',
+ $selector,
+ $class_name,
+ $base_style_rule['selector']
+ );
+ $block_rules .= static::to_ruleset( $layout_selector, $declarations );
+ }
+ }
+ }
+ }
+ }
+ return $block_rules;
+ }
+
+ /**
</ins><span class="cx" style="display: block; padding: 0 10px"> * Creates new rulesets as classes for each preset value such as:
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * .has-value-color {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1327,15 +1598,17 @@
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @since 5.8.0
</span><span class="cx" style="display: block; padding: 0 10px"> * @since 5.9.0 Added the `$settings` and `$properties` parameters.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @since 6.1.0 Added the `$theme_json` parameter.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @since 6.1.0 Added `$theme_json`, `$selector`, and `$use_root_padding` parameters.
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @param array $styles Styles to process.
- * @param array $settings Theme settings.
- * @param array $properties Properties metadata.
- * @param array $theme_json Theme JSON array.
- * @return array Returns the modified $declarations.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @param array $styles Styles to process.
+ * @param array $settings Theme settings.
+ * @param array $properties Properties metadata.
+ * @param array $theme_json Theme JSON array.
+ * @param string $selector The style block selector.
+ * @param boolean $use_root_padding Whether to add custom properties at root level.
+ * @return array Returns the modified $declarations.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- protected static function compute_style_properties( $styles, $settings = array(), $properties = null, $theme_json = null ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ protected static function compute_style_properties( $styles, $settings = array(), $properties = null, $theme_json = null, $selector = null, $use_root_padding = null ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> if ( null === $properties ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $properties = static::PROPERTIES_METADATA;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1345,9 +1618,24 @@
</span><span class="cx" style="display: block; padding: 0 10px"> return $declarations;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $root_variable_duplicates = array();
+
</ins><span class="cx" style="display: block; padding: 0 10px"> foreach ( $properties as $css_property => $value_path ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $value = static::get_property_value( $styles, $value_path, $theme_json );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( str_starts_with( $css_property, '--wp--style--root--' ) && ( static::ROOT_BLOCK_SELECTOR !== $selector || ! $use_root_padding ) ) {
+ continue;
+ }
+ // Root-level padding styles don't currently support strings with CSS shorthand values.
+ // This may change: https://github.com/WordPress/gutenberg/issues/40132.
+ if ( '--wp--style--root--padding' === $css_property && is_string( $value ) ) {
+ continue;
+ }
+
+ if ( str_starts_with( $css_property, '--wp--style--root--' ) && $use_root_padding ) {
+ $root_variable_duplicates[] = substr( $css_property, strlen( '--wp--style--root--' ) );
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> // Look up protected properties, keyed by value path.
</span><span class="cx" style="display: block; padding: 0 10px"> // Skip protected properties that are explicitly set to `null`.
</span><span class="cx" style="display: block; padding: 0 10px"> if ( is_array( $value_path ) ) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1372,6 +1660,14 @@
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If a variable value is added to the root, the corresponding property should be removed.
+ foreach ( $root_variable_duplicates as $duplicate ) {
+ $discard = array_search( $duplicate, array_column( $declarations, 'name' ), true );
+ if ( is_numeric( $discard ) ) {
+ array_splice( $declarations, $discard, 1 );
+ }
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> return $declarations;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1396,7 +1692,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @return string|array Style property value.
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> protected static function get_property_value( $styles, $path, $theme_json = null ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $value = _wp_array_get( $styles, $path, '' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $value = _wp_array_get( $styles, $path );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /*
</span><span class="cx" style="display: block; padding: 0 10px"> * This converts references to a path to the value at that path
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1429,7 +1725,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ( '' === $value || is_array( $value ) ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( is_array( $value ) ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> return $value;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1622,11 +1918,17 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $duotone_selector = $selectors[ $name ]['duotone'];
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $feature_selectors = null;
+ if ( isset( $selectors[ $name ]['features'] ) ) {
+ $feature_selectors = $selectors[ $name ]['features'];
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> $nodes[] = array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'name' => $name,
</span><span class="cx" style="display: block; padding: 0 10px"> 'path' => array( 'styles', 'blocks', $name ),
</span><span class="cx" style="display: block; padding: 0 10px"> 'selector' => $selector,
</span><span class="cx" style="display: block; padding: 0 10px"> 'duotone' => $duotone_selector,
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'features' => $feature_selectors,
</ins><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> if ( isset( $theme_json['styles']['blocks'][ $name ]['elements'] ) ) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1659,16 +1961,49 @@
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @since 6.1.0
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @param array $block_metadata Meta data about the block to get styles for.
- * @return array Styles for the block.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @param array $block_metadata Metadata about the block to get styles for.
+ *
+ * @return string Styles for the block.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function get_styles_for_block( $block_metadata ) {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $node = _wp_array_get( $this->theme_json, $block_metadata['path'], array() );
+ $use_root_padding = isset( $this->theme_json['settings']['useRootPaddingAwareAlignments'] ) && true === $this->theme_json['settings']['useRootPaddingAwareAlignments'];
+ $selector = $block_metadata['selector'];
+ $settings = _wp_array_get( $this->theme_json, array( 'settings' ) );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $node = _wp_array_get( $this->theme_json, $block_metadata['path'], array() );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /*
+ * Process style declarations for block support features the current
+ * block contains selectors for. Values for a feature with a custom
+ * selector are filtered from the theme.json node before it is
+ * processed as normal.
+ */
+ $feature_declarations = array();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $selector = $block_metadata['selector'];
- $settings = _wp_array_get( $this->theme_json, array( 'settings' ) );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( ! empty( $block_metadata['features'] ) ) {
+ foreach ( $block_metadata['features'] as $feature_name => $feature_selector ) {
+ if ( ! empty( $node[ $feature_name ] ) ) {
+ // Create temporary node containing only the feature data
+ // to leverage existing `compute_style_properties` function.
+ $feature = array( $feature_name => $node[ $feature_name ] );
+ // Generate the feature's declarations only.
+ $new_feature_declarations = static::compute_style_properties( $feature, $settings, null, $this->theme_json );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Merge new declarations with any that already exist for
+ // the feature selector. This may occur when multiple block
+ // support features use the same custom selector.
+ if ( isset( $feature_declarations[ $feature_selector ] ) ) {
+ $feature_declarations[ $feature_selector ] = array_merge( $feature_declarations[ $feature_selector ], $new_feature_declarations );
+ } else {
+ $feature_declarations[ $feature_selector ] = $new_feature_declarations;
+ }
+
+ // Remove the feature from the block's node now the
+ // styles will be included under the feature level selector.
+ unset( $node[ $feature_name ] );
+ }
+ }
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> /*
</span><span class="cx" style="display: block; padding: 0 10px"> * Get a reference to element name from path.
</span><span class="cx" style="display: block; padding: 0 10px"> * $block_metadata['path'] = array( 'styles','elements','link' );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1709,9 +2044,9 @@
</span><span class="cx" style="display: block; padding: 0 10px"> array_key_exists( $current_element, static::VALID_ELEMENT_PSEUDO_SELECTORS )
</span><span class="cx" style="display: block; padding: 0 10px"> && in_array( $pseudo_selector, static::VALID_ELEMENT_PSEUDO_SELECTORS[ $current_element ], true )
</span><span class="cx" style="display: block; padding: 0 10px"> ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $declarations = static::compute_style_properties( $node[ $pseudo_selector ], $settings, null, $this->theme_json );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $declarations = static::compute_style_properties( $node[ $pseudo_selector ], $settings, null, $this->theme_json, $selector, $use_root_padding );
</ins><span class="cx" style="display: block; padding: 0 10px"> } else {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $declarations = static::compute_style_properties( $node, $settings, null, $this->theme_json );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $declarations = static::compute_style_properties( $node, $settings, null, $this->theme_json, $selector, $use_root_padding );
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $block_rules = '';
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1728,18 +2063,6 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- /*
- * Reset default browser margin on the root body element.
- * This is set on the root selector **before** generating the ruleset
- * from the `theme.json`. This is to ensure that if the `theme.json` declares
- * `margin` in its `spacing` declaration for the `body` element then these
- * user-generated values take precedence in the CSS cascade.
- * @link https://github.com/WordPress/gutenberg/issues/36147.
- */
- if ( static::ROOT_BLOCK_SELECTOR === $selector ) {
- $block_rules .= 'body { margin: 0; }';
- }
-
</del><span class="cx" style="display: block; padding: 0 10px"> // 2. Generate and append the rules that use the general selector.
</span><span class="cx" style="display: block; padding: 0 10px"> $block_rules .= static::to_ruleset( $selector, $declarations );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1749,16 +2072,17 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $block_rules .= static::to_ruleset( $selector_duotone, $declarations_duotone );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ( static::ROOT_BLOCK_SELECTOR === $selector ) {
- $block_rules .= '.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }';
- $block_rules .= '.wp-site-blocks > .alignright { float: right; margin-left: 2em; }';
- $block_rules .= '.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // 4. Generate Layout block gap styles.
+ if (
+ static::ROOT_BLOCK_SELECTOR !== $selector &&
+ ! empty( $block_metadata['name'] )
+ ) {
+ $block_rules .= $this->get_layout_styles( $block_metadata );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $has_block_gap_support = _wp_array_get( $this->theme_json, array( 'settings', 'spacing', 'blockGap' ) ) !== null;
- if ( $has_block_gap_support ) {
- $block_rules .= '.wp-site-blocks > * { margin-block-start: 0; margin-block-end: 0; }';
- $block_rules .= '.wp-site-blocks > * + * { margin-block-start: var( --wp--style--block-gap ); }';
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // 5. Generate and append the feature level rulesets.
+ foreach ( $feature_declarations as $feature_selector => $individual_feature_declarations ) {
+ $block_rules .= static::to_ruleset( $feature_selector, $individual_feature_declarations );
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> return $block_rules;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1765,6 +2089,81 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Outputs the CSS for layout rules on the root.
+ *
+ * @since 6.1.0
+ *
+ * @param string $selector The root node selector.
+ * @param array $block_metadata The metadata for the root block.
+ * @return string The additional root rules CSS.
+ */
+ public function get_root_layout_rules( $selector, $block_metadata ) {
+ $css = '';
+ $settings = _wp_array_get( $this->theme_json, array( 'settings' ) );
+ $use_root_padding = isset( $this->theme_json['settings']['useRootPaddingAwareAlignments'] ) && true === $this->theme_json['settings']['useRootPaddingAwareAlignments'];
+
+ /*
+ * Reset default browser margin on the root body element.
+ * This is set on the root selector **before** generating the ruleset
+ * from the `theme.json`. This is to ensure that if the `theme.json` declares
+ * `margin` in its `spacing` declaration for the `body` element then these
+ * user-generated values take precedence in the CSS cascade.
+ * @link https://github.com/WordPress/gutenberg/issues/36147.
+ */
+ $css .= 'body { margin: 0;';
+
+ /*
+ * If there are content and wide widths in theme.json, output them
+ * as custom properties on the body element so all blocks can use them.
+ */
+ if ( isset( $settings['layout']['contentSize'] ) || isset( $settings['layout']['wideSize'] ) ) {
+ $content_size = isset( $settings['layout']['contentSize'] ) ? $settings['layout']['contentSize'] : $settings['layout']['wideSize'];
+ $content_size = static::is_safe_css_declaration( 'max-width', $content_size ) ? $content_size : 'initial';
+ $wide_size = isset( $settings['layout']['wideSize'] ) ? $settings['layout']['wideSize'] : $settings['layout']['contentSize'];
+ $wide_size = static::is_safe_css_declaration( 'max-width', $wide_size ) ? $wide_size : 'initial';
+ $css .= '--wp--style--global--content-size: ' . $content_size . ';';
+ $css .= '--wp--style--global--wide-size: ' . $wide_size . ';';
+ }
+
+ $css .= ' }';
+
+ if ( $use_root_padding ) {
+ // Top and bottom padding are applied to the outer block container.
+ $css .= '.wp-site-blocks { padding-top: var(--wp--style--root--padding-top); padding-bottom: var(--wp--style--root--padding-bottom); }';
+ // Right and left padding are applied to the first container with `.has-global-padding` class.
+ $css .= '.has-global-padding { padding-right: var(--wp--style--root--padding-right); padding-left: var(--wp--style--root--padding-left); }';
+ // Nested containers with `.has-global-padding` class do not get padding.
+ $css .= '.has-global-padding :where(.has-global-padding) { padding-right: 0; padding-left: 0; }';
+ // Alignfull children of the container with left and right padding have negative margins so they can still be full width.
+ $css .= '.has-global-padding > .alignfull { margin-right: calc(var(--wp--style--root--padding-right) * -1); margin-left: calc(var(--wp--style--root--padding-left) * -1); }';
+ // The above rule is negated for alignfull children of nested containers.
+ $css .= '.has-global-padding :where(.has-global-padding) > .alignfull { margin-right: 0; margin-left: 0; }';
+ // Some of the children of alignfull blocks without content width should also get padding: text blocks and non-alignfull container blocks.
+ $css .= '.has-global-padding > .alignfull:where(:not(.has-global-padding)) > :where([class*="wp-block-"]:not(.alignfull):not([class*="__"]),p,h1,h2,h3,h4,h5,h6,ul,ol) { padding-right: var(--wp--style--root--padding-right); padding-left: var(--wp--style--root--padding-left); }';
+ // The above rule also has to be negated for blocks inside nested `.has-global-padding` blocks.
+ $css .= '.has-global-padding :where(.has-global-padding) > .alignfull:where(:not(.has-global-padding)) > :where([class*="wp-block-"]:not(.alignfull):not([class*="__"]),p,h1,h2,h3,h4,h5,h6,ul,ol) { padding-right: 0; padding-left: 0; }';
+ }
+
+ $css .= '.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }';
+ $css .= '.wp-site-blocks > .alignright { float: right; margin-left: 2em; }';
+ $css .= '.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }';
+
+ $block_gap_value = _wp_array_get( $this->theme_json, array( 'styles', 'spacing', 'blockGap' ), '0.5em' );
+ $has_block_gap_support = _wp_array_get( $this->theme_json, array( 'settings', 'spacing', 'blockGap' ) ) !== null;
+ if ( $has_block_gap_support ) {
+ $block_gap_value = static::get_property_value( $this->theme_json, array( 'styles', 'spacing', 'blockGap' ) );
+ $css .= '.wp-site-blocks > * { margin-block-start: 0; margin-block-end: 0; }';
+ $css .= ".wp-site-blocks > * + * { margin-block-start: $block_gap_value; }";
+
+ // For backwards compatibility, ensure the legacy block gap CSS variable is still available.
+ $css .= "$selector { --wp--style--block-gap: $block_gap_value; }";
+ }
+ $css .= $this->get_layout_styles( $block_metadata );
+
+ return $css;
+ }
+
+ /**
</ins><span class="cx" style="display: block; padding: 0 10px"> * For metadata values that can either be booleans or paths to booleans, gets the value.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * ```php
</span></span></pre></div>
<a id="trunksrcwpincludesglobalstylesandsettingsphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/global-styles-and-settings.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/global-styles-and-settings.php 2022-09-14 17:12:20 UTC (rev 54161)
+++ trunk/src/wp-includes/global-styles-and-settings.php 2022-09-14 18:42:04 UTC (rev 54162)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -107,7 +107,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $supports_theme_json = WP_Theme_JSON_Resolver::theme_has_support();
</span><span class="cx" style="display: block; padding: 0 10px"> if ( empty( $types ) && ! $supports_theme_json ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $types = array( 'variables', 'presets' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $types = array( 'variables', 'presets', 'base-layout-styles' );
</ins><span class="cx" style="display: block; padding: 0 10px"> } elseif ( empty( $types ) ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $types = array( 'variables', 'styles', 'presets' );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span></span></pre></div>
<a id="trunksrcwpincludesthemejson"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/theme.json</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/theme.json 2022-09-14 17:12:20 UTC (rev 54161)
+++ trunk/src/wp-includes/theme.json 2022-09-14 18:42:04 UTC (rev 54162)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2,6 +2,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> "version": 2,
</span><span class="cx" style="display: block; padding: 0 10px"> "settings": {
</span><span class="cx" style="display: block; padding: 0 10px"> "appearanceTools": false,
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "useRootPaddingAwareAlignments": false,
</ins><span class="cx" style="display: block; padding: 0 10px"> "border": {
</span><span class="cx" style="display: block; padding: 0 10px"> "color": false,
</span><span class="cx" style="display: block; padding: 0 10px"> "radius": false,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -12,8 +13,8 @@
</span><span class="cx" style="display: block; padding: 0 10px"> "background": true,
</span><span class="cx" style="display: block; padding: 0 10px"> "custom": true,
</span><span class="cx" style="display: block; padding: 0 10px"> "customDuotone": true,
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- "customGradient": true,
- "defaultDuotone": true,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "customGradient": true,
+ "defaultDuotone": true,
</ins><span class="cx" style="display: block; padding: 0 10px"> "defaultGradients": true,
</span><span class="cx" style="display: block; padding: 0 10px"> "defaultPalette": true,
</span><span class="cx" style="display: block; padding: 0 10px"> "duotone": [
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -185,11 +186,158 @@
</span><span class="cx" style="display: block; padding: 0 10px"> ],
</span><span class="cx" style="display: block; padding: 0 10px"> "text": true
</span><span class="cx" style="display: block; padding: 0 10px"> },
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "layout": {
+ "definitions": {
+ "default": {
+ "name": "default",
+ "slug": "flow",
+ "className": "is-layout-flow",
+ "baseStyles": [
+ {
+ "selector": " > .alignleft",
+ "rules": {
+ "float": "left",
+ "margin-inline-start": "0",
+ "margin-inline-end": "2em"
+ }
+ },
+ {
+ "selector": " > .alignright",
+ "rules": {
+ "float": "right",
+ "margin-inline-start": "2em",
+ "margin-inline-end": "0"
+ }
+ },
+ {
+ "selector": " > .aligncenter",
+ "rules": {
+ "margin-left": "auto !important",
+ "margin-right": "auto !important"
+ }
+ }
+ ],
+ "spacingStyles": [
+ {
+ "selector": " > *",
+ "rules": {
+ "margin-block-start": "0",
+ "margin-block-end": "0"
+ }
+ },
+ {
+ "selector": " > * + *",
+ "rules": {
+ "margin-block-start": null,
+ "margin-block-end": "0"
+ }
+ }
+ ]
+ },
+ "constrained": {
+ "name": "constrained",
+ "slug": "constrained",
+ "className": "is-layout-constrained",
+ "baseStyles": [
+ {
+ "selector": " > .alignleft",
+ "rules": {
+ "float": "left",
+ "margin-inline-start": "0",
+ "margin-inline-end": "2em"
+ }
+ },
+ {
+ "selector": " > .alignright",
+ "rules": {
+ "float": "right",
+ "margin-inline-start": "2em",
+ "margin-inline-end": "0"
+ }
+ },
+ {
+ "selector": " > .aligncenter",
+ "rules": {
+ "margin-left": "auto !important",
+ "margin-right": "auto !important"
+ }
+ },
+ {
+ "selector": " > :where(:not(.alignleft):not(.alignright):not(.alignfull))",
+ "rules": {
+ "max-width": "var(--wp--style--global--content-size)",
+ "margin-left": "auto !important",
+ "margin-right": "auto !important"
+ }
+ },
+ {
+ "selector": " > .alignwide",
+ "rules": {
+ "max-width": "var(--wp--style--global--wide-size)"
+ }
+ }
+ ],
+ "spacingStyles": [
+ {
+ "selector": " > *",
+ "rules": {
+ "margin-block-start": "0",
+ "margin-block-end": "0"
+ }
+ },
+ {
+ "selector": " > * + *",
+ "rules": {
+ "margin-block-start": null,
+ "margin-block-end": "0"
+ }
+ }
+ ]
+ },
+ "flex": {
+ "name": "flex",
+ "slug": "flex",
+ "className": "is-layout-flex",
+ "displayMode": "flex",
+ "baseStyles": [
+ {
+ "selector": "",
+ "rules": {
+ "flex-wrap": "wrap",
+ "align-items": "center"
+ }
+ },
+ {
+ "selector": " > *",
+ "rules": {
+ "margin": "0"
+ }
+ }
+ ],
+ "spacingStyles": [
+ {
+ "selector": "",
+ "rules": {
+ "gap": null
+ }
+ }
+ ]
+ }
+ }
+ },
</ins><span class="cx" style="display: block; padding: 0 10px"> "spacing": {
</span><span class="cx" style="display: block; padding: 0 10px"> "blockGap": null,
</span><span class="cx" style="display: block; padding: 0 10px"> "margin": false,
</span><span class="cx" style="display: block; padding: 0 10px"> "padding": false,
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- "units": [ "px", "em", "rem", "vh", "vw", "%" ]
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "customSpacingSize": true,
+ "units": [ "px", "em", "rem", "vh", "vw", "%" ],
+ "spacingScale": {
+ "operator": "*",
+ "increment": 1.5,
+ "steps": 7,
+ "mediumStep": 1.5,
+ "unit": "rem"
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> },
</span><span class="cx" style="display: block; padding: 0 10px"> "typography": {
</span><span class="cx" style="display: block; padding: 0 10px"> "customFontSize": true,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -240,6 +388,39 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> },
</span><span class="cx" style="display: block; padding: 0 10px"> "styles": {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- "spacing": { "blockGap": "24px" }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "elements": {
+ "button": {
+ "color": {
+ "text": "#fff",
+ "background": "#32373c"
+ },
+ "spacing": {
+ "padding": "calc(0.667em + 2px) calc(1.333em + 2px)"
+ },
+ "typography": {
+ "fontSize": "inherit",
+ "fontFamily": "inherit",
+ "lineHeight": "inherit",
+ "textDecoration": "none"
+ },
+ "border": {
+ "width": "0"
+ }
+ },
+ "link": {
+ "typography": {
+ "textDecoration": "underline"
+ }
+ }
+ },
+ "spacing": {
+ "blockGap": "24px",
+ "padding": {
+ "top": "0px",
+ "right": "0px",
+ "bottom": "0px",
+ "left": "0px"
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span></span></pre></div>
<a id="trunksrcwpincludesthemephp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/theme.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/theme.php 2022-09-14 17:12:20 UTC (rev 54161)
+++ trunk/src/wp-includes/theme.php 2022-09-14 18:42:04 UTC (rev 54162)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -4027,6 +4027,13 @@
</span><span class="cx" style="display: block; padding: 0 10px"> )
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px"> register_theme_feature(
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'disable-layout-styles',
+ array(
+ 'description' => __( 'Whether the theme disables generated layout styles.' ),
+ 'show_in_rest' => true,
+ )
+ );
+ register_theme_feature(
</ins><span class="cx" style="display: block; padding: 0 10px"> 'editor-color-palette',
</span><span class="cx" style="display: block; padding: 0 10px"> array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'type' => 'array',
</span></span></pre></div>
<a id="trunktestsphpunittestsblockseditorphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/tests/blocks/editor.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/blocks/editor.php 2022-09-14 17:12:20 UTC (rev 54161)
+++ trunk/tests/phpunit/tests/blocks/editor.php 2022-09-14 18:42:04 UTC (rev 54162)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -202,7 +202,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> public function test_get_default_block_editor_settings() {
</span><span class="cx" style="display: block; padding: 0 10px"> $settings = get_default_block_editor_settings();
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $this->assertCount( 18, $settings );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $this->assertCount( 19, $settings );
</ins><span class="cx" style="display: block; padding: 0 10px"> $this->assertFalse( $settings['alignWide'] );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertIsArray( $settings['allowedMimeTypes'] );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertTrue( $settings['allowedBlockTypes'] );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -249,6 +249,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertFalse( $settings['disableCustomColors'] );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertFalse( $settings['disableCustomFontSizes'] );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertFalse( $settings['disableCustomGradients'] );
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $this->assertFalse( $settings['disableLayoutStyles'] );
</ins><span class="cx" style="display: block; padding: 0 10px"> $this->assertFalse( $settings['enableCustomLineHeight'] );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertFalse( $settings['enableCustomSpacing'] );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertFalse( $settings['enableCustomUnits'] );
</span></span></pre></div>
<a id="trunktestsphpunittestsrestapirestthemescontrollerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/tests/rest-api/rest-themes-controller.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/rest-api/rest-themes-controller.php 2022-09-14 17:12:20 UTC (rev 54161)
+++ trunk/tests/phpunit/tests/rest-api/rest-themes-controller.php 2022-09-14 18:42:04 UTC (rev 54162)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -396,6 +396,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertArrayHasKey( 'dark-editor-style', $theme_supports );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertArrayHasKey( 'disable-custom-font-sizes', $theme_supports );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertArrayHasKey( 'disable-custom-gradients', $theme_supports );
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $this->assertArrayHasKey( 'disable-layout-styles', $theme_supports );
</ins><span class="cx" style="display: block; padding: 0 10px"> $this->assertArrayHasKey( 'editor-color-palette', $theme_supports );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertArrayHasKey( 'editor-font-sizes', $theme_supports );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertArrayHasKey( 'editor-gradient-presets', $theme_supports );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -406,7 +407,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertArrayHasKey( 'responsive-embeds', $theme_supports );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertArrayHasKey( 'title-tag', $theme_supports );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertArrayHasKey( 'wp-block-styles', $theme_supports );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $this->assertCount( 21, $theme_supports );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $this->assertCount( 22, $theme_supports );
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span></span></pre></div>
<a id="trunktestsphpunitteststhemewpThemeJsonphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/tests/theme/wpThemeJson.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/theme/wpThemeJson.php 2022-09-14 17:12:20 UTC (rev 54161)
+++ trunk/tests/phpunit/tests/theme/wpThemeJson.php 2022-09-14 18:42:04 UTC (rev 54162)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -423,7 +423,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> )
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $expected = 'body { margin: 0; }body{--wp--style--block-gap: 1em;}.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }.wp-site-blocks > * { margin-block-start: 0; margin-block-end: 0; }.wp-site-blocks > * + * { margin-block-start: var( --wp--style--block-gap ); }';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $expected = 'body { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }.wp-site-blocks > * { margin-block-start: 0; margin-block-end: 0; }.wp-site-blocks > * + * { margin-block-start: 1em; }body { --wp--style--block-gap: 1em; }';
</ins><span class="cx" style="display: block; padding: 0 10px"> $this->assertSame( $expected, $theme_json->get_stylesheet() );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles' ) ) );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -544,6 +544,9 @@
</span><span class="cx" style="display: block; padding: 0 10px"> ),
</span><span class="cx" style="display: block; padding: 0 10px"> ),
</span><span class="cx" style="display: block; padding: 0 10px"> ),
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'spacing' => array(
+ 'blockGap' => '24px',
+ ),
</ins><span class="cx" style="display: block; padding: 0 10px"> ),
</span><span class="cx" style="display: block; padding: 0 10px"> 'misc' => 'value',
</span><span class="cx" style="display: block; padding: 0 10px"> )
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -550,7 +553,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $variables = 'body{--wp--preset--color--grey: grey;--wp--preset--font-family--small: 14px;--wp--preset--font-family--big: 41px;}.wp-block-group{--wp--custom--base-font: 16;--wp--custom--line-height--small: 1.2;--wp--custom--line-height--medium: 1.4;--wp--custom--line-height--large: 1.8;}';
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $styles = 'body { margin: 0; }body{color: var(--wp--preset--color--grey);}.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }a:where(:not(.wp-element-button)){background-color: #333;color: #111;}.wp-block-group{border-radius: 10px;padding: 24px;}.wp-block-group a:where(:not(.wp-element-button)){color: #111;}h1,h2,h3,h4,h5,h6{color: #123456;}h1 a:where(:not(.wp-element-button)),h2 a:where(:not(.wp-element-button)),h3 a:where(:not(.wp-element-button)),h4 a:where(:not(.wp-element-button)),h5 a:where(:not(.wp-element-button)),h6 a:where(:not(.wp-element-button)){background-color: #333;color: #111;font-size: 60px;}.wp-block-post-date{color: #123456;}.wp-block-post-date a:where(:not(.wp-element-button)){bac
kground-color: #777;color: #555;}.wp-block-image{border-top-left-radius: 10px;border-bottom-right-radius: 1em;margin-bottom: 30px;}';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $styles = 'body { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }body{color: var(--wp--preset--color--grey);}a:where(:not(.wp-element-button)){background-color: #333;color: #111;}.wp-block-group{border-radius: 10px;padding: 24px;}.wp-block-group a:where(:not(.wp-element-button)){color: #111;}h1,h2,h3,h4,h5,h6{color: #123456;}h1 a:where(:not(.wp-element-button)),h2 a:where(:not(.wp-element-button)),h3 a:where(:not(.wp-element-button)),h4 a:where(:not(.wp-element-button)),h5 a:where(:not(.wp-element-button)),h6 a:where(:not(.wp-element-button)){background-color: #333;color: #111;font-size: 60px;}.wp-block-post-date{color: #123456;}.wp-block-post-date a:where(:not(.wp-element-button)){back
ground-color: #777;color: #555;}.wp-block-image{border-top-left-radius: 10px;border-bottom-right-radius: 1em;margin-bottom: 30px;}';
</ins><span class="cx" style="display: block; padding: 0 10px"> $presets = '.has-grey-color{color: var(--wp--preset--color--grey) !important;}.has-grey-background-color{background-color: var(--wp--preset--color--grey) !important;}.has-grey-border-color{border-color: var(--wp--preset--color--grey) !important;}.has-small-font-family{font-family: var(--wp--preset--font-family--small) !important;}.has-big-font-family{font-family: var(--wp--preset--font-family--big) !important;}';
</span><span class="cx" style="display: block; padding: 0 10px"> $all = $variables . $styles . $presets;
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertSame( $all, $theme_json->get_stylesheet() );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2675,8 +2678,8 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 'blocks' => array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'core/group' => array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'spacing' => array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'margin' => 'valid value',
- 'blockGap' => 'invalid value',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'margin' => 'valid value',
+ 'display' => 'none',
</ins><span class="cx" style="display: block; padding: 0 10px"> ),
</span><span class="cx" style="display: block; padding: 0 10px"> ),
</span><span class="cx" style="display: block; padding: 0 10px"> ),
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2989,7 +2992,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> )
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $expected = 'body { margin: 0; }body{background-color: #ffffff;color: #000000;}.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }.wp-element-button, .wp-block-button__link{background-color: #000000;color: #ffffff;}';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $expected = 'body { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }body{background-color: #ffffff;color: #000000;}.wp-element-button, .wp-block-button__link{background-color: #000000;color: #ffffff;}';
</ins><span class="cx" style="display: block; padding: 0 10px"> $this->assertSame( $expected, $theme_json->get_stylesheet() );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3021,7 +3024,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> )
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $expected = 'body { margin: 0; }body{background-color: #ffffff;}.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }.wp-element-button, .wp-block-button__link{color: #ffffff;}';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $expected = 'body { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }body{background-color: #ffffff;}.wp-element-button, .wp-block-button__link{color: #ffffff;}';
</ins><span class="cx" style="display: block; padding: 0 10px"> $this->assertSame( $expected, $theme_json->get_stylesheet() );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3053,7 +3056,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> )
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $expected = 'body { margin: 0; }body{background-color: #ffffff;color: #ffffff;}.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }.wp-element-button, .wp-block-button__link{color: #ffffff;}';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $expected = 'body { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }body{background-color: #ffffff;color: #ffffff;}.wp-element-button, .wp-block-button__link{color: #ffffff;}';
</ins><span class="cx" style="display: block; padding: 0 10px"> $this->assertSame( $expected, $theme_json->get_stylesheet() );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3077,8 +3080,417 @@
</span><span class="cx" style="display: block; padding: 0 10px"> )
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $expected = 'body { margin: 0; }body{background-color: #ffffff;}.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $expected = 'body { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }body{background-color: #ffffff;}';
</ins><span class="cx" style="display: block; padding: 0 10px"> $this->assertSame( $expected, $theme_json->get_stylesheet() );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+ /**
+ * @dataProvider data_get_layout_definitions
+ *
+ * @ticket 56467
+ *
+ * @param array $layout_definitions Layout definitions as stored in core theme.json.
+ */
+ public function test_get_stylesheet_generates_layout_styles( $layout_definitions ) {
+ $theme_json = new WP_Theme_JSON(
+ array(
+ 'version' => WP_Theme_JSON::LATEST_SCHEMA,
+ 'settings' => array(
+ 'layout' => array(
+ 'definitions' => $layout_definitions,
+ ),
+ 'spacing' => array(
+ 'blockGap' => true,
+ ),
+ ),
+ 'styles' => array(
+ 'spacing' => array(
+ 'blockGap' => '1em',
+ ),
+ ),
+ ),
+ 'default'
+ );
+
+ // Results also include root site blocks styles.
+ $this->assertSame(
+ 'body { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }.wp-site-blocks > * { margin-block-start: 0; margin-block-end: 0; }.wp-site-blocks > * + * { margin-block-start: 1em; }body { --wp--style--block-gap: 1em; }body .is-layout-flow > *{margin-block-start: 0;margin-block-end: 0;}body .is-layout-flow > * + *{margin-block-start: 1em;margin-block-end: 0;}body .is-layout-flex{gap: 1em;}body .is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}body .is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}body .is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}body .is-layout-flex{display: flex;}body .is-layout-flex{flex-wrap: wrap;align-items: center;}',
+ $theme_json->get_stylesheet( array( 'styles' ) )
+ );
+ }
+
+ /**
+ * @dataProvider data_get_layout_definitions
+ *
+ * @ticket 56467
+ *
+ * @param array $layout_definitions Layout definitions as stored in core theme.json.
+ */
+ public function test_get_stylesheet_generates_layout_styles_with_spacing_presets( $layout_definitions ) {
+ $theme_json = new WP_Theme_JSON(
+ array(
+ 'version' => WP_Theme_JSON::LATEST_SCHEMA,
+ 'settings' => array(
+ 'layout' => array(
+ 'definitions' => $layout_definitions,
+ ),
+ 'spacing' => array(
+ 'blockGap' => true,
+ ),
+ ),
+ 'styles' => array(
+ 'spacing' => array(
+ 'blockGap' => 'var:preset|spacing|60',
+ ),
+ ),
+ ),
+ 'default'
+ );
+
+ // Results also include root site blocks styles.
+ $this->assertSame(
+ 'body { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }.wp-site-blocks > * { margin-block-start: 0; margin-block-end: 0; }.wp-site-blocks > * + * { margin-block-start: var(--wp--preset--spacing--60); }body { --wp--style--block-gap: var(--wp--preset--spacing--60); }body .is-layout-flow > *{margin-block-start: 0;margin-block-end: 0;}body .is-layout-flow > * + *{margin-block-start: var(--wp--preset--spacing--60);margin-block-end: 0;}body .is-layout-flex{gap: var(--wp--preset--spacing--60);}body .is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}body .is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}body .is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !importa
nt;}body .is-layout-flex{display: flex;}body .is-layout-flex{flex-wrap: wrap;align-items: center;}',
+ $theme_json->get_stylesheet( array( 'styles' ) )
+ );
+ }
+
+ /**
+ * @dataProvider data_get_layout_definitions
+ *
+ * @ticket 56467
+ *
+ * @param array $layout_definitions Layout definitions as stored in core theme.json.
+ */
+ public function test_get_stylesheet_generates_fallback_gap_layout_styles( $layout_definitions ) {
+ $theme_json = new WP_Theme_JSON(
+ array(
+ 'version' => WP_Theme_JSON::LATEST_SCHEMA,
+ 'settings' => array(
+ 'layout' => array(
+ 'definitions' => $layout_definitions,
+ ),
+ 'spacing' => array(
+ 'blockGap' => null,
+ ),
+ ),
+ 'styles' => array(
+ 'spacing' => array(
+ 'blockGap' => '1em',
+ ),
+ ),
+ ),
+ 'default'
+ );
+ $stylesheet = $theme_json->get_stylesheet( array( 'styles' ) );
+
+ // Results also include root site blocks styles.
+ $this->assertSame(
+ 'body { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.is-layout-flex){gap: 0.5em;}body .is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}body .is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}body .is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}body .is-layout-flex{display: flex;}body .is-layout-flex{flex-wrap: wrap;align-items: center;}',
+ $stylesheet
+ );
+ }
+
+ /**
+ * @dataProvider data_get_layout_definitions
+ *
+ * @ticket 56467
+ *
+ * @param array $layout_definitions Layout definitions as stored in core theme.json.
+ */
+ public function test_get_stylesheet_generates_base_fallback_gap_layout_styles( $layout_definitions ) {
+ $theme_json = new WP_Theme_JSON(
+ array(
+ 'version' => WP_Theme_JSON::LATEST_SCHEMA,
+ 'settings' => array(
+ 'layout' => array(
+ 'definitions' => $layout_definitions,
+ ),
+ 'spacing' => array(
+ 'blockGap' => null,
+ ),
+ ),
+ ),
+ 'default'
+ );
+ $stylesheet = $theme_json->get_stylesheet( array( 'base-layout-styles' ) );
+
+ // Note the `base-layout-styles` includes a fallback gap for the Columns block for backwards compatibility.
+ $this->assertSame(
+ ':where(.is-layout-flex){gap: 0.5em;}body .is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}body .is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}body .is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}body .is-layout-flex{display: flex;}body .is-layout-flex{flex-wrap: wrap;align-items: center;}:where(.wp-block-columns.is-layout-flex){gap: 2em;}',
+ $stylesheet
+ );
+ }
+
+ /**
+ * @dataProvider data_get_layout_definitions
+ *
+ * @ticket 56467
+ *
+ * @param array $layout_definitions Layout definitions as stored in core theme.json.
+ */
+ public function test_get_stylesheet_skips_layout_styles( $layout_definitions ) {
+ add_theme_support( 'disable-layout-styles' );
+ $theme_json = new WP_Theme_JSON(
+ array(
+ 'version' => WP_Theme_JSON::LATEST_SCHEMA,
+ 'settings' => array(
+ 'layout' => array(
+ 'definitions' => $layout_definitions,
+ ),
+ 'spacing' => array(
+ 'blockGap' => null,
+ ),
+ ),
+ ),
+ 'default'
+ );
+ $stylesheet = $theme_json->get_stylesheet( array( 'base-layout-styles' ) );
+ remove_theme_support( 'disable-layout-styles' );
+
+ // All Layout styles should be skipped.
+ $this->assertSame(
+ '',
+ $stylesheet
+ );
+ }
+
+ /**
+ * @dataProvider data_get_layout_definitions
+ *
+ * @ticket 56467
+ *
+ * @param array $layout_definitions Layout definitions as stored in core theme.json.
+ */
+ public function test_get_stylesheet_generates_valid_block_gap_values_and_skips_null_or_false_values( $layout_definitions ) {
+ $theme_json = new WP_Theme_JSON(
+ array(
+ 'version' => WP_Theme_JSON::LATEST_SCHEMA,
+ 'settings' => array(
+ 'layout' => array(
+ 'definitions' => $layout_definitions,
+ ),
+ 'spacing' => array(
+ 'blockGap' => true,
+ ),
+ ),
+ 'styles' => array(
+ 'spacing' => array(
+ 'blockGap' => '1rem',
+ ),
+ 'blocks' => array(
+ 'core/post-content' => array(
+ 'color' => array(
+ 'text' => 'gray', // This value should not render block layout styles.
+ ),
+ ),
+ 'core/social-links' => array(
+ 'spacing' => array(
+ 'blockGap' => '0', // This value should render block layout gap as zero.
+ ),
+ ),
+ 'core/buttons' => array(
+ 'spacing' => array(
+ 'blockGap' => 0, // This value should render block layout gap as zero.
+ ),
+ ),
+ 'core/columns' => array(
+ 'spacing' => array(
+ 'blockGap' => false, // This value should be ignored. The block will use the global layout value.
+ ),
+ ),
+ ),
+ ),
+ ),
+ 'default'
+ );
+
+ $this->assertEquals(
+ 'body { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }.wp-site-blocks > * { margin-block-start: 0; margin-block-end: 0; }.wp-site-blocks > * + * { margin-block-start: 1rem; }body { --wp--style--block-gap: 1rem; }body .is-layout-flow > *{margin-block-start: 0;margin-block-end: 0;}body .is-layout-flow > * + *{margin-block-start: 1rem;margin-block-end: 0;}body .is-layout-flex{gap: 1rem;}body .is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}body .is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}body .is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}body .is-layout-flex{display: flex;}body .is-layout-flex{flex-wrap: wrap;align-items: center;}.wp-bl
ock-post-content{color: gray;}.wp-block-social-links.is-layout-flow > *{margin-block-start: 0;margin-block-end: 0;}.wp-block-social-links.is-layout-flow > * + *{margin-block-start: 0;margin-block-end: 0;}.wp-block-social-links.is-layout-flex{gap: 0;}.wp-block-buttons.is-layout-flow > *{margin-block-start: 0;margin-block-end: 0;}.wp-block-buttons.is-layout-flow > * + *{margin-block-start: 0;margin-block-end: 0;}.wp-block-buttons.is-layout-flex{gap: 0;}',
+ $theme_json->get_stylesheet()
+ );
+ }
+
+ /**
+ * Data provider for layout tests.
+ *
+ * @ticket 56467
+ *
+ * @return array
+ */
+ public function data_get_layout_definitions() {
+ return array(
+ 'layout definitions' => array(
+ array(
+ 'default' => array(
+ 'name' => 'default',
+ 'slug' => 'flow',
+ 'className' => 'is-layout-flow',
+ 'baseStyles' => array(
+ array(
+ 'selector' => ' > .alignleft',
+ 'rules' => array(
+ 'float' => 'left',
+ 'margin-inline-start' => '0',
+ 'margin-inline-end' => '2em',
+ ),
+ ),
+ array(
+ 'selector' => ' > .alignright',
+ 'rules' => array(
+ 'float' => 'right',
+ 'margin-inline-start' => '2em',
+ 'margin-inline-end' => '0',
+ ),
+ ),
+ array(
+ 'selector' => ' > .aligncenter',
+ 'rules' => array(
+ 'margin-left' => 'auto !important',
+ 'margin-right' => 'auto !important',
+ ),
+ ),
+ ),
+ 'spacingStyles' => array(
+ array(
+ 'selector' => ' > *',
+ 'rules' => array(
+ 'margin-block-start' => '0',
+ 'margin-block-end' => '0',
+ ),
+ ),
+ array(
+ 'selector' => ' > * + *',
+ 'rules' => array(
+ 'margin-block-start' => null,
+ 'margin-block-end' => '0',
+ ),
+ ),
+ ),
+ ),
+ 'flex' => array(
+ 'name' => 'flex',
+ 'slug' => 'flex',
+ 'className' => 'is-layout-flex',
+ 'displayMode' => 'flex',
+ 'baseStyles' => array(
+ array(
+ 'selector' => '',
+ 'rules' => array(
+ 'flex-wrap' => 'wrap',
+ 'align-items' => 'center',
+ ),
+ ),
+ ),
+ 'spacingStyles' => array(
+ array(
+ 'selector' => '',
+ 'rules' => array(
+ 'gap' => null,
+ ),
+ ),
+ ),
+ ),
+ ),
+ ),
+ );
+ }
+
+ /**
+ * @ticket 56467
+ */
+ function test_get_styles_for_block_with_padding_aware_alignments() {
+ $theme_json = new WP_Theme_JSON(
+ array(
+ 'version' => 2,
+ 'styles' => array(
+ 'spacing' => array(
+ 'padding' => array(
+ 'top' => '10px',
+ 'right' => '12px',
+ 'bottom' => '10px',
+ 'left' => '12px',
+ ),
+ ),
+ ),
+ 'settings' => array(
+ 'useRootPaddingAwareAlignments' => true,
+ ),
+ )
+ );
+
+ $metadata = array(
+ 'path' => array(
+ '0' => 'styles',
+ ),
+ 'selector' => 'body',
+ );
+
+ $expected = 'body { margin: 0; }.wp-site-blocks { padding-top: var(--wp--style--root--padding-top); padding-bottom: var(--wp--style--root--padding-bottom); }.has-global-padding { padding-right: var(--wp--style--root--padding-right); padding-left: var(--wp--style--root--padding-left); }.has-global-padding :where(.has-global-padding) { padding-right: 0; padding-left: 0; }.has-global-padding > .alignfull { margin-right: calc(var(--wp--style--root--padding-right) * -1); margin-left: calc(var(--wp--style--root--padding-left) * -1); }.has-global-padding :where(.has-global-padding) > .alignfull { margin-right: 0; margin-left: 0; }.has-global-padding > .alignfull:where(:not(.has-global-padding)) > :where([class*="wp-block-"]:not(.alignfull):not([class*="__"]),p,h1,h2,h3,h4,h5,h6,ul,ol) { padding-right: var(--wp--style--root--padding-right); padding-left: var(--wp--style--root--padding-left); }.has-global-padding :where(.has-global-padding) > .alignful
l:where(:not(.has-global-padding)) > :where([class*="wp-block-"]:not(.alignfull):not([class*="__"]),p,h1,h2,h3,h4,h5,h6,ul,ol) { padding-right: 0; padding-left: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }body{--wp--style--root--padding-top: 10px;--wp--style--root--padding-right: 12px;--wp--style--root--padding-bottom: 10px;--wp--style--root--padding-left: 12px;}';
+ $root_rules = $theme_json->get_root_layout_rules( WP_Theme_JSON::ROOT_BLOCK_SELECTOR, $metadata );
+ $style_rules = $theme_json->get_styles_for_block( $metadata );
+ $this->assertSame( $expected, $root_rules . $style_rules );
+ }
+
+ /**
+ * @ticket 56467
+ */
+ function test_get_styles_for_block_without_padding_aware_alignments() {
+ $theme_json = new WP_Theme_JSON(
+ array(
+ 'version' => 2,
+ 'styles' => array(
+ 'spacing' => array(
+ 'padding' => array(
+ 'top' => '10px',
+ 'right' => '12px',
+ 'bottom' => '10px',
+ 'left' => '12px',
+ ),
+ ),
+ ),
+ )
+ );
+
+ $metadata = array(
+ 'path' => array(
+ '0' => 'styles',
+ ),
+ 'selector' => 'body',
+ );
+
+ $expected = 'body { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }body{padding-top: 10px;padding-right: 12px;padding-bottom: 10px;padding-left: 12px;}';
+ $root_rules = $theme_json->get_root_layout_rules( WP_Theme_JSON::ROOT_BLOCK_SELECTOR, $metadata );
+ $style_rules = $theme_json->get_styles_for_block( $metadata );
+ $this->assertSame( $expected, $root_rules . $style_rules );
+ }
+
+ /**
+ * @ticket 56467
+ */
+ function test_get_styles_for_block_with_content_width() {
+ $theme_json = new WP_Theme_JSON(
+ array(
+ 'version' => 2,
+ 'settings' => array(
+ 'layout' => array(
+ 'contentSize' => '800px',
+ 'wideSize' => '1000px',
+ ),
+ ),
+ )
+ );
+
+ $metadata = array(
+ 'path' => array(
+ '0' => 'settings',
+ ),
+ 'selector' => 'body',
+ );
+
+ $expected = 'body { margin: 0;--wp--style--global--content-size: 800px;--wp--style--global--wide-size: 1000px; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }';
+ $root_rules = $theme_json->get_root_layout_rules( WP_Theme_JSON::ROOT_BLOCK_SELECTOR, $metadata );
+ $style_rules = $theme_json->get_styles_for_block( $metadata );
+ $this->assertSame( $expected, $root_rules . $style_rules );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span></span></pre>
</div>
</div>
</body>
</html>