Djot Syntax Reference
This document covers all Djot syntax supported by this library with input and output examples.
Block Elements
Headings
Headings use # characters. The number of # determines the level (1-6).
Input:
# Heading 1
## Heading 2
### Heading 3
#### Heading 4
##### Heading 5
###### Heading 6<h1>Heading 1</h1>
<h2>Heading 2</h2>
<h3>Heading 3</h3>
<h4>Heading 4</h4>
<h5>Heading 5</h5>
<h6>Heading 6</h6>Paragraphs
Paragraphs are separated by blank lines. Text within a paragraph wraps normally.
Input:
First paragraph with
multiple lines.
Second paragraph.<p>First paragraph with
multiple lines.</p>
<p>Second paragraph.</p>Code Blocks
Fenced code blocks use triple backticks with an optional language identifier.
Input:
```php
function hello(): void {
echo "Hello World";
}
```<pre><code class="language-php">function hello(): void {
echo "Hello World";
}
</code></pre>Without a language:
Input:
```
Plain code block
```<pre><code>Plain code block
</code></pre>Block Quotes
Block quotes use > at the start of each line.
Input:
> This is a quote
> spanning multiple lines.
>
> With multiple paragraphs.<blockquote>
<p>This is a quote
spanning multiple lines.</p>
<p>With multiple paragraphs.</p>
</blockquote>Nested block quotes:
Input:
> Outer quote
>
> > Nested quote<blockquote>
<p>Outer quote</p>
<blockquote>
<p>Nested quote</p>
</blockquote>
</blockquote>Block Quote Captions
Use ^ after a block quote to add an attribution/caption. The block quote will be wrapped in a <figure> element with a <figcaption>.
Input:
> To be or not to be, that is the question.
^ William Shakespeare<figure>
<blockquote>
<p>To be or not to be, that is the question.</p>
</blockquote>
<figcaption>William Shakespeare</figcaption>
</figure>Lists
Bullet Lists
Use -, *, or + for bullet lists.
Input:
- Item 1
- Item 2
- Item 3<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>Ordered Lists
Use numbers followed by . or ).
Input:
1. First
2. Second
3. Third<ol>
<li>First</li>
<li>Second</li>
<li>Third</li>
</ol>Lists can start at any number:
Input:
5. Fifth item
6. Sixth item<ol start="5">
<li>Fifth item</li>
<li>Sixth item</li>
</ol>Nested Lists
Indent with 2+ spaces for nested lists.
Input:
- Item 1
- Nested A
- Nested B
- Item 2<ul>
<li>Item 1
<ul>
<li>Nested A</li>
<li>Nested B</li>
</ul>
</li>
<li>Item 2</li>
</ul>Task Lists
Use [ ] or [_] for unchecked and [x] or [X] for checked items.
The underscore notation [_] is useful on mobile devices or in editors without monospaced fonts, where the space in [ ] can be hard to type or see.
Input:
- [ ] Todo item (space)
- [_] Todo item (underscore)
- [x] Done item<ul class="task-list">
<li><input type="checkbox" disabled> Todo item (space)</li>
<li><input type="checkbox" disabled> Todo item (underscore)</li>
<li><input type="checkbox" disabled checked> Done item</li>
</ul>List Item Attributes (Extension)
Attributes can be added to list items on the following indented line:
Input:
- item 1
{.highlight #id1}
- item 2
{data-value="test"}
- item 3<ul>
<li class="highlight" id="id1">item 1</li>
<li data-value="test">item 2</li>
<li>item 3</li>
</ul>Works with all list types (unordered, ordered, and task lists). The attribute line must be indented to the content indentation level.
Tight vs Loose Lists
Lists in Djot can be tight or loose, which affects how list items are rendered.
Tight lists have no blank lines between items. List item content is rendered directly without <p> tags:
Input:
- Item one
- Item two
- Item three<ul>
<li>Item one</li>
<li>Item two</li>
<li>Item three</li>
</ul>Loose lists have blank lines between items. Each item's content is wrapped in <p> tags:
Input:
- Item one
- Item two
- Item three<ul>
<li><p>Item one</p></li>
<li><p>Item two</p></li>
<li><p>Item three</p></li>
</ul>The tight/loose distinction affects visual spacing. Loose lists typically have more vertical space between items due to paragraph margins in CSS.
Mixed Lists
A list is loose if any item is separated by a blank line. One blank line makes the entire list loose.
Nested lists require a blank line before the nested content in standard Djot:
- Parent item
- Nested item A
- Nested item BWith significantNewlines mode enabled, nested lists can appear immediately without a blank line:
- Parent item
- Nested item A
- Nested item BSee the API Reference for more on significantNewlines mode.
Definition Lists
Terms are prefixed with : and definitions are indented below.
: Term 1
Definition of term 1
: Term 2
Definition of term 2: color
: colour
The visual property of objects.: word
First meaning.
: +
Second meaning (separate dd).<dl>
<dt>Term 1</dt>
<dd><p>Definition of term 1</p></dd>
<dt>Term 2</dt>
<dd><p>Definition of term 2</p></dd>
</dl>Enhancements
- Multiple terms: Consecutive
: termlines share a definition - Multiple definitions: Use
: +continuation for separate<dd>elements - Attributes: Add
{.class}to<dl>,<dt>, or<dd>elements
See definition list enhancements for full details.
Definition List Attributes (Extension)
Attributes can be attached to individual definition list elements:
Input:
{.vocabulary}
: color
{.american}
: colour
{.british}
The visual property of objects.
{.primary}<dl class="vocabulary">
<dt class="american">color</dt>
<dt class="british">colour</dt>
<dd class="primary">
<p>The visual property of objects.</p>
</dd>
</dl>{...}before first term → applies to<dl>{...}on line after term → applies to that<dt>{...}as last line in definition block → applies to that<dd>
Tables
Tables use | to separate columns.
Input:
| Header 1 | Header 2 |
|----------|----------|
| Cell 1 | Cell 2 |
| Cell 3 | Cell 4 |<table>
<thead>
<tr><th>Header 1</th><th>Header 2</th></tr>
</thead>
<tbody>
<tr><td>Cell 1</td><td>Cell 2</td></tr>
<tr><td>Cell 3</td><td>Cell 4</td></tr>
</tbody>
</table>Column Alignment
Use : in the separator row for alignment.
Input:
| Left | Center | Right |
|:-----|:------:|------:|
| L | C | R |<table>
<thead>
<tr><th style="text-align: left">Left</th><th style="text-align: center">Center</th><th style="text-align: right">Right</th></tr>
</thead>
<tbody>
<tr><td style="text-align: left">L</td><td style="text-align: center">C</td><td style="text-align: right">R</td></tr>
</tbody>
</table>Table Captions
Use ^ after the table for a caption.
Input:
| A | B |
|---|---|
| 1 | 2 |
^ This is the caption<table>
<caption>This is the caption</caption>
<thead>
<tr><th>A</th><th>B</th></tr>
</thead>
<tbody>
<tr><td>1</td><td>2</td></tr>
</tbody>
</table>Table Row and Cell Attributes (Extension)
Attributes can be added to table rows and individual cells:
Row attributes (after final pipe):
| Name | Age |{.header-row}
|------|-----|
| John | 30 |{.highlight}Cell attributes (after opening pipe):
|{.name} Name |{.age} Age |
|-------------|-----------|
|{.emphasis} John | 30 |<table>
<tr class="header-row">
<th class="name">Name</th>
<th class="age">Age</th>
</tr>
<tr class="highlight">
<td class="emphasis">John</td>
<td>30</td>
</tr>
</table>Table Multi-line Cells, Rowspan, and Colspan (Extension)
Multi-line cell content uses + prefix for continuation rows:
| Name | Description |
|------|------------------|
| Item | Long description |
+ | continued here |Rowspan uses ^ marker (points UP to cell above):
| Category | Item |
|----------|--------|
| Fruits | Apple |
| ^ | Banana |
| ^ | Orange |<table>
<tr><th>Category</th><th>Item</th></tr>
<tr><td rowspan="3">Fruits</td><td>Apple</td></tr>
<tr><td>Banana</td></tr>
<tr><td>Orange</td></tr>
</table>Colspan uses < marker (points LEFT to cell before):
| Name | Contact Info | < |
|-------|--------------|-------|
| Alice | alice@ex.com | x5234 |<table>
<tr><th>Name</th><th colspan="2">Contact Info</th></tr>
<tr><td>Alice</td><td>alice@ex.com</td><td>x5234</td></tr>
</table>Use \^ or \< for literal characters. Content like a < b is NOT treated as colspan.
Thematic Breaks
Use ***, ---, or ___ (3+ characters) on a line by itself.
Input:
Above
***
Below<p>Above</p>
<hr>
<p>Below</p>Divs
Fenced divs use ::: with an optional class name.
Input:
::: warning
This is a warning message.
:::<div class="warning">
<p>This is a warning message.</p>
</div>Nested divs:
Input:
::: outer
Outer content
::: inner
Inner content
:::
More outer
:::<div class="outer">
<p>Outer content</p>
<div class="inner">
<p>Inner content</p>
</div>
<p>More outer</p>
</div>Comments
Comments are not rendered in output.
Input:
Visible text
{% This is a comment %}
More visible text
{% Multi-line
comment here %}<p>Visible text</p>
<p>More visible text</p>Fenced Comments (Extension)
Standard {% %} comments cannot contain blank lines. For longer comments that need blank lines, use fenced comments with %%%:
Input:
Visible text
%%%
This is a fenced comment block.
It can contain blank lines.
Multiple paragraphs of notes, TODOs,
or documentation that won't render.
%%%
More visible text<p>Visible text</p>
<p>More visible text</p>Like code fences, you can use more than three % characters. The closing fence must have at least as many % as the opening fence:
Input:
Some text
%%%%
%%% This is not the end
Still inside the comment
%%%%
More text<p>Some text</p>
<p>More text</p>Note: This is a djot-php extension, not part of the official Djot specification. See discussion for background.
Fenced comment blocks are block-level elements that break paragraph continuity. Unlike other block elements, fenced comments can interrupt paragraphs without requiring a preceding blank line - making them truly "invisible" from a formatting perspective:
Input:
Lorem ipsum
%%%
comment
%%%
dolor sit amet<p>Lorem ipsum</p>
<p>dolor sit amet</p>This produces two separate paragraphs. For comments that should not interrupt paragraph flow (keeping text in the same paragraph), use inline comments ({% ... %}).
Line Blocks
Preserve line breaks using | at the start of each line. Useful for poetry or addresses.
Input:
| Roses are red,
| Violets are blue,
| Sugar is sweet,
| And so are you.<div class="line-block">
<p>Roses are red,<br>
Violets are blue,<br>
Sugar is sweet,<br>
And so are you.</p>
</div>Block Attributes
Apply attributes to the following block using {...} syntax.
Input:
{.highlight #intro}
# Introduction
{.note data-version="2.0"}
This is a note.<h1 class="highlight" id="intro">Introduction</h1>
<p class="note" data-version="2.0">This is a note.</p>Boolean Attribute Shorthand (Extension)
Boolean/flag attributes can be specified without a value:
Input:
{reversed}
1. Third
2. Second
3. First
[Download](file.zip){download .btn}<ol reversed="">
<li>Third</li>
<li>Second</li>
<li>First</li>
</ol>
<p><a href="file.zip" class="btn" download="">Download</a></p>Common boolean attributes: {reversed} (lists), {open} (details), {hidden}, {download} (links).
Inline Elements
Emphasis and Strong
Use _underscores_ for emphasis and *asterisks* for strong.
Input:
This is _emphasized_ and *strong* text.
You can _nest *strong* inside_ emphasis.<p>This is <em>emphasized</em> and <strong>strong</strong> text.</p>
<p>You can <em>nest <strong>strong</strong> inside</em> emphasis.</p>Code Spans
Use backticks for inline code.
Input:
Use the `print()` function.
For literal backticks: `` `code` ``<p>Use the <code>print()</code> function.</p>
<p>For literal backticks: <code>`code`</code></p>Links
Inline Links
Input:
[Link text](https://example.com)
[Link with title](https://example.com "Title")<p><a href="https://example.com">Link text</a></p>
<p><a href="https://example.com" title="Title">Link with title</a></p>Reference Links
Input:
[Link text][ref]
[Another link][ref]
[ref]: https://example.com<p><a href="https://example.com">Link text</a></p>
<p><a href="https://example.com">Another link</a></p>Reference Links with Attributes
Attributes can be added to reference definitions and will be applied to all links using that reference.
Input:
[Click here][example]
{.external title="Example Site"}
[example]: https://example.com<p><a href="https://example.com" class="external" title="Example Site">Click here</a></p>Link-level attributes can override or extend definition attributes:
Input:
[Click here][example]{.button}
{.external}
[example]: https://example.com<p><a href="https://example.com" class="external button">Click here</a></p>Autolinks
Input:
<https://example.com>
<user@example.com><p><a href="https://example.com">https://example.com</a></p>
<p><a href="mailto:user@example.com">user@example.com</a></p>Images
Input:

<p><img src="/demo.svg" alt="Demo landscape"></p>
<p><img src="/demo.svg" alt="Demo landscape" title="A simple landscape"></p>Image Captions
Use ^ after an image to add a caption. The image will be wrapped in a <figure> element with a <figcaption>.
Input:

^ A simple landscape with sun, hills, and sky<figure>
<img src="/demo.svg" alt="Demo landscape"><figcaption>A simple landscape with sun, hills, and sky</figcaption>
</figure>Superscript and Subscript
Use ^ for superscript and ~ for subscript.
Input:
E=mc^2^
H~2~O<p>E=mc<sup>2</sup></p>
<p>H<sub>2</sub>O</p>Highlight, Insert, Delete
Input:
{=highlighted text=}
{+inserted text+}
{-deleted text-}<p><mark>highlighted text</mark></p>
<p><ins>inserted text</ins></p>
<p><del>deleted text</del></p>Spans with Attributes
Apply attributes to inline text.
Input:
[styled text]{.highlight}
[more text]{#unique-id}
[data text]{data-value="42"}<p><span class="highlight">styled text</span></p>
<p><span id="unique-id">more text</span></p>
<p><span data-value="42">data text</span></p>Math
Inline Math
Input:
The equation $`E = mc^2`$ is famous.<p>The equation <span class="math inline">\(E = mc^2\)</span> is famous.</p>Display Math
Input:
$$`\sum_{i=0}^{n} i = \frac{n(n+1)}{2}`$$<span class="math display">\[\sum_{i=0}^{n} i = \frac{n(n+1)}{2}\]</span>Symbols
Use :name: for symbols.
Input:
I :heart: Djot<p>I <span class="symbol">heart</span> Djot</p>Note: Symbol rendering can be customized via events. See the Cookbook for examples.
Footnotes
Input:
Here is a statement[^1] with a footnote.
Another reference[^note].
[^1]: This is the first footnote.
[^note]: This is a named footnote.<p>Here is a statement<sup id="fnref-1-1"><a href="#fn-1">1</a></sup> with a footnote.</p>
<p>Another reference<sup id="fnref-note-1"><a href="#fn-note">note</a></sup>.</p>
<div class="footnote" id="fn-1">
<p><sup>1</sup> This is the first footnote. <a href="#fnref-1-1">↩</a></p>
</div>
<div class="footnote" id="fn-note">
<p><sup>note</sup> This is a named footnote. <a href="#fnref-note-1">↩</a></p>
</div>Raw HTML
Inline Raw HTML
Input:
Text `<span class="special">raw html</span>`{=html} more text<p>Text <span class="special">raw html</span> more text</p>Block Raw HTML
Input:
``` =html
<div class="custom">
<p>Raw HTML block</p>
</div>
```<div class="custom">
<p>Raw HTML block</p>
</div>Smart Typography
The parser automatically converts certain character sequences.
Quotes
Input:
"Double quotes" and 'single quotes'
"Nested 'quotes' work" too<p>"Double quotes" and 'single quotes'</p>
<p>"Nested 'quotes' work" too</p>Dashes
Input:
En-dash: 1--10
Em-dash: wait---what?<p>En-dash: 1–10</p>
<p>Em-dash: wait—what?</p>Ellipsis
Input:
Wait for it...<p>Wait for it…</p>Hard Line Breaks
End a line with a backslash for a hard break.
Input:
Line one\
Line two\
Line three<p>Line one<br>
Line two<br>
Line three</p>Abbreviations (Extension)
Abbreviations allow you to define terms that will automatically be wrapped in <abbr> tags with their definitions. This is an extension feature inspired by PHP Markdown Extra.
Input:
The HTML specification is maintained by the W3C.
*[HTML]: Hyper Text Markup Language
*[W3C]: World Wide Web Consortium<p>The <abbr title="Hyper Text Markup Language">HTML</abbr> specification is maintained by the <abbr title="World Wide Web Consortium">W3C</abbr>.</p>Abbreviation definitions can appear anywhere in the document and will be applied to all matching text. Matching is:
- Case-sensitive (HTML ≠ html)
- Word-boundary aware (HTML won't match HTMLElement)
Definitions can span multiple lines if continuation lines are indented:
*[HTML]: Hyper Text Markup Language,
the standard markup language for documents
designed to be displayed in a web browserInline Abbreviations
For one-off abbreviations or to override a definition, use the inline span syntax:
Input:
The [HTML]{abbr="Hyper Text Markup Language"} specification.<p>The <abbr title="Hyper Text Markup Language">HTML</abbr> specification.</p>The definition-based approach (*[ABBR]: ...) automatically applies to all matching text, while the inline [ABBR]{abbr="..."} approach allows marking specific occurrences.
Escaping
Use backslash to escape special characters.
Input:
\*not strong\*
\# not a heading
\[not a link\]<p>*not strong*</p>
<p># not a heading</p>
<p>[not a link]</p>Non-Breaking Space
An escaped space (\ ) produces a non-breaking space.
Input:
100\ km
Dr.\ Smith<p>100 km</p>
<p>Dr. Smith</p>This is useful for keeping values and units together, titles and names, or any text that shouldn't be split across lines.