Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Configuring languages

Everything lives under [preprocessor.tsitter].

Preprocessor options

keydefaultmeaning
injecttrueHighlight embedded languages using configured injection queries. Only configured languages are used. Set this to false to disable injections globally.
default-csstrueEmbed the highlighting stylesheet (the theme directory’s highlight_ts.css, or the bundled one) in chapters with highlighted blocks. See Theming.

Language options

Add one entry to [preprocessor.tsitter.languages] per grammar. A language from the built-in list needs no keys at all; any other grammar needs git as its source. Paths are relative to the book root.

keyrequiredmeaning
gitfor unlisted languagesURL of the grammar’s git repository, or a path to a local one, fetched and compiled on demand. Defaults to the built-in list’s repository.
revnoTag, branch, or commit to use. Defaults to the built-in list’s pinned revision, or for other repositories their default branch.
locationnoSubdirectory holding the grammar, for repositories with several grammars. Usually found automatically.
highlightsnoPath to a highlights query, used instead of the grammar’s.
injectionsnoPath to an injections query for embedded languages, used instead of the grammar’s.
localsnoPath to a locals query for scope-aware highlighting, used instead of the grammar’s.
aliasesnoCode-fence names handled by this grammar; defaults to the entry’s name.
librarynoDeprecated. Path to a compiled parser shared library, used instead of fetching; requires highlights.
symbolnoDeprecated. Constructor symbol in library; defaults to tree_sitter_<name> with - changed to _.

A language may need its own table when it carries several keys:

[preprocessor.tsitter.languages.markdown]
aliases = ["md", "markdown"]
injections = "queries/markdown/injections.scm"

Injection queries can select another configured grammar using standard @injection.language and @injection.content captures. All grammars share the same capture-class table during a build, so embedded and host languages use the same theme consistently.

Rust Playground and hidden lines

Highlighted blocks keep mdBook’s code-block features. Rust blocks stay runnable in the Rust Playground, with the book’s [rust] edition, the implicit fn main wrapper, and annotations such as ignore, noplayground, mdbook-runnable, or edition2021 handled as mdBook handles them. Hidden lines (# in Rust, or a prefix from hidelines= or [output.html.code.hidelines]) are collapsed behind mdBook’s toggle:

```rust
# use std::collections::HashMap;
let mut scores = HashMap::new();
scores.insert("tree-sitter", 1);
```

Editable playgrounds (editable with [output.html.playground] editable = true) are replaced by mdBook’s in-page editor, so they are always left to mdBook.

Leaving a block to mdBook

Processing a block replaces its Markdown with highlighted HTML. Add the notreesitter annotation when a block should keep mdBook’s highlight.js highlighting instead:

```rust,notreesitter
let highlighted = "by mdBook";
```

Side-by-side blocks

Blocks labelled with pane="…" are shown side by side, and compare shows one block as tree-sitter and highlight.js highlight it. See Side-by-side blocks.

Alongside other preprocessors

mdBook runs preprocessors in the order set by their before and after keys, and otherwise alphabetically by name. A highlighted block becomes HTML, so a preprocessor that generates code blocks, or that must see a block as a code fence, has to run before this one:

[preprocessor.tsitter]
after = ["links", "my-code-generator"]

Blocks are found with mdBook’s own Markdown settings, so a block is highlighted exactly when mdBook would render it as a code block. In highlighted code, $ and \ are written as HTML entities, so math preprocessors such as mdbook-katex leave the code alone whichever of the two runs first.