TS-27: Markdown
Markdown is a lightweight human-editable markup language. It is widely used for simple documentation such as README files, contribution guides, changelogs, pull request descriptions, and code comments, and it is supported by many source code hosting platforms, issue trackers, and chat tools.
For technical documentation that requires tables of contents, cross-references, included files, admonitions, or diagrams, AsciiDoc is RECOMMENDED instead. See TS-28.
This technical standard offers tips and best practices for writing Markdown. It recommends GitHub Flavored Markdown (GFM), a strict superset of the CommonMark specification, as the baseline dialect.
For a complete language reference, see the CommonMark Specification and the GitHub Flavored Markdown Specification.
Overview
Markdown is a lightweight markup language with a plain-text formatting syntax. Its design goal is to be readable as-is, without the formatting tags or instructions of a richer markup language, while still allowing the text to be converted to structured formats such as HTML.
Markdown is suited to short, relatively simple documents. For longer or more structured technical documentation, AsciiDoc is RECOMMENDED; see TS-28.
When to use Markdown
Markdown is a good choice for:
READMEfiles and other repository meta-documents.- Changelogs, pull request descriptions, and issue comments.
- Code comments and API documentation that is co-located with source code.
- Chat and messaging platforms that support Markdown input.
When not to use Markdown
Avoid Markdown when a document needs:
- A generated table of contents.
- File includes or modular content.
- Complex tables, cross-references, or admonitions.
- Embedded diagrams or conditional rendering.
Prefer AsciiDoc for these cases.
Flavors and specifications
There are many incompatible Markdown dialects. To maximize portability and predictable rendering, documents SHOULD target a single, well-specified dialect.
GitHub Flavored Markdown (GFM) is RECOMMENDED. GFM is a strict superset of the CommonMark specification, adding tables, strikethrough, task lists, and automatic linking of URLs.
Documents SHOULD be valid CommonMark at minimum. Features that are specific to GFM (tables, strikethrough, task lists) MAY be used where the target rendering platform supports GFM (which is not limited to GitHub.com).
Some platforms add their own extensions on top of GFM. GitHub, for example, supports callouts (see Callouts), which are not part of the GFM specification. Such extensions MAY be used where the target platform supports them, but authors SHOULD be aware that they are not portable and will degrade on other renderers.
Avoid dialects that are not backed by a formal specification, such as the original Markdown.pl implementation. Avoid proprietary extensions that are unlikely to be portable across renderers.
File extensions
Markdown files SHOULD use the .md extension.
The extensions .markdown, .mdown, and .mkd MAY be used, but .md is preferred for consistency and broad tool support.
Files that contain only Markdown table data, or that are consumed by a specific tool, MAY use a tool-specific extension.
Headings
Headings SHOULD be written using ATX-style syntax - one to six number signs (#) followed by a single space and the heading text.
# Level 1 heading ## Level 2 heading ### Level 3 heading
Setext-style headings (underlining text with = or -) SHOULD NOT be used. They only support two levels, are harder to edit, and are less widely supported.
A single space MUST be placed between the number signs and the heading text. Some processors do not recognize a heading when the space is omitted.
A blank line SHOULD be placed before and after each heading. Without blank lines, some processors will not parse the heading correctly.
Heading levels MUST increase by single steps. Do not skip from a level 1 heading directly to a level 3 heading.
Single top-level heading
A document SHOULD have a single level 1 () heading, used as the document title. It SHOULD match, or closely reflect, the file name. All subsequent headings SHOULD start at level 2 (#) or deeper.
Many renderers and static site generators treat the first level 1 heading as the document’s title, and a second level 1 heading later in the same document is either ignored or renders as a confusing repeat of the title. A single top-level heading also keeps the document’s own heading hierarchy consistent with the heading levels used for headings.
Unique and descriptive headings
Each heading SHOULD have unique, fully descriptive text, even across different sections of the same document. Do not repeat a heading such as "Overview" or "Configuration" more than once.
Most Markdown renderers generate a link anchor from each heading’s text, by lower-casing it and replacing spaces with hyphens. Duplicate or generic headings produce duplicate or vague anchors, and the renderer typically disambiguates duplicates by appending a numeric suffix (#configuration-1). That suffix is fragile — it depends on document order, so inserting or removing an earlier section shifts every anchor after it, silently breaking existing links.
Paragraphs and line breaks
A paragraph is a run of text separated from the surrounding content by a blank line. How it is wrapped across source lines is covered in Line length and wrapping.
Paragraphs SHOULD NOT be indented with spaces or tabs. Leading indentation of four or more spaces may be interpreted as a code block.
To insert a hard line break (<br>) within a paragraph, end a line with two or more spaces, or use a backslash (\) at the end of the line. The backslash form is RECOMMENDED, for clarity and because an auto-formatter that strips end-of-line whitespace will silently remove the two-space form. A hard line break changes the rendered output, unlike a soft wrap in the source.
Hard line breaks SHOULD be used sparingly, and only where a break is semantically required — a postal address, a verse, a short lead-in term set above the text it introduces. Prefer separate paragraphs or lists.
Note
Trailing whitespace is invisible in most editors. Configure your editor to highlight trailing whitespace, or use a linter, to avoid accidental hard line breaks.
Emphasis
Use underscores (_) for italics and double asterisks () for bold. Keeping the two markers distinct makes the intent of a run of emphasis obvious in source, where text and text** are easily confused at a glance.
_italic text_ **bold text** **_bold and italic text_**
Underscores in the middle of a word are not interpreted as emphasis by some processors. Where emphasis must fall inside a word, use a single asterisk (text) instead, which is reliable in all positions.
For GFM, strikethrough is written using two tildes (~~):
~~struck-through text~~
Emphasis SHOULD be applied to words or short phrases, not to entire paragraphs. Do not nest emphasis unnecessarily.
For guidance on using emphasis appropriately in technical writing, see TS-26.
Lists
Unordered lists use a single marker — the hyphen (-) — followed by a single space. Do not mix markers (-, *, +) within the same list.
- First item - Second item - Third item
Ordered lists use a number followed by a period and either one or two spaces:
1. First item 2. Second item 3. Third item
Two spaces are RECOMMENDED where list items carry continuation paragraphs or nested blocks. It puts the content at a four-space indent, matching the four-space nesting indent recommended below, so every continuation in the document lines up on the same column:
1. First item.
Continuation paragraph, aligned with the item text.
- A nested item, at the same indent.Note
CommonMark does not require the numbers in an ordered list to be sequential, but they SHOULD be sequential in source for readability. The rendered output is always sequential.
For a short, stable list, sequential numbering in source (1., 2., 3.) is RECOMMENDED, since it is easy to read directly and rarely needs maintenance. For a long list, or one that is edited frequently, "lazy" numbering — repeating 1. for every item — is RECOMMENDED instead:
1. First item 1. Second item 1. Third item
Lazy numbering avoids renumbering every subsequent item when one is inserted or removed in the middle of the list, which is otherwise a common source of noisy diffs and off-by-one mistakes in source. The rendered output is identical either way, since CommonMark renumbers sequentially regardless of the numbers used in source.
Nested lists are created by indenting child items. Indentation of nested list items MUST be consistent. Four spaces of indentation per nesting level is RECOMMENDED for portability and readability.
To include multiple paragraphs or other block elements in a single list item, indent the continuation lines to align the text with the first line (ie. the indentation size is the number of characters in the list marker plus its trailing space).
A fenced code block inside a list item MUST be indented to that same column, or CommonMark treats it as ending the list item rather than as content within it:
``
1. First item.
```sh echo "This code block belongs to the list item." ```
- Second item.
``
An indented code block (four-space indentation, without fences) is a valid alternative inside a list item, since its indentation already establishes it as belonging to the item. Fenced code blocks are still RECOMMENDED over indented ones, per Code, provided the fence itself is indented to align with the item’s own content.
Like any other prose, a list item is wrapped according to the approach the repository has chosen — see Line length and wrapping.
Items longer than a short phrase — in particular, any item written as one or more full sentences — SHOULD be separated from each other by a blank line. An item of that length reads as a paragraph, and setting it off with a blank line, the same way paragraphs are set off from each other, materially improves the readability of the plain-text source. Short items MAY be kept tight, without blank lines between them.
- This is the first item. It is written as full sentences. - This is a separate item. - This is another item in the same list.
A common pattern is to bold a short lead-in term at the start of each item, followed by a full sentence explaining it. Use the following syntax. The lead-in term is terminated by a full-stop, rather than by a colon or hyphen, for the best accessibility.
- **Performance.** The system responds to user input within 100ms under normal load. - **Reliability.** The system continues to operate correctly in the presence of hardware or software faults. - **Scalability.** The system handles growth in data volume, traffic, or complexity without a redesign. - **Maintainability.** The system is easy for engineers to understand, modify, and extend over time.
Another pattern, supported by Markdown’s hard line break, is to put the lead-in term on its own line and indent the text beneath it. This has the visual effect of better differentiating the lead-in term, so it is rendered more like a heading. The hard line break is intentional, so the text after it is not a soft wrap — but that text is still wrapped according to the chosen approach.
- **Performance.** \ The system responds to user input within 100ms under normal load. - **Reliability.** \ The system continues to operate correctly in the presence of hardware or software faults. - **Scalability.** \ The system handles growth in data volume, traffic, or complexity without a redesign. - **Maintainability.** \ The system is easy for engineers to understand, modify, and extend over time.
For lists of key-value pairs, place the colon inside the bold marker.
- **Status:** Active - **Owner:** Platform team - **Region:** eu-west-1 - **Version:** 2.4.0
GFM task lists MAY be used where the rendering platform supports them:
- [x] Completed task - [ ] Outstanding task
Code
Inline code is written with single backticks. Code that itself contains backticks may be enclosed in double backticks, with a space between the backticks and the content for clarity.
Use the `console.log()` function.
Fenced code blocks are written using three backticks on the lines before and after the block. Fenced code blocks are RECOMMENDED over indented code blocks (four-space indentation), as they are easier to read and edit in source.
```json
{
"name": "example"
}
```A language identifier SHOULD be specified immediately after the opening fence to enable syntax highlighting where the renderer supports it. Use text or plaintext for examples that do not belong to a specific language. This disables syntax highlighting in renderings.
Escaping newlines in shell snippets
A multi-line shell or command snippet intended to be copy-pasted as a single command SHOULD escape its newlines with a trailing backslash, so that the shell continues the line rather than terminating the command early:
gcloud compute instances create example-instance \ --zone=us-central1-a \ --machine-type=e2-medium
Without the trailing backslash, a reader who copies the whole block and pastes it into a terminal gets each line executed as a separate command, which usually fails partway through. This does not apply to output examples or to snippets that are meant to be read rather than executed.
Placeholders
The general convention across these standards is to write placeholder text in angle brackets (<placeholder>), as specified in TS-26. Markdown is a partial exception, where the bracket style depends on whether the placeholder is code-formatted.
Where the placeholder sits inside a code span or a fenced code block, angle brackets SHOULD be used, consistent with the convention across these standards. Nothing inside code formatting is parsed as HTML, so the hazard below does not arise:
git clone git@<hostname>:<group>/<project>.git
Everywhere else — bare prose, headings, table cells — placeholder text MUST be written in square brackets ([placeholder]). Markdown permits raw HTML inline, so outside code formatting a <placeholder> would be interpreted as an unknown HTML element by parsers, and may be stripped or rendered unexpectedly.
YAML front matter MUST follow the same rule as the body: square brackets by default, angle brackets only where the value is code-formatted. The HTML hazard does not arise in front matter, so this is a simplification rather than a safeguard — one rule per document is easier to apply, and easier to check, than one rule for the body and another for its header.
For example:
Run the installer from [project-root], then open [entry-point].
Links
Links are written by enclosing the link text in square brackets, immediately followed by the URL in parentheses.
My favorite search engine is [Duck Duck Go](https://duckduckgo.com).
A link MUST NOT be broken across lines. The whole construct — the bracketed text, the parenthesized URL, and the boundary between them — MUST sit on a single source line. This holds whichever approach to wrapping prose is used (see Line length and wrapping), because a wrap between the closing ] and the opening ( breaks the link outright: CommonMark stops treating it as a link and renders the raw syntax as literal text.
Where a long URL makes the line uncomfortable to work with, use a reference-style link instead, as described below.
An optional title may be added in double quotes after the URL. The title is displayed as a tooltip in most renderers.
[Duck Duck Go](https://duckduckgo.com "A privacy-focused search engine")
Bare URLs and email addresses SHOULD be enclosed in angle brackets to ensure they are auto-linked:
<https://www.example.com> <user@example.com>
To prevent a URL from being auto-linked, wrap it in backticks:
`https://www.example.com`
Reference-style links
Reference-style links separate the link text from the URL, which can improve readability in documents that contain many long URLs. The link is written as [text][label], and the URL is defined elsewhere as [label]: url "optional title".
See the [CommonMark spec][cm] for details. [cm]: https://spec.commonmark.org/ "CommonMark Specification"
Reference-style links are most useful where an inline link would disrupt the surrounding prose: a long URL that would push the line well past the usual length, a link that needs to appear inside a table cell (where a long inline URL makes the cell unreadable and can break the table’s column alignment in source), or a destination that is linked to more than once in the same document. For a short link used once, an inline link is simpler and keeps the destination visible at the point of use — reserve reference-style links for the cases above rather than using them by default.
Reference definitions MAY be placed immediately after the paragraph that uses them or at the end of the document. In a longer document, prefer placing each definition just before the next heading that follows its first use — this keeps the definition close to its use without having to scan past that section’s other content, treating each section like a small page. Reserve placing definitions at the end of the document for labels that are reused across multiple sections, where no single section is the natural home for the definition.
Link text quality
Link text SHOULD describe the destination, not the action of clicking it. Write the sentence naturally, then wrap the most descriptive phrase as the link. Avoid generic link text such as "here", "link", or "click here", and avoid using a bare URL as the visible text where a descriptive phrase is available.
✅ See the [CommonMark specification](https://spec.commonmark.org/) for details. ❌ Click [here](https://spec.commonmark.org/) for the spec.
Descriptive link text is more accessible — screen reader users often navigate a page by jumping between links read out of context, where "here" conveys nothing — and it reads correctly even where the underlying URL changes or the document is printed without its hyperlinks.
Explicit paths for internal links
A link to another file in the same repository SHOULD use an explicit path, including the .md extension, rather than relying on the target platform to infer it:
✅ See the [contribution guide](../docs/CONTRIBUTING.md). ❌ See the [contribution guide](../docs/CONTRIBUTING).
Relative paths that climb outside the current directory (../) SHOULD be avoided except where the target is genuinely close by. Prefer an explicit path rooted at a stable location — such as the repository root, where the hosting platform supports it — over a chain of ../../../ segments, which is fragile if either file is later moved and hard for a reader to verify by eye.
URL encoding
Spaces and parentheses in URLs can cause parsing problems. Spaces in URLs SHOULD be URL-encoded as %20. Where a URL contains parentheses, consider using reference-style links or HTML <a> tags.
Internal versus external links
As with AsciiDoc (see TS-28), a link is either internal or external. An internal link is one to another document within the same repository, eg. another file in a docs/ directory or a sibling README; an external link is everything else, including a link to a different repository.
Internal links MUST be bold; external links MUST NOT be. The bold markup MUST sit tight around the link text, inside the square brackets, not wrapped around the whole link construct:
✅ [**Style guide**](./docs/style-guide.md) ❌ **[Style guide](./docs/style-guide.md)**
A reader can then tell from the styling alone whether a link keeps them inside the current documentation set or takes them elsewhere.
Images
Images are written with an exclamation mark, followed by alternative text in square brackets, and the image path or URL in parentheses. An optional title may follow in double quotes.

All images MUST have alternative text. The alternative text SHOULD concisely describe the content of the image; see TS-26 for guidance.
To link an image, wrap the image syntax in a link:
[](https://www.example.com)
Markdown does not provide a standard way to set image dimensions. Where sizing or alignment is required, use an HTML <img> tag with explicit width and height attributes.
Reference-style images
Images MAY use the same reference-style form as reference-style links (see Reference-style links) — the image syntax with a label in place of the inline URL, and the URL defined elsewhere in the document:
![Alt text][logo] [logo]: /assets/images/logo.png "Company logo"
This is most useful where the same image is referenced from multiple places in a document, or where an inline URL would disrupt the surrounding prose.
When to use images
Use images sparingly, and prefer simple screenshots over elaborate diagrams or composited graphics. Reach for an image where it is genuinely easier to show a reader something than to describe it in text — a UI navigation path, a layout, or a visual state — rather than as decoration.
An image cannot be searched, diffed meaningfully in version control, or read by a screen reader beyond its alternative text. Where a diagram is a better fit than a screenshot, and the document’s rendering target supports it, prefer AsciiDoc; see TS-28.
Blockquotes
A blockquote is written by prefixing a line with a right angle bracket (>) and a single space.
> This is a quoted paragraph.
Blockquotes with multiple paragraphs require a > on each blank line between paragraphs:
> First paragraph. > > Second paragraph.
Blockquotes MAY be nested by adding additional > characters. Other block elements, such as lists and code blocks, MAY be included inside a blockquote by prefixing their lines with >.
Blockquotes SHOULD be surrounded by blank lines.
Callouts
Callouts, also known as alerts or admonitions, are a GitHub extension that renders a blockquote as a highlighted, labeled panel. A callout is written as a blockquote whose first line is a bracketed, exclamation-prefixed keyword.
> [!NOTE] > Useful information that readers should know.
Five keywords are supported: [!NOTE], [!TIP], [!IMPORTANT], [!WARNING], and [!CAUTION]. The keyword MUST be uppercase and on its own line, with the callout content following on subsequent blockquote lines.
Callouts MAY be used in documents targeting GitHub. Because they are a GitHub extension rather than part of the GFM specification, they are not portable: on renderers that do not support them, they degrade to an ordinary blockquote containing the literal keyword text. For admonition-heavy technical documentation that must render across platforms, AsciiDoc is RECOMMENDED instead. See TS-28.
Tables
Tables are a GFM extension. They are written with a header row separated by hyphens, and cells separated by pipes.
| Syntax | Description | | ----------- | ----------- | | Header | Title | | Paragraph | Text |
A pipe SHOULD be placed at the start and end of each row for portability. The hyphens in the separator row need not be aligned with the column widths; the rendered output is unaffected.
Column alignment is controlled by colons in the separator row:
| Left | Center | Right | | :----- | :----: | ----: | | Left | Center | Right |
Tables SHOULD be used sparingly in Markdown. Markdown tables do not support cell spanning, and block-level elements such as lists, headings, or nested tables cannot be placed inside cells. For complex tables, use AsciiDoc; see TS-28.
Inline Markdown formatting — emphasis, bold, inline code, and links — MAY be used within a table cell, and renders as expected:
| Option | Description | | ---------- | -------------------------------- | | `--force` | Skip the **confirmation** prompt. |
This is distinct from block-level elements, which cannot be placed inside cells at all, per the constraint above.
To display a literal pipe character inside a cell, use its HTML character reference (|).
Tables versus lists
Before writing a table, consider whether a list would present the same information more clearly. A table is a poor fit where a column carries only one or two distinct values across all rows, where the row-to-column ratio is heavily skewed (many rows against few columns, or vice versa), or where a cell’s content is a full sentence rather than a short value — rambling prose in a cell is harder to scan than the same content in a bulleted list.
❌ | Feature | Supported | | ------------- | --------- | | Dark mode | Yes | | Offline mode | No | | Notifications | Yes | ✅ Supported features: dark mode, notifications. Not supported: offline mode.
A table earns its place where the reader genuinely needs to compare values across two or more dimensions at a glance. Where the content is closer to a flat enumeration, prefer a list.
Horizontal rules
A horizontal rule is created with three or more asterisks (*), hyphens (---), or underscores (_) on a line by themselves.
Hyphens (---) are RECOMMENDED for consistency. A blank line MUST precede a horizontal rule; without one, a line of --- immediately after text may be interpreted as a setext heading.
Horizontal rules SHOULD be used sparingly to separate sections. Prefer headings for structuring content.
Escaping characters
A literal character that would otherwise be interpreted as Markdown formatting may be escaped by prefixing it with a backslash (\).
\* This is not a list item.
The following characters MAY be escaped:
\ ` * _ { } [ ] < > ( ) # + - . ! |Escaping SHOULD be used only where necessary. Prefer to restructure content to avoid ambiguity — for example, by adding blank lines around elements — rather than escaping many characters.
HTML
Most Markdown processors allow inline HTML. HTML is useful where Markdown lacks an equivalent, such as for setting image dimensions, controlling text color, or using <details> disclosure blocks.
This <em>word</em> is italic.
Block-level HTML elements such as <div>, <table>, and <pre> MUST be separated from surrounding Markdown by blank lines, and SHOULD NOT be indented.
Important
Markdown syntax is not processed inside block-level HTML tags. bold inside <div>bold</div> will be rendered as literal asterisks, not as bold text.
HTML SHOULD be used sparingly. Documents that rely heavily on HTML lose the portability and readability benefits of Markdown. For content that requires rich HTML, consider whether a more capable format such as AsciiDoc or direct HTML is more appropriate.
Embedding video
Markdown has no native syntax for embedding video, and most renderers strip <video> and <iframe> embeds for security reasons. The common workaround is a linked thumbnail image — an <a> tag wrapping an <img> of the video’s poster frame, pointing at the video’s hosted page:
<a href="https://www.youtube.com/watch?v=<video-id>"> <img src="https://img.youtube.com/vi/<video-id>/0.jpg" alt="Video title" width="480" height="360"> </a>
Clicking the thumbnail takes the reader to the video on its hosting platform rather than playing it inline. This keeps the document portable and avoids the security and privacy concerns of embedding third-party iframes directly.
Footnotes
Footnotes are an extension supported by GFM and several other processors, but not by pure CommonMark. A footnote reference is written as [^label], and the footnote content is defined as [^label]: text.
Here is a statement.[^1] [^1]: The supporting reference.
Footnote labels only correlate the reference with the definition; the rendered output is numbered sequentially regardless of the label.
Because footnote support is not universal, footnotes SHOULD be avoided in documents that must render across a wide range of Markdown processors. Prefer inline links for citations in portable documents.
Line length and wrapping
In CommonMark, a single newline inside a paragraph is a soft break, and it renders as a space. A paragraph split across several source lines therefore renders identically to the same paragraph written on one line. How prose is wrapped in the source is a decision about diffs, editing, and review, not about rendering. The same is true of most other lightweight markup languages.
The one exception is a line break that falls inside an inline construct — a bold or italic span, an inline code span, a link. Depending on the construct, the break can separate the markup from the text it applies to, so it may silently fail to render, or fail loudly by rendering the raw syntax as literal text. A wrapped line that happens to begin with a list marker, #, or > may also be parsed as the start of a new block.
There are three common approaches to wrapping prose in the source. Each has costs and benefits.
One line per paragraph
Each paragraph is written on a single source line, however long, and the editor soft wraps it for display (eg. "editor.wordWrap": "on" in VS Code).
- Benefits. It is the simplest approach. There is no reflow, and no wrap points to break an inline construct. It matches what most WYSIWYG-adjacent tools, such as note apps and Markdown exporters, produce.
- Costs. A one-word edit changes the whole paragraph’s line in a line-based diff. Word-level diffs (eg.
git diff --word-diff) and the intra-line highlighting in most code review tools take most of the sting out of this, but reviewers cannot comment on a specific sentence without quoting it.
Fixed-width hard wrapping
Lines are broken at a fixed column, usually 80, sometimes 72 or 100.
- Benefits. It is traditional, and it reads well in a terminal or plain-text viewer. It is the only sensible option where the consumer of the text cannot reflow it, such as commit messages, plain
.txtfiles, and READMEs that are meant to be read withcat. - Costs. Inserting a word near the top of a paragraph reflows every line below it. That inflates diffs, and it manufactures merge conflicts on exactly the kind of text that several people edit concurrently. Reflowing by hand invites the inline-construct breakage described above, so it works best with an editor or formatter that reflows automatically.
Semantic line breaks
Lines are broken at sentence ends, and sometimes at clause boundaries, but never at a column count. This is also called ventilated prose, or "one sentence per line". Brandon Rhodes popularised the approach in a 2012 essay, and sembr.org later wrote it up as a loose specification.
- Benefits. It gives the diff granularity of fixed-width wrapping without the reflow churn, because editing one sentence touches one line. Reviewers can comment on a specific sentence. It also makes over-long sentences visually obvious in the source.
- Costs. The raw file looks odd to people who have not seen the convention. Contributors who do not know about it will quietly reintroduce mixed styles.
Choosing an approach
This standard does not mandate one approach. It does set some ground rules for whichever is chosen:
- A repository SHOULD choose one approach for its Markdown prose and record the choice where contributors will find it, such as its contributing guide or
AGENTS.md. - Within a file, the chosen approach MUST be applied consistently. A file that mixes approaches has the costs of each and the benefits of none.
- When editing an existing file, follow the approach it already uses. Content MUST NOT be reflowed to a different approach as a side effect of an unrelated change.
- Where the text will be consumed without reflow, such as a commit message or a plain-text file, fixed-width hard wrapping SHOULD be used.
- A link MUST NOT be broken across lines (see Links), so a line that contains a long link may run past the wrap column.
- A heading MUST NOT be broken across lines in any case. Markdown has no continuation syntax for a heading, so a wrap would either break it or become part of the heading text.
- The cells of a table row MUST each sit on a single source line, because the pipe table syntax requires it.
- Where a line break is needed in the rendered output, use a hard line break. See Paragraphs and line breaks.
Wrapping applies to prose only. Fenced and indented code blocks keep the line structure their content needs, and code samples follow the line-length rules of the relevant language standard.
Tooling
A linter SHOULD be used to enforce consistent Markdown style across a project. markdownlint is RECOMMENDED. It is configurable and widely supported.
A code formatter such as Prettier MAY be used to automate list indentation and code-block formatting. It MUST NOT be configured to reflow prose: set Prettier’s proseWrap to never, so each paragraph is put back onto a single line, or to preserve, so it leaves line structure alone. The default, preserve, is safe. Any linter rule that caps line length — markdownlint’s MD013, for one — MUST be disabled for prose, since the line-length rule here is that prose is not wrapped at all. Formatting and linting SHOULD be reconciled so they do not produce conflicting results.
A link checker SHOULD be run as part of continuous integration to detect broken internal and external links.
Editor configuration SHOULD ensure:
- Long lines are soft wrapped for display (eg.
"editor.wordWrap": "on"in VS Code), if the repository’s approach to wrapping calls for it. - Trailing whitespace is highlighted.
- Files end with a single newline character.
- Indentation uses spaces, not tabs.
References
- Google. Documentation Style Guide.