diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index d578b20c6cb61..c29a18dcee2e0 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -125,7 +125,7 @@ /packages/report-flaky-tests @kevin940726 # wp-env -/packages/env @noahtallen @ObliviousHarmony +/packages/env @noahtallen @ObliviousHarmony @t-hamano # PHP /lib @spacedmonkey diff --git a/.github/workflows/performance.yml b/.github/workflows/performance.yml index 9ced7ce0f4684..7a5c523c8324b 100644 --- a/.github/workflows/performance.yml +++ b/.github/workflows/performance.yml @@ -54,7 +54,7 @@ jobs: WP_VERSION=$(awk -F ': ' '/^Tested up to/{print $2}' readme.txt) IFS=. read -ra WP_VERSION_ARRAY <<< "$WP_VERSION" WP_MAJOR="${WP_VERSION_ARRAY[0]}.${WP_VERSION_ARRAY[1]}" - ./bin/plugin/cli.js perf "wp/$WP_MAJOR" "$PREVIOUS_RELEASE_BRANCH" "$CURRENT_RELEASE_BRANCH" --wp-version "$WP_MAJOR" + ./bin/plugin/cli.js perf "wp/$WP_MAJOR" "$PREVIOUS_RELEASE_BRANCH" "$CURRENT_RELEASE_BRANCH" --tests-branch $GITHUB_SHA --wp-version "$WP_MAJOR" - name: Compare performance with base branch if: github.event_name == 'push' diff --git a/bin/build-plugin-zip.sh b/bin/build-plugin-zip.sh index 4ba931c4a4aeb..131e434d1383d 100755 --- a/bin/build-plugin-zip.sh +++ b/bin/build-plugin-zip.sh @@ -83,6 +83,7 @@ build_files=$( build/block-library/blocks/*.php \ build/block-library/blocks/*/block.json \ build/block-library/blocks/*/*.{js,js.map,css,asset.php} \ + build/block-library/interactivity/*.{js,js.map,asset.php} \ build/edit-widgets/blocks/*/block.json \ build/widgets/blocks/*.php \ build/widgets/blocks/*/block.json \ diff --git a/changelog.txt b/changelog.txt index c0eb6f61a62ae..5e96e8b095999 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,23 @@ == Changelog == -= 15.8.0-rc.1 = += 15.8.1 = + + + +Error: There are no unreleased pull requests associated with the milestone. + at fetchAllPullRequests (/home/runner/work/gutenberg/gutenberg/bin/plugin/commands/changelog.js:684:10) + at processTicksAndRejections (internal/process/task_queues.js:95:5) + at async createChangelog (/home/runner/work/gutenberg/gutenberg/bin/plugin/commands/changelog.js:994:24) + at async getReleaseChangelog (/home/runner/work/gutenberg/gutenberg/bin/plugin/commands/changelog.js:1020:2) + at async Command. (/home/runner/work/gutenberg/gutenberg/bin/plugin/cli.js:11:4) + + += 15.8.0 = + +## Contributors + +The following contributors merged PRs in this release: + ## Changelog @@ -103,6 +120,8 @@ - Fix/wp get global styles for custom props returns internal variable. ([50366](https://github.com/WordPress/gutenberg/pull/50366)) - Revisions controller: Fix author and date fields. ([50117](https://github.com/WordPress/gutenberg/pull/50117)) - Fix hover/focus styles for `style variation` buttons. ([50056](https://github.com/WordPress/gutenberg/pull/50056)) +- Use bundled files for enqueuing global styles. ([50310](https://github.com/WordPress/gutenberg/pull/50310)) + #### Block Editor - Fix issue with margin collapsing when selecting blocks. ([50215](https://github.com/WordPress/gutenberg/pull/50215)) @@ -158,6 +177,7 @@ #### Interactivity API - Add Interactivity API runtime. ([49994](https://github.com/WordPress/gutenberg/pull/49994)) - Navigation block with the Interactivity API. ([50041](https://github.com/WordPress/gutenberg/pull/50041)) +- Fix building plugin zip to include interactive blocks. ([50598](https://github.com/WordPress/gutenberg/pull/50598)) #### Command Center - Update the experiment label. ([50467](https://github.com/WordPress/gutenberg/pull/50467)) @@ -298,6 +318,8 @@ The following contributors merged PRs in this release: @aaronrobertshaw @afercia @ajlende @alexstine @andrewserong @apeatling @artemiomorales @aurooba @bph @chad1008 @ciampo @DAreRodz @dcalhoun @draganescu @ecgan @fluiddot @fullofcaffeine @geriux @getdave @glendaviesnz @gziolo @hellofromtonya @ironprogrammer @jameskoster @jasmussen @jeryj @jhnstn @johnhooks @jsnajdr @juanfra @kevin940726 @kienstra @Mamaduka @margolisj @mburridge @mirka @mokagio @mtias @n2erjo00 @ndiego @noahtallen @noisysocks @ntsekouras @oandregal @ObliviousHarmony @ocean90 @ockham @pavanpatil1 @pooja-muchandikar @priethor @ramonjd @richtabor @samnajian @SantosGuillamot @scruffian @SiobhyB @t-hamano @talldan @tellthemachines @torounit @tyxla @westonruter @youknowriad + + = 15.7.1 = diff --git a/docs/manifest.json b/docs/manifest.json index 8b6677d39c559..d6759f051a679 100644 --- a/docs/manifest.json +++ b/docs/manifest.json @@ -594,13 +594,13 @@ "parent": "reference-guides" }, { - "title": "Version 2 (living reference)", + "title": "Theme.json Version 2", "slug": "theme-json-living", "markdown_source": "../docs/reference-guides/theme-json-reference/theme-json-living.md", "parent": "theme-json-reference" }, { - "title": "Version 1 Reference", + "title": "Theme.json Version 1 Reference", "slug": "theme-json-v1", "markdown_source": "../docs/reference-guides/theme-json-reference/theme-json-v1.md", "parent": "theme-json-reference" diff --git a/docs/reference-guides/block-api/block-transforms.md b/docs/reference-guides/block-api/block-transforms.md index b2970e3d14ff2..5efc76064fe31 100644 --- a/docs/reference-guides/block-api/block-transforms.md +++ b/docs/reference-guides/block-api/block-transforms.md @@ -228,7 +228,7 @@ When pasting content it's possible to define a [content model](https://html.spec When writing `raw` transforms you can control this by supplying a `schema` which describes allowable content and which will be applied to clean up the pasted content before attempting to match with your block. The schemas are passed into [`cleanNodeList` from `@wordpress/dom`](https://github.com/wordpress/gutenberg/blob/trunk/packages/dom/src/dom/clean-node-list.js); check there for a [complete description of the schema](https://github.com/wordpress/gutenberg/blob/trunk/packages/dom/src/phrasing-content.js). ```js -schema = { span: { children: { '#text': {} } } } +schema = { span: { children: { '#text': {} } } }; ``` **Example: a custom content model** @@ -237,8 +237,8 @@ Suppose we want to match the following HTML snippet and turn it into some kind o ```html
-

The Post Title

-

Some great content.

+

The Post Title

+

Some great content.

``` @@ -270,7 +270,7 @@ A transformation of type `shortcode` is an object that takes the following param - **type** _(string)_: the value `shortcode`. - **tag** _(string|array)_: the shortcode tag or list of shortcode aliases this transform can work with. -- **transform** _(function, optional): a callback that receives the shortcode attributes as the first argument and the [WPShortcodeMatch](/packages/shortcode/README.md#next) as the second. It should return a block object or an array of block objects. When this parameter is defined, it will take precedence over the `attributes` parameter. +- **transform** _(function, optional)_: a callback that receives the shortcode attributes as the first argument and the [WPShortcodeMatch](/packages/shortcode/README.md#next) as the second. It should return a block object or an array of block objects. When this parameter is defined, it will take precedence over the `attributes` parameter. - **attributes** _(object, optional)_: object representing where the block attributes should be sourced from, according to the attributes shape defined by the [block configuration object](./block-registration.md). If a particular attribute contains a `shortcode` key, it should be a function that receives the shortcode attributes as the first arguments and the [WPShortcodeMatch](/packages/shortcode/README.md#next) as second, and returns a value for the attribute that will be sourced in the block's comment. - **isMatch** _(function, optional)_: a callback that receives the shortcode attributes per the [Shortcode API](https://codex.wordpress.org/Shortcode_API) and should return a boolean. Returning `false` from this function will prevent the shortcode to be transformed into this block. - **priority** _(number, optional)_: controls the priority with which a transform is applied, where a lower value will take precedence over higher values. This behaves much like a [WordPress hook](https://codex.wordpress.org/Plugin_API#Hook_to_WordPress). Like hooks, the default priority is `10` when not otherwise set. @@ -336,3 +336,25 @@ transforms: { ] }, ``` + +## `ungroup` blocks + +Via the optional `transforms` key of the block configuration, blocks can use the `ungroup` subkey to define the blocks that will replace the block being processed. These new blocks will usually be a subset of the existing inner blocks, but could also include new blocks. + +If a block has an `ungroup` transform, it is eligible for ungrouping, without the requirement of being the default grouping block. The UI used to ungroup a block with this API is the same as the one used for the default grouping block. In order for the Ungroup button to be displayed, we must have a single grouping block selected, which also contains some inner blocks. + +**ungroup** is a callback function that receives the attributes and inner blocks of the block being processed. It should return an array of block objects. + +Example: + +```js +export const settings = { + title: 'My grouping Block Title', + description: 'My grouping block description', + /* ... */ + transforms: { + ungroup: ( attributes, innerBlocks ) => + innerBlocks.flatMap( ( innerBlock ) => innerBlock.innerBlocks ), + }, +}; +``` diff --git a/docs/reference-guides/core-blocks.md b/docs/reference-guides/core-blocks.md index e5d20bb7b1edd..423676e2afe32 100644 --- a/docs/reference-guides/core-blocks.md +++ b/docs/reference-guides/core-blocks.md @@ -86,7 +86,7 @@ Display code snippets that respect your spacing and tabs. ([Source](https://gith - **Name:** core/code - **Category:** text -- **Supports:** anchor, color (background, gradients, text), spacing (margin, padding), typography (fontSize, lineHeight) +- **Supports:** align (wide), anchor, color (background, gradients, text), spacing (margin, padding), typography (fontSize, lineHeight) - **Attributes:** content ## Column @@ -94,7 +94,7 @@ Display code snippets that respect your spacing and tabs. ([Source](https://gith A single column within a columns block. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/column)) - **Name:** core/column -- **Category:** text +- **Category:** design - **Supports:** anchor, color (background, gradients, link, text), spacing (blockGap, padding), typography (fontSize, lineHeight), ~~html~~, ~~reusable~~ - **Attributes:** allowedBlocks, templateLock, verticalAlignment, width @@ -465,7 +465,7 @@ Show a block pattern. ([Source](https://github.com/WordPress/gutenberg/tree/trun - **Name:** core/pattern - **Category:** theme - **Supports:** ~~html~~, ~~inserter~~ -- **Attributes:** slug +- **Attributes:** slug, syncStatus ## Post Author diff --git a/docs/reference-guides/theme-json-reference/theme-json-living.md b/docs/reference-guides/theme-json-reference/theme-json-living.md index 505596819bfb4..3299739575430 100644 --- a/docs/reference-guides/theme-json-reference/theme-json-living.md +++ b/docs/reference-guides/theme-json-reference/theme-json-living.md @@ -1,16 +1,27 @@ -# Version 2 (living reference) +# Theme.json Version 2 -> This is the living specification for the **version 2** of theme.json. This version works with WordPress 5.9 or later, and the latest Gutenberg plugin. +> This is the living specification for **version 2** of `theme.json`. This version works with WordPress 5.9 or later, and the latest Gutenberg plugin. > -> There're related documents you may be interested in: the [theme.json v1](/docs/reference-guides/theme-json-reference/theme-json-v1.md) specification and the [reference to migrate from theme.json v1 to v2](/docs/reference-guides/theme-json-reference/theme-json-migrations.md). +> There are some related documents that you may be interested in: +> - the [theme.json v1](/docs/reference-guides/theme-json-reference/theme-json-v1.md) specification, and +> - the [reference to migrate from theme.json v1 to v2](/docs/reference-guides/theme-json-reference/theme-json-migrations.md). -This reference guide lists the settings and style properties defined in the theme.json schema. See the [theme.json how to guide](/docs/how-to-guides/themes/theme-json.md) for examples and guide on how to use the theme.json file in your theme. +This reference guide lists the settings and style properties defined in the `theme.json` schema. See the [theme.json how to guide](/docs/how-to-guides/themes/theme-json.md) for examples and guidance on how to use the `theme.json` file in your theme. ## Schema -It can be difficult to remember the theme.json settings and properties while you develop, so a JSON scheme was created to help. The schema is available at https://schemas.wp.org/trunk/theme.json +Remembering the `theme.json` settings and properties while you develop can be difficult, so a [JSON schema](https://schemas.wp.org/trunk/theme.json) was created to help. + +Code editors can pick up the schema and can provide helpful hints and suggestions such as tooltips, autocomplete, or schema validation in the editor. To use the schema in Visual Studio Code, add `$schema`: "https://schemas.wp.org/trunk/theme.json" to the beginning of your theme.json file together with a `version` corresponding to the version you wish to use, e.g.: + +``` +{ + "$schema": "https://schemas.wp.org/trunk/theme.json", + "version": 2, + ... +} +``` -Code editors can pick up the schema and can provide help like tooltips, autocomplete, or schema validation in the editor. To use the schema in Visual Studio Code, add "$schema": "https://schemas.wp.org/trunk/theme.json" to the beginning of your theme.json file. ## Settings diff --git a/docs/reference-guides/theme-json-reference/theme-json-v1.md b/docs/reference-guides/theme-json-reference/theme-json-v1.md index d0ed8a70a3110..3e7096ee420ef 100644 --- a/docs/reference-guides/theme-json-reference/theme-json-v1.md +++ b/docs/reference-guides/theme-json-reference/theme-json-v1.md @@ -1,4 +1,4 @@ -# Version 1 Reference +# Theme.json Version 1 Reference Theme.json version 2 has been released, see the [theme.json migration guide](/docs/reference-guides/theme-json-reference/theme-json-migrations.md#migrating-from-v1-to-v2) for updating to the latest version. diff --git a/docs/tool/manifest.js b/docs/tool/manifest.js index e407c47e7284b..d3ed5d61dc0bb 100644 --- a/docs/tool/manifest.js +++ b/docs/tool/manifest.js @@ -14,6 +14,7 @@ const componentPaths = glob( 'packages/components/src/*/**/README.md', { '**/src/ui/**/README.md', 'packages/components/src/theme/README.md', 'packages/components/src/view/README.md', + 'packages/components/src/dropdown-menu-v2/README.md', ], } ); const packagePaths = glob( 'packages/*/package.json' ) diff --git a/gutenberg.php b/gutenberg.php index ce72c8eb81e4c..dbf58c000a107 100644 --- a/gutenberg.php +++ b/gutenberg.php @@ -5,7 +5,7 @@ * Description: Printing since 1440. This is the development plugin for the block editor, site editor, and other future WordPress core functionality. * Requires at least: 6.1 * Requires PHP: 5.6 - * Version: 15.8.0-rc.1 + * Version: 15.8.1 * Author: Gutenberg Team * Text Domain: gutenberg * diff --git a/lib/block-editor-settings.php b/lib/block-editor-settings.php new file mode 100644 index 0000000000000..53668e114e04c --- /dev/null +++ b/lib/block-editor-settings.php @@ -0,0 +1,151 @@ + 'variables', + '__unstableType' => 'presets', + 'isGlobalStyles' => true, + ), + array( + 'css' => 'presets', + '__unstableType' => 'presets', + 'isGlobalStyles' => true, + ), + ); + foreach ( $presets as $preset_style ) { + $actual_css = gutenberg_get_global_stylesheet( array( $preset_style['css'] ) ); + if ( '' !== $actual_css ) { + $preset_style['css'] = $actual_css; + $global_styles[] = $preset_style; + } + } + + if ( wp_theme_has_theme_json() ) { + $block_classes = array( + 'css' => 'styles', + '__unstableType' => 'theme', + 'isGlobalStyles' => true, + ); + $actual_css = gutenberg_get_global_stylesheet( array( $block_classes['css'] ) ); + if ( '' !== $actual_css ) { + $block_classes['css'] = $actual_css; + $global_styles[] = $block_classes; + } + + /* + * Add the custom CSS as a separate stylesheet so any invalid CSS + * entered by users does not break other global styles. + */ + $global_styles[] = array( + 'css' => gutenberg_get_global_styles_custom_css(), + '__unstableType' => 'user', + 'isGlobalStyles' => true, + ); + } else { + // If there is no `theme.json` file, ensure base layout styles are still available. + $block_classes = array( + 'css' => 'base-layout-styles', + '__unstableType' => 'base-layout', + 'isGlobalStyles' => true, + ); + $actual_css = gutenberg_get_global_stylesheet( array( $block_classes['css'] ) ); + if ( '' !== $actual_css ) { + $block_classes['css'] = $actual_css; + $global_styles[] = $block_classes; + } + } + + $settings['styles'] = array_merge( $global_styles, get_block_editor_theme_styles() ); + + $settings['__experimentalFeatures'] = gutenberg_get_global_settings(); + // These settings may need to be updated based on data coming from theme.json sources. + if ( isset( $settings['__experimentalFeatures']['color']['palette'] ) ) { + $colors_by_origin = $settings['__experimentalFeatures']['color']['palette']; + $settings['colors'] = isset( $colors_by_origin['custom'] ) ? + $colors_by_origin['custom'] : ( + isset( $colors_by_origin['theme'] ) ? + $colors_by_origin['theme'] : + $colors_by_origin['default'] + ); + } + if ( isset( $settings['__experimentalFeatures']['color']['gradients'] ) ) { + $gradients_by_origin = $settings['__experimentalFeatures']['color']['gradients']; + $settings['gradients'] = isset( $gradients_by_origin['custom'] ) ? + $gradients_by_origin['custom'] : ( + isset( $gradients_by_origin['theme'] ) ? + $gradients_by_origin['theme'] : + $gradients_by_origin['default'] + ); + } + if ( isset( $settings['__experimentalFeatures']['typography']['fontSizes'] ) ) { + $font_sizes_by_origin = $settings['__experimentalFeatures']['typography']['fontSizes']; + $settings['fontSizes'] = isset( $font_sizes_by_origin['custom'] ) ? + $font_sizes_by_origin['custom'] : ( + isset( $font_sizes_by_origin['theme'] ) ? + $font_sizes_by_origin['theme'] : + $font_sizes_by_origin['default'] + ); + } + if ( isset( $settings['__experimentalFeatures']['color']['custom'] ) ) { + $settings['disableCustomColors'] = ! $settings['__experimentalFeatures']['color']['custom']; + unset( $settings['__experimentalFeatures']['color']['custom'] ); + } + if ( isset( $settings['__experimentalFeatures']['color']['customGradient'] ) ) { + $settings['disableCustomGradients'] = ! $settings['__experimentalFeatures']['color']['customGradient']; + unset( $settings['__experimentalFeatures']['color']['customGradient'] ); + } + if ( isset( $settings['__experimentalFeatures']['typography']['customFontSize'] ) ) { + $settings['disableCustomFontSizes'] = ! $settings['__experimentalFeatures']['typography']['customFontSize']; + unset( $settings['__experimentalFeatures']['typography']['customFontSize'] ); + } + if ( isset( $settings['__experimentalFeatures']['typography']['lineHeight'] ) ) { + $settings['enableCustomLineHeight'] = $settings['__experimentalFeatures']['typography']['lineHeight']; + unset( $settings['__experimentalFeatures']['typography']['lineHeight'] ); + } + if ( isset( $settings['__experimentalFeatures']['spacing']['units'] ) ) { + $settings['enableCustomUnits'] = $settings['__experimentalFeatures']['spacing']['units']; + unset( $settings['__experimentalFeatures']['spacing']['units'] ); + } + if ( isset( $settings['__experimentalFeatures']['spacing']['padding'] ) ) { + $settings['enableCustomSpacing'] = $settings['__experimentalFeatures']['spacing']['padding']; + unset( $settings['__experimentalFeatures']['spacing']['padding'] ); + } + if ( isset( $settings['__experimentalFeatures']['spacing']['customSpacingSize'] ) ) { + $settings['disableCustomSpacingSizes'] = ! $settings['__experimentalFeatures']['spacing']['customSpacingSize']; + unset( $settings['__experimentalFeatures']['spacing']['customSpacingSize'] ); + } + + if ( isset( $settings['__experimentalFeatures']['spacing']['spacingSizes'] ) ) { + $spacing_sizes_by_origin = $settings['__experimentalFeatures']['spacing']['spacingSizes']; + $settings['spacingSizes'] = isset( $spacing_sizes_by_origin['custom'] ) ? + $spacing_sizes_by_origin['custom'] : ( + isset( $spacing_sizes_by_origin['theme'] ) ? + $spacing_sizes_by_origin['theme'] : + $spacing_sizes_by_origin['default'] + ); + } + + return $settings; +} +add_filter( 'block_editor_settings_all', 'gutenberg_get_block_editor_settings', 0 ); diff --git a/lib/class-wp-duotone-gutenberg.php b/lib/class-wp-duotone-gutenberg.php index b461e4ba0a64f..b18121086bae0 100644 --- a/lib/class-wp-duotone-gutenberg.php +++ b/lib/class-wp-duotone-gutenberg.php @@ -712,6 +712,15 @@ private static function enqueue_custom_filter( $filter_id, $duotone_selector, $f * @param string $filter_value The filter CSS value. e.g. 'url(#wp-duotone-blue-orange)' or 'unset'. */ private static function enqueue_global_styles_preset( $filter_id, $duotone_selector, $filter_value ) { + if ( ! array_key_exists( $filter_id, self::$global_styles_presets ) ) { + $error_message = sprintf( + /* translators: %s: duotone filter ID */ + __( 'The duotone id "%s" is not registered in theme.json settings', 'gutenberg' ), + $filter_id + ); + _doing_it_wrong( __METHOD__, $error_message, '6.3.0' ); + return; + } self::$used_global_styles_presets[ $filter_id ] = self::$global_styles_presets[ $filter_id ]; self::enqueue_custom_filter( $filter_id, $duotone_selector, $filter_value, self::$global_styles_presets[ $filter_id ] ); } diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php index 6f72ef2c403ce..dc9c25c8f90a5 100644 --- a/lib/class-wp-theme-json-gutenberg.php +++ b/lib/class-wp-theme-json-gutenberg.php @@ -1928,10 +1928,6 @@ protected static function compute_style_properties( $styles, $settings = array() /** * Returns the style property for the given path. * - * It also converts CSS Custom Property stored as - * "var:preset|color|secondary" to the form - * "--wp--preset--color--secondary". - * * It also converts references to a path to the value * stored at that location, e.g. * { "ref": "style.color.background" } => "#fff". diff --git a/lib/compat/wordpress-6.2/block-editor-settings.php b/lib/compat/wordpress-6.2/block-editor-settings.php deleted file mode 100644 index 593a8b7e6b55f..0000000000000 --- a/lib/compat/wordpress-6.2/block-editor-settings.php +++ /dev/null @@ -1,31 +0,0 @@ - gutenberg_get_global_styles_custom_css(), - '__unstableType' => 'user', - 'isGlobalStyles' => true, - ); - } - - // Copied from get_block_editor_settings() at wordpress-develop/block-editor.php. - $settings['__experimentalFeatures'] = gutenberg_get_global_settings(); - - return $settings; -} - -add_filter( 'block_editor_settings_all', 'gutenberg_get_block_editor_settings_6_2', PHP_INT_MAX ); diff --git a/lib/compat/wordpress-6.2/default-filters.php b/lib/compat/wordpress-6.2/default-filters.php index 6a5bcb3b75b05..7e797af3e43b1 100644 --- a/lib/compat/wordpress-6.2/default-filters.php +++ b/lib/compat/wordpress-6.2/default-filters.php @@ -17,13 +17,6 @@ * @package gutenberg */ -/** - * When backporting to core, the existing filters hooked to WP_Theme_JSON_Resolver::clean_cached_data() - * need to be removed. - */ -add_action( 'start_previewing_theme', '_gutenberg_clean_theme_json_caches' ); -add_action( 'switch_theme', '_gutenberg_clean_theme_json_caches' ); - /** * This is a temporary fix to ensure that the block editor styles are enqueued * in the order the iframe expects. diff --git a/lib/compat/wordpress-6.2/get-global-styles-and-settings.php b/lib/compat/wordpress-6.2/get-global-styles-and-settings.php index e02a0466a0b98..eb1481a3808b6 100644 --- a/lib/compat/wordpress-6.2/get-global-styles-and-settings.php +++ b/lib/compat/wordpress-6.2/get-global-styles-and-settings.php @@ -59,176 +59,6 @@ function wp_theme_has_theme_json_clean_cache() { } } -/** - * Gets the global styles custom css from theme.json. - * - * @return string - */ -function gutenberg_get_global_styles_custom_css() { - // Ignore cache when `WP_DEBUG` is enabled, so it doesn't interfere with the theme developers workflow. - $can_use_cached = ! WP_DEBUG; - $cache_key = 'gutenberg_get_global_custom_css'; - $cache_group = 'theme_json'; - if ( $can_use_cached ) { - $cached = wp_cache_get( $cache_key, $cache_group ); - if ( $cached ) { - return $cached; - } - } - - if ( ! wp_theme_has_theme_json() ) { - return ''; - } - - $tree = WP_Theme_JSON_Resolver_Gutenberg::get_merged_data(); - $stylesheet = $tree->get_custom_css(); - - if ( $can_use_cached ) { - wp_cache_set( $cache_key, $stylesheet, $cache_group ); - } - - return $stylesheet; -} - -/** - * Returns the stylesheet resulting of merging core, theme, and user data. - * - * @param array $types Types of styles to load. Optional. - * It accepts as values: 'variables', 'presets', 'styles', 'base-layout-styles. - * If empty, it'll load the following: - * - for themes without theme.json: 'variables', 'presets', 'base-layout-styles'. - * - for themes with theme.json: 'variables', 'presets', 'styles'. - * - * @return string Stylesheet. - */ -function gutenberg_get_global_stylesheet( $types = array() ) { - // Ignore cache when `WP_DEBUG` is enabled, so it doesn't interfere with the theme developers workflow. - $can_use_cached = empty( $types ) && ! WP_DEBUG; - $cache_key = 'gutenberg_get_global_stylesheet'; - $cache_group = 'theme_json'; - if ( $can_use_cached ) { - $cached = wp_cache_get( $cache_key, $cache_group ); - if ( $cached ) { - return $cached; - } - } - $tree = WP_Theme_JSON_Resolver_Gutenberg::get_merged_data(); - $supports_theme_json = wp_theme_has_theme_json(); - if ( empty( $types ) && ! $supports_theme_json ) { - $types = array( 'variables', 'presets', 'base-layout-styles' ); - } elseif ( empty( $types ) ) { - $types = array( 'variables', 'presets', 'styles' ); - } - - /* - * If variables are part of the stylesheet, - * we add them. - * - * This is so themes without a theme.json still work as before 5.9: - * they can override the default presets. - * See https://core.trac.wordpress.org/ticket/54782 - */ - $styles_variables = ''; - if ( in_array( 'variables', $types, true ) ) { - /* - * We only use the default, theme, and custom origins. - * This is because styles for blocks origin are added - * at a later phase (render cycle) so we only render the ones in use. - * @see wp_add_global_styles_for_blocks - */ - $origins = array( 'default', 'theme', 'custom' ); - $styles_variables = $tree->get_stylesheet( array( 'variables' ), $origins ); - $types = array_diff( $types, array( 'variables' ) ); - } - - /* - * For the remaining types (presets, styles), we do consider origins: - * - * - themes without theme.json: only the classes for the presets defined by core - * - themes with theme.json: the presets and styles classes, both from core and the theme - */ - $styles_rest = ''; - if ( ! empty( $types ) ) { - /* - * We only use the default, theme, and custom origins. - * This is because styles for blocks origin are added - * at a later phase (render cycle) so we only render the ones in use. - * @see wp_add_global_styles_for_blocks - */ - $origins = array( 'default', 'theme', 'custom' ); - if ( ! $supports_theme_json ) { - $origins = array( 'default' ); - } - $styles_rest = $tree->get_stylesheet( $types, $origins ); - } - $stylesheet = $styles_variables . $styles_rest; - if ( $can_use_cached ) { - wp_cache_set( $cache_key, $stylesheet, $cache_group ); - } - return $stylesheet; -} - -/** - * Function to get the settings resulting of merging core, theme, and user data. - * - * @param array $path Path to the specific setting to retrieve. Optional. - * If empty, will return all settings. - * @param array $context { - * Metadata to know where to retrieve the $path from. Optional. - * - * @type string $block_name Which block to retrieve the settings from. - * If empty, it'll return the settings for the global context. - * @type string $origin Which origin to take data from. - * Valid values are 'all' (core, theme, and user) or 'base' (core and theme). - * If empty or unknown, 'all' is used. - * } - * - * @return array The settings to retrieve. - */ -function gutenberg_get_global_settings( $path = array(), $context = array() ) { - if ( ! empty( $context['block_name'] ) ) { - $new_path = array( 'blocks', $context['block_name'] ); - foreach ( $path as $subpath ) { - $new_path[] = $subpath; - } - $path = $new_path; - } - - // This is the default value when no origin is provided or when it is 'all'. - $origin = 'custom'; - if ( - ! wp_theme_has_theme_json() || - ( isset( $context['origin'] ) && 'base' === $context['origin'] ) - ) { - $origin = 'theme'; - } - - $cache_group = 'theme_json'; - $cache_key = 'gutenberg_get_global_settings_' . $origin; - $settings = wp_cache_get( $cache_key, $cache_group ); - - if ( false === $settings || WP_DEBUG ) { - $settings = WP_Theme_JSON_Resolver_Gutenberg::get_merged_data( $origin )->get_settings(); - wp_cache_set( $cache_key, $settings, $cache_group ); - } - - return _wp_array_get( $settings, $path, $settings ); -} - -/** - * Private function to clean the caches used by gutenberg_get_global_settings method. - * - * @access private - */ -function _gutenberg_clean_theme_json_caches() { - wp_cache_delete( 'wp_theme_has_theme_json', 'theme_json' ); - wp_cache_delete( 'gutenberg_get_global_stylesheet', 'theme_json' ); - wp_cache_delete( 'gutenberg_get_global_settings_custom', 'theme_json' ); - wp_cache_delete( 'gutenberg_get_global_settings_theme', 'theme_json' ); - wp_cache_delete( 'gutenberg_get_global_custom_css', 'theme_json' ); - WP_Theme_JSON_Resolver_Gutenberg::clean_cached_data(); -} - /** * Tell the cache mechanisms not to persist theme.json data across requests. * The data stored under this cache group: diff --git a/lib/compat/wordpress-6.2/script-loader.php b/lib/compat/wordpress-6.2/script-loader.php index 142cbf4e1477b..6ed69244726d3 100644 --- a/lib/compat/wordpress-6.2/script-loader.php +++ b/lib/compat/wordpress-6.2/script-loader.php @@ -152,25 +152,3 @@ function( $settings ) { }, 100 ); - -/** - * Enqueues the global styles custom css. - * - * @since 6.2.0 - */ -function gutenberg_enqueue_global_styles_custom_css() { - if ( ! wp_is_block_theme() ) { - return; - } - - // Don't enqueue Customizer's custom CSS separately. - remove_action( 'wp_head', 'wp_custom_css_cb', 101 ); - - $custom_css = wp_get_custom_css(); - $custom_css .= gutenberg_get_global_styles_custom_css(); - - if ( ! empty( $custom_css ) ) { - wp_add_inline_style( 'global-styles', $custom_css ); - } -} -add_action( 'wp_enqueue_scripts', 'gutenberg_enqueue_global_styles_custom_css' ); diff --git a/lib/compat/wordpress-6.3/class-gutenberg-rest-global-styles-controller-6-3.php b/lib/compat/wordpress-6.3/class-gutenberg-rest-global-styles-controller-6-3.php index 5eeb0a1014aed..09b0f4ec65dbf 100644 --- a/lib/compat/wordpress-6.3/class-gutenberg-rest-global-styles-controller-6-3.php +++ b/lib/compat/wordpress-6.3/class-gutenberg-rest-global-styles-controller-6-3.php @@ -10,14 +10,6 @@ * Base Global Styles REST API Controller. */ class Gutenberg_REST_Global_Styles_Controller_6_3 extends Gutenberg_REST_Global_Styles_Controller_6_2 { - /** - * Revision controller. - * - * @since 6.3.0 - * @var WP_REST_Revisions_Controller - */ - private $revisions_controller; - /** * Prepares links for the request. * diff --git a/lib/compat/wordpress-6.3/get-global-styles-and-settings.php b/lib/compat/wordpress-6.3/get-global-styles-and-settings.php index 609d9b3de38a1..009fa6253f79d 100644 --- a/lib/compat/wordpress-6.3/get-global-styles-and-settings.php +++ b/lib/compat/wordpress-6.3/get-global-styles-and-settings.php @@ -112,49 +112,3 @@ function wp_get_block_css_selector( $block_type, $target = 'root', $fallback = f return null; } } - -/** - * Returns the current theme's wanted patterns(slugs) to be - * registered from Pattern Directory. - * - * @since 6.3.0 - * - * @return string[] - */ -function gutenberg_get_remote_theme_patterns() { - return WP_Theme_JSON_Resolver_Gutenberg::get_theme_data( array(), array( 'with_supports' => false ) )->get_patterns(); -} - -/** - * Gets the styles resulting of merging core, theme, and user data. - * - * @since 5.9.0 - * @since 6.3.0 the internal link format "var:preset|color|secondary" is resolved - * to "var(--wp--preset--font-size--small)" so consumers don't have to. - * - * @param array $path Path to the specific style to retrieve. Optional. - * If empty, will return all styles. - * @param array $context { - * Metadata to know where to retrieve the $path from. Optional. - * - * @type string $block_name Which block to retrieve the styles from. - * If empty, it'll return the styles for the global context. - * @type string $origin Which origin to take data from. - * Valid values are 'all' (core, theme, and user) or 'base' (core and theme). - * If empty or unknown, 'all' is used. - * } - * @return array The styles to retrieve. - */ -function gutenberg_get_global_styles( $path = array(), $context = array() ) { - if ( ! empty( $context['block_name'] ) ) { - $path = array_merge( array( 'blocks', $context['block_name'] ), $path ); - } - - $origin = 'custom'; - if ( isset( $context['origin'] ) && 'base' === $context['origin'] ) { - $origin = 'theme'; - } - $styles = WP_Theme_JSON_Resolver_Gutenberg::get_merged_data( $origin )->get_raw_data()['styles']; - - return _wp_array_get( $styles, $path, $styles ); -} diff --git a/lib/compat/wordpress-6.3/link-template.php b/lib/compat/wordpress-6.3/link-template.php new file mode 100644 index 0000000000000..366dedba2b5aa --- /dev/null +++ b/lib/compat/wordpress-6.3/link-template.php @@ -0,0 +1,34 @@ +post_type || 'wp_template_part' === $post->post_type ) { + $post_type_object = get_post_type_object( $post->post_type ); + $slug = urlencode( get_stylesheet() . '//' . $post->post_name ); + $link = admin_url( sprintf( $post_type_object->_edit_link, $slug ) ); + } + return $link; +} + +add_filter( 'get_edit_post_link', 'gutenberg_update_get_edit_post_link', 10, 2 ); diff --git a/lib/compat/wordpress-6.3/navigation-block-preloading.php b/lib/compat/wordpress-6.3/navigation-block-preloading.php new file mode 100644 index 0000000000000..82fe81b236a59 --- /dev/null +++ b/lib/compat/wordpress-6.3/navigation-block-preloading.php @@ -0,0 +1,63 @@ +name ) && 'core/edit-site' !== $context->name ) { + return $preload_paths; + } + + $navigation_rest_route = rest_get_route_for_post_type_items( + 'wp_navigation' + ); + + // Preload the OPTIONS request for all Navigation posts request. + $preload_paths[] = array( $navigation_rest_route, 'OPTIONS' ); + + // Preload the GET request for ALL 'published' or 'draft' Navigation posts. + $preload_paths[] = array( + add_query_arg( + array( + 'context' => 'edit', + 'per_page' => 100, + '_locale' => 'user', + // array indices are required to avoid query being encoded and not matching in cache. + 'status[0]' => 'publish', + 'status[1]' => 'draft', + ), + $navigation_rest_route + ), + 'GET', + ); + + // Preload request for Browse Mode sidebar "Navigation" section. + $preload_paths[] = array( + add_query_arg( + array( + 'context' => 'edit', + 'per_page' => 1, + 'status' => 'publish', + 'order' => 'desc', + 'orderby' => 'date', + ), + $navigation_rest_route + ), + 'GET', + ); + + return $preload_paths; +} +add_filter( 'block_editor_rest_api_preload_paths', 'gutenberg_preload_navigation_posts', 10, 2 ); diff --git a/lib/compat/wordpress-6.3/rest-api.php b/lib/compat/wordpress-6.3/rest-api.php index e111980887ef5..757bd317dcd54 100644 --- a/lib/compat/wordpress-6.3/rest-api.php +++ b/lib/compat/wordpress-6.3/rest-api.php @@ -15,21 +15,35 @@ function gutenberg_register_rest_pattern_directory() { add_action( 'rest_api_init', 'gutenberg_register_rest_pattern_directory' ); /** - * Update `wp_template` and `wp_template-part` post types to use - * Gutenberg's REST controller. + * Updates `wp_template` and `wp_template_part` post types to use + * Gutenberg's REST controllers + * + * Adds `_edit_link` to the `wp_global_styles`, `wp_template`, + * and `wp_template_part` post type schemata. See https://github.com/WordPress/gutenberg/issues/48065 * * @param array $args Array of arguments for registering a post type. * @param string $post_type Post type key. */ function gutenberg_update_templates_template_parts_rest_controller( $args, $post_type ) { if ( in_array( $post_type, array( 'wp_template', 'wp_template_part' ), true ) ) { + $template_edit_link = 'site-editor.php?' . build_query( + array( + 'postType' => $post_type, + 'postId' => '%s', + 'canvas' => 'edit', + ) + ); + $args['_edit_link'] = $template_edit_link; $args['rest_controller_class'] = 'Gutenberg_REST_Templates_Controller_6_3'; } + + if ( in_array( $post_type, array( 'wp_global_styles' ), true ) ) { + $args['_edit_link'] = '/site-editor.php?canvas=edit'; + } return $args; } add_filter( 'register_post_type_args', 'gutenberg_update_templates_template_parts_rest_controller', 10, 2 ); - /** * Registers the Global Styles Revisions REST API routes. */ diff --git a/lib/experimental/editor-settings.php b/lib/experimental/editor-settings.php index c7dd5850a505c..96cd4e4844039 100644 --- a/lib/experimental/editor-settings.php +++ b/lib/experimental/editor-settings.php @@ -83,24 +83,18 @@ function gutenberg_enable_experiments() { if ( $gutenberg_experiments && array_key_exists( 'gutenberg-color-randomizer', $gutenberg_experiments ) ) { wp_add_inline_script( 'wp-block-editor', 'window.__experimentalEnableColorRandomizer = true', 'before' ); } - if ( $gutenberg_experiments && array_key_exists( 'gutenberg-command-center', $gutenberg_experiments ) ) { - wp_add_inline_script( 'wp-edit-site', 'window.__experimentalEnableCommandCenter = true', 'before' ); - } - if ( $gutenberg_experiments && array_key_exists( 'gutenberg-command-center', $gutenberg_experiments ) ) { - wp_add_inline_script( 'wp-edit-post', 'window.__experimentalEnableCommandCenter = true', 'before' ); - } if ( $gutenberg_experiments && array_key_exists( 'gutenberg-group-grid-variation', $gutenberg_experiments ) ) { wp_add_inline_script( 'wp-block-editor', 'window.__experimentalEnableGroupGridVariation = true', 'before' ); } if ( $gutenberg_experiments && array_key_exists( 'gutenberg-details-blocks', $gutenberg_experiments ) ) { wp_add_inline_script( 'wp-block-editor', 'window.__experimentalEnableDetailsBlocks = true', 'before' ); } - if ( $gutenberg_experiments && array_key_exists( 'gutenberg-interactivity-api-navigation-block', $gutenberg_experiments ) ) { - wp_add_inline_script( 'wp-block-editor', 'window.__experimentalEnableNavigationBlockInteractivity = true', 'before' ); - } if ( $gutenberg_experiments && array_key_exists( 'gutenberg-theme-previews', $gutenberg_experiments ) ) { wp_add_inline_script( 'wp-block-editor', 'window.__experimentalEnableThemePreviews = true', 'before' ); } + if ( $gutenberg_experiments && array_key_exists( 'gutenberg-pattern-enhancements', $gutenberg_experiments ) ) { + wp_add_inline_script( 'wp-block-editor', 'window.__experimentalEnablePatternEnhancements = true', 'before' ); + } } diff --git a/lib/experimental/fonts-api/class-wp-fonts-resolver.php b/lib/experimental/fonts-api/class-wp-fonts-resolver.php new file mode 100644 index 0000000000000..d3d0ecba992b8 --- /dev/null +++ b/lib/experimental/fonts-api/class-wp-fonts-resolver.php @@ -0,0 +1,109 @@ +get_raw_data(); + if ( isset( $user_global_styles['styles'] ) ) { + $user_selected_fonts = static::get_user_selected_fonts( $user_global_styles['styles'] ); + } + + if ( empty( $user_selected_fonts ) ) { + return array(); + } + + wp_enqueue_fonts( $user_selected_fonts ); + return $user_selected_fonts; + } + + /** + * Gets the user-selected font-family handles. + * + * @since X.X.X + * + * @param array $global_styles Global styles potentially containing user-selected fonts. + * @return array User-selected font-families. + */ + private static function get_user_selected_fonts( array $global_styles ) { + $font_families = array(); + + foreach ( static::$global_styles_font_family_structure as $path ) { + $style_value = _wp_array_get( $global_styles, $path, '' ); + + $font_family = static::get_value_from_style( $style_value ); + if ( '' !== $font_family ) { + $font_families[] = $font_family; + } + } + + return array_unique( $font_families ); + } + + /** + * Get the value (i.e. preset slug) from the given style value. + * + * @since X.X.X + * + * @param string $style The style to parse. + * @param string $preset_type Optional. The type to parse. Default 'font-family'. + * @return string Preset slug. + */ + private static function get_value_from_style( $style, $preset_type = 'font-family' ) { + if ( '' === $style ) { + return ''; + } + + $starting_pattern = "var(--wp--preset--{$preset_type}--"; + $ending_pattern = ')'; + if ( ! str_starts_with( $style, $starting_pattern ) ) { + return ''; + } + + $offset = strlen( $starting_pattern ); + $length = strpos( $style, $ending_pattern ) - $offset; + return substr( $style, $offset, $length ); + } +} diff --git a/lib/experimental/fonts-api/fonts-api.php b/lib/experimental/fonts-api/fonts-api.php index 5f3f7a60ee883..7075f20f76a21 100644 --- a/lib/experimental/fonts-api/fonts-api.php +++ b/lib/experimental/fonts-api/fonts-api.php @@ -198,19 +198,17 @@ function wp_print_fonts( $handles = false ) { return array(); } - // Skip this reassignment decision-making when using the default of `false`. - if ( false !== $handles ) { - // When `true`, print all registered fonts for the iframed editor. - if ( $in_iframed_editor ) { - $queue = $wp_fonts->queue; - $done = $wp_fonts->done; - $wp_fonts->done = array(); - $wp_fonts->queue = $registered; - $handles = false; - } elseif ( empty( $handles ) ) { - // When falsey, assign `false` to print enqueued fonts. - $handles = false; - } + if ( empty( $handles ) ) { + // Automatically enqueue all user-selected fonts. + WP_Fonts_Resolver::enqueue_user_selected_fonts(); + $handles = false; + } elseif ( $in_iframed_editor ) { + // Print all registered fonts for the iframed editor. + $queue = $wp_fonts->queue; + $done = $wp_fonts->done; + $wp_fonts->done = array(); + $wp_fonts->queue = $registered; + $handles = false; } _wp_scripts_maybe_doing_it_wrong( __FUNCTION__ ); diff --git a/lib/experimental/interactivity-api/navigation-block-interactivity.php b/lib/experimental/interactivity-api/blocks.php similarity index 79% rename from lib/experimental/interactivity-api/navigation-block-interactivity.php rename to lib/experimental/interactivity-api/blocks.php index 21e1e0381b70e..1c6e7d2b1fbb9 100644 --- a/lib/experimental/interactivity-api/navigation-block-interactivity.php +++ b/lib/experimental/interactivity-api/blocks.php @@ -6,6 +6,29 @@ * @package gutenberg */ +/** + * Adds Interactivity API directives to the File block markup using the Tag Processor. + * + * @param string $block_content Markup of the File block. + * @param array $block The full block, including name and attributes. + * @param WP_Block $instance The block instance. + * + * @return string File block markup with the directives injected when applicable. + */ +function gutenberg_block_core_file_add_directives_to_content( $block_content, $block, $instance ) { + if ( empty( $instance->attributes['displayPreview'] ) ) { + return $block_content; + } + $processor = new WP_HTML_Tag_Processor( $block_content ); + $processor->next_tag(); + $processor->set_attribute( 'data-wp-island', '' ); + $processor->next_tag( 'object' ); + $processor->set_attribute( 'data-wp-bind.hidden', '!selectors.core.file.hasPdfPreview' ); + $processor->set_attribute( 'hidden', true ); + return $processor->get_updated_html(); +} +add_filter( 'render_block_core/file', 'gutenberg_block_core_file_add_directives_to_content', 10, 3 ); + /** * Add Interactivity API directives to the navigation block markup using the Tag Processor * The final HTML of the navigation block will look similar to this: @@ -24,8 +47,8 @@ * data-wp-class.has-modal-open="context.core.navigation.isMenuOpen" * data-wp-class.is-menu-open="context.core.navigation.isMenuOpen" * data-wp-bind.aria-hidden="!context.core.navigation.isMenuOpen" - * data-wp-effect="effects.core.navigation.initModal" - * data-wp-on.keydow="actions.core.navigation.handleMenuKeydown" + * data-wp-effect="effects.core.navigation.initMenu" + * data-wp-on.keydown="actions.core.navigation.handleMenuKeydown" * data-wp-on.focusout="actions.core.navigation.handleMenuFocusout" * tabindex="-1" * > @@ -74,21 +97,6 @@ function gutenberg_block_core_navigation_add_directives_to_markup( $block_conten // If the open modal button not found, we handle submenus immediately. $w = new WP_HTML_Tag_Processor( $w->get_updated_html() ); - // Add directives to the menu container. - if ( $w->next_tag( - array( - 'tag_name' => 'UL', - 'class_name' => 'wp-block-navigation__container', - ) - ) ) { - $w->set_attribute( 'data-wp-class.is-menu-open', 'context.core.navigation.isMenuOpen' ); - $w->set_attribute( 'data-wp-bind.aria-hidden', '!context.core.navigation.isMenuOpen' ); - $w->set_attribute( 'data-wp-effect', 'effects.core.navigation.initModal' ); - $w->set_attribute( 'data-wp-on.keydown', 'actions.core.navigation.handleMenuKeydown' ); - $w->set_attribute( 'data-wp-on.focusout', 'actions.core.navigation.handleMenuFocusout' ); - $w->set_attribute( 'tabindex', '-1' ); - }; - gutenberg_block_core_navigation_add_directives_to_submenu( $w ); return $w->get_updated_html(); @@ -104,7 +112,7 @@ function gutenberg_block_core_navigation_add_directives_to_markup( $block_conten $w->set_attribute( 'data-wp-class.has-modal-open', 'context.core.navigation.isMenuOpen' ); $w->set_attribute( 'data-wp-class.is-menu-open', 'context.core.navigation.isMenuOpen' ); $w->set_attribute( 'data-wp-bind.aria-hidden', '!context.core.navigation.isMenuOpen' ); - $w->set_attribute( 'data-wp-effect', 'effects.core.navigation.initModal' ); + $w->set_attribute( 'data-wp-effect', 'effects.core.navigation.initMenu' ); $w->set_attribute( 'data-wp-on.keydown', 'actions.core.navigation.handleMenuKeydown' ); $w->set_attribute( 'data-wp-on.focusout', 'actions.core.navigation.handleMenuFocusout' ); $w->set_attribute( 'tabindex', '-1' ); @@ -168,7 +176,7 @@ function gutenberg_block_core_navigation_add_directives_to_markup( $block_conten * Title *