Skip to main content

Markdown input format

Elium reads and writes 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 recognized. "Inline" means it lives inside a line of text; "block" means it occupies its own line(s).

Feature

You write

Kind

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 / superscript

H~2~O / x^2^

inline

Heading (1-3)

# Title / ## Section

block

List

- item / 1. item

block

Task list

- [ ] todo / - [x] done

block

Blockquote

> quote

block

Fenced code

```lang … ```

block

Table

pipe table

block

Horizontal rule

---

block

Footnote

text[^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 centered heading with an anchor
{% endattrs %}

Elium normalizes your input

Elium stores and re-emits a single canonical form, 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

Block

Plain Markdown

Add attributes with…

Reach higher when…

## Title

{% attrs %}

it needs alignment or an anchor id

plain text

{% attrs %}

it needs alignment

- item / - [ ]

{% attrs %} (task item)

an aligned task item

> quote

-

-

pipe table

HTML <table>

it needs spans, colors, widths, or a heading column

```lang … ```

fence info string

it has a title or filename

-

{% callout %}

always

-

{% collapse %}

always

![alt](url)

HTML <img>

it needs style, link, or sizing

-

HTML <el-asset>

always

-

HTML <el-gallery>

always

```html type="embed" … ```

-

always

-

HTML <el-space-box> / <el-story-box> / <el-user-box> / <el-drive-folder>

always

```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
summarized: 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:

Need

Markup

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" %}
    ## Centered title
    {% endattrs %}

Attributes (on {% attrs %})

Option

Values

Default

align

center, right, justify, inherit

left

id

anchor 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 %})

Option

Values

Default

align

center, right, justify, inherit

left

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 centered 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)

Scope

Options

table

heading row/column, width/height, column widths

cell

colspan, 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">

**Centered**

</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

Option

Values

Default

language

a language id (the first bare token)

plaintext

name

source title / filename

-

language

a 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

Option

Values

Default

type

info, warning

info

align

center, right, justify, inherit

left

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 %})

Option

Values

Default

id

anchor id

-

isTree

boolean

false

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)

Attribute

Meaning

src

image URL

alt

caption / alt text

data-link

URL opened on click

data-style

align-left, align-center, align-right, full-width, inline, banner

data-align

center, right, justify, inherit

width, height

display size

data-width, data-height

intrinsic source size

data-mimetype

MIME 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

Attribute

Meaning

data-asset

asset UUID

data-type

asset type (file, story, url, cloudfile, cloudfolder, drawing, user, email)

data-display-mode

collapsed, expanded, card

data-style

align-left, align-center, align-right, full-width, inline, banner

data-align

center, right, justify, inherit

data-link

URL opened on click

title

caption / alt text

data-width, data-height, data-display-width, data-display-height

size

Gallery

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

Attribute

Meaning

title

gallery title

data-layout

gallery (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

Option

Values

Default

height

size

-

scrolling

auto, 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

Box

Attribute

<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 formatMarkdown (vanilla CommonMark), Elium Markdown (CommonMark plus the {% … %} directives and frontmatter on this page), Canonical Elium HTML, or Slate;

  • a targetStory, 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 normalized), 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 normalization did to your content.


Did this answer your question?