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: