<!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>[52049] trunk: Update theme.json classes for WordPress 5.9.</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/52049">52049</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/52049","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>jorgefilipecosta</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2021-11-08 19:18:39 +0000 (Mon, 08 Nov 2021)</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'>Update theme.json classes for WordPress 5.9.
This commit ports to core the changes to the classes that deal with theme.json code.
See <a href="https://core.trac.wordpress.org/ticket/54336">#54336</a>.
Props oandregal, spacedmonkey, noisysocks, hellofromtonya, youknowriad.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunksrcwpincludesblockeditorphp">trunk/src/wp-includes/block-editor.php</a></li>
<li><a href="#trunksrcwpincludesblocksupportsduotonephp">trunk/src/wp-includes/block-supports/duotone.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="#trunksrcwpincludesdefaultfiltersphp">trunk/src/wp-includes/default-filters.php</a></li>
<li><a href="#trunksrcwpincludesksesphp">trunk/src/wp-includes/kses.php</a></li>
<li><a href="#trunksrcwpincludesscriptloaderphp">trunk/src/wp-includes/script-loader.php</a></li>
<li><a href="#trunksrcwpincludesthemei18njson">trunk/src/wp-includes/theme-i18n.json</a></li>
<li><a href="#trunksrcwpincludesthemejson">trunk/src/wp-includes/theme.json</a></li>
<li><a href="#trunksrcwpsettingsphp">trunk/src/wp-settings.php</a></li>
<li><a href="#trunktestsphpunitdatalanguagesthemesblockthemepl_PLpo">trunk/tests/phpunit/data/languages/themes/block-theme-pl_PL.po</a></li>
<li><a href="#trunktestsphpunitdatathemedir1blockthemethemejson">trunk/tests/phpunit/data/themedir1/block-theme/theme.json</a></li>
<li><a href="#trunktestsphpunitteststhemethemeDirphp">trunk/tests/phpunit/tests/theme/themeDir.php</a></li>
<li><a href="#trunktestsphpunitteststhemewpThemeJsonphp">trunk/tests/phpunit/tests/theme/wpThemeJson.php</a></li>
<li><a href="#trunktestsphpunitteststhemewpThemeJsonResolverphp">trunk/tests/phpunit/tests/theme/wpThemeJsonResolver.php</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#trunksrcwpincludesclasswpthemejsonschemaphp">trunk/src/wp-includes/class-wp-theme-json-schema.php</a></li>
<li>trunk/tests/phpunit/data/themedir1/block-theme-child/</li>
<li><a href="#trunktestsphpunitdatathemedir1blockthemechildstylecss">trunk/tests/phpunit/data/themedir1/block-theme-child/style.css</a></li>
<li><a href="#trunktestsphpunitdatathemedir1blockthemechildthemejson">trunk/tests/phpunit/data/themedir1/block-theme-child/theme.json</a></li>
<li><a href="#trunktestsphpunitteststhemewpThemeJsonSchemaphp">trunk/tests/phpunit/tests/theme/wpThemeJsonSchema.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 2021-11-08 17:07:49 UTC (rev 52048)
+++ trunk/src/wp-includes/block-editor.php 2021-11-08 19:18:39 UTC (rev 52049)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -303,15 +303,15 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $custom_settings
</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">- $theme_json = WP_Theme_JSON_Resolver::get_merged_data( $editor_settings );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $theme_json = WP_Theme_JSON_Resolver::get_merged_data();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> if ( WP_Theme_JSON_Resolver::theme_has_support() ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $editor_settings['styles'][] = array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'css' => $theme_json->get_stylesheet( 'block_styles' ),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'css' => $theme_json->get_stylesheet( array( 'styles', 'presets' ) ),
</ins><span class="cx" style="display: block; padding: 0 10px"> '__unstableType' => 'globalStyles',
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px"> $editor_settings['styles'][] = array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'css' => $theme_json->get_stylesheet( 'css_variables' ),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'css' => $theme_json->get_stylesheet( array( 'variables' ) ),
</ins><span class="cx" style="display: block; padding: 0 10px"> '__experimentalNoWrapper' => true,
</span><span class="cx" style="display: block; padding: 0 10px"> '__unstableType' => 'globalStyles',
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -358,17 +358,17 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $editor_settings['disableCustomFontSizes'] = ! $editor_settings['__experimentalFeatures']['typography']['customFontSize'];
</span><span class="cx" style="display: block; padding: 0 10px"> unset( $editor_settings['__experimentalFeatures']['typography']['customFontSize'] );
</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 ( isset( $editor_settings['__experimentalFeatures']['typography']['customLineHeight'] ) ) {
- $editor_settings['enableCustomLineHeight'] = $editor_settings['__experimentalFeatures']['typography']['customLineHeight'];
- unset( $editor_settings['__experimentalFeatures']['typography']['customLineHeight'] );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( isset( $editor_settings['__experimentalFeatures']['typography']['lineHeight'] ) ) {
+ $editor_settings['enableCustomLineHeight'] = $editor_settings['__experimentalFeatures']['typography']['lineHeight'];
+ unset( $editor_settings['__experimentalFeatures']['typography']['lineHeight'] );
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> if ( isset( $editor_settings['__experimentalFeatures']['spacing']['units'] ) ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $editor_settings['enableCustomUnits'] = $editor_settings['__experimentalFeatures']['spacing']['units'];
</span><span class="cx" style="display: block; padding: 0 10px"> unset( $editor_settings['__experimentalFeatures']['spacing']['units'] );
</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 ( isset( $editor_settings['__experimentalFeatures']['spacing']['customPadding'] ) ) {
- $editor_settings['enableCustomSpacing'] = $editor_settings['__experimentalFeatures']['spacing']['customPadding'];
- unset( $editor_settings['__experimentalFeatures']['spacing']['customPadding'] );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( isset( $editor_settings['__experimentalFeatures']['spacing']['padding'] ) ) {
+ $editor_settings['enableCustomSpacing'] = $editor_settings['__experimentalFeatures']['spacing']['padding'];
+ unset( $editor_settings['__experimentalFeatures']['spacing']['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"> /**
</span></span></pre></div>
<a id="trunksrcwpincludesblocksupportsduotonephp"></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-supports/duotone.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/block-supports/duotone.php 2021-11-08 17:07:49 UTC (rev 52048)
+++ trunk/src/wp-includes/block-supports/duotone.php 2021-11-08 19:18:39 UTC (rev 52049)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -70,6 +70,28 @@
</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">+ * Direct port of tinycolor's boundAlpha function to maintain consistency with
+ * how tinycolor works.
+ *
+ * @see https://github.com/bgrins/TinyColor
+ *
+ * @since 5.9.0
+ * @access private
+ *
+ * @param mixed $n Number of unknown type.
+ * @return float Value in the range [0,1].
+ */
+function _wp_tinycolor_bound_alpha( $n ) {
+ if ( is_numeric( $n ) ) {
+ $n = (float) $n;
+ if ( $n >= 0 && $n <= 1 ) {
+ return $n;
+ }
+ }
+ return 1;
+}
+
+/**
</ins><span class="cx" style="display: block; padding: 0 10px"> * Round and convert values of an RGB object.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Direct port of TinyColor's function, lightly simplified to maintain
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -170,8 +192,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"> * Parses hex, hsl, and rgb CSS strings using the same regex as TinyColor v1.4.2
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * used in the JavaScript. Only colors output from react-color are implemented
- * and the alpha value is ignored as it is not used in duotone.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * used in the JavaScript. Only colors output from react-color are implemented.
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Direct port of TinyColor's function, lightly simplified to maintain
</span><span class="cx" style="display: block; padding: 0 10px"> * consistency with TinyColor.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -180,6 +201,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @see https://github.com/casesandberg/react-color/
</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><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @since 5.9.0 Added alpha processing.
</ins><span class="cx" style="display: block; padding: 0 10px"> * @access private
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @param string $color_str CSS color string.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -199,7 +221,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $rgb_regexp = '/^rgb' . $permissive_match3 . '$/';
</span><span class="cx" style="display: block; padding: 0 10px"> if ( preg_match( $rgb_regexp, $color_str, $match ) ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return wp_tinycolor_rgb_to_rgb(
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $rgb = wp_tinycolor_rgb_to_rgb(
</ins><span class="cx" style="display: block; padding: 0 10px"> array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'r' => $match[1],
</span><span class="cx" style="display: block; padding: 0 10px"> 'g' => $match[2],
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -206,11 +228,15 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 'b' => $match[3],
</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">+
+ $rgb['a'] = 1;
+
+ return $rgb;
</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"> $rgba_regexp = '/^rgba' . $permissive_match4 . '$/';
</span><span class="cx" style="display: block; padding: 0 10px"> if ( preg_match( $rgba_regexp, $color_str, $match ) ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return wp_tinycolor_rgb_to_rgb(
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $rgb = wp_tinycolor_rgb_to_rgb(
</ins><span class="cx" style="display: block; padding: 0 10px"> array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'r' => $match[1],
</span><span class="cx" style="display: block; padding: 0 10px"> 'g' => $match[2],
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -217,11 +243,15 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 'b' => $match[3],
</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">+
+ $rgb['a'] = _wp_tinycolor_bound_alpha( $match[4] );
+
+ return $rgb;
</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"> $hsl_regexp = '/^hsl' . $permissive_match3 . '$/';
</span><span class="cx" style="display: block; padding: 0 10px"> if ( preg_match( $hsl_regexp, $color_str, $match ) ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return wp_tinycolor_hsl_to_rgb(
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $rgb = wp_tinycolor_hsl_to_rgb(
</ins><span class="cx" style="display: block; padding: 0 10px"> array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'h' => $match[1],
</span><span class="cx" style="display: block; padding: 0 10px"> 's' => $match[2],
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -228,6 +258,10 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 'l' => $match[3],
</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">+
+ $rgb['a'] = 1;
+
+ return $rgb;
</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"> $hsla_regexp = '/^hsla' . $permissive_match4 . '$/';
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -239,11 +273,15 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 'l' => $match[3],
</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">+
+ $rgb['a'] = _wp_tinycolor_bound_alpha( $match[4] );
+
+ return $rgb;
</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"> $hex8_regexp = '/^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/';
</span><span class="cx" style="display: block; padding: 0 10px"> if ( preg_match( $hex8_regexp, $color_str, $match ) ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return wp_tinycolor_rgb_to_rgb(
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $rgb = wp_tinycolor_rgb_to_rgb(
</ins><span class="cx" style="display: block; padding: 0 10px"> array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'r' => base_convert( $match[1], 16, 10 ),
</span><span class="cx" style="display: block; padding: 0 10px"> 'g' => base_convert( $match[2], 16, 10 ),
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -250,11 +288,17 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 'b' => base_convert( $match[3], 16, 10 ),
</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">+
+ $rgb['a'] = _wp_tinycolor_bound_alpha(
+ base_convert( $match[4], 16, 10 ) / 255
+ );
+
+ return $rgb;
</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"> $hex6_regexp = '/^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/';
</span><span class="cx" style="display: block; padding: 0 10px"> if ( preg_match( $hex6_regexp, $color_str, $match ) ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return wp_tinycolor_rgb_to_rgb(
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $rgb = wp_tinycolor_rgb_to_rgb(
</ins><span class="cx" style="display: block; padding: 0 10px"> array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'r' => base_convert( $match[1], 16, 10 ),
</span><span class="cx" style="display: block; padding: 0 10px"> 'g' => base_convert( $match[2], 16, 10 ),
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -261,11 +305,15 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 'b' => base_convert( $match[3], 16, 10 ),
</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">+
+ $rgb['a'] = 1;
+
+ return $rgb;
</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"> $hex4_regexp = '/^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/';
</span><span class="cx" style="display: block; padding: 0 10px"> if ( preg_match( $hex4_regexp, $color_str, $match ) ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return wp_tinycolor_rgb_to_rgb(
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $rgb = wp_tinycolor_rgb_to_rgb(
</ins><span class="cx" style="display: block; padding: 0 10px"> array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'r' => base_convert( $match[1] . $match[1], 16, 10 ),
</span><span class="cx" style="display: block; padding: 0 10px"> 'g' => base_convert( $match[2] . $match[2], 16, 10 ),
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -272,11 +320,17 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 'b' => base_convert( $match[3] . $match[3], 16, 10 ),
</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">+
+ $rgb['a'] = _wp_tinycolor_bound_alpha(
+ base_convert( $match[4] . $match[4], 16, 10 ) / 255
+ );
+
+ return $rgb;
</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"> $hex3_regexp = '/^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/';
</span><span class="cx" style="display: block; padding: 0 10px"> if ( preg_match( $hex3_regexp, $color_str, $match ) ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return wp_tinycolor_rgb_to_rgb(
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $rgb = wp_tinycolor_rgb_to_rgb(
</ins><span class="cx" style="display: block; padding: 0 10px"> array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'r' => base_convert( $match[1] . $match[1], 16, 10 ),
</span><span class="cx" style="display: block; padding: 0 10px"> 'g' => base_convert( $match[2] . $match[2], 16, 10 ),
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -283,7 +337,24 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 'b' => base_convert( $match[3] . $match[3], 16, 10 ),
</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">+
+ $rgb['a'] = 1;
+
+ return $rgb;
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+ /*
+ * The JS color picker considers the string "transparent" to be a hex value,
+ * so we need to handle it here as a special case.
+ */
+ if ( 'transparent' === $color_str ) {
+ return array(
+ 'r' => 0,
+ 'g' => 0,
+ 'b' => 0,
+ 'a' => 0,
+ );
+ }
</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">@@ -313,7 +384,96 @@
</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">+/**
+ * Renders the duotone filter SVG and returns the CSS filter property to
+ * reference the rendered SVG.
+ *
+ * @since 5.9.0
+ *
+ * @param array $preset Duotone preset value as seen in theme.json.
+ * @return string Duotone CSS filter property.
+ */
+function wp_render_duotone_filter_preset( $preset ) {
+ $duotone_id = $preset['slug'];
+ $duotone_colors = $preset['colors'];
+ $filter_id = 'wp-duotone-' . $duotone_id;
+ $duotone_values = array(
+ 'r' => array(),
+ 'g' => array(),
+ 'b' => array(),
+ 'a' => array(),
+ );
+ foreach ( $duotone_colors as $color_str ) {
+ $color = wp_tinycolor_string_to_rgb( $color_str );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $duotone_values['r'][] = $color['r'] / 255;
+ $duotone_values['g'][] = $color['g'] / 255;
+ $duotone_values['b'][] = $color['b'] / 255;
+ $duotone_values['a'][] = $color['a'];
+ }
+
+ ob_start();
+
+ ?>
+
+ <svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 0 0"
+ width="0"
+ height="0"
+ focusable="false"
+ role="none"
+ style="visibility: hidden; position: absolute; left: -9999px; overflow: hidden;"
+ >
+ <defs>
+ <filter id="<?php echo esc_attr( $filter_id ); ?>">
+ <feColorMatrix
+ color-interpolation-filters="sRGB"
+ type="matrix"
+ values="
+ .299 .587 .114 0 0
+ .299 .587 .114 0 0
+ .299 .587 .114 0 0
+ .299 .587 .114 0 0
+ "
+ />
+ <feComponentTransfer color-interpolation-filters="sRGB" >
+ <feFuncR type="table" tableValues="<?php echo esc_attr( implode( ' ', $duotone_values['r'] ) ); ?>" />
+ <feFuncG type="table" tableValues="<?php echo esc_attr( implode( ' ', $duotone_values['g'] ) ); ?>" />
+ <feFuncB type="table" tableValues="<?php echo esc_attr( implode( ' ', $duotone_values['b'] ) ); ?>" />
+ <feFuncA type="table" tableValues="<?php echo esc_attr( implode( ' ', $duotone_values['a'] ) ); ?>" />
+ </feComponentTransfer>
+ <feComposite in2="SourceGraphic" operator="in" />
+ </filter>
+ </defs>
+ </svg>
+
+ <?php
+
+ $svg = ob_get_clean();
+
+ if ( ! defined( 'SCRIPT_DEBUG' ) || ! SCRIPT_DEBUG ) {
+ // Clean up the whitespace.
+ $svg = preg_replace( "/[\r\n\t ]+/", ' ', $svg );
+ $svg = preg_replace( '/> </', '><', $svg );
+ $svg = trim( $svg );
+ }
+
+ add_action(
+ /*
+ * Safari doesn't render SVG filters defined in data URIs,
+ * and SVG filters won't render in the head of a document,
+ * so the next best place to put the SVG is in the footer.
+ */
+ is_admin() ? 'admin_footer' : 'wp_footer',
+ static function () use ( $svg ) {
+ echo $svg;
+ }
+ );
+
+ return "url('#" . $filter_id . "')";
+}
+
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Render out the duotone stylesheet and SVG.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</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 2021-11-08 17:07:49 UTC (rev 52048)
+++ trunk/src/wp-includes/class-wp-theme-json-resolver.php 2021-11-08 19:18:39 UTC (rev 52049)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -11,6 +11,10 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * Class that abstracts the processing of the different data sources
</span><span class="cx" style="display: block; padding: 0 10px"> * for site-level config and offers an API to work with them.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * This class is for internal core usage and is not supposed to be used by extenders (plugins and/or themes).
+ * This is a low-level API that may need to do breaking changes. Please,
+ * use get_global_settings, get_global_styles, and get_global_stylesheet instead.
+ *
</ins><span class="cx" style="display: block; padding: 0 10px"> * @access private
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> class WP_Theme_JSON_Resolver {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -40,9 +44,27 @@
</span><span class="cx" style="display: block; padding: 0 10px"> private static $theme_has_support = null;
</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">+ * Container for data coming from the user.
+ *
+ * @since 5.9.0
+ * @var WP_Theme_JSON
+ */
+ private static $user = null;
+
+ /**
+ * Stores the ID of the custom post type
+ * that holds the user data.
+ *
+ * @since 5.9.0
+ * @var integer
+ */
+ private static $user_custom_post_type_id = null;
+
+ /**
</ins><span class="cx" style="display: block; padding: 0 10px"> * Container to keep loaded i18n schema for `theme.json`.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @since 5.9.0
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @since 5.8.0
+ * @since 5.9.0 Renamed from $theme_json_i18n
</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"> private static $i18n_schema = null;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -122,34 +144,45 @@
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Returns the theme's data.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Data from theme.json can be augmented via the $theme_support_data variable.
- * This is useful, for example, to backfill the gaps in theme.json that a theme
- * has declared via add_theme_supports.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Data from theme.json will be backfilled from existing
+ * theme supports, if any. Note that if the same data
+ * is present in theme.json and in theme supports,
+ * the theme.json takes precendence.
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Note that if the same data is present in theme.json and in $theme_support_data,
- * the theme.json's is not overwritten.
- *
</del><span class="cx" style="display: block; padding: 0 10px"> * @since 5.8.0
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @since 5.9.0 Theme supports have been inlined and the argument removed.
</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 $theme_support_data Optional. Theme support data in theme.json format.
- * Default empty array.
</del><span class="cx" style="display: block; padding: 0 10px"> * @return WP_Theme_JSON Entity that holds theme data.
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public static function get_theme_data( $theme_support_data = array() ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public static function get_theme_data( $deprecated = array() ) {
+ if ( ! empty( $deprecated ) ) {
+ _deprecated_argument( __METHOD__, '5.9' );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> if ( null === self::$theme ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $theme_json_data = self::read_json_file( self::get_file_path_from_theme( 'theme.json' ) );
</span><span class="cx" style="display: block; padding: 0 10px"> $theme_json_data = self::translate( $theme_json_data, wp_get_theme()->get( 'TextDomain' ) );
</span><span class="cx" style="display: block; padding: 0 10px"> self::$theme = new WP_Theme_JSON( $theme_json_data );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- }
</del><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ( empty( $theme_support_data ) ) {
- return self::$theme;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( wp_get_theme()->parent() ) {
+ // Get parent theme.json.
+ $parent_theme_json_data = self::read_json_file( self::get_file_path_from_theme( 'theme.json', true ) );
+ $parent_theme_json_data = self::translate( $parent_theme_json_data, wp_get_theme()->parent()->get( 'TextDomain' ) );
+ $parent_theme = new WP_Theme_JSON( $parent_theme_json_data );
+
+ // Merge the child theme.json into the parent theme.json.
+ // The child theme takes precedence over the parent.
+ $parent_theme->merge( self::$theme );
+ self::$theme = $parent_theme;
+ }
</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><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * We want the presets and settings declared in theme.json
- * to override the ones declared via add_theme_support.
- */
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * We want the presets and settings declared in theme.json
+ * to override the ones declared via theme supports.
+ * So we take theme supports, transform it to theme.json shape
+ * and merge the self::$theme upon that.
+ */
+ $theme_support_data = WP_Theme_JSON::get_from_editor_settings( get_default_block_editor_settings() );
</ins><span class="cx" style="display: block; padding: 0 10px"> $with_theme_supports = new WP_Theme_JSON( $theme_support_data );
</span><span class="cx" style="display: block; padding: 0 10px"> $with_theme_supports->merge( self::$theme );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -157,40 +190,180 @@
</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">- * There are different sources of data for a site: core and theme.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Returns the CPT that contains the user's origin config
+ * for the current theme or a void array if none found.
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * While the getters {@link get_core_data}, {@link get_theme_data} return the raw data
- * from the respective origins, this method merges them all together.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * It can also create and return a new draft CPT.
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * If the same piece of data is declared in different origins (core and theme),
- * the last origin overrides the previous. For example, if core disables custom colors
- * but a theme enables them, the theme config wins.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @since 5.9.0
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @param bool $should_create_cpt Optional. Whether a new CPT should be created if no one was found.
+ * False by default.
+ * @param array $post_status_filter Filter Optional. CPT by post status.
+ * ['publish'] by default, so it only fetches published posts.
+ *
+ * @return array Custom Post Type for the user's origin config.
+ */
+ private static function get_user_data_from_custom_post_type( $should_create_cpt = false, $post_status_filter = array( 'publish' ) ) {
+ $user_cpt = array();
+ $post_type_filter = 'wp_global_styles';
+ $query = new WP_Query(
+ array(
+ 'posts_per_page' => 1,
+ 'orderby' => 'date',
+ 'order' => 'desc',
+ 'post_type' => $post_type_filter,
+ 'post_status' => $post_status_filter,
+ 'tax_query' => array(
+ array(
+ 'taxonomy' => 'wp_theme',
+ 'field' => 'name',
+ 'terms' => wp_get_theme()->get_stylesheet(),
+ ),
+ ),
+ )
+ );
+
+ if ( is_array( $query->posts ) && ( 1 === $query->post_count ) ) {
+ $user_cpt = $query->posts[0]->to_array();
+ } elseif ( $should_create_cpt ) {
+ $cpt_post_id = wp_insert_post(
+ array(
+ 'post_content' => '{"version": ' . WP_Theme_JSON::LATEST_SCHEMA . ', "isGlobalStylesUserThemeJSON": true }',
+ 'post_status' => 'publish',
+ 'post_title' => __( 'Custom Styles', 'default' ),
+ 'post_type' => $post_type_filter,
+ 'post_name' => 'wp-global-styles-' . urlencode( wp_get_theme()->get_stylesheet() ),
+ 'tax_input' => array(
+ 'wp_theme' => array( wp_get_theme()->get_stylesheet() ),
+ ),
+ ),
+ true
+ );
+
+ if ( is_wp_error( $cpt_post_id ) ) {
+ $user_cpt = array();
+ } else {
+ $user_cpt = get_post( $cpt_post_id, ARRAY_A );
+ }
+ }
+
+ return $user_cpt;
+ }
+
+ /**
+ * Returns the user's origin config.
+ *
+ * @since 5.9.0
+ *
+ * @return WP_Theme_JSON Entity that holds user data.
+ */
+ public static function get_user_data() {
+ if ( null !== self::$user ) {
+ return self::$user;
+ }
+
+ $config = array();
+ $user_cpt = self::get_user_data_from_custom_post_type();
+
+ if ( array_key_exists( 'post_content', $user_cpt ) ) {
+ $decoded_data = json_decode( $user_cpt['post_content'], true );
+
+ $json_decoding_error = json_last_error();
+ if ( JSON_ERROR_NONE !== $json_decoding_error ) {
+ trigger_error( 'Error when decoding a theme.json schema for user data. ' . json_last_error_msg() );
+ return new WP_Theme_JSON( $config, 'user' );
+ }
+
+ // Very important to verify if the flag isGlobalStylesUserThemeJSON is true.
+ // If is not true the content was not escaped and is not safe.
+ if (
+ is_array( $decoded_data ) &&
+ isset( $decoded_data['isGlobalStylesUserThemeJSON'] ) &&
+ $decoded_data['isGlobalStylesUserThemeJSON']
+ ) {
+ unset( $decoded_data['isGlobalStylesUserThemeJSON'] );
+ $config = $decoded_data;
+ }
+ }
+ self::$user = new WP_Theme_JSON( $config, 'user' );
+
+ return self::$user;
+ }
+
+ /**
+ * There are three sources of data (origins) for a site:
+ * core, theme, and user. The user's has higher priority
+ * than the theme's, and the theme's higher than core's.
+ *
+ * Unlike the getters {@link get_core_data},
+ * {@link get_theme_data}, and {@link get_user_data},
+ * this method returns data after it has been merged
+ * with the previous origins. This means that if the same piece of data
+ * is declared in different origins (user, theme, and core),
+ * the last origin overrides the previous.
+ *
+ * For example, if the user has set a background color
+ * for the paragraph block, and the theme has done it as well,
+ * the user preference wins.
+ *
</ins><span class="cx" style="display: block; padding: 0 10px"> * @since 5.8.0
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @since 5.9.0 Add user data and change the arguments.
</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 $settings Optional. Existing block editor settings. Default empty array.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @param string $origin Optional. To what level should we merge data.
+ * Valid values are 'theme' or 'user'.
+ * Default is 'user'.
</ins><span class="cx" style="display: block; padding: 0 10px"> * @return WP_Theme_JSON
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public static function get_merged_data( $settings = array() ) {
- $theme_support_data = WP_Theme_JSON::get_from_editor_settings( $settings );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public static function get_merged_data( $origin = 'user' ) {
+ if ( is_array( $origin ) ) {
+ _deprecated_argument( __FUNCTION__, '5.9' );
+ }
</ins><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( self::get_core_data() );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $result->merge( self::get_theme_data( $theme_support_data ) );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $result->merge( self::get_theme_data() );
</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 ( 'user' === $origin ) {
+ $result->merge( self::get_user_data() );
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> return $result;
</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">+ * Returns the ID of the custom post type
+ * that stores user data.
+ *
+ * @since 5.9.0
+ *
+ * @return integer|null
+ */
+ public static function get_user_custom_post_type_id() {
+ if ( null !== self::$user_custom_post_type_id ) {
+ return self::$user_custom_post_type_id;
+ }
+
+ $user_cpt = self::get_user_data_from_custom_post_type( true );
+
+ if ( array_key_exists( 'ID', $user_cpt ) ) {
+ self::$user_custom_post_type_id = $user_cpt['ID'];
+ }
+
+ return self::$user_custom_post_type_id;
+ }
+
+ /**
</ins><span class="cx" style="display: block; padding: 0 10px"> * Whether the current theme has a theme.json file.
</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><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @since 5.9.0 Also check in the parent theme.
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @return bool
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public static function theme_has_support() {
</span><span class="cx" style="display: block; padding: 0 10px"> if ( ! isset( self::$theme_has_support ) ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self::$theme_has_support = (bool) self::get_file_path_from_theme( 'theme.json' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self::$theme_has_support = is_readable( get_theme_file_path( 'theme.json' ) );
</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 self::$theme_has_support;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -202,24 +375,17 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * If it isn't, returns an empty string, otherwise returns the whole file path.
</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><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @since 5.9.0 Adapt to work with child themes.
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @param string $file_name Name of the file.
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @param bool $template Optional. Use template theme directory. Default false.
</ins><span class="cx" style="display: block; padding: 0 10px"> * @return string The whole file path or empty if the file doesn't exist.
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- private static function get_file_path_from_theme( $file_name ) {
- /*
- * This used to be a locate_template call. However, that method proved problematic
- * due to its use of constants (STYLESHEETPATH) that threw errors in some scenarios.
- *
- * When the theme.json merge algorithm properly supports child themes,
- * this should also fall back to the template path, as locate_template did.
- */
- $located = '';
- $candidate = get_stylesheet_directory() . '/' . $file_name;
- if ( is_readable( $candidate ) ) {
- $located = $candidate;
- }
- return $located;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ private static function get_file_path_from_theme( $file_name, $template = false ) {
+ $path = $template ? get_template_directory() : get_stylesheet_directory();
+ $candidate = $path . '/' . $file_name;
+
+ return is_readable( $candidate ) ? $candidate : '';
</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">@@ -226,11 +392,15 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * Cleans the cached data so it can be recalculated.
</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><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @since 5.9.0 Added new variables to reset.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public static function clean_cached_data() {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self::$core = null;
- self::$theme = null;
- self::$theme_has_support = null;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self::$core = null;
+ self::$theme = null;
+ self::$user = null;
+ self::$user_custom_post_type_id = null;
+ self::$theme_has_support = null;
+ self::$i18n_schema = null;
</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="trunksrcwpincludesclasswpthemejsonschemaphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/src/wp-includes/class-wp-theme-json-schema.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-schema.php (rev 0)
+++ trunk/src/wp-includes/class-wp-theme-json-schema.php 2021-11-08 19:18:39 UTC (rev 52049)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,141 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+/**
+ * WP_Theme_JSON_Schema class
+ *
+ * @package WordPress
+ * @subpackage Theme
+ * @since 5.9.0
+ */
+
+/**
+ * Class that migrates a given theme.json structure to the latest schema.
+ *
+ * This class is for internal core usage and is not supposed to be used by extenders (plugins and/or themes).
+ * This is a low-level API that may need to do breaking changes. Please,
+ * use get_global_settings, get_global_styles, and get_global_stylesheet instead.
+ *
+ * @access private
+ */
+class WP_Theme_JSON_Schema {
+
+ /**
+ * Maps old properties to their new location within the schema's settings.
+ * This will be applied at both the defaults and individual block levels.
+ */
+ const V1_TO_V2_RENAMED_PATHS = array(
+ 'border.customRadius' => 'border.radius',
+ 'spacing.customMargin' => 'spacing.margin',
+ 'spacing.customPadding' => 'spacing.padding',
+ 'typography.customLineHeight' => 'typography.lineHeight',
+ );
+
+ /**
+ * Function that migrates a given theme.json structure to the last version.
+ *
+ * @param array $theme_json The structure to migrate.
+ *
+ * @return array The structure in the last version.
+ */
+ public static function migrate( $theme_json ) {
+ if ( ! isset( $theme_json['version'] ) ) {
+ $theme_json = array(
+ 'version' => WP_Theme_JSON::LATEST_SCHEMA,
+ );
+ }
+
+ if ( 1 === $theme_json['version'] ) {
+ $theme_json = self::migrate_v1_to_v2( $theme_json );
+ }
+
+ return $theme_json;
+ }
+
+ /**
+ * Removes the custom prefixes for a few properties
+ * that were part of v1:
+ *
+ * 'border.customRadius' => 'border.radius',
+ * 'spacing.customMargin' => 'spacing.margin',
+ * 'spacing.customPadding' => 'spacing.padding',
+ * 'typography.customLineHeight' => 'typography.lineHeight',
+ *
+ * @param array $old Data to migrate.
+ *
+ * @return array Data without the custom prefixes.
+ */
+ private static function migrate_v1_to_v2( $old ) {
+ // Copy everything.
+ $new = $old;
+
+ // Overwrite the things that changed.
+ if ( isset( $old['settings'] ) ) {
+ $new['settings'] = self::rename_paths( $old['settings'], self::V1_TO_V2_RENAMED_PATHS );
+ }
+
+ // Set the new version.
+ $new['version'] = 2;
+
+ return $new;
+ }
+
+ /**
+ * Processes the settings subtree.
+ *
+ * @param array $settings Array to process.
+ * @param array $paths_to_rename Paths to rename.
+ *
+ * @return array The settings in the new format.
+ */
+ private static function rename_paths( $settings, $paths_to_rename ) {
+ $new_settings = $settings;
+
+ // Process any renamed/moved paths within default settings.
+ self::rename_settings( $new_settings, $paths_to_rename );
+
+ // Process individual block settings.
+ if ( isset( $new_settings['blocks'] ) && is_array( $new_settings['blocks'] ) ) {
+ foreach ( $new_settings['blocks'] as &$block_settings ) {
+ self::rename_settings( $block_settings, $paths_to_rename );
+ }
+ }
+
+ return $new_settings;
+ }
+
+ /**
+ * Processes a settings array, renaming or moving properties.
+ *
+ * @param array $settings Reference to settings either defaults or an individual block's.
+ * @param arary $paths_to_rename Paths to rename.
+ */
+ private static function rename_settings( &$settings, $paths_to_rename ) {
+ foreach ( $paths_to_rename as $original => $renamed ) {
+ $original_path = explode( '.', $original );
+ $renamed_path = explode( '.', $renamed );
+ $current_value = _wp_array_get( $settings, $original_path, null );
+
+ if ( null !== $current_value ) {
+ _wp_array_set( $settings, $renamed_path, $current_value );
+ self::unset_setting_by_path( $settings, $original_path );
+ }
+ }
+ }
+
+ /**
+ * Removes a property from within the provided settings by its path.
+ *
+ * @param array $settings Reference to the current settings array.
+ * @param array $path Path to the property to be removed.
+ *
+ * @return void
+ */
+ private static function unset_setting_by_path( &$settings, $path ) {
+ $tmp_settings = &$settings; // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
+ $last_key = array_pop( $path );
+ foreach ( $path as $key ) {
+ $tmp_settings = &$tmp_settings[ $key ];
+ }
+
+ unset( $tmp_settings[ $last_key ] );
+ }
+}
</ins></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 2021-11-08 17:07:49 UTC (rev 52048)
+++ trunk/src/wp-includes/class-wp-theme-json.php 2021-11-08 19:18:39 UTC (rev 52049)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -10,6 +10,10 @@
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Class that encapsulates the processing of structures that adhere to the theme.json spec.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * This class is for internal core usage and is not supposed to be used by extenders (plugins and/or themes).
+ * This is a low-level API that may need to do breaking changes. Please,
+ * use get_global_settings, get_global_styles, and get_global_stylesheet instead.
+ *
</ins><span class="cx" style="display: block; padding: 0 10px"> * @access private
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> class WP_Theme_JSON {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -70,119 +74,153 @@
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * This contains the necessary metadata to process them:
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * - path => where to find the preset within the settings section
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * - path => where to find the preset within the settings section
+ * - value_key => the key that represents the value
+ * - value_func => the callback to render the value (either value_key or value_func should be present)
+ * - css_vars => template string to use in generating the CSS Custom Property.
+ * Example output: "--wp--preset--duotone--blue: <value>" will generate as many CSS Custom Properties as presets defined
+ * substituting the $slug for the slug's value for each preset value.
+ * - classes => array containing a structure with the classes to generate for the presets.
+ * Each key is a template string to resolve similarly to the css_vars and each value is the CSS property to use for that class.
+ * Example output: ".has-blue-color { color: <value> }"
+ * - properties => a list of CSS properties to be used by kses to check the preset value is safe.
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * - value_key => the key that represents the value
- *
- * - css_var_infix => infix to use in generating the CSS Custom Property. Example:
- * --wp--preset--<preset_infix>--<slug>: <preset_value>
- *
- * - classes => array containing a structure with the classes to
- * generate for the presets. Each class should have
- * the class suffix and the property name. Example:
- *
- * .has-<slug>-<class_suffix> {
- * <property_name>: <preset_value>
- * }
- *
</del><span class="cx" style="display: block; padding: 0 10px"> * @since 5.8.0
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @since 5.9.0 Added new presets and simplified the metadata structure.
</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 PRESETS_METADATA = array(
</span><span class="cx" style="display: block; padding: 0 10px"> array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'path' => array( 'color', 'palette' ),
- 'value_key' => 'color',
- 'css_var_infix' => 'color',
- 'classes' => array(
- array(
- 'class_suffix' => 'color',
- 'property_name' => 'color',
- ),
- array(
- 'class_suffix' => 'background-color',
- 'property_name' => 'background-color',
- ),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'path' => array( 'color', 'palette' ),
+ 'value_key' => 'color',
+ 'css_vars' => '--wp--preset--color--$slug',
+ 'classes' => array(
+ '.has-$slug-color' => 'color',
+ '.has-$slug-background-color' => 'background-color',
+ '.has-$slug-border-color' => 'border-color',
</ins><span class="cx" style="display: block; padding: 0 10px"> ),
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'properties' => array( 'color', 'background-color', 'border-color' ),
</ins><span class="cx" style="display: block; padding: 0 10px"> ),
</span><span class="cx" style="display: block; padding: 0 10px"> array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'path' => array( 'color', 'gradients' ),
- 'value_key' => 'gradient',
- 'css_var_infix' => 'gradient',
- 'classes' => array(
- array(
- 'class_suffix' => 'gradient-background',
- 'property_name' => 'background',
- ),
- ),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'path' => array( 'color', 'gradients' ),
+ 'value_key' => 'gradient',
+ 'css_vars' => '--wp--preset--gradient--$slug',
+ 'classes' => array( '.has-$slug-gradient-background' => 'background' ),
+ 'properties' => array( 'background' ),
</ins><span class="cx" style="display: block; padding: 0 10px"> ),
</span><span class="cx" style="display: block; padding: 0 10px"> array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'path' => array( 'typography', 'fontSizes' ),
- 'value_key' => 'size',
- 'css_var_infix' => 'font-size',
- 'classes' => array(
- array(
- 'class_suffix' => 'font-size',
- 'property_name' => 'font-size',
- ),
- ),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'path' => array( 'color', 'duotone' ),
+ 'value_func' => 'wp_render_duotone_filter_preset',
+ 'css_vars' => '--wp--preset--duotone--$slug',
+ 'classes' => array(),
+ 'properties' => array( 'filter' ),
</ins><span class="cx" style="display: block; padding: 0 10px"> ),
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ array(
+ 'path' => array( 'typography', 'fontSizes' ),
+ 'value_key' => 'size',
+ 'css_vars' => '--wp--preset--font-size--$slug',
+ 'classes' => array( '.has-$slug-font-size' => 'font-size' ),
+ 'properties' => array( 'font-size' ),
+ ),
+ array(
+ 'path' => array( 'typography', 'fontFamilies' ),
+ 'value_key' => 'fontFamily',
+ 'css_vars' => '--wp--preset--font-family--$slug',
+ 'classes' => array( '.has-$slug-font-family' => 'font-family' ),
+ 'properties' => array( 'font-family' ),
+ ),
</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="cx" style="display: block; padding: 0 10px"> * Metadata for style properties.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Each property declares:
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Each element is a direct mapping from the CSS property name to the
+ * path to the value in theme.json & block attributes.
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * - 'value': path to the value in theme.json and block attributes.
- *
</del><span class="cx" style="display: block; padding: 0 10px"> * @since 5.8.0
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @since 5.9.0 Added new properties and simplified the metadata structure.
</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(
- 'value' => array( 'color', 'gradient' ),
- ),
- 'background-color' => array(
- 'value' => array( 'color', 'background' ),
- ),
- 'color' => array(
- 'value' => array( 'color', 'text' ),
- ),
- 'font-size' => array(
- 'value' => array( 'typography', 'fontSize' ),
- ),
- 'line-height' => array(
- 'value' => array( 'typography', 'lineHeight' ),
- ),
- 'margin' => array(
- 'value' => array( 'spacing', 'margin' ),
- 'properties' => array( 'top', 'right', 'bottom', 'left' ),
- ),
- 'padding' => array(
- 'value' => array( 'spacing', 'padding' ),
- 'properties' => array( 'top', 'right', 'bottom', 'left' ),
- ),
</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' ),
+ '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' ),
</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><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Protected style properties.
+ *
+ * These style properties are only rendered if a setting enables it
+ * via a value other than `null`.
+ *
+ * Each element maps the style property to the corresponding theme.json
+ * setting key.
+ *
+ * @since 5.9.0
+ */
+ const PROTECTED_PROPERTIES = array(
+ 'spacing.blockGap' => array( 'spacing', 'blockGap' ),
+ );
+
+ /**
+ * The top-level keys a theme.json can have.
+ *
</ins><span class="cx" style="display: block; padding: 0 10px"> * @since 5.8.0
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @since 5.9.0 Renamed from ALLOWED_TOP_LEVEL_KEYS and added new values.
</ins><span class="cx" style="display: block; padding: 0 10px"> * @var string[]
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- const ALLOWED_TOP_LEVEL_KEYS = array(
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ const VALID_TOP_LEVEL_KEYS = array(
+ 'customTemplates',
</ins><span class="cx" style="display: block; padding: 0 10px"> 'settings',
</span><span class="cx" style="display: block; padding: 0 10px"> 'styles',
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'templateParts',
</ins><span class="cx" style="display: block; padding: 0 10px"> 'version',
</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">+ * The valid properties under the settings key.
+ *
</ins><span class="cx" style="display: block; padding: 0 10px"> * @since 5.8.0
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @since 5.9.0 Renamed from ALLOWED_SETTINGS, gained new properties, and renamed others according to the new schema.
</ins><span class="cx" style="display: block; padding: 0 10px"> * @var array
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- const ALLOWED_SETTINGS = array(
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ const VALID_SETTINGS = array(
</ins><span class="cx" style="display: block; padding: 0 10px"> 'border' => array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'customRadius' => null,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'color' => null,
+ 'radius' => null,
+ 'style' => null,
+ 'width' => null,
</ins><span class="cx" style="display: block; padding: 0 10px"> ),
</span><span class="cx" style="display: block; padding: 0 10px"> 'color' => array(
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'background' => null,
</ins><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="cx" style="display: block; padding: 0 10px"> 'customGradient' => null,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -190,6 +228,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 'gradients' => null,
</span><span class="cx" style="display: block; padding: 0 10px"> 'link' => null,
</span><span class="cx" style="display: block; padding: 0 10px"> 'palette' => null,
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'text' => null,
</ins><span class="cx" style="display: block; padding: 0 10px"> ),
</span><span class="cx" style="display: block; padding: 0 10px"> 'custom' => null,
</span><span class="cx" style="display: block; padding: 0 10px"> 'layout' => array(
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -197,25 +236,38 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 'wideSize' => null,
</span><span class="cx" style="display: block; padding: 0 10px"> ),
</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">- 'customMargin' => null,
- 'customPadding' => null,
- 'units' => null,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'blockGap' => null,
+ 'margin' => null,
+ 'padding' => null,
+ 'units' => null,
</ins><span class="cx" style="display: block; padding: 0 10px"> ),
</span><span class="cx" style="display: block; padding: 0 10px"> 'typography' => array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'customFontSize' => null,
- 'customLineHeight' => null,
- 'dropCap' => null,
- 'fontSizes' => null,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'customFontSize' => null,
+ 'dropCap' => null,
+ 'fontFamilies' => null,
+ 'fontSizes' => null,
+ 'fontStyle' => null,
+ 'fontWeight' => null,
+ 'letterSpacing' => null,
+ 'lineHeight' => null,
+ 'textDecoration' => null,
+ 'textTransform' => null,
</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="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * The valid properties under the styles key.
+ *
</ins><span class="cx" style="display: block; padding: 0 10px"> * @since 5.8.0
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @since 5.9.0 Renamed from ALLOWED_SETTINGS, gained new properties.
</ins><span class="cx" style="display: block; padding: 0 10px"> * @var array
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- const ALLOWED_STYLES = array(
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ const VALID_STYLES = array(
</ins><span class="cx" style="display: block; padding: 0 10px"> 'border' => array(
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'color' => null,
</ins><span class="cx" style="display: block; padding: 0 10px"> 'radius' => null,
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'style' => null,
+ 'width' => 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">@@ -222,23 +274,23 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 'gradient' => null,
</span><span class="cx" style="display: block; padding: 0 10px"> 'text' => null,
</span><span class="cx" style="display: block; padding: 0 10px"> ),
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'filter' => array(
+ 'duotone' => null,
+ ),
</ins><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' => array(
- 'top' => null,
- 'right' => null,
- 'bottom' => null,
- 'left' => null,
- ),
- 'padding' => array(
- 'bottom' => null,
- 'left' => null,
- 'right' => null,
- 'top' => null,
- ),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'margin' => null,
+ 'padding' => null,
+ '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><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'fontSize' => null,
- 'lineHeight' => null,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'fontFamily' => null,
+ 'fontSize' => null,
+ 'fontStyle' => null,
+ 'fontWeight' => null,
+ 'letterSpacing' => null,
+ 'lineHeight' => null,
+ 'textDecoration' => null,
+ 'textTransform' => null,
</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">@@ -257,10 +309,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"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * The latest version of the schema in use.
+ *
</ins><span class="cx" style="display: block; padding: 0 10px"> * @since 5.8.0
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @since 5.9.0 Changed value.
</ins><span class="cx" style="display: block; padding: 0 10px"> * @var int
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- const LATEST_SCHEMA = 1;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ const LATEST_SCHEMA = 2;
</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"> * Constructor.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -276,18 +331,16 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $origin = 'theme';
</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 ( ! isset( $theme_json['version'] ) || self::LATEST_SCHEMA !== $theme_json['version'] ) {
- $this->theme_json = array();
- return;
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $this->theme_json = WP_Theme_JSON_Schema::migrate( $theme_json );
+ $valid_block_names = array_keys( self::get_blocks_metadata() );
+ $valid_element_names = array_keys( self::ELEMENTS );
+ $this->theme_json = self::sanitize( $this->theme_json, $valid_block_names, $valid_element_names );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $this->theme_json = self::sanitize( $theme_json );
-
</del><span class="cx" style="display: block; padding: 0 10px"> // Internally, presets are keyed by origin.
</span><span class="cx" style="display: block; padding: 0 10px"> $nodes = self::get_setting_nodes( $this->theme_json );
</span><span class="cx" style="display: block; padding: 0 10px"> foreach ( $nodes as $node ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- foreach ( self::PRESETS_METADATA as $preset ) {
- $path = array_merge( $node['path'], $preset['path'] );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ foreach ( self::PRESETS_METADATA as $preset_metadata ) {
+ $path = array_merge( $node['path'], $preset_metadata['path'] );
</ins><span class="cx" style="display: block; padding: 0 10px"> $preset = _wp_array_get( $this->theme_json, $path, null );
</span><span class="cx" style="display: block; padding: 0 10px"> if ( null !== $preset ) {
</span><span class="cx" style="display: block; padding: 0 10px"> _wp_array_set( $this->theme_json, $path, array( $origin => $preset ) );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -300,11 +353,14 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * Sanitizes the input according to the schemas.
</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><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @since 5.9.0 Has new parameters.
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @param array $input Structure to sanitize.
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @param array $valid_block_names List of valid block names.
+ * @param array $valid_element_names List of valid element names.
</ins><span class="cx" style="display: block; padding: 0 10px"> * @return array The sanitized output.
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- private static function sanitize( $input ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ private static function sanitize( $input, $valid_block_names, $valid_element_names ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $output = array();
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> if ( ! is_array( $input ) ) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -311,31 +367,25 @@
</span><span class="cx" style="display: block; padding: 0 10px"> return $output;
</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">- $allowed_top_level_keys = self::ALLOWED_TOP_LEVEL_KEYS;
- $allowed_settings = self::ALLOWED_SETTINGS;
- $allowed_styles = self::ALLOWED_STYLES;
- $allowed_blocks = array_keys( self::get_blocks_metadata() );
- $allowed_elements = array_keys( self::ELEMENTS );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $output = array_intersect_key( $input, array_flip( self::VALID_TOP_LEVEL_KEYS ) );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $output = array_intersect_key( $input, array_flip( $allowed_top_level_keys ) );
-
- // Build the schema.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Build the schema based on valid block & element names.
</ins><span class="cx" style="display: block; padding: 0 10px"> $schema = array();
</span><span class="cx" style="display: block; padding: 0 10px"> $schema_styles_elements = array();
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- foreach ( $allowed_elements as $element ) {
- $schema_styles_elements[ $element ] = $allowed_styles;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ foreach ( $valid_element_names as $element ) {
+ $schema_styles_elements[ $element ] = self::VALID_STYLES;
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> $schema_styles_blocks = array();
</span><span class="cx" style="display: block; padding: 0 10px"> $schema_settings_blocks = array();
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- foreach ( $allowed_blocks as $block ) {
- $schema_settings_blocks[ $block ] = $allowed_settings;
- $schema_styles_blocks[ $block ] = $allowed_styles;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ foreach ( $valid_block_names as $block ) {
+ $schema_settings_blocks[ $block ] = self::VALID_SETTINGS;
+ $schema_styles_blocks[ $block ] = self::VALID_STYLES;
</ins><span class="cx" style="display: block; padding: 0 10px"> $schema_styles_blocks[ $block ]['elements'] = $schema_styles_elements;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $schema['styles'] = $allowed_styles;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $schema['styles'] = self::VALID_STYLES;
</ins><span class="cx" style="display: block; padding: 0 10px"> $schema['styles']['blocks'] = $schema_styles_blocks;
</span><span class="cx" style="display: block; padding: 0 10px"> $schema['styles']['elements'] = $schema_styles_elements;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $schema['settings'] = $allowed_settings;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $schema['settings'] = self::VALID_SETTINGS;
</ins><span class="cx" style="display: block; padding: 0 10px"> $schema['settings']['blocks'] = $schema_settings_blocks;
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Remove anything that's not present in the schema.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -360,7 +410,6 @@
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> return $output;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Returns the metadata for each block.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -377,14 +426,16 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * 'core/heading': {
</span><span class="cx" style="display: block; padding: 0 10px"> * 'selector': 'h1',
</span><span class="cx" style="display: block; padding: 0 10px"> * 'elements': {}
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * }
- * 'core/group': {
- * 'selector': '.wp-block-group',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * },
+ * 'core/image': {
+ * 'selector': '.wp-block-image',
+ * 'duotone': 'img',
</ins><span class="cx" style="display: block; padding: 0 10px"> * 'elements': {}
</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><span class="cx" style="display: block; padding: 0 10px"> * @since 5.8.0
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @since 5.9.0 Added duotone key with CSS selector.
</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">@@ -407,11 +458,16 @@
</span><span class="cx" style="display: block; padding: 0 10px"> self::$blocks_metadata[ $block_name ]['selector'] = '.wp-block-' . str_replace( '/', '-', str_replace( 'core/', '', $block_name ) );
</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">- /*
- * Assign defaults, then overwrite those that the block sets by itself.
- * If the block selector is compounded, will append the element to each
- * individual block selector.
- */
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (
+ isset( $block_type->supports['color']['__experimentalDuotone'] ) &&
+ is_string( $block_type->supports['color']['__experimentalDuotone'] )
+ ) {
+ self::$blocks_metadata[ $block_name ]['duotone'] = $block_type->supports['color']['__experimentalDuotone'];
+ }
+
+ // Assign defaults, then overwrite those that the block sets by itself.
+ // If the block selector is compounded, will append the element to each
+ // individual block selector.
</ins><span class="cx" style="display: block; padding: 0 10px"> $block_selectors = explode( ',', self::$blocks_metadata[ $block_name ]['selector'] );
</span><span class="cx" style="display: block; padding: 0 10px"> foreach ( self::ELEMENTS as $el_name => $el_selector ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $element_selector = array();
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -493,28 +549,98 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * the theme.json structure this object represents.
</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><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @since 5.9.0 Changed the arguments passed to the function.
</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 string $type Optional. Type of stylesheet we want. Accepts 'all',
- * 'block_styles', and 'css_variables'. Default 'all'.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @param array $types Types of styles to load. Will load all by default. It accepts:
+ * 'variables': only the CSS Custom Properties for presets & custom ones.
+ * 'styles': only the styles section in theme.json.
+ * 'presets': only the classes for the presets.
+ * @param array $origins A list of origins to include. By default it includes self::VALID_ORIGINS.
</ins><span class="cx" style="display: block; padding: 0 10px"> * @return string Stylesheet.
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function get_stylesheet( $type = 'all' ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function get_stylesheet( $types = array( 'variables', 'styles', 'presets' ), $origins = self::VALID_ORIGINS ) {
+ if ( is_string( $types ) ) {
+ // Dispatch error and map old arguments to new ones.
+ _deprecated_argument( __FUNCTION__, '5.9' );
+ if ( 'block_styles' === $types ) {
+ $types = array( 'styles', 'presets' );
+ } elseif ( 'css_variables' === $types ) {
+ $types = array( 'variables' );
+ } else {
+ $types = array( 'variables', 'styles', 'presets' );
+ }
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> $blocks_metadata = self::get_blocks_metadata();
</span><span class="cx" style="display: block; padding: 0 10px"> $style_nodes = self::get_style_nodes( $this->theme_json, $blocks_metadata );
</span><span class="cx" style="display: block; padding: 0 10px"> $setting_nodes = self::get_setting_nodes( $this->theme_json, $blocks_metadata );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- switch ( $type ) {
- case 'block_styles':
- return $this->get_block_styles( $style_nodes, $setting_nodes );
- case 'css_variables':
- return $this->get_css_variables( $setting_nodes );
- default:
- return $this->get_css_variables( $setting_nodes ) . $this->get_block_styles( $style_nodes, $setting_nodes );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $stylesheet = '';
+
+ if ( in_array( 'variables', $types, true ) ) {
+ $stylesheet .= $this->get_css_variables( $setting_nodes, $origins );
</ins><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 ( in_array( 'styles', $types, true ) ) {
+ $stylesheet .= $this->get_block_classes( $style_nodes );
+ }
+
+ if ( in_array( 'presets', $types, true ) ) {
+ $stylesheet .= $this->get_preset_classes( $setting_nodes, $origins );
+ }
+
+ return $stylesheet;
</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><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Returns the page templates of the current theme.
+ *
+ * @since 5.9.0
+ *
+ * @return array
+ */
+ public function get_custom_templates() {
+ $custom_templates = array();
+ if ( ! isset( $this->theme_json['customTemplates'] ) ) {
+ return $custom_templates;
+ }
+
+ foreach ( $this->theme_json['customTemplates'] as $item ) {
+ if ( isset( $item['name'] ) ) {
+ $custom_templates[ $item['name'] ] = array(
+ 'title' => isset( $item['title'] ) ? $item['title'] : '',
+ 'postTypes' => isset( $item['postTypes'] ) ? $item['postTypes'] : array( 'page' ),
+ );
+ }
+ }
+ return $custom_templates;
+ }
+
+ /**
+ * Returns the template part data of current theme.
+ *
+ * @since 5.9.0
+ *
+ * @return array
+ */
+ public function get_template_parts() {
+ $template_parts = array();
+ if ( ! isset( $this->theme_json['templateParts'] ) ) {
+ return $template_parts;
+ }
+
+ foreach ( $this->theme_json['templateParts'] as $item ) {
+ if ( isset( $item['name'] ) ) {
+ $template_parts[ $item['name'] ] = array(
+ 'title' => isset( $item['title'] ) ? $item['title'] : '',
+ 'area' => isset( $item['area'] ) ? $item['area'] : '',
+ );
+ }
+ }
+ return $template_parts;
+ }
+
+ /**
</ins><span class="cx" style="display: block; padding: 0 10px"> * Converts each style section into a list of rulesets
</span><span class="cx" style="display: block; padding: 0 10px"> * containing the block styles to be appended to the stylesheet.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -526,37 +652,15 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * style-property-one: value;
</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">- * Additionally, it'll also create new rulesets
- * as classes for each preset value such as:
- *
- * .has-value-color {
- * color: value;
- * }
- *
- * .has-value-background-color {
- * background-color: value;
- * }
- *
- * .has-value-font-size {
- * font-size: value;
- * }
- *
- * .has-value-gradient-background {
- * background: value;
- * }
- *
- * p.has-value-gradient-background {
- * background: value;
- * }
- *
</del><span class="cx" style="display: block; padding: 0 10px"> * @since 5.8.0
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @since 5.9.0 Renamed to get_block_classes and no longer returns preset classes.
</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 $style_nodes Nodes with styles.
- * @param array $setting_nodes Nodes with settings.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @param array $style_nodes Nodes with styles.
</ins><span class="cx" style="display: block; padding: 0 10px"> * @return string The new stylesheet.
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- private function get_block_styles( $style_nodes, $setting_nodes ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ private function get_block_classes( $style_nodes ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $block_rules = '';
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px"> foreach ( $style_nodes as $metadata ) {
</span><span class="cx" style="display: block; padding: 0 10px"> if ( null === $metadata['selector'] ) {
</span><span class="cx" style="display: block; padding: 0 10px"> continue;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -564,11 +668,77 @@
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $node = _wp_array_get( $this->theme_json, $metadata['path'], array() );
</span><span class="cx" style="display: block; padding: 0 10px"> $selector = $metadata['selector'];
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $declarations = self::compute_style_properties( $node );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $settings = _wp_array_get( $this->theme_json, array( 'settings' ) );
+ $declarations = self::compute_style_properties( $node, $settings );
+
+ // 1. Separate the ones who use the general selector
+ // and the ones who use the duotone selector.
+ $declarations_duotone = array();
+ foreach ( $declarations as $index => $declaration ) {
+ if ( 'filter' === $declaration['name'] ) {
+ unset( $declarations[ $index ] );
+ $declarations_duotone[] = $declaration;
+ }
+ }
+
+ // 2. Generate the rules that use the general selector.
</ins><span class="cx" style="display: block; padding: 0 10px"> $block_rules .= self::to_ruleset( $selector, $declarations );
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+ // 3. Generate the rules that use the duotone selector.
+ if ( isset( $metadata['duotone'] ) && ! empty( $declarations_duotone ) ) {
+ $selector_duotone = self::scope_selector( $metadata['selector'], $metadata['duotone'] );
+ $block_rules .= self::to_ruleset( $selector_duotone, $declarations_duotone );
+ }
+
+ if ( self::ROOT_BLOCK_SELECTOR === $selector ) {
+ $block_rules .= 'body { margin: 0; }';
+ $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; }';
+
+ $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-top: 0; margin-bottom: 0; }';
+ $block_rules .= '.wp-site-blocks > * + * { margin-top: var( --wp--style--block-gap ); }';
+ }
+ }
</ins><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">+ return $block_rules;
+ }
+
+ /**
+ * Creates new rulesets as classes for each preset value such as:
+ *
+ * .has-value-color {
+ * color: value;
+ * }
+ *
+ * .has-value-background-color {
+ * background-color: value;
+ * }
+ *
+ * .has-value-font-size {
+ * font-size: value;
+ * }
+ *
+ * .has-value-gradient-background {
+ * background: value;
+ * }
+ *
+ * p.has-value-gradient-background {
+ * background: value;
+ * }
+ *
+ * @since 5.9.0
+ *
+ * @param array $setting_nodes Nodes with settings.
+ * @param array $origins List of origins to process presets from.
+ * @return string The new stylesheet.
+ */
+ private function get_preset_classes( $setting_nodes, $origins ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $preset_rules = '';
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px"> foreach ( $setting_nodes as $metadata ) {
</span><span class="cx" style="display: block; padding: 0 10px"> if ( null === $metadata['selector'] ) {
</span><span class="cx" style="display: block; padding: 0 10px"> continue;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -576,10 +746,10 @@
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $selector = $metadata['selector'];
</span><span class="cx" style="display: block; padding: 0 10px"> $node = _wp_array_get( $this->theme_json, $metadata['path'], array() );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $preset_rules .= self::compute_preset_classes( $node, $selector );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $preset_rules .= self::compute_preset_classes( $node, $selector, $origins );
</ins><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">- return $block_rules . $preset_rules;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return $preset_rules;
</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">@@ -597,11 +767,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"> * @since 5.8.0
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @since 5.9.0 Added origins parameter.
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @param array $nodes Nodes with settings.
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @param array $origins List of origins to process.
</ins><span class="cx" style="display: block; padding: 0 10px"> * @return string The new stylesheet.
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- private function get_css_variables( $nodes ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ private function get_css_variables( $nodes, $origins ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $stylesheet = '';
</span><span class="cx" style="display: block; padding: 0 10px"> foreach ( $nodes as $metadata ) {
</span><span class="cx" style="display: block; padding: 0 10px"> if ( null === $metadata['selector'] ) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -611,7 +783,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $selector = $metadata['selector'];
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $node = _wp_array_get( $this->theme_json, $metadata['path'], array() );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $declarations = array_merge( self::compute_preset_vars( $node ), self::compute_theme_vars( $node ) );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $declarations = array_merge( self::compute_preset_vars( $node, $origins ), self::compute_theme_vars( $node ) );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $stylesheet .= self::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">@@ -668,45 +840,18 @@
</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">- * Given an array of presets keyed by origin and the value key of the preset,
- * it returns an array where each key is the preset slug and each value the preset value.
- *
- * @since 5.8.0
- *
- * @param array $preset_per_origin Array of presets keyed by origin.
- * @param string $value_key The property of the preset that contains its value.
- * @return array Array of presets where each key is a slug and each value is the preset value.
- */
- private static function get_merged_preset_by_slug( $preset_per_origin, $value_key ) {
- $result = array();
- foreach ( self::VALID_ORIGINS as $origin ) {
- if ( ! isset( $preset_per_origin[ $origin ] ) ) {
- continue;
- }
- foreach ( $preset_per_origin[ $origin ] as $preset ) {
- /*
- * We don't want to use kebabCase here,
- * see https://github.com/WordPress/gutenberg/issues/32347
- * However, we need to make sure the generated class or CSS variable
- * doesn't contain spaces.
- */
- $result[ preg_replace( '/\s+/', '-', $preset['slug'] ) ] = $preset[ $value_key ];
- }
- }
- return $result;
- }
-
- /**
</del><span class="cx" style="display: block; padding: 0 10px"> * Given a settings array, it returns the generated rulesets
</span><span class="cx" style="display: block; padding: 0 10px"> * for the preset classes.
</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><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @since 5.9.0 Added origins parameter.
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @param array $settings Settings to process.
</span><span class="cx" style="display: block; padding: 0 10px"> * @param string $selector Selector wrapping the classes.
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @param array $origins List of origins to process.
</ins><span class="cx" style="display: block; padding: 0 10px"> * @return string The result of processing the presets.
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- private static function compute_preset_classes( $settings, $selector ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ private static function compute_preset_classes( $settings, $selector, $origins ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> if ( self::ROOT_BLOCK_SELECTOR === $selector ) {
</span><span class="cx" style="display: block; padding: 0 10px"> // Classes at the global level do not need any CSS prefixed,
</span><span class="cx" style="display: block; padding: 0 10px"> // and we don't want to increase its specificity.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -714,17 +859,18 @@
</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"> $stylesheet = '';
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- foreach ( self::PRESETS_METADATA as $preset ) {
- $preset_per_origin = _wp_array_get( $settings, $preset['path'], array() );
- $preset_by_slug = self::get_merged_preset_by_slug( $preset_per_origin, $preset['value_key'] );
- foreach ( $preset['classes'] as $class ) {
- foreach ( $preset_by_slug as $slug => $value ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ foreach ( self::PRESETS_METADATA as $preset_metadata ) {
+ $slugs = self::get_settings_slugs( $settings, $preset_metadata, $origins );
+ foreach ( $preset_metadata['classes'] as $class => $property ) {
+ foreach ( $slugs as $slug ) {
+ $css_var = self::replace_slug_in_string( $preset_metadata['css_vars'], $slug );
+ $class_name = self::replace_slug_in_string( $class, $slug );
</ins><span class="cx" style="display: block; padding: 0 10px"> $stylesheet .= self::to_ruleset(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- self::append_to_selector( $selector, '.has-' . _wp_to_kebab_case( $slug ) . '-' . $class['class_suffix'] ),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ self::append_to_selector( $selector, $class_name ),
</ins><span class="cx" style="display: block; padding: 0 10px"> array(
</span><span class="cx" style="display: block; padding: 0 10px"> array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'name' => $class['property_name'],
- 'value' => 'var(--wp--preset--' . $preset['css_var_infix'] . '--' . _wp_to_kebab_case( $slug ) . ') !important',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'name' => $property,
+ 'value' => 'var(' . $css_var . ') !important',
</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">@@ -736,6 +882,147 @@
</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">+ * Function that scopes a selector with another one. This works a bit like
+ * SCSS nesting except the `&` operator isn't supported.
+ *
+ * <code>
+ * $scope = '.a, .b .c';
+ * $selector = '> .x, .y';
+ * $merged = scope_selector( $scope, $selector );
+ * // $merged is '.a > .x, .a .y, .b .c > .x, .b .c .y'
+ * </code>
+ *
+ * @since 5.9.0
+ *
+ * @param string $scope Selector to scope to.
+ * @param string $selector Original selector.
+ *
+ * @return string Scoped selector.
+ */
+ private static function scope_selector( $scope, $selector ) {
+ $scopes = explode( ',', $scope );
+ $selectors = explode( ',', $selector );
+
+ $selectors_scoped = array();
+ foreach ( $scopes as $outer ) {
+ foreach ( $selectors as $inner ) {
+ $selectors_scoped[] = trim( $outer ) . ' ' . trim( $inner );
+ }
+ }
+
+ return implode( ', ', $selectors_scoped );
+ }
+
+ /**
+ * Gets preset values keyed by slugs based on settings and metadata.
+ *
+ * <code>
+ * $settings = array(
+ * 'typography' => array(
+ * 'fontFamilies' => array(
+ * array(
+ * 'slug' => 'sansSerif',
+ * 'fontFamily' => '"Helvetica Neue", sans-serif',
+ * ),
+ * array(
+ * 'slug' => 'serif',
+ * 'colors' => 'Georgia, serif',
+ * )
+ * ),
+ * ),
+ * );
+ * $meta = array(
+ * 'path' => array( 'typography', 'fontFamilies' ),
+ * 'value_key' => 'fontFamily',
+ * );
+ * $values_by_slug = get_settings_values_by_slug();
+ * // $values_by_slug === array(
+ * // 'sans-serif' => '"Helvetica Neue", sans-serif',
+ * // 'serif' => 'Georgia, serif',
+ * // );
+ * </code>
+ *
+ * @since 5.9.0
+ *
+ * @param array $settings Settings to process.
+ * @param array $preset_metadata One of the PRESETS_METADATA values.
+ * @param array $origins List of origins to process.
+ * @return array Array of presets where each key is a slug and each value is the preset value.
+ */
+ private static function get_settings_values_by_slug( $settings, $preset_metadata, $origins ) {
+ $preset_per_origin = _wp_array_get( $settings, $preset_metadata['path'], array() );
+
+ $result = array();
+ foreach ( $origins as $origin ) {
+ if ( ! isset( $preset_per_origin[ $origin ] ) ) {
+ continue;
+ }
+ foreach ( $preset_per_origin[ $origin ] as $preset ) {
+ $slug = _wp_to_kebab_case( $preset['slug'] );
+
+ $value = '';
+ if ( isset( $preset_metadata['value_key'] ) ) {
+ $value_key = $preset_metadata['value_key'];
+ $value = $preset[ $value_key ];
+ } elseif (
+ isset( $preset_metadata['value_func'] ) &&
+ is_callable( $preset_metadata['value_func'] )
+ ) {
+ $value_func = $preset_metadata['value_func'];
+ $value = call_user_func( $value_func, $preset );
+ } else {
+ // If we don't have a value, then don't add it to the result.
+ continue;
+ }
+
+ $result[ $slug ] = $value;
+ }
+ }
+ return $result;
+ }
+
+ /**
+ * Similar to get_settings_values_by_slug, but doesn't compute the value.
+ *
+ * @since 5.9.0
+ *
+ * @param array $settings Settings to process.
+ * @param array $preset_metadata One of the PRESETS_METADATA values.
+ * @param array $origins List of origins to process.
+ * @return array Array of presets where the key and value are both the slug.
+ */
+ private static function get_settings_slugs( $settings, $preset_metadata, $origins = self::VALID_ORIGINS ) {
+ $preset_per_origin = _wp_array_get( $settings, $preset_metadata['path'], array() );
+
+ $result = array();
+ foreach ( $origins as $origin ) {
+ if ( ! isset( $preset_per_origin[ $origin ] ) ) {
+ continue;
+ }
+ foreach ( $preset_per_origin[ $origin ] as $preset ) {
+ $slug = _wp_to_kebab_case( $preset['slug'] );
+
+ // Use the array as a set so we don't get duplicates.
+ $result[ $slug ] = $slug;
+ }
+ }
+ return $result;
+ }
+
+ /**
+ * Transform a slug into a CSS Custom Property.
+ *
+ * @since 5.9.0
+ *
+ * @param string $input String to replace.
+ * @param string $slug The slug value to use to generate the custom property.
+ * @return string The CSS Custom Property. Something along the lines of --wp--preset--color--black.
+ */
+ private static function replace_slug_in_string( $input, $slug ) {
+ return strtr( $input, array( '$slug' => $slug ) );
+ }
+
+ /**
</ins><span class="cx" style="display: block; padding: 0 10px"> * Given the block settings, it extracts the CSS Custom Properties
</span><span class="cx" style="display: block; padding: 0 10px"> * for the presets and adds them to the $declarations array
</span><span class="cx" style="display: block; padding: 0 10px"> * following the format:
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -748,16 +1035,16 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @since 5.8.0
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @param array $settings Settings to process.
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @param array $origins List of origins to process.
</ins><span class="cx" style="display: block; padding: 0 10px"> * @return array Returns the modified $declarations.
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- private static function compute_preset_vars( $settings ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ private static function compute_preset_vars( $settings, $origins ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $declarations = array();
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- foreach ( self::PRESETS_METADATA as $preset ) {
- $preset_per_origin = _wp_array_get( $settings, $preset['path'], array() );
- $preset_by_slug = self::get_merged_preset_by_slug( $preset_per_origin, $preset['value_key'] );
- foreach ( $preset_by_slug as $slug => $value ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ foreach ( self::PRESETS_METADATA as $preset_metadata ) {
+ $values_by_slug = self::get_settings_values_by_slug( $settings, $preset_metadata, $origins );
+ foreach ( $values_by_slug as $slug => $value ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $declarations[] = array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'name' => '--wp--preset--' . $preset['css_var_infix'] . '--' . _wp_to_kebab_case( $slug ),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'name' => self::replace_slug_in_string( $preset_metadata['css_vars'], $slug ),
</ins><span class="cx" style="display: block; padding: 0 10px"> 'value' => $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">@@ -864,46 +1151,42 @@
</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"> * @since 5.8.0
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @since 5.9.0 Added theme setting and properties parameters.
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @param array $styles Styles to process.
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @param array $settings Theme settings.
+ * @param array $properties Properties metadata.
</ins><span class="cx" style="display: block; padding: 0 10px"> * @return array Returns the modified $declarations.
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- private static function compute_style_properties( $styles ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ private static function compute_style_properties( $styles, $settings = array(), $properties = self::PROPERTIES_METADATA ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $declarations = array();
</span><span class="cx" style="display: block; padding: 0 10px"> if ( empty( $styles ) ) {
</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><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $properties = array();
- foreach ( self::PROPERTIES_METADATA as $name => $metadata ) {
- /*
- * Some properties can be shorthand properties, meaning that
- * they contain multiple values instead of a single one.
- * An example of this is the padding property.
- */
- if ( self::has_properties( $metadata ) ) {
- foreach ( $metadata['properties'] as $property ) {
- $properties[] = array(
- 'name' => $name . '-' . $property,
- 'value' => array_merge( $metadata['value'], array( $property ) ),
- );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ foreach ( $properties as $css_property => $value_path ) {
+ $value = self::get_property_value( $styles, $value_path );
+
+ // Look up protected properties, keyed by value path.
+ // Skip protected properties that are explicitly set to `null`.
+ if ( is_array( $value_path ) ) {
+ $path_string = implode( '.', $value_path );
+ if (
+ array_key_exists( $path_string, self::PROTECTED_PROPERTIES ) &&
+ _wp_array_get( $settings, self::PROTECTED_PROPERTIES[ $path_string ], null ) === null
+ ) {
+ continue;
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- } else {
- $properties[] = array(
- 'name' => $name,
- 'value' => $metadata['value'],
- );
</del><span class="cx" style="display: block; padding: 0 10px"> }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- }
</del><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- foreach ( $properties as $prop ) {
- $value = self::get_property_value( $styles, $prop['value'] );
- if ( empty( $value ) ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Skip if empty and not "0" or value represents array of longhand values.
+ $has_missing_value = empty( $value ) && ! is_numeric( $value );
+ if ( $has_missing_value || is_array( $value ) ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> continue;
</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"> $declarations[] = array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'name' => $prop['name'],
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'name' => $css_property,
</ins><span class="cx" style="display: block; padding: 0 10px"> 'value' => $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">@@ -912,22 +1195,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">- * Whether the metadata contains a key named properties.
- *
- * @since 5.8.0
- *
- * @param array $metadata Description of the style property.
- * @return bool True if properties exists, false otherwise.
- */
- private static function has_properties( $metadata ) {
- if ( array_key_exists( 'properties', $metadata ) ) {
- return true;
- }
-
- return false;
- }
-
- /**
</del><span class="cx" style="display: block; padding: 0 10px"> * Returns the style property for the given path.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * It also converts CSS Custom Property stored as
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -935,6 +1202,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * "--wp--preset--color--secondary".
</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><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @since 5.9.0 Consider $value that are arrays as well.
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @param array $styles Styles subtree.
</span><span class="cx" style="display: block; padding: 0 10px"> * @param array $path Which property to process.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -943,7 +1211,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> private static function get_property_value( $styles, $path ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $value = _wp_array_get( $styles, $path, '' );
</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 ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( '' === $value || 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">@@ -1015,7 +1283,6 @@
</span><span class="cx" style="display: block; padding: 0 10px"> return $nodes;
</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">-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Builds metadata for the style nodes, which returns in the form of:
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1022,11 +1289,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"> * 'path' => [ 'path', 'to', 'some', 'node' ],
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * 'selector' => 'CSS selector for some node'
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * 'selector' => 'CSS selector for some node',
+ * 'duotone' => 'CSS selector for duotone for some 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"> * 'path' => ['path', 'to', 'other', 'node' ],
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * 'selector' => 'CSS selector for other node'
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * 'selector' => 'CSS selector for other node',
+ * 'duotone' => null
</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">@@ -1068,9 +1337,15 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $selector = $selectors[ $name ]['selector'];
</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">+ $duotone_selector = null;
+ if ( isset( $selectors[ $name ]['duotone'] ) ) {
+ $duotone_selector = $selectors[ $name ]['duotone'];
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> $nodes[] = array(
</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><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'duotone' => $duotone_selector,
</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">@@ -1090,6 +1365,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * Merge new incoming data.
</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><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @since 5.9.0 Duotone preset also has origins.
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @param WP_Theme_JSON $incoming Data to merge.
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1098,14 +1374,14 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $this->theme_json = array_replace_recursive( $this->theme_json, $incoming_data );
</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">- * The array_replace_recursive() algorithm merges at the leaf level.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * The array_replace_recursive algorithm merges at the leaf level.
</ins><span class="cx" style="display: block; padding: 0 10px"> * For leaf values that are arrays it will use the numeric indexes for replacement.
</span><span class="cx" style="display: block; padding: 0 10px"> * In those cases, we want to replace the existing with the incoming value, if it exists.
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> $to_replace = array();
</span><span class="cx" style="display: block; padding: 0 10px"> $to_replace[] = array( 'spacing', 'units' );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $to_replace[] = array( 'color', 'duotone' );
</del><span class="cx" style="display: block; padding: 0 10px"> foreach ( self::VALID_ORIGINS as $origin ) {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $to_replace[] = array( 'color', 'duotone', $origin );
</ins><span class="cx" style="display: block; padding: 0 10px"> $to_replace[] = array( 'color', 'palette', $origin );
</span><span class="cx" style="display: block; padding: 0 10px"> $to_replace[] = array( 'color', 'gradients', $origin );
</span><span class="cx" style="display: block; padding: 0 10px"> $to_replace[] = array( 'typography', 'fontSizes', $origin );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1122,9 +1398,167 @@
</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">+
</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><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Removes insecure data from theme.json.
+ *
+ * @since 5.9.0
+ *
+ * @param array $theme_json Structure to sanitize.
+ * @return array Sanitized structure.
+ */
+ public static function remove_insecure_properties( $theme_json ) {
+ $sanitized = array();
+
+ $theme_json = WP_Theme_JSON_Schema::migrate( $theme_json );
+
+ $valid_block_names = array_keys( self::get_blocks_metadata() );
+ $valid_element_names = array_keys( self::ELEMENTS );
+ $theme_json = self::sanitize( $theme_json, $valid_block_names, $valid_element_names );
+
+ $blocks_metadata = self::get_blocks_metadata();
+ $style_nodes = self::get_style_nodes( $theme_json, $blocks_metadata );
+ foreach ( $style_nodes as $metadata ) {
+ $input = _wp_array_get( $theme_json, $metadata['path'], array() );
+ if ( empty( $input ) ) {
+ continue;
+ }
+
+ $output = self::remove_insecure_styles( $input );
+ if ( ! empty( $output ) ) {
+ _wp_array_set( $sanitized, $metadata['path'], $output );
+ }
+ }
+
+ $setting_nodes = self::get_setting_nodes( $theme_json );
+ foreach ( $setting_nodes as $metadata ) {
+ $input = _wp_array_get( $theme_json, $metadata['path'], array() );
+ if ( empty( $input ) ) {
+ continue;
+ }
+
+ $output = self::remove_insecure_settings( $input );
+ if ( ! empty( $output ) ) {
+ _wp_array_set( $sanitized, $metadata['path'], $output );
+ }
+ }
+
+ if ( empty( $sanitized['styles'] ) ) {
+ unset( $theme_json['styles'] );
+ } else {
+ $theme_json['styles'] = $sanitized['styles'];
+ }
+
+ if ( empty( $sanitized['settings'] ) ) {
+ unset( $theme_json['settings'] );
+ } else {
+ $theme_json['settings'] = $sanitized['settings'];
+ }
+
+ return $theme_json;
+ }
+
+ /**
+ * Processes a setting node and returns the same node
+ * without the insecure settings.
+ *
+ * @since 5.9.0
+ *
+ * @param array $input Node to process.
+ * @return array
+ */
+ private static function remove_insecure_settings( $input ) {
+ $output = array();
+ foreach ( self::PRESETS_METADATA as $preset_metadata ) {
+ $presets = _wp_array_get( $input, $preset_metadata['path'], null );
+ if ( null === $presets ) {
+ continue;
+ }
+
+ $escaped_preset = array();
+ foreach ( $presets as $preset ) {
+ if (
+ esc_attr( esc_html( $preset['name'] ) ) === $preset['name'] &&
+ sanitize_html_class( $preset['slug'] ) === $preset['slug']
+ ) {
+ $value = null;
+ if ( isset( $preset_metadata['value_key'] ) ) {
+ $value = $preset[ $preset_metadata['value_key'] ];
+ } elseif (
+ isset( $preset_metadata['value_func'] ) &&
+ is_callable( $preset_metadata['value_func'] )
+ ) {
+ $value = call_user_func( $preset_metadata['value_func'], $preset );
+ }
+
+ $preset_is_valid = true;
+ foreach ( $preset_metadata['properties'] as $property ) {
+ if ( ! self::is_safe_css_declaration( $property, $value ) ) {
+ $preset_is_valid = false;
+ break;
+ }
+ }
+
+ if ( $preset_is_valid ) {
+ $escaped_preset[] = $preset;
+ }
+ }
+ }
+
+ if ( ! empty( $escaped_preset ) ) {
+ _wp_array_set( $output, $preset_metadata['path'], $escaped_preset );
+ }
+ }
+
+ return $output;
+ }
+
+ /**
+ * Processes a style node and returns the same node
+ * without the insecure styles.
+ *
+ * @since 5.9.0
+ *
+ * @param array $input Node to process.
+ * @return array
+ */
+ private static function remove_insecure_styles( $input ) {
+ $output = array();
+ $declarations = self::compute_style_properties( $input );
+
+ foreach ( $declarations as $declaration ) {
+ if ( self::is_safe_css_declaration( $declaration['name'], $declaration['value'] ) ) {
+ $path = self::PROPERTIES_METADATA[ $declaration['name'] ];
+
+ // Check the value isn't an array before adding so as to not
+ // double up shorthand and longhand styles.
+ $value = _wp_array_get( $input, $path, array() );
+ if ( ! is_array( $value ) ) {
+ _wp_array_set( $output, $path, $value );
+ }
+ }
+ }
+ return $output;
+ }
+
+ /**
+ * Checks that a declaration provided by the user is safe.
+ *
+ * @since 5.9.0
+ *
+ * @param string $property_name Property name in a CSS declaration, i.e. the `color` in `color: red`.
+ * @param string $property_value Value in a CSS declaration, i.e. the `red` in `color: red`.
+ * @return boolean
+ */
+ private static function is_safe_css_declaration( $property_name, $property_value ) {
+ $style_to_validate = $property_name . ': ' . $property_value;
+ $filtered = esc_html( safecss_filter_attr( $style_to_validate ) );
+ return ! empty( trim( $filtered ) );
+ }
+
+ /**
</ins><span class="cx" style="display: block; padding: 0 10px"> * Returns the raw data.
</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="lines" style="display: block; padding: 0 10px; color: #888">@@ -1176,7 +1610,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> if ( ! isset( $theme_settings['settings']['typography'] ) ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $theme_settings['settings']['typography'] = array();
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $theme_settings['settings']['typography']['customLineHeight'] = $settings['enableCustomLineHeight'];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $theme_settings['settings']['typography']['lineHeight'] = $settings['enableCustomLineHeight'];
</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( $settings['enableCustomUnits'] ) ) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1220,7 +1654,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> if ( ! isset( $theme_settings['settings']['spacing'] ) ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $theme_settings['settings']['spacing'] = array();
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $theme_settings['settings']['spacing']['customPadding'] = $settings['enableCustomSpacing'];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $theme_settings['settings']['spacing']['padding'] = $settings['enableCustomSpacing'];
</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 $theme_settings;
</span></span></pre></div>
<a id="trunksrcwpincludesdefaultfiltersphp"></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/default-filters.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/default-filters.php 2021-11-08 17:07:49 UTC (rev 52048)
+++ trunk/src/wp-includes/default-filters.php 2021-11-08 19:18:39 UTC (rev 52049)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -336,6 +336,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> add_action( 'init', 'check_theme_switched', 99 );
</span><span class="cx" style="display: block; padding: 0 10px"> add_action( 'init', array( 'WP_Block_Supports', 'init' ), 22 );
</span><span class="cx" style="display: block; padding: 0 10px"> add_action( 'switch_theme', array( 'WP_Theme_JSON_Resolver', 'clean_cached_data' ) );
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+add_action( 'start_previewing_theme', array( 'WP_Theme_JSON_Resolver', 'clean_cached_data' ) );
</ins><span class="cx" style="display: block; padding: 0 10px"> add_action( 'after_switch_theme', '_wp_menus_changed' );
</span><span class="cx" style="display: block; padding: 0 10px"> add_action( 'after_switch_theme', '_wp_sidebars_changed' );
</span><span class="cx" style="display: block; padding: 0 10px"> add_action( 'wp_print_styles', 'print_emoji_styles' );
</span></span></pre></div>
<a id="trunksrcwpincludesksesphp"></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/kses.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/kses.php 2021-11-08 17:07:49 UTC (rev 52048)
+++ trunk/src/wp-includes/kses.php 2021-11-08 19:18:39 UTC (rev 52049)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2260,6 +2260,8 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 'border-bottom-color',
</span><span class="cx" style="display: block; padding: 0 10px"> 'border-bottom-style',
</span><span class="cx" style="display: block; padding: 0 10px"> 'border-bottom-width',
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'border-bottom-right-radius',
+ 'border-bottom-left-radius',
</ins><span class="cx" style="display: block; padding: 0 10px"> 'border-left',
</span><span class="cx" style="display: block; padding: 0 10px"> 'border-left-color',
</span><span class="cx" style="display: block; padding: 0 10px"> 'border-left-style',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2268,6 +2270,8 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 'border-top-color',
</span><span class="cx" style="display: block; padding: 0 10px"> 'border-top-style',
</span><span class="cx" style="display: block; padding: 0 10px"> 'border-top-width',
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'border-top-left-radius',
+ 'border-top-right-radius',
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> 'border-spacing',
</span><span class="cx" style="display: block; padding: 0 10px"> 'border-collapse',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2282,6 +2286,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 'column-width',
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> 'color',
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'filter',
</ins><span class="cx" style="display: block; padding: 0 10px"> 'font',
</span><span class="cx" style="display: block; padding: 0 10px"> 'font-family',
</span><span class="cx" style="display: block; padding: 0 10px"> 'font-size',
</span></span></pre></div>
<a id="trunksrcwpincludesscriptloaderphp"></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/script-loader.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/script-loader.php 2021-11-08 17:07:49 UTC (rev 52048)
+++ trunk/src/wp-includes/script-loader.php 2021-11-08 19:18:39 UTC (rev 52049)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2321,8 +2321,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"> if ( null === $stylesheet ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $settings = get_default_block_editor_settings();
- $theme_json = WP_Theme_JSON_Resolver::get_merged_data( $settings );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $theme_json = WP_Theme_JSON_Resolver::get_merged_data();
</ins><span class="cx" style="display: block; padding: 0 10px"> $stylesheet = $theme_json->get_stylesheet();
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> if ( $can_use_cache ) {
</span></span></pre></div>
<a id="trunksrcwpincludesthemei18njson"></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-i18n.json</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/theme-i18n.json 2021-11-08 17:07:49 UTC (rev 52048)
+++ trunk/src/wp-includes/theme-i18n.json 2021-11-08 19:18:39 UTC (rev 52049)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -5,6 +5,11 @@
</span><span class="cx" style="display: block; padding: 0 10px"> {
</span><span class="cx" style="display: block; padding: 0 10px"> "name": "Font size name"
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ ],
+ "fontFamilies": [
+ {
+ "name": "Font family name"
+ }
</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"> "color": {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -31,6 +36,11 @@
</span><span class="cx" style="display: block; padding: 0 10px"> {
</span><span class="cx" style="display: block; padding: 0 10px"> "name": "Font size name"
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ ],
+ "fontFamilies": [
+ {
+ "name": "Font family name"
+ }
</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"> "color": {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -47,5 +57,15 @@
</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">- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ },
+ "customTemplates": [
+ {
+ "title": "Custom template name"
+ }
+ ],
+ "templateParts": [
+ {
+ "title": "Template part name"
+ }
+ ]
</ins><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 2021-11-08 17:07:49 UTC (rev 52048)
+++ trunk/src/wp-includes/theme.json 2021-11-08 19:18:39 UTC (rev 52049)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,8 +1,11 @@
</span><span class="cx" style="display: block; padding: 0 10px"> {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- "version": 1,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "version": 2,
</ins><span class="cx" style="display: block; padding: 0 10px"> "settings": {
</span><span class="cx" style="display: block; padding: 0 10px"> "border": {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- "customRadius": false
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "color": false,
+ "radius": false,
+ "style": false,
+ "width": false
</ins><span class="cx" style="display: block; padding: 0 10px"> },
</span><span class="cx" style="display: block; padding: 0 10px"> "color": {
</span><span class="cx" style="display: block; padding: 0 10px"> "custom": true,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -9,6 +12,8 @@
</span><span class="cx" style="display: block; padding: 0 10px"> "customDuotone": true,
</span><span class="cx" style="display: block; padding: 0 10px"> "customGradient": true,
</span><span class="cx" style="display: block; padding: 0 10px"> "link": false,
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "background": true,
+ "text": true,
</ins><span class="cx" style="display: block; padding: 0 10px"> "duotone": [
</span><span class="cx" style="display: block; padding: 0 10px"> {
</span><span class="cx" style="display: block; padding: 0 10px"> "name": "Dark grayscale" ,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -177,14 +182,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"> "spacing": {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- "customMargin": false,
- "customPadding": false,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "blockGap": null,
+ "margin": false,
+ "padding": false,
</ins><span class="cx" style="display: block; padding: 0 10px"> "units": [ "px", "em", "rem", "vh", "vw", "%" ]
</span><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><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- "customLineHeight": false,
</del><span class="cx" style="display: block; padding: 0 10px"> "dropCap": true,
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "fontStyle": true,
+ "fontWeight": true,
+ "letterSpacing": true,
+ "lineHeight": false,
+ "textDecoration": true,
+ "textTransform": true,
</ins><span class="cx" style="display: block; padding: 0 10px"> "fontSizes": [
</span><span class="cx" style="display: block; padding: 0 10px"> {
</span><span class="cx" style="display: block; padding: 0 10px"> "name": "Small",
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -216,9 +227,20 @@
</span><span class="cx" style="display: block; padding: 0 10px"> "blocks": {
</span><span class="cx" style="display: block; padding: 0 10px"> "core/button": {
</span><span class="cx" style="display: block; padding: 0 10px"> "border": {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- "customRadius": true
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "radius": true
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ },
+ "core/pullquote": {
+ "border": {
+ "color": true,
+ "radius": true,
+ "style": true,
+ "width": true
+ }
</ins><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">+ },
+ "styles": {
+ "spacing": { "blockGap": "24px" }
</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="trunksrcwpsettingsphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-settings.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-settings.php 2021-11-08 17:07:49 UTC (rev 52048)
+++ trunk/src/wp-settings.php 2021-11-08 19:18:39 UTC (rev 52049)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -170,6 +170,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> require ABSPATH . WPINC . '/class-wp-date-query.php';
</span><span class="cx" style="display: block; padding: 0 10px"> require ABSPATH . WPINC . '/theme.php';
</span><span class="cx" style="display: block; padding: 0 10px"> require ABSPATH . WPINC . '/class-wp-theme.php';
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+require ABSPATH . WPINC . '/class-wp-theme-json-schema.php';
</ins><span class="cx" style="display: block; padding: 0 10px"> require ABSPATH . WPINC . '/class-wp-theme-json.php';
</span><span class="cx" style="display: block; padding: 0 10px"> require ABSPATH . WPINC . '/class-wp-theme-json-resolver.php';
</span><span class="cx" style="display: block; padding: 0 10px"> require ABSPATH . WPINC . '/class-wp-block-template.php';
</span></span></pre></div>
<a id="trunktestsphpunitdatalanguagesthemesblockthemepl_PLpo"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/data/languages/themes/block-theme-pl_PL.po</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/data/languages/themes/block-theme-pl_PL.po 2021-11-08 17:07:49 UTC (rev 52048)
+++ trunk/tests/phpunit/data/languages/themes/block-theme-pl_PL.po 2021-11-08 19:18:39 UTC (rev 52049)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -22,6 +22,10 @@
</span><span class="cx" style="display: block; padding: 0 10px"> msgid "Homepage template"
</span><span class="cx" style="display: block; padding: 0 10px"> msgstr "Szablon strony głównej"
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+msgctxt "Template part name"
+msgid "Small Header"
+msgstr "Mały nagłówek"
+
</ins><span class="cx" style="display: block; padding: 0 10px"> msgctxt "Color name"
</span><span class="cx" style="display: block; padding: 0 10px"> msgid "Light"
</span><span class="cx" style="display: block; padding: 0 10px"> msgstr "Jasny"
</span></span></pre></div>
<a id="trunktestsphpunitdatathemedir1blockthemethemejson"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/data/themedir1/block-theme/theme.json</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/data/themedir1/block-theme/theme.json 2021-11-08 17:07:49 UTC (rev 52048)
+++ trunk/tests/phpunit/data/themedir1/block-theme/theme.json 2021-11-08 19:18:39 UTC (rev 52049)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -64,6 +64,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> "templateParts": [
</span><span class="cx" style="display: block; padding: 0 10px"> {
</span><span class="cx" style="display: block; padding: 0 10px"> "name": "small-header",
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "title": "Small Header",
</ins><span class="cx" style="display: block; padding: 0 10px"> "area": "header"
</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="trunktestsphpunitdatathemedir1blockthemechildstylecss"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/tests/phpunit/data/themedir1/block-theme-child/style.css</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/data/themedir1/block-theme-child/style.css (rev 0)
+++ trunk/tests/phpunit/data/themedir1/block-theme-child/style.css 2021-11-08 19:18:39 UTC (rev 52049)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,8 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/*
+Theme Name: Block Theme Child Theme
+Theme URI: https://wordpress.org/
+Description: For testing purposes only.
+Template: block-theme
+Version: 1.0.0
+Text Domain: block-theme-child
+*/
</ins></span></pre></div>
<a id="trunktestsphpunitdatathemedir1blockthemechildthemejson"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/tests/phpunit/data/themedir1/block-theme-child/theme.json</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/data/themedir1/block-theme-child/theme.json (rev 0)
+++ trunk/tests/phpunit/data/themedir1/block-theme-child/theme.json 2021-11-08 19:18:39 UTC (rev 52049)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,51 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+{
+ "version": 1,
+ "settings": {
+ "color": {
+ "palette": [
+ {
+ "slug": "light",
+ "name": "Light",
+ "color": "#f3f4f6"
+ },
+ {
+ "slug": "primary",
+ "name": "Primary",
+ "color": "#3858e9"
+ },
+ {
+ "slug": "dark",
+ "name": "Dark",
+ "color": "#111827"
+ }
+ ],
+ "link": true
+ },
+ "blocks": {
+ "core/post-title": {
+ "color": {
+ "palette": [
+ {
+ "slug": "light",
+ "name": "Light",
+ "color": "#f3f4f6"
+ }
+ ]
+ }
+ }
+ }
+ },
+ "customTemplates": [
+ {
+ "name": "page-home",
+ "title": "Homepage"
+ }
+ ],
+ "templateParts": [
+ {
+ "name": "small-header",
+ "title": "Small Header",
+ "area": "header"
+ }
+ ]
+}
</ins></span></pre></div>
<a id="trunktestsphpunitteststhemethemeDirphp"></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/themeDir.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/theme/themeDir.php 2021-11-08 17:07:49 UTC (rev 52048)
+++ trunk/tests/phpunit/tests/theme/themeDir.php 2021-11-08 19:18:39 UTC (rev 52049)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -162,6 +162,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 'camelCase',
</span><span class="cx" style="display: block; padding: 0 10px"> 'REST Theme',
</span><span class="cx" style="display: block; padding: 0 10px"> 'Block Theme',
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'Block Theme Child Theme',
</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"> sort( $theme_names );
</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 2021-11-08 17:07:49 UTC (rev 52048)
+++ trunk/tests/phpunit/tests/theme/wpThemeJson.php 2021-11-08 19:18:39 UTC (rev 52049)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -15,6 +15,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"> * @ticket 52991
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 54336
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function test_get_settings() {
</span><span class="cx" style="display: block; padding: 0 10px"> $theme_json = new WP_Theme_JSON(
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -24,6 +25,10 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 'color' => array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'custom' => false,
</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' => array(
+ 'contentSize' => 'value',
+ 'invalid/key' => 'value',
+ ),
</ins><span class="cx" style="display: block; padding: 0 10px"> 'invalid/key' => 'value',
</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="lines" style="display: block; padding: 0 10px; color: #888">@@ -52,6 +57,9 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 'color' => array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'custom' => false,
</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' => array(
+ 'contentSize' => 'value',
+ ),
</ins><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"> 'color' => array(
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -61,7 +69,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">- $this->assertSameSetsWithIndex( $expected, $actual );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $this->assertEqualSetsWithIndex( $expected, $actual );
</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">@@ -193,7 +201,116 @@
</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">+ * @ticket 54336
+ */
+ public function test_get_stylesheet_support_for_shorthand_and_longhand_values() {
+ $theme_json = new WP_Theme_JSON(
+ array(
+ 'version' => WP_Theme_JSON::LATEST_SCHEMA,
+ 'styles' => array(
+ 'blocks' => array(
+ 'core/group' => array(
+ 'border' => array(
+ 'radius' => '10px',
+ ),
+ 'spacing' => array(
+ 'padding' => '24px',
+ 'margin' => '1em',
+ ),
+ ),
+ 'core/image' => array(
+ 'border' => array(
+ 'radius' => array(
+ 'topLeft' => '10px',
+ 'bottomRight' => '1em',
+ ),
+ ),
+ 'spacing' => array(
+ 'padding' => array(
+ 'top' => '15px',
+ ),
+ 'margin' => array(
+ 'bottom' => '30px',
+ ),
+ ),
+ ),
+ ),
+ ),
+ )
+ );
+
+ $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; }.wp-block-group{border-radius: 10px;margin: 1em;padding: 24px;}.wp-block-image{border-top-left-radius: 10px;border-bottom-right-radius: 1em;margin-bottom: 30px;padding-top: 15px;}';
+ $this->assertEquals( $styles, $theme_json->get_stylesheet() );
+ $this->assertEquals( $styles, $theme_json->get_stylesheet( array( 'styles' ) ) );
+ }
+
+ /**
+ * @ticket 54336
+ */
+ public function test_get_stylesheet_skips_disabled_protected_properties() {
+ $theme_json = new WP_Theme_JSON(
+ array(
+ 'version' => WP_Theme_JSON::LATEST_SCHEMA,
+ 'settings' => array(
+ 'spacing' => array(
+ 'blockGap' => null,
+ ),
+ ),
+ 'styles' => array(
+ 'spacing' => array(
+ 'blockGap' => '1em',
+ ),
+ 'blocks' => array(
+ 'core/columns' => array(
+ 'spacing' => array(
+ 'blockGap' => '24px',
+ ),
+ ),
+ ),
+ ),
+ )
+ );
+
+ $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; }';
+ $this->assertEquals( $expected, $theme_json->get_stylesheet() );
+ $this->assertEquals( $expected, $theme_json->get_stylesheet( array( 'styles' ) ) );
+ }
+
+ /**
+ * @ticket 54336
+ */
+ public function test_get_stylesheet_renders_enabled_protected_properties() {
+ $theme_json = new WP_Theme_JSON(
+ array(
+ 'version' => WP_Theme_JSON::LATEST_SCHEMA,
+ 'settings' => array(
+ 'spacing' => array(
+ 'blockGap' => true,
+ ),
+ ),
+ 'styles' => array(
+ 'spacing' => array(
+ 'blockGap' => '1em',
+ ),
+ 'blocks' => array(
+ 'core/columns' => array(
+ 'spacing' => array(
+ 'blockGap' => '24px',
+ ),
+ ),
+ ),
+ ),
+ )
+ );
+
+ $expected = 'body{--wp--style--block-gap: 1em;}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-top: 0; margin-bottom: 0; }.wp-site-blocks > * + * { margin-top: var( --wp--style--block-gap ); }.wp-block-columns{--wp--style--block-gap: 24px;}';
+ $this->assertEquals( $expected, $theme_json->get_stylesheet() );
+ $this->assertEquals( $expected, $theme_json->get_stylesheet( array( 'styles' ) ) );
+ }
+
+ /**
</ins><span class="cx" style="display: block; padding: 0 10px"> * @ticket 53175
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 54336
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function test_get_stylesheet() {
</span><span class="cx" style="display: block; padding: 0 10px"> $theme_json = new WP_Theme_JSON(
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -221,6 +338,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' => false,
+ ),
</ins><span class="cx" style="display: block; padding: 0 10px"> 'misc' => 'value',
</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="lines" style="display: block; padding: 0 10px; color: #888">@@ -250,6 +370,9 @@
</span><span class="cx" style="display: block; padding: 0 10px"> ),
</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><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'border' => array(
+ 'radius' => '10px',
+ ),
</ins><span class="cx" style="display: block; padding: 0 10px"> 'elements' => array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'link' => array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'color' => array(
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -258,10 +381,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"> 'spacing' => array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'padding' => array(
- 'top' => '12px',
- 'bottom' => '24px',
- ),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'padding' => '24px',
</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"> 'core/heading' => array(
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -293,6 +413,19 @@
</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">+ 'core/image' => array(
+ 'border' => array(
+ 'radius' => array(
+ 'topLeft' => '10px',
+ 'bottomRight' => '1em',
+ ),
+ ),
+ 'spacing' => array(
+ 'margin' => array(
+ 'bottom' => '30px',
+ ),
+ ),
+ ),
</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"> 'misc' => 'value',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -299,22 +432,19 @@
</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">- $this->assertSame(
- 'body{--wp--preset--color--grey: grey;}.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;}body{color: var(--wp--preset--color--grey);}a{background-color: #333;color: #111;}.wp-block-group{padding-top: 12px;padding-bottom: 24px;}.wp-block-group a{color: #111;}h1,h2,h3,h4,h5,h6{color: #123456;}h1 a,h2 a,h3 a,h4 a,h5 a,h6 a{background-color: #333;color: #111;font-size: 60px;}.wp-block-post-date{color: #123456;}.wp-block-post-date a{background-color: #777;color: #555;}.has-grey-color{color: var(--wp--preset--color--grey) !important;}.has-grey-background-color{background-color: var(--wp--preset--color--grey) !important;}',
- $theme_json->get_stylesheet()
- );
- $this->assertSame(
- 'body{color: var(--wp--preset--color--grey);}a{background-color: #333;color: #111;}.wp-block-group{padding-top: 12px;padding-bottom: 24px;}.wp-block-group a{color: #111;}h1,h2,h3,h4,h5,h6{color: #123456;}h1 a,h2 a,h3 a,h4 a,h5 a,h6 a{background-color: #333;color: #111;font-size: 60px;}.wp-block-post-date{color: #123456;}.wp-block-post-date a{background-color: #777;color: #555;}.has-grey-color{color: var(--wp--preset--color--grey) !important;}.has-grey-background-color{background-color: var(--wp--preset--color--grey) !important;}',
- $theme_json->get_stylesheet( 'block_styles' )
- );
- $this->assertSame(
- 'body{--wp--preset--color--grey: grey;}.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;}',
- $theme_json->get_stylesheet( 'css_variables' )
- );
</del><ins style="background-color: #dfd; text-decoration:none; 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;}';
+ $styles = 'body{color: var(--wp--preset--color--grey);}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-top: 0; margin-bottom: 0; }.wp-site-blocks > * + * { margin-top: var( --wp--style--block-gap ); }a{background-color: #333;color: #111;}.wp-block-group{border-radius: 10px;padding: 24px;}.wp-block-group a{color: #111;}h1,h2,h3,h4,h5,h6{color: #123456;}h1 a,h2 a,h3 a,h4 a,h5 a,h6 a{background-color: #333;color: #111;font-size: 60px;}.wp-block-post-date{color: #123456;}.wp-block-post-date a{background-color: #777;color: #555;}.wp-block-image{border-top-left-radius: 10px;border-bottom-right-radius: 1em;margin-bottom: 30px;}';
+ $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;}';
+ $all = $variables . $styles . $presets;
+ $this->assertEquals( $all, $theme_json->get_stylesheet() );
+ $this->assertEquals( $styles, $theme_json->get_stylesheet( array( 'styles' ) ) );
+ $this->assertEquals( $presets, $theme_json->get_stylesheet( array( 'presets' ) ) );
+ $this->assertEquals( $variables, $theme_json->get_stylesheet( array( 'variables' ) ) );
</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="cx" style="display: block; padding: 0 10px"> * @ticket 52991
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 54336
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function test_get_stylesheet_preset_classes_work_with_compounded_selectors() {
</span><span class="cx" style="display: block; padding: 0 10px"> $theme_json = new WP_Theme_JSON(
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -337,14 +467,15 @@
</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">- $this->assertSame(
- 'h1.has-white-color,h2.has-white-color,h3.has-white-color,h4.has-white-color,h5.has-white-color,h6.has-white-color{color: var(--wp--preset--color--white) !important;}h1.has-white-background-color,h2.has-white-background-color,h3.has-white-background-color,h4.has-white-background-color,h5.has-white-background-color,h6.has-white-background-color{background-color: var(--wp--preset--color--white) !important;}',
- $theme_json->get_stylesheet( 'block_styles' )
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $this->assertEquals(
+ 'h1.has-white-color,h2.has-white-color,h3.has-white-color,h4.has-white-color,h5.has-white-color,h6.has-white-color{color: var(--wp--preset--color--white) !important;}h1.has-white-background-color,h2.has-white-background-color,h3.has-white-background-color,h4.has-white-background-color,h5.has-white-background-color,h6.has-white-background-color{background-color: var(--wp--preset--color--white) !important;}h1.has-white-border-color,h2.has-white-border-color,h3.has-white-border-color,h4.has-white-border-color,h5.has-white-border-color,h6.has-white-border-color{border-color: var(--wp--preset--color--white) !important;}',
+ $theme_json->get_stylesheet( array( 'presets' ) )
</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="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * @ticket 53175
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 54336
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function test_get_stylesheet_preset_rules_come_after_block_rules() {
</span><span class="cx" style="display: block; padding: 0 10px"> $theme_json = new WP_Theme_JSON(
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -376,18 +507,62 @@
</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">- $this->assertSame(
- '.wp-block-group{--wp--preset--color--grey: grey;}.wp-block-group{color: red;}.wp-block-group.has-grey-color{color: var(--wp--preset--color--grey) !important;}.wp-block-group.has-grey-background-color{background-color: var(--wp--preset--color--grey) !important;}',
- $theme_json->get_stylesheet()
</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; }.wp-block-group{color: red;}';
+ $presets = '.wp-block-group.has-grey-color{color: var(--wp--preset--color--grey) !important;}.wp-block-group.has-grey-background-color{background-color: var(--wp--preset--color--grey) !important;}.wp-block-group.has-grey-border-color{border-color: var(--wp--preset--color--grey) !important;}';
+ $variables = '.wp-block-group{--wp--preset--color--grey: grey;}';
+ $all = $variables . $styles . $presets;
+ $this->assertEquals( $all, $theme_json->get_stylesheet() );
+ $this->assertEquals( $styles, $theme_json->get_stylesheet( array( 'styles' ) ) );
+ $this->assertEquals( $presets, $theme_json->get_stylesheet( array( 'presets' ) ) );
+ $this->assertEquals( $variables, $theme_json->get_stylesheet( array( 'variables' ) ) );
+ }
+
+ /**
+ * @ticket 54336
+ */
+ public function test_get_stylesheet_generates_proper_classes_from_slugs() {
+ $theme_json = new WP_Theme_JSON(
+ array(
+ 'version' => WP_Theme_JSON::LATEST_SCHEMA,
+ 'settings' => array(
+ 'color' => array(
+ 'palette' => array(
+ array(
+ 'slug' => 'grey',
+ 'color' => 'grey',
+ ),
+ array(
+ 'slug' => 'dark grey',
+ 'color' => 'grey',
+ ),
+ array(
+ 'slug' => 'light-grey',
+ 'color' => 'grey',
+ ),
+ array(
+ 'slug' => 'white2black',
+ 'color' => 'grey',
+ ),
+ ),
+ ),
+ ),
+ )
</ins><span class="cx" style="display: block; padding: 0 10px"> );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $this->assertSame(
- '.wp-block-group{color: red;}.wp-block-group.has-grey-color{color: var(--wp--preset--color--grey) !important;}.wp-block-group.has-grey-background-color{background-color: var(--wp--preset--color--grey) !important;}',
- $theme_json->get_stylesheet( 'block_styles' )
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+ $this->assertEquals(
+ '.has-grey-color{color: var(--wp--preset--color--grey) !important;}.has-dark-grey-color{color: var(--wp--preset--color--dark-grey) !important;}.has-light-grey-color{color: var(--wp--preset--color--light-grey) !important;}.has-white-2-black-color{color: var(--wp--preset--color--white-2-black) !important;}.has-grey-background-color{background-color: var(--wp--preset--color--grey) !important;}.has-dark-grey-background-color{background-color: var(--wp--preset--color--dark-grey) !important;}.has-light-grey-background-color{background-color: var(--wp--preset--color--light-grey) !important;}.has-white-2-black-background-color{background-color: var(--wp--preset--color--white-2-black) !important;}.has-grey-border-color{border-color: var(--wp--preset--color--grey) !important;}.has-dark-grey-border-color{border-color: var(--wp--preset--color--dark-grey) !important;}.has-light-grey-border-color{border-color: var(--wp--preset--color--light-grey) !important;}.has-white-2-black-border-color{bor
der-color: var(--wp--preset--color--white-2-black) !important;}',
+ $theme_json->get_stylesheet( array( 'presets' ) )
</ins><span class="cx" style="display: block; padding: 0 10px"> );
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $this->assertEquals(
+ 'body{--wp--preset--color--grey: grey;--wp--preset--color--dark-grey: grey;--wp--preset--color--light-grey: grey;--wp--preset--color--white-2-black: grey;}',
+ $theme_json->get_stylesheet( array( 'variables' ) )
+ );
+
</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="cx" style="display: block; padding: 0 10px"> * @ticket 53175
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 54336
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function test_get_stylesheet_preset_values_are_marked_as_important() {
</span><span class="cx" style="display: block; padding: 0 10px"> $theme_json = new WP_Theme_JSON(
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -421,8 +596,8 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 'core'
</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">- $this->assertSame(
- 'body{--wp--preset--color--grey: grey;}p{background-color: blue;color: red;font-size: 12px;line-height: 1.3;}.has-grey-color{color: var(--wp--preset--color--grey) !important;}.has-grey-background-color{background-color: var(--wp--preset--color--grey) !important;}',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $this->assertEquals(
+ 'body{--wp--preset--color--grey: grey;}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; }p{background-color: blue;color: red;font-size: 12px;line-height: 1.3;}.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;}',
</ins><span class="cx" style="display: block; padding: 0 10px"> $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">@@ -429,6 +604,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"> * @ticket 52991
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 54336
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function test_merge_incoming_data() {
</span><span class="cx" style="display: block; padding: 0 10px"> $theme_json = new WP_Theme_JSON(
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -608,7 +784,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"> 'typography' => array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'fontSizes' => array(
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'fontSizes' => array(
</ins><span class="cx" style="display: block; padding: 0 10px"> 'theme' => array(
</span><span class="cx" style="display: block; padding: 0 10px"> array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'slug' => 'fontSize',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -616,6 +792,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">+ 'fontFamilies' => array(
+ 'theme' => array(
+ array(
+ 'slug' => 'fontFamily',
+ 'fontFamily' => 'fontFamily',
+ ),
+ ),
+ ),
</ins><span class="cx" style="display: block; padding: 0 10px"> ),
</span><span class="cx" style="display: block; padding: 0 10px"> 'blocks' => array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'core/paragraph' => array(
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -669,6 +853,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"> * @ticket 53175
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 54336
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function test_merge_incoming_data_empty_presets() {
</span><span class="cx" style="display: block; padding: 0 10px"> $theme_json = new WP_Theme_JSON(
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -736,7 +921,9 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 'version' => WP_Theme_JSON::LATEST_SCHEMA,
</span><span class="cx" style="display: block; padding: 0 10px"> 'settings' => array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'color' => array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'duotone' => array(),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'duotone' => array(
+ 'theme' => array(),
+ ),
</ins><span class="cx" style="display: block; padding: 0 10px"> 'gradients' => array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'theme' => array(),
</span><span class="cx" style="display: block; padding: 0 10px"> ),
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -760,6 +947,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"> * @ticket 53175
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 54336
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function test_merge_incoming_data_null_presets() {
</span><span class="cx" style="display: block; padding: 0 10px"> $theme_json = new WP_Theme_JSON(
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -810,10 +998,10 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 'custom' => false,
</span><span class="cx" style="display: block; padding: 0 10px"> ),
</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">- 'customMargin' => false,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'margin' => false,
</ins><span class="cx" style="display: block; padding: 0 10px"> ),
</span><span class="cx" style="display: block; padding: 0 10px"> 'typography' => array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'customLineHeight' => false,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'lineHeight' => false,
</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">@@ -827,9 +1015,11 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 'color' => array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'custom' => false,
</span><span class="cx" style="display: block; padding: 0 10px"> 'duotone' => array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- array(
- 'slug' => 'value',
- 'colors' => array( 'red', 'green' ),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'theme' => array(
+ array(
+ 'slug' => 'value',
+ 'colors' => array( 'red', 'green' ),
+ ),
</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"> 'gradients' => array(
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -850,12 +1040,12 @@
</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"> 'spacing' => array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'customMargin' => false,
- 'units' => array( 'px', 'em' ),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'margin' => false,
+ 'units' => array( 'px', 'em' ),
</ins><span class="cx" style="display: block; padding: 0 10px"> ),
</span><span class="cx" style="display: block; padding: 0 10px"> 'typography' => array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'customLineHeight' => false,
- 'fontSizes' => array(
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'lineHeight' => false,
+ 'fontSizes' => array(
</ins><span class="cx" style="display: block; padding: 0 10px"> 'theme' => array(
</span><span class="cx" style="display: block; padding: 0 10px"> array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'slug' => 'size',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -871,6 +1061,558 @@
</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">+ * @ticket 54336
+ */
+ public function test_remove_insecure_properties_removes_unsafe_styles() {
+ $actual = WP_Theme_JSON::remove_insecure_properties(
+ array(
+ 'version' => WP_Theme_JSON::LATEST_SCHEMA,
+ 'styles' => array(
+ 'color' => array(
+ 'gradient' => 'url(\'data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHdpZHRoPScxMCcgaGVpZ2h0PScxMCc+PHNjcmlwdD5hbGVydCgnb2snKTwvc2NyaXB0PjxsaW5lYXJHcmFkaWVudCBpZD0nZ3JhZGllbnQnPjxzdG9wIG9mZnNldD0nMTAlJyBzdG9wLWNvbG9yPScjRjAwJy8+PHN0b3Agb2Zmc2V0PSc5MCUnIHN0b3AtY29sb3I9JyNmY2MnLz4gPC9saW5lYXJHcmFkaWVudD48cmVjdCBmaWxsPSd1cmwoI2dyYWRpZW50KScgeD0nMCcgeT0nMCcgd2lkdGg9JzEwMCUnIGhlaWdodD0nMTAwJScvPjwvc3ZnPg==\')',
+ 'text' => 'var:preset|color|dark-red',
+ ),
+ 'elements' => array(
+ 'link' => array(
+ 'color' => array(
+ 'gradient' => 'url(\'data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHdpZHRoPScxMCcgaGVpZ2h0PScxMCc+PHNjcmlwdD5hbGVydCgnb2snKTwvc2NyaXB0PjxsaW5lYXJHcmFkaWVudCBpZD0nZ3JhZGllbnQnPjxzdG9wIG9mZnNldD0nMTAlJyBzdG9wLWNvbG9yPScjRjAwJy8+PHN0b3Agb2Zmc2V0PSc5MCUnIHN0b3AtY29sb3I9JyNmY2MnLz4gPC9saW5lYXJHcmFkaWVudD48cmVjdCBmaWxsPSd1cmwoI2dyYWRpZW50KScgeD0nMCcgeT0nMCcgd2lkdGg9JzEwMCUnIGhlaWdodD0nMTAwJScvPjwvc3ZnPg==\')',
+ 'text' => 'var:preset|color|dark-pink',
+ 'background' => 'var:preset|color|dark-red',
+ ),
+ ),
+ ),
+ 'blocks' => array(
+ 'core/image' => array(
+ 'filter' => array(
+ 'duotone' => 'var:preset|duotone|blue-red',
+ ),
+ ),
+ 'core/cover' => array(
+ 'filter' => array(
+ 'duotone' => 'var(--wp--preset--duotone--blue-red, var(--fallback-unsafe))',
+ ),
+ ),
+ 'core/group' => array(
+ 'color' => array(
+ 'gradient' => 'url(\'data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHdpZHRoPScxMCcgaGVpZ2h0PScxMCc+PHNjcmlwdD5hbGVydCgnb2snKTwvc2NyaXB0PjxsaW5lYXJHcmFkaWVudCBpZD0nZ3JhZGllbnQnPjxzdG9wIG9mZnNldD0nMTAlJyBzdG9wLWNvbG9yPScjRjAwJy8+PHN0b3Agb2Zmc2V0PSc5MCUnIHN0b3AtY29sb3I9JyNmY2MnLz4gPC9saW5lYXJHcmFkaWVudD48cmVjdCBmaWxsPSd1cmwoI2dyYWRpZW50KScgeD0nMCcgeT0nMCcgd2lkdGg9JzEwMCUnIGhlaWdodD0nMTAwJScvPjwvc3ZnPg==\')',
+ 'text' => 'var:preset|color|dark-gray',
+ ),
+ 'elements' => array(
+ 'link' => array(
+ 'color' => array(
+ 'gradient' => 'url(\'data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHdpZHRoPScxMCcgaGVpZ2h0PScxMCc+PHNjcmlwdD5hbGVydCgnb2snKTwvc2NyaXB0PjxsaW5lYXJHcmFkaWVudCBpZD0nZ3JhZGllbnQnPjxzdG9wIG9mZnNldD0nMTAlJyBzdG9wLWNvbG9yPScjRjAwJy8+PHN0b3Agb2Zmc2V0PSc5MCUnIHN0b3AtY29sb3I9JyNmY2MnLz4gPC9saW5lYXJHcmFkaWVudD48cmVjdCBmaWxsPSd1cmwoI2dyYWRpZW50KScgeD0nMCcgeT0nMCcgd2lkdGg9JzEwMCUnIGhlaWdodD0nMTAwJScvPjwvc3ZnPg==\')',
+ 'text' => 'var:preset|color|dark-pink',
+ ),
+ ),
+ ),
+ ),
+ 'invalid/key' => array(
+ 'background' => 'green',
+ ),
+ ),
+ ),
+ )
+ );
+
+ $expected = array(
+ 'version' => WP_Theme_JSON::LATEST_SCHEMA,
+ 'styles' => array(
+ 'color' => array(
+ 'text' => 'var:preset|color|dark-red',
+ ),
+ 'elements' => array(
+ 'link' => array(
+ 'color' => array(
+ 'text' => 'var:preset|color|dark-pink',
+ 'background' => 'var:preset|color|dark-red',
+ ),
+ ),
+ ),
+ 'blocks' => array(
+ 'core/image' => array(
+ 'filter' => array(
+ 'duotone' => 'var:preset|duotone|blue-red',
+ ),
+ ),
+ 'core/group' => array(
+ 'color' => array(
+ 'text' => 'var:preset|color|dark-gray',
+ ),
+ 'elements' => array(
+ 'link' => array(
+ 'color' => array(
+ 'text' => 'var:preset|color|dark-pink',
+ ),
+ ),
+ ),
+ ),
+ ),
+ ),
+ );
+ $this->assertEqualSetsWithIndex( $expected, $actual );
+ }
+
+ /**
+ * @ticket 54336
+ */
+ public function test_remove_insecure_properties_removes_unsafe_styles_sub_properties() {
+ $actual = WP_Theme_JSON::remove_insecure_properties(
+ array(
+ 'version' => WP_Theme_JSON::LATEST_SCHEMA,
+ 'styles' => array(
+ 'border' => array(
+ 'radius' => array(
+ 'topLeft' => '6px',
+ 'topRight' => 'var(--top-right, var(--unsafe-fallback))',
+ 'bottomRight' => '6px',
+ 'bottomLeft' => '6px',
+ ),
+ ),
+ 'spacing' => array(
+ 'padding' => array(
+ 'top' => '1px',
+ 'right' => '1px',
+ 'bottom' => 'var(--bottom, var(--unsafe-fallback))',
+ 'left' => '1px',
+ ),
+ ),
+ 'elements' => array(
+ 'link' => array(
+ 'spacing' => array(
+ 'padding' => array(
+ 'top' => '2px',
+ 'right' => '2px',
+ 'bottom' => 'var(--bottom, var(--unsafe-fallback))',
+ 'left' => '2px',
+ ),
+ ),
+ ),
+ ),
+ 'blocks' => array(
+ 'core/group' => array(
+ 'border' => array(
+ 'radius' => array(
+ 'topLeft' => '5px',
+ 'topRight' => 'var(--top-right, var(--unsafe-fallback))',
+ 'bottomRight' => '5px',
+ 'bottomLeft' => '5px',
+ ),
+ ),
+ 'spacing' => array(
+ 'padding' => array(
+ 'top' => '3px',
+ 'right' => '3px',
+ 'bottom' => 'var(bottom, var(--unsafe-fallback))',
+ 'left' => '3px',
+ ),
+ ),
+ 'elements' => array(
+ 'link' => array(
+ 'spacing' => array(
+ 'padding' => array(
+ 'top' => '4px',
+ 'right' => '4px',
+ 'bottom' => 'var(--bottom, var(--unsafe-fallback))',
+ 'left' => '4px',
+ ),
+ ),
+ ),
+ ),
+ ),
+ ),
+ ),
+ ),
+ true
+ );
+
+ $expected = array(
+ 'version' => WP_Theme_JSON::LATEST_SCHEMA,
+ 'styles' => array(
+ 'border' => array(
+ 'radius' => array(
+ 'topLeft' => '6px',
+ 'bottomRight' => '6px',
+ 'bottomLeft' => '6px',
+ ),
+ ),
+ 'spacing' => array(
+ 'padding' => array(
+ 'top' => '1px',
+ 'right' => '1px',
+ 'left' => '1px',
+ ),
+ ),
+ 'elements' => array(
+ 'link' => array(
+ 'spacing' => array(
+ 'padding' => array(
+ 'top' => '2px',
+ 'right' => '2px',
+ 'left' => '2px',
+ ),
+ ),
+ ),
+ ),
+ 'blocks' => array(
+ 'core/group' => array(
+ 'border' => array(
+ 'radius' => array(
+ 'topLeft' => '5px',
+ 'bottomRight' => '5px',
+ 'bottomLeft' => '5px',
+ ),
+ ),
+ 'spacing' => array(
+ 'padding' => array(
+ 'top' => '3px',
+ 'right' => '3px',
+ 'left' => '3px',
+ ),
+ ),
+ 'elements' => array(
+ 'link' => array(
+ 'spacing' => array(
+ 'padding' => array(
+ 'top' => '4px',
+ 'right' => '4px',
+ 'left' => '4px',
+ ),
+ ),
+ ),
+ ),
+ ),
+ ),
+ ),
+ );
+ $this->assertEqualSetsWithIndex( $expected, $actual );
+ }
+
+ /**
+ * @ticket 54336
+ */
+ public function test_remove_insecure_properties_removes_non_preset_settings() {
+ $actual = WP_Theme_JSON::remove_insecure_properties(
+ array(
+ 'version' => WP_Theme_JSON::LATEST_SCHEMA,
+ 'settings' => array(
+ 'color' => array(
+ 'custom' => true,
+ 'palette' => array(
+ array(
+ 'name' => 'Red',
+ 'slug' => 'red',
+ 'color' => '#ff0000',
+ ),
+ array(
+ 'name' => 'Green',
+ 'slug' => 'green',
+ 'color' => '#00ff00',
+ ),
+ array(
+ 'name' => 'Blue',
+ 'slug' => 'blue',
+ 'color' => '#0000ff',
+ ),
+ ),
+ ),
+ 'spacing' => array(
+ 'padding' => false,
+ ),
+ 'blocks' => array(
+ 'core/group' => array(
+ 'color' => array(
+ 'custom' => true,
+ 'palette' => array(
+ array(
+ 'name' => 'Yellow',
+ 'slug' => 'yellow',
+ 'color' => '#ff0000',
+ ),
+ array(
+ 'name' => 'Pink',
+ 'slug' => 'pink',
+ 'color' => '#00ff00',
+ ),
+ array(
+ 'name' => 'Orange',
+ 'slug' => 'orange',
+ 'color' => '#0000ff',
+ ),
+ ),
+ ),
+ 'spacing' => array(
+ 'padding' => false,
+ ),
+ ),
+ ),
+ ),
+ )
+ );
+
+ $expected = array(
+ 'version' => WP_Theme_JSON::LATEST_SCHEMA,
+ 'settings' => array(
+ 'color' => array(
+ 'palette' => array(
+ array(
+ 'name' => 'Red',
+ 'slug' => 'red',
+ 'color' => '#ff0000',
+ ),
+ array(
+ 'name' => 'Green',
+ 'slug' => 'green',
+ 'color' => '#00ff00',
+ ),
+ array(
+ 'name' => 'Blue',
+ 'slug' => 'blue',
+ 'color' => '#0000ff',
+ ),
+ ),
+ ),
+ 'blocks' => array(
+ 'core/group' => array(
+ 'color' => array(
+ 'palette' => array(
+ array(
+ 'name' => 'Yellow',
+ 'slug' => 'yellow',
+ 'color' => '#ff0000',
+ ),
+ array(
+ 'name' => 'Pink',
+ 'slug' => 'pink',
+ 'color' => '#00ff00',
+ ),
+ array(
+ 'name' => 'Orange',
+ 'slug' => 'orange',
+ 'color' => '#0000ff',
+ ),
+ ),
+ ),
+ ),
+ ),
+ ),
+ );
+ $this->assertEqualSetsWithIndex( $expected, $actual );
+ }
+
+ /**
+ * @ticket 54336
+ */
+ public function test_remove_insecure_properties_removes_unsafe_preset_settings() {
+ $actual = WP_Theme_JSON::remove_insecure_properties(
+ array(
+ 'version' => WP_Theme_JSON::LATEST_SCHEMA,
+ 'settings' => array(
+ 'color' => array(
+ 'palette' => array(
+ array(
+ 'name' => 'Red/><b>ok</ok>',
+ 'slug' => 'red',
+ 'color' => '#ff0000',
+ ),
+ array(
+ 'name' => 'Green',
+ 'slug' => 'a" attr',
+ 'color' => '#00ff00',
+ ),
+ array(
+ 'name' => 'Blue',
+ 'slug' => 'blue',
+ 'color' => 'var(--color, var(--unsafe-fallback))',
+ ),
+ array(
+ 'name' => 'Pink',
+ 'slug' => 'pink',
+ 'color' => '#FFC0CB',
+ ),
+ ),
+ ),
+ 'typography' => array(
+ 'fontFamilies' => array(
+ array(
+ 'name' => 'Helvetica Arial/><b>test</b>',
+ 'slug' => 'helvetica-arial',
+ 'fontFamily' => 'Helvetica Neue, Helvetica, Arial, sans-serif',
+ ),
+ array(
+ 'name' => 'Geneva',
+ 'slug' => 'geneva#asa',
+ 'fontFamily' => 'Geneva, Tahoma, Verdana, sans-serif',
+ ),
+ array(
+ 'name' => 'Cambria',
+ 'slug' => 'cambria',
+ 'fontFamily' => 'Cambria, Georgia, serif',
+ ),
+ array(
+ 'name' => 'Helvetica Arial',
+ 'slug' => 'helvetica-arial',
+ 'fontFamily' => 'var(--fontFamily, var(--unsafe-fallback))',
+ ),
+ ),
+ ),
+ 'blocks' => array(
+ 'core/group' => array(
+ 'color' => array(
+ 'palette' => array(
+ array(
+ 'name' => 'Red/><b>ok</ok>',
+ 'slug' => 'red',
+ 'color' => '#ff0000',
+ ),
+ array(
+ 'name' => 'Green',
+ 'slug' => 'a" attr',
+ 'color' => '#00ff00',
+ ),
+ array(
+ 'name' => 'Blue',
+ 'slug' => 'blue',
+ 'color' => 'var(--color, var(--unsafe--fallback))',
+ ),
+ array(
+ 'name' => 'Pink',
+ 'slug' => 'pink',
+ 'color' => '#FFC0CB',
+ ),
+ ),
+ ),
+ ),
+ ),
+ ),
+ )
+ );
+
+ $expected = array(
+ 'version' => WP_Theme_JSON::LATEST_SCHEMA,
+ 'settings' => array(
+ 'color' => array(
+ 'palette' => array(
+ array(
+ 'name' => 'Pink',
+ 'slug' => 'pink',
+ 'color' => '#FFC0CB',
+ ),
+ ),
+ ),
+ 'typography' => array(
+ 'fontFamilies' => array(
+ array(
+ 'name' => 'Cambria',
+ 'slug' => 'cambria',
+ 'fontFamily' => 'Cambria, Georgia, serif',
+ ),
+ ),
+ ),
+ 'blocks' => array(
+ 'core/group' => array(
+ 'color' => array(
+ 'palette' => array(
+ array(
+ 'name' => 'Pink',
+ 'slug' => 'pink',
+ 'color' => '#FFC0CB',
+ ),
+ ),
+ ),
+ ),
+ ),
+ ),
+ );
+ $this->assertEqualSetsWithIndex( $expected, $actual );
+ }
+
+ /**
+ * @ticket 54336
+ */
+ public function test_remove_insecure_properties_applies_safe_styles() {
+ $actual = WP_Theme_JSON::remove_insecure_properties(
+ array(
+ 'version' => WP_Theme_JSON::LATEST_SCHEMA,
+ 'styles' => array(
+ 'color' => array(
+ 'text' => '#abcabc ', // Trailing space.
+ ),
+ ),
+ ),
+ true
+ );
+
+ $expected = array(
+ 'version' => WP_Theme_JSON::LATEST_SCHEMA,
+ 'styles' => array(
+ 'color' => array(
+ 'text' => '#abcabc ',
+ ),
+ ),
+ );
+ $this->assertEqualSetsWithIndex( $expected, $actual );
+ }
+
+ /**
+ * @ticket 54336
+ */
+ public function test_get_custom_templates() {
+ $theme_json = new WP_Theme_JSON(
+ array(
+ 'version' => 1,
+ 'customTemplates' => array(
+ array(
+ 'name' => 'page-home',
+ 'title' => 'Homepage template',
+ ),
+ ),
+ )
+ );
+
+ $page_templates = $theme_json->get_custom_templates();
+
+ $this->assertEqualSetsWithIndex(
+ $page_templates,
+ array(
+ 'page-home' => array(
+ 'title' => 'Homepage template',
+ 'postTypes' => array( 'page' ),
+ ),
+ )
+ );
+ }
+
+ /**
+ * @ticket 54336
+ */
+ public function test_get_template_parts() {
+ $theme_json = new WP_Theme_JSON(
+ array(
+ 'version' => 1,
+ 'templateParts' => array(
+ array(
+ 'name' => 'small-header',
+ 'title' => 'Small Header',
+ 'area' => 'header',
+ ),
+ ),
+ )
+ );
+
+ $template_parts = $theme_json->get_template_parts();
+
+ $this->assertEqualSetsWithIndex(
+ $template_parts,
+ array(
+ 'small-header' => array(
+ 'title' => 'Small Header',
+ 'area' => 'header',
+ ),
+ )
+ );
+ }
+
+ /**
</ins><span class="cx" style="display: block; padding: 0 10px"> * @ticket 52991
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function test_get_from_editor_settings() {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -928,9 +1670,9 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 'units' => array( 'px', 'em', 'rem', 'vh', 'vw', '%' ),
</span><span class="cx" style="display: block; padding: 0 10px"> ),
</span><span class="cx" style="display: block; padding: 0 10px"> 'typography' => array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'customFontSize' => false,
- 'customLineHeight' => true,
- 'fontSizes' => array(
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'customFontSize' => false,
+ 'lineHeight' => true,
+ 'fontSizes' => array(
</ins><span class="cx" style="display: block; padding: 0 10px"> array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'slug' => 'size-slug',
</span><span class="cx" style="display: block; padding: 0 10px"> 'name' => 'Size Name',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -948,6 +1690,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"> * @ticket 52991
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 54336
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function test_get_editor_settings_no_theme_support() {
</span><span class="cx" style="display: block; padding: 0 10px"> $input = array(
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -990,8 +1733,8 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 'units' => false,
</span><span class="cx" style="display: block; padding: 0 10px"> ),
</span><span class="cx" style="display: block; padding: 0 10px"> 'typography' => array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'customFontSize' => true,
- 'customLineHeight' => false,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'customFontSize' => true,
+ 'lineHeight' => false,
</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">@@ -1003,6 +1746,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"> * @ticket 52991
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 54336
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function test_get_editor_settings_blank() {
</span><span class="cx" style="display: block; padding: 0 10px"> $expected = array(
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1011,58 +1755,57 @@
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px"> $actual = WP_Theme_JSON::get_from_editor_settings( array() );
</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->assertSameSetsWithIndex( $expected, $actual );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $this->assertEqualSetsWithIndex( $expected, $actual );
</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="cx" style="display: block; padding: 0 10px"> * @ticket 52991
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 54336
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function test_get_editor_settings_custom_units_can_be_disabled() {
</span><span class="cx" style="display: block; padding: 0 10px"> add_theme_support( 'custom-units', array() );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $input = get_default_block_editor_settings();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $actual = WP_Theme_JSON::get_from_editor_settings( get_default_block_editor_settings() );
+ remove_theme_support( 'custom-units' );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $expected = array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'units' => array( array() ),
- 'customPadding' => false,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'units' => array( array() ),
+ 'padding' => false,
</ins><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">- $actual = WP_Theme_JSON::get_from_editor_settings( $input );
-
- $this->assertSameSetsWithIndex( $expected, $actual['settings']['spacing'] );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $this->assertEqualSetsWithIndex( $expected, $actual['settings']['spacing'] );
</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="cx" style="display: block; padding: 0 10px"> * @ticket 52991
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 54336
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function test_get_editor_settings_custom_units_can_be_enabled() {
</span><span class="cx" style="display: block; padding: 0 10px"> add_theme_support( 'custom-units' );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $input = get_default_block_editor_settings();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $actual = WP_Theme_JSON::get_from_editor_settings( get_default_block_editor_settings() );
+ remove_theme_support( 'custom-units' );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $expected = array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'units' => array( 'px', 'em', 'rem', 'vh', 'vw', '%' ),
- 'customPadding' => false,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'units' => array( 'px', 'em', 'rem', 'vh', 'vw', '%' ),
+ 'padding' => false,
</ins><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">- $actual = WP_Theme_JSON::get_from_editor_settings( $input );
-
- $this->assertSameSetsWithIndex( $expected, $actual['settings']['spacing'] );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $this->assertEqualSetsWithIndex( $expected, $actual['settings']['spacing'] );
</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="cx" style="display: block; padding: 0 10px"> * @ticket 52991
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 54336
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function test_get_editor_settings_custom_units_can_be_filtered() {
</span><span class="cx" style="display: block; padding: 0 10px"> add_theme_support( 'custom-units', 'rem', 'em' );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $input = get_default_block_editor_settings();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $actual = WP_Theme_JSON::get_from_editor_settings( get_default_block_editor_settings() );
+ remove_theme_support( 'custom-units' );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $expected = array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'units' => array( 'rem', 'em' ),
- 'customPadding' => false,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'units' => array( 'rem', 'em' ),
+ 'padding' => false,
</ins><span class="cx" style="display: block; padding: 0 10px"> );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
- $actual = WP_Theme_JSON::get_from_editor_settings( $input );
-
- $this->assertSameSetsWithIndex( $expected, $actual['settings']['spacing'] );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $this->assertEqualSetsWithIndex( $expected, $actual['settings']['spacing'] );
</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="trunktestsphpunitteststhemewpThemeJsonResolverphp"></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/wpThemeJsonResolver.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/theme/wpThemeJsonResolver.php 2021-11-08 17:07:49 UTC (rev 52048)
+++ trunk/tests/phpunit/tests/theme/wpThemeJsonResolver.php 2021-11-08 19:18:39 UTC (rev 52049)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -46,6 +46,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"> * @ticket 52991
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 54336
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function test_translations_are_applied() {
</span><span class="cx" style="display: block; padding: 0 10px"> add_filter( 'locale', array( $this, 'filter_set_locale_to_polish' ) );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -52,7 +53,6 @@
</span><span class="cx" style="display: block; padding: 0 10px"> load_textdomain( 'block-theme', realpath( DIR_TESTDATA . '/languages/themes/block-theme-pl_PL.mo' ) );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> switch_theme( 'block-theme' );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><span class="cx" style="display: block; padding: 0 10px"> $actual = WP_Theme_JSON_Resolver::get_theme_data();
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> unload_textdomain( 'block-theme' );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -62,6 +62,8 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertSame(
</span><span class="cx" style="display: block; padding: 0 10px"> array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'color' => array(
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'custom' => false,
+ 'customGradient' => false,
</ins><span class="cx" style="display: block; padding: 0 10px"> 'palette' => array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'theme' => array(
</span><span class="cx" style="display: block; padding: 0 10px"> array(
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -85,11 +87,11 @@
</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">- 'custom' => false,
- 'customGradient' => false,
</del><span class="cx" style="display: block; padding: 0 10px"> ),
</span><span class="cx" style="display: block; padding: 0 10px"> 'typography' => array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'fontSizes' => array(
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'customFontSize' => false,
+ 'lineHeight' => true,
+ 'fontSizes' => array(
</ins><span class="cx" style="display: block; padding: 0 10px"> 'theme' => array(
</span><span class="cx" style="display: block; padding: 0 10px"> array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'name' => 'Custom',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -98,14 +100,10 @@
</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">- 'customFontSize' => false,
- 'customLineHeight' => true,
</del><span class="cx" style="display: block; padding: 0 10px"> ),
</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">- 'units' => array(
- 'rem',
- ),
- 'customPadding' => true,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'units' => array( 'rem' ),
+ 'padding' => true,
</ins><span class="cx" style="display: block; padding: 0 10px"> ),
</span><span class="cx" style="display: block; padding: 0 10px"> 'blocks' => array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'core/paragraph' => array(
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -125,6 +123,24 @@
</span><span class="cx" style="display: block; padding: 0 10px"> ),
</span><span class="cx" style="display: block; padding: 0 10px"> $actual->get_settings()
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $this->assertSame(
+ $actual->get_custom_templates(),
+ array(
+ 'page-home' => array(
+ 'title' => 'Szablon strony głównej',
+ 'postTypes' => array( 'page' ),
+ ),
+ )
+ );
+ $this->assertSame(
+ $actual->get_template_parts(),
+ array(
+ 'small-header' => array(
+ 'title' => 'Mały nagłówek',
+ 'area' => 'header',
+ ),
+ )
+ );
</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">@@ -143,4 +159,157 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertTrue( $has_theme_json_support );
</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">+ /**
+ * @ticket 54336
+ */
+ function test_add_theme_supports_are_loaded_for_themes_without_theme_json() {
+ switch_theme( 'default' );
+ $color_palette = array(
+ array(
+ 'name' => 'Primary',
+ 'slug' => 'primary',
+ 'color' => '#F00',
+ ),
+ array(
+ 'name' => 'Secondary',
+ 'slug' => 'secondary',
+ 'color' => '#0F0',
+ ),
+ array(
+ 'name' => 'Tertiary',
+ 'slug' => 'tertiary',
+ 'color' => '#00F',
+ ),
+ );
+ add_theme_support( 'editor-color-palette', $color_palette );
+ add_theme_support( 'custom-line-height' );
+
+ $settings = WP_Theme_JSON_Resolver::get_theme_data()->get_settings();
+
+ remove_theme_support( 'custom-line-height' );
+ remove_theme_support( 'editor-color-palette' );
+
+ $this->assertFalse( WP_Theme_JSON_Resolver::theme_has_support() );
+ $this->assertTrue( $settings['typography']['lineHeight'] );
+ $this->assertSame( $color_palette, $settings['color']['palette']['theme'] );
+ }
+
+ /**
+ * Recursively applies ksort to an array.
+ */
+ private static function recursive_ksort( &$array ) {
+ foreach ( $array as &$value ) {
+ if ( is_array( $value ) ) {
+ self::recursive_ksort( $value );
+ }
+ }
+ ksort( $array );
+ }
+
+ /**
+ * @ticket 54336
+ */
+ function test_merges_child_theme_json_into_parent_theme_json() {
+ switch_theme( 'block-theme-child' );
+
+ $actual_settings = WP_Theme_JSON_Resolver::get_theme_data()->get_settings();
+ $expected_settings = array(
+ 'color' => array(
+ 'custom' => false,
+ 'customGradient' => false,
+ 'gradients' => array(
+ 'theme' => array(
+ array(
+ 'name' => 'Custom gradient',
+ 'gradient' => 'linear-gradient(135deg,rgba(0,0,0) 0%,rgb(0,0,0) 100%)',
+ 'slug' => 'custom-gradient',
+ ),
+ ),
+ ),
+ 'palette' => array(
+ 'theme' => array(
+ array(
+ 'slug' => 'light',
+ 'name' => 'Light',
+ 'color' => '#f3f4f6',
+ ),
+ array(
+ 'slug' => 'primary',
+ 'name' => 'Primary',
+ 'color' => '#3858e9',
+ ),
+ array(
+ 'slug' => 'dark',
+ 'name' => 'Dark',
+ 'color' => '#111827',
+ ),
+ ),
+ ),
+ 'link' => true,
+ ),
+ 'typography' => array(
+ 'customFontSize' => false,
+ 'lineHeight' => true,
+ 'fontSizes' => array(
+ 'theme' => array(
+ array(
+ 'name' => 'Custom',
+ 'slug' => 'custom',
+ 'size' => '100px',
+ ),
+ ),
+ ),
+ ),
+ 'spacing' => array(
+ 'units' => array( 'rem' ),
+ 'padding' => true,
+ ),
+ 'blocks' => array(
+ 'core/paragraph' => array(
+ 'color' => array(
+ 'palette' => array(
+ 'theme' => array(
+ array(
+ 'slug' => 'light',
+ 'name' => 'Light',
+ 'color' => '#f5f7f9',
+ ),
+ ),
+ ),
+ ),
+ ),
+ 'core/post-title' => array(
+ 'color' => array(
+ 'palette' => array(
+ 'theme' => array(
+ array(
+ 'slug' => 'light',
+ 'name' => 'Light',
+ 'color' => '#f3f4f6',
+ ),
+ ),
+ ),
+ ),
+ ),
+ ),
+ );
+ self::recursive_ksort( $actual_settings );
+ self::recursive_ksort( $expected_settings );
+
+ // Should merge settings.
+ $this->assertSame(
+ $expected_settings,
+ $actual_settings
+ );
+
+ $this->assertSame(
+ WP_Theme_JSON_Resolver::get_theme_data()->get_custom_templates(),
+ array(
+ 'page-home' => array(
+ 'title' => 'Homepage',
+ 'postTypes' => array( 'page' ),
+ ),
+ )
+ );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span></span></pre></div>
<a id="trunktestsphpunitteststhemewpThemeJsonSchemaphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/tests/phpunit/tests/theme/wpThemeJsonSchema.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/theme/wpThemeJsonSchema.php (rev 0)
+++ trunk/tests/phpunit/tests/theme/wpThemeJsonSchema.php 2021-11-08 19:18:39 UTC (rev 52049)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,193 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+
+/**
+ * Test WP_Theme_JSON_Schema class.
+ *
+ * @package WordPress
+ * @subpackage Theme
+ *
+ * @since 5.9.0
+ *
+ * @group themes
+ */
+class Tests_Theme_wpThemeJsonSchema extends WP_UnitTestCase {
+ /**
+ * The current theme.json schema version.
+ */
+ const LATEST_SCHEMA_VERSION = WP_Theme_JSON::LATEST_SCHEMA;
+
+ /**
+ * @ticket 54336
+ */
+ function test_migrate_v1_to_v2() {
+ $theme_json_v1 = array(
+ 'version' => 1,
+ 'settings' => array(
+ 'color' => array(
+ 'palette' => array(
+ array(
+ 'name' => 'Pale Pink',
+ 'slug' => 'pale-pink',
+ 'color' => '#f78da7',
+ ),
+ array(
+ 'name' => 'Vivid Red',
+ 'slug' => 'vivid-red',
+ 'color' => '#cf2e2e',
+ ),
+ ),
+ 'custom' => false,
+ 'link' => true,
+ ),
+ 'border' => array(
+ 'color' => false,
+ 'customRadius' => false,
+ 'style' => false,
+ 'width' => false,
+ ),
+ 'typography' => array(
+ 'fontStyle' => false,
+ 'fontWeight' => false,
+ 'letterSpacing' => false,
+ 'textDecoration' => false,
+ 'textTransform' => false,
+ ),
+ 'blocks' => array(
+ 'core/group' => array(
+ 'border' => array(
+ 'color' => true,
+ 'customRadius' => true,
+ 'style' => true,
+ 'width' => true,
+ ),
+ 'typography' => array(
+ 'fontStyle' => true,
+ 'fontWeight' => true,
+ 'letterSpacing' => true,
+ 'textDecoration' => true,
+ 'textTransform' => true,
+ ),
+ ),
+ ),
+ ),
+ 'styles' => array(
+ 'color' => array(
+ 'background' => 'purple',
+ ),
+ 'blocks' => array(
+ 'core/group' => array(
+ 'color' => array(
+ 'background' => 'red',
+ ),
+ 'spacing' => array(
+ 'padding' => array(
+ 'top' => '10px',
+ ),
+ ),
+ 'elements' => array(
+ 'link' => array(
+ 'color' => array(
+ 'text' => 'yellow',
+ ),
+ ),
+ ),
+ ),
+ ),
+ 'elements' => array(
+ 'link' => array(
+ 'color' => array(
+ 'text' => 'red',
+ ),
+ ),
+ ),
+ ),
+ );
+
+ $actual = WP_Theme_JSON_Schema::migrate( $theme_json_v1 );
+
+ $expected = array(
+ 'version' => self::LATEST_SCHEMA_VERSION,
+ 'settings' => array(
+ 'color' => array(
+ 'palette' => array(
+ array(
+ 'name' => 'Pale Pink',
+ 'slug' => 'pale-pink',
+ 'color' => '#f78da7',
+ ),
+ array(
+ 'name' => 'Vivid Red',
+ 'slug' => 'vivid-red',
+ 'color' => '#cf2e2e',
+ ),
+ ),
+ 'custom' => false,
+ 'link' => true,
+ ),
+ 'border' => array(
+ 'color' => false,
+ 'radius' => false,
+ 'style' => false,
+ 'width' => false,
+ ),
+ 'typography' => array(
+ 'fontStyle' => false,
+ 'fontWeight' => false,
+ 'letterSpacing' => false,
+ 'textDecoration' => false,
+ 'textTransform' => false,
+ ),
+ 'blocks' => array(
+ 'core/group' => array(
+ 'border' => array(
+ 'color' => true,
+ 'radius' => true,
+ 'style' => true,
+ 'width' => true,
+ ),
+ 'typography' => array(
+ 'fontStyle' => true,
+ 'fontWeight' => true,
+ 'letterSpacing' => true,
+ 'textDecoration' => true,
+ 'textTransform' => true,
+ ),
+ ),
+ ),
+ ),
+ 'styles' => array(
+ 'color' => array(
+ 'background' => 'purple',
+ ),
+ 'blocks' => array(
+ 'core/group' => array(
+ 'color' => array(
+ 'background' => 'red',
+ ),
+ 'spacing' => array(
+ 'padding' => array(
+ 'top' => '10px',
+ ),
+ ),
+ 'elements' => array(
+ 'link' => array(
+ 'color' => array(
+ 'text' => 'yellow',
+ ),
+ ),
+ ),
+ ),
+ ),
+ 'elements' => array(
+ 'link' => array(
+ 'color' => array(
+ 'text' => 'red',
+ ),
+ ),
+ ),
+ ),
+ );
+
+ $this->assertEqualSetsWithIndex( $expected, $actual );
+ }
+}
</ins></span></pre>
</div>
</div>
</body>
</html>