diff --git a/.travis.yml b/.travis.yml index 32e41294c57f9..db9acbf2d2174 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,6 +21,7 @@ branches: only: - master - rnmobile/master + - rnmobile/releases - /wp\/.*/ env: diff --git a/README.md b/README.md index e6b4565775def..c11f2a71a5650 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![Build Status](https://img.shields.io/travis/com/WordPress/gutenberg/master.svg)](https://travis-ci.com/WordPress/gutenberg) [![lerna](https://img.shields.io/badge/maintained%20with-lerna-cc00ff.svg)](https://lerna.js.org) -![Screenshot of the Gutenberg Editor, editing a post in WordPress](https://cldup.com/H0oKBfpidk.png) +![Screenshot of the Gutenberg Editor, editing a post in WordPress](https://cldup.com/R84R5fNgrI.png) This repo is the development hub for the editor focus in WordPress Core. `Gutenberg` is the project name. @@ -32,7 +32,6 @@ Here's why we're looking at the whole editing screen, as opposed to just the con 4. **A fresh look at content creation.** Considering the whole interface lays a solid foundation for the next focus: full site customization. 5. **Modern tooling.** Looking at the full editor screen also gives WordPress the opportunity to drastically modernize the foundation, and take steps towards a more fluid and JavaScript-powered future that fully leverages the WordPress REST API. -![Writing in Gutenberg 1.6](https://make.wordpress.org/core/files/2017/10/gutenberg-typing-1_6.gif) ## Blocks diff --git a/bin/commander.js b/bin/commander.js index dcc863872f034..95cfc56b25efd 100755 --- a/bin/commander.js +++ b/bin/commander.js @@ -17,7 +17,7 @@ const uuid = require( 'uuid/v4' ); // Config const gitRepoOwner = 'WordPress'; -const gitRepoURL = 'git@github.com:' + gitRepoOwner + '/gutenberg.git'; +const gitRepoURL = 'https://github.com/' + gitRepoOwner + '/gutenberg.git'; const svnRepoURL = 'https://plugins.svn.wordpress.org/gutenberg'; // Working Directories @@ -95,6 +95,7 @@ function runShellScript( script, cwd ) { env: { NO_CHECKS: true, PATH: process.env.PATH, + HOME: process.env.HOME, }, stdio: [ 'inherit', 'ignore', 'inherit' ], } ); diff --git a/bin/get-vendor-scripts.php b/bin/get-vendor-scripts.php index 442e77b0eb435..e7295f556b4cb 100755 --- a/bin/get-vendor-scripts.php +++ b/bin/get-vendor-scripts.php @@ -32,4 +32,13 @@ function wp_add_inline_script() {} require_once dirname( dirname( __FILE__ ) ) . '/lib/client-assets.php'; -gutenberg_register_vendor_scripts(); +/** + * Hi, phpcs + */ +function run_gutenberg_register_vendor_scripts() { + global $wp_scripts; + + gutenberg_register_vendor_scripts( $wp_scripts ); +} + +run_gutenberg_register_vendor_scripts(); diff --git a/docs/designers-developers/developers/block-api/block-registration.md b/docs/designers-developers/developers/block-api/block-registration.md index 6cc028ab8c94f..217bbd27608ac 100644 --- a/docs/designers-developers/developers/block-api/block-registration.md +++ b/docs/designers-developers/developers/block-api/block-registration.md @@ -1,6 +1,6 @@ # Block Registration -## `register_block_type` +## `registerBlockType` * **Type:** `Function` diff --git a/docs/designers-developers/developers/themes/theme-support.md b/docs/designers-developers/developers/themes/theme-support.md index 210072f5d2cf0..62d650eb5aa47 100644 --- a/docs/designers-developers/developers/themes/theme-support.md +++ b/docs/designers-developers/developers/themes/theme-support.md @@ -134,6 +134,46 @@ Themes are responsible for creating the classes that apply the colors in differe The class name is built appending 'has-', followed by the class name _using_ kebab case and ending with the context name. +### Block Gradient Presents + +Different blocks have the possibility of selecting from a list of predined of gradients. The block editor provides a default gradient presets, but a theme can overwrite them and provide its own: + +```php +add_theme_support( + '__experimental-editor-gradient-presets', + array( + array( + 'name' => __( 'Vivid cyan blue to vivid purple', 'themeLangDomain' ), + 'gradient' => 'linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%)', + 'slug' => 'vivid-cyan-blue-to-vivid-purple' + ), + array( + 'name' => __( 'Vivid green cyan to vivid cyan blue', 'themeLangDomain' ), + 'gradient' => 'linear-gradient(135deg,rgba(0,208,132,1) 0%,rgba(6,147,227,1) 100%)', + 'slug' => 'vivid-green-cyan-to-vivid-cyan-blue', + ), + array( + 'name' => __( 'Light green cyan to vivid green cyan', 'themeLangDomain' ), + 'gradient' => 'linear-gradient(135deg,rgb(122,220,180) 0%,rgb(0,208,130) 100%)', + 'slug' => 'light-green-cyan-to-vivid-green-cyan', + ), + array( + 'name' => __( 'Luminous vivid amber to luminous vivid orange', 'themeLangDomain' ), + 'gradient' => 'linear-gradient(135deg,rgba(252,185,0,1) 0%,rgba(255,105,0,1) 100%)', + 'slug' => 'luminous-vivid-amber-to-luminous-vivid-orange', + ), + array( + 'name' => __( 'Luminous vivid orange to vivid red', 'themeLangDomain' ), + 'gradient' => 'linear-gradient(135deg,rgba(255,105,0,1) 0%,rgb(207,46,46) 100%)', + 'slug' => 'luminous-vivid-orange-to-vivid-red', + ), + ) +); +``` + +`name` is a human-readable label (demonstrated above) that appears in the tooltip and provides a meaningful description of the gradient to users. It is especially important for those who rely on screen readers or would otherwise have difficulty perceiving the color. `gradient` is a CSS value of a gradient applied to a background-image of the block. Details of valid gradient types can be found in the [mozilla documentation](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Images/Using_CSS_gradients). `slug` is a unique identifier for the gradient and is used to generate the CSS classes used by the block editor. + + ### Block Font Sizes: Blocks may allow the user to configure the font sizes they use, e.g., the paragraph block. The block provides a default set of font sizes, but a theme can overwrite it and provide its own: diff --git a/gutenberg.php b/gutenberg.php index 9e80dee2f6a1a..76bf483c8f74b 100644 --- a/gutenberg.php +++ b/gutenberg.php @@ -3,7 +3,7 @@ * Plugin Name: Gutenberg * Plugin URI: https://github.com/WordPress/gutenberg * Description: Printing since 1440. This is the development plugin for the new block editor in core. - * Version: 6.8.0-rc.1 + * Version: 6.8.0 * Author: Gutenberg Team * Text Domain: gutenberg * diff --git a/lib/block-directory.php b/lib/block-directory.php new file mode 100644 index 0000000000000..723db66de2b3c --- /dev/null +++ b/lib/block-directory.php @@ -0,0 +1,21 @@ + instead of in the
. * Default 'false'. */ -function gutenberg_override_script( $handle, $src, $deps = array(), $ver = false, $in_footer = false ) { - global $wp_scripts; - - $script = $wp_scripts->query( $handle, 'registered' ); +function gutenberg_override_script( &$scripts, $handle, $src, $deps = array(), $ver = false, $in_footer = false ) { + $script = $scripts->query( $handle, 'registered' ); if ( $script ) { /* * In many ways, this is a reimplementation of `wp_register_script` but @@ -67,6 +66,7 @@ function gutenberg_override_script( $handle, $src, $deps = array(), $ver = false $script->src = $src; $script->deps = $deps; $script->ver = $ver; + $script->args = $in_footer; /* * The script's `group` designation is an indication of whether it is @@ -81,7 +81,7 @@ function gutenberg_override_script( $handle, $src, $deps = array(), $ver = false $script->add_data( 'group', 1 ); } } else { - wp_register_script( $handle, $src, $deps, $ver, $in_footer ); + $scripts->add( $handle, $src, $deps, $ver, $in_footer ); } /* @@ -93,7 +93,7 @@ function gutenberg_override_script( $handle, $src, $deps = array(), $ver = false * See: https://core.trac.wordpress.org/ticket/46089 */ if ( 'wp-i18n' !== $handle && 'wp-polyfill' !== $handle ) { - wp_set_script_translations( $handle, 'default' ); + $scripts->set_translations( $handle, 'default' ); } } @@ -155,6 +155,7 @@ function gutenberg_override_translation_file( $file, $handle ) { * * @since 4.1.0 * + * @param WP_Styles $styles WP_Styles instance (passed by reference). * @param string $handle Name of the stylesheet. Should be unique. * @param string $src Full URL of the stylesheet, or path of the stylesheet relative to the WordPress root directory. * @param array $deps Optional. An array of registered stylesheet handles this stylesheet depends on. Default empty array. @@ -166,18 +167,69 @@ function gutenberg_override_translation_file( $file, $handle ) { * Default 'all'. Accepts media types like 'all', 'print' and 'screen', or media queries like * '(orientation: portrait)' and '(max-width: 640px)'. */ -function gutenberg_override_style( $handle, $src, $deps = array(), $ver = false, $media = 'all' ) { - wp_deregister_style( $handle ); - wp_register_style( $handle, $src, $deps, $ver, $media ); +function gutenberg_override_style( &$styles, $handle, $src, $deps = array(), $ver = false, $media = 'all' ) { + $style = $styles->query( $handle, 'registered' ); + if ( $style ) { + $styles->remove( $handle ); + } + $styles->add( $handle, $src, $deps, $ver, $media ); } +/** + * Registers vendor JavaScript files to be used as dependencies of the editor + * and plugins. + * + * This function is called from a script during the plugin build process, so it + * should not call any WordPress PHP functions. + * + * @since 0.1.0 + * + * @param WP_Scripts $scripts WP_Scripts instance (passed by reference). + */ +function gutenberg_register_vendor_scripts( &$scripts ) { + $suffix = SCRIPT_DEBUG ? '' : '.min'; + + // Vendor Scripts. + $react_suffix = ( SCRIPT_DEBUG ? '.development' : '.production' ) . $suffix; + + // TODO: Overrides for react, react-dom and lodash are necessary + // until WordPress 5.3 is released. + gutenberg_register_vendor_script( + $scripts, + 'react', + 'https://unpkg.com/react@16.9.0/umd/react' . $react_suffix . '.js', + array( 'wp-polyfill' ), + '16.9.0', + true + ); + gutenberg_register_vendor_script( + $scripts, + 'react-dom', + 'https://unpkg.com/react-dom@16.9.0/umd/react-dom' . $react_suffix . '.js', + array( 'react' ), + '16.9.0', + true + ); + gutenberg_register_vendor_script( + $scripts, + 'lodash', + 'https://unpkg.com/lodash@4.17.15/lodash' . $suffix . '.js', + array(), + '4.17.15', + true + ); +} +add_action( 'wp_default_scripts', 'gutenberg_register_vendor_scripts' ); + /** * Registers all the WordPress packages scripts that are in the standardized * `build/` location. * * @since 4.5.0 + * + * @param WP_Scripts $scripts WP_Scripts instance (passed by reference). */ -function gutenberg_register_packages_scripts() { +function gutenberg_register_packages_scripts( &$scripts ) { foreach ( glob( gutenberg_dir_path() . 'build/*/index.js' ) as $path ) { // Prefix `wp-` to package directory to get script handle. // For example, `…/build/a11y/index.js` becomes `wp-a11y`. @@ -206,6 +258,7 @@ function gutenberg_register_packages_scripts() { $gutenberg_path = substr( $path, strlen( gutenberg_dir_path() ) ); gutenberg_override_script( + $scripts, $handle, gutenberg_url( $gutenberg_path ), $dependencies, @@ -214,117 +267,74 @@ function gutenberg_register_packages_scripts() { ); } } +add_action( 'wp_default_scripts', 'gutenberg_register_packages_scripts' ); /** - * Registers common scripts and styles to be used as dependencies of the editor - * and plugins. + * Registers all the WordPress packages styles that are in the standardized + * `build/` location. * - * @since 0.1.0 - */ -function gutenberg_register_scripts_and_styles() { - global $wp_scripts; - - gutenberg_register_vendor_scripts(); - gutenberg_register_packages_scripts(); - - // Add nonce middleware which accounts for the absence of the heartbeat - // listener. This relies on API Fetch implementation running middlewares in - // order of last added, and that the original nonce middleware would defer - // to an X-WP-Nonce header already being present. This inline script should - // be removed once the following Core ticket is resolved in assigning the - // nonce received from heartbeat to the created middleware. - // - // See: https://core.trac.wordpress.org/ticket/46107 . - // See: https://github.com/WordPress/gutenberg/pull/13451 . - if ( isset( $wp_scripts->registered['wp-api-fetch'] ) ) { - $wp_scripts->registered['wp-api-fetch']->deps[] = 'wp-hooks'; - } - wp_add_inline_script( - 'wp-api-fetch', - sprintf( - 'wp.apiFetch.nonceMiddleware = wp.apiFetch.createNonceMiddleware( "%s" );' . - 'wp.apiFetch.use( wp.apiFetch.nonceMiddleware );' . - 'wp.apiFetch.nonceEndpoint = "%s";' . - 'wp.apiFetch.use( wp.apiFetch.mediaUploadMiddleware );', - ( wp_installing() && ! is_multisite() ) ? '' : wp_create_nonce( 'wp_rest' ), - admin_url( 'admin-ajax.php?action=gutenberg_rest_nonce' ) - ), - 'after' - ); - - // TEMPORARY: Core does not (yet) provide persistence migration from the - // introduction of the block editor and still calls the data plugins. - // We unset the existing inline scripts first. - $wp_scripts->registered['wp-data']->extra['after'] = array(); - wp_add_inline_script( - 'wp-data', - implode( - "\n", - array( - '( function() {', - ' var userId = ' . get_current_user_ID() . ';', - ' var storageKey = "WP_DATA_USER_" + userId;', - ' wp.data', - ' .use( wp.data.plugins.persistence, { storageKey: storageKey } );', - ' wp.data.plugins.persistence.__unstableMigrate( { storageKey: storageKey } );', - '} )();', - ) - ) - ); + * @since 6.7.0 + * @param WP_Styles $styles WP_Styles instance (passed by reference). + */ +function gutenberg_register_packages_styles( &$styles ) { // Editor Styles. - // This empty stylesheet is defined to ensure backward compatibility. - gutenberg_override_style( 'wp-blocks', false ); - gutenberg_override_style( + $styles, 'wp-block-editor', gutenberg_url( 'build/block-editor/style.css' ), array( 'wp-components', 'wp-editor-font' ), filemtime( gutenberg_dir_path() . 'build/editor/style.css' ) ); - wp_style_add_data( 'wp-block-editor', 'rtl', 'replace' ); + $styles->add_data( 'wp-block-editor', 'rtl', 'replace' ); gutenberg_override_style( + $styles, 'wp-editor', gutenberg_url( 'build/editor/style.css' ), - array( 'wp-components', 'wp-block-editor', 'wp-nux', 'wp-block-directory' ), + array( 'wp-components', 'wp-block-editor', 'wp-nux' ), filemtime( gutenberg_dir_path() . 'build/editor/style.css' ) ); - wp_style_add_data( 'wp-editor', 'rtl', 'replace' ); + $styles->add_data( 'wp-editor', 'rtl', 'replace' ); gutenberg_override_style( + $styles, 'wp-edit-post', gutenberg_url( 'build/edit-post/style.css' ), array( 'wp-components', 'wp-block-editor', 'wp-editor', 'wp-edit-blocks', 'wp-block-library', 'wp-nux' ), filemtime( gutenberg_dir_path() . 'build/edit-post/style.css' ) ); - wp_style_add_data( 'wp-edit-post', 'rtl', 'replace' ); + $styles->add_data( 'wp-edit-post', 'rtl', 'replace' ); gutenberg_override_style( + $styles, 'wp-components', gutenberg_url( 'build/components/style.css' ), array(), filemtime( gutenberg_dir_path() . 'build/components/style.css' ) ); - wp_style_add_data( 'wp-components', 'rtl', 'replace' ); + $styles->add_data( 'wp-components', 'rtl', 'replace' ); gutenberg_override_style( + $styles, 'wp-block-library', gutenberg_url( 'build/block-library/style.css' ), array(), filemtime( gutenberg_dir_path() . 'build/block-library/style.css' ) ); - wp_style_add_data( 'wp-block-library', 'rtl', 'replace' ); + $styles->add_data( 'wp-block-library', 'rtl', 'replace' ); gutenberg_override_style( + $styles, 'wp-format-library', gutenberg_url( 'build/format-library/style.css' ), array( 'wp-block-editor', 'wp-components' ), filemtime( gutenberg_dir_path() . 'build/format-library/style.css' ) ); - wp_style_add_data( 'wp-format-library', 'rtl', 'replace' ); + $styles->add_data( 'wp-format-library', 'rtl', 'replace' ); gutenberg_override_style( + $styles, 'wp-edit-blocks', gutenberg_url( 'build/block-library/editor.css' ), array( @@ -336,92 +346,107 @@ function gutenberg_register_scripts_and_styles() { ), filemtime( gutenberg_dir_path() . 'build/block-library/editor.css' ) ); - wp_style_add_data( 'wp-edit-blocks', 'rtl', 'replace' ); + $styles->add_data( 'wp-edit-blocks', 'rtl', 'replace' ); gutenberg_override_style( + $styles, 'wp-nux', gutenberg_url( 'build/nux/style.css' ), array( 'wp-components' ), filemtime( gutenberg_dir_path() . 'build/nux/style.css' ) ); - wp_style_add_data( 'wp-nux', 'rtl', 'replace' ); + $styles->add_data( 'wp-nux', 'rtl', 'replace' ); gutenberg_override_style( + $styles, 'wp-block-library-theme', gutenberg_url( 'build/block-library/theme.css' ), array(), filemtime( gutenberg_dir_path() . 'build/block-library/theme.css' ) ); - wp_style_add_data( 'wp-block-library-theme', 'rtl', 'replace' ); + $styles->add_data( 'wp-block-library-theme', 'rtl', 'replace' ); gutenberg_override_style( + $styles, 'wp-list-reusable-blocks', gutenberg_url( 'build/list-reusable-blocks/style.css' ), array( 'wp-components' ), filemtime( gutenberg_dir_path() . 'build/list-reusable-blocks/style.css' ) ); - wp_style_add_data( 'wp-list-reusable-block', 'rtl', 'replace' ); + $styles->add_data( 'wp-list-reusable-block', 'rtl', 'replace' ); gutenberg_override_style( + $styles, 'wp-edit-widgets', gutenberg_url( 'build/edit-widgets/style.css' ), array( 'wp-components', 'wp-block-editor', 'wp-edit-blocks' ), filemtime( gutenberg_dir_path() . 'build/edit-widgets/style.css' ) ); - wp_style_add_data( 'wp-edit-widgets', 'rtl', 'replace' ); + $styles->add_data( 'wp-edit-widgets', 'rtl', 'replace' ); gutenberg_override_style( + $styles, 'wp-block-directory', gutenberg_url( 'build/block-directory/style.css' ), - array( 'wp-components' ), + array( 'wp-block-editor', 'wp-components' ), filemtime( gutenberg_dir_path() . 'build/block-directory/style.css' ) ); - wp_style_add_data( 'wp-block-directory', 'rtl', 'replace' ); - - if ( defined( 'GUTENBERG_LIVE_RELOAD' ) && GUTENBERG_LIVE_RELOAD ) { - $live_reload_url = ( GUTENBERG_LIVE_RELOAD === true ) ? 'http://localhost:35729/livereload.js' : GUTENBERG_LIVE_RELOAD; - - wp_enqueue_script( - 'gutenberg-live-reload', - $live_reload_url - ); - } + $styles->add_data( 'wp-block-directory', 'rtl', 'replace' ); } -add_action( 'wp_enqueue_scripts', 'gutenberg_register_scripts_and_styles', 5 ); -add_action( 'admin_enqueue_scripts', 'gutenberg_register_scripts_and_styles', 5 ); +add_action( 'wp_default_styles', 'gutenberg_register_packages_styles' ); /** - * Registers vendor JavaScript files to be used as dependencies of the editor + * Registers common scripts and styles to be used as dependencies of the editor * and plugins. * - * This function is called from a script during the plugin build process, so it - * should not call any WordPress PHP functions. - * * @since 0.1.0 */ -function gutenberg_register_vendor_scripts() { - $suffix = SCRIPT_DEBUG ? '' : '.min'; - - // Vendor Scripts. - $react_suffix = ( SCRIPT_DEBUG ? '.development' : '.production' ) . $suffix; +function gutenberg_enqueue_block_editor_assets() { + global $wp_scripts; - // TODO: Overrides for react, react-dom and lodash are necessary - // until WordPress 5.3 is released. - gutenberg_register_vendor_script( - 'react', - 'https://unpkg.com/react@16.9.0/umd/react' . $react_suffix . '.js', - array( 'wp-polyfill' ) - ); - gutenberg_register_vendor_script( - 'react-dom', - 'https://unpkg.com/react-dom@16.9.0/umd/react-dom' . $react_suffix . '.js', - array( 'react' ) + wp_add_inline_script( + 'wp-api-fetch', + sprintf( + 'wp.apiFetch.nonceMiddleware = wp.apiFetch.createNonceMiddleware( "%s" );' . + 'wp.apiFetch.use( wp.apiFetch.nonceMiddleware );' . + 'wp.apiFetch.nonceEndpoint = "%s";' . + 'wp.apiFetch.use( wp.apiFetch.mediaUploadMiddleware );', + ( wp_installing() && ! is_multisite() ) ? '' : wp_create_nonce( 'wp_rest' ), + admin_url( 'admin-ajax.php?action=gutenberg_rest_nonce' ) + ), + 'after' ); - gutenberg_register_vendor_script( - 'lodash', - 'https://unpkg.com/lodash@4.17.15/lodash' . $suffix . '.js' + + // TEMPORARY: Core does not (yet) provide persistence migration from the + // introduction of the block editor and still calls the data plugins. + // We unset the existing inline scripts first. + $wp_scripts->registered['wp-data']->extra['after'] = array(); + wp_add_inline_script( + 'wp-data', + implode( + "\n", + array( + '( function() {', + ' var userId = ' . get_current_user_ID() . ';', + ' var storageKey = "WP_DATA_USER_" + userId;', + ' wp.data', + ' .use( wp.data.plugins.persistence, { storageKey: storageKey } );', + ' wp.data.plugins.persistence.__unstableMigrate( { storageKey: storageKey } );', + '} )();', + ) + ) ); + + if ( defined( 'GUTENBERG_LIVE_RELOAD' ) && GUTENBERG_LIVE_RELOAD ) { + $live_reload_url = ( GUTENBERG_LIVE_RELOAD === true ) ? 'http://localhost:35729/livereload.js' : GUTENBERG_LIVE_RELOAD; + + wp_enqueue_script( + 'gutenberg-live-reload', + $live_reload_url + ); + } } +add_action( 'enqueue_block_editor_assets', 'gutenberg_enqueue_block_editor_assets' ); /** * Retrieves a unique and reasonably short and human-friendly filename for a @@ -459,14 +484,21 @@ function gutenberg_vendor_script_filename( $handle, $src ) { * possible, or downloading it if the cached version is unavailable or * outdated. * - * @param string $handle Name of the script. - * @param string $src Full URL of the external script. - * @param array $deps Optional. An array of registered script handles this - * script depends on. + * @param WP_Scripts $scripts WP_Scripts instance (passed by reference). + * @param string $handle Name of the script. + * @param string $src Full URL of the external script. + * @param array $deps Optional. An array of registered script handles this + * script depends on. + * @param string|bool|null $ver Optional. String specifying script version number, if it has one, which is added to the URL + * as a query string for cache busting purposes. If version is set to false, a version + * number is automatically added equal to current installed WordPress version. + * If set to null, no version is added. + * @param bool $in_footer Optional. Whether to enqueue the script before instead of in the . + * Default 'false'. * * @since 0.1.0 */ -function gutenberg_register_vendor_script( $handle, $src, $deps = array() ) { +function gutenberg_register_vendor_script( &$scripts, $handle, $src, $deps = array(), $ver = null, $in_footer = false ) { if ( defined( 'GUTENBERG_LOAD_VENDOR_SCRIPTS' ) && ! GUTENBERG_LOAD_VENDOR_SCRIPTS ) { return; } @@ -496,7 +528,7 @@ function gutenberg_register_vendor_script( $handle, $src, $deps = array() ) { if ( ! $f ) { // Failed to open the file for writing, probably due to server // permissions. Enqueue the script directly from the URL instead. - gutenberg_override_script( $handle, $src, $deps, null ); + gutenberg_override_script( $scripts, $handle, $src, $deps, $ver, $in_footer ); return; } fclose( $f ); @@ -509,16 +541,18 @@ function gutenberg_register_vendor_script( $handle, $src, $deps = array() ) { // The request failed. If the file is already cached, continue to // use this file. If not, then unlink the 0 byte file, and enqueue // the script directly from the URL. - gutenberg_override_script( $handle, $src, $deps, null ); + gutenberg_override_script( $scripts, $handle, $src, $deps, $ver, $in_footer ); unlink( $full_path ); return; } } gutenberg_override_script( + $scripts, $handle, gutenberg_url( 'vendor/' . $filename ), $deps, - null + $ver, + $in_footer ); } diff --git a/lib/customizer.php b/lib/customizer.php index 771ced523f5c9..1f27db00ee308 100644 --- a/lib/customizer.php +++ b/lib/customizer.php @@ -55,7 +55,7 @@ function gutenberg_customize_register( $wp_customize ) { 'sanitize_callback' => 'gutenberg_customize_sanitize', ) ); - if ( get_option( 'gutenberg-experiments' ) && array_key_exists( 'gutenberg-widget-experiments', get_option( 'gutenberg-experiments' ) ) ) { + if ( gutenberg_is_experiment_enabled( 'gutenberg-widget-experiments' ) ) { $wp_customize->add_section( 'gutenberg_widget_blocks', array( 'title' => __( 'Widget Blocks (Experimental)', 'gutenberg' ) ) diff --git a/lib/experiments-page.php b/lib/experiments-page.php index bbc04650a732e..f88fcca5c1611 100644 --- a/lib/experiments-page.php +++ b/lib/experiments-page.php @@ -130,14 +130,19 @@ function gutenberg_display_experiment_section() { * @return array Filtered editor settings. */ function gutenberg_experiments_editor_settings( $settings ) { - $experiments_exist = get_option( 'gutenberg-experiments' ); $experiments_settings = array( - '__experimentalEnableLegacyWidgetBlock' => $experiments_exist ? array_key_exists( 'gutenberg-widget-experiments', get_option( 'gutenberg-experiments' ) ) : false, - '__experimentalEnableMenuBlock' => $experiments_exist ? array_key_exists( 'gutenberg-menu-block', get_option( 'gutenberg-experiments' ) ) : false, - '__experimentalBlockDirectory' => $experiments_exist ? array_key_exists( 'gutenberg-block-directory', get_option( 'gutenberg-experiments' ) ) : false, - '__experimentalEnableFullSiteEditing' => $experiments_exist ? array_key_exists( 'gutenberg-full-site-editing', get_option( 'gutenberg-experiments' ) ) : false, + '__experimentalEnableLegacyWidgetBlock' => gutenberg_is_experiment_enabled( 'gutenberg-widget-experiments' ), + '__experimentalEnableMenuBlock' => gutenberg_is_experiment_enabled( 'gutenberg-menu-block' ), + '__experimentalBlockDirectory' => gutenberg_is_experiment_enabled( 'gutenberg-block-directory' ), + '__experimentalEnableFullSiteEditing' => gutenberg_is_experiment_enabled( 'gutenberg-full-site-editing' ), ); + + $gradient_presets = current( (array) get_theme_support( '__experimental-editor-gradient-presets' ) ); + if ( false !== $gradient_presets ) { + $experiments_settings['gradients'] = $gradient_presets; + } + return array_merge( $settings, $experiments_settings ); } add_filter( 'block_editor_settings', 'gutenberg_experiments_editor_settings' ); diff --git a/lib/load.php b/lib/load.php index 35b49b2ead5b9..58e545b38a6f7 100644 --- a/lib/load.php +++ b/lib/load.php @@ -9,6 +9,20 @@ die( 'Silence is golden.' ); } +/** + * Checks whether the Gutenberg experiment is enabled. + * + * @since 6.7.0 + * + * @param string $name The name of the experiment. + * + * @return bool True when the experiment is enabled. + */ +function gutenberg_is_experiment_enabled( $name ) { + $experiments = get_option( 'gutenberg-experiments' ); + return ! empty( $experiments[ $name ] ); +} + // These files only need to be loaded if within a rest server instance // which this class will exist if that is the case. if ( class_exists( 'WP_REST_Controller' ) ) { @@ -22,13 +36,12 @@ require dirname( __FILE__ ) . '/class-experimental-wp-widget-blocks-manager.php'; require dirname( __FILE__ ) . '/class-wp-rest-widget-areas-controller.php'; } - /** - * End: Include for phase 2 - */ - if ( ! class_exists( 'WP_REST_Block_Directory_Controller' ) ) { require dirname( __FILE__ ) . '/class-wp-rest-block-directory-controller.php'; } + /** + * End: Include for phase 2 + */ require dirname( __FILE__ ) . '/rest-api.php'; } @@ -43,6 +56,7 @@ require dirname( __FILE__ ) . '/templates.php'; require dirname( __FILE__ ) . '/template-loader.php'; require dirname( __FILE__ ) . '/client-assets.php'; +require dirname( __FILE__ ) . '/block-directory.php'; require dirname( __FILE__ ) . '/demo.php'; require dirname( __FILE__ ) . '/widgets.php'; require dirname( __FILE__ ) . '/widgets-page.php'; diff --git a/lib/rest-api.php b/lib/rest-api.php index 5aa85b6d83e48..6ad5e6d0e6f0e 100644 --- a/lib/rest-api.php +++ b/lib/rest-api.php @@ -85,6 +85,10 @@ function gutenberg_register_rest_widget_areas() { * @since 6.5.0 */ function gutenberg_register_rest_block_directory() { + if ( ! gutenberg_is_experiment_enabled( 'gutenberg-block-directory' ) ) { + return; + } + $block_directory_controller = new WP_REST_Block_Directory_Controller(); $block_directory_controller->register_routes(); } diff --git a/lib/template-loader.php b/lib/template-loader.php index 1c6923091ce32..30ea5fae54f8e 100644 --- a/lib/template-loader.php +++ b/lib/template-loader.php @@ -80,7 +80,7 @@ function gutenberg_override_query_template( $template, $type, array $templates = * @return string Path to the canvas file to include. */ function gutenberg_find_template( $template_file ) { - global $_wp_current_template_post, $_wp_current_template_hierarchy; + global $_wp_current_template_content, $_wp_current_template_hierarchy; // Bail if no relevant template hierarchy was determined, or if the template file // was overridden another way. @@ -105,8 +105,56 @@ function gutenberg_find_template( $template_file ) { ); if ( $template_query->have_posts() ) { - $template_posts = $template_query->get_posts(); - $_wp_current_template_post = array_shift( $template_posts ); + $template_posts = $template_query->get_posts(); + $current_template_post = array_shift( $template_posts ); + + // Build map of template slugs to their priority in the current hierarchy. + $slug_priorities = array_flip( $slugs ); + + // See if there is a theme block template with higher priority than the resolved template post. + $higher_priority_block_template_path = null; + $higher_priority_block_template_priority = PHP_INT_MAX; + $block_template_files = glob( get_stylesheet_directory() . '/block-templates/*.html', 1 ); + if ( is_child_theme() ) { + $block_template_files = array_merge( $block_template_files, glob( get_template_directory() . '/block-templates/*.html', 1 ) ); + } + foreach ( $block_template_files as $path ) { + $theme_block_template_priority = $slug_priorities[ basename( $path, '.html' ) ]; + if ( + isset( $theme_block_template_priority ) && + $theme_block_template_priority < $higher_priority_block_template_priority && + $theme_block_template_priority < $slug_priorities[ $current_template_post->post_name ] + ) { + $higher_priority_block_template_path = $path; + $higher_priority_block_template_priority = $theme_block_template_priority; + } + } + + // If there is, use it instead. + if ( isset( $higher_priority_block_template_path ) ) { + $post_name = basename( $path, '.html' ); + $current_template_post = array( + 'post_content' => file_get_contents( $higher_priority_block_template_path ), + 'post_title' => ucfirst( $post_name ), + 'post_status' => 'auto-draft', + 'post_type' => 'wp_template', + 'post_name' => $post_name, + ); + if ( is_admin() ) { + // Only create auto-draft of block template for editing + // in admin screens, similarly to how we do it for new + // posts in the editor. + $current_template_post = get_post( + wp_insert_post( $current_template_post ) + ); + } else { + $current_template_post = new WP_Post( + (object) $current_template_post + ); + } + } + + $_wp_current_template_content = $current_template_post->post_content; } // Add extra hooks for template canvas. @@ -131,17 +179,15 @@ function gutenberg_render_title_tag() { * Renders the markup for the current template. */ function gutenberg_render_the_template() { - global $_wp_current_template_post; + global $_wp_current_template_content; global $wp_embed; - if ( ! $_wp_current_template_post || 'wp_template' !== $_wp_current_template_post->post_type ) { + if ( ! $_wp_current_template_content ) { echo '+ { __( 'Currently selected' ) }: +
+