Markdown in MDN

Warning

This document is a work-in-progress draft at the moment.

It's not actually possible, yet, to write MDN documentation using Markdown, so at the moment this document is used to record the decisions we've made about how we will expect Markdown to be written, when it is supported.

This page describes how we use Markdown to write documentation on MDN. We have chosen GitHub-Flavored Markdown (GFM) as a baseline, and added some extensions to support some of the things we need to do on MDN that aren't readily supported in GFM.

Baseline: GitHub-Flavored Markdown

The baseline for MDN Markdown is GitHub-Flavored Markdown (GFM): https://github.github.com/gfm/. This means that for anything not otherwise specified in this page, you can refer to the GFM specification. GFM in turn is a superset of CommonMark (http://spec.commonmark.org/).

Example code blocks

In GFM and CommonMark, authors can use "code fences" to demarcate <pre> blocks. The opening code fence may be followed by some text that is called the "info string". From the spec:

The first word of the info string is typically used to specify the language of the code sample, and rendered in the class attribute of the code tag.

It's permissible for the info string to contain multiple words, like:

```fee fi fo fum
// some example code
```
In MDN, writers will use code fences for example code blocks. They must specify the language of the code sample using the first word of the info string, and this will be used to provide syntax highlighting for the block. The following words will be supported:
  • bash
  • cpp (for C/C++)
  • css
  • html
  • java
  • js (for JavaScript)
  • json
  • php
  • python
  • sql
  • xml
  • wasm (for WebAssembly text format)
For example:
```js
const greeting = "I will get syntax highlighting";
```

Writers will be able to supply any one of the following additional words, which must come after the language word:

  • example-good: style this example as a good example (one to follow)
  • example-bad: style this example as a bad example (one to avoid)
  • hidden: don't render this code block in the page. This is for use in live samples.
For example:
```js example-good
const greeting = "I'm a good example";
```

Discussion reference

This issue was resolved in https://github.com/mdn/content/issues/3512.

Notes, warnings, and callouts

Sometimes writers want to call special attention to some piece of content. To do this, they will use a GFM blockquote with a special first paragraph. There are three types of these: notes, warnings, and callouts.

  • To add a note, create a GFM blockquote whose first paragraph starts with **Note:**.
  • To add a warning, create a GFM blockquote whose first paragraph starts with **Warning:**.
  • To add a callout, create a GFM blockquote whose first paragraph starts with **Callout:**.

Notes and warnings will render the Note: or Warning: text in the output, while callouts will not. This makes callouts a good choice when an author wants to provide a custom title.

Processing of the markup works on the AST it produces, not on the exact characters provided. This means that providing <strong>Note:</strong> will also generate a note. However, the Markdown syntax is required as a matter of style.

Multiple lines are produced by an empty block quote line in the same way as normal paragraphs. Further, multiple lines without a space are also treated like normal markdown lines, and concatenated.

The blockquote can contain code blocks or other block elements.

Because the text "Note:" or "Warning:" also appears in the rendered output, it has to be sensitive to translations. In practice this means that every locale supported by MDN must supply its own translation of these strings, and the platform must recognize them as indicating that the construct needs special treatment.

Examples

Note
> **Note:** This is how you write a note.
>
> It can have multiple lines.

This will produce the following HTML:

<div class="notecard note">
  <p><strong>Note:</strong> This is how you write a note.</p>
  <p>It can have multiple lines.</p>
</div>

This HTML will be rendered as a highlighted box, like:

Note: This is how you write a note.

It can have multiple lines.

Warnings
> **Warning:** This is how you write a warning.
>
> It can have multiple paragraphs.

This will produce the following HTML:

<div class="notecard warning">
  <p><strong>Warning:</strong> This is how you write a warning.</p>
  <p>It can have multiple paragraphs.</p>
</div>

This HTML will be rendered as a highlighted box, like:

Warning: This is how you write a warning.

It can have multiple paragraphs.

Callouts
> **Callout:** **This is how you write a callout**.
>
> It can have multiple paragaphs.

This will produce the following HTML:

<div class="callout">
  <p><strong>This is how you write a callout.</strong></p>
  <p>It can have multiple paragraphs.</p>
</div>

This HTML will be rendered as a highlighted box, like:

This is how you write a callout.

It can have multiple paragraphs.

Translated warning

For example, if we want to use "Warnung" for "Warning" in German, then in German pages we would write:

> Warnung: So schreibt man eine Warnung.

...and this will produce:

<div class="notecard warning">
  <p><strong>Warnung:</strong> So schreibt man eine Warnung.</p>
</div>
Note containing a code block

This example contains a code block.

> **Note:** This is how you write a note.
>
> It can contain code blocks.
>
> ```js
> const s = "I'm in a code block";
> ```
> Like that.

This will produce the following HTML:

<div class="notecard note">
  <p><strong>Note:</strong> This is how you write a note.</p>
  <p>It can contain code blocks.</p>
  <pre class="brush: js">const s = "I'm in a code block";</pre>
  <p>Like that.</p>
</div>

This HTML will be rendered as with a code block, like:

Note: This is how you write a note.

It can contain code blocks.

const s = "I'm in a code block";

Like that.

Discussion reference

This issue was resolved in https://github.com/mdn/content/issues/3483.

Definition lists

To create definition lists in MDN authors write a modified form of a GFM unordered list (<ul>). In this form:

  • The GFM <ul> contains any number of top-level GFM <li> elements.
  • Each of these top-level GFM <li> elements must contain, as its final element, one GFM <ul> element.
  • This final nested <ul> must contain a single GFM <li> element, whose text content must start with (a colon followed by a space). This element may contain block elements, including paragraphs, code blocks, embedded lists, and notes.

Each of these top-level GFM <li> elements will be transformed into a <dt>/<dd> pair, as follows:

  • The top-level GFM <li> element will be parsed as a GFM <li> element and its internal contents will comprise the contents of the <dt>, except for the final nested <ul>, which will not be included in the <dt>.
  • The <li> element in the final nested <ul> will be parsed as a GFM <li> element and its internal contents will comprise the contents of the <dd>, except for the leading , which will be discarded.
For example, this is a <dl>:
* term1
    * : My description of term1

* `term2`
    * : My description of term2

      It can have multiple paragraphs, and code blocks too:

      ```js
      const thing = 1;
      ```
In GFM/CommonMark, this would produce the following HTML:
<ul>
  <li>
    <p>term1</p>
    <ul>
      <li>: My description of term1</li>
    </ul>
  </li>
  <li>
    <p><code>term2</code></p>
    <ul>
      <li>
        <p>: My description of term2</p>
        <p>It can have multiple paragraphs, and code blocks too:</p>
        <pre>
          <code class="brush: js">const thing = 1;</code>
        </pre>
      </li>
    </ul>
  </li>
</ul>
On MDN, this would produce the following HTML:
<dl>
  <dt>
    <p>term1</p>
  </dt>
  <dd>My description of term1</dd>
  <dt>
    <p><code>term2</code></p>
  </dt>
  <dd>
    <p>My description of term2</p>
    <p>It can have multiple paragraphs, and code blocks too:</p>
    <pre>
       <code class="brush: js">const thing = 1;</code>
    </pre>
  </dd>
</dl>

Definition lists written using this syntax must consist of pairs of <dt>/<dd> elements. Using this syntax, it's not possible to write a list with more than one consecutive <dt> element or more than one consecutive <dd> element: the parser will treat this as an error. We expect almost all definition lists on MDN will work with this limitation, and for those that do not, authors can fall back to raw HTML.

As a workaround for cases where an author needs to associate multiple <dt> items with a single <dd>, consider providing them as a single <dt> that holds multiple terms, separated by commas, like this:

* `param1`, `param2`, `param3`
    * : My description of params 1, 2, and 3

The rationale for the syntax described here is that it works well enough with tools that expect CommonMark (for example, Prettier or GitHub previews) while being reasonably easy to write and to parse.

Discussion reference

This issue was resolved in https://github.com/mdn/content/issues/4367.

Tables

In GFM (but not CommonMark) there is a syntax for tables: https://github.github.com/gfm/#tables-extension-. We will make use of this but the GFM syntax only supports a subset of the features available in HTML.

So the general principle here is: authors should use the GFM Markdown syntax when they can, and fall back to raw HTML when they have to.

The main limitations of GFM table syntax are:

  • GFM tables must have a header row.
  • GFM tables may not have a header column.
  • GFM won't parse GFM block elements in table cells. For example, you can't have a list in a table cell.
  • GFM doesn't support any table elements beyond <table>, <tr>, and <th>, and <td>.
  • GFM doesn't support any table element attributes like colspan, rowspan, or scope.

If an author needs to use any of the unsupported features, they should write the table in HTML.

We don't recommend the general use of <caption> elements on tables, since that would also rule out the GFM syntax.

In GFM table syntax, authors can omit leading and trailing pipes for rows. MDN authors must include these pipes, for the sake of readability.

That is, MDN authors must use this style:

| Heading 1 | Heading 2 | Heading 3 |
|-----------|-----------|-----------|
| cell 1    | cell 2    | cell 3    |
| cell 4    | cell 5    | cell 6    |

and not this style:

Heading 1 | Heading 2 | Heading 3
 --- | --- | ---
cell 1    | cell 2    | cell 3
cell 4    | cell 5    | cell 6

Discussion reference

This issue was resolved in https://github.com/mdn/content/issues/4325.

Heading IDs

Live samples

Inline styles

Superscript and subscript

Writers will be able to use the HTML <sup>> and <sub> elements if necessary, but should use alternatives if possible. In particular:

  • For exponentiation, use the caret: 2^53.
  • For ordinal expressions like 1st, prefer words like "first".
  • For footnotes, don’t mark up the footnote references with, e.g., <sup>[1]</sup>; it’s unnecessary.

Discussion reference

This issue was resolved in https://github.com/mdn/content/issues/4578.

KumaScript

Writers will be able to include KumaScript macro calls in prose content:

The **`margin`** [CSS](https://developer.mozilla.org/en-US/docs/Web/CSS) property
sets the margin area on all four sides of an element. It is a shorthand for
{{cssxref("margin-top")}}, {{cssxref("margin-right")}}, {{cssxref("margin-bottom")}},
and {{cssxref("margin-left")}}.

{{EmbedInteractiveExample("pages/css/margin.html")}}

The top and bottom margins have no effect on replaced inline elements, such as
{{HTMLElement("span")}} or {{HTMLElement("code")}}.