Document Structure
Learn how documents (the content of the rich text editor) are structured to make the most out of BlockNote.
Blocks
Each BlockNote document is made up of a list of blocks. A block is a piece of content like a paragraph, heading, list item or image. Blocks can be dragged around by users in the editor. A block contains a piece of content and optionally nested (child) blocks:
Block Objects
The Block
type is used to describe any given block in the editor:
type Block = {
id: string;
type: string;
props: Record<string, boolean | number | string>;
content: InlineContent[] | TableContent | undefined;
children: Block[];
};
id:
The block's ID. Multiple blocks cannot share a single ID, and a block will keep the same ID from when it's created until it's removed.
type:
The block's type, such as a paragraph, heading, or list item. For an overview of built-in block types, see Default Blocks.
props:
The block's properties, which is a set of key/value pairs that further specify how the block looks and behaves. Different block types have different props - see Default Blocks for more.
content:
The block's rich text content, usually represented as an array of InlineContent
objects. This does not include content from any nested blocks. Read on to Inline Content for more on this.
children:
Any blocks nested inside the block. The nested blocks are also represented using Block
objects.
Editor Content in JSON
The demo below shows the editor contents (document) in JSON. It's basically an array of Block
objects that updates as you type in the editor:
import { Block } from "@blocknote/core";
import { BlockNoteView, useCreateBlockNote } from "@blocknote/react";
import "@blocknote/react/style.css";
import { useState } from "react";
export default function App() {
// Stores the editor's contents (document) as an array of Block objects.
const [blocks, setBlocks] = useState<Block[]>([]);
// Creates a new editor instance.
const editor = useCreateBlockNote({
initialContent: [
{
type: "paragraph",
content: "Welcome to this demo!",
},
{
type: "heading",
content: "This is a heading block",
},
{
type: "paragraph",
content: "This is a paragraph block",
},
{
type: "paragraph",
},
],
});
// Renders the editor instance and its contents, as an array of Block
// objects, below.
return (
<div>
<BlockNoteView
editor={editor}
onChange={() => {
// Get the editor content (document) and store on the state.
setBlocks(editor.document);
}}
/>
<p>Document JSON:</p>
<pre>{JSON.stringify(blocks, null, 2)}</pre>
</div>
);
}
Inline Content
The content
field of a block contains the rich-text content of a block. This is defined as an array of InlineContent
objects. Inline content can either be styled text or a link (or a custom inline content type if you customize the editor schema).
Inline Content Objects
The InlineContent
type is used to describe a piece of inline content:
type Link = {
type: "link";
content: StyledText[];
href: string;
};
type StyledText = {
type: "text";
text: string;
styles: Styles;
};
type InlineContent = Link | StyledText;
The styles
property is explained below.
Other types of Block Content
While most blocks use an array of InlineContent
objects to describe their content (e.g.: paragraphs, headings, list items). Some blocks, like images, don't contain any rich text content, so their content
fields will be undefined
.
Tables are also different, as they contain TableContent
. Here, each table cell is represented as an array of InlineContent
objects:
type TableContent = {
type: "tableContent";
rows: {
cells: InlineContent[][];
}[];
};
Styles and rich text
The styles
property of StyledText
objects is used to describe the rich text styles (e.g.: bold, italic, color) or other attributes of a piece of text. It's a set of key / value pairs that specify the styles applied to the text.
See the Default Schema to learn which styles are included in BlockNote by default.
Demo: Block Content
In the demo below, you can explore how the block content and styles are represented in JSON by outputting only the content
field of each top level block.
import {
DefaultInlineContentSchema,
DefaultStyleSchema,
InlineContent,
TableContent,
} from "@blocknote/core";
import { BlockNoteView, useCreateBlockNote } from "@blocknote/react";
import "@blocknote/react/style.css";
import { useState } from "react";
export default function App() {
// Stores the editor's contents as an array of Block objects.
// TODO: InlineContent and TableContent should have default type args
const [inlineContent, setInlineContent] = useState<
(
| InlineContent<DefaultInlineContentSchema, DefaultStyleSchema>[]
| TableContent<DefaultInlineContentSchema, DefaultStyleSchema>
| undefined
)[]
>([]);
// Creates a new editor instance.
const editor = useCreateBlockNote({
initialContent: [
{
type: "paragraph",
content: "Welcome to this demo!",
},
{
type: "paragraph",
content: [
{
type: "text",
text: "Hello ",
styles: {},
},
{
type: "text",
text: "there, ",
styles: {
bold: true,
},
},
{
type: "link",
content: "BlockNote",
href: "https://www.blocknotejs.org",
},
],
},
{
type: "paragraph",
},
],
});
// Renders the editor instance and the contents of its blocks below.
return (
<div>
<BlockNoteView
editor={editor}
onChange={() => {
// Converts the editor's contents to an array with each top level
// block's content.
setInlineContent(editor.document.map((block) => block.content));
}}
/>
<p>Document JSON:</p>
<pre>{JSON.stringify(inlineContent, null, 2)}</pre>
</div>
);
}