Category: Code Snippets

  • How to customize WebPack config in modern WordPress block development

    How to customize WebPack config in modern WordPress block development

    I find myself continuing to dive deeper and deeper into WordPress block development, and the frustrating part is a lack of documentation. So here is a quick post on something I struggled with for a little a bit in the hopes it helps someone else.

    block.json has some pretty cool features like render, style, viewScript, etc. Team this up with @wordpress/scripts to handle transpiling and the process is quite simple… until you want to add entry to a custom webpack config file to extend some capabilities.

    The problem is that if the transpiler finds any block.json files it completely bypasses your root index.js file, which me and others used as the entry point. This wouldn’t be a problem if you just extend your custom webpack.config.js. This is how I was writing it when I first started.

    /**
     * External Dependencies
     */
    const path = require('path');
    
    /**
     * WordPress Dependencies
     */
    const defaultConfig = require('@wordpress/scripts/config/webpack.config.js');
    
    module.exports = {
    	...defaultConfig,
    	entry: {
    		...defaultConfig.entry,
    		index: path.resolve(process.cwd(), 'src', 'index.js')
    	},
    };
    

    Problem here is that running this removes index.js and index.assets.php from all your blocks that use block.json in the build directory, but why? I found that when I removed entry and transpiled again, the index.js and index.assets.php files came back. So it was something with that. It looked correct though. I used defaultConfig.entry with a spread operator like I always did because every documentation I read said to do it that way. Because defaultConfig.entry is an object, right?

    Nope! It’s a function here! If you console.log(defautConfig) you’ll notice entry looks like this:

    entry: [Function: getWebpackEntryPoints],
    

    If you call that function you’ll see all the entry points in an object for your blocks. That means all you have to do in your webpack.config.js file to extend entry is change ...defaultConfig.entry to ...defaultConfig.entry() like so.

    /**
     * External Dependencies
     */
    const path = require('path');
    
    /**
     * WordPress Dependencies
     */
    const defaultConfig = require('@wordpress/scripts/config/webpack.config.js');
    
    module.exports = {
    	...defaultConfig,
    	entry: {
    		...defaultConfig.entry(),
    		index: path.resolve(process.cwd(), 'src', 'index.js')
    	},
    };
    

    Now everything works. I’m posting this because most documentation says to write it ...defaultConfig.entry, because entry is a JavaScript object. But since we are extending with the spread operator, we need to call the function to get the actual object.

  • How to protect your WordPress site from problematic code in the_content

    How to protect your WordPress site from problematic code in the_content

    By default, WordPress lets you write basically anything in the content of a page, post, or custom post type. When you write or see the_content like this in a WordPress template:

    <?php the_content(); ?>

    That’s likely allowing any code through. Even content that could be problematic. Problematic code would include raw iframes and JavaScript scripts. For example, let’s say you wrote this in the text tab of the classic editor or in the custom HTML block in Gutenberg.

    <script>alert('here');</script>

    When you save that post and viewed it, you would see a JavaScript alert pop up that says here. That is an innocuous example that is maybe just annoying. But let’s say some admin or editor credentials are compromised and a hacker writes JavaScript that could exploit the viewer in some way. How can you defend against that? Here is a simple PHP script you can add to your site to remove any scripts or iframes from the content, but will not effect embeds and shortcodes which may have iframes or scripts:

    function please_sanitize_the_content( $content ) {
    	return wp_kses_post( $content );
    }
    
    add_filter( 'the_content', 'please_sanitize_the_content', 1 );

    This filter on the_content utilizes the function wp_kses_post which will only allow HTML that WordPress deems safe. We are putting it at priority 1 (that’s what the 1 means in the add_filter function) so it runs really early and doesn’t effect embeds or shortcodes that could have scripts or iframes that your site allows.

    In addition you can also include this line if you are using the Advanced Custom Fields plugin:

    add_filter( 'acf_the_content', 'please_sanitize_the_content', 1 );

    This is a similar filter to the_content but is for Advanced Custom Fields rich editor fields.

    Also note… you can also set the disallow unfiltered HTML constant as such in wp-config.php to ensure your content is clear of malicious scripts and iframes.

    define( 'DISALLOW_UNFILTERED_HTML', true );

    However, this method is not retroactive to content that has already been saved to the database, and it also removes the Additional CSS feature in the customizer (which I don’t love, but find useful at a moment’s notice).

  • How to create unique widget areas for individual posts in WordPress

    How to create unique widget areas for individual posts in WordPress

    Here’s a cool little trick for adding widget areas that are unique to posts, but without cluttering up Appearance->Widgets in the admin. Instead, we utilize the Customizer, which is perfect for this sort of thing.

    First thing, we need to hook a function into `init` where we register our widget area.

    (more…)