Skip to main content

Markdown support

Twain renders standard Markdown (CommonMark) plus GitHub Flavoured Markdown and a few common extensions. Rendering happens offline: the parser, styles, fonts, and maths are all bundled, and nothing is fetched to lay out a document. Remote images are the one exception. An image with an https: source is loaded from the network, and the Mac app loads them by default; turn off Load Remote Images in the reading settings menu to block them.

GitHub Flavoured Markdown

All of GitHub Flavoured Markdown is supported:

  • Tables

    | Feature | Supported |
    | ------- | --------- |
    | Tables | Yes |
  • Task lists

    - [x] Done
    - [ ] To do
  • Strikethrough with ~~two tildes~~.

  • Autolinks: a bare URL such as https://twain.md becomes a link automatically.

  • Footnotes

    Here is a claim.[^1]

    [^1]: And here is the note that backs it up.

    Footnotes render as a numbered reference in place and a footnotes section at the end of the document. Clicking the reference does not currently jump to the note, and the return arrow does not jump back: the generated identifiers and the link targets do not match.

Frontmatter

A YAML frontmatter block at the very top of a document, fenced by ---, is recognised and shown as a tidy card rather than as body text:

---
title: Release notes
author: Marcus
tags: [markdown, mdx]
---

The title becomes the document's heading and the top entry in the table of contents. Every other key is shown as a labelled key-and-value pair. Lists are joined with commas.

YAML only

Frontmatter is recognised in YAML form (--- fences). TOML frontmatter (+++ fences) is not treated as frontmatter and would render as ordinary text.

Headings and anchors

Every heading is given a slug identifier, so in-page links such as [jump](#my-heading) work, and the table of contents can scroll to any heading. Twain does not add a visible clickable anchor symbol next to headings.

Identifiers you write yourself on raw HTML headings are a special case. For safety they are rewritten with a user-content- prefix, so <h2 id="manual"> becomes id="user-content-manual" and a [jump](#manual) link will not find it. Use a Markdown heading if you want to link to it.

Syntax highlighting

Fenced code blocks are highlighted. Tag the block with a language for accurate colours:

```swift
func greet(_ name: String) { print("Hello, \(name)") }
```

Highlighting covers the common languages you are likely to use in documentation, including JavaScript, TypeScript, Python, Swift, Go, Rust, C, C++, C#, Java, Kotlin, Ruby, PHP, Shell, SQL, JSON, YAML, CSS, and Markdown, among others. Common aliases work too (js, ts, py, sh, yml, html).

If a code block has no language tag, the block still renders and Twain guesses the language so it can highlight it. If the tag names a language Twain does not know, the block renders as plain, unhighlighted code: an unrecognised tag is never guessed at, and it never causes an error.

What is not supported

Twain sticks to CommonMark, GFM, and the extensions listed above. The following are not recognised, and render as literal text:

  • Container directives such as :::note:::. Use a GitHub alert or, in an .mdx file, an MDX callout instead.
  • Wiki links written as [[Page name]].
  • Highlight written as ==marked==, and superscript written as ^text^.
  • Emoji shortcodes such as :smile:. Paste the emoji character itself instead.
  • Custom heading identifiers written as ## Heading {#custom-id}. The braces render as part of the heading text and end up in its slug, so the identifier you intended will not exist.
  • Definition lists. You can still write <dl>, <dt>, and <dd> as HTML if you need them.
  • TOML frontmatter (+++ fences), as noted above.

Raw HTML

Inline and block HTML in a Markdown document is parsed and rendered, then sanitised. Common formatting and structural tags come through unchanged, including <dl>, <details>, <figure>, and tables. Anything that could execute or reach the network is removed: <script> is discarded outright, and <style>, <iframe>, <object>, <embed>, and <svg> are dropped with any text inside them left as plain text. Form controls are neutralised. Event attributes such as onclick, inline style attributes, and javascript: or data: link targets are stripped too.

Beyond plain Markdown

Twain also renders several richer constructs, each on its own page: