Whitelisting & Blacklisting Blocks

The Gutenberg editor (slated for WordPress core release in v5.0) ships with more than 60 blocks, many of which are likely irrelevant for many projects.

The official Gutenberg documentation provides methods for whitelisting and blacklisting blocks, but at the time of writing this, those documented methods don’t work, and there are several open issues in the Gutenberg Github repo regarding this.

If you need to whitelist (or blacklist) blocks today, below is an outline of how I accomplished this.

Note, that at the time of writing this, I’m using Gutenberg v2.8, and based on how quickly Gutenberg is moving, I don’t have much confidence that this will work for future versions, so take my tips/tricks with a grain of Gutenberg salt.

tl;dr

The approach below documents how to whitelist blocks in Gutenberg. You can use this to blacklist if that’s your cup of tea as well. The gist of what needs to happen:

  • Defined a list of allowed blocks
  • Pass that list from the server to the client on page load
  • Use that list with some custom JS to remove blocks that are not whitelisted

Define the list of allowed blocks & pass to the client

Gutenberg core ships with an allowed_block_types filter, but there are several issues open related to this filter not being well respected by the Gutenberg client (#6363, #6070, #5893), so before you get burned trying to use this, we’re going to define our own list of blocks and send the list up to the client.

Here we define a filterable array, and localize that array to be passed up to the client with the custom Gutenblock JS you’re already enqueuing to interact with Gutenberg (assuming you already have custom JS being enqueued)

$localized_data = apply_filters( 'my_localized_gutenblock_data_filter', [] ) ;
wp_localize_script( 'my-custom-gutenblocks-js', 'gutenblockHelpers', $localized_data );

Next, we’re going to add a whitelist of blocks to this filtered data.

add_filter( 'my_localized_gutenblock_data_filter', function( $localized_data ) {

  $localized_data['whitelistedBlocks'] = [
    'core/image',
    'core/paragraph'
  ];

  return $localized_data;

}, 10, 1 );

This adds a new whitelistedBlocks key to our localized data, with an array of blocks that we want to whitelist, in this case, core/image and core/paragraph.

Now, if we did this properly, we should see our `gutenblockHelpers` object enqueued and accessible via window.gutenblockHelpers. You can see this in your browser console.

 

Use the whitelist on the client to filter Gutenberg

Now that we’re successfully passing up a list of whitelistedBlocks up to the client, we need some JS to use that list and tell Gutenberg to respect it.

We need to enqueue a new script like so:

wp_enqueue_script(
  'gutenberg-block-whitelist',
  "/path/to/your/gutenbergWhitelist.min.js",
  [ 'wp-i18n', 'wp-element', 'wp-blocks', 'wp-components', 'wp-api' ],
  1,
  true
);

Note the dependencies. I noticed that if this script is loaded without the proper dependencies, it will be enqueued too early and not work. I can’t explain all the reasons why these need to be the dependencies, but these are the dependencies I declared to get things working and without them, things went a bit wonky.

Next, we need to write the script that we’re enqueueing.

Note:, I’m using es6 which is being transpiled/minified by Webpack & Babel. I’m using the 10up theme scaffold which has Webpack configured and a build script that handles this. 

let whitelistedBlocks =gutenblockHelpers &&gutenblockHelpers.whitelistedBlocks ?gutenblockHelpers.whitelistedBlocks : null;
const {unregisterBlockType, getBlockTypes} = wp.blocks;


/**
 * We have to wait until all blocks have been registered before unregistering them.
 *
 * This is SUPER fragile and hacky and will likely cause things to break over time, so I suggest
 * keeping an eye on Gutenberg to see how blacklisting/whitelisting evolves in the core plugin.
 */
wp.api.init().then( ( () => {

	/**
	 * Loop through the blacklisted blocks and unregister them.
	 *
	 * The blacklist is added to the gutenblockHelpers global via wp_localize_script.
	 */
	if (
		whitelistedBlocks.length &&
		typeof unregisterBlockType !== 'undefined' &&
		getBlockTypes !== 'undefined'
	) {
		getBlockTypes().forEach( block => {
			if ( whitelistedBlocks.indexOf( block.name ) === -1 ) {
				unregisterBlockType( block.name );
			}
		} );
	}

} ) );

This script checks to see if there’s a list of whitelisted blocks passed up to the client from our localized data.

If there is, it waits for the wp.api to initialize, then if the core Gutenberg methods getBlockTypes and unregisterBlockType is available and the whitelist has items defined, it asks Gutenberg for a list of ALL registered blocks usinggetBlockTypes, then it loops through them and unregisters all that are NOT part of the list of whitelisted blocks.

At this point, if you try and interact with Gutenberg, the only blocks you should now have access to are the core/paragraph and core/image blocks.

Customizing the whitelist for Post Types or other conditions

It’s likely that you may want to customize the list of blocks that are allowed for certain post_types.

To do that, you just need to adjust your filtered list of blocks, like so:

add_filter( 'my_localized_gutenblock_data_filter', function( $localized_data ) {

  global $post;

  $localized_data['whitelistedBlocks'] = [
    'core/image',
    'core/paragraph'
  ];

  // whitelist a custom block for a custom post type
  if ( 'my-custom-type' === $post->post_type ) {
    array_push( $localized_data, 'your-prefix/custom-block' );
  }

  // Remove the core/image block for a specific post type
  if ( isset(  $localized_data['whitelistedBlocks'][''core/image'] ) && 'my-custom-type' === $post->post_type ) {
    unset( $localized_data['whitelistedBlocks'][''core/image'] );
  }

  return $localized_data;

}, 10, 1 );

 

Automatic Featured Images from Post Title

As I’ve been starting to post to my blog more often, I’ve struggled with how the design of my site should be. . .I want it to be visually appealing, but I don’t have the time or desire to work on images for all my posts. . .this could be an interesting solution to add more visual appeal with little work.

I’ve yet to check it out, but I’m saving the link here to check out sometime soon.

http://www.wpmayor.com/featured-image-plugin/

Blogging Daily

I’ve wanted to blog daily for several years, but I’ve never been able to make it a habit.

My goal, starting today, is to at least spend 30 minutes a day working on blogging for at least 30 days.

Some ideas I have to write about include:

  • Reviewing WordPress plugins
  • Discussing ideas for WordPress projects
  • Giving insight into how I solved something while working on a WordPress project
  • Experiments with Meteorjs
  • Connecting WordPress and Meteor in various ways
  • Bookmarking interesting links for future reference
  • Venting about frustrations at work or in life in general

Ultimately, I’ve learned so much from other people sharing content so freely on the web, and I make my living developing for WordPress, but I hardly spend time actually using WordPress anymore. . .so I think it’s time I start using WordPress again, not just building things for it. And it’s time I stop just consuming other’s knowledge, but start sharing knowledge I’ve acquired.

Here’s to 30-days of blogging for at least 3o minutes. . .that might mean one post a day, maybe more. We’ll see. Hopefully I can make this thing a habit and really start giving back to the community that’s given so much to me.