👋 Next.js Conf 2024: Come build, party, run, and connect with us! See all events

Discussion comparing Delta and Portable Text formats for storing rich text

4 replies
Last updated: Oct 1, 2021
I've been looking into sanity recently and was wondering what people's thoughts were on portable text. I've used quill before, and after a few hours of research and thought, I still feel like quill's delta is easier to understand and serialize over portable text. Has anyone else researched this and/or have input?
Sep 30, 2021, 1:56 AM
To clarify, I am not focusing so much on the quill's implementation of deltas or sanity's implementation of portable text. Instead, I am talking about the medium of storing rich text as a whole.
Sep 30, 2021, 3:09 AM
I've given a brief example of both formats that depicts custom blocks and custom inline text along with plain and formatted text.
Delta:

{ 
  ops: [
    {
      insert: "text",
      attributes: { 
       bold: true 
      }
    },
    {
      insert: " and more text\n..."
    },
    {
      insert: "and still more",
      attributes: {
        link: "<https://somelink.com|https://somelink.com>",
        target: "_blank"
      }
    },
    {
      insert: "\n",
      attributes: {
        paragraph: true
      }
    },
    {
      insert: {
        image: "<https://imagelink.com|https://imagelink.com>"
      },
      attributes: {
        b: true,
        c: 100,
        d: "data"
      }
    }
  ]
}
Portable Text:

[
  {
    _type: "block",
    style: "normal",
    children: [
      {
        _type: "span",
        text: "text",
        marks: ["bold"]
      },
      {
        _type: "span",
        text: " and more text\n...",
        marks: []
      },
      {
        _type: "span",
        text: "and still more",
        marks: ["random1"]
      }
    ],
    markDefs: [
      {
        _key: "random1",
        _type: "link",
        href: "<https://somelink.com|https://somelink.com>",
        target: "_blank"
      }
    ]
  },
  {
    _type: "image",
    src: "<https://imagelink.com|https://imagelink.com>",
    b: true,
    c: 100,
    d: "data"
  }
]
As you can see, deltas seem to have the advantage when it comes to the availability of attributes. However, portable text does do a better job of handling block styles (it is much easier to enforce block styles when a block must exist for children to be attached, whereas a new line could easily be forgotten).

I do wonder if there is a way to combine the benefits of both specs, though I think there is certainly something to be said about the readability and parseability of deltas as compared to portable text. The fact that it is one dimensional as compared to the two dimensions created by block-children pairs helps.
Sep 30, 2021, 3:25 AM
I've worked with prosemirror before and found it slightly easier to read and serialise than portable text. Here's a sample:
{
  "type": "doc",
  "content": [
    {
      "type": "paragraph",
      "content": [
        {
          "type": "text",
          "text": "This is the "
        },
        {
          "type": "text",
          "marks": [
            {
              "type": "strong"
            }
          ],
          "text": "first"
        },
        {
          "type": "text",
          "text": " sentence in the "
        },
        {
          "type": "text",
          "marks": [
            {
              "type": "em"
            }
          ],
          "text": "first"
        },
        {
          "type": "text",
          "text": " paragraph."
        }
      ]
    },
    {
      "type": "paragraph",
      "content": [
        {
          "type": "text",
          "text": "This is the second paragraph."
        }
      ]
    }
  ]
}
To me one of the main issues i've encountered with serialising portable text is the inconsistencies in storing
marks
and
markDefs
. I don't see the benefit of storing "default" marks as strings, and "custom" marks as references to an array in an outer scope. The inconsistency here is that what portable text defines as "default marks" are specific semantic references to html, and require special handling when working with custom serialisers. There's a similar issue opened here on the nomenclature of styles , which also heavily relies on references to html, all of which doesn't align with the goal of creating an "agnostic abstraction of rich text". Prosemirror's document model is more consistent in the sense that all marks are stored as objects with a type key without any reference to a specific implementation, because ideally the format could be used in a context where HTML is not used at all. Lastly, the fact that the spec has not been revised in almost 4 years is also something to consider when comparing different formats.
Oct 1, 2021, 4:01 PM
Lastly, the fact that the spec has not been revised in almost 4 years is also something to consider when comparing different formats.
We’re working on it!
Oct 1, 2021, 5:05 PM

Sanity– build remarkable experiences at scale

Sanity is a modern headless CMS that treats content as data to power your digital business. Free to get started, and pay-as-you-go on all plans.

Was this answer helpful?