# Introduction

mdBook is a command line tool and Rust crate to create books with Markdown. The output resembles tools like Gitbook, and is ideal for creating product or API documentation, tutorials, course materials or anything that requires a clean, easily navigable and customizable presentation. mdBook is written in Rust; its performance and simplicity made it ideal for use as a tool to publish directly to hosted websites such as GitHub Pages via automation. This guide, in fact, serves as both the mdBook documentation and a fine example of what mdBook produces.

mdBook includes built in support for both preprocessing your Markdown and alternative renderers for producing formats other than HTML. These facilities also enable other functionality such as validation. Searching Rust's crates.io is a great way to discover more extensions.

## API Documentation

In addition to the above features, mdBook also has a Rust API. This allows you to write your own preprocessor or renderer, as well as incorporate mdBook features into other applications. The For Developers section of this guide contains more information and some examples.

## Markdown

mdBook's parser adheres to the CommonMark specification. You can take a quick tutorial, or try out CommonMark in real time. For a more in-depth experience, check out the Markdown Guide.

## Contributing

mdBook is free and open source. You can find the source code on GitHub and issues and feature requests can be posted on the GitHub issue tracker. mdBook relies on the community to fix bugs and add features: if you'd like to contribute, please read the CONTRIBUTING guide and consider opening a pull request.

## License

The mdBook source and documentation are released under the Mozilla Public License v2.0.

# Command Line Tool

mdBook can be used either as a command line tool or a Rust crate. Let's focus on the command line tool capabilities first.

## Install From Binaries

Precompiled binaries are provided for major platforms on a best-effort basis. Visit the releases page to download the appropriate version for your platform.

## Install From Source

mdBook can also be installed by compiling the source code on your local machine.

### Pre-requisite

mdBook is written in Rust and therefore needs to be compiled with Cargo. If you haven't already installed Rust, please go ahead and install it now.

### Install Crates.io version

Installing mdBook is relatively easy if you already have Rust and Cargo installed. You just have to type this snippet in your terminal:

    cargo install mdbook

This will fetch the source code for the latest release from Crates.io and compile it. You will have to add Cargo's `bin` directory to your `PATH`.

Run `mdbook help` in your terminal to verify if it works. Congratulations, you have installed mdBook!

### Install Git version

The git version contains all the latest bug-fixes and features, that will be released in the next version on Crates.io, if you can't wait until the next release. You can build the git version yourself. Open your terminal and navigate to the directory of you choice. We need to clone the git repository and then build it with Cargo.

    git clone --depth=1 https://github.com/rust-lang/mdBook.git
    cd mdBook
    cargo build --release

The executable `mdbook` will be in the `./target/release` folder, this should be added to the path.

# The init command

There is some minimal boilerplate that is the same for every new book. It's for this purpose that mdBook includes an `init` command.

The `init` command is used like this:

    mdbook init

When using the `init` command for the first time, a couple of files will be set up for you:

    book-test/
    ├── book
    └── src
        ├── chapter_1.md
        └── SUMMARY.md

- The `src` directory is where you write your book in markdown. It contains all the source files, configuration files, etc.

- The `book` directory is where your book is rendered. All the output is ready to be uploaded to a server to be seen by your audience.

- The `SUMMARY.md` is the skeleton of your book, and is discussed in more detail in another chapter.

#### Tip: Generate chapters from SUMMARY.md

When a `SUMMARY.md` file already exists, the `init` command will first parse it and generate the missing files according to the paths used in the `SUMMARY.md`. This allows you to think and create the whole structure of your book and then let mdBook generate it for you.

#### Specify a directory

The `init` command can take a directory as an argument to use as the book's root instead of the current working directory.

    mdbook init path/to/book

#### --theme

When you use the `--theme` flag, the default theme will be copied into a directory called `theme` in your source directory so that you can modify it.

The theme is selectively overwritten, this means that if you don't want to overwrite a specific file, just delete it and the default file will be used.

#### --title

Specify a title for the book. If not supplied, an interactive prompt will ask for a title.

    mdbook init --title="my amazing book"

#### --ignore

Create a `.gitignore` file configured to ignore the `book` directory created when building a book. If not supplied, an interactive prompt will ask whether it should be created.

# The build command

The build command is used to render your book:

    mdbook build

It will try to parse your `SUMMARY.md` file to understand the structure of your book and fetch the corresponding files. Note that files mentioned in `SUMMARY.md` but not present will be created.

The rendered output will maintain the same directory structure as the source for convenience. Large books will therefore remain structured when rendered.

#### Specify a directory

The `build` command can take a directory as an argument to use as the book's root instead of the current working directory.

    mdbook build path/to/book

#### --open

When you use the `--open` (`-o`) flag, mdbook will open the rendered book in your default web browser after building it.

#### --dest-dir

The `--dest-dir` (`-d`) option allows you to change the output directory for the book. Relative paths are interpreted relative to the book's root directory. If not specified it will default to the value of the `build.build-dir` key in `book.toml`, or to `./book`.

Note: The build command copies all files (excluding files with `.md` extension) from the source directory into the build directory.

# The watch command

The `watch` command is useful when you want your book to be rendered on every file change. You could repeatedly issue `mdbook build` every time a file is changed. But using `mdbook watch` once will watch your files and will trigger a build automatically whenever you modify a file; this includes re-creating deleted files still mentioned in `SUMMARY.md`!

#### Specify a directory

The `watch` command can take a directory as an argument to use as the book's root instead of the current working directory.

    mdbook watch path/to/book

#### --open

When you use the `--open` (`-o`) option, mdbook will open the rendered book in your default web browser.

#### --dest-dir

The `--dest-dir` (`-d`) option allows you to change the output directory for the book. Relative paths are interpreted relative to the book's root directory. If not specified it will default to the value of the `build.build-dir` key in `book.toml`, or to `./book`.

#### Specify exclude patterns

The `watch` command will not automatically trigger a build for files listed in the `.gitignore` file in the book root directory. The `.gitignore` file may contain file patterns described in the gitignore documentation. This can be useful for ignoring temporary files created by some editors.

Note: Only `.gitignore` from book root directory is used. Global `$HOME/.gitignore` or `.gitignore` files in parent directories are not used.

# The serve command

The serve command is used to preview a book by serving it via HTTP at `localhost:3000` by default:

    mdbook serve

The `serve` command watches the book's `src` directory for changes, rebuilding the book and refreshing clients for each change; this includes re-creating deleted files still mentioned in `SUMMARY.md`! A websocket connection is used to trigger the client-side refresh.

Note: The `serve` command is for testing a book's HTML output, and is not intended to be a complete HTTP server for a website.

#### Specify a directory

The `serve` command can take a directory as an argument to use as the book's root instead of the current working directory.

    mdbook serve path/to/book

### Server options

The `serve` hostname defaults to `localhost`, and the port defaults to `3000`. Either option can be specified on the command line:

    mdbook serve path/to/book -p 8000 -n 127.0.0.1

#### --open

When you use the `--open` (`-o`) flag, mdbook will open the book in your default web browser after starting the server.

#### --dest-dir

The `--dest-dir` (`-d`) option allows you to change the output directory for the book. Relative paths are interpreted relative to the book's root directory. If not specified it will default to the value of the `build.build-dir` key in `book.toml`, or to `./book`.

#### Specify exclude patterns

The `serve` command will not automatically trigger a build for files listed in the `.gitignore` file in the book root directory. The `.gitignore` file may contain file patterns described in the gitignore documentation. This can be useful for ignoring temporary files created by some editors.

Note: Only the `.gitignore` from the book root directory is used. Global `$HOME/.gitignore` or `.gitignore` files in parent directories are not used.

# The test command

When writing a book, you sometimes need to automate some tests. For example, The Rust Programming Book uses a lot of code examples that could get outdated. Therefore it is very important for them to be able to automatically test these code examples.

mdBook supports a `test` command that will run all available tests in a book. At the moment, only rustdoc tests are supported, but this may be expanded upon in the future.

#### Disable tests on a code block

rustdoc doesn't test code blocks which contain the `ignore` attribute:

    ```rust,ignore
    fn main() {}
    ```

rustdoc also doesn't test code blocks which specify a language other than Rust:

    ```markdown
    **Foo**: _bar_
    ```

rustdoc does test code blocks which have no language specified:

    ```
    This is going to cause an error!
    ```

#### Specify a directory

The `test` command can take a directory as an argument to use as the book's root instead of the current working directory.

    mdbook test path/to/book

#### --library-path

The `--library-path` (`-L`) option allows you to add directories to the library search path used by `rustdoc` when it builds and tests the examples. Multiple directories can be specified with multiple options (`-L foo -L bar`) or with a comma-delimited list (`-L foo,bar`). The path should point to the Cargo build cache `deps` directory that contains the build output of your project. For example, if your Rust project's book is in a directory named `my-book`, the following command would include the crate's dependencies when running `test`:

    mdbook test my-book -L target/debug/deps/

See the `rustdoc` command-line documentation for more information.

#### --dest-dir

The `--dest-dir` (`-d`) option allows you to change the output directory for the book. Relative paths are interpreted relative to the book's root directory. If not specified it will default to the value of the `build.build-dir` key in `book.toml`, or to `./book`.

# The clean command

The clean command is used to delete the generated book and any other build artifacts.

    mdbook clean

#### Specify a directory

The `clean` command can take a directory as an argument to use as the book's root instead of the current working directory.

    mdbook clean path/to/book

#### --dest-dir

The `--dest-dir` (`-d`) option allows you to override the book's output directory, which will be deleted by this command. Relative paths are interpreted relative to the book's root directory. If not specified it will default to the value of the `build.build-dir` key in `book.toml`, or to `./book`.

    mdbook clean --dest-dir=path/to/book

`path/to/book` could be absolute or relative.

# Format

In this section you will learn how to:

- Structure your book correctly
- Format your `SUMMARY.md` file
- Configure your book using `book.toml`
- Customize your theme

# SUMMARY.md

The summary file is used by mdBook to know what chapters to include, in what order they should appear, what their hierarchy is and where the source files are. Without this file, there is no book.

This markdown file must be named `SUMMARY.md`. Its formatting is very strict and must follow the structure outlined below to allow for easy parsing. Any element not specified below, be it formatting or textual, is likely to be ignored at best, or may cause an error when attempting to build the book.

### Structure

1. Title - While optional, it's common practice to begin with a title, generally `# Summary`. This is ignored by the parser however, and can be omitted.

       # Summary

2. Prefix Chapter - Before the main numbered chapters, prefix chapters can be added that will not be numbered. This is useful for forewords, introductions, etc. There are, however, some constraints. Prefix chapters cannot be nested; they should all be on the root level. And you can not add prefix chapters once you have added numbered chapters.

       [A Prefix Chapter](relative/path/to/markdown.md)

       - [First Chapter](relative/path/to/markdown2.md)

3. Part Title - Headers can be used as a title for the following numbered chapters. This can be used to logically separate different sections of the book. The title is rendered as unclickable text. Titles are optional, and the numbered chapters can be broken into as many parts as desired.

       # My Part Tile

       - [First Chapter](relative/path/to/markdown.md)

4. Numbered Chapter - Numbered chapters outline the main content of the book and can be nested, resulting in a nice hierarchy (chapters, sub-chapters, etc.).

       # Title of Part

       - [First Chapter](relative/path/to/markdown.md)
       - [Second Chapter](relative/path/to/markdown2.md)
          - [Sub Chapter](relative/path/to/markdown3.md)

       # Title of Another Part

       - [Another Chapter](relative/path/to/markdown4.md)

   Numbered chapters can be denoted with either `-` or `*` (do not mix delimiters).

5. Suffix Chapter - Like prefix chapters, suffix chapters are unnumbered, but they come after numbered chapters.

       - [Last Chapter](relative/path/to/markdown.md)

       [Title of Suffix Chapter](relative/path/to/markdown2.md)

6. Draft chapters - Draft chapters are chapters without a file and thus content. The purpose of a draft chapter is to signal future chapters still to be written. Or when still laying out the structure of the book to avoid creating the files while you are still changing the structure of the book a lot. Draft chapters will be rendered in the HTML renderer as disabled links in the table of contents, as you can see for the next chapter in the table of contents on the left. Draft chapters are written like normal chapters but without writing the path to the file.

       - [Draft Chapter]()

7. Separators - Separators can be added before, in between, and after any other element. They result in an HTML rendered line in the built table of contents. A separator is a line containing exclusively dashes and at least three of them: `---`.

       # My Part Title

       [A Prefix Chapter](relative/path/to/markdown.md)

       ---

       - [First Chapter](relative/path/to/markdown2.md)

### Example

Below is the markdown source for the `SUMMARY.md` for this guide, with the resulting table of contents as rendered to the left.

    # Summary

    - [Introduction](README.md)
    - [Command Line Tool](cli/README.md)
        - [init](cli/init.md)
        - [build](cli/build.md)
        - [watch](cli/watch.md)
        - [serve](cli/serve.md)
        - [test](cli/test.md)
        - [clean](cli/clean.md)
    - [Format](format/README.md)
        - [SUMMARY.md](format/summary.md)
            - [Draft chapter]()
        - [Configuration](format/configuration/README.md)
            - [General](format/configuration/general.md)
            - [Preprocessors](format/configuration/preprocessors.md)
            - [Renderers](format/configuration/renderers.md)
            - [Environment Variables](format/configuration/environment-variables.md)
        - [Theme](format/theme/README.md)
            - [index.hbs](format/theme/index-hbs.md)
            - [Syntax highlighting](format/theme/syntax-highlighting.md)
            - [Editor](format/theme/editor.md)
        - [MathJax Support](format/mathjax.md)
        - [mdBook-specific features](format/mdbook.md)
    - [Continuous Integration](continuous-integration.md)
    - [For Developers](for_developers/README.md)
        - [Preprocessors](for_developers/preprocessors.md)
        - [Alternative Backends](for_developers/backends.md)

    -----------

    [Contributors](misc/contributors.md)

# Configuration

This section details the configuration options available in the book.toml:

- General configuration including the `book`, `rust`, `build` sections
- Preprocessor configuration for default and custom book preprocessors
- Renderer configuration for the HTML, Markdown and custom renderers
- Environment Variable configuration for overriding configuration options in your environment

# General Configuration

You can configure the parameters for your book in the book.toml file.

Here is an example of what a book.toml file might look like:

    [book]
    title = "Example book"
    author = "John Doe"
    description = "The example book covers examples."

    [rust]
    edition = "2018"

    [build]
    build-dir = "my-example-book"
    create-missing = false

    [preprocessor.index]

    [preprocessor.links]

    [output.html]
    additional-css = ["custom.css"]

    [output.html.search]
    limit-results = 15

## Supported configuration options

It is important to note that any relative path specified in the configuration will always be taken relative from the root of the book where the configuration file is located.

### General metadata

This is general information about your book.

- title: The title of the book
- authors: The author(s) of the book
- description: A description for the book, which is added as meta information in the html `<head>` of each page
- src: By default, the source directory is found in the directory named `src` directly under the root folder. But this is configurable with the `src` key in the configuration file.
- language: The main language of the book, which is used as a language attribute `<html lang="en">` for example.

book.toml

    [book]
    title = "Example book"
    authors = ["John Doe", "Jane Doe"]
    description = "The example book covers examples."
    src = "my-src"  # the source files will be found in `root/my-src` instead of `root/src`
    language = "en"

### Rust options

Options for the Rust language, relevant to running tests and playground integration.

- edition: Rust edition to use by default for the code snippets. Default is "2015". Individual code blocks can be controlled with the `edition2015`, `edition2018` or `edition2021` annotations, such as:

      ```rust,edition2015
      // This only works in 2015.
      let try = true;
      ```

### Build options

This controls the build process of your book.

- build-dir: The directory to put the rendered book in. By default this is `book/` in the book's root directory.

- create-missing: By default, any missing files specified in `SUMMARY.md` will be created when the book is built (i.e. `create-missing = true`). If this is `false` then the build process will instead exit with an error if any files do not exist.

- use-default-preprocessors: Disable the default preprocessors of (`links` & `index`) by setting this option to `false`.

  If you have the same, and/or other preprocessors declared via their table of configuration, they will run instead.

  - For clarity, with no preprocessor configuration, the default `links` and `index` will run.
  - Setting `use-default-preprocessors = false` will disable these default preprocessors from running.
  - Adding `[preprocessor.links]`, for example, will ensure, regardless of `use-default-preprocessors` that `links` it will run.

# Configuring Preprocessors

The following preprocessors are available and included by default:

- `links`: Expand the `{{ #playground }}`, `{{ #include }}`, and `{{ #rustdoc_include }}` handlebars helpers in a chapter to include the contents of a file.
- `index`: Convert all chapter files named `README.md` into `index.md`. That is to say, all `README.md` would be rendered to an index file `index.html` in the rendered book.

book.toml

    [build]
    build-dir = "build"
    create-missing = false

    [preprocessor.links]

    [preprocessor.index]

### Custom Preprocessor Configuration

Like renderers, preprocessor will need to be given its own table (e.g. `[preprocessor.mathjax]`). In the section, you may then pass extra configuration to the preprocessor by adding key-value pairs to the table.

For example

    [preprocessor.links]
    # set the renderers this preprocessor will run for
    renderers = ["html"]
    some_extra_feature = true

#### Locking a Preprocessor dependency to a renderer

You can explicitly specify that a preprocessor should run for a renderer by binding the two together.

    [preprocessor.mathjax]
    renderers = ["html"]  # mathjax only makes sense with the HTML renderer

### Provide Your Own Command

By default when you add a `[preprocessor.foo]` table to your `book.toml` file, `mdbook` will try to invoke the `mdbook-foo` executable. If you want to use a different program name or pass in command-line arguments, this behaviour can be overridden by adding a `command` field.

    [preprocessor.random]
    command = "python random.py"

### Require A Certain Order

The order in which preprocessors are run can be controlled with the `before` and `after` fields. For example, suppose you want your `linenos` preprocessor to process lines that may have been `{{#include}}`d; then you want it to run after the built-in `links` preprocessor, which you can require using either the `before` or `after` field:

    [preprocessor.linenos]
    after = [ "links" ]

or

    [preprocessor.links]
    before = [ "linenos" ]

It would also be possible, though redundant, to specify both of the above in the same config file.

Preprocessors having the same priority specified through `before` and `after` are sorted by name. Any infinite loops will be detected and produce an error.

# Configuring Renderers

### HTML renderer options

The HTML renderer has a couple of options as well. All the options for the renderer need to be specified under the TOML table `[output.html]`.

The following configuration options are available:

- theme: mdBook comes with a default theme and all the resource files needed for it. But if this option is set, mdBook will selectively overwrite the theme files with the ones found in the specified folder.
- default-theme: The theme color scheme to select by default in the 'Change Theme' dropdown. Defaults to `light`.
- preferred-dark-theme: The default dark theme. This theme will be used if the browser requests the dark version of the site via the 'prefers-color-scheme' CSS media query. Defaults to `navy`.
- curly-quotes: Convert straight quotes to curly quotes, except for those that occur in code blocks and code spans. Defaults to `false`.
- mathjax-support: Adds support for MathJax. Defaults to `false`.
- copy-fonts: Copies fonts.css and respective font files to the output directory and use them in the default theme. Defaults to `true`.
- google-analytics: If you use Google Analytics, this option lets you enable it by simply specifying your ID in the configuration file.
- additional-css: If you need to slightly change the appearance of your book without overwriting the whole style, you can specify a set of stylesheets that will be loaded after the default ones where you can surgically change the style.
- additional-js: If you need to add some behaviour to your book without removing the current behaviour, you can specify a set of JavaScript files that will be loaded alongside the default one.
- print: A subtable for configuration print settings. mdBook by default adds support for printing out the book as a single page. This is accessed using the print icon on the top right of the book.
- no-section-label: mdBook by defaults adds section label in table of contents column. For example, "1.", "2.1". Set this option to true to disable those labels. Defaults to `false`.
- fold: A subtable for configuring sidebar section-folding behavior.
- playground: A subtable for configuring various playground settings.
- search: A subtable for configuring the in-browser search functionality. mdBook must be compiled with the `search` feature enabled (on by default).
- git-repository-url: A url to the git repository for the book. If provided an icon link will be output in the menu bar of the book.
- git-repository-icon: The FontAwesome icon class to use for the git repository link. Defaults to `fa-github`.
- edit-url-template: Edit url template, when provided shows a "Suggest an edit" button for directly jumping to editing the currently viewed page. For e.g. GitHub projects set this to `https://github.com/<owner>/<repo>/edit/master/{path}` or for Bitbucket projects set it to `https://bitbucket.org/<owner>/<repo>/src/master/{path}?mode=edit` where {path} will be replaced with the full path of the file in the repository.
- redirect: A subtable used for generating redirects when a page is moved. The table contains key-value pairs where the key is where the redirect file needs to be created, as an absolute path from the build directory, (e.g. `/appendices/bibliography.html`). The value can be any valid URI the browser should navigate to (e.g. `https://rust-lang.org/`, `/overview.html`, or `../bibliography.html`).
- input-404: The name of the markdown file used for missing files. The corresponding output file will be the same, with the extension replaced with `html`. Defaults to `404.md`.
- site-url: The url where the book will be hosted. This is required to ensure navigation links and script/css imports in the 404 file work correctly, even when accessing urls in subdirectories. Defaults to `/`.
- cname: The DNS subdomain or apex domain at which your book will be hosted. This string will be written to a file named CNAME in the root of your site, as required by GitHub Pages (see Managing a custom domain for your GitHub Pages site).

Available configuration options for the `[output.html.print]` table:

- enable: Enable print support. When `false`, all print support will not be rendered. Defaults to `true`.

Available configuration options for the `[output.html.fold]` table:

- enable: Enable section-folding. When off, all folds are open. Defaults to `false`.
- level: The higher the more folded regions are open. When level is 0, all folds are closed. Defaults to `0`.

Available configuration options for the `[output.html.playground]` table:

- editable: Allow editing the source code. Defaults to `false`.
- copyable: Display the copy button on code snippets. Defaults to `true`.
- copy-js: Copy JavaScript files for the editor to the output directory. Defaults to `true`.
- line-numbers Display line numbers on editable sections of code. Requires both `editable` and `copy-js` to be `true`. Defaults to `false`.

Available configuration options for the `[output.html.search]` table:

- enable: Enables the search feature. Defaults to `true`.
- limit-results: The maximum number of search results. Defaults to `30`.
- teaser-word-count: The number of words used for a search result teaser. Defaults to `30`.
- use-boolean-and: Define the logical link between multiple search words. If true, all search words must appear in each result. Defaults to `false`.
- boost-title: Boost factor for the search result score if a search word appears in the header. Defaults to `2`.
- boost-hierarchy: Boost factor for the search result score if a search word appears in the hierarchy. The hierarchy contains all titles of the parent documents and all parent headings. Defaults to `1`.
- boost-paragraph: Boost factor for the search result score if a search word appears in the text. Defaults to `1`.
- expand: True if search should match longer results e.g. search `micro` should match `microwave`. Defaults to `true`.
- heading-split-level: Search results will link to a section of the document which contains the result. Documents are split into sections by headings this level or less. Defaults to `3`. (`### This is a level 3 heading`)
- copy-js: Copy JavaScript files for the search implementation to the output directory. Defaults to `true`.

This shows all available HTML output options in the book.toml:

    [book]
    title = "Example book"
    authors = ["John Doe", "Jane Doe"]
    description = "The example book covers examples."

    [output.html]
    theme = "my-theme"
    default-theme = "light"
    preferred-dark-theme = "navy"
    curly-quotes = true
    mathjax-support = false
    copy-fonts = true
    google-analytics = "UA-123456-7"
    additional-css = ["custom.css", "custom2.css"]
    additional-js = ["custom.js"]
    no-section-label = false
    git-repository-url = "https://github.com/rust-lang/mdBook"
    git-repository-icon = "fa-github"
    edit-url-template = "https://github.com/rust-lang/mdBook/edit/master/guide/{path}"
    site-url = "/example-book/"
    cname = "myproject.rs"
    input-404 = "not-found.md"

    [output.html.print]
    enable = true

    [output.html.fold]
    enable = false
    level = 0

    [output.html.playground]
    editable = false
    copy-js = true
    line-numbers = false

    [output.html.search]
    enable = true
    limit-results = 30
    teaser-word-count = 30
    use-boolean-and = true
    boost-title = 2
    boost-hierarchy = 1
    boost-paragraph = 1
    expand = true
    heading-split-level = 3
    copy-js = true

    [output.html.redirect]
    "/appendices/bibliography.html" = "https://rustc-dev-guide.rust-lang.org/appendix/bibliography.html"
    "/other-installation-methods.html" = "../infra/other-installation-methods.html"

### Markdown Renderer

The Markdown renderer will run preprocessors and then output the resulting Markdown. This is mostly useful for debugging preprocessors, especially in conjunction with `mdbook test` to see the Markdown that `mdbook` is passing to `rustdoc`.

The Markdown renderer is included with `mdbook` but disabled by default. Enable it by adding an empty table to your `book.toml` as follows:

    [output.markdown]

There are no configuration options for the Markdown renderer at this time; only whether it is enabled or disabled.

See the preprocessors documentation for how to specify which preprocessors should run before the Markdown renderer.

### Custom Renderers

A custom renderer can be enabled by adding a `[output.foo]` table to your `book.toml`. Similar to preprocessors this will instruct `mdbook` to pass a representation of the book to `mdbook-foo` for rendering. See the alternative backends chapter for more detail.

The custom renderer has access to all the fields within its table (i.e. anything under `[output.foo]`). mdBook checks for two common fields:

- command: The command to execute for this custom renderer. Defaults to the name of the renderer with the `mdbook-` prefix (such as `mdbook-foo`).
- optional: If `true`, then the command will be ignored if it is not installed, otherwise mdBook will fail with an error. Defaults to `false`.

# Environment Variables

All configuration values can be overridden from the command line by setting the corresponding environment variable. Because many operating systems restrict environment variables to be alphanumeric characters or `_`, the configuration key needs to be formatted slightly differently to the normal `foo.bar.baz` form.

Variables starting with `MDBOOK_` are used for configuration. The key is created by removing the `MDBOOK_` prefix and turning the resulting string into `kebab-case`. Double underscores (`__`) separate nested keys, while a single underscore (`_`) is replaced with a dash (`-`).

For example:

- `MDBOOK_foo` -> `foo`
- `MDBOOK_FOO` -> `foo`
- `MDBOOK_FOO__BAR` -> `foo.bar`
- `MDBOOK_FOO_BAR` -> `foo-bar`
- `MDBOOK_FOO_bar__baz` -> `foo-bar.baz`

So by setting the `MDBOOK_BOOK__TITLE` environment variable you can override the book's title without needing to touch your `book.toml`.

> Note: To facilitate setting more complex config items, the value of an environment variable is first parsed as JSON, falling back to a string if the parse fails.

> This means, if you so desired, you could override all book metadata when building the book with something like

>     $ export MDBOOK_BOOK="{'title': 'My Awesome Book', authors: ['Michael-F-Bryan']}"
>     $ mdbook build

The latter case may be useful in situations where `mdbook` is invoked from a script or CI, where it sometimes isn't possible to update the `book.toml` before building.

# Theme

The default renderer uses a handlebars template to render your markdown files and comes with a default theme included in the mdBook binary.

The theme is totally customizable, you can selectively replace every file from the theme by your own by adding a `theme` directory next to `src` folder in your project root. Create a new file with the name of the file you want to override and now that file will be used instead of the default file.

Here are the files you can override:

- index.hbs is the handlebars template.
- head.hbs is appended to the HTML `<head>` section.
- header.hbs content is appended on top of every book page.
- css/ contains the CSS files for styling the book.
  - css/chrome.css is for UI elements.
  - css/general.css is the base styles.
  - css/print.css is the style for printer output.
  - css/variables.css contains variables used in other CSS files.
- book.js is mostly used to add client side functionality, like hiding / un-hiding the sidebar, changing the theme, ...
- highlight.js is the JavaScript that is used to highlight code snippets, you should not need to modify this.
- highlight.css is the theme used for the code highlighting.
- favicon.svg and favicon.png the favicon that will be used. The SVG version is used by newer browsers.

Generally, when you want to tweak the theme, you don't need to override all the files. If you only need changes in the stylesheet, there is no point in overriding all the other files. Because custom files take precedence over built-in ones, they will not get updated with new fixes / features.

Note: When you override a file, it is possible that you break some functionality. Therefore I recommend to use the file from the default theme as template and only add / modify what you need. You can copy the default theme into your source directory automatically by using `mdbook init --theme` just remove the files you don't want to override.

If you completely replace all built-in themes, be sure to also set `output.html.preferred-dark-theme` in the config, which defaults to the built-in `navy` theme.

# index.hbs

`index.hbs` is the handlebars template that is used to render the book. The markdown files are processed to html and then injected in that template.

If you want to change the layout or style of your book, chances are that you will have to modify this template a little bit. Here is what you need to know.

## Data

A lot of data is exposed to the handlebars template with the "context". In the handlebars template you can access this information by using

    {{name_of_property}}

Here is a list of the properties that are exposed:

- language Language of the book in the form `en`, as specified in `book.toml` (if not specified, defaults to `en`). To use in `<html lang="{{ language }}">` for example.

- title Title used for the current page. This is identical to `{{ chapter_title }} - {{ book_title }}` unless `book_title` is not set in which case it just defaults to the `chapter_title`.

- book_title Title of the book, as specified in `book.toml`

- chapter_title Title of the current chapter, as listed in `SUMMARY.md`

- path Relative path to the original markdown file from the source directory

- content This is the rendered markdown.

- path_to_root This is a path containing exclusively `../`'s that points to the root of the book from the current file. Since the original directory structure is maintained, it is useful to prepend relative links with this `path_to_root`.

- chapters Is an array of dictionaries of the form

      {"section": "1.2.1", "name": "name of this chapter", "path": "dir/markdown.md"}

  containing all the chapters of the book. It is used for example to construct the table of contents (sidebar).

## Handlebars Helpers

In addition to the properties you can access, there are some handlebars helpers at your disposal.

### 1. toc

The toc helper is used like this

    {{#toc}}{{/toc}}

and outputs something that looks like this, depending on the structure of your book

    <ul class="chapter">
        <li><a href="link/to/file.html">Some chapter</a></li>
        <li>
            <ul class="section">
                <li><a href="link/to/other_file.html">Some other Chapter</a></li>
            </ul>
        </li>
    </ul>

If you would like to make a toc with another structure, you have access to the chapters property containing all the data. The only limitation at the moment is that you would have to do it with JavaScript instead of with a handlebars helper.

    <script>
    var chapters = {{chapters}};
    // Processing here
    </script>

### 2. previous / next

The previous and next helpers expose a `link` and `name` property to the previous and next chapters.

They are used like this

    {{#previous}}
        <a href="{{link}}" class="nav-chapters previous">
            <i class="fa fa-angle-left"></i>
        </a>
    {{/previous}}

The inner html will only be rendered if the previous / next chapter exists. Of course the inner html can be changed to your liking.

If you would like other properties or helpers exposed, please create a new issue

# Syntax Highlighting

mdBook uses Highlight.js with a custom theme for syntax highlighting.

Automatic language detection has been turned off, so you will probably want to specify the programming language you use like this:

    ```rust
    fn main() {
        // Some code
    }
    ```

## Supported languages

These languages are supported by default, but you can add more by supplying your own `highlight.js` file:

- apache
- armasm
- bash
- c
- coffeescript
- cpp
- csharp
- css
- d
- diff
- go
- handlebars
- haskell
- http
- ini
- java
- javascript
- json
- julia
- kotlin
- less
- lua
- makefile
- markdown
- nginx
- objectivec
- perl
- php
- plaintext
- properties
- python
- r
- ruby
- rust
- scala
- scss
- shell
- sql
- swift
- typescript
- x86asm
- xml
- yaml

## Custom theme

Like the rest of the theme, the files used for syntax highlighting can be overridden with your own.

- highlight.js normally you shouldn't have to overwrite this file, unless you want to use a more recent version.
- highlight.css theme used by highlight.js for syntax highlighting.

If you want to use another theme for `highlight.js` download it from their website, or make it yourself, rename it to `highlight.css` and put it in the `theme` folder of your book.

Now your theme will be used instead of the default theme.

## Hiding code lines

There is a feature in mdBook that lets you hide code lines by prepending them with a `#`.

    # fn main() {
        let x = 5;
        let y = 6;

        println!("{}", x + y);
    # }

Will render as

    fn main() {
        let x = 5;
        let y = 7;

        println!("{}", x + y);
    }

At the moment, this only works for code examples that are annotated with `rust`. Because it would collide with semantics of some programming languages. In the future, we want to make this configurable through the `book.toml` so that everyone can benefit from it.

## Improve default theme

If you think the default theme doesn't look quite right for a specific language, or could be improved, feel free to submit a new issue explaining what you have in mind and I will take a look at it.

You could also create a pull-request with the proposed improvements.

Overall the theme should be light and sober, without too many flashy colors.

# Editor

In addition to providing runnable code playgrounds, mdBook optionally allows them to be editable. In order to enable editable code blocks, the following needs to be added to the book.toml:

    [output.html.playground]
    editable = true

To make a specific block available for editing, the attribute `editable` needs to be added to it:

    ```rust,editable
    fn main() {
        let number = 5;
        print!("{}", number);
    }
    ```

The above will result in this editable playground:

    fn main() {
        let number = 5;
        print!("{}", number);
    }

Note the new `Undo Changes` button in the editable playgrounds.

## Customizing the Editor

By default, the editor is the Ace editor, but, if desired, the functionality may be overridden by providing a different folder:

    [output.html.playground]
    editable = true
    editor = "/path/to/editor"

Note that for the editor changes to function correctly, the `book.js` inside of the `theme` folder will need to be overridden as it has some couplings with the default Ace editor.

# MathJax Support

mdBook has optional support for math equations through MathJax.

To enable MathJax, you need to add the `mathjax-support` key to your `book.toml` under the `output.html` section.

    [output.html]
    mathjax-support = true

> Note: The usual delimiters MathJax uses are not yet supported. You can't currently use `$$ ... $$` as delimiters and the `\[ ... \]` delimiters need an extra backslash to work. Hopefully this limitation will be lifted soon.

> Note: When you use double backslashes in MathJax blocks (for example in commands such as `\begin{cases} \frac 1 2 \\ \frac 3 4 \end{cases}`) you need to add two extra backslashes (e.g., `\begin{cases} \frac 1 2 \\\\ \frac 3 4 \end{cases}`).

### Inline equations

Inline equations are delimited by `\\(` and `\\)`. So for example, to render the following inline equation \( \int x dx = \frac{x^2}{2} + C \) you would write the following:

    \\( \int x dx = \frac{x^2}{2} + C \\)

### Block equations

Block equations are delimited by `\\[` and `\\]`. To render the following equation

\[ \mu = \frac{1}{N} \sum_{i=0} x_i \]

you would write:

    \\[ \mu = \frac{1}{N} \sum_{i=0} x_i \\]

# mdBook-specific features

## Hiding code lines

There is a feature in mdBook that lets you hide code lines by prepending them with a `#` like you would with Rustdoc.

    # fn main() {
        let x = 5;
        let y = 6;

        println!("{}", x + y);
    # }

Will render as

    fn main() {
        let x = 5;
        let y = 6;

        println!("{}", x + y);
    }

## Including files

With the following syntax, you can include files into your book:

    {{#include file.rs}}

The path to the file has to be relative from the current source file.

mdBook will interpret included files as Markdown. Since the include command is usually used for inserting code snippets and examples, you will often wrap the command with ````` to display the file contents without interpreting them.

    ```
    {{#include file.rs}}
    ```

## Including portions of a file

Often you only need a specific part of the file, e.g. relevant lines for an example. We support four different modes of partial includes:

    {{#include file.rs:2}}
    {{#include file.rs::10}}
    {{#include file.rs:2:}}
    {{#include file.rs:2:10}}

The first command only includes the second line from file `file.rs`. The second command includes all lines up to line 10, i.e. the lines from 11 till the end of the file are omitted. The third command includes all lines from line 2, i.e. the first line is omitted. The last command includes the excerpt of `file.rs` consisting of lines 2 to 10.

To avoid breaking your book when modifying included files, you can also include a specific section using anchors instead of line numbers. An anchor is a pair of matching lines. The line beginning an anchor must match the regex `ANCHOR:\s*[\w_-]+` and similarly the ending line must match the regex `ANCHOR_END:\s*[\w_-]+`. This allows you to put anchors in any kind of commented line.

Consider the following file to include:

    /* ANCHOR: all */

    // ANCHOR: component
    struct Paddle {
        hello: f32,
    }
    // ANCHOR_END: component

    ////////// ANCHOR: system
    impl System for MySystem { ... }
    ////////// ANCHOR_END: system

    /* ANCHOR_END: all */

Then in the book, all you have to do is:

    Here is a component:
    ```rust,no_run,noplayground
    {{#include file.rs:component}}
    ```

    Here is a system:
    ```rust,no_run,noplayground
    {{#include file.rs:system}}
    ```

    This is the full file.
    ```rust,no_run,noplayground
    {{#include file.rs:all}}
    ```

Lines containing anchor patterns inside the included anchor are ignored.

## Including a file but initially hiding all except specified lines

The `rustdoc_include` helper is for including code from external Rust files that contain complete examples, but only initially showing particular lines specified with line numbers or anchors in the same way as with `include`.

The lines not in the line number range or between the anchors will still be included, but they will be prefaced with `#`. This way, a reader can expand the snippet to see the complete example, and Rustdoc will use the complete example when you run `mdbook test`.

For example, consider a file named `file.rs` that contains this Rust program:

    fn main() {
        let x = add_one(2);
        assert_eq!(x, 3);
    }

    fn add_one(num: i32) -> i32 {
        num + 1
    }

We can include a snippet that initially shows only line 2 by using this syntax:

    To call the `add_one` function, we pass it an `i32` and bind the returned value to `x`:

    ```rust
    {{#rustdoc_include file.rs:2}}
    ```

This would have the same effect as if we had manually inserted the code and hidden all but line 2 using `#`:

    To call the `add_one` function, we pass it an `i32` and bind the returned value to `x`:

    ```rust
    # fn main() {
        let x = add_one(2);
    #     assert_eq!(x, 3);
    # }
    #
    # fn add_one(num: i32) -> i32 {
    #     num + 1
    # }
    ```

That is, it looks like this (click the "expand" icon to see the rest of the file):

    fn main() {
        let x = add_one(2);
        assert_eq!(x, 3);
    }

    fn add_one(num: i32) -> i32 {
        num + 1
    }

## Inserting runnable Rust files

With the following syntax, you can insert runnable Rust files into your book:

    {{#playground file.rs}}

The path to the Rust file has to be relative from the current source file.

When play is clicked, the code snippet will be sent to the Rust Playground to be compiled and run. The result is sent back and displayed directly underneath the code.

Here is what a rendered code snippet looks like:

    fn main() {
        println!("Hello World!");

        // You can even hide lines! :D
        println!("I am hidden! Expand the code snippet to see me");
    }

## Controlling page <title>

A chapter can set a <title> that is different from its entry in the table of contents (sidebar) by including a `{{#title ...}}` near the top of the page.

    {{#title My Title}}

# Running `mdbook` in Continuous Integration

While the following examples use Travis CI, their principles should straightforwardly transfer to other continuous integration providers as well.

## Ensuring Your Book Builds and Tests Pass

Here is a sample Travis CI `.travis.yml` configuration that ensures `mdbook build` and `mdbook test` run successfully. The key to fast CI turnaround times is caching `mdbook` installs, so that you aren't compiling `mdbook` on every CI run.

    language: rust
    sudo: false

    cache:
      - cargo

    rust:
      - stable

    before_script:
      - (test -x $HOME/.cargo/bin/cargo-install-update || cargo install cargo-update)
      - (test -x $HOME/.cargo/bin/mdbook || cargo install --vers "^0.3" mdbook)
      - cargo install-update -a

    script:
      - mdbook build && mdbook test # In case of custom book path: mdbook build path/to/mybook && mdbook test path/to/mybook

## Deploying Your Book to GitHub Pages

Following these instructions will result in your book being published to GitHub pages after a successful CI run on your repository's `master` branch.

First, create a new GitHub "Personal Access Token" with the "public_repo" permissions (or "repo" for private repositories). Go to your repository's Travis CI settings page and add an environment variable named `GITHUB_TOKEN` that is marked secure and not shown in the logs.

Whilst still in your repository's settings page, navigate to Options and change the Source on GitHub pages to `gh-pages`.

Then, append this snippet to your `.travis.yml` and update the path to the `book` directory:

    deploy:
      provider: pages
      skip-cleanup: true
      github-token: $GITHUB_TOKEN
      local-dir: book # In case of custom book path: path/to/mybook/book
      keep-history: false
      on:
        branch: main

That's it!

Note: Travis has a new dplv2 configuration that is currently in beta. To use this new format, update your `.travis.yml` file to:

    language: rust
    os: linux
    dist: xenial

    cache:
      - cargo

    rust:
      - stable

    before_script:
      - (test -x $HOME/.cargo/bin/cargo-install-update || cargo install cargo-update)
      - (test -x $HOME/.cargo/bin/mdbook || cargo install --vers "^0.3" mdbook)
      - cargo install-update -a

    script:
      - mdbook build && mdbook test # In case of custom book path: mdbook build path/to/mybook && mdbook test path/to/mybook

    deploy:
      provider: pages
      strategy: git
      edge: true
      cleanup: false
      github-token: $GITHUB_TOKEN
      local-dir: book # In case of custom book path: path/to/mybook/book
      keep-history: false
      on:
        branch: main
      target_branch: gh-pages

### Deploying to GitHub Pages manually

If your CI doesn't support GitHub pages, or you're deploying somewhere else with integrations such as Github Pages: note: you may want to use different tmp dirs:

    $> git worktree add /tmp/book gh-pages
    $> mdbook build
    $> rm -rf /tmp/book/* # this won't delete the .git directory
    $> cp -rp book/* /tmp/book/
    $> cd /tmp/book
    $> git add -A
    $> git commit 'new book message'
    $> git push origin gh-pages
    $> cd -

Or put this into a Makefile rule:

    .PHONY: deploy
    deploy: book
    	@echo "====> deploying to github"
    	git worktree add /tmp/book gh-pages
    	rm -rf /tmp/book/*
    	cp -rp book/* /tmp/book/
    	cd /tmp/book && \
    		git add -A && \
    		git commit -m "deployed on $(shell date) by ${USER}" && \
    		git push origin gh-pages

## Deploying Your Book to GitLab Pages

Inside your repository's project root, create a file named `.gitlab-ci.yml` with the following contents:

    stages:
        - deploy

    pages:
      stage: deploy
      image: rust
      variables:
        CARGO_HOME: $CI_PROJECT_DIR/cargo
      before_script:
        - export PATH="$PATH:$CARGO_HOME/bin"
        - mdbook --version || cargo install mdbook
      script:
        - mdbook build -d public
      rules:
        - if: '$CI_COMMIT_REF_NAME == "master"'
      artifacts:
        paths:
          - public
      cache:
        paths:
          - $CARGO_HOME/bin

After you commit and push this new file, GitLab CI will run and your book will be available!

# For Developers

While `mdbook` is mainly used as a command line tool, you can also import the underlying library directly and use that to manage a book. It also has a fairly flexible plugin mechanism, allowing you to create your own custom tooling and consumers (often referred to as backends) if you need to do some analysis of the book or render it in a different format.

The For Developers chapters are here to show you the more advanced usage of `mdbook`.

The two main ways a developer can hook into the book's build process is via,

- Preprocessors
- Alternative Backends

## The Build Process

The process of rendering a book project goes through several steps.

1. Load the book
   - Parse the `book.toml`, falling back to the default `Config` if it doesn't exist
   - Load the book chapters into memory
   - Discover which preprocessors/backends should be used
2. Run the preprocessors
3. Call each backend in turn

## Using `mdbook` as a Library

The `mdbook` binary is just a wrapper around the `mdbook` crate, exposing its functionality as a command-line program. As such it is quite easy to create your own programs which use `mdbook` internally, adding your own functionality (e.g. a custom preprocessor) or tweaking the build process.

The easiest way to find out how to use the `mdbook` crate is by looking at the API Docs. The top level documentation explains how one would use the `MDBook` type to load and build a book, while the config module gives a good explanation on the configuration system.

# Preprocessors

A preprocessor is simply a bit of code which gets run immediately after the book is loaded and before it gets rendered, allowing you to update and mutate the book. Possible use cases are:

- Creating custom helpers like `{{#include /path/to/file.md}}`
- Updating links so `[some chapter](some_chapter.md)` is automatically changed to `[some chapter](some_chapter.html)` for the HTML renderer
- Substituting in latex-style expressions (`$$ \frac{1}{3} $$`) with their mathjax equivalents

## Hooking Into MDBook

MDBook uses a fairly simple mechanism for discovering third party plugins. A new table is added to `book.toml` (e.g. `preprocessor.foo` for the `foo` preprocessor) and then `mdbook` will try to invoke the `mdbook-foo` program as part of the build process.

A preprocessor can be hard-coded to specify which backend(s) it should be run for with the `preprocessor.foo.renderer` key. For example, it doesn't make sense for MathJax to be used for non-HTML renderers.

    [book]
    title = "My Book"
    authors = ["Michael-F-Bryan"]

    [preprocessor.foo]
    # The command can also be specified manually
    command = "python3 /path/to/foo.py"
    # Only run the `foo` preprocessor for the HTML and EPUB renderer
    renderer = ["html", "epub"]

Once the preprocessor has been defined and the build process starts, mdBook executes the command defined in the `preprocessor.foo.command` key twice. The first time it runs the preprocessor to determine if it supports the given renderer. mdBook passes two arguments to the process: the first argument is the string `supports` and the second argument is the renderer name. The preprocessor should exit with a status code 0 if it supports the given renderer, or return a non-zero exit code if it does not.

If the preprocessor supports the renderer, then mdbook runs it a second time, passing JSON data into stdin. The JSON consists of an array of `[context, book]` where `context` is the serialized object `PreprocessorContext` and `book` is a `Book` object containing the content of the book.

The preprocessor should return the JSON format of the `Book` object to stdout, with any modifications it wishes to perform.

The easiest way to get started is by creating your own implementation of the `Preprocessor` trait (e.g. in `lib.rs`) and then creating a shell binary which translates inputs to the correct `Preprocessor` method. For convenience, there is an example no-op preprocessor in the `examples/` directory which can easily be adapted for other preprocessors.

Example no-op preprocessor

    // nop-preprocessors.rs

    use crate::nop_lib::Nop;
    use clap::{App, Arg, ArgMatches, SubCommand};
    use mdbook::book::Book;
    use mdbook::errors::Error;
    use mdbook::preprocess::{CmdPreprocessor, Preprocessor, PreprocessorContext};
    use semver::{Version, VersionReq};
    use std::io;
    use std::process;

    pub fn make_app() -> App<'static, 'static> {
        App::new("nop-preprocessor")
            .about("A mdbook preprocessor which does precisely nothing")
            .subcommand(
                SubCommand::with_name("supports")
                    .arg(Arg::with_name("renderer").required(true))
                    .about("Check whether a renderer is supported by this preprocessor"),
            )
    }

    fn main() {
        let matches = make_app().get_matches();

        // Users will want to construct their own preprocessor here
        let preprocessor = Nop::new();

        if let Some(sub_args) = matches.subcommand_matches("supports") {
            handle_supports(&preprocessor, sub_args);
        } else if let Err(e) = handle_preprocessing(&preprocessor) {
            eprintln!("{}", e);
            process::exit(1);
        }
    }

    fn handle_preprocessing(pre: &dyn Preprocessor) -> Result<(), Error> {
        let (ctx, book) = CmdPreprocessor::parse_input(io::stdin())?;

        let book_version = Version::parse(&ctx.mdbook_version)?;
        let version_req = VersionReq::parse(mdbook::MDBOOK_VERSION)?;

        if !version_req.matches(&book_version) {
            eprintln!(
                "Warning: The {} plugin was built against version {} of mdbook, \
                 but we're being called from version {}",
                pre.name(),
                mdbook::MDBOOK_VERSION,
                ctx.mdbook_version
            );
        }

        let processed_book = pre.run(&ctx, book)?;
        serde_json::to_writer(io::stdout(), &processed_book)?;

        Ok(())
    }

    fn handle_supports(pre: &dyn Preprocessor, sub_args: &ArgMatches) -> ! {
        let renderer = sub_args.value_of("renderer").expect("Required argument");
        let supported = pre.supports_renderer(renderer);

        // Signal whether the renderer is supported by exiting with 1 or 0.
        if supported {
            process::exit(0);
        } else {
            process::exit(1);
        }
    }

    /// The actual implementation of the `Nop` preprocessor. This would usually go
    /// in your main `lib.rs` file.
    mod nop_lib {
        use super::*;

        /// A no-op preprocessor.
        pub struct Nop;

        impl Nop {
            pub fn new() -> Nop {
                Nop
            }
        }

        impl Preprocessor for Nop {
            fn name(&self) -> &str {
                "nop-preprocessor"
            }

            fn run(&self, ctx: &PreprocessorContext, book: Book) -> Result<Book, Error> {
                // In testing we want to tell the preprocessor to blow up by setting a
                // particular config value
                if let Some(nop_cfg) = ctx.config.get_preprocessor(self.name()) {
                    if nop_cfg.contains_key("blow-up") {
                        anyhow::bail!("Boom!!1!");
                    }
                }

                // we *are* a no-op preprocessor after all
                Ok(book)
            }

            fn supports_renderer(&self, renderer: &str) -> bool {
                renderer != "not-supported"
            }
        }
    }

## Hints For Implementing A Preprocessor

By pulling in `mdbook` as a library, preprocessors can have access to the existing infrastructure for dealing with books.

For example, a custom preprocessor could use the `CmdPreprocessor::parse_input()` function to deserialize the JSON written to `stdin`. Then each chapter of the `Book` can be mutated in-place via `Book::for_each_mut()`, and then written to `stdout` with the `serde_json` crate.

Chapters can be accessed either directly (by recursively iterating over chapters) or via the `Book::for_each_mut()` convenience method.

The `chapter.content` is just a string which happens to be markdown. While it's entirely possible to use regular expressions or do a manual find & replace, you'll probably want to process the input into something more computer-friendly. The `pulldown-cmark` crate implements a production-quality event-based Markdown parser, with the `pulldown-cmark-to-cmark` allowing you to translate events back into markdown text.

The following code block shows how to remove all emphasis from markdown, without accidentally breaking the document.

    #![allow(unused)]
    fn main() {
    fn remove_emphasis(
        num_removed_items: &mut usize,
        chapter: &mut Chapter,
    ) -> Result<String> {
        let mut buf = String::with_capacity(chapter.content.len());

        let events = Parser::new(&chapter.content).filter(|e| {
            let should_keep = match *e {
                Event::Start(Tag::Emphasis)
                | Event::Start(Tag::Strong)
                | Event::End(Tag::Emphasis)
                | Event::End(Tag::Strong) => false,
                _ => true,
            };
            if !should_keep {
                *num_removed_items += 1;
            }
            should_keep
        });

        cmark(events, &mut buf, None).map(|_| buf).map_err(|err| {
            Error::from(format!("Markdown serialization failed: {}", err))
        })
    }
    }

For everything else, have a look at the complete example.

## Implementing a preprocessor with a different language

The fact that mdBook utilizes stdin and stdout to communicate with the preprocessors makes it easy to implement them in a language other than Rust. The following code shows how to implement a simple preprocessor in Python, which will modify the content of the first chapter. The example below follows the configuration shown above with `preprocessor.foo.command` actually pointing to a Python script.

    import json
    import sys

    if __name__ == '__main__':
        if len(sys.argv) > 1: # we check if we received any argument
            if sys.argv[1] == "supports":
                # then we are good to return an exit status code of 0, since the other argument will just be the renderer's name
                sys.exit(0)

        # load both the context and the book representations from stdin
        context, book = json.load(sys.stdin)
        # and now, we can just modify the content of the first chapter
        book['sections'][0]['Chapter']['content'] = '# Hello'
        # we are done with the book's modification, we can just print it to stdout,
        print(json.dumps(book))

# Alternative Backends

A "backend" is simply a program which `mdbook` will invoke during the book rendering process. This program is passed a JSON representation of the book and configuration information via `stdin`. Once the backend receives this information it is free to do whatever it wants.

There are already several alternative backends on GitHub which can be used as a rough example of how this is accomplished in practice.

- mdbook-linkcheck - a simple program for verifying the book doesn't contain any broken links
- mdbook-epub - an EPUB renderer
- mdbook-test - a program to run the book's contents through rust-skeptic to verify everything compiles and runs correctly (similar to `rustdoc --test`)
- mdbook-man - generate manual pages from the book

This page will step you through creating your own alternative backend in the form of a simple word counting program. Although it will be written in Rust, there's no reason why it couldn't be accomplished using something like Python or Ruby.

## Setting Up

First you'll want to create a new binary program and add `mdbook` as a dependency.

    $ cargo new --bin mdbook-wordcount
    $ cd mdbook-wordcount
    $ cargo add mdbook

When our `mdbook-wordcount` plugin is invoked, `mdbook` will send it a JSON version of `RenderContext` via our plugin's `stdin`. For convenience, there's a `RenderContext::from_json()` constructor which will load a `RenderContext`.

This is all the boilerplate necessary for our backend to load the book.

    // src/main.rs
    extern crate mdbook;

    use std::io;
    use mdbook::renderer::RenderContext;

    fn main() {
        let mut stdin = io::stdin();
        let ctx = RenderContext::from_json(&mut stdin).unwrap();
    }

> Note: The `RenderContext` contains a `version` field. This lets backends figure out whether they are compatible with the version of `mdbook` it's being called by. This `version` comes directly from the corresponding field in `mdbook`'s `Cargo.toml`.

It is recommended that backends use the `semver` crate to inspect this field and emit a warning if there may be a compatibility issue.

## Inspecting the Book

Now our backend has a copy of the book, lets count how many words are in each chapter!

Because the `RenderContext` contains a `Book` field (`book`), and a `Book` has the `Book::iter()` method for iterating over all items in a `Book`, this step turns out to be just as easy as the first.

    fn main() {
        let mut stdin = io::stdin();
        let ctx = RenderContext::from_json(&mut stdin).unwrap();

        for item in ctx.book.iter() {
            if let BookItem::Chapter(ref ch) = *item {
                let num_words = count_words(ch);
                println!("{}: {}", ch.name, num_words);
            }
        }
    }

    fn count_words(ch: &Chapter) -> usize {
        ch.content.split_whitespace().count()
    }

## Enabling the Backend

Now we've got the basics running, we want to actually use it. First, install the program.

    $ cargo install --path .

Then `cd` to the particular book you'd like to count the words of and update its `book.toml` file.

      [book]
      title = "mdBook Documentation"
      description = "Create book from markdown files. Like Gitbook but implemented in Rust"
      authors = ["Mathieu David", "Michael-F-Bryan"]

    + [output.html]

    + [output.wordcount]

When it loads a book into memory, `mdbook` will inspect your `book.toml` file to try and figure out which backends to use by looking for all `output.*` tables. If none are provided it'll fall back to using the default HTML renderer.

Notably, this means if you want to add your own custom backend you'll also need to make sure to add the HTML backend, even if its table just stays empty.

Now you just need to build your book like normal, and everything should Just Work.

    $ mdbook build
    ...
    2018-01-16 07:31:15 [INFO] (mdbook::renderer): Invoking the "mdbook-wordcount" renderer
    mdBook: 126
    Command Line Tool: 224
    init: 283
    build: 145
    watch: 146
    serve: 292
    test: 139
    Format: 30
    SUMMARY.md: 259
    Configuration: 784
    Theme: 304
    index.hbs: 447
    Syntax highlighting: 314
    MathJax Support: 153
    Rust code specific features: 148
    For Developers: 788
    Alternative Backends: 710
    Contributors: 85

The reason we didn't need to specify the full name/path of our `wordcount` backend is because `mdbook` will try to infer the program's name via convention. The executable for the `foo` backend is typically called `mdbook-foo`, with an associated `[output.foo]` entry in the `book.toml`. To explicitly tell `mdbook` what command to invoke (it may require command-line arguments or be an interpreted script), you can use the `command` field.

      [book]
      title = "mdBook Documentation"
      description = "Create book from markdown files. Like Gitbook but implemented in Rust"
      authors = ["Mathieu David", "Michael-F-Bryan"]

      [output.html]

      [output.wordcount]
    + command = "python /path/to/wordcount.py"

## Configuration

Now imagine you don't want to count the number of words on a particular chapter (it might be generated text/code, etc). The canonical way to do this is via the usual `book.toml` configuration file by adding items to your `[output.foo]` table.

The `Config` can be treated roughly as a nested hashmap which lets you call methods like `get()` to access the config's contents, with a `get_deserialized()` convenience method for retrieving a value and automatically deserializing to some arbitrary type `T`.

To implement this, we'll create our own serializable `WordcountConfig` struct which will encapsulate all configuration for this backend.

First add `serde` and `serde_derive` to your `Cargo.toml`,

    $ cargo add serde serde_derive

And then you can create the config struct,

    #![allow(unused)]
    fn main() {
    extern crate serde;
    #[macro_use]
    extern crate serde_derive;

    ...

    #[derive(Debug, Default, Serialize, Deserialize)]
    #[serde(default, rename_all = "kebab-case")]
    pub struct WordcountConfig {
      pub ignores: Vec<String>,
    }
    }

Now we just need to deserialize the `WordcountConfig` from our `RenderContext` and then add a check to make sure we skip ignored chapters.

      fn main() {
          let mut stdin = io::stdin();
          let ctx = RenderContext::from_json(&mut stdin).unwrap();
    +     let cfg: WordcountConfig = ctx.config
    +         .get_deserialized("output.wordcount")
    +         .unwrap_or_default();

          for item in ctx.book.iter() {
              if let BookItem::Chapter(ref ch) = *item {
    +             if cfg.ignores.contains(&ch.name) {
    +                 continue;
    +             }
    +
                  let num_words = count_words(ch);
                  println!("{}: {}", ch.name, num_words);
              }
          }
      }

## Output and Signalling Failure

While it's nice to print word counts to the terminal when a book is built, it might also be a good idea to output them to a file somewhere. `mdbook` tells a backend where it should place any generated output via the `destination` field in `RenderContext`.

    + use std::fs::{self, File};
    + use std::io::{self, Write};
    - use std::io;
      use mdbook::renderer::RenderContext;
      use mdbook::book::{BookItem, Chapter};

      fn main() {
        ...

    +     let _ = fs::create_dir_all(&ctx.destination);
    +     let mut f = File::create(ctx.destination.join("wordcounts.txt")).unwrap();
    +
          for item in ctx.book.iter() {
              if let BookItem::Chapter(ref ch) = *item {
                  ...

                  let num_words = count_words(ch);
                  println!("{}: {}", ch.name, num_words);
    +             writeln!(f, "{}: {}", ch.name, num_words).unwrap();
              }
          }
      }

> Note: There is no guarantee that the destination directory exists or is empty (`mdbook` may leave the previous contents to let backends do caching), so it's always a good idea to create it with `fs::create_dir_all()`.

> If the destination directory already exists, don't assume it will be empty. To allow backends to cache the results from previous runs, `mdbook` may leave old content in the directory.

There's always the possibility that an error will occur while processing a book (just look at all the `unwrap()`'s we've written already), so `mdbook` will interpret a non-zero exit code as a rendering failure.

For example, if we wanted to make sure all chapters have an even number of words, erroring out if an odd number is encountered, then you may do something like this:

    + use std::process;
      ...

      fn main() {
          ...

          for item in ctx.book.iter() {
              if let BookItem::Chapter(ref ch) = *item {
                  ...

                  let num_words = count_words(ch);
                  println!("{}: {}", ch.name, num_words);
                  writeln!(f, "{}: {}", ch.name, num_words).unwrap();

    +             if cfg.deny_odds && num_words % 2 == 1 {
    +               eprintln!("{} has an odd number of words!", ch.name);
    +               process::exit(1);
                  }
              }
          }
      }

      #[derive(Debug, Default, Serialize, Deserialize)]
      #[serde(default, rename_all = "kebab-case")]
      pub struct WordcountConfig {
          pub ignores: Vec<String>,
    +     pub deny_odds: bool,
      }

Now, if we reinstall the backend and build a book,

    $ cargo install --path . --force
    $ mdbook build /path/to/book
    ...
    2018-01-16 21:21:39 [INFO] (mdbook::renderer): Invoking the "wordcount" renderer
    mdBook: 126
    Command Line Tool: 224
    init: 283
    init has an odd number of words!
    2018-01-16 21:21:39 [ERROR] (mdbook::renderer): Renderer exited with non-zero return code.
    2018-01-16 21:21:39 [ERROR] (mdbook::utils): Error: Rendering failed
    2018-01-16 21:21:39 [ERROR] (mdbook::utils):    Caused By: The "mdbook-wordcount" renderer failed

As you've probably already noticed, output from the plugin's subprocess is immediately passed through to the user. It is encouraged for plugins to follow the "rule of silence" and only generate output when necessary (e.g. an error in generation or a warning).

All environment variables are passed through to the backend, allowing you to use the usual `RUST_LOG` to control logging verbosity.

## Handling missing backends

If you enable a backend that isn't installed, the default behavior is to throw an error:

    The command `mdbook-wordcount` wasn't found, is the "wordcount" backend installed?
    If you want to ignore this error when the "wordcount" backend is not installed,
    set `optional = true` in the `[output.wordcount]` section of the book.toml configuration file.

This behavior can be changed by marking the backend as optional.

      [book]
      title = "mdBook Documentation"
      description = "Create book from markdown files. Like Gitbook but implemented in Rust"
      authors = ["Mathieu David", "Michael-F-Bryan"]

      [output.html]

      [output.wordcount]
      command = "python /path/to/wordcount.py"
    + optional = true

This demotes the error to a warning, and it will instead look like this:

    The command was not found, but was marked as optional.
        Command: wordcount

## Wrapping Up

Although contrived, hopefully this example was enough to show how you'd create an alternative backend for `mdbook`. If you feel it's missing something, don't hesitate to create an issue in the issue tracker so we can improve the user guide.

The existing backends mentioned towards the start of this chapter should serve as a good example of how it's done in real life, so feel free to skim through the source code or ask questions.

# Contributors

Here is a list of the contributors who have helped improving mdBook. Big shout-out to them!

- mdinger
- Kevin (kbknapp)
- Steve Klabnik (steveklabnik)
- Adam Solove (asolove)
- Wayne Nilsen (waynenilsen)
- funnkill
- Fu Gangqiang (FuGangqiang)
- Michael-F-Bryan
- Chris Spiegel (cspiegel)
- projektir
- Phaiax
- Matt Ickstadt (mattico)
- Weihang Lo (weihanglo)
- Avision Ho (avisionh)
- Vivek Akupatni (apatniv)
- Eric Huss (ehuss)
- Josh Rotenberg (joshrotenberg)

If you feel you're missing from this list, feel free to add yourself in a PR.