Half-Elf on Tech

Thoughts From a Professional Lesbian

Tag: gutenberg

  • Gutenberg Spoiler Blocks Redux

    Gutenberg Spoiler Blocks Redux

    While I did write up Spoiler Blocks for Gutenberg one way, I also sat down recently and rewrote it a little cleaner. The primary difference here is how I’m properly using defaults:

    The Code

    ( function( blocks, element, editor, components ) {
    
    	const { registerBlockType } = blocks;
    	const { RichText } = editor;
    	const { createElement } = element;
    	const { InspectorControls } = editor;
    	const { SelectControl, ToggleControl } = components;
    
    	registerBlockType( 'library/spoilers', {
    		title: __( 'Spoiler Warning' ),
    		icon: 'vault',
    		category: 'halfelf',
    		customClassName: false,
    		className: false,
    		attributes: {
    			content: {
    				source: 'children',
    				selector: 'div',
    				default: 'Warning: This post contains spoilers!'
    			}
    		},
    
    		save: function( props ) {
    			const content = props.attributes.content;
    			const container = createElement(
    				'div', { className: 'alert alert-danger' },
    				React.createElement( RichText.Content, { value: content })
    			);
    			return container;
    		},
    
    		edit: function( props ) {
    			const content = props.attributes.content;
    			const focus = props.focus;
    
    			function onChangeSpoiler( newContent ) {
    				props.setAttributes( { content: newContent } );
    			}
    
    			const editSpoiler = createElement(
    				RichText,
    				{
    					tagName: 'div',
    					className: props.className,
    					onChange: onChangeSpoiler,
    					value: content,
    					focus: focus,
    					onFocus: props.setFocus,
    				}
    			);
    
    			return createElement(
    				'div', { className: 'alert alert-danger' },
    				editSpoiler
    			);
    		},
    
    	});
    
    })(
    	window.wp.blocks,
    	window.wp.element,
    	window.wp.editor,
    	window.wp.components,
    	window.wp.i18n
    );
    

    Learning more and more about Gutenberg, and javascript, I’ve been able to iterate on the existing code and keep improving.

  • Gutenberg Categories

    Gutenberg Categories

    No, this isn’t something snazzy about doing cool things with categories within Gutenberg (although you could). This is about making a section for your own blocks. A category.

    What’s a Category?

    I’m incredibly lazy, so when I use blocks, I type /head and make sure I get the right block, hit enter, and keep on typing.

    The slash command at work!

    But. Sometimes I think I need a specific block and I don’t know the name, so I click on the circle + sign and I get a list of categories!

    Block categories

    You won’t see reusable if you didn’t make some, but the point is that you could make a custom category for your custom blocks.

    Show me the code!

    Glad you asked! You’re gonna love this one.

    add_filter( 'block_categories', function( $categories, $post ) {
    	return array_merge(
    		$categories,
    		array(
    			array(
    				'slug'  => 'halfelf',
    				'title' => 'Half-Elf',
    			),
    		)
    	);
    }, 10, 2 );

    Yep. That’s it! It’s an array, so you can add more and more and more as you want. Don’t go too wild, though, or you’ll make it too long.

  • Advanced Block Behaviour

    Advanced Block Behaviour

    Making a straight forward block to insert content in Gutenberg is (relatively) easy. I hate using the word ‘easy’ here, because in order to do it you will need to master a whole new world of coding, but all things considered, yes. It is easy. In fact, Gary (aka Pento) wrote a sample plugin that will let you convert a shortcode to a Gutenberg Block.

    I myself have written a mildly complicated Spoiler Block (there’s a new version of it I will share soon). But then the day happened that my cohort in lesbian TV crime, Tracy, expressed annoyance at how Gutenberg destroyed her listicle.

    What is a Listicle?

    Have you seen those posts that show you the top ten ways to LifeHack your used egg cartons? Those are listicles. They’re lists (list) articles (icle). Makes sense, right? Listicles have a pretty basic format as well, there will be a header with some sort of numerical mark, then content with images etc. This repeats for the number of times you have an article.

    Most people make them by hand by manually editing the numbers in their header. That’s all well and good until you want to craft better formatting and have a listicle look somehow ‘different’ from the rest of your content. Maybe you want them to have a special background color, or a different design for the header. 

    If we were doing this in the old, simple, HTML way, it would look like this:

    <dl class="listicle">
        <dt>The Title</dt>
        <dd>The Content</dd>
    </dl>

    Of course that doesn’t make anything look like a list until you put in some CSS magic:

    .listicle {
      counter-reset: listicle-counter;
    }
    
    .listicle dt:before { 
        content: counter(listicle-counter);
        counter-increment: listicle-counter;
        margin-right: 6px;
    }

    What this does is create a CSS counter and increment it every time you use <dt> creating an auto incrementing list.

    No HTML for Gutenberg

    Now, if you know the HTML, you can still do this in Gutenberg in HTML by using the HTML block.

    Example of summoning the Custom HTML block.

    But if you don’t know HTML, then this is a bloody nightmare to handle. And part of the reason why I’m very pro-Gutenberg is that it’s 2018, and expecting people to know all the myriad magical steps of HTML, in order to create a webpage, feels passé. No, it feels restrictive. We can’t expect websites to advance and become more than just pages if we don’t give them the tools.

    Complex Design

    Unlike the relatively simple javascript I used to make my Spoiler Box block, to do this requires the use of a feature called ‘Inner Blocks‘ which is effectively putting a block inside a block. 

    My original idea was to have a multiple nested block with the following:

    1. Listicle Block that calls a template of a list item
    2. ListItem block that calls a title and description
    3. ListDT block that calls the title
    4. ListDD block that allows you to add whatever more inner blocks you want

    It sounds incredibly complicated, and sadly the perfect version was so difficult I actually started with a pared down version.

    1. Listicle block that sets up a template of title and description

    The problem here is that I end up having a separate dl for each block. I can work around it with some CSS magic, but it’s not perfect. So I knuckled down and actually wrote the code that does exactly what I want. Whew.

    Some Code

    … Actually I’m going to do something I hate and that’s link to an external directory.

    I’ve build out Listicles for Gutenberg for you to peruse and fork and enjoy. Or even use if you want, becuase it does work. But it’s big. No, it’s huge for an in-post example. And to explain everything line by line wouldn’t help.

    If you go to the repository, the Gutenberg source code is located in /src/ – that’s where most (if not all) of your work will happen.

    • blocks.js – A list of all the separate JS files included
    • /block/listicle.js – The main listicle file
    • /block/listitem.js – Individual list items (this is only usable inside the Listicles block)
    • /block/listdt.js – The list title
    • /block/listdd.js – The list content (this allows you to add as many sub blocks as you can)

    And yes, not only does it auto increment as you move the slider (or bump the counter), you can flip it into reverse mode:

    The real trick of it all was the copious use of templates.

    It’s all Complicated

    Besides the fact that the blocks aren’t quite  where I want them to be, I also have to use a block builder to convert that javascript into my real files. I chose the Create Guten Block builder, instead of building out my own NPM build script.

    That too illustrates some of the concerns people have, and rightly so, about blocks being incredibly more complicated than they need to be. And yet, having gone through the exercise myself, I think that it’s perhaps not going to be that much of a drama.

    For those of use who generally just make new shortcodes, the world won’t change too much. Gutenberg supports inline shortcodes, after all, which is the majority of what people need from it. We want to be able to make our own embed blocks, which again isn’t terrible, and when someone gets to the complicated point of needing something advanced like a listicle, well eventually there will be a plugin that will handle this better than a shortcode.

    Or you could just use that HTML block.

  • Post Editing Is Broken

    Post Editing Is Broken

    By now I’m sure most of you have seen Gutenberg. And I’m sure you all have a lot of opinions about Gutenberg and why it’s absolutely not needed. You may also have read conversation about how we totally need Gutenberg, and it’s part of the long view of the future.

    I’m going to tell you something that may be difficult to accept.

    We need Gutenberg because post editing is broken.

    The Visual Editor is Limited

    The current visual editor, which uses TinyMCE, is incredibly limited. It’s awesome, as you can make a WYSIMWYG (What you see is mostly what you get) post, but it can be really hard to get layout and design flow to look ‘right.’ And if you want to insert custom content, you’re left using embeds or shortcodes.

    I love shortcodes. But. They’re weird and complicated and no two work exactly the same way. People don’t always document them, they’re not discoverable, and they can be incredibly obscure to use. Which ones take input and which are nested and so on.

    This means that advanced customization of post content is left to templating engines in those page-builder plugins, which either have to re-jigger the whole screen (like Gutenberg) or utilize a complex nesting of shortcodes (like that other plugin you’re thinking about). Neither is a great experience for users, especially when no two page builders work the same way.

    The HTML Editor is Cryptic

    If you’re not a developer or someone who read the original HTML 2.0 spec book (hardcover, y’all), then HTML may be a beast you don’t understand. It’s complicated, it has a lot of weird quirks, and you’ll hear people tell you to use tables (or not), or use divs (or not), or only troglodytes use spans and colors.

    Basically it’s confusing unless you know HTML, and that means if you’re not an advanced user or a designer/developer, you’re screwed. You’re expected to learn a whole new suite of complex arcana just to make a table with today’s WordPress. Or you use a plugin and then you find out the semantic HTML it used was problematic, and you have no idea how to fix it.

    Anyone who supports end-users who know MS Word and not WordPress have dealt with this drama. It’s real, and WordPress is still struggling to address it. Which is why we have Gutenberg in the pipeline.

    Gutenberg Isn’t Perfect

    None of this is to say that Gutenberg is perfect. I’ve had experiences with exactly how hard it is to wrangle. Building new blocks is crazy hard if you’re not using simple reusable blocks like my favourite spoiler block:

    If you want to make a complicated nested block it’s frustrating. You have to decide what flavour of Javascript you want to use and how to build it. Let’s be honest here, folks, it’s tough to be a developer in this new land.

    And as a user it’s no picnic either. It’s a lot of change and kicking yourself out of old habits and into embracing the new. Which we’re all generally terrible at. You have to shift from a fundamental concept of “Big Chunk of Content” and into “Smaller Blocks of Content.” Meta boxes and data like we add with ACF and CMB2 isn’t perfect yet either. Heck, I can’t even customize my Jetpack sharing with Gutenberg yet.

    But. As we use Gutenberg and as we inch forward, we start to see the progress. I can still insert tables via HTML inside a Gutenberg post. I can build (or hire someone to have built) a block to tweak things to my heart’s content. Things may be hard, but they’re possible.

    You Must Break a Bone to Set It

    When I was 11, I broke my arm. And I remember the feeling of abject horror when the doctor told me they’d have to break my arm again in order to set it. I used some language they’d never heard from a child my age. And it hurt like hell. It was the most pain I’d been in my young life.

    My arm never worked the ‘same’ way afterwards either. Oh sure, I could do pretty much everything, but I had to compensate and learn new ways to do other things. I don’t have full rotation in my wrist still, though it’s much better, which meant I had to change how I did certain motions. Like typing, that hand rarely rests on the keyboard. In short, I had to adapt. 

    The current editor is imperfect and broken. In order to fix it, we must shatter it and move forward. It hurts, it’s a struggle, but if we push each other, we can do this. Continue to criticize the things that are missing (not being able to hide taxonomies from use, for example), but do so in a way to help it forward.

  • You’ll Probably be Fine with Gutenberg

    You’ll Probably be Fine with Gutenberg

    With WordPress 5.0 getting closer and closer, I know a lot of people are worried about Gutenberg and what that will mean for their themes and plugins.

    Most Themes Will Be Fine

    The majority of themes, every single one you can download from WordPress.org, and the ones from reputable theme shops like StudioPress, will be just fine. Nothing will break, and other than getting a new editor experience, there’s no change.

    What will happen, and yes people will call this breaking, is that not all features will be supported

    Right now, most themes don’t support some of the more outré block types. And a lot of themes don’t support text columns like this:

    And then again, Genesis? Does!

    This is a left column

    This is a right column

    And every theme is going to support repeatable blocks which means you’ll be able to build out some nice defaults and standards.

    The reason for all this is that if you’re just using Gutenberg as an editor, not a whole lot has changed with your content. It remains the same as it ever was, just with a fresh coat of paint.

    There are exceptions, like themes that rely heavily on features that alter the post editor. I’ll get there in a minute.

    Most Plugins Will be Fine, Too

    Here again, unless your plugin interest with the post editor, you are going to be just fine. You use Jetpack to publicize your posts? Cool. No change. AMP? No change.  Go look at most of your plugins. Caching? No changes. Google Analytics? No change.

    The reason here is, again, most plugins don’t mess with post editing. I should know. I review them.

    I know what you’re thinking, though. What about plugins like Yoast SEO, which add in a bunch of extra boxes at the bottom and sides of a post? The boxes are called Meta Boxes, and they’re already supported. Plus Yoast went to the extra effort of being on the forefront of Gutenberging.

    The colours to indicate how good your post’s SEO is, however, are missing right now. So is the field to customize your Jetpack publicize content. Basically everything that went on that sidebar on the post edit screen (the Publish Box) isn’t done yet.

    Which brings me to…

    The Exceptions Will Hurt

    Okay.  I won’t sugar coat this. If you use a complex post editor, like Visual Composer or Bold Grid, or if you use a plugin with a lot of custom meta boxes, the world will be very different, and probably unhappy.

    Now that said, Visual Composer will work with Gutenberg! And so will ACF and CMB2 is well on it’s way. But. The problem is people who have bundled those plugins in their themes. And those themes will have to update their packages and make sure users update.

    Anyone who just had a mental image of how many premium themes bundle Visual Composer and tried to calculate the number of users who don’t properly update themes regularly… welcome to my world. I’d like to say I’m ‘against’ the bundle, but the reality is that I’m against premium products using libraries and then not managing those libraries properly. Not that it’s easy, and that’s a different topic.

    The problem in the exception is that there will be a non-insignificant number of people who have no idea they’re using a problematic library that needs an update.

    Where Do We Go From Here?

    This problem is WordPress’ own doing, make no mistake. If the ability to add custom meta boxes and settings and the like was less complicated to begin with, we wouldn’t have needed tools like these to work around it. We still have no decent meta box API, and the settings API is something I regularly call “as intelligent as a bag of wet hair.”

    But. Innovation is necessary. We can’t just not move forward because we didn’t do things right the first time. And in WordPress’ defence, there was no way to know or even write the ‘right’ way back 15 years ago when all this started. The best tools didn’t exist. And all those ways we built to hack around the problem made it more clear what the right way needed to be.

    Which brings us here.

    Most of what you do won’t be impacted by Gutenberg. What is adversely impacted won’t break most things, but it will be really annoying. And then those rare edge case exceptions? Well. We’re back to the words (paraphrased) of Hecht.

    When infrequently used systems break, they do so in big ways.

  • A Slightly More Complex Sample Box: Spoilers

    A Slightly More Complex Sample Box: Spoilers

    Round two!

    Once I made a simple, sample spoiler box, it was time to jump into the next stage. Customizable, editable, not simple, sample spoiler boxes!

    Here’s the best part. All I had to change was the index.js file from the previous example.

    The Javascript

    ( function( blocks, i18n, element ) {
    	var el = element.createElement;
    	var __ = i18n.__;
    	var RichText = blocks.RichText;
    
    	blocks.registerBlockType( 'library/spoilers', {
    
    		title: __( 'Spoiler Warning' ),
    		icon: 'vault',
    		category: 'widgets',
    		supportHTML: false,
    
    		attributes: {
    			content: {
    				type: 'array',
    				source: 'children',
    				selector: 'div',
    			},
    		},
    
    		edit: function( props ) {
    			var content = props.attributes.content || 'Warning: This post contains spoilers!';
    			var focus = props.focus;
    			function onChangeContent( newContent ) {
    				props.setAttributes( { content: newContent } );
    			}
    
    			return el(
    				RichText,
    				{
    					tagName: 'div',
    					className: props.className,
    					onChange: onChangeContent,
    					value: content,
    					focus: focus,
    					onFocus: props.setFocus
    				}
    			);
    		},
    
    		save: function( props ) {
    			return el(
    				'div',
    				{ className: 'alert alert-danger'},
    				props.attributes.content
    			);
    		}
    	} );
    } )(
    	window.wp.blocks,
    	window.wp.i18n,
    	window.wp.element
    );
    

    What’s Different?

    A few things. A lot of things. The idea is that we need to pass the content attribute (i.e. our warning) to be processed. This is very much like how you pass attributes through shortcodes, so don’t panic.

    var content = props.attributes.content || 'Warning: This post contains spoilers!';
    var focus = props.focus;
    function onChangeContent( newContent ) {
    	props.setAttributes( { content: newContent } );
    }
    

    This says “Set the content to ‘Warning: This post contains spoilers!’ if there’s nothing there. Then watch the focus. If the focus changes, use the new content to replace the original content.”

    Down in our return el section, we’ve changed it to be Rich Text (so people can use bold and so on… even though it’s always bold), and the value: content, is the variable content we edited above.

    What’s It Like?

    It’s just like any other Block. It inserts itself when you click the icon, it loads the default, and you can edit it:

    An example Gif of spoilers

    And that is a simple, editable, Gutenberg Block