Skip to content

Why Djot? Upgrading from Markdown

Djot was created by John MacFarlane (creator of Pandoc and CommonMark) to address Markdown's accumulated quirks and limitations. This document explains why you might want to upgrade.

The Problem with Markdown

Markdown was designed in 2004 as a simple format for writing blog posts. Twenty years later, it's used everywhere - but with significant problems:

  1. No single specification - CommonMark, GFM, MultiMarkdown, PHP Markdown Extra, and dozens more
  2. Ambiguous syntax - _ and * behave differently based on context
  3. Limited features - no highlighting, attributes, or consistent extensions
  4. HTML dependency - raw HTML is the escape hatch for everything
  5. Complex parsing - requires backtracking and lookahead

Parser Design: No Backtracking

One of Djot's most significant technical advantages is its parser design.

The Markdown Parsing Problem

Markdown requires backtracking - the parser must sometimes go back and reinterpret what it already parsed. Consider:

markdown
*foo *bar* baz*

A Markdown parser sees *foo and thinks "this might be emphasis." It continues, finds *bar* (definitely emphasis), then hits baz*. Now it must decide: is the outer *...* emphasis too?

The parser has to backtrack and try different interpretations. This leads to:

  • Unpredictable results - different parsers make different choices
  • Performance costs - worst-case exponential time complexity
  • Edge case bugs - complex nesting creates surprising output

Djot's Solution

Djot was designed from the ground up to parse without backtracking:

  • * always means strong, _ always means emphasis
  • Delimiters must be "matched" - *foo* works, *foo _bar* baz_ doesn't cross
  • The parser never needs to reconsider previous decisions

Benefits:

AspectMarkdownDjot
Parse complexityCan require backtrackingLinear, single-pass
PredictabilityContext-dependentAlways consistent
Edge casesMany surprising resultsMinimal surprises
Error recoveryVaries by parserPredictable fallback

Real-World Example

markdown
_(_foo_)_

Different Markdown parsers produce different output for this. Some treat it as emphasis around (_foo_), others as _(_foo followed by )_.

In Djot, the rules are clear: underscores must balance, and the result is always predictable.

Side-by-Side Comparison

Emphasis and Strong

FeatureMarkdownDjot
Emphasis*text* or _text__text_
Strong**text** or __text__*text*

Djot uses single characters consistently: _ for emphasis, * for strong. No ambiguity.

Text Formatting

FeatureMarkdownDjot
HighlightNot supported{=highlighted=}
InsertNot standard{+inserted+}
Delete~~text~~ (GFM only){-deleted-}
SuperscriptNot standard{^superscript^}
SubscriptNot standard{~subscript~}

Attributes

Markdown has no standard way to add classes, IDs, or attributes.

Markdown (with non-standard extensions):

markdown
# Heading {#my-id .my-class}
<!-- Depends on parser, often not supported -->

Djot:

djot
# Heading {#my-id .my-class}

A paragraph with [styled text]{.highlight} inline.

![Image](photo.jpg){width=300}

Djot attributes work on any element - headings, paragraphs, spans, images, code blocks, and more.

Code Blocks

Markdown:

markdown
```javascript
const x = 1;
```

Djot:

djot
``` javascript
const x = 1;
```
{#example-code .highlighted linenos=true}

Djot allows attributes on code blocks for syntax highlighting configuration, line numbers, etc.

FeatureMarkdownDjot
Basic link[text](url)[text](url)
Basic image![alt](url)![alt](url)
Link with title[text](url "title")[text](url "title")
Link with attributesNot supported[text](url){target=_blank}
Image with sizeNot standard![alt](url){width=300}

Footnotes

Markdown (extension, varies by parser):

markdown
Here's a footnote[^1].

[^1]: The footnote content.

Djot (built-in, consistent):

djot
Here's a footnote[^1].

[^1]: The footnote content.

Same syntax, but Djot guarantees it works everywhere.

Math

Markdown: Depends entirely on the parser. Some use $...$, others \(...\), many don't support it.

Djot:

djot
Inline math: $E = mc^2$

Display math:
$$
\int_0^\infty e^{-x^2} dx = \frac{\sqrt{\pi}}{2}
$$

Raw Content

Markdown: Only raw HTML is supported.

Djot:

djot
`<b>raw html</b>`{=html}

`\textbf{raw latex}`{=latex}

``` =html
<div class="custom">
  Raw HTML block
</div>

Output to any format, not just HTML.

### Divs and Spans

**Markdown:** Not supported. Must use raw HTML.

**Djot:**
```djot
::: warning
This is a warning div.
:::

This has a [styled span]{.highlight} inline.

Symbols

Markdown: Not supported.

Djot:

djot
I :heart: Djot! The weather is :sunny: today.

Symbols can be rendered as emoji, HTML entities, or custom output.

Definition Lists

Markdown: Non-standard extension with varying syntax.

Djot:

djot
: Term
  Definition of the term.

: Another term
  Another definition.

Tables

Both support tables, but Djot tables are more consistent:

Djot:

djot
| Header 1 | Header 2 |
|----------|----------|
| Cell 1   | Cell 2   |
{.striped .bordered}

Attributes on tables!

Migration Path

This library provides tools for gradual migration:

1. Convert Existing Content

php
use Djot\Converter\MarkdownToDjot;

$converter = new MarkdownToDjot();
$djot = $converter->convert($markdownContent);

2. Output to Markdown if Needed

php
use Djot\DjotConverter;
use Djot\Renderer\MarkdownRenderer;

$converter = new DjotConverter();
$doc = $converter->parse($djotContent);

$renderer = new MarkdownRenderer();
$markdown = $renderer->render($doc);

3. Accept Both Formats

php
// Detect and convert Markdown on input
if (containsMarkdownPatterns($input)) {
    $input = (new MarkdownToDjot())->convert($input);
}

$html = (new DjotConverter())->convert($input);

When to Stick with Markdown

Markdown may still be the right choice when:

  • Your content is very simple (just paragraphs and basic formatting)
  • You're locked into a Markdown-only ecosystem (GitHub issues, etc.)
  • Your team is familiar with Markdown and change is costly
  • You don't need any of Djot's additional features

When to Choose Djot

Djot is the better choice when:

  • You need consistent, predictable parsing
  • You want attributes on elements (classes, IDs, custom data)
  • You need features like highlighting, super/subscript, or symbols
  • You're building a new system without legacy constraints
  • You want a single specification, not "which Markdown flavor?"
  • You need to output to formats other than HTML

Learn More

Released under the MIT License.