The Productive JSON Document Format represents rich text stored in Productive objects. It's very similar to [Atlassian Document Fromat (ADF)](https://developer.atlassian.com/cloud/jira/platform/apis/document/structure/).

It's currently being used in the following resources:

| Resource | Property |                                  Description                                   |
| -------- | -------- | ------------------------------------------------------------------------------ |
| `pages`  | `body`   | Productive Docs are represented by `pages` resource and it's `body` property is stored as Productive Document Format |


### JSON structure

<!-- A JSON schema is available to validate documents. This JSON schema is found at <link here>. -->

A document in Productive is a JSON object, composed of a hierarchy of nodes. There are two categories of nodes: block and inline. Block nodes define the structural elements of the document such as headings, paragraphs, lists, and alike. Inline nodes contain the document content such as text and images. Some of these nodes can take marks that define text formatting or embellishment such as centered, bold, italics, and alike.

A document is ordered, that is, there's a single sequential path through it: traversing a document in sequence and concatenating the nodes yields content in the correct order.

For example:

```
{
  "type": "doc",
  "content": [
    {
      "type": "paragraph",
      "content": [
        {
          "type": "text",
          "text": "Hello "
        },
        {
          "type": "text",
          "text": "world",
          "marks": [
            {
              "type": "strong"
            }
          ]
        }
      ]
    }
  ]
}
```

Result in the text "Hello **world**".

<br />

**Nodes**

Nodes have the following common properties:

| Property | Required |                                  Description                                   |
| -------- | -------- | ------------------------------------------------------------------------------ |
| type     | ✔        | Defines the type of block node such as `paragraph`, `table`, and alike.                       |
| content  |          | in block nodes, not applicable in inline nodes	An array contaning inline and block nodes that define the content of a section of the document. |

<br />

**Block nodes**

Block nodes can be subdivided into:

- the root `doc` node
- top level nodes, nodes that can be placed directly below the root node
- child nodes, nodes that have to be the child of a higher-level mode

Some top-level nodes can be used as child nodes. For example, the `paragraph` node can be used at the top level or embedded within a `list` or `table`.

<br />

**Root block node:**

```
{
  "type": "doc",
  "content": []
}
```

<br />

**Top-level block nodes:**

- paragraph
- blockquote
- heading
- ol
- ul
- checklist
- table
- divider
- banner

<!-- ADF top-level nodes not supported in Productive:
- codeBlock
- mediaGroup
- mediaSingle
- panel
- rule -->

<br />

**Child block nodes:**

- checklist_item
- table_row
- table_cell
- table_header
- li

<!-- ADF child block nodes not supported in Productive:

- media -->

<br />

**Inline nodes:**

- text
- image
- file
- mention
- br

<!-- ADF inline nodes not supported in Productive:

- emoji
- hardBreak
- inlineCard -->

<br />

**Marks**

Mark have the following properties:

| Property | Required |                                  Description                                   |
| -------- | -------- | ------------------------------------------------------------------------------ |
| type     | ✔        | Defines the type of mark such as code, link, and alike.                        |
| attrs    |          | Further information defining attributes of the mask such as the URL in a link. |


The marks types are:

- link
- em
- strike
- underline
- strong
- code
- discussion

<!-- ADF marks not supported in Productive:

- subsup
- textColor -->

### Node types

**Doc**

The `doc` node is the root container node representing a document.

```
{
  "type": "doc",
  "content": [
    {
      "type": "paragraph",
      "content": [
        {
          "type": "text",
          "text": "Hello world"
        }
      ]
    }
  ]
}
```

<br>

**Paragraph**

The `paragraph` node is a container for a block of formatted text delineated by a carriage return.
It's the equivalent of the HTML `<p>` tag. Paragraph is a top-level block node that can take any inline node as `content`.

```
{
  "type": "paragraph",
  "content": [
    {
      "type": "text",
      "text": "Hello world"
    }
  ]
}
```

<br>

**Quote**

The `blockquote` node is a container for quotes.

```
{
  "type": "blockquote",
  "content": [
    {
      "type": "text",
      "text": "Hello world"
    }
  ]
}
```

<br>

**Heading**

The `heading` represents a heading. Heading can have 3 levels.

```
{
  "type": "heading",
  "attrs": {
    "level": 1
  },
  "content": [
    {
      "type": "text",
      "text": "Hello world"
    }
  ]
}
```

<br>

**Ordered list**

The `ol` node is a container for ordered list. List node can only contain `li` (list item) child block nodes.

```
{
  "type": "ol",
  "content": [
    {
      "type": "li",
      "content": [
        {
          "type": "paragraph",
          "content": [
            {
              "type": "text",
              "text": "Hello world"
            }
          ]
        }
      ]
    }
  ]
}
```

<br>

**Unordered list**

The `ul` node is a container for unordered list. List node can only contain `li` (list item) child block nodes.

```
{
  "type": "ul",
  "content": [
    {
      "type": "li",
      "content": [
        {
          "type": "paragraph",
          "content": [
            {
              "type": "text",
              "text": "Hello world"
            }
          ]
        }
      ]
    }
  ]
}
```

<br>

**Checklist**

The `checklist` node is a container for list of checkbox items. `checklist` can only contain `checklist_item` child block nodes.

```
{
  "type": "checklist",
  "content": [
    {
      "type": "cheklist_item",
      "attrs": {
        "checked": true
      },
      "content": [
        {
          "type": "paragraph",
          "content": [
            {
              "type": "text",
              "text": "Hello world"
            }
          ]
        }
      ]
    }
  ]
}
```

<br>

**Table**

The `table` node is a container for a table. Table node can only contain `table_row` nodes, which can contain `table_cell` or `table_header` child block nodes.

```
{
  "type": "table",
  "content": [
    {
      "type": "table_row",
      "content": [
        {
          "type": "table_cell",
          "attrs": {
            "colspan": 1,
            "rowspan": 1,
            "colwidth": null
          },
          "content": [
            {
              "type": "paragraph"
            }
          ]
        },
        {
          "type": "table_cell",
          "attrs": {
            "colspan": 1,
            "rowspan": 1,
            "colwidth": null
          },
          "content": [
            {
              "type": "paragraph"
            }
          ]
        },
        {
          "type": "table_cell",
          "attrs": {
            "colspan": 1,
            "rowspan": 1,
            "colwidth": null
          },
          "content": [
            {
              "type": "paragraph"
            }
          ]
        }
      ]
    },
    {
      "type": "table_row",
      "content": [
        {
          "type": "table_cell",
          "attrs": {
            "colspan": 1,
            "rowspan": 1,
            "colwidth": null
          },
          "content": [
            {
              "type": "paragraph"
            }
          ]
        },
        {
          "type": "table_cell",
          "attrs": {
            "colspan": 1,
            "rowspan": 1,
            "colwidth": null
          },
          "content": [
            {
              "type": "paragraph"
            }
          ]
        },
        {
          "type": "table_cell",
          "attrs": {
            "colspan": 1,
            "rowspan": 1,
            "colwidth": null
          },
          "content": [
            {
              "type": "paragraph"
            }
          ]
        }
      ]
    }
  ]
}

```

<br>

**Divider**

The `divider` node is a divider between different blocks.

```
{
  "type": "divider"
}
```

<br>

**Banner**

The `banner` node is a banner-like block element with 4 different types. Supported types are - "warning", "success", "critical", "info".

```
{
  "type": "banner",
  "attrs": {
    "type": "warning"
  },
  "content": [
    {
      "type": "paragraph",
      "content": [
        {
          "type": "text",
          "text": "This is a banner"
        }
      ]
    }
  ]
}
```

<br>

**Text**

The `text` node is inline element that contains text and can have "marks" applied to it.

```
{
  "type": "text",
  "text": "hello",
  "marks": [
    {
      "type": "strong"
    }
  ]
}
```

<br>

**Image**

The `image` node represents an inline image and supports `src`, `alt`, `title` and `width` attrs.

```
{
  "type": "image",
  "attrs": {
    "src": "<url>",
    "alt": "some text",
    "title": "title.jpeg",
    "width": 100
  }
}
```

<br>

**File**

The `file` node is an inline node that represents a link to an uploaded file.

```
{
  "type": "file",
  "attrs": {
    "url": "<url>",
    "name": "file.html",
    "type": "xml"
  }
}
```

<br>

**Mention**

The `mention` node is an inline node that represents a reference to an object - person, task or a page. It behaves like a link and visually renders as a mention tag. Mention node supports these attrs:

- `id` -> the ID of the referencing object
- `type` -> type of the referencing object
- `label` -> the text inside of an mention tag
- `avatarUrl` -> URL of an avatar if the mention is person object

<br>

```
{
  "type": "mention",
  "attrs": {
    "id": "1",
    "type": "person",
    "label": "John Doe",
    "avatarUrl": "<url>"
  }
}
```

<br>

**Break**

The `br` node inserts a new line in a text string. It's the equivalent to a `<br/>` in HTML.

```
{
  "type": "doc",
  "content": [
    {
      "type": "paragraph",
      "content": [
        {
          "type": "text",
          "text": "Hello"
        },
        {
          "type": "br"
        },
        {
          "type": "text",
          "text": "world"
        }
      ]
    }
  ]
}
```

### Mark types

**Link**

The `link` mark sets a hyperlink. This mark applies to text nodes

```
{
  "type": "text",
  "text": "Productive",
  "marks": [
    {
      "type": "link",
      "attrs": {
        "href": "https://productive.io",
        "title": "Productive"
      }
    }
  ]
}
```

<br>

**Em**

The `em` mark sets italic styling. This mark applies to `text` nodes.

```
{
  "type": "text",
  "text": "Hello world",
  "marks": [
    {
      "type": "em"
    }
  ]
}
```

<br>

**Strike**

The `strike` mark sets strike-through styling. This mark applies to `text` nodes.

```
{
  "type": "text",
  "text": "Hello world",
  "marks": [
    {
      "type": "strike"
    }
  ]
}
```

<br>

**Underline**

The `underline` mark sets underline styling. This mark applies to text nodes.

```
{
  "type": "text",
  "text": "Hello world",
  "marks": [
    {
      "type": "underline"
    }
  ]
}
```

<br>

**Strong**

The `strong` mark sets strong styling. This mark applies to text nodes.

```
{
  "type": "text",
  "text": "Hello world",
  "marks": [
    {
      "type": "strong"
    }
  ]
}
```

<br>

**Code**

The `code` mark sets code styling. This mark applies to text nodes.

```
{
  "type": "text",
  "text": "Hello world",
  "marks": [
    {
      "type": "code"
    }
  ]
}
```

<br>

**Discussion**

The `discussion` mark highlights the text and links to a discussion feed. This mark applies to text nodes.

```
{
  "type": "text",
  "text": "world",
  "marks": [
    {
      "type": "discussion",
      "attrs": {
        "discussionId": "1",
        "resolvedId": ""
      }
    }
  ]
}
```
