What Is Markdown?
Markdown is a lightweight markup language created by John Gruber and Aaron Swartz in 2004, designed to be readable as plain text while also converting cleanly to HTML. The core philosophy: the source should look good as plain text, not be cluttered with tags. An .md or .markdown file is plain text that any text editor can open, but that rendering tools convert to formatted HTML, PDF, DOCX, or other formats.
Markdown is now ubiquitous in technical writing:
- GitHub, GitLab, Bitbucket: All README files, wikis, and issue comments use Markdown
- Static site generators: Jekyll, Hugo, Gatsby, Astro all use Markdown for content
- Documentation platforms: ReadTheDocs, GitBook, Docusaurus, MkDocs
- Note-taking apps: Obsidian, Logseq, Notion, Bear, iA Writer
- Developer tools: Jupyter notebooks, VS Code preview, Slack (subset), Discord
Markdown Syntax
Headings
# Heading 1 (H1) — one # sign
## Heading 2 (H2) — two # signs
### Heading 3 (H3)
#### Heading 4 (H4)
Alternate syntax (Setext style):
Heading 1
=========
Heading 2
---------
Emphasis
**Bold text** or __bold__
*Italic text* or _italic_
***Bold and italic*** or ___triple underscores___
~~Strikethrough~~ (GFM extension)
`Inline code` — monospace, not processed
Lists
Unordered list:
- Item one
- Item two
- Nested item (2-space or tab indent)
- Another nested
- Item three
Ordered list:
1. First item
2. Second item
3. Third item
Mixed:
1. Ordered top-level
- Unordered nested
- Another nested item
Links and Images
[Link text](https://example.com)
[Link with title](https://example.com "Hover tooltip text")
[Reference link][link-id]
[link-id]: https://example.com


![Reference image][img-id]
[img-id]: image.png "Optional title"
Autolinks: <https://example.com>
Blockquotes and Code
> This is a blockquote.
> It can span multiple lines.
>> Nested blockquote
Fenced code block (specify language for syntax highlighting):
```python
def hello(name):
return f"Hello, {name}!"
Indented code block (4 spaces): def hello(): pass
### Horizontal Rules
```markdown
--- (three or more hyphens)
*** (three or more asterisks)
___ (three or more underscores)
Markdown Flavors and Specs
The original Markdown spec (2004) was underspecified, leading to inconsistent implementations. Several standardization efforts emerged:
CommonMark
A strict, unambiguous specification (spec.commonmark.org, 2014+) that resolves ambiguities in Gruber's original spec. Defines exactly how edge cases behave. Used by GitHub (as base for GFM), Reddit, Stack Overflow.
GFM (GitHub Flavored Markdown)
A CommonMark superset with GitHub-specific extensions:
- Tables (pipe syntax)
- Task lists (checkboxes)
- Strikethrough (
~~text~~) - Autolinks (bare URLs become links)
- Fenced code blocks with language specifier
GFM Tables
| Column 1 | Column 2 | Column 3 |
|----------|:--------:|----------:|
| Left | Center | Right |
| Aligned | Aligned | Aligned |
Minimum valid table:
| A | B |
|---|---|
| 1 | 2 |
GFM Task Lists
- [x] Completed task
- [x] Another done item
- [ ] Pending task
- [ ] Another to-do
MultiMarkdown (MMD)
Extended with metadata (frontmatter), footnotes, citations, definition lists, math (LaTeX syntax), file transclusion. Used in academic and technical writing.
Pandoc Markdown
The most feature-rich flavor, adding:
- YAML frontmatter metadata
- Citations and bibliographies (
[@citation-key]) - Footnotes (
[^1]) - Definition lists
- Superscript/subscript (
H~2~O,x^2^) - Math blocks (
$...$,$$...$$) - Div and span with attributes
YAML Frontmatter
Many Markdown processors support YAML frontmatter — structured metadata at the top of a file between --- delimiters:
---
title: "My Document"
author: "Jane Smith"
date: 2025-03-15
tags: [programming, documentation]
draft: false
toc: true
---
# First Heading
Document content begins here...
Frontmatter is used by static site generators (Hugo, Jekyll, Gatsby) and Pandoc for document metadata.
Converting Markdown
Pandoc — The Universal Converter
# Markdown to HTML
pandoc input.md -o output.html
# Markdown to standalone HTML (with CSS)
pandoc -s input.md -o output.html --css styles.css
# Markdown to PDF (requires LaTeX)
pandoc input.md -o output.pdf
# Markdown to PDF via HTML (no LaTeX needed, uses wkhtmltopdf)
pandoc input.md -t html | wkhtmltopdf - output.pdf
# Markdown to DOCX
pandoc input.md -o output.docx
# Markdown to DOCX with custom template
pandoc input.md --reference-doc=template.docx -o output.docx
# Markdown to EPUB
pandoc input.md -o output.epub --epub-cover-image=cover.jpg
# Markdown with citations to PDF
pandoc input.md --bibliography refs.bib --csl apa.csl -o output.pdf
# Multiple Markdown files concatenated
pandoc chapter1.md chapter2.md chapter3.md -o book.pdf
Python Markdown Processing
import markdown
# Basic Markdown to HTML
with open('input.md') as f:
text = f.read()
html = markdown.markdown(text, extensions=[
'tables',
'fenced_code',
'codehilite',
'toc',
'footnotes',
])
print(html)
Node.js (marked, remark)
import { marked } from 'marked';
import { readFileSync } from 'fs';
const md = readFileSync('input.md', 'utf-8');
const html = marked.parse(md);
console.log(html);
// With custom renderer
const renderer = new marked.Renderer();
renderer.heading = (text, level) => `<h${level} class="heading-${level}">${text}</h${level}>`;
marked.setOptions({ renderer });
CLI tools
# markdown-it (Node.js)
npx markdown-it input.md > output.html
# cmark (CommonMark reference implementation in C)
cmark input.md > output.html
cmark --to latex input.md > output.tex
# mdBook (Rust, for book-like output)
mdbook build --dest-dir ./book ./
Markdown Linting and Validation
Markdown linting catches style inconsistencies:
# markdownlint (Node.js)
npm install -g markdownlint-cli
markdownlint **/*.md
# Common rules:
# MD013: Line length (default 80 chars)
# MD022: Headings should be surrounded by blank lines
# MD032: Lists should be surrounded by blank lines
# MD041: First line should be a top-level heading
Markdown vs Alternative Lightweight Markup Languages
| Feature | Markdown | reStructuredText (RST) | AsciiDoc | Org-mode |
|---|---|---|---|---|
| Learning curve | Lowest | Medium | Medium | High |
| Spec conformance | GFM/CommonMark | Docutils spec | AsciiDoc spec | Emacs Org spec |
| Math support | Via MathJax/KaTeX | Decent | Good | Excellent |
| Cross-references | Limited | Full (RST roles) | Full | Full |
| Output targets | HTML, PDF, DOCX | HTML, PDF, EPUB | HTML, PDF, EPUB, DocBook | HTML, PDF, LaTeX |
| Primary use | Dev docs, GitHub | Python docs (Sphinx) | Technical books, docs | Emacs power users |
| Table support | GFM only | Full | Full | Full |
Markdown Best Practices
For documentation:
- Use ATX headings (
#) rather than Setext headings - Keep lines under 100 characters (easier diffs in version control)
- Always add alt text to images
- Use reference-style links for readability in dense documents
- Add blank lines before and after headings and code blocks
- Use sentence-case for headings (not Title Case) in technical docs
For maintainability:
- Validate frontmatter schema (YAML linting)
- Use a linter (markdownlint) in CI pipelines
- Pin the Pandoc/remark version to avoid behavior changes
- Store images near the Markdown files they reference (relative paths)
Markdown's enduring appeal lies in its balance: enough structure to enable automation, enough simplicity to remain readable as source code. That balance has made it the de facto standard for developer-facing documentation in a remarkably short time.
Related conversions
Document conversions that follow this topic naturally: