Skip to content

Commit

Permalink
Try: Aggressive TinyMCE deprecation (#50387)
Browse files Browse the repository at this point in the history
* Add experiment setting field

* Set a global when experiment enabled

* Load Classic block only when experiment is not enabled

* Do not enqueue any TinyMCE assets if experiment is enabled

* Do not enqueue editor if experiment enabled

* Set and utilize a cookie when tinymce is requested

* Safeer cookie access on the server side

* Add a script to force TinyMCE usage for testing

* Move experiment toggle to the higheest priority

* Add PHP comments and fix coding standards

* Rename class file

* More CS

* Use gutenberg_is_experiment_enabled()

* Cleanup lines from rebase

* Backend detection of classic block instances

* Comment the cookie testing code again

* Fix code style

* Consider the freeform block, or any raw HTML to be Unknown block

* Proper post object existence testing

* Register classic block if server declares it's needed

* A custom message when converting from classic block

* Improve content length check

`empty()` will return `true` if we pass the '0' string.

* Expand comment on classic block registration

* Move example TinyMCE usage code up

* Use a query argument instead of a cookie

* Rename proxy trap

* Fix the comment

* Rename another function

* Improve the classic block load conditions comment

* Further polish the conditions comment

* Fix a fatal in the wp-admin dashboard
  • Loading branch information
tyxla authored Jul 3, 2023
1 parent a9ce107 commit b819f63
Show file tree
Hide file tree
Showing 9 changed files with 203 additions and 14 deletions.
8 changes: 7 additions & 1 deletion lib/client-assets.php
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,13 @@ function gutenberg_register_packages_scripts( $scripts ) {
// Add dependencies that cannot be detected and generated by build tools.
switch ( $handle ) {
case 'wp-block-library':
array_push( $dependencies, 'editor' );
if (
! gutenberg_is_experiment_enabled( 'gutenberg-no-tinymce' ) ||
! empty( $_GET['requiresTinymce'] ) ||
gutenberg_post_being_edited_requires_classic_block()
) {
array_push( $dependencies, 'editor' );
}
break;

case 'wp-edit-post':
Expand Down
14 changes: 14 additions & 0 deletions lib/experimental/assets/tinymce-proxy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
async function reloadWithTinymce() {
const currentUrl = new URL( window.location.href );
currentUrl.searchParams.set( 'requiresTinymce', '1' );
window.location.href = currentUrl;
}

window.tinymce = new Proxy(
{},
{
get: reloadWithTinymce,
set: reloadWithTinymce,
apply: reloadWithTinymce,
}
);
27 changes: 27 additions & 0 deletions lib/experimental/class--wp-editors.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php
/**
* Contains the placeholder class to replace the default `_WP_Editors`.
*
* @package gutenberg
* @since 6.3.0
*/

// phpcs:disable PEAR.NamingConventions.ValidClassName.StartWithCapital

/**
* Placeholder class.
* Used to disable loading of TinyMCE assets.
*
* @access public
*/
final class _WP_Editors {
/**
* Necessary to ensure no additional TinyMCE assets are enqueued.
*/
public static function enqueue_default_editor() {}

/**
* Necessary for wp admin dashboard.
*/
public static function editor() {}
}
86 changes: 86 additions & 0 deletions lib/experimental/disable-tinymce.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<?php
/**
* Experiment to disable TinyMCE and the Classic block.
*
* @package gutenberg
*/

// add_action( 'admin_footer', 'gutenberg_test_tinymce_access' ); // Uncomment the following line to force an external TinyMCE usage.

/**
* Render a variable that we'll use to declare that the editor will need the classic block.
*/
function gutenberg_declare_classic_block_necessary() {
if ( ! gutenberg_post_being_edited_requires_classic_block() ) {
return;
}
echo '<script type="text/javascript">window.wp.needsClassicBlock = true;</script>';
}
add_action( 'admin_footer', 'gutenberg_declare_classic_block_necessary' );

// If user has already requested TinyMCE, we're ending the experiment.
if ( ! empty( $_GET['requiresTinymce'] ) || gutenberg_post_being_edited_requires_classic_block() ) {
return;
}


/**
* Disable TinyMCE by introducing a placeholder `_WP_Editors` class.
*/
function gutenberg_disable_tinymce() {
require __DIR__ . '/class--wp-editors.php';
}

add_action( 'admin_init', 'gutenberg_disable_tinymce' );

/**
* Enqueue TinyMCE proxy script.
* Detects TinyMCE usage and sets the `requiresTinymce` query argument to stop disabling TinyMCE loading.
*/
function gutenberg_enqueue_tinymce_proxy() {
wp_enqueue_script( 'gutenberg-tinymce-proxy', plugins_url( 'assets/tinymce-proxy.js', __FILE__ ) );
}

add_action( 'admin_enqueue_scripts', 'gutenberg_enqueue_tinymce_proxy' );

/**
* Example TinyMCE usage used for testing.
* Uncomment line 8 in this file to enable.
*/
function gutenberg_test_tinymce_access() {
echo '<script type="text/javascript">const a = window.tinymce.$;</script>';
}

/**
* Whether the current editor contains a classic block instance.
*
* @return bool True if the editor contains a classic block, false otherwse.
*/
function gutenberg_post_being_edited_requires_classic_block() {
if ( ! is_admin() ) {
return false;
}

// Handle the post editor.
if ( ! empty( $_GET['post'] ) && ! empty( $_GET['action'] ) && 'edit' === $_GET['action'] ) {
$current_post = get_post( intval( $_GET['post'] ) );
if ( ! $current_post || is_wp_error( $current_post ) ) {
return false;
}

$content = $current_post->post_content;
}

if ( empty( $content ) ) {
return false;
}

$parsed_blocks = parse_blocks( $content );
foreach ( $parsed_blocks as $block ) {
if ( empty( $block['blockName'] ) && strlen( trim( $block['innerHTML'] ) ) > 0 ) {
return true;
}
}

return false;
}
3 changes: 3 additions & 0 deletions lib/experimental/editor-settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ function gutenberg_enable_experiments() {
wp_add_inline_script( 'wp-block-editor', 'window.__experimentalInteractivityAPI = true', 'before' );
}

if ( gutenberg_is_experiment_enabled( 'gutenberg-no-tinymce' ) ) {
wp_add_inline_script( 'wp-block-library', 'window.__experimentalDisableTinymce = true', 'before' );
}
}

add_action( 'admin_init', 'gutenberg_enable_experiments' );
12 changes: 12 additions & 0 deletions lib/experiments-page.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,18 @@ function gutenberg_initialize_experiments_settings() {
)
);

add_settings_field(
'gutenberg-no-tinymce',
__( 'Disable TinyMCE and Classic block', 'gutenberg' ),
'gutenberg_display_experiment_field',
'gutenberg-experiments',
'gutenberg_experiments_section',
array(
'label' => __( 'Disable TinyMCE and Classic block', 'gutenberg' ),
'id' => 'gutenberg-no-tinymce',
)
);

register_setting(
'gutenberg-experiments',
'gutenberg-experiments'
Expand Down
6 changes: 5 additions & 1 deletion lib/load.php
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,11 @@ function gutenberg_is_experiment_enabled( $name ) {
require __DIR__ . '/experimental/navigation-theme-opt-in.php';
require __DIR__ . '/experimental/kses.php';
require __DIR__ . '/experimental/l10n.php';

if ( gutenberg_is_experiment_enabled( 'gutenberg-no-tinymce' ) ) {
require __DIR__ . '/experimental/disable-tinymce.php';
}

if ( gutenberg_is_experiment_enabled( 'gutenberg-interactivity-api-core-blocks' ) ) {
require __DIR__ . '/experimental/interactivity-api/blocks.php';
}
Expand All @@ -123,7 +128,6 @@ function gutenberg_is_experiment_enabled( $name ) {
require __DIR__ . '/experimental/interactivity-api/directives/wp-style.php';
require __DIR__ . '/experimental/interactivity-api/directives/wp-text.php';


// Fonts API.
if ( ! class_exists( 'WP_Fonts' ) ) {
// Fonts API files.
Expand Down
19 changes: 18 additions & 1 deletion packages/block-library/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,6 @@ const getAllBlocks = () => {
buttons,
calendar,
categories,
...( window.wp && window.wp.oldEditor ? [ classic ] : [] ), // Only add the classic block in WP Context.
code,
column,
columns,
Expand Down Expand Up @@ -229,6 +228,24 @@ const getAllBlocks = () => {
queryTitle,
postAuthorBiography,
];

// When in a WordPress context, conditionally
// add the classic block and TinyMCE editor
// under any of the following conditions:
// - the current post contains a classic block
// - the experiment to disable TinyMCE isn't active.
// - a query argument specifies that TinyMCE should be loaded
if (
window?.wp?.oldEditor &&
( window?.wp?.needsClassicBlock ||
! window?.__experimentalDisableTinymce ||
!! new URLSearchParams( window?.location?.search ).get(
'requiresTinymce'
) )
) {
blocks.push( classic );
}

return blocks.filter( Boolean );
};

Expand Down
42 changes: 31 additions & 11 deletions packages/block-library/src/missing/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,34 +16,54 @@ import { safeHTML } from '@wordpress/dom';
function MissingBlockWarning( { attributes, convertToHTML, clientId } ) {
const { originalName, originalUndelimitedContent } = attributes;
const hasContent = !! originalUndelimitedContent;
const hasHTMLBlock = useSelect(
const { hasFreeformBlock, hasHTMLBlock } = useSelect(
( select ) => {
const { canInsertBlockType, getBlockRootClientId } =
select( blockEditorStore );

return canInsertBlockType(
'core/html',
getBlockRootClientId( clientId )
);
return {
hasFreeformBlock: canInsertBlockType(
'core/freeform',
getBlockRootClientId( clientId )
),
hasHTMLBlock: canInsertBlockType(
'core/html',
getBlockRootClientId( clientId )
),
};
},
[ clientId ]
);

const actions = [];
let messageHTML;
if ( hasContent && hasHTMLBlock ) {

const convertToHtmlButton = (
<Button key="convert" onClick={ convertToHTML } variant="primary">
{ __( 'Keep as HTML' ) }
</Button>
);

if ( hasContent && ! hasFreeformBlock && ! originalName ) {
if ( hasHTMLBlock ) {
messageHTML = __(
'It appears you are trying to use the deprecated Classic block. You can leave this block intact, convert its content to a Custom HTML block, or remove it entirely. Alternatively, you can refresh the page to use the Classic block.'
);
actions.push( convertToHtmlButton );
} else {
messageHTML = __(
'It appears you are trying to use the deprecated Classic block. You can leave this block intact, or remove it entirely. Alternatively, you can refresh the page to use the Classic block.'
);
}
} else if ( hasContent && hasHTMLBlock ) {
messageHTML = sprintf(
/* translators: %s: block name */
__(
'Your site doesn’t include support for the "%s" block. You can leave this block intact, convert its content to a Custom HTML block, or remove it entirely.'
),
originalName
);
actions.push(
<Button key="convert" onClick={ convertToHTML } variant="primary">
{ __( 'Keep as HTML' ) }
</Button>
);
actions.push( convertToHtmlButton );
} else {
messageHTML = sprintf(
/* translators: %s: block name */
Expand Down

1 comment on commit b819f63

@github-actions
Copy link

@github-actions github-actions bot commented on b819f63 Jul 3, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Flaky tests detected in b819f63.
Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/5443493909
📝 Reported issues:

Please sign in to comment.