Pluma
Docs index
docs/reference/rich-text.md View markdown →

Rich text

rich_text fields are stored as JSON blocks, not HTML. That way the content doesn't depend on any framework: the API also delivers it converted to markdown and to HTML.

In the dashboard you write in markdown. Through the API (phase 3) you send JSON or markdown.

Document

{
  "type": "doc",
  "content": [
    { "type": "heading", "level": 2, "content": [ { "type": "text", "text": "Open House" } ] },
    { "type": "paragraph", "content": [
      { "type": "text", "text": "A " },
      { "type": "text", "text": "great", "marks": ["bold"] },
      { "type": "text", "text": " day. " },
      { "type": "link", "href": "https://acton.example", "content": [ { "type": "text", "text": "Sign up" } ] }
    ] }
  ]
}

Blocks

type Fields Markdown
paragraph content: inline A paragraph
heading level (1 to 6), content: inline ## Title
list ordered (bool), content: items { "type": "item", "content": [blocks] } - one or 1. one
quote content: blocks > quote
code text, language (optional) Block with three backticks
hr — ---
image asset (ID of a Pluma asset) or src (external URL), and alt ![alt](asset:ID) or ![alt](https://…) in its own paragraph
table content: rows { "type": "row", "content": [ { "type": "cell", "content": [inline] } ] }. The first row is the header GitHub table: | A | B | and the line | --- | --- |

Inline

type Fields Markdown
text text, marks (optional): bold, italic, code, strike **bold**, *italic*, `code`, ~~strikethrough~~
link href, or entry (ID of another entry, see Links to entries); content: inline [text](url) or [text](entry:ID)
break — Two spaces at the end of the line

To link to another entry of your site, write [text](entry:12): it's stored as { "type": "link", "entry": "12", … }, a link to that entry, not to its address today.

  • Reading with rich_text=markdown or html, it comes out as the entry's path on your site, from its type's page URL: [seeded rye](/menu/rye-seeded). Change the slug and every link follows it, without editing the posts.
  • If the type has no page URL, or the entry isn't published (with a delivery key), the link stays entry:12 in markdown and becomes # in HTML.
  • Publishing checks every entry link: the target has to exist and be published, or you get validation_failed with links to entry:12, which isn't published yet. Publish the target first (in a batch, put its publish_entry earlier).

Rules

  • Markdown → blocks → markdown gives the same document (lossless round trip).
  • When reading with rich_text=markdown or rich_text=html, Pluma images come out with their real URL, ready for your site. With rich_text=json they stay as "asset": "ID" and the URL is in includes (with include=1).
  • HTML comes out escaped. Links that don't start with http, https, mailto, / or # are replaced with #: no javascript:.
  • Raw HTML inside the markdown (<u>, <div>) is stored as text, not interpreted. If your content needs HTML, store it in a text field with the markdown as is and render it on your site.
  • Table column alignment (:---:) is not stored.