The Block Editor field, and all the content created within it, is stored as JSON data. For example, if your Block Editor content consisted of the message “Hello World” in a single paragraph block, its field object would look like this:
{
"type": "doc",
"attrs":
{
"charCount": 11,
"wordCount": 2,
"readingTime": 1
},
"content": [
{
"type": "paragraph",
"content": [
{
"type": "text",
"marks": [
{
"type": "bold"
}
],
"text": "Hello"
},
{
"type": "text",
"text": " World"
}
]
}
]
}
Understanding the JSON schema that yielded this example can be useful for validation, headless operation, and still other applications.
Block Editor Objects
Block objects have a few core properties. Each block possesses a type
, at the very least, but also usually one or more of the others on this table:
Property | Value |
---|---|
type | A string consisting of the name of the block (all blocks possess this property) |
attrs | An object containing properties that define the block's presentation |
content | An array of objects expressing the block's user-defined content |
marks | An array of objects containing formatting instructions for text content (only text objects possess this property) |
text | A content string (only text objects possess this property) |
Most blocks, for example, have both attrs
(attributes) and content
.
The content
property may contain in its array additional nested block objects, objects of the special text
type, or countless possible combinations thereof.
Any property without a distinct value may be safely omitted. For example, a paragraph block left blank will not possess a content
property, and unformatted text will not have marks
.
Document
A Block Editor Field always begins with an object whose type
is doc
, representing the whole field's content.
The associated attrs
consist of an object with three properties. All three correspond to the field's count bar feature, and all three take integers for their value:
Property | Value |
---|---|
charCount | The number of characters in the field's text content |
wordCount | The number of words in the field's text content |
readingTime | An estimate of the time needed to read the content |
The content
property of the document object holds all of the field's block objects in sequence.
Text
An object with type
equal to text
specifies a section of user-composed text. Instead of attrs
or content
, Text objects possess two unique properties called marks
and text
, which function in an analogous fashion — the first contains objects that define formatting, and the second contains a string of text content.
The marks
property accepts an array of one or more simple objects, each containing only a type
property with one of the following values:
Type | Result |
---|---|
bold | sample text |
italic | sample text |
underline | sample text |
strike | |
superscript | samplesuperscripttext |
subscript | samplesubscripttext |
A text object using several of these might appear as follows:
{
"type": "text",
"marks": [
{"type":"underline"},
{"type":"bold"},
{"type":"italic"},
{"type":"strike"}
],
"text":"Hello World!"
}
And would render as:
Hello World!
Paragraph
Blocks with the type paragraph
are the simplest block, and also the Block Editor's default.
A paragraph block's only attrs
property is textAlign
, which corresponds to the CSS property of the same name. The paragraph block uses text objects in its content array.
{
"type": "paragraph",
"attrs": {
"textAlign": "left"
},
"content": [
{
"type": "text",
"text": "this is a paragraph block"
}
]
}
Headings
The heading
type uses text content, as the paragraph block, but exposes two attrs
properties: textAlign
and level
. The integer value of level
specifies the corresponding HTML heading — e.g., 2
is the equivalent of <h2>
.
{
"type": "heading",
"attrs": {
"textAlign": "left",
"level": 2
},
"content": [
{
"type": "text",
"text": "this is a heading 2 block"
}
]
}
Lists
There are three type
values associated with list blocks.
Type | Description |
---|---|
orderedList | An ordered list, similar to <ol> |
bulletList | An unordered list, similar to <ul> |
listItem | An individual entry in either type of list, similar to <li> |
All three block types have access to the textAlign
property in the attributes object; the ordered list also has the start
property, which takes as its value an integer indicating the first listed value.
Ordered and bullet lists use an array of list items as content, while list items may use other kinds of blocks, in turn, for its own content — including paragraphs, or even ordered or bullet list blocks, allowing nested lists.
{
"type": "orderedList",
"attrs": {
"start": 1,
"textAlign": "left"
},
"content": [
{
"type": "listItem",
"attrs": {
"textAlign": "left"
},
"content": [
{
"type": "paragraph",
"attrs": {
"textAlign": "left"
},
"content": [
{
"type": "text",
"text": "behold! an ordered list!"
}
]
}
]
}
]
|
Block Quotes
The blockquote
-type object functions similarly to the HTML tag of the same name. It can use the textAlign
attribute property, and typically contains a paragraph block as content.
{
"type": "blockquote",
"attrs": {
"textAlign": "left"
},
"content": [
{
"type": "paragraph",
"attrs": {
"textAlign": "left"
},
"content": [
{
"type": "text",
"text": "This is the line we have chosen as our quote."
}
]
}
]
}
Code
The codeBlock
object exposes the attribute property language
, which takes as value an integer corresponding to a dotCMS language ID. Its value is typically a plain and unformatted text object. Because of the difference in the interface's handling, special characters like newlines can be added more easily; in a code block, use Shift+Enter
to proceed to the next block, as you would with just Enter
on a paragraph block.
{
"type": "codeBlock",
"attrs": {
"language": null
},
"content": [
{
"type": "text",
"text": "code block here\n"
}
]
}
Table Blocks
Tables encompass four distinct type
values.
Type | Description |
---|---|
table | The parent object, as with <table> |
tableRow | A table row, similar to <tr> |
tableHeader | A table heading cell, as with <th> , generally within the first row |
tableCell | An individual cell within a row, similar to <td> |
Tables and table rows can invoke no attribute properties. However, both headers and cells have three attr
properties of note:
Property | Description |
---|---|
colspan | The number of columns the element is intended to span |
rowspan | The number of rows the element is intended to span |
colwidth | Defines the width of the column in pixels, percent, etc. |
Similar to the HTML table structure, a table takes as its content an array of table rows, and a table row uses an array of either table headers or table cells.
{
"type": "table",
"content": [
{
"type": "tableRow",
"content": [
{
"type": "tableHeader",
"attrs": {
"colspan": 1,
"rowspan": 1,
"colwidth": null
},
"content": [
{
"type": "paragraph",
"attrs": {
"textAlign": "left"
},
"content": [
{
"type": "text",
"text": "table heading cell 1"
}
]
}
]
}
]
},
{
"type": "tableRow",
"content": [
{
"type": "tableCell",
"attrs": {
"colspan": 1,
"rowspan": 1,
"colwidth": null
},
"content": [
{
"type": "paragraph",
"attrs": {
"textAlign": "left"
},
"content": [
{
"type": "text",
"text": "row 1 cell 1"
}
]
}
]
}
]
}
]
}
Images
Image blocks have a type
property with the value dotImage
, and the following attribute properties.
Attribute | Data Type | Description |
---|---|---|
textAlign | string | Text-align CSS property assigned by default to an enclosing div around the image |
src | string | The address of the image |
alt | string | Alt text for the image |
title | string | Image tag's title attribute |
href | string | Address the image should link to, if activated |
data | object | Contains the full set of metadata associated with the image's dotAsset, as though accessed via the content object |
Image blocks — along with video blocks and contentlet blocks — distinguish themselves by having no content
property; the content in this case is a file referenced through its attributes.
{
"type": "dotImage",
"attrs": {
"textAlign": "left",
"src": "/dA/1acf2998-b36d-4dd7-bb73-06ce2531ee09/asset/shark-feeding.jpeg",
"alt": "shark-feeding.jpeg",
"title": "shark-feeding.jpeg",
"href": null,
"data": {
"hostName": "demo.dotcms.com",
"modDate": "2022-04-12 20:18:32.787",
"extension": "jpeg",
"publishDate": "2022-04-12 20:18:32.787",
"assetContentAsset": "1acf2998-b36d-4dd7-bb73-06ce2531ee09/asset",
"mimeType": "image/jpeg",
"title": "shark-feeding.jpeg",
"type": "dotasset",
"baseType": "DOTASSET",
"inode": "7f71124d-8dd8-4081-b6a0-eb036464e940",
"archived": false,
"path": "/content.7f71124d-8dd8-4081-b6a0-eb036464e940",
"host": "48190c8c-42c4-46af-8d1a-0cd5db894797",
"working": true,
"variantId": "DEFAULT",
"locked": false,
"stInode": "657897dfb36ef211ebfb4128de818787",
"contentType": "PDF",
"live": true,
"owner": "dotcms.org.1",
"identifier": "1acf2998-b36d-4dd7-bb73-06ce2531ee09",
"isContentlet": true,
"languageId": 1,
"__icon__": "jpegIcon",
"statusIcons": "<span class='greyDotIcon' style='opacity:.4'><\/span><span class='liveIcon'><\/span>",
"url": "/content.7f71124d-8dd8-4081-b6a0-eb036464e940",
"titleImage": "asset",
"modUserName": "Admin User",
"hasLiveVersion": true,
"folder": "SYSTEM_FOLDER",
"size": 98885,
"hasTitleImage": true,
"sortOrder": 0,
"modUser": "dotcms.org.1",
"assetVersion": "/dA/7f71124d-8dd8-4081-b6a0-eb036464e940/asset/shark-feeding.jpeg",
"name": "shark-feeding.jpeg",
"assetMetaData": {
"modDate": 1685620932314,
"sha256": "03fc29afd486f484b22d5b19408d61bde01314d5164f36f02bacb0d140780065",
"length": 98885,
"title": "shark-feeding.jpeg",
"version": 20220201,
"isImage": true,
"fileSize": 98885,
"name": "shark-feeding.jpeg",
"width": 780,
"contentType": "image/jpeg",
"height": 413
},
"asset": "/dA/1acf2998-b36d-4dd7-bb73-06ce2531ee09/asset/shark-feeding.jpeg",
"contentTypeIcon": "picture_as_pdf",
"language": "en-US"
}
}
}
Videos
There are two block types that support video: dotVideo
and youtube
.
As with image blocks, above, neither of these two block types has a content
property; both refer to file content via their attributes.
dotVideo Block
The dotVideo Block has six attribute properties of note.
Attribute | Data Type | Description |
---|---|---|
src | string | The address of the video |
mimeType | string | The MIME type of the file |
width | integer | Video width in pixels |
height | integer | Video height in pixels |
orientation | string | Specify horizontal or vertical |
data | object | Contains the full set of metadata associated with the video's dotAsset, as though accessed via the content object |
This block is ideal for uploading videos to your site, or making use of videos already stored as dotAssets.
{
"type": "dotVideo",
"attrs": {
"src": "/dA/3f6ba3f29edc30313a922179fa43acd5/asset/sample.mp4",
"mimeType": "application/mp4",
"width": 3840,
"height": 2160,
"orientation": "horizontal",
"data": {
"AUTO_ASSIGN_WORKFLOW": false,
"__icon__": "mp4Icon",
"archived": false,
"asset": "/dA/3f6ba3f29edc30313a922179fa43acd5/asset/sample.mp4",
"assetContentAsset": "3f6ba3f29edc30313a922179fa43acd5/asset",
"assetMetaData": {
"contentType": "application/mp4",
"fileSize": 158490586,
"height": 2160,
"isImage": false,
"length": 158490586,
"modDate": 1680287148719,
"name": "sample.mp4",
"sha256": "52572f71395b62a12dd1527f3fea2ae183ce5f67fdb0bcaf7d09b354a14dbd00",
"title": "sample.mp4",
"version": 20220201,
"width": 3840
},
"assetVersion": "/dA/412ba697-e4cf-4ec7-90ac-2cbdd878a1ea/asset/sample.mp4",
"baseType": "DOTASSET",
"contentType": "dotAsset",
"extension": "mp4",
"folder": "SYSTEM_FOLDER",
"hasLiveVersion": true,
"hasTitleImage": false,
"host": "SYSTEM_HOST",
"hostName": "System Host",
"identifier": "3f6ba3f29edc30313a922179fa43acd5",
"inode": "412ba697-e4cf-4ec7-90ac-2cbdd878a1ea",
"isContentlet": true,
"languageId": 1,
"live": true,
"locked": false,
"mimeType": "video/mp4",
"modDate": 1680287148926,
"modUser": "dotcms.org.1",
"modUserName": "Admin User",
"name": "sample.mp4",
"owner": "dotcms.org.1",
"path": "/content.412ba697-e4cf-4ec7-90ac-2cbdd878a1ea",
"publishDate": 1680287148926,
"size": 158490586,
"sortOrder": 0,
"stInode": "f2d8a1c7-2b77-2081-bcf1-b5348988c08d",
"statusIcons": "<span class='greyDotIcon' style='opacity:.4'></span><span class='liveIcon'></span>",
"title": "sample.mp4",
"titleImage": "TITLE_IMAGE_NOT_FOUND",
"type": "dotasset",
"url": "/content.412ba697-e4cf-4ec7-90ac-2cbdd878a1ea",
"variantId": "DEFAULT",
"working": true
}
}
}
YouTube Block
The YouTube block, designed to simplify embedding videos from YouTube, has four attribute properties.
Attribute | Data Type | Description |
---|---|---|
src | string | The address of the linked video |
start | integer | The starting position of the video in seconds |
width | integer | Video width in pixels |
height | integer | Video height in pixels |
And indeed, its data consists of little else:
{
"type": "youtube",
"attrs": {
"src": "https://www.youtube.com/watch?v=u5Lx1UZfCK8",
"start": 0,
"width": 400,
"height": 300
}
}
Contentlet Blocks
The Contentlet block, which uses the type
property value dotContent
, allows you to embed structured content developed in dotCMS into the Block Editor. It has only one attribute property: data
. Its value is an object that includes content object metadata.
{
"type": "dotContent",
"attrs": {
"data": {
"hostName": "demo.dotcms.com",
"modDate": "2020-09-02 16:45:53.787",
"publishDate": "2020-09-02 16:45:53.787",
"title": "French Alps",
"body": "<h2>SKIING IN THE FRENCH ALPS<\/h2>\n<p>Noted for being a significant source of skiing, the French Alps are...<\/p>",
"baseType": "CONTENT",
"inode": "919d6bf4-a712-43cf-9cc2-d69d384d8392",
"archived": false,
"host": "48190c8c-42c4-46af-8d1a-0cd5db894797",
"working": true,
"variantId": "DEFAULT",
"locked": false,
"stInode": "2a3e91e4-fbbf-4876-8c5b-2233c1739b05",
"contentType": "webPageContent",
"live": true,
"owner": "dotcms.org.1",
"identifier": "0e773815-26da-4098-9343-214fb301bafd",
"languageId": 1,
"url": "/content.ef67af58-c36b-4127-afb6-03928ad41673",
"titleImage": "TITLE_IMAGE_NOT_FOUND",
"modUserName": "Admin User",
"hasLiveVersion": true,
"folder": "SYSTEM_FOLDER",
"hasTitleImage": false,
"sortOrder": 0,
"modUser": "dotcms.org.1",
"__icon__": "contentIcon",
"contentTypeIcon": "wysiwyg",
"language": "en-US"
}
}
}
Horizontal Line
The horizontal line has only a type
property.
{
"type": "horizontalRule"
}