As we start looking at the editor from a technical perspective it’s important we identify the main obstacles and requirements we face before we start conjecturing solutions. As @matt wrote before, the editor focus aims to make writing rich posts effortless. This has taken the path of treating a post as being composed of distinct pieces of content called blocks. These pieces should be easy to insert and manipulate, providing rich and contextual interfaces to interact with as you craft a post.
So how do we go about turning this into a reality? Content in WordPress is, fundamentally, HTML-augmented text; that is to say, it has no inherent data structure. This has been a very important aspect of WordPress and a force for the open web—it speaks to the sense of ownership and freedom WordPress gives you, since it’s always easy to get the full content of your publications—yet the lack of structure gets in the way of the goal to treat content as composed from individual pieces. (This reality also became an issue for the development of post formats a few years ago, but I digress.)
It’s relatively easy to add structure, but it’s not trivial to do so in a way that doesn’t harm data integrity, portability, and the cohesiveness of the
post_content. So let’s lay out a first requirement:
① Shape of the Data: Portable Text
To ensure we keep a key component of WordPress’ strength intact, the source of truth for the content should remain in
post_content, where the bulk of the post data needs to be present in a way that is accessible and portable, while still providing additional structure on top of HTML semantics for our editing tools. Data needs to be praised and respected. This additional structure would hopefully be invisible to the document’s display context, as it ensures the rendered content is viewable in situations that may not be aware of blocks at all. (Think of email clients, RSS, older editor versions, mobile editors, database dumps, etc.)
Storing things separately means
post_content becomes either a pointer or duplicated data, which fragments the source of truth since they can get out of sync easily. (A few content block plugins do this by storing structured data in postmeta and pure data in
post_content.) On the other hand, storing things together means structure can become gibberish if it’s not formatted properly before display.
How can we then offer users a great experience when creating or manipulating content without sacrificing the spirit of integrity and data reliability that is expected from WordPress? Good representations of the data would also make it easier to develop robust collaboration tools in the future by allowing us to lock things in a more fine grained way. I believe this is important to figure out soon to allow us to prototype quickly, so I’ll follow up with an initial proposal by the end.
Honouring HTML leads to a second requirement:
② Simplicity and Semantics of Representation
Unless we are improving the semantics of the document we should minimize what markup we add to identify a block; for example, avoid adding extra DOM elements or attributes, both for simplicity and standards sake. WordPress has been a champion of web standards, and we should not venture away from this quality. How can we add structure in a way that remains invisible to the output (as meaningful content as possible) but gives the necessary hooks to infer a structured view for editing purposes?
While we discuss how to structure the content to include invisible demarcation of blocks, the aspect of their nature leads to a third requirement:
③ Static & Dynamic Blocks
Blocks can be either static or dynamic. That is to say, some blocks can be stored with all the necessary aspects needed for their display, while others need to be processed before generating their final output (shortcodes, embeds, widgets, etc). This distinction is important because the most common two blocks people will naturally use are text and images. We should not break their clarity as we treat them as blocks.
Here’s some text.
[text id=123] // Pulls "Here's some text" from somewhere.
This conceptual separation of blocks is useful for designing our project, yet they generate abstract complexity which users should not be exposed to, leading to a fourth requirement:
④ Consistent Experience
One of the biggest benefits of blocks is that composing a post becomes more intuitive and reliable. Everything is inserted under the same assumptions; discovering what can be inserted is a natural part of inserting content. To the user all blocks behave in a consistent and familiar way, even if they provide tailored UIs for their controls.
The user should also be able to edit a post in a different system (mobile, REST, older version of core, apps like Mars Edit, etc), even if they lose the advantages of block editing. That’s another reason why
post_content as source of truth matters, compared to storing a JSON structure in postmeta. Having things in two places means they can get out of sync depending on what tool you used to edit.
These nuances of data, UI, and display lead to a final and more general requirement, which is understanding the system we’ll be crafting:
⑤ The System
The editor experience has three fundamental aspects to its system: the UI used to manipulate a block; the demarcation of the block; the rendered output of the block. These are all separate concerns, from the tools we craft to edit a post, to the document syntax that holds the data structure, to the way the final output is generated to be displayed as HTML. (With static blocks that last aspect may be of no significant concern since the document doesn’t care about the presence of static blocks, it just displays them.)
As a final coda, and following @joen‘s design exploration, let’s keep in mind that our first goal should be to set up a reliable foundation to allow us to iterate quickly and test assumptions. I propose we focus initially on a few static blocks (text, image with and without caption, quote) to limit scope of the project.
In which ways can we fulfil ① and ② from the above requirements?
Shortcodes fall short in that they are not invisible, they are opaque, not standing to the scrutiny of semantics, and are also painful to parse. Alternatives could be
data-* attributes in the HTML elements or custom elements (paving the way for web components, perhaps), yet we need to be careful with adding cruft.
One other possibility is to look at HTML comments as a way to provide explicit demarcation to
post_content without affecting the node structure of the document for something that is inherently spurious to the HTML semantics. WordPress already uses comments for the more tag (
<!--more-->) and splitting content into pages in a way that has proven to be quite robust.
It could look something like this:
<!-- wp:image -->
<figcaption>A picture is worth a thousand words</figcaption>
<!-- /wp -->
There are drawbacks, benefits, and implications with each that we should discuss separately. Are there any other possible solutions?
Please, join us in #core-editor if you are interested. We’re holding weekly meetings in Slack, Wednesdays at 19:00 CET.