# Writing pages

The Markdown that smalldocs reads, each feature with its source and its result.

A page is a Markdown file. smalldocs reads [CommonMark](https://commonmark.org), the standard form of
Markdown. It also reads some additions to Markdown, which this page describes:

- front matter, the options of the page at its top
- attributes, which give an id, classes or a width to a heading, a link or a picture
- divs, which are blocks with their own classes, and the callouts and tabs made from them
- lists with letters, figures, table captions, maths, diagrams and raw HTML
- content that only some builds show
- shortcodes, which put other text into the page

Each section below shows the source of a feature, and then the result.

## .md and .qmd files

A page can be a `.md` file or a `.qmd` file. smalldocs reads both in the same way. A `.qmd` file is a
Markdown file that uses the additions above. The name `.qmd` comes from Quarto, and the additions come
from the Markdown of [Pandoc](https://pandoc.org), as Quarto uses it. So name a page `.qmd` to show
that it uses them. A Markdown viewer that does not know them, such as the file view of GitHub, shows
them as plain text.

A page can also be a Jupyter notebook, a `.ipynb` file. See [Notebooks](notebooks.llms.md).

## Front matter

Front matter is a block of YAML between two `---` lines at the top of a page. It holds the options of
the page:

```markdown
---
title: Writing pages
description: The Markdown that smalldocs reads.
order: 3
---
```

The title goes at the top of the page and in the sidebar. [The configuration](config.llms.md) lists the
other options.

## Text

smalldocs changes some characters in text. To keep them as you type them, set the option
`from: markdown-smart`:

| You write | The page shows |
|---|---|
| `"quoted"` | "quoted" |
| `--` | -- |
| `---` | --- |
| `...` | ... |

Footnotes get numbers[^1]. Text can be ~~struck out~~, and `code` keeps its own characters.

[^1]: A footnote goes to the end of the page.

A subscript goes between tildes, and a superscript goes between carets. So `H~2~O` shows H~2~O, and
`x^2^` shows x^2^. A subscript or a superscript cannot hold a space. To put a space in one, write a
backslash before the space, as in `P~a\ b~`. Two tildes on each side still strike text out.

Term
: A definition list gives each term its definition.

- [x] A task list
- [ ] with boxes

## Lists

A numbered list can count with letters or with roman numerals. Write each item with a letter or a numeral,
and then a period or a parenthesis:

```markdown
a. One
b. Two

i) First
ii) Second

(c) A list can start at a letter other than a.
(d) And it goes on from there.
```

a. One
b. Two

i) First
ii) Second

(c) A list can start at a letter other than a.
(d) And it goes on from there.

A capital letter with a period needs two spaces after it, as in `A.  Text`. With one space, the line is
text, so a name such as "B. Smith" at the start of a line stays as it is. The same rule holds for the
capital roman numerals `I.`, `V.` and `X.`.

## Headings and attributes

Each heading has an id, so a link can point at it, as in `config.qmd#globs`. smalldocs makes the id
from the text of the heading. The id is in lower case, with a `-` between the words. It keeps letters,
digits, `_`, `-` and `.`, and it drops other punctuation and anything before the first letter. So
`## A _quarto.yml` gets the id `a-_quarto.yml`. Pandoc makes ids by the same rules, so a link written for
Pandoc or Quarto still works.

To give your own id and classes, put them in braces:

```markdown
## Install it {#install .important}
```

A link, a picture, a span and inline code take attributes too. A span is text in brackets with
attributes after it. Write `[text](url){.btn .btn-primary}`,
`![alt](pic.png){width=50%}` or `[red]{.text-danger}`. Here is [a button](get-started.llms.md){.btn .btn-primary .btn-sm}
and a <span class="text-danger">span with a class</span>.

## Divs

A div is a block of the page with its own attributes. A line of three or more colons starts or ends a
div. A line with attributes starts a div, and a line of colons only ends the innermost div. So divs can
nest, with lines of the same length:

```markdown
::: {.border .p-3}
Outer.

::: {.text-center}
Inner, in the centre.
:::
:::
```

<div class="border p-3">

Outer.

<div class="text-center">

Inner, in the centre.

</div>

</div>


A div can also sit in a list item or a quote, even on the item's first line, as in `1. ::: {.callout-note}`.
Indent its lines as far as the item's text. A `:::` ends only a div in its own list item or quote.
smalldocs reads divs as Pandoc does. The cases where the two differ are in `tests/fence_cases.json`,
each with its reason.

## Callouts

A callout is a box that sets off a note, a tip or a warning:

```markdown
::: {.callout-note}
A note, with the default title.
:::

::: {.callout-tip}
## A tip with its own title
The first heading in a callout becomes its title.
:::

::: {.callout-warning title="Folded" collapse="true"}
This warning opens when you click its title.
:::
```

<div class="callout-note">

A note, with the default title.

</div>


<div class="callout-tip">

## A tip with its own title
The first heading in a callout becomes its title.

</div>


<div class="callout-warning" title="Folded" collapse="true">

This warning opens when you click its title.

</div>


<div class="callout-important">

An important callout. A caution callout comes next.

</div>


<div class="callout-caution" appearance="simple">

A caution with `appearance="simple"`.

</div>


The attribute `appearance` takes `default`, `simple` or `minimal`, and `icon=false` removes the icon. To
set them for each callout of a page, use the options `callout-appearance` and `callout-icon` in the front
matter or in the config. The attributes of one callout still win over the options:

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

## Tabs

A tabset is a group of tabs. In a div with the class `panel-tabset`, each heading becomes a tab:

<div class="panel-tabset" group="language">

## Python

```python
def greet(name: str) -> str:
    "Say hello."
    return f"Hello, {name}!"
```

## Shell

```bash
for name in Ann Bo; do echo "Hello, $name!"; done
```

## Prose

A tab can hold any Markdown.

</div>


Tabsets with the same `group` attribute switch together. If you choose the tab "Shell" in one tabset,
each other tabset of the group shows its tab "Shell" too. The browser keeps the choice for the next page
that has the group. Click a tab below, and then look at the tabset above it:

```markdown
::: {.panel-tabset group="language"}
## Python
...
## Shell
...
:::
```

<div class="panel-tabset" group="language">

## Python

```python
print("Hello from a tabset of the group language.")
```

## Shell

```bash
echo "Hello from a tabset of the group language."
```

</div>


## Code

smalldocs colours code with [Pygments](https://pygments.org), in the light theme and in the dark
theme. See [Themes](themes.llms.md). A copy button shows when the pointer is on the code. A `filename` goes above the code:

```{.python filename="hello.py"}
import sys

def main() -> int:
    for arg in sys.argv[1:]:
        print(arg.upper())  # one line each
    return 0
```

A `diff` block shows a change to files, as `git diff` prints it. As on GitHub, smalldocs shows each
removed line in red and each added line in green. The `---` and `+++` lines that name the files are red
and green too. A hunk header, the line that starts with `@@`, is grey on a blue band. A `diff --git` or
`index` line is grey and bold. The other lines keep their text as written, with the space at their start.

The names `udiff` and `patch` do the same. In a combined diff from a merge, smalldocs colours only the
lines that start with `+` or `-`. Quarto and Pandoc colour a diff in the colours of strings and
variables, and not in red and green.

```diff
--- a/hello.py
+++ b/hello.py
@@ -3,3 +3,3 @@
 def main() -> int:
-    for arg in sys.argv:
+    for arg in sys.argv[1:]:
         print(arg.upper())  # one line each
```

A code block whose fence names a language in braces, such as `{python}` or `{r}`, is a cell. A cell is
code that is meant to run when the page is built, with its output in the page. smalldocs does not run
code. It shows the cell as code, and the page shows no output. The build gives a warning for each page
with cells.

A cell can start with option lines that begin with `#|`. smalldocs removes these lines. It hides the
cell for `#| echo: false` or `#| include: false`. To hide every cell of a page, set `echo: false` in its
front matter.

### Line numbers, long lines and folded code

To number the lines of a code block, give it the attribute `code-line-numbers="true"`. To number the lines
of every block of a page, set the option `code-line-numbers: true`. A link to a line, such as `#cb1-2`,
goes to that line:

```{.python code-line-numbers="true"}
def area(width: float, height: float) -> float:
    "Give the area of a rectangle."
    return width * height
```

A long line scrolls to the side. To wrap it onto the next line, set `code-overflow: wrap` for the page,
or give one block the attribute `code-overflow="wrap"`:

```{.python code-overflow="wrap"}
message = "This line is too long for the column of text, so it wraps onto the next line and does not scroll to the side."
```

To fold the code of a cell, set `code-fold: true`. The page then shows a line with the word "Code", and
the code opens when you click the line. With `code-fold: show`, the code starts open. `code-summary`
gives other words for the line. A cell can set both options for itself in its `#|` lines. smalldocs folds
only cells, and not other code blocks:

````markdown
```{python}
#| code-fold: true
#| code-summary: "Show the code"
import math

print(math.pi)
```
````

The folded cell looks like this:

<details class="code-fold">
<summary>Show the code</summary>

```python
import math

print(math.pi)
```

</details>

A cell of a notebook takes these options only from its own `#|` lines. The options of the page do not
apply to it. See [Folded code and line numbers](notebooks.llms.md#folded-code-and-line-numbers).

## Raw HTML

HTML in the Markdown goes into the page unchanged. A block marked `{=html}` also goes in unchanged:

```{=html}
<p class="text-success">This paragraph came from a raw HTML block.</p>
```

## Figures

A picture alone in its paragraph becomes a figure, if it has alt text. The alt text becomes the
caption:

![The smalldocs mark, drawn as an SVG.](../images/mark.svg){width=120px}

A figure starts at the left of the column, and its picture is in the centre of the figure, over the
caption. Quarto puts the whole figure in the centre of the column. The attribute `fig-align` puts the
figure at the `left` or the `right`. The option `fig-align` does the same for each figure of a page.

A screen reader reads the alt text of a picture. The attribute `fig-alt` gives an alt text that differs from the caption:

```markdown
![The mark at the right.](../images/mark.svg){width=80px fig-align="right" fig-alt="A small logo."}
```

![The mark at the right.](../images/mark.svg){width=80px fig-align="right" fig-alt="A small logo."}

### Figures side by side

A div with `layout-ncol` puts its blocks in columns. Each block, such as a figure or a paragraph, goes in
a cell of its own. `layout-nrow` gives the number of rows. `layout` gives the width of each cell in each
row. So `layout="[[1,1],[1]]"` makes two cells in the first row and one wide cell in the second.
smalldocs does not read a negative width, which Quarto reads as an empty space.

On a phone, the cells go one under the other:

```markdown
::: {layout-ncol=2}
![Left](../images/mark.svg){width=60px}

![Right](../images/mark.svg){width=60px}
:::
```

<div layout-ncol="2">

![Left](../images/mark.svg){width=60px}

![Right](../images/mark.svg){width=60px}

</div>


## Tables

A table has a row of headings, a row of dashes, and a row for each line of the table. A `|` goes
between the cells:

| Feature | Written as | Note |
|---|---|---|
| A column | `\| a \|` | Put `\|` at both ends of each row |
| Alignment | `\|:---\|---:\|` | A colon sets the side |
| `\|` in a cell | `\\|` | A backslash before it |

smalldocs does not read the grid tables of Pandoc, which are drawn with `+` and `-`.

### Table captions

A paragraph that starts with `: ` or `Table: ` is the caption of the table directly before it or directly
after it. Attributes in braces at the end of the caption belong to the table. The classes `.striped`,
`.hover`, `.bordered` and `.sm` give the Bootstrap styles of the same names:

```markdown
| Shortcode | Kind |
|---|---|
| `kbd` | Inline |
| `video` | Block |

: Two shortcodes. {#tbl-shortcodes .striped}
```

| Shortcode | Kind |
|---|---|
| `kbd` | Inline |
| `video` | Block |

: Two shortcodes. {#tbl-shortcodes .striped}

A caption with an id, such as `#tbl-shortcodes`, puts the table in a figure with that id. A link to
`#tbl-shortcodes` goes to the table. smalldocs does not number tables. The caption goes above the table.
The option `tbl-cap-location` moves it to the `bottom`, or into the `margin`. The attribute
`tbl-cap-location` in the braces does the same for one table.

## Content for some builds only

smalldocs shows or leaves out a div or a span with the class `.content-visible` or `.content-hidden`, by
these attributes:

| Attribute | Holds when |
|---|---|
| `when-format="html"` | The page is built as HTML. smalldocs builds only HTML, so `html`, `html:js` and `html5` hold, and other formats, such as `pdf`, do not |
| `when-format="llms-txt"` | The text is the Markdown copy of the page, with `llms-txt` on. See [Pages for agents](llms.llms.md) |
| `when-meta="key"` | The option of the page with that key is true. A key such as `book.draft` reads a nested option |
| `when-profile="name"` | The environment variable `QUARTO_PROFILE`, a list of names with commas, has the name |
| `unless-format`, `unless-meta`, `unless-profile` | The same test does not hold |

smalldocs shows a `.content-visible` div when all its attributes hold. It leaves out a `.content-hidden`
div when all its attributes hold. Content that it leaves out is not in the HTML, and the search box does not
find it:

```markdown
::: {.content-visible when-format="html"}
smalldocs shows this paragraph.
:::

::: {.content-visible when-format="pdf"}
smalldocs leaves this paragraph out.
:::
```

smalldocs shows this paragraph.


## The margin and wide content

The margin is the column at the right of the text, where the table of contents is. A note in the
margin stands beside the text that it belongs to. smalldocs reads the classes of Quarto for it.

<div class="column-margin">

This note is in a `.column-margin` div. It stands beside the paragraph below it.

</div>


A div with the class `.column-margin` goes in the margin. It starts level with the next paragraph,
and it can hold any Markdown:

```markdown
::: {.column-margin}
A note in the margin.
:::
```

A span with the class `.aside` goes in the margin, level with its line. Write it as
`[a short note]{.aside}`, for example <span class="aside">a note from a span</span> in this paragraph.

### Footnotes in the margin

To put each footnote in the margin, set `reference-location` in the config or in the front matter:

```yaml
reference-location: margin
```

Each footnote then goes beside the paragraph that cites it first, and not to the end of the page. The
links to the footnotes keep their anchors, `#fn1` and `#fnref1`, as in Quarto.

### Captions in the margin

To put the caption of each figure in the margin, set `fig-cap-location: margin`. For one figure,
give the attribute `fig-cap-location=margin` to the picture. A figure with the
class `.column-margin` goes in the margin itself, with its caption under it.

### Content wider than the text

A div with one of these classes is wider than the text:

| Class | Width |
|---|---|
| `.column-body-outset` | A little wider than the text, on both sides |
| `.column-page` | From a little left of the text to the right side of the margin |
| `.column-page-inset` | A little narrower than `.column-page` |
| `.column-screen` | The whole width of the window |
| `.column-screen-inset` | The width of the window, less a small space at each side |
| `.column-screen-inset-shaded` | The same, with a shaded background |

Each class except `.column-page-inset` and `.column-screen-inset-shaded` also has a `-left` and a
`-right` form, which is wide on one side only. A figure in such a div fills its width if the figure
has `width=100%`.

On a narrow screen, the content of the margin goes into the text, after the paragraph it belongs to.
Content for a wide column takes the width of the text. If margin or wide content passes under the
sidebar or the table of contents, that panel is hidden until the content has passed.

## Maths

Inline maths goes between dollars, as in $e^{i\pi} + 1 = 0$. Display maths goes between double dollars:

$$
\int_0^1 x^2 \, dx = \frac{1}{3}
$$

Double dollars inside a sentence also give display maths, on a line of its own, as in Quarto.

KaTeX, a JavaScript library, draws the maths. smalldocs loads KaTeX only on pages that have maths.

smalldocs reads a dollar as the start of maths when it has no digit before it and no space after it.
The maths ends at the next dollar in the paragraph. If that dollar has a space before it or a digit
after it, the first dollar is only a dollar. So the text "it costs $5 and $10" stays as it is. To keep
one dollar as a dollar, write `\$`.

For text with many prices, set the option `from: markdown-tex_math_dollars`, in the front matter or in
`_smalldocs.yml`. Then each dollar is a dollar, and smalldocs draws no maths written with dollars.

## Diagrams

The JavaScript library mermaid.js draws a `mermaid` block. smalldocs loads it only on pages that have a
diagram:

```{mermaid}
flowchart LR
  A[_smalldocs.yml] --> B(smalldocs render)
  C[pages] --> B
  B --> D[_site]
```

## Shortcodes

A shortcode is a tag in double braces that smalldocs replaces before it reads the Markdown. smalldocs
replaces these shortcodes everywhere except in code blocks:

| Shortcode | Becomes |
|---|---|
| `{{< include _part.qmd >}}` | The file, without its front matter |
| `{{< meta title >}}` | An option of the page: Writing pages |
| `{{< var version >}}` | A value from `_variables.yml`, a YAML map of names to values at the root of the project |
| `{{< env HOME >}}` | An environment variable |
| `{{< kbd Shift-Ctrl-P mac=Shift-Command-P >}}` | Keys to press: <kbd title="Shift-Ctrl-P, mac: Shift-Command-P" aria-hidden="true" data-mac="Shift-Command-P">Shift-Ctrl-P</kbd><span class="visually-hidden">Shift-Ctrl-P</span>. `mac`, `win` and `linux` give the keys on each system, which show when the pointer is on the keys |
| `{{< video https://www.youtube.com/watch?v=ID >}}` | A video. A YouTube, Vimeo or Brightcove address becomes a player from that site. A file becomes a `<video>` with controls, and smalldocs copies the file into the site. `title`, `width`, `height`, `aspect-ratio` and `start` set the video |
| `{{< lipsum 2 >}}` | Two paragraphs of placeholder text |
| `{{< placeholder 120 40 >}}` | A grey box of 120 by 40 pixels, in place of a picture: <img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMjAiIGhlaWdodD0iNDAiIHZpZXdCb3g9IjAgMCAxMjAgNDAiPjxyZWN0IHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9IiNjZWQ0ZGEiLz48dGV4dCB4PSI1MCUiIHk9IjUwJSIgZmlsbD0iIzZjNzU3ZCIgZm9udC1mYW1pbHk9InNhbnMtc2VyaWYiIGZvbnQtc2l6ZT0iOCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZG9taW5hbnQtYmFzZWxpbmU9Im1pZGRsZSI+MTIwIMOXIDQwPC90ZXh0Pjwvc3ZnPg==" class="img-fluid" alt="" width="120" height="40"> |

To show a shortcode as it is, put `/*` and `*/` inside its braces. The left column of the table does
so in its source.
