1

The site I've inherited relies heavily on TinyMCE custom menu buttons and shortcodes, but I think its time for the site to move beyond TinyMCE and shortcodes.

Our site's TinyMCE customization is a blocker (I know very little about Gutenberg) and I am unsure if Gutenberg can offer the same feature - specifically we have 2 buttons which will format the entire post:

  • Text formatter - this menu has various options to do things like parse the entire document and convert all bolded text into headings. Or to remove extra spaces from the entire document. Or to convert Microsoft Word endnote anchors/links to something we prefer

  • Table formatter - similar to the above. there are functions that will strip all tables of all style attributes, or moves the first row of each table into a tag ect

We are doing this in TinyMCE simply by grabbing the editor content and running it though various functions. But Gutenberg is different and paragraphs, block quotes, images ect are all their own specific blocks instead of being in 1 big node of content.

So is there a way to do something similar in Gutenberg?

1 Answer 1

3
+50

I think you can do this in a couple of different ways. I can't help with the specific processing you want done (since I don't know exactly what all you want done) but hopefully this gets you started.

Option 1

Loop through all blocks and "process" each block independently.

import { useSelect } from '@wordpress/data';

// Get the full list of blocks in the editor
const blocks = useSelect((select) => {
    return select('core/block-editor').getBlocks();
});

// Loop through each block and do whatever needs doing
if (blocks.length > 0) {
    blocks.forEach((block) => {
        // Process the block here
    });
}

You can console.log to see what each block contains, but they are essentially just a bunch of attributes stored as an object.

You may need to recursively loop over nested blocks since Gutenberg supports InnerBlocks.

if (block.hasOwnProperty('innerBlocks') && block.innerBlocks.length > 0) {
    block.innerBlocks.forEach((innerBlock) => {
        // Do your processing
    });
}

Option 2

Get the full HTML content of the edited post and process it as if it were static HTML.

import { useSelect } from '@wordpress/data';

// Get the full edited post content (HTML string)
const content = useSelect((select) => {
    return select('core/editor').getEditedPostContent();
});

// Parse the HTML so you can do things with it.
const parser = new DOMParser();
const htmlDoc = parser.parseFromString(content, 'text/html');

// Do whatever with the HTML (htmlDoc) you want
// E.g. Get all the links: 
const links = htmlDoc.getElementsByTagName('a');

You can add a custom button to the editor sidebar to trigger the processing like this:

import { PluginPostStatusInfo } from '@wordpress/edit-post';
import { Button } from '@wordpress/components';

registerPlugin('my-post-status-info', {
    render: () => {
        const doProcessing = () => {
            // Do your processing
        };

        return (
            <PluginPostStatusInfo>
                <Button
                    isLink={ true }
                    onClick={ () => doProcessing }
                >
                    { __('Process', 'pb') }
                </Button>
            </PluginPostStatusInfo>
        );
    }
});
1
  • dude this is awesome, and is exactly what i needed! I really just needed to be pointed in the general direction so I could better justify investing in Gutenberg to my handlers. Now we know that GB is going to offer what we need to move forward. Thanks a ton Phil!
    – rugbert
    Aug 9, 2021 at 20:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.