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 |
| inline |
Italic |
| inline |
Strikethrough |
| inline |
Inline code |
| inline |
Link |
| inline |
Image |
| inline |
Subscript / superscript |
| inline |
Heading (1-3) |
| block |
List |
| block |
Task list |
| block |
Blockquote |
| block |
Fenced code |
| block |
Table | pipe table | block |
Horizontal rule |
| block |
Footnote |
| 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:
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.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.
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>) plusel-*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 meantrue(isTree). A missing boolean isfalse.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).
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… |
|
| it needs alignment or an anchor id | |
plain text |
| it needs alignment | |
|
| an aligned task item | |
| - | - | |
pipe table | HTML | it needs spans, colors, widths, or a heading column | |
| fence info string | it has a title or filename | |
- |
| always | |
- |
| always | |
| HTML | it needs style, link, or sizing | |
- | HTML | always | |
- | HTML | always | |
| - | always | |
- | HTML | always | |
| - | 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 . Elium adds:
Subscript
H~2~Oand superscriptx^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 |
|
Sub / sup |
|
Text / background color |
|
Tracked change (diff) |
|
Mention |
|
Inline image with options |
|
Inline asset |
|
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 |
|
|
|
| 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 |
|
|
|
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 |
|
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) |
|
| source title / filename | - |
| 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 |
|
|
|
|
|
|
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 |
| anchor id | - |
| boolean |
|
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 (tois the target id,labelits 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:
(an inline image with no options).Canonical HTML (style, link, size, or a block-level image): an
<img>element.
Options (HTML form)
Attribute | Meaning |
| image URL |
| caption / alt text |
| URL opened on click |
|
|
|
|
| display size |
| intrinsic source size |
| 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 |
| asset UUID |
| asset type ( |
|
|
|
|
|
|
| URL opened on click |
| caption / alt text |
| 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 |
| gallery title |
|
|
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 |
| size | - |
|
| - |
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 |
|
|
|
|
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, orSlate;a target —
Story,Comment,Template, orSmart 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.