logo
GitHub

Data Structure

Data structure refers to how data is represented in software.

Data structures are programming language-agnostic, which is highly beneficial for data exchange between different programming languages.

Node

The data structure in JuiceEditor is primarily composed of Nodes. A Node is the most fundamental data structure in JuiceEditor, and all content is made up of Nodes.

Definition

Node is a programming language-agnostic data structure. For clarity, we’ll define it using TypeScript.

interface Node {
  type: string;
  html?: string;
  text?: string;
  attrs?: Record<string, any>;
  content?: Node[];
}

A Node is an object that contains the following properties:

  • type: Node type
  • html: HTML string corresponding to the node
  • text: Text string corresponding to the node
  • attrs: Attributes corresponding to the node
  • content: Child nodes contained within the node

Node Types

JuiceEditor has many node types, and more may be added. The main ones are:

  • root: Root node, contains all other nodes
  • text: Text node, the most basic node type, has no child nodes
  • paragraph: Paragraph node, contains text nodes
  • heading: Heading node, contains text nodes
  • list: List node
  • quote: Quote node

HTML

Only the root node has the html property; other nodes do not.

For example:

const node: Node = {
  type: 'root',
  html: '<div data-type="root"><h1>Hello, world!</h1><p>This is a paragraph.</p></div>',
};

HTML stores all document data and can be converted to and from a Root node.

The above example converted to a Root node becomes:

{
  type: 'root',
  content: [
    {
        type: 'heading',
        attrs: { level: 1 },
        content: [{ type: 'text', text: 'Hello, world!' }]
    },
    {
        type: 'paragraph',
        content: [{ type: 'text', text: 'This is a paragraph.' }]
    }
  ]
};

When storing this data in a database, sometimes it needs to be flattened into an array of Nodes.

const nodes: Node[] = [
  { type: 'root' },
  { type: 'heading', attrs: { level: 1 } },
  { type: 'text', text: 'Hello, world!' },
  { type: 'paragraph' },
  { type: 'text', text: 'This is a paragraph.' },
];

In the database, it appears as multiple rows:

idtypetextparent_id
1rootnullnull
2headingnull1
3text’Hello, world!‘2
4paragraphnull1
5text’This is a paragraph.‘4

Data

EditorData contains all the data in the editor.

Definition

EditorData is a programming language-agnostic data structure. For clarity, we’ll define it using TypeScript.

interface EditorData {
  title: string;
  html: string;
  node: Node;
  wordCount: number;
  characterCount: number;
}

EditorData is an object that contains the following properties:

  • title: Document title
  • html: Document HTML string
  • node: Document node object, an alternative representation of the HTML
  • wordCount: Number of words in the document
  • characterCount: Number of characters in the document

When document content changes, JuiceEditor automatically updates the data in EditorData and passes it externally.

Example

const editorData: EditorData = {
  title: 'Hello, world!',
  html: '<div data-type="root"><h1>Hello, world!</h1><p>This is a paragraph.</p></div>',
  node: {
    type: 'root',
    content: [
      {
        type: 'heading',
        attrs: { level: 1 },
        content: [{ type: 'text', text: 'Hello, world!' }],
      },
      {
        type: 'paragraph',
        content: [{ type: 'text', text: 'This is a paragraph.' }],
      },
    ],
  },
  wordCount: 1,
  characterCount: 1,
};