diff --git a/lib/compat/wordpress-6.1/class-wp-theme-json-6-1.php b/lib/compat/wordpress-6.1/class-wp-theme-json-6-1.php index 189e3694dd87f6..638ebecc625a92 100644 --- a/lib/compat/wordpress-6.1/class-wp-theme-json-6-1.php +++ b/lib/compat/wordpress-6.1/class-wp-theme-json-6-1.php @@ -491,23 +491,25 @@ function( $pseudo_selector ) use ( $selector ) { // If the current selector is a pseudo selector that's defined in the allow list for the current // element then compute the style properties for it. // Otherwise just compute the styles for the default selector as normal. - if ( $pseudo_selector && isset( $node[ $pseudo_selector ] ) && isset( static::VALID_ELEMENT_PSEUDO_SELECTORS[ $current_element ] ) && in_array( $pseudo_selector, static::VALID_ELEMENT_PSEUDO_SELECTORS[ $current_element ], true ) ) { - $declarations = static::compute_style_properties( $node[ $pseudo_selector ], $settings, null, $this->theme_json ); - } else { - $declarations = static::compute_style_properties( $node, $settings, null, $this->theme_json ); - } + +// if ( $pseudo_selector && isset( $node[ $pseudo_selector ] ) && isset( static::VALID_ELEMENT_PSEUDO_SELECTORS[ $current_element ] ) && in_array( $pseudo_selector, static::VALID_ELEMENT_PSEUDO_SELECTORS[ $current_element ], true ) ) { +// $declarations = static::compute_style_properties( $node[ $pseudo_selector ], $settings, null, $this->theme_json ); +// } else { +// $declarations = static::compute_style_properties( $node, $settings, null, $this->theme_json ); +// } $block_rules = ''; + // @TODO migrate duotone to style engine // 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; - } - } +// $declarations_duotone = array(); +// foreach ( $declarations as $index => $declaration ) { +// if ( 'filter' === $declaration['name'] ) { +// unset( $declarations[ $index ] ); +// $declarations_duotone[] = $declaration; +// } +// } /* * Reset default browser margin on the root body element. @@ -522,14 +524,41 @@ function( $pseudo_selector ) use ( $selector ) { } // 2. Generate and append the rules that use the general selector. - $block_rules .= static::to_ruleset( $selector, $declarations ); + //$block_rules .= static::to_ruleset( $selector, $declarations ); + + $block_styles = $pseudo_selector && isset( $node[ $pseudo_selector ] ) && isset( static::VALID_ELEMENT_PSEUDO_SELECTORS[ $current_element ] ) && in_array( $pseudo_selector, static::VALID_ELEMENT_PSEUDO_SELECTORS[ $current_element ], true ) ? $node[ $pseudo_selector ] : $node; + + if ( isset( $block_styles['filter']['duotone'] ) && ! empty( $block_styles['filter']['duotone'] ) ) { + $selector = static::scope_selector( $selector, $block_metadata['duotone'] ); + } + + $styles = gutenberg_style_engine_generate( + $block_styles, + array( + 'selector' => $selector, + 'custom_metadata' => array( + 'spacing.blockGap' => array( + 'property_keys' => array( + 'default' => '--wp--style--block-gap', + ), + ), + ), + 'css_vars' => true, // @TODO this doesn't make sense in this context. Refactor. + 'prettify' => defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG, + ) + ); - // 3. Generate and append the rules that use the duotone selector. - if ( isset( $block_metadata['duotone'] ) && ! empty( $declarations_duotone ) ) { - $selector_duotone = static::scope_selector( $block_metadata['selector'], $block_metadata['duotone'] ); - $block_rules .= static::to_ruleset( $selector_duotone, $declarations_duotone ); + if ( isset( $styles['css'] ) ) { + $block_rules .= $styles['css']; } + // 3. Generate and append the rules that use the duotone selector. + // @TODO migrate duotone to style engine +// if ( isset( $block_metadata['duotone'] ) && ! empty( $declarations_duotone ) ) { +// $selector_duotone = static::scope_selector( $block_metadata['selector'], $block_metadata['duotone'] ); +// $block_rules .= static::to_ruleset( $selector_duotone, $declarations_duotone ); +// } + if ( static::ROOT_BLOCK_SELECTOR === $selector ) { $block_rules .= '.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }'; $block_rules .= '.wp-site-blocks > .alignright { float: right; margin-left: 2em; }'; diff --git a/packages/style-engine/class-wp-style-engine-css-declarations.php b/packages/style-engine/class-wp-style-engine-css-declarations.php index cde6b51355195e..3c7ddc1083552b 100644 --- a/packages/style-engine/class-wp-style-engine-css-declarations.php +++ b/packages/style-engine/class-wp-style-engine-css-declarations.php @@ -26,7 +26,13 @@ class WP_Style_Engine_CSS_Declarations { protected $styles = array(); /** - * Contructor for this object. + * A white list of CSS custom properties. + * Used to bypass safecss_filter_attr(). + */ + const VALID_CUSTOM_PROPERTIES = array( '--wp--style--block-gap' => 'blockGap' ); + + /** + * Constructor for this object. * * If a `$styles` array is passed, it will be used to populate * the initial $styles prop of the object by calling add_declarations(). @@ -92,15 +98,22 @@ public function get_styles() { /** * Get the CSS styles. * + * @param boolean $should_prettify Whether to format the output with indents. + * * @return string The CSS styles. */ - public function get_styles_string() { + public function get_styles_string( $should_prettify = false ) { $styles_array = $this->get_styles(); $styles = ''; + $indent = $should_prettify ? "\t" : ''; + $newline = $should_prettify ? "\n" : ' '; foreach ( $styles_array as $property => $value ) { $css = esc_html( safecss_filter_attr( "{$property}: {$value}" ) ); + // @TODO The safecss_filter_attr_allow_css filter in safecss_filter_attr (kses.php) does not let through CSS custom variables. + // So we have to be strict about them here. + $css = isset( static::VALID_CUSTOM_PROPERTIES[ $property ] ) ? esc_html( "{$property}: {$value}" ) : esc_html( safecss_filter_attr( "{$property}: {$value}" ) ); if ( $css ) { - $styles .= $css . '; '; + $styles .= "$indent$css;$newline"; } } return rtrim( $styles ); diff --git a/packages/style-engine/class-wp-style-engine.php b/packages/style-engine/class-wp-style-engine.php index 15c803832fcbff..1c9bb9ec2eae9d 100644 --- a/packages/style-engine/class-wp-style-engine.php +++ b/packages/style-engine/class-wp-style-engine.php @@ -63,6 +63,9 @@ class WP_Style_Engine { 'default' => 'background-color', ), 'path' => array( 'color', 'background' ), + 'css_vars' => array( + 'color' => '--wp--preset--color--$slug', + ), 'classnames' => array( 'has-background' => true, 'has-$slug-background-color' => 'color', @@ -141,8 +144,16 @@ class WP_Style_Engine { ), ), ), + 'filter' => array( + 'duotone' => array( + 'property_keys' => array( + 'default' => 'filter', + ), + 'path' => array( 'filter', 'duotone' ), + ), + ), 'spacing' => array( - 'padding' => array( + 'padding' => array( 'property_keys' => array( 'default' => 'padding', 'individual' => 'padding-%s', @@ -152,7 +163,7 @@ class WP_Style_Engine { 'spacing' => '--wp--preset--spacing--$slug', ), ), - 'margin' => array( + 'margin' => array( 'property_keys' => array( 'default' => 'margin', 'individual' => 'margin-%s', @@ -162,6 +173,15 @@ class WP_Style_Engine { 'spacing' => '--wp--preset--spacing--$slug', ), ), + 'blockGap' => array( + 'property_keys' => array( + // @TODO 'grid-gap' has been deprecated in favor of 'gap'. + // See: https://developer.mozilla.org/en-US/docs/Web/CSS/gap. + // Update the white list in safecss_filter_attr (kses.php). + 'default' => 'grid-gap', + ), + 'path' => array( 'spacing', 'blockGap' ), + ), ), 'typography' => array( 'fontSize' => array( @@ -236,6 +256,25 @@ public static function get_instance() { return self::$instance; } + /** + * Merges single style definitions with incoming custom style definitions. + * + * @param array $style_definition The internal style definition metadata. + * @param array $custom_definition The custom style definition metadata to be merged. + * + * @return array The merged definition metadata. + */ + public static function merge_custom_style_definitions_metadata( $style_definition, $custom_definition = array() ) { + $valid_keys = array( 'property_keys', 'classnames' ); + foreach ( $valid_keys as $key ) { + if ( isset( $custom_definition[ $key ] ) && is_array( $custom_definition[ $key ] ) ) { + $style_definition[ $key ] = array_merge( $style_definition[ $key ], $custom_definition[ $key ] ); + } + } + + return $style_definition; + } + /** * Extracts the slug in kebab case from a preset string, e.g., "heavenly-blue" from 'var:preset|color|heavenlyBlue'. * @@ -332,29 +371,30 @@ protected static function get_classnames( $style_value, $style_definition ) { /** * Returns an array of CSS declarations based on valid block style values. * - * @param array $style_value A single raw style value from the generate() $block_styles array. - * @param array $style_definition A single style definition from BLOCK_STYLE_DEFINITIONS_METADATA. - * @param boolean $should_skip_css_vars Whether to skip compiling CSS var values. + * @param array $style_value A single raw style value from the generate() $block_styles array. + * @param array $style_definition A single style definition from BLOCK_STYLE_DEFINITIONS_METADATA. + * @param array $options Options passed to generate(). * * @return array An array of CSS definitions, e.g., array( "$property" => "$value" ). */ - protected static function get_css_declarations( $style_value, $style_definition, $should_skip_css_vars = false ) { + protected static function get_css_declarations( $style_value, $style_definition, $options ) { if ( isset( $style_definition['value_func'] ) && is_callable( $style_definition['value_func'] ) ) { - return call_user_func( $style_definition['value_func'], $style_value, $style_definition, $should_skip_css_vars ); + return call_user_func( $style_definition['value_func'], $style_value, $style_definition, $options ); } - $css_declarations = array(); - $style_property_keys = $style_definition['property_keys']; + $css_declarations = array(); + $style_property_keys = $style_definition['property_keys']; + $should_skip_css_vars = isset( $options['convert_vars_to_classnames'] ) && true === $options['convert_vars_to_classnames']; // Build CSS var values from var:? values, e.g, `var(--wp--css--rule-slug )` // Check if the value is a CSS preset and there's a corresponding css_var pattern in the style definition. if ( is_string( $style_value ) && strpos( $style_value, 'var:' ) !== false ) { if ( ! $should_skip_css_vars && ! empty( $style_definition['css_vars'] ) ) { $css_var = static::get_css_var_value( $style_value, $style_definition['css_vars'] ); - if ( $css_var ) { + if ( $css_var && isset( $style_property_keys['default'] ) ) { $css_declarations[ $style_property_keys['default'] ] = $css_var; } } @@ -366,6 +406,9 @@ protected static function get_css_declarations( $style_value, $style_definition, // for styles such as margins and padding. if ( is_array( $style_value ) ) { foreach ( $style_value as $key => $value ) { + if ( ! isset( $style_property_keys['individual'] ) ) { + return $css_declarations; + } if ( is_string( $value ) && strpos( $value, 'var:' ) !== false && ! $should_skip_css_vars && ! empty( $style_definition['css_vars'] ) ) { $value = static::get_css_var_value( $value, $style_definition['css_vars'] ); } @@ -374,7 +417,7 @@ protected static function get_css_declarations( $style_value, $style_definition, $css_declarations[ $individual_property ] = $value; } } - } else { + } elseif ( isset( $style_property_keys['default'] ) ) { $css_declarations[ $style_property_keys['default'] ] = $style_value; } @@ -401,16 +444,20 @@ public function generate( $block_styles, $options ) { return null; } - $css_declarations = array(); - $classnames = array(); - $should_skip_css_vars = isset( $options['convert_vars_to_classnames'] ) && true === $options['convert_vars_to_classnames']; + $css_declarations = array(); + $classnames = array(); + $custom_metadata = isset( $options['custom_metadata'] ) && is_array( $options['custom_metadata'] ) ? $options['custom_metadata'] : null; // Collect CSS and classnames. foreach ( static::BLOCK_STYLE_DEFINITIONS_METADATA as $definition_group_key => $definition_group_style ) { if ( empty( $block_styles[ $definition_group_key ] ) ) { continue; } - foreach ( $definition_group_style as $style_definition ) { + foreach ( $definition_group_style as $style_key => $style_definition ) { + // Merge incoming custom metadata. + if ( isset( $custom_metadata[ "$definition_group_key.$style_key" ] ) ) { + $style_definition = static::merge_custom_style_definitions_metadata( $style_definition, $custom_metadata[ "$definition_group_key.$style_key" ] ); + } $style_value = _wp_array_get( $block_styles, $style_definition['path'], null ); if ( ! static::is_valid_style_value( $style_value ) ) { @@ -418,24 +465,28 @@ public function generate( $block_styles, $options ) { } $classnames = array_merge( $classnames, static::get_classnames( $style_value, $style_definition ) ); - $css_declarations = array_merge( $css_declarations, static::get_css_declarations( $style_value, $style_definition, $should_skip_css_vars ) ); + $css_declarations = array_merge( $css_declarations, static::get_css_declarations( $style_value, $style_definition, $options ) ); } } // Build CSS rules output. - $css_selector = isset( $options['selector'] ) ? $options['selector'] : null; - $style_rules = new WP_Style_Engine_CSS_Declarations( $css_declarations ); + $css_selector = isset( $options['selector'] ) ? $options['selector'] : null; + $should_prettify = isset( $options['prettify'] ) ? $options['prettify'] : null; + $style_rules = new WP_Style_Engine_CSS_Declarations( $css_declarations ); // The return object. $styles_output = array(); - $css = $style_rules->get_styles_string(); + $css = $style_rules->get_styles_string( $should_prettify ); // Return css, if any. if ( ! empty( $css ) ) { $styles_output['css'] = $css; // Return an entire rule if there is a selector. if ( $css_selector ) { - $styles_output['css'] = $css_selector . ' { ' . $css . ' }'; + $new_line = $should_prettify ? "\n" : ''; + $spacer = $should_prettify ? '' : ' '; + // @TODO this is just weird. Simplify? + $styles_output['css'] = "$css_selector {{$spacer}{$new_line}{$css}{$new_line}{$spacer}}$new_line"; } } @@ -456,17 +507,18 @@ public function generate( $block_styles, $options ) { * * @param array $style_value A single raw Gutenberg style attributes value for a CSS property. * @param array $individual_property_definition A single style definition from BLOCK_STYLE_DEFINITIONS_METADATA. - * @param boolean $should_skip_css_vars Whether to skip compiling CSS var values. + * @param array $options Options passed to generate(). * * @return array An array of CSS definitions, e.g., array( "$property" => "$value" ). */ - protected static function get_individual_property_css_declarations( $style_value, $individual_property_definition, $should_skip_css_vars ) { + protected static function get_individual_property_css_declarations( $style_value, $individual_property_definition, $options ) { $css_declarations = array(); if ( ! is_array( $style_value ) || empty( $style_value ) || empty( $individual_property_definition['path'] ) ) { return $css_declarations; } + $should_skip_css_vars = isset( $options['convert_vars_to_classnames'] ) && true === $options['convert_vars_to_classnames']; // The first item in $individual_property_definition['path'] array tells us the style property, e.g., "border". // We use this to get a corresponding CSS style definition such as "color" or "width" from the same group. // The second item in $individual_property_definition['path'] array refers to the individual property marker, e.g., "top". diff --git a/packages/style-engine/phpunit/class-wp-style-engine-test.php b/packages/style-engine/phpunit/class-wp-style-engine-test.php index 3038364a5fc386..71f713810c53d1 100644 --- a/packages/style-engine/phpunit/class-wp-style-engine-test.php +++ b/packages/style-engine/phpunit/class-wp-style-engine-test.php @@ -18,7 +18,7 @@ class WP_Style_Engine_Test extends WP_UnitTestCase { * * @dataProvider data_generate_styles_fixtures */ - function test_generate_styles( $block_styles, $options, $expected_output ) { + public function test_generate_styles( $block_styles, $options, $expected_output ) { $generated_styles = wp_style_engine_generate( $block_styles, $options ); $this->assertSame( $expected_output, $generated_styles ); } @@ -74,8 +74,9 @@ public function data_generate_styles_fixtures() { 'text' => 'var:preset|color|texas-flood', ), 'spacing' => array( - 'margin' => '111px', - 'padding' => '0', + 'margin' => '111px', + 'padding' => '0', + 'blockGap' => '100px', ), 'border' => array( 'color' => 'var:preset|color|cool-caramel', @@ -85,7 +86,7 @@ public function data_generate_styles_fixtures() { ), 'options' => array( 'convert_vars_to_classnames' => true ), 'expected_output' => array( - 'css' => 'border-style: dotted; border-width: 2rem; padding: 0; margin: 111px;', + 'css' => 'border-style: dotted; border-width: 2rem; padding: 0; margin: 111px; grid-gap: 100px;', 'classnames' => 'has-text-color has-texas-flood-color has-border-color has-cool-caramel-border-color', ), ), @@ -157,6 +158,32 @@ public function data_generate_styles_fixtures() { ), ), + 'style_block_with_selector_and_pretty_css' => array( + 'block_styles' => array( + 'spacing' => array( + 'padding' => array( + 'top' => '42px', + 'left' => '2%', + 'bottom' => '44px', + 'right' => '5rem', + ), + ), + ), + 'options' => array( + 'selector' => '.wp-selector > p', + 'prettify' => true, + ), + 'expected_output' => array( + 'css' => '.wp-selector > p { + padding-top: 42px; + padding-left: 2%; + padding-bottom: 44px; + padding-right: 5rem; +} +', + ), + ), + 'elements_with_css_var_value' => array( 'block_styles' => array( 'color' => array( @@ -205,13 +232,14 @@ public function data_generate_styles_fixtures() { 'valid_classnames_and_css_vars' => array( 'block_styles' => array( 'color' => array( - 'text' => 'var:preset|color|teal-independents', + 'text' => 'var:preset|color|teal-independents', + 'background' => 'var:preset|color|blue-ribbon', ), ), 'options' => array(), 'expected_output' => array( - 'css' => 'color: var(--wp--preset--color--teal-independents);', - 'classnames' => 'has-text-color has-teal-independents-color', + 'css' => 'color: var(--wp--preset--color--teal-independents); background-color: var(--wp--preset--color--blue-ribbon);', + 'classnames' => 'has-text-color has-teal-independents-color has-background has-blue-ribbon-background-color', ), ), @@ -299,7 +327,7 @@ public function data_generate_styles_fixtures() { ), ), - 'invalid_classnames_options' => array( + 'invalid_property_array_values' => array( 'block_styles' => array( 'typography' => array( 'fontSize' => array( @@ -373,6 +401,26 @@ public function data_generate_styles_fixtures() { 'css' => 'border-bottom-color: var(--wp--preset--color--terrible-lizard);', ), ), + + 'valid_css_custom_property' => array( + 'block_styles' => array( + 'spacing' => array( + 'blockGap' => '10000rem', + ), + ), + 'options' => array( + 'custom_metadata' => array( + 'spacing.blockGap' => array( + 'property_keys' => array( + 'default' => '--wp--style--block-gap', + ), + ), + ), + ), + 'expected_output' => array( + 'css' => '--wp--style--block-gap: 10000rem;', + ), + ), ); } } diff --git a/test/emptytheme/theme.json b/test/emptytheme/theme.json index ed2d7b8d0946aa..b22c80cb4ebe31 100644 --- a/test/emptytheme/theme.json +++ b/test/emptytheme/theme.json @@ -1,11 +1,357 @@ { "version": 2, + "customTemplates": [ + { + "name": "blank", + "title": "Blank", + "postTypes": [ "page", "post" ] + }, + { + "name": "page-large-header", + "title": "Page (Large Header)", + "postTypes": [ "page" ] + }, + { + "name": "single-no-separators", + "title": "Single Post (No Separators)", + "postTypes": [ "post" ] + }, + { + "name": "page-no-separators", + "title": "Page (No Separators)", + "postTypes": [ "page" ] + } + ], "settings": { "appearanceTools": true, + "color": { + "duotone": [ + { + "colors": [ "#000000", "#ffffff" ], + "slug": "foreground-and-background", + "name": "Foreground and background" + }, + { + "colors": [ "#000000", "#ffe2c7" ], + "slug": "foreground-and-secondary", + "name": "Foreground and secondary" + }, + { + "colors": [ "#000000", "#f6f6f6" ], + "slug": "foreground-and-tertiary", + "name": "Foreground and tertiary" + }, + { + "colors": [ "#1a4548", "#ffffff" ], + "slug": "primary-and-background", + "name": "Primary and background" + }, + { + "colors": [ "#1a4548", "#ffe2c7" ], + "slug": "primary-and-secondary", + "name": "Primary and secondary" + }, + { + "colors": [ "#1a4548", "#f6f6f6" ], + "slug": "primary-and-tertiary", + "name": "Primary and tertiary" + } + ], + "gradients": [ + { + "slug": "vertical-secondary-to-tertiary", + "gradient": "linear-gradient(to bottom,var(--wp--preset--color--secondary) 0%,var(--wp--preset--color--tertiary) 100%)", + "name": "Vertical secondary to tertiary" + }, + { + "slug": "vertical-secondary-to-background", + "gradient": "linear-gradient(to bottom,var(--wp--preset--color--secondary) 0%,var(--wp--preset--color--background) 100%)", + "name": "Vertical secondary to background" + }, + { + "slug": "vertical-tertiary-to-background", + "gradient": "linear-gradient(to bottom,var(--wp--preset--color--tertiary) 0%,var(--wp--preset--color--background) 100%)", + "name": "Vertical tertiary to background" + }, + { + "slug": "diagonal-primary-to-foreground", + "gradient": "linear-gradient(to bottom right,var(--wp--preset--color--primary) 0%,var(--wp--preset--color--foreground) 100%)", + "name": "Diagonal primary to foreground" + }, + { + "slug": "diagonal-secondary-to-background", + "gradient": "linear-gradient(to bottom right,var(--wp--preset--color--secondary) 50%,var(--wp--preset--color--background) 50%)", + "name": "Diagonal secondary to background" + }, + { + "slug": "diagonal-background-to-secondary", + "gradient": "linear-gradient(to bottom right,var(--wp--preset--color--background) 50%,var(--wp--preset--color--secondary) 50%)", + "name": "Diagonal background to secondary" + }, + { + "slug": "diagonal-tertiary-to-background", + "gradient": "linear-gradient(to bottom right,var(--wp--preset--color--tertiary) 50%,var(--wp--preset--color--background) 50%)", + "name": "Diagonal tertiary to background" + }, + { + "slug": "diagonal-background-to-tertiary", + "gradient": "linear-gradient(to bottom right,var(--wp--preset--color--background) 50%,var(--wp--preset--color--tertiary) 50%)", + "name": "Diagonal background to tertiary" + } + ], + "palette": [ + { + "slug": "foreground", + "color": "#000000", + "name": "Foreground" + }, + { + "slug": "background", + "color": "#ffffff", + "name": "Background" + }, + { + "slug": "primary", + "color": "#1a4548", + "name": "Primary" + }, + { + "slug": "secondary", + "color": "#ffe2c7", + "name": "Secondary" + }, + { + "slug": "tertiary", + "color": "#F6F6F6", + "name": "Tertiary" + } + ], + "customDuotone": true + }, + "custom": { + "spacing": { + "small": "max(1.25rem, 5vw)", + "medium": "clamp(2rem, 8vw, calc(4 * var(--wp--style--block-gap)))", + "large": "clamp(4rem, 10vw, 8rem)", + "outer": "var(--wp--custom--spacing--small, 1.25rem)" + }, + "typography": { + "font-size": { + "huge": "clamp(2.25rem, 4vw, 2.75rem)", + "gigantic": "clamp(2.75rem, 6vw, 3.25rem)", + "colossal": "clamp(3.25rem, 8vw, 6.25rem)" + }, + "line-height": { + "tiny": 1.15, + "small": 1.2, + "medium": 1.4, + "normal": 1.6 + } + } + }, + "spacing": { + "units": [ "%", "px", "em", "rem", "vh", "vw" ] + }, + "typography": { + "dropCap": false, + "fontFamilies": [ + { + "fontFamily": "-apple-system,BlinkMacSystemFont,\"Segoe UI\",Roboto,Oxygen-Sans,Ubuntu,Cantarell,\"Helvetica Neue\",sans-serif", + "name": "System Font", + "slug": "system-font" + }, + { + "fontFamily": "\"Source Serif Pro\", serif", + "name": "Source Serif Pro", + "slug": "source-serif-pro" + } + ], + "fontSizes": [ + { + "size": "1rem", + "slug": "small" + }, + { + "size": "1.125rem", + "slug": "medium" + }, + { + "size": "1.75rem", + "slug": "large" + }, + { + "size": "clamp(1.75rem, 3vw, 2.25rem)", + "slug": "x-large" + } + ] + }, "layout": { - "contentSize": "840px", - "wideSize": "1100px" + "contentSize": "650px", + "wideSize": "1000px" + } + }, + "styles": { + "blocks": { + "core/button": { + "border": { + "radius": "0" + }, + "color": { + "background": "var(--wp--preset--color--primary)", + "text": "var(--wp--preset--color--background)" + }, + "typography": { + "fontSize": "var(--wp--preset--font-size--medium)" + } + }, + "core/post-title": { + "typography": { + "fontFamily": "var(--wp--preset--font-family--source-serif-pro)", + "fontWeight": "300", + "lineHeight": "var(--wp--custom--typography--line-height--tiny)", + "fontSize": "var(--wp--custom--typography--font-size--gigantic)" + } + }, + "core/post-comments": { + "spacing": { + "padding": { + "top": "var(--wp--custom--spacing--small)" + } + } + }, + "core/pullquote": { + "border": { + "width": "1px 0" + } + }, + "core/query-title": { + "typography": { + "fontFamily": "var(--wp--preset--font-family--source-serif-pro)", + "fontWeight": "300", + "lineHeight": "var(--wp--custom--typography--line-height--small)", + "fontSize": "var(--wp--custom--typography--font-size--gigantic)" + } + }, + "core/quote": { + "border": { + "width": "1px" + } + }, + "core/site-title": { + "typography": { + "fontFamily": "var(--wp--preset--font-family--system-font)", + "lineHeight": "var(--wp--custom--typography--line-height--normal)", + "fontSize": "var(--wp--preset--font-size--medium)", + "fontWeight": "normal" + } + }, + "core/image": { + "filter": { + "duotone": "var(--wp--preset--duotone--primary-and-tertiary)" + } + }, + "core/group": { + "spacing": { + "margin": { + "top": "40px" + } + }, + "color": { + "background": "var(--wp--preset--color--primary)", + "text": "var(--wp--preset--color--background)" + } + } + }, + "color": { + "background": "var(--wp--preset--color--background)", + "text": "var(--wp--preset--color--foreground)" + }, + "elements": { + "h1": { + "typography": { + "fontFamily": "var(--wp--preset--font-family--source-serif-pro)", + "fontWeight": "300", + "lineHeight": "var(--wp--custom--typography--line-height--tiny)", + "fontSize": "var(--wp--custom--typography--font-size--colossal)" + } + }, + "h2": { + "typography": { + "fontFamily": "var(--wp--preset--font-family--source-serif-pro)", + "fontWeight": "300", + "lineHeight": "var(--wp--custom--typography--line-height--small)", + "fontSize": "var(--wp--custom--typography--font-size--gigantic)" + } + }, + "h3": { + "typography": { + "fontFamily": "var(--wp--preset--font-family--source-serif-pro)", + "fontWeight": "300", + "lineHeight": "var(--wp--custom--typography--line-height--tiny)", + "fontSize": "var(--wp--custom--typography--font-size--huge)" + } + }, + "h4": { + "typography": { + "fontFamily": "var(--wp--preset--font-family--source-serif-pro)", + "fontWeight": "300", + "lineHeight": "var(--wp--custom--typography--line-height--tiny)", + "fontSize": "var(--wp--preset--font-size--x-large)" + } + }, + "h5": { + "typography": { + "fontFamily": "var(--wp--preset--font-family--system-font)", + "fontWeight": "700", + "textTransform": "uppercase", + "lineHeight": "var(--wp--custom--typography--line-height--normal)", + "fontSize": "var(--wp--preset--font-size--medium)" + } + }, + "h6": { + "typography": { + "fontFamily": "var(--wp--preset--font-family--system-font)", + "fontWeight": "400", + "textTransform": "uppercase", + "lineHeight": "var(--wp--custom--typography--line-height--normal)", + "fontSize": "var(--wp--preset--font-size--medium)" + } + }, + "link": { + "color": { + "text": "var(--wp--preset--color--foreground)" + } + } + }, + "spacing": { + "blockGap": "1.5rem" + }, + "typography": { + "fontFamily": "var(--wp--preset--font-family--system-font)", + "lineHeight": "var(--wp--custom--typography--line-height--normal)", + "fontSize": "var(--wp--preset--font-size--medium)" } }, - "patterns": [ "short-text-surrounded-by-round-images", "partner-logos" ] + "templateParts": [ + { + "name": "header", + "title": "Header", + "area": "header" + }, + { + "name": "header-large-dark", + "title": "Header (Dark, large)", + "area": "header" + }, + { + "name": "header-small-dark", + "title": "Header (Dark, small)", + "area": "header" + }, + { + "name": "footer", + "title": "Footer", + "area": "footer" + } + ] }