The block grammar

A content file is optional YAML front matter, then blocks. A block is a run of lines between an opening ::: kind line and a closing ::: line. Blocks nest one level deep. The format has ten blocks and one fenced language, plot.

The ten blocks

BlockIdSits inHoldsIs
::: cardnonea deckMarkdownone step of the deck
::: figureoptionala deckMarkdowna picture with a caption, as a card
::: flashcardoptionala deckMarkdown, answer, solutiona practice item, after the cards or between two
::: questionoptionala checkpointMarkdown, answer, solutiona question of an exam
::: answernonea flashcard, a questionMarkdownthe back of the flashcard, or the answer to the question
::: solutionnonea flashcard, a questionMarkdownthe full working
::: referencerequireda deck# Title, Markdown, equation, legend, derivationa result to look up
::: equationnonea referenceplain LaTeXthe bare equation
::: legendnonea reference$symbol$: meaning rowswhat each symbol means
::: derivationnonea referenceMarkdownwhy the reference holds

An index.md holds no blocks. Its front matter is all that counts, and text after the front matter is an error.

Each block has its own page: Decks and cards for card and figure, Flashcards and solutions for flashcard, answer and solution, Exams for question, and References and derivations for reference, equation, legend and derivation.

The syntax

Front matter

The front matter starts on the first line of the file, with a line that holds only ---. It ends at the next line that holds only ---. Between the two lines, write YAML.

---
title: Ohm's law
---

A file without a first --- line has no front matter. A file whose front matter never closes has no front matter either: the parser reads the whole file as body.

An opening line

An opening line starts with :::, then the kind of the block, then an optional id:

::: flashcard q1
  • Spaces before ::: and between the words have no effect.
  • The id is the first word after the kind. Further words have no effect.
  • The compiler reads the id of a flashcard, a question, a figure and a reference. It ignores a word after any other block.
  • An id is one word: it contains no space.

A closing line

A closing line holds ::: and nothing else. It closes the block that opened last.

Nesting

A block inside another block opens and closes inside it. Close the inner block first. Blocks nest one level only: a block inside a block cannot hold a third block.

::: flashcard q1
Solve $3x - 6 = 9$ for $x$.

::: answer
$x = 5$.
:::

::: solution
$$ 3x - 6 = 9 \implies 3x = 15 \implies x = 5 $$ ∎
:::
:::

The last ::: closes the flashcard. Indentation is optional. You can indent the inner blocks for clarity, but do not indent Markdown by four spaces or more: Markdown reads such lines as code.

Fenced code

Inside a fenced code block, a ::: line is content, not a marker. A fence opens with three or more backticks or tildes, and it closes on a line that starts with the same run. So a card can show the format itself:

::: card
A card opens like this:

```markdown
::: card
One idea.
:::
```
:::

A fence with the language plot is a live plot (Live plots). Any other fence shows as code.

Where each block can sit

Five blocks can stand at the top level of a file: card, figure, flashcard, question and reference. The other five always sit inside a parent.

FileTop-level blocks
a deckcard, figure, flashcard, reference
a checkpointquestion
an index.mdnone
ParentChildren
flashcard, questionanswer, solution
referenceequation, legend, derivation
any other blocknone

The faults

The checker reports a fault in the grammar with its file and its line.

FaultMessage
a word that is not a blockERROR ./math/alg/linears/solving.md:23: `lesson` is not a block: the grammar is card, figure, flashcard, question, answer, solution, reference, equation, legend, derivation
a block that never closesERROR ./math/alg/linears/solving.md:23: block `card` is never closed: add a `:::` line
a ::: that closes nothingERROR ./math/alg/linears/solving.md:23: `:::` closes nothing here
a block two levels deepERROR ./math/alg/linears/solving.md:27: `::: card` opens two blocks deep, and a block nests one level at most (an `answer` in a `flashcard`, a `legend` in a `reference`): close the block above it first
a child block at the top levelERROR ./math/alg/linears/solving.md:23: `answer` cannot sit on its own: it belongs inside the block it explains
a block in the wrong parentERROR ./math/alg/linears/solving.md:24: `answer` cannot sit inside `card`
a block in the wrong fileERROR ./math/alg/linears/index.md:5: `card` cannot sit inside `topic`
text outside a block in a deckERROR ./math/alg/linears/solving.md:5: this text sits outside any block, so the app never shows it: put it in a `::: card`, or take it out
text after the front matter of an index.mdERROR ./math/alg/linears/index.md:7: this text sits outside any block, so the app never shows it: an `index.md` holds front matter and nothing else: take it out
a flashcard without an answerERROR ./math/alg/linears/solving.md:9: this block has no `::: answer`: a flashcard needs its back, and a question its answer
the block of format 2ERROR ./math/alg/linears/solving.md:9: `exercise` is not a block since format 3: write `flashcard` in a deck and `question` in a checkpoint
two flashcards with one idERROR ./math/alg/linears/solving.md:13: `q1` is already the id of another flashcard in this file, at line 5: rename one
two figures with one idERROR ./math/alg/linears/solving.md:9: `f` is already the id of another figure in this file, at line 5: rename one

The first four faults stop the parse of the file. The file does not load. If it is the only child of its parent, the checker also reports the parent as empty:

ERROR ./math/alg/linears/index.md: this topic holds nothing: give it children, or take it out

Fix the first fault, and the second one goes too.

Markdown in a block

A block that holds Markdown takes CommonMark, with math:

WorksWritten
paragraphsa blank line between them
emphasis*italic*, **bold**
inline code`code`
lists- item, 1. item
quotes> text
headings## Heading
codea fenced block
inline math$a x + b = 0$
display math$$ x = 3 $$
pictures![caption](assets/x.svg)
links[label](reference:id), [label](figure:id), [label](https://…)

These do not work:

  • Tables. A pipe table shows as plain text with its | characters.
  • Strikethrough and footnotes. The marks show as plain text.
  • Raw HTML. The app shows an HTML tag as the text it is. A <b> in a card shows as <b>.
  • Remote pictures. A picture must come from an assets/ directory of the repository.

A deck with every block

---
title: What a field is
---

::: card
The most familiar field is gravity. The Earth fills the space around it with a gravitational
field, and any mass placed in that field feels a pull ([Figure](figure:gravity-field)).
:::

::: figure gravity-field
![Earth's field reaching the Moon](assets/gravity-field.svg)

Earth's gravitational field reaches every point of the surrounding space.
:::

::: card
Near the surface, the pull on a mass is its weight.[Weight](reference:weight)

```plot
x: { var: m, label: "$m$ in kg", from: 0, to: 10, ticks: 2, grid: true }
y: { label: "$W$ in N", from: 0, to: 100 }
draw:
  - curve: { is: 9.81 * m, accent: true }
```
:::

::: flashcard q1
What is the weight of a 2 kg mass near the surface of the Earth?

::: answer
About 19.6 N. Multiply the mass by $g$.
:::

::: solution
$W = m g = 2 \times 9.81 = 19.62$ N. ∎
:::
:::

::: reference weight
# Weight

The weight of a mass near the surface of the Earth.

::: equation
W = m g
:::

::: legend
$W$: weight, in newtons
$m$: mass, in kilograms
$g$: gravitational field strength, about 9.81 N/kg
:::

::: derivation
The field strength $g$ is the force on each kilogram, so a mass $m$ feels $m$ times that force. ∎
:::
:::