Make WordPress Core

Opened 2 years ago

Closed 2 years ago

#45893 closed defect (bug) (maybelater)

tinyMCEPreInit.load_ext() isn't called for TinyMCE external plugins in block editor

Reported by: danielbachhuber Owned by:
Milestone: Priority: normal
Severity: normal Version: 5.0
Component: Editor Keywords:
Focuses: Cc:


In the Classic Editor, a TinyMCE plugin registered with the mce_external_plugins filter will be loaded with the following:

<script type='text/javascript' src='http://tastyrecipes.test/wp-includes/js/tinymce/langs/wp-langs-en.js?ver=4800-20180716'></script>
<script type="text/javascript">

tinyMCEPreInit.load_ext("http://tastyrecipes.test/wp-content/plugins/tasty-links/assets/js", "en");

( function() {
	var init, id, $wrap;

This is generated in WP_Editor:

The block editor's wp_tinymce_inline_scripts() doesn't perform the same, which means TinyMCE external plugins aren't executed for editor instances on the page (only the Classic Block instances).

I'm not sure whether this was intentional or unintentional, or even what the expected behavior is!

Change History (1)

#1 @danielbachhuber
2 years ago

  • Keywords dev-feedback removed
  • Milestone Future Release deleted
  • Resolution set to maybelater
  • Status changed from new to closed

After much struggle, I managed to track down the problem:

  1. Our specific plugin calls wp_editor( '', 'tasty-recipes-editor', array( 'teeny' => true ) );. This instance isn't ever rendered. Rather, we then steal tinyMCEPreInit.mceInit['tasty-recipes-editor'] when we call tinyMCE.init() for our dynamic text fields.
  2. In the Classic Editor, TinyMCE is initialized via WP_Editor->editor_js(). However, TinyMCE is initialized in Gutenberg with print_default_editor_scripts(). The former makes the tinyMCEPreInit.load_ext() call while the latter does not.
  3. Gutenberg doesn't initialize external plugins globally on preinit, only when the Classic Block TinyMCE is initialized.

I was able to work around this by filtering TeenyMCE init and always including our external plugin:

add_filter( 'teeny_mce_before_init', function( $settings, $editor_id ) {
	if ( 'tasty-recipes-editor' !== $editor_id ) {
		return $settings;
	$external_plugins = array();
	if ( isset( $settings['external_plugins'] ) ) {
		if ( is_string( $settings['external_plugins'] ) ) {
			$external_plugins = json_decode( $settings['external_plugins'], true ) ? : array();
		} elseif ( is_array( $settings['external_plugins'] ) ) {
			$external_plugins = $settings['external_plugins'];
	$assets_path                    = dirname( dirname( __FILE__ ) ) . '/assets';
	$assets_url                     = plugins_url( 'assets', __DIR__ );
	$filepath                       = '/js/tinymce-plugin.js';
	$mtime                          = filemtime( $assets_path . $filepath );
	$external_plugins['tastylinks'] = $assets_url . $filepath . '?v=' . (int) $mtime;
	$settings['external_plugins']   = $external_plugins;
	return $settings;
}, 10, 2 );

Closing this as maybelater as I don't think it's worth spending time fixing.

Note: See TracTickets for help on using tickets.