Integrations

Markdown input format

Updated on 13 July 2026

Elium can import and export content as Markdown. This page is the reference for producing Markdown that Elium will import cleanly, whether you are pasting from another tool, migrating content in bulk, or generating it programmatically (for example from an AI model).

It is CommonMark plus a small set of widely-used extensions. Where Markdown has no notation for something, Elium leans on Markdown's own syntax as far as it goes and reaches for richer notation only for what is left over: a {% … %} directive to decorate a native block or to express a block Markdown cannot (callouts, collapsible sections), and canonical HTML as the ultimate, fully-precise form for everything else (files, galleries, embeds, linked-content boxes, rich tables and images).

How it works

Supported Markdown

Everything below is recognised. "Inline" means it lives inside a line of text; "block" means it occupies its own line(s).

FeatureYou writeKind
Bold**bold**inline
Italic*italic*inline
Strikethrough~~strike~~inline
Inline code`code`inline
Link[label](https://example.com)inline
Image![alt](https://example.com/pic.png)inline
Subscript / superscriptH~2~O / x^2^inline
Heading (1-3)# Title / ## Sectionblock
List- item / 1. itemblock
Task list- [ ] todo / - [x] doneblock
Blockquote> quoteblock
Fenced code```lang … ```block
Tablepipe tableblock
Horizontal rule---block
Footnotetext[^1] + [^1]: …block

Soft line breaks inside a paragraph are kept (a single newline becomes a line break). Bare URLs are not auto-linked. Wrap them in [label](url) to make a link.

The three forms

Everything you write lands on one of three rungs. Always take the highest one that can express what you need:

  1. Plain Markdown. If CommonMark can say it, say it in CommonMark: a heading is ## Title, a task is - [x] done, code is a fenced block. This is always the preferred form.

  2. A {% … %} directive. Two jobs only:

    • {% attrs %} decorates a native block with attributes Markdown can't carry (a heading's alignment or anchor, a paragraph's alignment). You still write the block in native Markdown inside it.

    • A named directive ({% callout %}, {% collapse %}) expresses a block that has no Markdown notation at all but is still authored as Markdown-bearing content.

  3. Canonical HTML. The most precise and complete form: a well-defined subset of HTML tags and attributes maps one-to-one onto every construct Elium supports. Real HTML tags (<table>, <img>, <blockquote>) plus el-* custom elements (<el-callout>, <el-asset>, <el-collapse>) for Elium blocks. Everything can be written this way, and a handful of rich blocks (files, galleries, linked-content boxes, rich tables and images) have only this form.

The directive form:

{% callout type="warning" %}
Content, written as normal Markdown.
{% endcallout %}
  • Options are space-separated name="value" pairs on the opening tag. Values may be quoted (title="A b"), bare if space-free (type=warning), or omitted to mean true (isTree). A missing boolean is false.

  • The body is Markdown and may nest other blocks.

  • Single-line form is allowed: {% callout %}Heads up.{% endcallout %}.

The {% attrs %} form wraps exactly one native block and pushes its options onto it:

{% attrs align="center" id="intro" %}
## A centred heading with an anchor
{% endattrs %}

Elium normalizes your input

Elium stores a single canonical form and re-emits it when it exports Markdown, so your Markdown does not come back byte-for-byte. It rewrites whatever you wrote to the highest rung that still expresses it:

  • a fenced code block keeps its language as the info-string token, and a source filename rides there as name="…";

  • a plain rectangular table stays a pipe table, but one with spans, colors, widths, or a heading column is re-emitted as an HTML <table>;

  • an aligned or anchored heading, and an aligned paragraph or task item, come back wrapped in {% attrs %};

  • an image with a style, link, or explicit size comes back as an HTML <img> (a plain inline image stays ![alt](url)).

Write whichever accepted form is convenient; expect the canonical form back.

What happens to the unrecognized

The format degrades predictably:

  • An unknown directive name ({% foo %}) stays as plain text. Only the directives listed on this page are recognized.

  • Inline HTML outside the recognized set (see Text & inline formatting) is left literal.

  • A {% … %} tag indented four or more spaces, or one sitting inside a list item, is ordinary text/code, not a directive.

  • Frontmatter is only the very first block and must be a valid YAML mapping; unrecognized keys are ignored.

At a glance

BlockPlain MarkdownAdd attributes with…Reach higher when…
Heading## Title{% attrs %}it needs alignment or an anchor id
Paragraphplain text{% attrs %}it needs alignment
List & task list- item / - [ ]{% attrs %} (task item)an aligned task item
Blockquote> quote--
Tablepipe tableHTML <table>it needs spans, colors, widths, or a heading column
Code```lang … ```fence info stringit has a title or filename
Callout-{% callout %}always
Collapse-{% collapse %}always
Image![alt](url)HTML <img>it needs style, link, or sizing
File-HTML <el-asset>always
Gallery-HTML <el-gallery>always
Embed```html type="embed" … ```-always
Linked content-HTML <el-space-box> / <el-story-box> / <el-user-box> / <el-drive-folder>always
Raw HTML```html type="html" … ```-always

Quick example

---
showHeadingNumbers: true
---

# What's new  We shipped a few things this week.

{% callout type="info" %}
See the [changelog](https://example.com/log) for the full list.
{% endcallout %}

## Highlights

- [x] Faster import
- [ ] Dark mode

```bash name="upgrade.sh"
npm install elium@latest
```

Document frontmatter

A document may begin with a YAML frontmatter block of story- and document-level metadata. It must be the very first block and a valid YAML mapping; unrecognized keys are ignored.

---
showHeadingNumbers: true
summarised: false
---

# First heading

Supported keys: showHeadingNumbers, summarized, toc, truncationResult.

Text & inline formatting

The foundational layer, shared by every block that holds text.

Plain CommonMark covers most of it: **bold**, *italic*, ~~strike~~, `code`, [link](url), and ![alt](url). Elium adds:

  • Subscript H~2~O and superscript x^2^.

  • Footnotes: a [^label] reference (inline) and a matching [^label]: … definition (Markdown) collected at the foot of the content:

Elium imports CommonMark[^cm] and a few extensions.

[^cm]: The standard Markdown specification.

When inline content needs semantics CommonMark cannot represent, Elium uses a constrained set of inline HTML, which the importer understands:

NeedMarkup
Underline<u>text</u>
Sub / sup<sub>2</sub> / <sup>2</sup>
Text / background color<span style="color: red">…</span> / <span style="background-color: yellow">…</span>
Tracked change (diff)<span data-diff="added">…</span> / <span data-diff="removed">…</span>
Mention<el-mention data-type="user" data-id="42" data-name="Jo"></el-mention>
Inline image with options<img src="…" width="700" height="316" data-mimetype="image/png">
Inline asset<el-asset-inline data-asset="2f1c8e44-…" data-type="file"></el-asset-inline>

A mention is the inline reference to a person, space, team, or story. It is an empty element: data-type is one of user, space, team, story, data-id is the entity id, and data-name carries the display name. Anything outside this recognized set stays as literal text.

Blocks

Every content block Elium supports, with its plain-Markdown form (where one exists) and how to reach the richer forms. See At a glance for the index.

Heading

Section titles, levels 1-3.

Syntax

  • Plain Markdown: ## Section title (the number of # sets the level).

  • {% attrs %} (when it needs alignment or an anchor id), wrapping the native heading:

    {% attrs align="center" id="intro" %}
    ## Centred title
    {% endattrs %}
    

Attributes (on {% attrs %})

OptionValuesDefault
aligncenter, right, justify, inheritleft
idanchor id-

Content Inline Markdown.

Paragraph

A run of inline text. Use {% attrs %} only to set an alignment.

Syntax

  • Plain Markdown: ordinary text separated by a blank line.

  • {% attrs %} (when aligned):

    {% attrs align="right" %}
    This paragraph is right-aligned.
    {% endattrs %}
    

Attributes (on {% attrs %})

OptionValuesDefault
aligncenter, right, justify, inheritleft

Content Inline Markdown.

List & task list

Bulleted, numbered, and checkable lists.

Syntax

- bullet
- with a
  - nested item

1. first
2. second

- [ ] todo
- [x] done

A list mixing checked items with plain items is split into separate lists on import. To align a single task item, wrap the native - [x] in {% attrs %}:

{% attrs align="center" %}
- [x] A centred task item
{% endattrs %}

Content Each item holds inline Markdown and nested lists. Headings or tables inside a list item are flattened to plain text.

Blockquote

Quoted text.

Syntax

> A quoted line.
> A second line.

Content Inline Markdown; multiple lines join with line breaks.

Table

A grid of cells. A plain rectangular table is a pipe table; anything richer falls back to canonical HTML.

Syntax

  • Plain Markdown: a CommonMark pipe table (escape a literal pipe in a cell as \|).

  • HTML fallback (column widths, cell spans, per-cell alignment/colors, a heading column, or block content in a cell): a raw <table>.

Options (HTML form)

ScopeOptions
tableheading row/column, width/height, column widths
cellcolspan, rowspan, align, valign, width/height, background color, border color, heading flag

Content Each cell holds Markdown.

Example

| Name     | Character |
| -------- | --------- |
| Backtick | `         |
| Pipe     | \|        |
<table data-column-widths="120,-">
<tr>
<td>

Plain

</td>
<td align="center">

**Centred**

</td>
</tr>
</table>

Code

A fenced block of code, optionally with a title or filename.

Syntax

  • Plain Markdown: a normal fenced block. The first bare word of the info string is the language; a name="…" attribute after it sets the title/filename.

Info-string options

OptionValuesDefault
languagea language id (the first bare token)plaintext
namesource title / filename-
languagea language id, when it contains spaces or `/=/"/~-

The language is normally the first bare token; the explicit language="…" attribute is only needed (and only emitted) when the language string cannot sit bare in the info line.

Content Literal. The body is kept verbatim, not reparsed as Markdown.

Example

```python
import re

def word_count(html: str) -> int:
    return max(len(re.sub(r"<[^>]+>", " ", html).split()), 1)
```
```python name="word_count.py"
import re

def word_count(html: str) -> int:
    return max(len(re.sub(r"<[^>]+>", " ", html).split()), 1)
```

Callout

A highlighted note or warning panel. Canonical HTML: <el-callout>.

Syntax

{% callout type="warning" %}
Be careful: this action cannot be undone.
{% endcallout %}

Options

OptionValuesDefault
typeinfo, warninginfo
aligncenter, right, justify, inheritleft

Content Inline Markdown.

Collapse

A collapsible section, built from sub-directives: a title, an optional set of navigation links, and a body. Canonical HTML: <el-collapse>.

Syntax

{% collapse id="faq" %}
{% collapse-title %}
## Frequently asked questions
{% endcollapse-title %}

{% collapsable %}
The body is normal Markdown and may contain any other blocks.
{% endcollapsable %}
{% endcollapse %}

Options (on {% collapse %})

OptionValuesDefault
idanchor id-
isTreebooleanfalse

Sub-directives

  • {% collapse-title %}: holds the title as a single heading or paragraph. Its level comes from the # heading you put inside (a paragraph means no heading level).

  • {% collapsable %}: holds the body blocks.

  • {% collapse-navigation to="…" label="…" %}{% endcollapse-navigation %}: an optional jump link to another section (to is the target id, label its text). It is empty and sits directly inside {% collapse %}:

    {% collapse id="q1" %}
    {% collapse-title %}
    ## Question 1
    {% endcollapse-title %}
    
    {% collapse-navigation to="q2" label="Next question" %}{% endcollapse-navigation %}
    
    {% collapsable %}
    The answer goes here.
    {% endcollapsable %}
    {% endcollapse %}
    

Image

Plain Markdown covers the simple inline case; canonical HTML carries layout, links, and sizing.

Syntax

  • Plain Markdown: ![alt](url) (an inline image with no options).

  • Canonical HTML (style, link, size, or a block-level image): an <img> element.

Options (HTML form)

AttributeMeaning
srcimage URL
altcaption / alt text
data-linkURL opened on click
data-stylealign-left, align-center, align-right, full-width, inline, banner
data-aligncenter, right, justify, inherit
width, heightdisplay size
data-width, data-heightintrinsic source size
data-mimetypeMIME type

Example

<img src="https://example.com/photo.png" alt="Sunset" data-style="full-width" width="1200" height="630">

File

A reference to a stored Elium asset, shown as a card or preview. Canonical HTML only: <el-asset>.

Syntax

<el-asset data-asset="2f1c8e44-…" data-type="file" data-display-mode="card">
</el-asset>

Options

AttributeMeaning
data-assetasset UUID
data-typeasset type (file, story, url, cloudfile, cloudfolder, drawing, user, email)
data-display-modecollapsed, expanded, card
data-stylealign-left, align-center, align-right, full-width, inline, banner
data-aligncenter, right, justify, inherit
data-linkURL opened on click
titlecaption / alt text
data-width, data-height, data-display-width, data-display-heightsize

A collection of assets laid out as a grid or list. Canonical HTML only: <el-gallery> holding <el-gallery-asset> items.

Syntax

<el-gallery title="Vacation" data-layout="gallery">
<el-gallery-asset data-asset="2f1c8e44-…" title="Itinerary"></el-gallery-asset>
<el-gallery-asset data-asset="7c41ab90-…"></el-gallery-asset>
</el-gallery>

Options

AttributeMeaning
titlegallery title
data-layoutgallery (grid), list

Each <el-gallery-asset> carries data-asset (the UUID) and an optional title (the caption).

Embed

Embedded external content (a player, a widget) expressed as HTML. A fenced code block whose info string is html type="embed".

Syntax

```html type="embed" height="420" scrolling="no"
<iframe src="https://example.com/player"></iframe>
```

Info-string options

OptionValuesDefault
heightsize-
scrollingauto, yes, no-

Content Literal HTML, kept verbatim.

Linked content

Block boxes that link to an Elium entity. Canonical HTML only. (For an inline person/space/story reference, use a mention instead.)

Syntax

<el-space-box data-id="9b2e-…"></el-space-box>
<el-story-box data-id="7c41-…"></el-story-box>
<el-user-box data-id="42"></el-user-box>
<el-drive-folder data-folder-id="1AbCdEf…"></el-drive-folder>

Options

BoxAttribute
<el-space-box> / <el-story-box> / <el-user-box>data-id
<el-drive-folder>data-folder-id

Raw HTML

The escape hatch: arbitrary HTML for anything with no richer Elium block above. A fenced code block whose info string is html type="html".

Syntax

```html type="html"
\<section class="hero">Raw HTML content\</section>
```

Content Literal HTML, kept verbatim.

Trying it out: the rich playground

The rich playground at /_debug/rich/playground shows exactly how a piece of content is interpreted before you commit to it.

You give it:

  • an input format: Markdown (vanilla CommonMark), Elium Markdown (CommonMark plus the {% … %} directives and frontmatter on this page), Canonical Elium HTML, or Slate;

  • a target: Story, Comment, Template, or Smart feed. The target narrows which blocks are allowed (for example a comment drops galleries, a story drops template placeholders), so the same input can interpret differently per target.

It then lists any interpretation errors and warnings (blocks dropped, values defaulted, content normalised), and shows the result three ways: the rendered HTML, the raw canonical HTML text it maps to, and the Markdown it re-renders to. Comparing the input against that round-tripped Markdown is the quickest way to see what Elium's normalisation did to your content.