# Syntax Differences Between .Qmd and .Md


`.qmd` is the Markdown file format used by Quarto. A regular `.md` file mainly handles text formatting. `.qmd` adds executable code, output control, cross-references, callouts, shortcodes, and more on top of that.

Quarto is based on Pandoc Markdown, so most Markdown syntax still works: headings, lists, tables, footnotes, and equations. The real differences come from the syntax below.

Quarto official docs: [Quarto Guide](https://quarto.org/docs/guide/)

## 1. YAML does more than metadata

In a regular `.md` file, front matter usually stores a title, date, and tags. In `.qmd`, YAML also controls rendering, output formats, and code execution behavior.

```yaml
---
title: "Quarto Example"
format:
  html:
    toc: true
    code-fold: true
  pdf:
    documentclass: report
execute:
  echo: true
  warning: false
jupyter: python3
---
```

Here, `format` decides what the document is rendered into, and `execute` controls how code blocks run. `jupyter: python3` selects the Jupyter kernel.

The same `.qmd` file can be rendered to HTML, PDF, Word, or Reveal.js slides. A regular `.md` file is usually just static text, unless another tool processes it.

## 2. Code blocks can run

Code blocks in `.md` are mostly for display. Code blocks in `.qmd` can actually run, and Quarto inserts the results back into the rendered document.

````markdown
```{python}
import pandas as pd

df = pd.DataFrame({"name": ["Alice", "Bob"], "score": [95, 88]})
df
```
````

For R:

````markdown
```{r}
summary(cars)
```
````

Quarto binds an execution engine automatically based on code blocks. `{r}` usually uses knitr. `{python}`, `{julia}`, `{bash}`, and similar blocks generally use Jupyter. You can also set it manually:

```yaml
---
engine: jupyter
---
```

If you only want to show Quarto code block syntax without running it, use double braces:

````markdown
```{{python}}
print("display only, do not execute")
```
````

## 3. `#|` defines code block options

The most common special syntax in `.qmd` is `#|`. It appears at the top of an executable code block and controls the current cell.

````markdown
```{python}
#| label: fig-sales
#| fig-cap: "Monthly sales trend"
#| echo: false
#| warning: false

import matplotlib.pyplot as plt

plt.plot([12, 18, 15, 22])
plt.show()
```
````

Common options:

| Option    | Purpose                                                  |
| --------- | -------------------------------------------------------- |
| `echo`    | Whether to show source code                              |
| `eval`    | Whether to execute the code                              |
| `output`  | Whether to show execution output; `asis` emits raw Markdown |
| `warning` | Whether to show warnings                                 |
| `error`   | Whether to include errors in the document                |
| `include` | Whether to include code and results                      |
| `label`   | Names a code cell for references and debugging           |
| `fig-cap` | Figure caption                                           |
| `tbl-cap` | Table caption                                            |

Document-level defaults can go in YAML, then a single code block can override them with `#|`:

```yaml
---
execute:
  echo: false
  warning: false
---
```

## 4. Inline code can execute too

Inline code in regular Markdown is just monospace text, like `` `code` ``. `.qmd` can execute expressions inside prose.

````markdown
```{python}
radius = 5
```

The radius of the circle is `{python} radius`.
````

After rendering:

```text
The radius of the circle is 5.
```

R uses the same style:

```markdown
The radius of the circle is `{r} radius`.
```

This is useful when narrative text needs computed values. It is better to compute variables in normal code blocks first, then keep inline expressions simple.

## 5. Callout blocks

`.qmd` supports callouts wrapped in `:::`. Compared with plain blockquotes, they are better for notes, warnings, extra context, and pitfalls.

```markdown
::: {.callout-note}
This is a normal note.
:::

::: {.callout-tip title="Writing habit"}
The same note can keep a similar callout style in HTML and PDF.
:::

::: {.callout-caution collapse="true"}

## Expand to read

Put longer text here. It is collapsed by default.
:::
```

Quarto includes five built-in types: `note`, `tip`, `warning`, `caution`, and `important`.

You can adjust the appearance in YAML:

```yaml
---
callout-appearance: simple
callout-icon: false
---
```

## 6. Panel tabsets

Tutorials often need to show commands for different languages or operating systems. `.qmd` can use `.panel-tabset` to create tabs.

````markdown
::: {.panel-tabset}

## Python

```python
print("hello")
```

## R

```r
print("hello")
```

## Bash

```bash
echo "hello"
```

:::
````

When rendered to HTML, readers can switch between tabs. Regular `.md` can use multiple headings, but it does not have this built-in interactive structure.

## 7. Cross-references

Quarto cross-references are much stronger than plain Markdown links. Figures, tables, code listings, equations, and sections can be numbered automatically, then referenced with `@id`.

Figure reference:

```markdown
![Example image](image.png){#fig-demo}

See @fig-demo.
```

Table reference:

```markdown
| name  | score |
| ----- | ----: |
| Alice |    95 |
| Bob   |    88 |

: Score table {#tbl-score}

See @tbl-score.
```

Equation reference:

```markdown
Euler's formula is shown in @eq-euler.

$$
e^{i\pi} + 1 = 0
$$ {#eq-euler}
```

Section references require a `#sec-` ID on the heading and section numbering enabled:

```yaml
---
number-sections: true
---
```

```markdown
## Data processing {#sec-data}

See @sec-data.
```

The ID prefix matters. Use `fig-` for figures, `tbl-` for tables, `eq-` for equations, and `sec-` for sections. Quarto uses these prefixes to determine the reference type.

## 8. Code-generated figures and tables can be numbered

A figure produced by executable code can also be numbered. Add `label` and `fig-cap` to the cell.

````markdown
```{python}
#| label: fig-line
#| fig-cap: "Line chart"

import matplotlib.pyplot as plt

plt.plot([1, 2, 3], [1, 4, 9])
plt.show()
```

See @fig-line.
````

Tables work the same way:

````markdown
```{r}
#| label: tbl-cars
#| tbl-cap: "First rows of the cars dataset"

knitr::kable(head(cars))
```

See @tbl-cars.
````

The `label` must start with `fig-` or `tbl-`. Otherwise, Quarto will not treat it as a referenceable object.

## 9. Diagram code blocks

If you need flowcharts, sequence diagrams, state diagrams, Gantt charts, or similar diagrams, `.qmd` can write Mermaid and Graphviz directly. Whether a regular `.md` file can render these diagrams depends on the platform; Quarto treats them as executable cells.

Official docs: [Diagrams](https://quarto.org/docs/authoring/diagrams.html)

### I. Mermaid

Mermaid uses `{mermaid}` code blocks. Its cell options are not written with `#|`, but with `%%|`. The options must appear immediately after the opening fence.

````markdown
As shown in @fig-flow, the deployment flow is written directly in the document.

```{mermaid}
%%| label: fig-flow
%%| fig-cap: "Automated deployment flow"
flowchart LR
  A[Commit code] --> B{CI check}
  B -- Pass --> C[Build image]
  B -- Fail --> D[Notify developer]
  C --> E[Deploy]
```
````

Because the `label` starts with `fig-`, you can reference it with `@fig-flow`. `fig-cap` becomes the caption, and Quarto handles numbering.

Sequence diagrams use the same pattern:

````markdown
```{mermaid}
%%| label: fig-seq
%%| fig-cap: "Login request sequence"
sequenceDiagram
  participant Browser
  participant API
  participant DB
  Browser->>API: POST /login
  API->>DB: Query user
  DB-->>API: Return result
  API-->>Browser: Return token
```
````

### II. Graphviz

Graphviz uses `{dot}` code blocks. It is good for topology and dependency graphs, and it also works well for complex network structures. Its cell options are written as `//|`.

````markdown
```{dot}
//| label: fig-service-map
//| fig-cap: "Service dependency map"
digraph G {
  rankdir=LR;
  node [shape=box];

  "User" -> "Gateway";
  "Gateway" -> "Service A";
  "Gateway" -> "Service B";
  "Service A" -> "Redis";
  "Service B" -> "PostgreSQL";
}
```

See @fig-service-map.
````

Mermaid is concise and works well for tutorials or rough architecture sketches. Graphviz gives you more control over layout, so it tends to be steadier for dense relationship graphs.

### III. PlantUML

PlantUML is not part of Quarto's native diagram support. To write PlantUML directly in `.qmd`, use the `pandoc-ext/diagram` Lua filter.

Project: [pandoc-ext/diagram](https://github.com/pandoc-ext/diagram)

Install the Quarto extension first:

```bash
quarto install extension pandoc-ext/diagram
```

Then enable the filter in YAML:

```yaml
---
filters:
  - diagram
---
```

The filter calls external programs to generate images. For PlantUML, the system needs a working `plantuml` command. Common installations also need Java. If the command cannot be found, specify its path with an environment variable:

```bash
export PLANTUML_BIN=/usr/local/bin/plantuml
```

You can also pin the path in YAML:

```yaml
---
filters:
  - diagram
diagram:
  engine:
    plantuml:
      execpath: /usr/local/bin/plantuml
---
```

PlantUML code blocks use `{plantuml}`. The cell options use PlantUML's comment syntax, so the prefix is `'|`, not `#|`.

````markdown
As shown in @fig-login-puml, this login flow is drawn with PlantUML.

```{plantuml}
'| label: fig-login-puml
'| fig-cap: "User login sequence"
@startuml
actor User
participant "Web Portal" as Web
database "Auth DB" as DB

User -> Web: Enter credentials
Web -> DB: Verify user
DB --> Web: Return result
Web --> User: Login successful
@enduml
```
````

Class diagrams are also a natural fit for PlantUML:

````markdown
```{plantuml}
'| label: fig-class-puml
'| fig-cap: "User model class diagram"
@startuml
package "Domain" {
  class User {
    - username: String
    - passwordHash: String
    + login(): boolean
  }

  class Profile {
    - avatar: String
    - bio: String
  }

  User "1" *-- "1" Profile
}
@enduml
```
````

Diagrams generated by `pandoc-ext/diagram` can still use Quarto-style captions and cross-references. The `label` above starts with `fig-`, so the prose can reference it with `@fig-login-puml`.

The output format is selected based on the target format. It is commonly SVG or PNG, and can also be PDF. If one format does not work in your environment, disable it with `mime-type`:

```yaml
---
filters:
  - diagram
diagram:
  engine:
    plantuml:
      mime-type:
        application/pdf: false
---
```

This filter runs local commands, so do not use it with untrusted `.qmd` files. The repository README calls out this security issue as well.

Mermaid and Graphviz are built into Quarto and need less setup. PlantUML requires the filter and an external command-line tool, but it is better suited to UML modeling, such as class diagrams and use case diagrams.

### IV. External files

If a diagram gets long, you do not need to put all of it inside the `.qmd` file. Put Mermaid in `.mmd`, or Graphviz in `.dot`, then include it with `file`.

````markdown
```{dot}
//| label: fig-kernel
//| fig-cap: "Linux kernel structure diagram"
//| file: linux-kernel-diagram.dot
```
````

Mermaid can use the same style:

````markdown
```{mermaid}
%%| label: fig-state
%%| fig-cap: "Order state machine"
%%| file: order-state.mmd
```
````

This works well for complex diagrams. The `.qmd` file handles prose and references; the diagram source is maintained separately.

### V. Size and output formats

By default, Quarto renders diagrams at their natural size. In HTML output, diagrams are responsive to the page width, so they usually do not overflow the content column.

Use `fig-width` and `fig-height` when you need explicit sizing:

````markdown
```{mermaid}
%%| fig-width: 6.5
flowchart LR
  A[Start] --> B[Process]
  B --> C[End]
```
````

If you do not want HTML diagrams to resize responsively, turn it off:

```yaml
---
fig-responsive: false
---
```

Mermaid is handled differently across output formats. HTML usually uses Mermaid's JavaScript renderer, while `gfm` keeps the Mermaid code block. Print-oriented formats like PDF and docx generate PNG. Rendering diagrams for print formats uses Chrome or Edge; without a browser environment, install Quarto's headless shell:

```bash
quarto install chrome-headless-shell
```

You can also specify the Mermaid output format manually:

```yaml
---
format:
  html:
    mermaid-format: svg
---
```

Common values include `js` and `png`; `svg` is also available. If your target is a LaTeX-generated PDF, `svg` may require extra tools, so the default `png` is often simpler.

### VI. Themes and source display

Mermaid can follow the Quarto theme, or you can specify a Mermaid built-in theme:

```yaml
---
format:
  html:
    mermaid:
      theme: forest
---
```

Mermaid's built-in themes include `default`, `dark`, `forest`, and `neutral`.

Diagram cells do not show their source code in the rendered document by default. If you are writing a tutorial and want to show both source and rendered output, enable `echo`:

````markdown
```{mermaid}
%%| echo: true
flowchart LR
  A --> B
```

```{dot}
//| echo: true
graph G {
  A -- B
}
```
````

This is where `.qmd` is more complete than regular `.md`: diagrams are not just code blocks. They can participate in numbering, references, output conversion, and theme control. With filters like `pandoc-ext/diagram`, PlantUML can join the same writing workflow.

## 10. Citations

`.qmd` can handle references directly with Pandoc citation syntax. The common pattern is to declare `bibliography` in YAML, then cite entries in the body with `@key` or `[@key]`.

Official docs: [Citations](https://quarto.org/docs/authoring/citations.html)

Start with a BibTeX file such as `references.bib`:

```bibtex
@book{knuth1984,
  author    = {Donald E. Knuth},
  title     = {The TeXbook},
  year      = {1984},
  publisher = {Addison-Wesley}
}

@book{wickham2015,
  author    = {Hadley Wickham},
  title     = {R Packages},
  year      = {2015},
  publisher = {O'Reilly Media}
}
```

Then point the document at it in the front matter:

```yaml
---
title: "Quarto citation example"
bibliography: references.bib
---
```

In the body, you can write:

```markdown
This is a parenthetical citation [@knuth1984].

This adds a locator [@knuth1984, pp. 33-35].

You can cite multiple entries at once [@knuth1984; @wickham2015].

@knuth1984 brings the author name directly into the sentence.
```

If you do not place it manually, Quarto puts the bibliography at the end of the document. If you want to control its position, add a `refs` container:

```markdown
## References

::: {#refs}
:::
```

The default style is Chicago author-date. To switch to another style such as Nature or APA, add a CSL file:

```yaml
---
bibliography: references.bib
csl: nature.csl
---
```

If you want an entry in the bibliography without citing it in the body, use `nocite`:

```yaml
---
bibliography: references.bib
nocite: |
  @knuth1984
---
```

You can also include every entry from the `.bib` file:

```yaml
---
bibliography: references.bib
nocite: |
  @*
---
```

A regular `.md` file usually cannot do this on its own unless the publishing pipeline adds Pandoc or another citation processor on top.

## 11. Div and Span attributes

`.qmd` inherits Pandoc Markdown's attribute syntax. You can add classes, IDs, and attributes to block-level or inline content.

Block-level content:

```markdown
::: {#example .border}
This block has an ID and a class.
:::
```

Inline content:

```markdown
[These words are marked]{.mark}
```

This syntax may not work in regular Markdown renderers. Quarto passes it to Pandoc, then generates the right output for the target format.

Attribute order also matters: ID first, then classes, then key-value attributes.

```markdown
[Correct]{#id .class key="value"}
[Unreliable]{.class key="value" #id}
```

## 11. Shortcode

Quarto has its own shortcodes, with a form similar to Hugo:

```markdown
{{</* meta title */>}}
{{</* var version */>}}
{{</* pagebreak */>}}
{{</* kbd Ctrl-C */>}}
{{</* video https://www.youtube.com/embed/xxx */>}}
```

Common shortcodes:

| Shortcode   | Purpose                                      |
| ----------- | -------------------------------------------- |
| `meta`      | Reads document metadata                      |
| `var`       | Reads variables from `_variables.yml`        |
| `env`       | Reads environment variables                  |
| `include`   | Inserts content from another file            |
| `embed`     | Embeds a notebook cell                       |
| `pagebreak` | Inserts a page break                         |
| `kbd`       | Displays keyboard shortcuts                  |
| `video`     | Embeds a video                               |

If the article itself is talking about shortcodes, Quarto may try to process examples inside code blocks. You can use `shortcodes=false`:

````markdown
```{shortcodes=false}
{{</* var version */>}}
```
````

Or escape it with one extra pair of braces:

```markdown
{{{</* var version */>}}}
```

## 12. Reusing content with include

`.qmd` can use `include` to insert another file. This is useful for shared introductions, setup code, and common notes.

```markdown
{{</* include _intro.qmd */>}}
```

Included files usually start with an underscore, such as `_intro.qmd`. This prevents project rendering from treating them as standalone pages.

You can also include script content inside a code block:

````markdown
```python
{{</* include _demo.py */>}}
```
````

Two details are easy to miss:

- `include` must be on its own line, with blank lines around it.
- Include is basically copy and paste. Relative paths inside the included file are resolved from the main file's location.

## 13. Raw content blocks

`.qmd` can write raw content for a specific output format. For HTML:

````markdown
```{=html}
<iframe src="https://quarto.org/" width="600" height="400"></iframe>
```
````

LaTeX:

````markdown
```{=latex}
\newpage
```
````

This content only applies to the matching format. Be careful when writing multi-format documents. An HTML fragment usually does not mean much in PDF output.

## 14. Extensions and filters

Quarto can attach Lua filters or extensions. They are usually configured in YAML:

```yaml
---
filters:
  - diagram
---
```

Extensions can modify the AST, add output features, or package shortcodes. A regular `.md` file does not have this kind of project-level extension mechanism by itself, unless an external build system adds one.

## 15. When to choose `.qmd` or `.md`

If you are only writing a regular article, README, or project note, `.md` is lighter and can be viewed almost anywhere.

Use `.qmd` when you need these features:

- The document needs to run Python, R, Julia, or Bash code.
- Figures and tables need automatic numbering and references in the text.
- One source file needs to output HTML, PDF, Word, or slides.
- You want Mermaid, Graphviz, or PlantUML diagrams directly in the document.
- You want callouts, tabsets, variables, or includes to reuse content.
- The article and the data analysis workflow should live in the same file.

For migration, you can rename `.md` to `.qmd` first, keep the original Markdown content, then gradually add `#|`, callouts, and cross-references. This keeps the diff small and easy to roll back.


---

> Author: Nite  
> URL: https://www.nite07.com/en/posts/quarto-qmd-syntax/  

