Markdown spec
This is the exact markdown superset LavaTex reads. It’s deliberately opinionated — some things are fixed and not configurable — and everything that is configurable lives in one place: the note’s YAML frontmatter.
Preamble
Equations are always numbered per section
(\counterwithin{equation}{section}, which needs no package,
so a note with no preamble at all still compiles); everything else about
the preamble — the package list included — comes from the note’s
preamble frontmatter field, not a hardcoded list in
template.latex.
examples/Util/preamble.md is a suggested opinionated
default (mathtools, amssymb,
amsthm, mathrsfs, bbm,
bm, hyperref with colored blue links,
setspace, enumitem), referenced from
examples/weierstrass.md’s frontmatter — reuse it, or write
your own if a project needs a different package set.
Frontmatter fields
| Field | Meaning |
|---|---|
title, author, date |
Passed straight to
\title/\author/\date |
fontsize, margin,
linestretch |
Document-wide layout knobs |
refname |
Renames \refname (e.g. Referenzen for a
German bibliography heading) |
proofname |
Renames \proofname, and is the word
you bold to start a proof block (see below) |
preamble |
Literal LaTeX (\usepackage...), inserted right after
\documentclass/geometry/inputenc |
theorems |
List of environments — see below |
macros |
Literal \newcommand/\renewcommand
text |
bibliography-raw |
Literal LaTeX (e.g. a thebibliography block), inserted
after the body. Normally left unset — see “Citations” below, which fills
it in automatically |
autoEqnLabels: true |
Number every display equation, not just ones with an explicit
{#eq:...} |
preamble, theorems, macros,
and bibliography-raw each also accept
"[[Some Note]]" — a wikilink to another note holding that
content, instead of the literal value — so a shared
preamble/macro/bibliography/theorem setup doesn’t have to be copy-pasted
into every note. For preamble/macros/
bibliography-raw the linked note’s body is used
(frontmatter stripped, if it has any); for theorems it’s
the linked note’s own theorems: frontmatter field, so that
file’s shape is identical to writing the list inline, just in its own
note.
Several sources compose as a YAML list (what Obsidian’s properties editor writes for a list property), which may also mix in inline values:
preamble:
- "[[preamble]]"
- \usepackage{tikz-cd}
theorems:
- "[[theorems]]"
- "[[problem-theorems]]"Text fields are joined in the order listed; theorems
lists are concatenated (a linked theorems note may itself link further
notes), and if two sources declare the same id the first
one wins. A link that doesn’t resolve is an export error.
Default frontmatter
Settings → LaTeX Exporter → Default frontmatter
names a note (e.g. Util/Default frontmatter.md) whose
frontmatter every export falls back on: any field the exported note
doesn’t set itself — preamble, theorems, macros, author, layout — comes
from there, its [[links]] resolved from the template note.
The title is the exception: it’s always the note’s own
title:, else its file name, never the template’s. So a bare
scratch note with no frontmatter at all compiles to a proper PDF. The
template is a normal note, so it can double as an Obsidian template for
new notes. See examples/Util/Default frontmatter.md and
examples/Scratch/Quick note.md.
theorems
A list of environments to declare, each one of:
theorems:
- {id: theorem, name: Theorem, counter: section} # gets its own counter, numbered within section
- {id: lemma, name: Lemma, like: theorem} # shares the "theorem" counter
- {id: exercise, name: Exercise} # own plain counter: 1, 2, 3, ...idbecomes the LaTeX environment name (\newtheorem{id}..., and whattheorems.luamatches on).nameis the word you bold in the note body to start one — see “Theorem-like blocks” below. It does not have to matchid; you write**Theorem**even though the environment is internallytheorem, and**Definition und Lemma**for an id likedeflemma.- An entry with neither
counternorlikegets its own plain counter (1, 2, 3). In a single note without any#headings,counter: sectionis dropped the same way, and equations aren’t numbered within sections, so the numbering isn’t “0.1”, “0.2”, …. proofis always available as an environment without being listed here — its trigger word is whateverproofnameis set to (or “Proof” if unset).
Citations
Each bibliography source is its own note, with key (the
\cite{} argument) and bibitem (the hardcoded
\bibitem[...]{...} entry, written exactly as it should
appear in the exported document) in its frontmatter:
---
key: kk
bibitem: |
\bibitem[KK]{kk}
Koecher, Max, und Aloys Krieg. 2007. Elliptische Funktionen und Modulformen. ...
---Citing one from a note’s body is &[[Koecher-Krieg]]
— an & right before a wikilink to the source note —
expanded to a raw `\cite{kk}`{=latex} span. Every distinct
source cited this way has its bibitem collected and
assembled into bibliography-raw automatically, in citation
order, so the exported bibliography always matches exactly what got
cited.
Plain wikilinks
An ordinary [[Some Note]] or
[[Some Note|display text]] — the personal knowledge-graph
links Obsidian is for, unrelated to citing a source — is left completely
alone in the editor, but every export target (LaTeX, PDF, plain
Markdown) replaces it with just its display text before handing the note
to pandoc. A note written for both linking your own vault together and
being exported doesn’t have to choose: keep linking notes to each other
exactly as you would anywhere else, and the exported document just sees
prose, never a broken link or literal double brackets.
Theorem-like blocks
Written as a bold label, not a fenced div — or as an Obsidian callout
(see below), though a callout’s > prefix on every line
fights multi-line math and copy/paste. This instead mirrors how a paper
actually typesets a theorem: a bold label opens the statement, an
end-of-proof-style mark closes it.
**Lemma** (&[[Koecher-Krieg]] S.21f) {#lem-gitter-invariant}
Man nennt
$$
\delta := \delta(\omega_1, \omega_2)
$$
**Beweis**
Betrachte ...
∎
Teilt man die Gleichung durch ... erhält man die Behauptung.
∎
Rules:
**Word**only starts a block whenWord— trailing period stripped, matched case-insensitively — is atheorems[].nameor the note’sproofname. Bold text that doesn’t match anything is left alone; you can still write normal bold text anywhere else.(title)right after the bold word, if present, becomes the\begin{env}[title]optional argument.{#label}right after that (or right after the bold word, if there’s no title), if present, becomes\label{label}. Use hyphens, not colons (lem-foo, notlem:foo) — see “Known deviations”.- Anything left on the same line after the header is the first line of the body — equivalent to just starting the body on the next line instead.
∎on its own line closes the innermost still-open block. Blocks nest by stacking: opening a**Beweis**block inside an open**Theorem**block and closing it with its own∎before the theorem’s∎produces a nested\begin{proof}...\end{proof}inside\begin{theorem}...\end{theorem}. There’s no visual indentation for nesting — the∎s alone determine structure.- The command “Insert environment end mark (∎)” inserts the character if you don’t want to type/paste it — worth a hotkey.
Callouts
Obsidian callouts are an alternative spelling of the same blocks:
> [!lemma] Gitterinvarianz {#lem-gitter-invariant}
> Man nennt ...
> > [!beweis]
> > Betrachte ...
The callout type is matched like a bold word (a
theorems[].name or the proofname) or against a
theorems[].id, case-insensitively; the title becomes
\begin{env}[title], a trailing {#label}
becomes \label{label}, and the callout ends where its
> lines do — no ∎ needed. Nested callouts
(> >) nest environments. A callout whose type isn’t a
declared environment (> [!info]) is exported as an
ordinary blockquote with a bold title. See
examples/problem-sheet.md.
Images
Obsidian image embeds export as figures, so images pasted into a note in Obsidian just work:
| Note | LaTeX |
|---|---|
![[plot.png]] |
\includegraphics{../attachments/plot.png} |
![[plot.png\|300]] |
300px wide (300x200 sets the height too) |
![[plot.png\|A caption]] |
a figure captioned “A caption” |
The file is found the way Obsidian finds it — by name, anywhere in
the vault — and written as a path relative to the folder LaTeX compiles
in (the note’s, or a project’s master note’s). PNG, JPG and PDF work
with every engine. Standard Markdown images
(, relative to the note) work
too. Embeds of other notes (![[Note]]) are not
exported.
TikZ diagrams
A ```tikz ``` fenced block — the same plain syntax the
community obsidian-tikzjax
plugin renders live via TikZJax, if it’s installed too — is passed
through as raw LaTeX instead of a literal code block:
\begin{tikzpicture}
\draw[-Stealth] (0,0) -- (2,1);
\end{tikzpicture}Figure: A TikZ diagram, exported as a numbered figure. {#fig:comm}
A Figure: line right after the closing fence — same
shape as a bold-statement header’s (title) {#label} —
promotes the block to a captioned, labelled figure
environment, numbered and cross-referenceable with
[#fig:comm] like anything else with a
{#label}. Without a Figure: line the diagram
is centered in the text flow, like display math, rather than floated and
numbered.
No preamble setup is needed. \usepackage{tikz}, plus
every \usepackage{...}/\usetikzlibrary{...}
line written inside a block (the way TikZJax wants them,
e.g. \usepackage{tikz-cd}), is added to the exported
preamble automatically, after the note’s own preamble:.
Code listings
Any fenced code block with a language tag — ```python,
```r, whatever actually describes the code — is passed
through as a raw lstlisting environment instead of a
literal pandoc code block (tikz is the one reserved tag;
see “TikZ diagrams” above):
def f(x):
return x + 1Pandoc’s own fenced-code handling goes through skylighting (its own
preamble macros, its own styling), which doesn’t match a
listings-based project. The language tag itself is
discarded — it’s there for your own editor’s syntax highlighting, not
passed to listings — since \lstset{...}
applies globally: set the actual language once via \lstset
in preamble: (or a shared macros note), same as any
hand-written thesis already does. Needs
\usepackage{listings} in preamble: — not added
automatically.
Multi-chapter projects
Everything above is per-note. Export project to
LaTeX/PDF assembles several notes into one
\documentclass{report} document instead: point a
master note’s chapters: frontmatter at the chapter
notes, in order.
---
title: Die geometrische Brownsche Bewegung und Anwendungen
author: Fabian Schuller
preamble: "[[preamble]]"
theorems: "[[theorems]]"
chapters:
- "[[00 Motivation]]"
- "[[10 Stochastische Prozesse]]"
- "[[70 Anhang]]"
appendix-from: "[[70 Anhang]]"
---
Optional preface/abstract text, placed before the first chapter.| Field | Meaning |
|---|---|
chapters |
Required. Non-empty list of [[wikilinks]] to chapter
notes, in order. Each note’s own #-heading becomes
\chapter{...}
(--top-level-division=chapter) |
appendix-from |
[[wikilink]] to the chapter that starts the appendix; a
raw \appendix is inserted immediately before it |
documentclass |
Defaults to report; book for
\part-structured front/main/back matter |
division |
pandoc top-level-division; defaults to chapter |
numberwithin |
What \numberwithin{equation}{...} numbers by; defaults
to section (a thesis numbering equations per chapter sets
this to chapter) |
toc |
Defaults to true (project export only; single-note
export leaves it unset — opt in with toc: true there
too) |
Everything a single note’s frontmatter supports —
preamble, macros, theorems,
title/author/date, layout knobs,
refname/proofname — works identically,
declared once on the master note and shared by every chapter.
&[[Source]] citations work across chapters exactly as
within one note: a source cited from two different chapters gets one
\cite{} key and one bibliography entry, in
first-cited-across-the-whole-project order.
The master note’s own body (if non-empty) is treated as front matter
content — an abstract, a dedication — placed before the first chapter.
The Export project to… commands only appear in the
command palette when the active note’s frontmatter has a
chapters: list — run them from the master note.
Cross-references
Two independent mechanisms, because they resolve at different times:
- Anything with a
{#label}— a theorem header or a labelled equation — is referenced with[#label]. This expands to a raw`\ref{label}`{=latex}span;\refresolves it at LaTeX-compile time via amsthm/hyperref, no pandoc filter involved. The “Insert reference to label” command opens a fuzzy picker over every{#label}in the current note so you never have to remember or retype an id. - Numbered equations specifically can also use
pandoc-crossref’s own syntax: label with
$$...$$ {#eq:foo}, reference with[@eq:foo]. This renders as\eqref{}(parenthesized) rather than plain\ref{}— prefer it when you want that style.[#eq:foo]also works (plain\ref) if you don’t. The “Reference equation” command is “Insert reference to label” filtered toeq:...labels and inserting[@eq:foo]instead.
Two more commands add the labels themselves, so you don’t have to
type {#...} by hand: “Add equation label”
prompts for a name and inserts {#eq:name} at the cursor
(place it right after a $$...$$ block’s closing
$$); “Add theorem label” prompts for a
name and inserts {#name} at the cursor (place it in a
bold-statement header).
Math and raw LaTeX
$...$and$$...$$are passed to pandoc, and from there into the.tex, completely unmodified — never reinterpreted. Any macro frommacros:just works in the exported document.\begin{align}...\end{align}(andalign*) needs$$around it, same as any other display equation — MathJax does not auto-detect AMS environments outside math delimiters, so a bare\begin{align}is just plain text to Obsidian’s live renderer. The exporter strips that$$and wraps the environment in a raw LaTeX block for pandoc instead (pandoc’s LaTeX writer can’t emitalignnested inside$$...$$math, so passing it through unchanged would come out broken).Anything else pandoc’s markdown can’t express directly — a mid-document
\newcommandlocal to one proof, an environment MathJax doesn’t support — goes in an explicit raw block:```{=latex} \newcommand{\sumoverannuli}{...} ```A
\newcommandwritten this way is also picked up for live MathJax rendering (see the Architecture page) — it isn’t limited to the frontmattermacros:field.
Known deviations from hand-written LaTeX
- Numbered equations are wrapped by pandoc-crossref as
\begin{equation}{...}— an extra brace group. This is pandoc-crossref’s normal output, compiles fine, and is left alone rather than patched. - A bare
\itemlist outside any list environment (as in the worked example’s original Liouville theorem) is invalid LaTeX. Use a real ordered list instead; you’ll get1./2.numbering rather than(1)/(2). - Theorem/lemma labels use hyphens (
thm-weier), not colons (thm:weier) — a holdover from when labels were briefly Obsidian block-references (which don’t allow colons); kept for consistency even though nothing enforces it anymore.