How to create a dummy content generator for WordPress block editor Gutenberg

In this tutorial, I’ll cover how you can create a content generator extension for WordPress Gutenberg. With this extension plugin, we will be able to generate random “lorem ipsum” content within Gutenberg editor. Dummy content can be very useful in some cases.

What are we going to learn?

I think it’s always better to know what benefit a tutorial will provide (in terms of knowledge) before following it. After covering this tutorial, you’ll have some basic understanding of the following:

Overview

When following a tutorial, it’s better to know upfront what to expect at the end.

The goal is for a user to insert a command in a paragraph block, and our plugin should transform that to dummy content based on the command.

Let’s review all commands we’re going to create in this tutorial

Command 1: lorem<length>

A simple command that will transform the paragraph block into lorem ipsum dummy content according to the given length.

generating 300 characters dummy content

Command 2: loremlist<list-length>

A simple command that will generate lists based on the given length, containing dummy content with 50 characters each.

basic loremlist command

Command 3: loremlist<list-length>-<character-length>

Command extending the previous command, but also including each list character length.

loremlist command with character length

User interaction

Planning user interaction is the most crucial part when you’re developing something, the same goes for Gutenberg block. Here’s how the user should generate dummy content using our plugin.

user inserts a paragraph block

user types a command and hit enter

paragraph block transforms into dummy content based on the command

Getting Started

In order to get started, use this starter template “CakeWP/gutenberg-extension-starter-template” for quickly creating Gutenberg based plugins.


Introduction to gutenberg block transform API

block to block transformation

Before we proceed with this tutorial, It’s important for you to have some basic knowledge about Gutenberg block transform API.

You can read more about Gutenberg block transform API here.

We’re not going to cover the API in-depth in this tutorial, Let’s leave that for future tutorials.

Basically, The Block Transforms API allows us to transform blocks from one block to another. It also transforms blocks from different entities, such as shortcodes, files, regular expressions, and raw DOM nodes.

There are total of 6 types of transformations available (at the time of this tutorial).

  1. block
  2. enter
  3. files
  4. prefix
  5. raw
  6. shortcode

Introduction to gutenberg block filters

We can supercharge/extend Gutenberg blocks with Gutenberg block filters. Gutenberg Block filters basically allow us to add more functionalities to the existing Gutenberg block.

You can read more about Gutenberg block filters here.

There are different filters available to extend Gutenberg blocks. Here is a list of some available block filters.

Creating utility methods

We need some utility methods that will help us generate random dummy content, For the sake of simplicity, we are not going to call an external API in this tutorial. Instead, we will generate dummy content based on random words.

Let’s create a directory named “utils” that’ll store our dummy words in JSON format, as well as some utility functions.

Download the following words.json in the utils directory. It contains a bunch of random words.

Now, let’s create some utility methods, that will use this JSON file to generate dummy content. Create “functions.js” in utils directory

// src/utils/functions.js
import words from "../words.json";

export const generateRandomContent = (length) => {
	let content = "";

	while (content.length < length) {
		let randomWords = words[Math.floor(Math.random() * words.length)];
		content += ` ${randomWords}`;
	}

	return content.trim().substring(0, length);
};

export const generateRandomLists = (listItemLength, characterLength = 50) => {
	let lists = [];

	// for each list.
	for (let i = 0; i < listItemLength; i++) {
		const listContent =
			"<li>" + generateRandomContent(characterLength) + "</li>";
		lists.push(listContent);
	}

	return lists.join(" ");
};

So far, we have 2 simple utility methods. Let me explain what each one does:

  • generateRandomContent(length): Generates random content based on the argument length.
  • generateRandomLists(listItemLength, characterLength = 50): Generates a dummy list content based on 2 arguments. Here’s what each argument does.
    • listItemLength: Specifies length of list items needed.
    • characterLength (optional): Specifies length of dummy content required in each list item. Default to 50 characters if not provided.

Extending gutenberg core paragraph block

Now that we’ve some basic knowledge covered about Gutenberg block transformation API and Gutenberg block filters.

We need to extend the Gutenberg core paragraph to include a new transformation method. We’re going to use a block filter blocks.registerBlockType to extend the Gutenberg paragraph block.

// src/index.js
import { addFilter } from "@wordpress/hooks";

Gutenberg “addFilter” accepts 3 arguments, i.e hook name, namespace, callback, and priority (optional).

// src/index.js
addFilter(
	"blocks.registerBlockType",
	"gutenberghub/content-generator",
	(settings, blockName) => {

		if ("core/paragraph" !== blockName) {
			return settings;
		}

        // extend settings for paragraph block here.
		return settings;
	}
);

We need to also ensure that all other block setting still persists after our filter.

The filter above will be applied to all Gutenberg blocks. Therefore we need to narrow down with an additional condition that ensures that our filter only applies to the Gutenberg paragraph block.


As we’ve set up a basic filter that can manipulate Gutenberg block settings. It’s time to create all commands.

Command 1: lorem<length>

Let’s work for the first and most basic command lorem<length>.

Creating the regex

we need a regex that matches the lorem<length> command. We need to capture both in separate groups.

lorem command explanation

Here’s what the final regex looks like:

/^(lorem\s?)(\d+)$/i

Here’s a visual explanation of the regex above.

lorem command regex explanation

Adding transformation

Let’s now add a new transformation method to the paragraph block.

// src/index.js

addFilter(
	"blocks.registerBlockType",
	"gutenberghub/content-generator",
	(settings, blockName) => {
		if ("core/paragraph" !== blockName) {
			return settings;
		}

		return {
			...settings,
			transforms: {
				...settings.transforms,
				from: [
					...settings.transforms.from,
					{
						type: "enter",
						regExp: /^(lorem\s?)(\d+)$/i,
						transform: ({ content }) => {
							// obtaining required content length from 2nd captured group
							const requiredContentLength = Number(
								content.match(/^(lorem\s?)(\d+)$/i)[2]
							);

							// using our utility method.
							const generatedContent = generateRandomContent(
								requiredContentLength
							);

							return createBlock("core/paragraph", {
								content: generatedContent,
							});
						},
					},
				],
			},
		};
	}
);

Command 2: loremlist<list-length>

Now, let’s work on creating our second command loremlist<list-length>.

Creating the regex

Like the previous command, we need a regex that matches this command in 2 separate groups

loremlist command explanation

Here’s what the final regex looks like:

/^(loremlist\s?)(\d+)$/i

Here’s a visual explanation of the regex above.

loremlist command explanation with regex

Adding transformation

Let’s add another transformation method for this command in our block filter.

// src/index.js
addFilter(
	"blocks.registerBlockType",
	"gutenberghub/content-generator",
	(settings, blockName) => {
		if ("core/paragraph" !== blockName) {
			return settings;
		}

		return {
			...settings,
			transforms: {
				...settings.transforms,
				from: [
					...settings.transforms.from,
					{
						type: "enter",
						regExp: /^(lorem\s?)(\d+)$/i,
						transform: ({ content }) => {
							// obtaining required content length from 2nd captured group
							const requiredContentLength = Number(
								content.match(/^(lorem\s?)(\d+)$/i)[2]
							);

							// using our utility method.
							const generatedContent = generateRandomContent(
								requiredContentLength
							);

							return createBlock("core/paragraph", {
								content: generatedContent,
							});
						},
					},
                    // loremlist transformation
					{
						type: "enter",
						regExp: /^(loremlist\s?)(\d+)$/i,
						transform: ({ content }) => {
							const listItemLength = Number(
								content.match(/^(loremlist\s?)(\d+)$/i)[2]
							);
							const generatedContent = generateRandomLists(listItemLength);
							return createBlock("core/list", {
								values: generatedContent,
							});
						},
					},
				],
			},
		};
	}
);

Command 3: loremlist<list-length>-<character-length>

This command is basically an extended version of the previous command. For this particular command, we need to capture 4 separate regex groups.

Creating the regex

We need a regex that matches 4 separate groups

loremlist with character length, explanation

Here’s what final regex looks like

/^(loremlist\s?)(\d+)(-)(\d+)$/i

Here’s a visual explanation of the regex above.

loremlist with character length explanation

Adding transformation

Now, adding another transformation method for this particular command


addFilter(
	"blocks.registerBlockType",
	"gutenberghub/content-generator",
	(settings, blockName) => {
		if ("core/paragraph" !== blockName) {
			return settings;
		}

		return {
			...settings,
			transforms: {
				...settings.transforms,
				from: [
					...settings.transforms.from,
					{
						type: "enter",
						regExp: /^(lorem\s?)(\d+)$/i,
						transform: ({ content }) => {
							// obtaining required content length from 2nd captured group
							const requiredContentLength = Number(
								content.match(/^(lorem\s?)(\d+)$/i)[2]
							);

							// using our utility method.
							const generatedContent = generateRandomContent(
								requiredContentLength
							);

							return createBlock("core/paragraph", {
								content: generatedContent,
							});
						},
					},
					{
						type: "enter",
						regExp: /^(loremlist\s?)(\d+)$/i,
						transform: ({ content }) => {
							const listItemLength = Number(
								content.match(/^(loremlist\s?)(\d+)$/i)[2]
							);
							const generatedContent = generateRandomLists(listItemLength);
							return createBlock("core/list", {
								values: generatedContent,
							});
						},
					},
					// loremlist extended transformation
					{
						type: "enter",
						regExp: /^(loremlist\s?)(\d+)(-)(\d+)$/i,
						transform: ({ content }) => {
							const matches = content.match(/^(loremlist\s?)(\d+)(-)(\d+)$/i);

							const contentLength = Number(matches[4]);
							const listItemLength = Number(matches[2]);
							const generatedContent = generateRandomLists(
								listItemLength,
								contentLength
							);
							return createBlock("core/list", {
								values: generatedContent,
							});
						},
					},
				],
			},
		};
	}
);

Let’s wrap up this tutorial. If you’ve any questions, Feel free to comment below.


Leave a Reply

Subscribe and Get Updates Weekly

Latest articles, blocks, templates, tools, news every week