Content Modeling for WYSIWYG Authoring with Edge Delivery Services Projects content-modeling
Learn how content modeling works for WYSIWYG Authoring with Edge Delivery Services projects and how to model your own content.
Prerequisites prerequisites
Projects using WYSIWYG Authoring with Edge Delivery Services inherit the majority of the mechanics of any other Edge Delivery Services project, independent of the content source or authoring method.
Before you begin modeling content for your project, make sure you first read the following documentation.
It is essential to understand those concepts in order to come up with a compelling content model that works in a content source-agnostic way. This document provides details about the mechanics implemented specifically for WYSIWYG authoring.
Default Content default-content
Default content is content an author intuitively would put on a page without adding any additional semantics. This includes text, headings, links, and images. Such content is self-explanatory in its function and purpose.
In AEM, this content is implemented as components with very simple, pre-defined models, which include everything that can serialized in Markdown and HTML.
- Text: Rich text (including list elements and strong or italic text)
- Title: Text, type (h1-h6)
- Image: Source, description
- Button: Text, title, url, type (default, primary, secondary)
The model of these components is part of the Boilerplate for WYSIWYG authoring with Edge Delivery Services.
Blocks blocks
Blocks are used to create richer content with specific styles and functionality. In contrast to default content, blocks do require additional semantics.
Blocks are essentially pieces of content decorated by JavaScript and styled with a stylesheet.
Block Model Definition model-definition
When using WYSIWYG authoring with Edge Delivery Services, the content of blocks must be modelled explicitly in order to provide the author the interface to create content. Essentially you need to create a model so the authoring UI knows what options to present to the author based on the block.
The component-models.json
file defines the model of blocks. The fields defined in the component model are persisted as properties in AEM and rendered as cells in the table that makes up a block.
{
"id": "hero",
"fields": [
{
"component": "reference",
"valueType": "string",
"name": "image",
"label": "Image",
"multi": false
},
{
"component": "text-input",
"valueType": "string",
"name": "imageAlt",
"label": "Alt",
"value": ""
},
{
"component": "text-area",
"name": "text",
"value": "",
"label": "Text",
"valueType": "string"
}
]
}
Note that not every block must have a model. Some blocks are simply containers for a list of children, where each child has its own model.
It is also necessary to define which blocks exist and can be added to a page using the Universal Editor. The component-definitions.json
file lists the components as they are made available by the Universal Editor.
{
"title": "Hero",
"id": "hero",
"plugins": {
"xwalk": {
"page": {
"resourceType": "core/franklin/components/block/v1/block",
"template": {
"name": "Hero",
"model": "hero"
}
}
}
}
}
It is possible to use one model for many blocks. For example, some blocks may share a model that defines a text and image.
For each block, the developer:
- Must use the
core/franklin/components/block/v1/block
resource type, the generic implementation of the block logic in AEM. - Must define the block name, which will be rendered in the block’s table header.
- The block name is used to fetch the right style and script to decorate the block.
- Can define a model ID.
- The model ID is a reference to the component’s model, which defines the fields available to the author in the properties panel.
- Can define a filter ID.
- The filter ID is a reference to the component’s filter, which allows to change the authoring behavior, for example by limiting which children can be added to the block or section, or which RTE features are enabled.
All this information is stored in AEM when a block is added to a page. If either the resource type or block name are missing, the block will not render on the page.
Block Structure block-structure
The properties of blocks are defined in the component models and persisted as such in AEM. Properties are rendered as cells in the block’s table-like structure.
Simple Blocks simple
In the simplest form, a block renders each property in a single row/column in the order the properties are defined in the model.
In the following example, the image is defined first in the model and the text second. They are thus rendered with the image first and text second.
code language-json |
---|
|
code language-html |
---|
|
code language-text |
---|
|
You may notice that some types of values allow inferring semantics in the markup, and properties are combined into in single cells. This behavior is described in the section Type Inference.
Key-Value Block key-value
In many cases, it it recommended to decorate the rendered semantic markup, add CSS class names, add new nodes or move them around in the DOM, and apply styles.
In other cases however, the block is read as a key-value pair-like configuration.
An example of this is the section metadata. In this use case, the block can be configured to render as key-value pair table. Please see the section Sections and Section Metadata for more information.
code language-json |
---|
|
code language-html |
---|
|
code language-text |
---|
|
Container Blocks container
Both of the previous structures have a single dimension: the list of properties. Container blocks allow adding children (usually of the same type or model) and hence are two-dimensional. These blocks still support their own properties rendered as rows with a single column first. But they also allow adding children, for which each item is rendered as row and each property as column within that row.
In the following example, a block accepts a list of linked icons as children, where each linked icon has an image and a link. Notice the filter ID set in the data of the block in order to reference the filter configuration.
code language-json |
---|
|
code language-html |
---|
|
code language-text |
---|
|
Creating Semantic Content Models for Blocks creating-content-models
With the mechanics of block structure explained, it is possible to create a content model that maps content persisted in AEM one-to-one to the delivery tier.
Early in every project, a content model must be carefully considered for every block. It must be agnostic to the content source and authoring experience in order to allow authors to switch or combine them while reusing block implementations and styles. More details and general guidance can be found in David’s Model (take 2). More specifically, the block collection contains a extensive set of content models for specific use cases of common user interface patterns.
For WYSIWYG authoring with Edge Delivery Services, this raises the question how to serve a compelling semantic content model when the information is authored with forms composed of multiple fields instead of editing semantic markup in-context like rich text.
To solve this problem, there are three methods that facilitate creating a compelling content model:
Type Inference type-inference
For some values we can infer the semantic meaning from the values itself. Such values include:
- Images - If a reference to a resource in AEM is an asset with a MIME type starting with
image/
, the reference is rendered as<picture><img src="${reference}"></picture>
. - Links - If a reference exists in AEM and is not an image, or if the value starts with
https?://
or#
, the reference is rendered as<a href="${reference}">${reference}</a>
. - Rich Text - If a trimmed value starts with a paragraph (
p
,ul
,ol
,h1
-h6
, etc.), the value is rendered as rich text. - Class Names - The
classes
property is treated as block options and rendered in the table header for simple blocks, or as value list for items in a container block. It is useful if you wish to style a block differently, but don’t need to create an entirely new block. - Value Lists - If a value is a multi-value property and the first value is none of the previous, all values are concatenated as comma-separated list.
Everything else will be rendered as plain text.
Field Collapse field-collapse
Field collapse is the mechanism to combine multiple field values into a single semantic element based on a naming convention using the suffixes Title
, Type
, MimeType
, Alt
, and Text
(all case sensitive). Any property ending with any of those suffixes will not be considered a value, but rather as an attribute of another property.
Images image-collapse
code language-json |
---|
|
code language-html |
---|
|
code language-text |
---|
|
Links & Buttons links-buttons-collapse
code language-json |
---|
|
No linkType
, or linkType=default
code language-html |
---|
|
linkType=primary
code language-html |
---|
|
linkType=secondary
code language-html |
---|
|
code language-text |
---|
|
Headings headings-collapse
code language-json |
---|
|
code language-html |
---|
|
code language-text |
---|
|
Element Grouping element-grouping
While field collapse is about combining multiple properties into a single semantic element, element grouping is about concatenating multiple semantic elements into a single cell. This is particularly helpful for use cases where the author should be restricted in the type and number of elements that they can create.
For example, a teaser component may allow the author to only create a subtitle, title, and a single paragraph description combined with a maximum of two call-to-action buttons. Grouping these elements together yields a semantic markup that can be styled without further action.
Element grouping uses a naming convention, where the group name is separated from each property in the group by an underscore. Field collapse of the properties in a group works as previously described.
code language-json |
---|
|
code language-html |
---|
|
code language-text |
---|
|
Sections and Section Metadata sections-metadata
The same way a developer can define and model multiple blocks, they can define different sections.
The content model of Edge Delivery Services deliberately allows only a single level of nesting, which is any default content or block contained by a section. This means in order to have more complex visual components that can contain other components, they have to be modelled as sections and combined together using auto-blocking client side. Typical examples of this are tabs and collapsible sections like accordions.
A section can be defined in the same way as a block, but with the resource type of core/franklin/components/section/v1/section
. Sections can have a name and a filter ID, which are used by the Universal Editor only, as well as a model ID, which is used to render the section metadata. The model is in this way the model of the section metadata block, which will automatically be appended to a section as key-value block if it is not empty.
The model ID and filter ID of the default section is section
. It can be used to alter the behavior of the default section. The following example adds some styles and and a background image to the section metadata model.
{
"id": "section",
"fields": [
{
"component": "multiselect",
"name": "style",
"value": "",
"label": "Style",
"valueType": "string",
"options": [
{
"name": "Fade in Background",
"value": "fade-in"
},
{
"name": "Highlight",
"value": "highlight"
}
]
},
{
"component": "reference",
"valueType": "string",
"name": "background",
"label": "Image",
"multi": false
}
]
}
The following example defines a tab section, which can be used to create a tabs block by combining consecutive sections with a tab title data attribute into a tabs block during auto-blocking.
{
"title": "Tab",
"id": "tab",
"plugins": {
"xwalk": {
"page": {
"resourceType": "core/franklin/components/section/v1/section",
"template": {
"name": "Tab",
"model": "tab",
"filter": "section"
}
}
}
}
}
Page Metadata page-metadata
Documents can have a page metadata block, which is used to define which <meta>
elements are rendered in the <head>
of a page. The page properties of pages in AEM as a Cloud Service map to those that are available out-of-the-box for Edge Delivery Services, like title
, description
, keywords
, etc.
Before further exploring how to define your own metadata, please review the following documents to understand the concept of page metadata first.
It is also possible to define additional page metadata in two ways.
Metadata Spreadsheets metadata-spreadsheets
It is possible to define metadata on a per path or per path pattern basis in a table-like way in AEM as a Cloud Service. There is an authoring UI for table-like data available that is similar to Excel or Google Sheets.
For further details, please see the document Using Spreadsheets to Manage Tabular Data for more information.
Page Properties page-properties
Many of the default page properties available in AEM are mapped to the respective page metadata in a document. That includes for example title
, description
, robots
, canonical url
or keywords
. Some AEM-specific properties are available as well:
cq:lastModified
asmodified-time
in ISO8601 format- The time the document was last published as
published-time
in ISO8601 format cq:tags
ascq-tags
as a comma-separated list of the tag IDs.
It is also possible to define a component model for custom page metadata, which will be made available to the author in the Universal Editor.
To do so, create a component model with the ID page-metadata
.
{
"id": "page-metadata",
"fields": [
{
"component": "text",
"name": "theme",
"label": "Theme"
}
]
}
Next Steps next-steps
Now that you know how to model content, you can create blocks for your own Edge Delivery Services with WYSIWYG authoring project.
See the document Creating Blocks Instrumented for use with the Universal Editor to learn how to create blocks instrumented for use with the Universal Editor in WYSIWYG authoring with Edge Delivery Services projects.
If you are already familiar with creating blocks, please see the document Developer Getting Started Guide for WYSIWYG authoring with Edge Delivery Services to get you up-and-running with a new Adobe Experience Manager site using Edge Delivery Services and the Universal Editor for content authoring.