diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index bd3c7558..bfd114ca 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -31,7 +31,8 @@ jobs:
rust: stable
- build: msrv
os: ubuntu-latest
- rust: 1.46.0
+ # sync MSRV with docs: guide/src/guide/installation.md
+ rust: 1.54.0
steps:
- uses: actions/checkout@master
- name: Install Rust
@@ -48,4 +49,4 @@ jobs:
- uses: actions/checkout@master
- name: Install Rust
run: rustup update stable && rustup default stable && rustup component add rustfmt
- - run: cargo fmt -- --check
+ - run: cargo fmt --check
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 83e7818f..87d281c4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,50 @@
# Changelog
+## mdBook 0.4.17
+[a5fddfa...981b79b](https://github.com/rust-lang/mdBook/compare/a5fddfa...981b79b)
+
+### Fixed
+- Fixed parsing of `output.html.print` configuration table.
+ [#1775](https://github.com/rust-lang/mdBook/pull/1775)
+
+## mdBook 0.4.16
+[68a5c09...a5fddfa](https://github.com/rust-lang/mdBook/compare/68a5c09...a5fddfa)
+
+### Added
+- Added `output.html.print.page-break` config option to control whether or not
+ there is a page break between chapters in the print output.
+ [#1728](https://github.com/rust-lang/mdBook/pull/1728)
+- Added `output.html.playground.runnable` config option to globally disable
+ the run button in code blocks.
+ [#1546](https://github.com/rust-lang/mdBook/pull/1546)
+
+### Changed
+- The `cargo serve` live reload websocket now uses the protocol, host, and
+ port of the current page, allowing access through a proxy.
+ [#1771](https://github.com/rust-lang/mdBook/pull/1771)
+- The 404 not-found page now includes the books title in the HTML title tag.
+ [#1693](https://github.com/rust-lang/mdBook/pull/1693)
+- Migrated to clap 3.0 which which handles CLI option parsing.
+ [#1731](https://github.com/rust-lang/mdBook/pull/1731)
+
+### Fixed
+- Minor fixes to the markdown parser.
+ [#1729](https://github.com/rust-lang/mdBook/pull/1729)
+- Fixed incorrect parsing in `SUMMARY.md` when it didn't start with a title.
+ [#1744](https://github.com/rust-lang/mdBook/pull/1744)
+- Fixed duplicate anchor IDs for links in search results.
+ [#1749](https://github.com/rust-lang/mdBook/pull/1749)
+
+## mdBook 0.4.15
+[5eb7d46...68a5c09](https://github.com/rust-lang/mdBook/compare/5eb7d46...68a5c09)
+
+### Changed
+- Major update to expand the documentation located at .
+ [#1709](https://github.com/rust-lang/mdBook/pull/1709)
+ [#1710](https://github.com/rust-lang/mdBook/pull/1710)
+- Updated the markdown parser with various fixes for common-mark compliance.
+ [#1712](https://github.com/rust-lang/mdBook/pull/1712)
+
## mdBook 0.4.14
[ffa8284...c9b6be8](https://github.com/rust-lang/mdBook/compare/ffa8284...c9b6be8)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 924cfdba..72010ad2 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -127,4 +127,4 @@ The following are instructions for updating [highlight.js](https://highlightjs.o
1. Compare the language list that it spits out to the one in [`syntax-highlighting.md`](https://github.com/camelid/mdBook/blob/master/guide/src/format/theme/syntax-highlighting.md). If any are missing, add them to the list and rebuild (and update these docs). If any are added to the common set, add them to `syntax-highlighting.md`.
1. Copy `build/highlight.min.js` to mdbook's directory [`highlight.js`](https://github.com/rust-lang/mdBook/blob/master/src/theme/highlight.js).
1. Be sure to check the highlight.js [CHANGES](https://github.com/highlightjs/highlight.js/blob/main/CHANGES.md) for any breaking changes. Breaking changes that would affect users will need to wait until the next major release.
-1. Build mdbook with the new file and build some books with the new version and compare the output with a variety of languages to see if anything changes. (TODO: It would be nice to have a demo file in the repo to help with this.)
+1. Build mdbook with the new file and build some books with the new version and compare the output with a variety of languages to see if anything changes. The [test_book](https://github.com/rust-lang/mdBook/tree/master/test_book) contains a chapter with many languages to examine.
diff --git a/Cargo.lock b/Cargo.lock
index ea59887b..2428b308 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -185,17 +185,27 @@ dependencies = [
[[package]]
name = "clap"
-version = "2.33.3"
+version = "3.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
+checksum = "7a30c3bf9ff12dfe5dae53f0a96e0febcd18420d1c0e7fad77796d9d5c4b5375"
dependencies = [
- "ansi_term",
"atty",
"bitflags",
+ "indexmap",
+ "lazy_static",
+ "os_str_bytes",
"strsim",
+ "termcolor",
"textwrap",
- "unicode-width",
- "vec_map",
+]
+
+[[package]]
+name = "clap_complete"
+version = "3.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d044e9db8cd0f68191becdeb5246b7462e4cf0c069b19ae00d1bf3fa9889498d"
+dependencies = [
+ "clap",
]
[[package]]
@@ -473,15 +483,6 @@ dependencies = [
"version_check",
]
-[[package]]
-name = "getopts"
-version = "0.2.21"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5"
-dependencies = [
- "unicode-width",
-]
-
[[package]]
name = "getrandom"
version = "0.1.16"
@@ -839,13 +840,14 @@ checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f"
[[package]]
name = "mdbook"
-version = "0.4.14"
+version = "0.4.17"
dependencies = [
"ammonia",
"anyhow",
"assert_cmd",
"chrono",
"clap",
+ "clap_complete",
"elasticlunr-rs",
"env_logger",
"futures-util",
@@ -1062,6 +1064,15 @@ dependencies = [
"winapi 0.3.9",
]
+[[package]]
+name = "os_str_bytes"
+version = "6.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64"
+dependencies = [
+ "memchr",
+]
+
[[package]]
name = "output_vt100"
version = "0.1.2"
@@ -1267,12 +1278,11 @@ dependencies = [
[[package]]
name = "pulldown-cmark"
-version = "0.8.0"
+version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ffade02495f22453cd593159ea2f59827aae7f53fa8323f756799b670881dcf8"
+checksum = "34f197a544b0c9ab3ae46c359a7ec9cbbb5c7bf97054266fecb7ead794a181d6"
dependencies = [
"bitflags",
- "getopts",
"memchr",
"unicase",
]
@@ -1400,9 +1410,9 @@ dependencies = [
[[package]]
name = "regex"
-version = "1.5.4"
+version = "1.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
+checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286"
dependencies = [
"aho-corasick",
"memchr",
@@ -1464,21 +1474,9 @@ dependencies = [
[[package]]
name = "semver"
-version = "0.11.0"
+version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6"
-dependencies = [
- "semver-parser",
-]
-
-[[package]]
-name = "semver-parser"
-version = "0.10.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7"
-dependencies = [
- "pest",
-]
+checksum = "568a8e6258aa33c13358f81fd834adb854c6f7c9468520910a9b1e8fac068012"
[[package]]
name = "serde"
@@ -1600,9 +1598,9 @@ dependencies = [
[[package]]
name = "strsim"
-version = "0.8.0"
+version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
+checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "strum"
@@ -1669,12 +1667,9 @@ dependencies = [
[[package]]
name = "textwrap"
-version = "0.11.0"
+version = "0.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
-dependencies = [
- "unicode-width",
-]
+checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80"
[[package]]
name = "time"
@@ -1882,12 +1877,6 @@ version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b"
-[[package]]
-name = "unicode-width"
-version = "0.1.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
-
[[package]]
name = "unicode-xid"
version = "0.2.2"
@@ -1912,12 +1901,6 @@ version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
-[[package]]
-name = "vec_map"
-version = "0.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
-
[[package]]
name = "version_check"
version = "0.9.3"
diff --git a/Cargo.toml b/Cargo.toml
index fc5e1b16..15f0e5ec 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "mdbook"
-version = "0.4.14"
+version = "0.4.17"
authors = [
"Mathieu David ",
"Michael-F-Bryan ",
@@ -18,15 +18,16 @@ description = "Creates a book from markdown files"
[dependencies]
anyhow = "1.0.28"
chrono = "0.4"
-clap = "2.24"
+clap = { version = "3.0", features = ["cargo"] }
+clap_complete = "3.0"
env_logger = "0.7.1"
handlebars = "4.0"
lazy_static = "1.0"
log = "0.4"
memchr = "2.0"
opener = "0.5"
-pulldown-cmark = "0.8.0"
-regex = "1.0.0"
+pulldown-cmark = { version = "0.9.1", default-features = false }
+regex = "1.5.5"
serde = "1.0"
serde_derive = "1.0"
serde_json = "1.0"
@@ -52,7 +53,7 @@ ammonia = { version = "3", optional = true }
assert_cmd = "1"
predicates = "2"
select = "0.5"
-semver = "0.11.0"
+semver = "1.0"
pretty_assertions = "0.6"
walkdir = "2.0"
diff --git a/README.md b/README.md
index c70cf225..b2177cf3 100644
--- a/README.md
+++ b/README.md
@@ -6,233 +6,15 @@
mdBook is a utility to create modern online books from Markdown files.
+Check out the **[User Guide]** for a list of features and installation and usage information.
+The User Guide also serves as a demonstration to showcase what a book looks like.
-## What does it look like?
-
-The [User Guide] for mdBook has been written in Markdown and is using mdBook to
-generate the online book-like website you can read. The documentation uses the
-latest version on GitHub and showcases the available features.
-
-## Installation
-
-There are multiple ways to install mdBook.
-
-1. **Binaries**
-
- Binaries are available for download [here][releases]. Make sure to put the
- path to the binary into your `PATH`.
-
-2. **From Crates.io**
-
- This requires at least [Rust] 1.46 and Cargo to be installed. Once you have installed
- Rust, type the following in the terminal:
-
- ```
- cargo install mdbook
- ```
-
- This will download and compile mdBook for you, the only thing left to do is
- to add the Cargo bin directory to your `PATH`.
-
- **Note for automatic deployment**
-
- If you are using a script to do automatic deployments, we recommend that
- you specify a semver version range for mdBook when you install it through
- your script!
-
- This will constrain the server to install the latest **non-breaking**
- version of mdBook and will prevent your books from failing to build because
- we released a new version.
-
- You can also disable default features to speed up compile time.
-
- Example:
-
- ```
- cargo install mdbook --no-default-features --vers "^0.4.0"
- ```
-
-3. **From Git**
-
- The version published to crates.io will ever so slightly be behind the
- version hosted here on GitHub. If you need the latest version you can build
- the git version of mdBook yourself. Cargo makes this ***super easy***!
-
- ```
- cargo install --git https://github.com/rust-lang/mdBook.git mdbook
- ```
-
- Again, make sure to add the Cargo bin directory to your `PATH`.
-
-4. **For Contributions**
-
- If you want to contribute to mdBook you will have to clone the repository on
- your local machine:
-
- ```
- git clone https://github.com/rust-lang/mdBook.git
- ```
-
- `cd` into `mdBook/` and run
-
- ```
- cargo build
- ```
-
- The resulting binary can be found in `mdBook/target/debug/` under the name
- `mdBook` or `mdBook.exe`.
-
-
-## Usage
-
-mdBook is primarily used as a command line tool, even though it exposes
-all its functionality as a Rust crate for integration in other projects.
-
-Here are the main commands you will want to run. For a more exhaustive
-explanation, check out the [User Guide].
-
-- `mdbook init `
-
- The init command will create a directory with the minimal boilerplate to
- start with. If the `` parameter is omitted, the current
- directory will be used.
-
- ```
- book-test/
- ├── book
- └── src
- ├── chapter_1.md
- └── SUMMARY.md
- ```
-
- `book` and `src` are both directories. `src` contains the markdown files
- that will be used to render the output to the `book` directory.
-
- Please, take a look at the [CLI docs] for more information and some neat tricks.
-
-- `mdbook build`
-
- This is the command you will run to render your book, it reads the
- `SUMMARY.md` file to understand the structure of your book, takes the
- markdown files in the source directory as input and outputs static html
- pages that you can upload to a server.
-
-- `mdbook watch`
-
- When you run this command, mdbook will watch your markdown files to rebuild
- the book on every change. This avoids having to come back to the terminal
- to type `mdbook build` over and over again.
-
-- `mdbook serve`
-
- Does the same thing as `mdbook watch` but additionally serves the book at
- `http://localhost:3000` (port is changeable) and reloads the browser when a
- change occurs.
-
-- `mdbook clean`
-
- Delete directory in which generated book is located.
-
-### 3rd Party Plugins
-
-The way a book is loaded and rendered can be configured by the user via third
-party plugins. These plugins are just programs which will be invoked during the
-build process and are split into roughly two categories, *preprocessors* and
-*renderers*.
-
-Preprocessors are used to transform a book before it is sent to a renderer.
-One example would be to replace all occurrences of
-`{{#include some_file.ext}}` with the contents of that file. Some existing
-preprocessors are:
-
-- `index` - a built-in preprocessor (enabled by default) which will transform
- all `README.md` chapters to `index.md` so `foo/README.md` can be accessed via
- the url `foo/` when published to a browser
-- `links` - a built-in preprocessor (enabled by default) for expanding the
- `{{# playground}}` and `{{# include}}` helpers in a chapter.
-- [`katex`](https://github.com/lzanini/mdbook-katex) - a preprocessor rendering LaTex equations to HTML.
-
-Renderers are given the final book so they can do something with it. This is
-typically used for, as the name suggests, rendering the document in a particular
-format, however there's nothing stopping a renderer from doing static analysis
-of a book in order to validate links or run tests. Some existing renderers are:
-
-- `html` - the built-in renderer which will generate a HTML version of the book
-- `markdown` - the built-in renderer (disabled by default) which will run
- preprocessors then output the resulting Markdown. Useful for debugging
- preprocessors.
-- [`linkcheck`] - a backend which will check that all links are valid
-- [`epub`] - an experimental EPUB generator
-- [`man`] - a backend that generates manual pages from the book
-
-> **Note for Developers:** Feel free to send us a PR if you've developed your
-> own plugin and want it mentioned here.
-
-A preprocessor or renderer is enabled by installing the appropriate program and
-then mentioning it in the book's `book.toml` file.
-
-```console
-$ cargo install mdbook-linkcheck
-$ edit book.toml && cat book.toml
-[book]
-title = "My Awesome Book"
-authors = ["Michael-F-Bryan"]
-
-[output.html]
-
-[output.linkcheck] # enable the "mdbook-linkcheck" renderer
-
-$ mdbook build
-2018-10-20 13:57:51 [INFO] (mdbook::book): Book building has started
-2018-10-20 13:57:51 [INFO] (mdbook::book): Running the html backend
-2018-10-20 13:57:53 [INFO] (mdbook::book): Running the linkcheck backend
-```
-
-For more information on the plugin system, consult the [User Guide].
-
-### As a library
-
-Aside from the command line interface, this crate can also be used as a
-library. This means that you could integrate it in an existing project, like a
-web-app for example. Since the command line interface is just a wrapper around
-the library functionality, when you use this crate as a library you have full
-access to all the functionality of the command line interface with an easy to
-use API and more!
-
-See the [User Guide] and the [API docs] for more information.
-
-## Contributions
-
-Contributions are highly appreciated and encouraged! Don't hesitate to
-participate to discussions in the issues, propose new features and ask for
-help.
-
-If you are just starting out with Rust, there are a series of issues that are
-tagged [E-Easy] and **we will gladly mentor you** so that you can successfully
-go through the process of fixing a bug or adding a new feature! Let us know if
-you need any help.
-
-For more info about contributing, check out our [contribution guide] which helps
-you go through the build and contribution process!
-
-There is also a [rendered version][master-docs] of the latest API docs
-available, for those hacking on `master`.
-
+If you are interested in contributing to the development of mdBook, check out the [Contribution Guide].
## License
All the code in this repository is released under the ***Mozilla Public License v2.0***, for more information take a look at the [LICENSE] file.
-
[User Guide]: https://rust-lang.github.io/mdBook/
-[API docs]: https://docs.rs/mdbook/*/mdbook/
-[E-Easy]: https://github.com/rust-lang/mdBook/issues?q=is%3Aopen+is%3Aissue+label%3AE-Easy
[contribution guide]: https://github.com/rust-lang/mdBook/blob/master/CONTRIBUTING.md
[LICENSE]: https://github.com/rust-lang/mdBook/blob/master/LICENSE
-[releases]: https://github.com/rust-lang/mdBook/releases
-[Rust]: https://www.rust-lang.org/
-[CLI docs]: http://rust-lang.github.io/mdBook/cli/init.html
-[master-docs]: http://rust-lang.github.io/mdBook/
-[`linkcheck`]: https://crates.io/crates/mdbook-linkcheck
-[`epub`]: https://crates.io/crates/mdbook-epub
-[`man`]: https://crates.io/crates/mdbook-man
diff --git a/examples/nop-preprocessor.rs b/examples/nop-preprocessor.rs
index 486fd86d..ace40093 100644
--- a/examples/nop-preprocessor.rs
+++ b/examples/nop-preprocessor.rs
@@ -1,5 +1,5 @@
use crate::nop_lib::Nop;
-use clap::{App, Arg, ArgMatches, SubCommand};
+use clap::{App, Arg, ArgMatches};
use mdbook::book::Book;
use mdbook::errors::Error;
use mdbook::preprocess::{CmdPreprocessor, Preprocessor, PreprocessorContext};
@@ -7,12 +7,12 @@ use semver::{Version, VersionReq};
use std::io;
use std::process;
-pub fn make_app() -> App<'static, 'static> {
+pub fn make_app() -> App<'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))
+ App::new("supports")
+ .arg(Arg::new("renderer").required(true))
.about("Check whether a renderer is supported by this preprocessor"),
)
}
diff --git a/guide/src/README.md b/guide/src/README.md
index 7bbfd995..a3aeb68d 100644
--- a/guide/src/README.md
+++ b/guide/src/README.md
@@ -1,22 +1,30 @@
# 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](https://www.rust-lang.org); its performance
-and simplicity made it ideal for use as a tool to publish directly to hosted websites such
-as [GitHub Pages](https://pages.github.com) via automation. This guide, in fact, serves as both the mdBook documentation
-and a fine example of what mdBook produces.
+**mdBook** is a command line tool to create books with Markdown.
+It is ideal for creating product or API documentation, tutorials, course materials or anything that requires a clean,
+easily navigable and customizable presentation.
-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](https://crates.io/search?q=mdbook&sort=relevance) Rust's [crates.io](https://crates.io) is a
-great way to discover more extensions.
+* Lightweight [Markdown] syntax helps you focus more on your content
+* Integrated [search] support
+* Color [syntax highlighting] for code blocks for many different languages
+* [Theme] files allow customizing the formatting of the output
+* [Preprocessors] can provide extensions for custom syntax and modifying content
+* [Backends] can render the output to multiple formats
+* Written in [Rust] for speed, safety, and simplicity
+* Automated testing of [Rust code samples]
-## API Documentation
+This guide is an example of what mdBook produces.
+mdBook is used by the Rust programming language project, and [The Rust Programming Language][trpl] book is another fine example of mdBook in action.
-In addition to the above features, mdBook also has a Rust [API](https://docs.rs/mdbook/*/mdbook/). This allows you to
-write your own preprocessor or renderer, as well as incorporate mdBook features into other applications.
-The [For Developers](for_developers) section of this guide contains more information and some examples.
+[Markdown]: format/markdown.md
+[search]: guide/reading.md#search
+[syntax highlighting]: format/theme/syntax-highlighting.md
+[theme]: format/theme/index.html
+[preprocessors]: format/configuration/preprocessors.md
+[backends]: format/configuration/renderers.md
+[Rust]: https://www.rust-lang.org/
+[trpl]: https://doc.rust-lang.org/book/
+[Rust code samples]: cli/test.md
## Contributing
diff --git a/guide/src/SUMMARY.md b/guide/src/SUMMARY.md
index 181d7972..974d65fa 100644
--- a/guide/src/SUMMARY.md
+++ b/guide/src/SUMMARY.md
@@ -1,6 +1,15 @@
# Summary
-- [Introduction](README.md)
+[Introduction](README.md)
+
+# User Guide
+
+- [Installation](guide/installation.md)
+- [Reading Books](guide/reading.md)
+- [Creating a Book](guide/creating.md)
+
+# Reference Guide
+
- [Command Line Tool](cli/README.md)
- [init](cli/init.md)
- [build](cli/build.md)
@@ -8,6 +17,7 @@
- [serve](cli/serve.md)
- [test](cli/test.md)
- [clean](cli/clean.md)
+ - [completions](cli/completions.md)
- [Format](format/README.md)
- [SUMMARY.md](format/summary.md)
- [Draft chapter]()
diff --git a/guide/src/cli/README.md b/guide/src/cli/README.md
index 9fc7c2a9..2fbe3781 100644
--- a/guide/src/cli/README.md
+++ b/guide/src/cli/README.md
@@ -1,55 +1,14 @@
# Command Line Tool
-mdBook can be used either as a command line tool or a [Rust
-crate](https://crates.io/crates/mdbook). Let's focus on the command line tool
-capabilities first.
+The `mdbook` command-line tool is used to create and build books.
+After you have [installed](../guide/installation.md) `mdbook`, you can run the `mdbook help` command in your terminal to view the available commands.
-## Install From Binaries
+This following sections provide in-depth information on the different commands available.
-Precompiled binaries are provided for major platforms on a best-effort basis.
-Visit [the releases page](https://github.com/rust-lang/mdBook/releases)
-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](https://www.rust-lang.org/)** and therefore needs
-to be compiled with **Cargo**. If you haven't already installed Rust, please go
-ahead and [install it](https://www.rust-lang.org/tools/install) 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:
-
-```bash
-cargo install mdbook
-```
-
-This will fetch the source code for the latest release from
-[Crates.io](https://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](https://github.com/rust-lang/mdBook)** 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.
-
-```bash
-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.
+* [`mdbook init `](init.md) — Creates a new book with minimal boilerplate to start with.
+* [`mdbook build`](build.md) — Renders the book.
+* [`mdbook watch`](watch.md) — Rebuilds the book any time a source file changes.
+* [`mdbook serve`](serve.md) — Runs a web server to view the book, and rebuilds on changes.
+* [`mdbook test`](test.md) — Tests Rust code samples.
+* [`mdbook clean`](clean.md) — Deletes the rendered output.
+* [`mdbook completions`](completions.md) — Support for shell auto-completion.
diff --git a/guide/src/cli/completions.md b/guide/src/cli/completions.md
new file mode 100644
index 00000000..1246b1ee
--- /dev/null
+++ b/guide/src/cli/completions.md
@@ -0,0 +1,16 @@
+# The completions command
+
+The completions command is used to generate auto-completions for some common shells.
+This means when you type `mdbook` in your shell, you can then press your shell's auto-complete key (usually the Tab key) and it may display what the valid options are, or finish partial input.
+
+The completions first need to be installed for your shell:
+
+```bash
+mdbook completions bash > ~/.local/share/bash-completion/completions/mdbook
+```
+
+The command prints a completion script for the given shell.
+Run `mdbook completions --help` for a list of supported shells.
+
+Where to place the completions depend on which shell you are using and your operating system.
+Consult your shell's documentation for more information one where to place the script.
diff --git a/guide/src/continuous-integration.md b/guide/src/continuous-integration.md
index ce075040..0196200c 100644
--- a/guide/src/continuous-integration.md
+++ b/guide/src/continuous-integration.md
@@ -1,154 +1,121 @@
# Running `mdbook` in Continuous Integration
-While the following examples use Travis CI, their principles should
-straightforwardly transfer to other continuous integration providers as well.
+There are a variety of services such as [GitHub Actions] or [GitLab CI/CD] which can be used to test and deploy your book automatically.
-## Ensuring Your Book Builds and Tests Pass
+The following provides some general guidelines on how to configure your service to run mdBook.
+Specific recipes can be found at the [Automated Deployment] wiki page.
-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.
+[GitHub Actions]: https://docs.github.com/en/actions
+[GitLab CI/CD]: https://docs.gitlab.com/ee/ci/
+[Automated Deployment]: https://github.com/rust-lang/mdBook/wiki/Automated-Deployment
-```yaml
-language: rust
-sudo: false
+## Installing mdBook
-cache:
- - cargo
+There are several different strategies for installing mdBook.
+The particular method depends on your needs and preferences.
-rust:
- - stable
+### Pre-compiled binaries
-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
+Perhaps the easiest method is to use the pre-compiled binaries found on the [GitHub Releases page][releases].
+A simple approach would be to use the popular `curl` CLI tool to download the executable:
-script:
- - mdbook build && mdbook test # In case of custom book path: mdbook build path/to/mybook && mdbook test path/to/mybook
+```sh
+mkdir bin
+curl -sSL https://github.com/rust-lang/mdBook/releases/download/v0.4.17/mdbook-v0.4.17-x86_64-unknown-linux-gnu.tar.gz | tar -xz --directory=bin
+bin/mdbook build
```
-## Deploying Your Book to GitHub Pages
+Some considerations for this approach:
-Following these instructions will result in your book being published to GitHub
-pages after a successful CI run on your repository's `master` branch.
+* This is relatively fast, and does not necessarily require dealing with caching.
+* This does not require installing Rust.
+* Specifying a specific URL means you have to manually update your script to get a new version.
+ This may be a benefit if you want to lock to a specific version.
+ However, some users prefer to automatically get a newer version when they are published.
+* You are reliant on the GitHub CDN being available.
-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.
+[releases]: https://github.com/rust-lang/mdBook/releases
-Whilst still in your repository's settings page, navigate to Options and change the
-Source on GitHub pages to `gh-pages`.
+### Building from source
-Then, append this snippet to your `.travis.yml` and update the path to the
-`book` directory:
+Building from source will require having Rust installed.
+Some services have Rust pre-installed, but if your service does not, you will need to add a step to install it.
-```yaml
-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
+After Rust is installed, `cargo install` can be used to build and install mdBook.
+We recommend using a SemVer version specifier so that you get the latest **non-breaking** version of mdBook.
+For example:
+
+```sh
+cargo install mdbook --no-default-features --features search --vers "^0.4" --locked
```
-That's it!
+This includes several recommended options:
-Note: Travis has a new [dplv2](https://blog.travis-ci.com/2019-08-27-deployment-tooling-dpl-v2-preview-release) configuration that is currently in beta. To use this new format, update your `.travis.yml` file to:
+* `--no-default-features` — Disables features like the HTTP server used by `mdbook serve` that is likely not needed on CI.
+ This will speed up the build time significantly.
+* `--features search` — Disabling default features means you should then manually enable features that you want, such as the built-in [search] capability.
+* `--vers "^0.4"` — This will install the most recent version of the `0.4` series.
+ However, versions after like `0.5.0` won't be installed, as they may break your build.
+ Cargo will automatically upgrade mdBook if you have an older version already installed.
+* `--locked` — This will use the dependencies that were used when mdBook was released.
+ Without `--locked`, it will use the latest version of all dependencies, which may include some fixes since the last release, but may also (rarely) cause build problems.
-```yaml
-language: rust
-os: linux
-dist: xenial
+You will likely want to investigate caching options, as building mdBook can be somewhat slow.
-cache:
- - cargo
+[search]: guide/reading.md#search
-rust:
- - stable
+## Running tests
-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
+You may want to run tests using [`mdbook test`] every time you push a change or create a pull request.
+This can be used to validate Rust code examples in the book.
-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
+This will require having Rust installed.
+Some services have Rust pre-installed, but if your service does not, you will need to add a step to install it.
+
+Other than making sure the appropriate version of Rust is installed, there's not much more than just running `mdbook test` from the book directory.
+
+You may also want to consider running other kinds of tests, like [mdbook-linkcheck] which will check for broken links.
+Or if you have your own style checks, spell checker, or any other tests it might be good to run them in CI.
+
+[`mdbook test`]: cli/test.md
+[mdbook-linkcheck]: https://github.com/Michael-F-Bryan/mdbook-linkcheck#continuous-integration
+
+## Deploying
+
+You may want to automatically deploy your book.
+Some may want to do this with every time a change is pushed, and others may want to only deploy when a specific release is tagged.
+
+You'll also need to understand the specifics on how to push a change to your web service.
+For example, [GitHub Pages] just requires committing the output onto a specific git branch.
+Other services may require using something like SSH to connect to a remote server.
+
+The basic outline is that you need to run `mdbook build` to generate the output, and then transfer the files (which are in the `book` directory) to the correct location.
+
+You may then want to consider if you need to invalidate any caches on your web service.
+
+See the [Automated Deployment] wiki page for examples of various different services.
+
+[GitHub Pages]: https://docs.github.com/en/pages
+
+### 404 handling
+
+mdBook automatically generates a 404 page to be used for broken links.
+The default output is a file named `404.html` at the root of the book.
+Some services like [GitHub Pages] will automatically use this page for broken links.
+For other services, you may want to consider configuring the web server to use this page as it will provide the reader navigation to get back to the book.
+
+If your book is not deployed at the root of the domain, then you should set the [`output.html.site-url`] setting so that the 404 page works correctly.
+It needs to know where the book is deployed in order to load the static files (like CSS) correctly.
+For example, this guide is deployed at , and the `site-url` setting is configured like this:
+
+```toml
+# book.toml
+[output.html]
+site-url = "/mdBook/"
```
-### Deploying to GitHub Pages manually
+You can customize the look of the 404 page by creating a file named `src/404.md` in your book.
+If you want to use a different filename, you can set [`output.html.input-404`] to a different filename.
-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*:
-
-```console
-$> 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:
-
-```makefile
-.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:
-```yml
-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!
+[`output.html.site-url`]: format/configuration/renderers.md#html-renderer-options
+[`output.html.input-404`]: format/configuration/renderers.md#html-renderer-options
diff --git a/guide/src/for_developers/README.md b/guide/src/for_developers/README.md
index 14a56d55..d8b97709 100644
--- a/guide/src/for_developers/README.md
+++ b/guide/src/for_developers/README.md
@@ -24,8 +24,9 @@ The process of rendering a book project goes through several steps.
exist
- Load the book chapters into memory
- Discover which preprocessors/backends should be used
-2. Run the preprocessors
-3. Call each backend in turn
+2. For each backend:
+ 1. Run all the preprocessors.
+ 2. Call the backend to render the processed result.
## Using `mdbook` as a Library
diff --git a/guide/src/for_developers/backends.md b/guide/src/for_developers/backends.md
index fcc44a47..78326a36 100644
--- a/guide/src/for_developers/backends.md
+++ b/guide/src/for_developers/backends.md
@@ -5,23 +5,17 @@ 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.
+See [Configuring Renderers](../format/configuration/renderers.md) for more information about using backends.
-- [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
+The community has developed several backends.
+See the [Third Party Plugins] wiki page for a list of available backends.
+
+## Setting Up
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.
@@ -330,39 +324,6 @@ 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:
-
-```text
-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.
-
-```diff
- [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:
-
-```text
-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
@@ -375,11 +336,7 @@ as a good example of how it's done in real life, so feel free to skim through
the source code or ask questions.
-[mdbook-linkcheck]: https://github.com/Michael-F-Bryan/mdbook-linkcheck
-[mdbook-epub]: https://github.com/Michael-F-Bryan/mdbook-epub
-[mdbook-test]: https://github.com/Michael-F-Bryan/mdbook-test
-[mdbook-man]: https://github.com/vv9k/mdbook-man
-[rust-skeptic]: https://github.com/budziq/rust-skeptic
+[Third Party Plugins]: https://github.com/rust-lang/mdBook/wiki/Third-party-plugins
[`RenderContext`]: https://docs.rs/mdbook/*/mdbook/renderer/struct.RenderContext.html
[`RenderContext::from_json()`]: https://docs.rs/mdbook/*/mdbook/renderer/struct.RenderContext.html#method.from_json
[`semver`]: https://crates.io/crates/semver
diff --git a/guide/src/for_developers/preprocessors.md b/guide/src/for_developers/preprocessors.md
index 074d1c3c..1ac46256 100644
--- a/guide/src/for_developers/preprocessors.md
+++ b/guide/src/for_developers/preprocessors.md
@@ -5,35 +5,18 @@ 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
+See [Configuring Preprocessors](../format/configuration/preprocessors.md) for more information about using preprocessors.
## 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`
+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](../format/mathjax.md) to be used for non-HTML renderers.
-
-```toml
-[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.
@@ -78,7 +61,7 @@ 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`][pc] crate implements a production-quality event-based
-Markdown parser, with the [`pulldown-cmark-to-cmark`][pctc] allowing you to
+Markdown parser, with the [`pulldown-cmark-to-cmark`][pctc] crate allowing you to
translate events back into markdown text.
The following code block shows how to remove all emphasis from markdown,
diff --git a/guide/src/format/configuration/general.md b/guide/src/format/configuration/general.md
index 1c3884fb..b1fe49e4 100644
--- a/guide/src/format/configuration/general.md
+++ b/guide/src/format/configuration/general.md
@@ -62,6 +62,11 @@ language = "en"
Options for the Rust language, relevant to running tests and playground
integration.
+```toml
+[rust]
+edition = "2015" # the default edition for code blocks
+```
+
- **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:
@@ -77,8 +82,16 @@ integration.
This controls the build process of your book.
+```toml
+[build]
+build-dir = "book" # the directory where the output is placed
+create-missing = true # whether or not to create missing pages
+use-default-preprocessors = true # use the default preprocessors
+```
+
- **build-dir:** The directory to put the rendered book in. By default this is
`book/` in the book's root directory.
+ This can overridden with the `--dest-dir` CLI option.
- **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
diff --git a/guide/src/format/configuration/preprocessors.md b/guide/src/format/configuration/preprocessors.md
index 8d3e1dc6..f44bdd4f 100644
--- a/guide/src/format/configuration/preprocessors.md
+++ b/guide/src/format/configuration/preprocessors.md
@@ -1,51 +1,58 @@
# Configuring Preprocessors
-The following preprocessors are available and included by default:
+Preprocessors are extensions that can modify the raw Markdown source before it gets sent to the renderer.
-- `links`: Expand the `{{ #playground }}`, `{{ #include }}`, and `{{ #rustdoc_include }}` handlebars
+The following preprocessors are built-in and included by default:
+
+- `links`: Expands the `{{ #playground }}`, `{{ #include }}`, and `{{ #rustdoc_include }}` handlebars
helpers in a chapter to include the contents of a file.
+ See [Including files] for more.
- `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.
+The built-in preprocessors can be disabled with the [`build.use-default-preprocessors`] config option.
-**book.toml**
-```toml
-[build]
-build-dir = "build"
-create-missing = false
+The community has developed several preprocessors.
+See the [Third Party Plugins] wiki page for a list of available preprocessors.
-[preprocessor.links]
+For information on how to create a new preprocessor, see the [Preprocessors for Developers] chapter.
-[preprocessor.index]
-```
+[Including files]: ../mdbook.md#including-files
+[`build.use-default-preprocessors`]: general.md#build-options
+[Third Party Plugins]: https://github.com/rust-lang/mdBook/wiki/Third-party-plugins
+[Preprocessors for Developers]: ../../for_developers/preprocessors.md
-### Custom Preprocessor Configuration
+## 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
+Preprocessors can be added by including a `preprocessor` table in `book.toml` with the name of the preprocessor.
+For example, if you have a preprocessor called `mdbook-example`, then you can include it with:
```toml
-[preprocessor.links]
-# set the renderers this preprocessor will run for
-renderers = ["html"]
-some_extra_feature = true
+[preprocessor.example]
```
-#### Locking a Preprocessor dependency to a renderer
+With this table, mdBook will execute the `mdbook-example` preprocessor.
+
+This table can include additional key-value pairs that are specific to the preprocessor.
+For example, if our example prepocessor needed some extra configuration options:
+
+```toml
+[preprocessor.example]
+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.
```toml
-[preprocessor.mathjax]
-renderers = ["html"] # mathjax only makes sense with the HTML renderer
+[preprocessor.example]
+renderers = ["html"] # example preprocessor only runs with the HTML renderer
```
-### Provide Your Own Command
+## 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
@@ -57,7 +64,7 @@ be overridden by adding a `command` field.
command = "python random.py"
```
-### Require A Certain Order
+## 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:
diff --git a/guide/src/format/configuration/renderers.md b/guide/src/format/configuration/renderers.md
index df105c8d..f1d5ee15 100644
--- a/guide/src/format/configuration/renderers.md
+++ b/guide/src/format/configuration/renderers.md
@@ -1,9 +1,115 @@
# Configuring Renderers
-### HTML renderer options
+Renderers (also called "backends") are responsible for creating the output of the book.
-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 backends are built-in:
+
+* [`html`](#html-renderer-options) — This renders the book to HTML.
+ This is enabled by default if no other `[output]` tables are defined in `book.toml`.
+* [`markdown`](#markdown-renderer) — This outputs the book as markdown after running the preprocessors.
+ This is useful for debugging preprocessors.
+
+The community has developed several backends.
+See the [Third Party Plugins] wiki page for a list of available backends.
+
+For information on how to create a new backend, see the [Backends for Developers] chapter.
+
+[Third Party Plugins]: https://github.com/rust-lang/mdBook/wiki/Third-party-plugins
+[Backends for Developers]: ../../for_developers/backends.md
+
+## Output tables
+
+Backends can be added by including a `output` table in `book.toml` with the name of the backend.
+For example, if you have a backend called `mdbook-wordcount`, then you can include it with:
+
+```toml
+[output.wordcount]
+```
+
+With this table, mdBook will execute the `mdbook-wordcount` backend.
+
+This table can include additional key-value pairs that are specific to the backend.
+For example, if our example backend needed some extra configuration options:
+
+```toml
+[output.wordcount]
+ignores = ["Example Chapter"]
+```
+
+If you define any `[output]` tables, then the `html` backend is not enabled by default.
+If you want to keep the `html` backend running, then just include it in the `book.toml` file.
+For example:
+
+```toml
+[book]
+title = "My Awesome Book"
+
+[output.wordcount]
+
+[output.html]
+```
+
+If more than one `output` table is included, this changes the behavior for the layout of the output directory.
+If there is only one backend, then it places its output directly in the `book` directory (see [`build.build-dir`] to override this location).
+If there is more than one backend, then each backend is placed in a separate directory underneath `book`.
+For example, the above would have directories `book/html` and `book/wordcount`.
+
+[`build.build-dir`]: general.md#build-options
+
+### Custom backend commands
+
+By default when you add an `[output.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.
+
+```toml
+[output.random]
+command = "python random.py"
+```
+
+### Optional backends
+
+If you enable a backend that isn't installed, the default behavior is to throw an error.
+This behavior can be changed by marking the backend as optional:
+
+```toml
+[output.wordcount]
+optional = true
+```
+
+This demotes the error to a warning.
+
+
+## HTML renderer options
+
+The HTML renderer has a variety of options detailed below.
+They should be specified in the `[output.html]` table of the `book.toml` file.
+
+```toml
+# Example book.toml file with all output options.
+[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
+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"
+```
The following configuration options are available:
@@ -30,34 +136,22 @@ The following configuration options are available:
- **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
+- **no-section-label:** mdBook by defaults adds numeric section labels in the 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`.
+ repository link. Defaults to `fa-github` which looks like .
+ If you are not using GitHub, another option to consider is `fa-code-fork` which looks like .
- **edit-url-template:** Edit url template, when provided shows a
- "Suggest an edit" button for directly jumping to editing the currently
+ "Suggest an edit" button (which looks like ) for directly jumping to editing the currently
viewed page. For e.g. GitHub projects set this to
`https://github.com///edit/master/{path}` or for
Bitbucket projects set it to
`https://bitbucket.org///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`.
@@ -71,29 +165,80 @@ The following configuration options are available:
[custom domain]: https://docs.github.com/en/github/working-with-github-pages/managing-a-custom-domain-for-your-github-pages-site
-Available configuration options for the `[output.html.print]` table:
+### `[output.html.print]`
+
+The `[output.html.print]` table provides options for controlling the printable output.
+By default, mdBook will include an icon on the top right of the book (which looks like ) that will print the book as a single page.
+
+```toml
+[output.html.print]
+enable = true # include support for printable output
+page-break = true # insert page-break after each chapter
+```
- **enable:** Enable print support. When `false`, all print support will not be
rendered. Defaults to `true`.
+- **page-break** Insert page breaks between chapters. Defaults to `true`.
-Available configuration options for the `[output.html.fold]` table:
+### `[output.html.fold]`
+
+The `[output.html.fold]` table provides options for controlling folding of the chapter listing in the navigation sidebar.
+
+```toml
+[output.html.fold]
+enable = false # whether or not to enable section folding
+level = 0 # the depth to start folding
+```
- **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:
+### `[output.html.playground]`
+
+The `[output.html.playground]` table provides options for controlling Rust sample code blocks, and their integration with the [Rust Playground].
+
+[Rust Playground]: https://play.rust-lang.org/
+
+```toml
+[output.html.playground]
+editable = false # allows editing the source code
+copyable = true # include the copy button for copying code snippets
+copy-js = true # includes the JavaScript for the code editor
+line-numbers = false # displays line numbers for editable code
+runnable = true # displays a run button for rust code
+```
- **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`.
+- **runnable** Displays a run button for rust code snippets. Changing this to `false` will disable the run in playground feature globally. Defaults to `true`.
[Ace]: https://ace.c9.io/
-Available configuration options for the `[output.html.search]` table:
+### `[output.html.search]`
+
+The `[output.html.search]` table provides options for controlling the built-in text [search].
+mdBook must be compiled with the `search` feature enabled (on by default).
+
+[search]: ../../guide/reading.md#search
+
+```toml
+[output.html.search]
+enable = true # enables the search feature
+limit-results = 30 # maximum number of search results
+teaser-word-count = 30 # number of words used for a search result teaser
+use-boolean-and = true # multiple search terms must all match
+boost-title = 2 # ranking boost factor for matches in headers
+boost-hierarchy = 1 # ranking boost factor for matches in page names
+boost-paragraph = 1 # ranking boost factor for matches in text
+expand = true # partial words will match longer terms
+heading-split-level = 3 # link results to heading levels
+copy-js = true # include Javascript code for search
+```
- **enable:** Enables the search feature. Defaults to `true`.
- **limit-results:** The maximum number of search results. Defaults to `30`.
@@ -116,61 +261,24 @@ Available configuration options for the `[output.html.search]` table:
- **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**:
+### `[output.html.redirect]`
+
+The `[output.html.redirect]` table provides a way to add redirects.
+This is useful when you move, rename, or remove a page to ensure that links to the old URL will go to the new location.
```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
-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 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`).
+
+This will generate an HTML page which will automatically redirect to the given location.
+Note that the source location does not support `#` anchor redirects.
+
+## Markdown Renderer
The Markdown renderer will run preprocessors and then output the resulting
Markdown. This is mostly useful for debugging preprocessors, especially in
@@ -189,20 +297,3 @@ only whether it is enabled or disabled.
See [the preprocessors documentation](preprocessors.md) 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](preprocessors.md) 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`.
-
-[alternative backends]: ../../for_developers/backends.md
diff --git a/guide/src/format/markdown.md b/guide/src/format/markdown.md
index 74ecaf56..963a1538 100644
--- a/guide/src/format/markdown.md
+++ b/guide/src/format/markdown.md
@@ -1,7 +1,7 @@
# Markdown
-mdBook's [parser](https://github.com/raphlinus/pulldown-cmark) adheres to the [CommonMark](https://commonmark.org/)
-specification. You can take a quick [tutorial](https://commonmark.org/help/tutorial/),
+mdBook's [parser](https://github.com/raphlinus/pulldown-cmark) adheres to the [CommonMark](https://commonmark.org/) specification with some extensions described below.
+You can take a quick [tutorial](https://commonmark.org/help/tutorial/),
or [try out](https://spec.commonmark.org/dingus/) CommonMark in real time. A complete Markdown overview is out of scope for
this documentation, but below is a high level overview of some of the basics. For a more in-depth experience, check out the
[Markdown Guide](https://www.markdownguide.org).
@@ -84,6 +84,20 @@ Read about [mdBook](mdBook.md).
A bare url: .
+----
+
+Relative links that end with `.md` will be converted to the `.html` extension.
+It is recommended to use `.md` links when possible.
+This is useful when viewing the Markdown file outside of mdBook, for example on GitHub or GitLab which render Markdown automatically.
+
+Links to `README.md` will be converted to `index.html`.
+This is done since some services like GitHub render README files automatically, but web servers typically expect the root file to be called `index.html`.
+
+You can link to individual headings with `#` fragments.
+For example, `mdbook.md#text-and-paragraphs` would link to the [Text and Paragraphs](#text-and-paragraphs) section above.
+The ID is created by transforming the heading such as converting to lowercase and replacing spaces with dashes.
+You can click on any heading and look at the URL in your browser to see what the fragment looks like.
+
## Images
Including images is simply a matter of including a link to them, much like in the _Links_ section above. The following markdown
@@ -103,5 +117,106 @@ Which, of course displays the image like so:
![The Rust Logo](images/rust-logo-blk.svg)
+## Extensions
-See the [Markdown Guide Basic Syntax](https://www.markdownguide.org/basic-syntax/) document for more.
+mdBook has several extensions beyond the standard CommonMark specification.
+
+### Strikethrough
+
+Text may be rendered with a horizontal line through the center by wrapping the
+text with two tilde characters on each side:
+
+```text
+An example of ~~strikethrough text~~.
+```
+
+This example will render as:
+
+> An example of ~~strikethrough text~~.
+
+This follows the [GitHub Strikethrough extension][strikethrough].
+
+### Footnotes
+
+A footnote generates a small numbered link in the text which when clicked
+takes the reader to the footnote text at the bottom of the item. The footnote
+label is written similarly to a link reference with a caret at the front. The
+footnote text is written like a link reference definition, with the text
+following the label. Example:
+
+```text
+This is an example of a footnote[^note].
+
+[^note]: This text is the contents of the footnote, which will be rendered
+ towards the bottom.
+```
+
+This example will render as:
+
+> This is an example of a footnote[^note].
+>
+> [^note]: This text is the contents of the footnote, which will be rendered
+> towards the bottom.
+
+The footnotes are automatically numbered based on the order the footnotes are
+written.
+
+### Tables
+
+Tables can be written using pipes and dashes to draw the rows and columns of
+the table. These will be translated to HTML table matching the shape. Example:
+
+```text
+| Header1 | Header2 |
+|---------|---------|
+| abc | def |
+```
+
+This example will render similarly to this:
+
+| Header1 | Header2 |
+|---------|---------|
+| abc | def |
+
+See the specification for the [GitHub Tables extension][tables] for more
+details on the exact syntax supported.
+
+### Task lists
+
+Task lists can be used as a checklist of items that have been completed.
+Example:
+
+```md
+- [x] Complete task
+- [ ] Incomplete task
+```
+
+This will render as:
+
+> - [x] Complete task
+> - [ ] Incomplete task
+
+See the specification for the [task list extension] for more details.
+
+### Smart punctuation
+
+Some ASCII punctuation sequences will be automatically turned into fancy Unicode
+characters:
+
+| ASCII sequence | Unicode |
+|----------------|---------|
+| `--` | – |
+| `---` | — |
+| `...` | … |
+| `"` | “ or ”, depending on context |
+| `'` | ‘ or ’, depending on context |
+
+So, no need to manually enter those Unicode characters!
+
+This feature is disabled by default.
+To enable it, see the [`output.html.curly-quotes`] config option.
+
+[strikethrough]: https://github.github.com/gfm/#strikethrough-extension-
+[tables]: https://github.github.com/gfm/#tables-extension-
+[task list extension]: https://github.github.com/gfm/#task-list-items-extension-
+[`output.html.curly-quotes`]: configuration/renderers.md#html-renderer-options
diff --git a/guide/src/format/mdbook.md b/guide/src/format/mdbook.md
index 6c691473..62e89843 100644
--- a/guide/src/format/mdbook.md
+++ b/guide/src/format/mdbook.md
@@ -4,6 +4,7 @@
There is a feature in mdBook that lets you hide code lines by prepending them
with a `#` [like you would with Rustdoc][rustdoc-hide].
+This currently only works with Rust language code blocks.
[rustdoc-hide]: https://doc.rust-lang.org/stable/rustdoc/documentation-tests.html#hiding-portions-of-the-example
@@ -27,6 +28,67 @@ Will render as
# }
```
+The code block has an eyeball icon () which will toggle the visibility of the hidden lines.
+
+## Rust Playground
+
+Rust language code blocks will automatically get a play button () which will execute the code and display the output just below the code block.
+This works by sending the code to the [Rust Playground].
+
+```rust
+println!("Hello, World!");
+```
+
+If there is no `main` function, then the code is automatically wrapped inside one.
+
+If you wish to disable the play button for a code block, you can include the `noplayground` option on the code block like this:
+
+~~~markdown
+```rust,noplayground
+let mut name = String::new();
+std::io::stdin().read_line(&mut name).expect("failed to read line");
+println!("Hello {}!", name);
+```
+~~~
+
+Or, if you wish to disable the play button for all code blocks in your book, you can write the config to the `book.toml` like this.
+
+```toml
+[output.html.playground]
+runnable = false
+```
+
+## Rust code block attributes
+
+Additional attributes can be included in Rust code blocks with comma, space, or tab-separated terms just after the language term. For example:
+
+~~~markdown
+```rust,ignore
+# This example won't be tested.
+panic!("oops!");
+```
+~~~
+
+These are particularly important when using [`mdbook test`] to test Rust examples.
+These use the same attributes as [rustdoc attributes], with a few additions:
+
+* `editable` — Enables the [editor].
+* `noplayground` — Removes the play button, but will still be tested.
+* `mdbook-runnable` — Forces the play button to be displayed.
+ This is intended to be combined with the `ignore` attribute for examples that should not be tested, but you want to allow the reader to run.
+* `ignore` — Will not be tested and no play button is shown, but it is still highlighted as Rust syntax.
+* `should_panic` — When executed, it should produce a panic.
+* `no_run` — The code is compiled when tested, but it is not run.
+ The play button is also not shown.
+* `compile_fail` — The code should fail to compile.
+* `edition2015`, `edition2018`, `edition2021` — Forces the use of a specific Rust edition.
+ See [`rust.edition`] to set this globally.
+
+[`mdbook test`]: ../cli/test.md
+[rustdoc attributes]: https://doc.rust-lang.org/rustdoc/documentation-tests.html#attributes
+[editor]: theme/editor.md
+[`rust.edition`]: configuration/general.md#rust-options
+
## Including files
With the following syntax, you can include files into your book:
@@ -191,6 +253,17 @@ Here is what a rendered code snippet looks like:
{{#playground example.rs}}
+Any additional values passed after the filename will be included as attributes of the code block.
+For example `\{{#playground example.rs editable}}` will create the code block like the following:
+
+~~~markdown
+```rust,editable
+# Contents of example.rs here.
+```
+~~~
+
+And the `editable` attribute will enable the [editor] as described at [Rust code block attributes](#rust-code-block-attributes).
+
[Rust Playground]: https://play.rust-lang.org/
## Controlling page \
diff --git a/guide/src/format/theme/README.md b/guide/src/format/theme/README.md
index c298272a..4a776e60 100644
--- a/guide/src/format/theme/README.md
+++ b/guide/src/format/theme/README.md
@@ -38,6 +38,10 @@ template and only add / modify what you need. You can copy the default theme
into your source directory automatically by using `mdbook init --theme` and just
remove the files you don't want to override.
+`mdbook init --theme` will not create every file listed above.
+Some files, such as `head.hbs`, do not have built-in equivalents.
+Just create the file if you need it.
+
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.
diff --git a/guide/src/format/theme/editor.md b/guide/src/format/theme/editor.md
index 04f6cc91..9294dd44 100644
--- a/guide/src/format/theme/editor.md
+++ b/guide/src/format/theme/editor.md
@@ -12,12 +12,14 @@ editable = true
To make a specific block available for editing, the attribute `editable` needs
to be added to it:
-
```rust,editable
+~~~markdown
+```rust,editable
fn main() {
let number = 5;
print!("{}", number);
}
-```
+```
+~~~
The above will result in this editable playground:
diff --git a/guide/src/guide/README.md b/guide/src/guide/README.md
new file mode 100644
index 00000000..90deb10e
--- /dev/null
+++ b/guide/src/guide/README.md
@@ -0,0 +1,7 @@
+# User Guide
+
+This user guide provides an introduction to basic concepts of using mdBook.
+
+- [Installation](installation.md)
+- [Reading Books](reading.md)
+- [Creating a Book](creating.md)
diff --git a/guide/src/guide/creating.md b/guide/src/guide/creating.md
new file mode 100644
index 00000000..f68a8c60
--- /dev/null
+++ b/guide/src/guide/creating.md
@@ -0,0 +1,109 @@
+# Creating a Book
+
+Once you have the `mdbook` CLI tool installed, you can use it to create and render a book.
+
+## Initializing a book
+
+The `mdbook init` command will create a new directory containing an empty book for you to get started.
+Give it the name of the directory that you want to create:
+
+```sh
+mdbook init my-first-book
+```
+
+It will ask a few questions before generating the book.
+After answering the questions, you can change the current directory into the new book:
+
+```sh
+cd my-first-book
+```
+
+There are several ways to render a book, but one of the easiest methods is to use the `serve` command, which will build your book and start a local webserver:
+
+```sh
+mdbook serve --open
+```
+
+The `--open` option will open your default web browser to view your new book.
+You can leave the server running even while you edit the content of the book, and `mdbook` will automatically rebuild the output *and* automatically refresh your web browser.
+
+Check out the [CLI Guide](../cli/index.html) for more information about other `mdbook` commands and CLI options.
+
+## Anatomy of a book
+
+A book is built from several files which define the settings and layout of the book.
+
+### `book.toml`
+
+In the root of your book, there is a `book.toml` file which contains settings for describing how to build your book.
+This is written in the [TOML markup language](https://toml.io/).
+The default settings are usually good enough to get you started.
+When you are interested in exploring more features and options that mdBook provides, check out the [Configuration chapter](../format/configuration/index.html) for more details.
+
+A very basic `book.toml` can be as simple as this:
+
+```toml
+[book]
+title = "My First Book"
+```
+
+### `SUMMARY.md`
+
+The next major part of a book is the summary file located at `src/SUMMARY.md`.
+This file contains a list of all the chapters in the book.
+Before a chapter can be viewed, it must be added to this list.
+
+Here's a basic summary file with a few chapters:
+
+```md
+# Summary
+
+[Introduction](README.md)
+
+- [My First Chapter](my-first-chapter.md)
+- [Nested example](nested/README.md)
+ - [Sub-chapter](nested/sub-chapter.md)
+```
+
+Try opening up `src/SUMMARY.md` in your editor and adding a few chapters.
+If any of the chapter files do not exist, `mdbook` will automatically create them for you.
+
+For more details on other formatting options for the summary file, check out the [Summary chapter](../format/summary.md).
+
+### Source files
+
+The content of your book is all contained in the `src` directory.
+Each chapter is a separate Markdown file.
+Typically, each chapter starts with a level 1 heading with the title of the chapter.
+
+```md
+# My First Chapter
+
+Fill out your content here.
+```
+
+The precise layout of the files is up to you.
+The organization of the files will correspond to the HTML files generated, so keep in mind that the file layout is part of the URL of each chapter.
+
+While the `mdbook serve` command is running, you can open any of the chapter files and start editing them.
+Each time you save the file, `mdbook` will rebuild the book and refresh your web browser.
+
+Check out the [Markdown chapter](../format/markdown.md) for more information on formatting the content of your chapters.
+
+All other files in the `src` directory will be included in the output.
+So if you have images or other static files, just include them somewhere in the `src` directory.
+
+## Publishing a book
+
+Once you've written your book, you may want to host it somewhere for others to view.
+The first step is to build the output of the book.
+This can be done with the `mdbook build` command in the same directory where the `book.toml` file is located:
+
+```sh
+mdbook build
+```
+
+This will generate a directory named `book` which contains the HTML content of your book.
+You can then place this directory on any web server to host it.
+
+For more information about publishing and deploying, check out the [Continuous Integration chapter](../continuous-integration.md) for more.
\ No newline at end of file
diff --git a/guide/src/guide/installation.md b/guide/src/guide/installation.md
new file mode 100644
index 00000000..d7946587
--- /dev/null
+++ b/guide/src/guide/installation.md
@@ -0,0 +1,50 @@
+# Installation
+
+There are multiple ways to install the mdBook CLI tool.
+Choose any one of the methods below that best suit your needs.
+If you are installing mdBook for automatic deployment, check out the [continuous integration] chapter for more examples on how to install.
+
+[continuous integration]: ../continuous-integration.md
+
+## Pre-compiled binaries
+
+Executable binaries are available for download on the [GitHub Releases page][releases].
+Download the binary for your platform (Windows, macOS, or Linux) and extract the archive.
+The archive contains an `mdbook` executable which you can run to build your books.
+
+To make it easier to run, put the path to the binary into your `PATH`.
+
+[releases]: https://github.com/rust-lang/mdBook/releases
+
+## Build from source using Rust
+
+To build the `mdbook` executable from source, you will first need to install Rust and Cargo.
+Follow the instructions on the [Rust installation page].
+mdBook currently requires at least Rust version 1.54.
+
+Once you have installed Rust, the following command can be used to build and install mdBook:
+
+```sh
+cargo install mdbook
+```
+
+This will automatically download mdBook from [crates.io], build it, and install it in Cargo's global binary directory (`~/.cargo/bin/` by default).
+
+[Rust installation page]: https://www.rust-lang.org/tools/install
+[crates.io]: https://crates.io/
+
+### Installing the latest master version
+
+The version published to crates.io will ever so slightly be behind the version hosted on GitHub.
+If you need the latest version you can build the git version of mdBook yourself.
+Cargo makes this ***super easy***!
+
+```sh
+cargo install --git https://github.com/rust-lang/mdBook.git mdbook
+```
+
+Again, make sure to add the Cargo bin directory to your `PATH`.
+
+If you are interested in making modifications to mdBook itself, check out the [Contributing Guide] for more information.
+
+[Contributing Guide]: https://github.com/rust-lang/mdBook/blob/master/CONTRIBUTING.md
diff --git a/guide/src/guide/reading.md b/guide/src/guide/reading.md
new file mode 100644
index 00000000..cab3a865
--- /dev/null
+++ b/guide/src/guide/reading.md
@@ -0,0 +1,74 @@
+# Reading Books
+
+This chapter gives an introduction on how to interact with a book produced by mdBook.
+This assumes you are reading an HTML book.
+The options and formatting will be different for other output formats such as PDF.
+
+A book is organized into *chapters*.
+Each chapter is a separate page.
+Chapters can be nested into a hierarchy of sub-chapters.
+Typically, each chapter will be organized into a series of *headings* to subdivide a chapter.
+
+## Navigation
+
+There are several methods for navigating through the chapters of a book.
+
+The **sidebar** on the left provides a list of all chapters.
+Clicking on any of the chapter titles will load that page.
+
+The sidebar may not automatically appear if the window is too narrow, particularly on mobile displays.
+In that situation, the menu icon (three horizontal bars) at the top-left of the page can be pressed to open and close the sidebar.
+
+The **arrow buttons** at the bottom of the page can be used to navigate to the previous or the next chapter.
+
+The **left and right arrow keys** on the keyboard can be used to navigate to the previous or the next chapter.
+
+## Top menu bar
+
+The menu bar at the top of the page provides some icons for interacting with the book.
+The icons displayed will depend on the settings of how the book was generated.
+
+| Icon | Description |
+|------|-------------|
+| | Opens and closes the chapter listing sidebar. |
+| | Opens a picker to choose a different color theme. |
+| | Opens a search bar for searching within the book. |
+| | Instructs the web browser to print the entire book. |
+| | Opens a link to the website that hosts the source code of the book. |
+| | Opens a page to directly edit the source of the page you are currently reading. |
+
+Tapping the menu bar will scroll the page to the top.
+
+## Search
+
+Each book has a built-in search system.
+Pressing the search icon () in the menu bar, or pressing the `S` key on the keyboard will open an input box for entering search terms.
+Typing some terms will show matching chapters and sections in real time.
+
+Clicking any of the results will jump to that section.
+The up and down arrow keys can be used to navigate the results, and enter will open the highlighted section.
+
+After loading a search result, the matching search terms will be highlighted in the text.
+Clicking a highlighted word or pressing the `Esc` key will remove the highlighting.
+
+## Code blocks
+
+mdBook books are often used for programming projects, and thus support highlighting code blocks and samples.
+Code blocks may contain several different icons for interacting with them:
+
+| Icon | Description |
+|------|-------------|
+| | Copies the code block into your local clipboard, to allow pasting into another application. |
+| | For Rust code examples, this will execute the sample code and display the compiler output just below the example (see [playground]). |
+| | For Rust code examples, this will toggle visibility of "hidden" lines. Sometimes, larger examples will hide lines which are not particularly relevant to what is being illustrated (see [hiding code lines]). |
+| | For [editable code examples][editor], this will undo any changes you have made. |
+
+Here's an example:
+
+```rust
+println!("Hello, World!");
+```
+
+[editor]: ../format/theme/editor.md
+[playground]: ../format/mdbook.md#rust-playground
+[hiding code lines]: ../format/mdbook.md#hiding-code-lines
diff --git a/guide/src/misc/introduction.md b/guide/src/misc/introduction.md
deleted file mode 100644
index 36495382..00000000
--- a/guide/src/misc/introduction.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# Introduction
-
-A frontmatter chapter.
diff --git a/src/book/summary.rs b/src/book/summary.rs
index 981e1079..4bb8e969 100644
--- a/src/book/summary.rs
+++ b/src/book/summary.rs
@@ -1,6 +1,6 @@
use crate::errors::*;
use memchr::{self, Memchr};
-use pulldown_cmark::{self, Event, Tag};
+use pulldown_cmark::{self, Event, HeadingLevel, Tag};
use std::fmt::{self, Display, Formatter};
use std::iter::FromIterator;
use std::ops::{Deref, DerefMut};
@@ -161,7 +161,7 @@ impl From for SummaryItem {
/// > match the following regex: "[^<>\n[]]+".
struct SummaryParser<'a> {
src: &'a str,
- stream: pulldown_cmark::OffsetIter<'a>,
+ stream: pulldown_cmark::OffsetIter<'a, 'a>,
offset: usize,
/// We can't actually put an event back into the `OffsetIter` stream, so instead we store it
@@ -263,7 +263,7 @@ impl<'a> SummaryParser<'a> {
loop {
match self.next_event() {
Some(ev @ Event::Start(Tag::List(..)))
- | Some(ev @ Event::Start(Tag::Heading(1))) => {
+ | Some(ev @ Event::Start(Tag::Heading(HeadingLevel::H1, ..))) => {
if is_prefix {
// we've finished prefix chapters and are at the start
// of the numbered section.
@@ -302,10 +302,10 @@ impl<'a> SummaryParser<'a> {
break;
}
- Some(Event::Start(Tag::Heading(1))) => {
+ Some(Event::Start(Tag::Heading(HeadingLevel::H1, ..))) => {
debug!("Found a h1 in the SUMMARY");
- let tags = collect_events!(self.stream, end Tag::Heading(1));
+ let tags = collect_events!(self.stream, end Tag::Heading(HeadingLevel::H1, ..));
Some(stringify_events(tags))
}
@@ -375,7 +375,7 @@ impl<'a> SummaryParser<'a> {
}
// The expectation is that pulldown cmark will terminate a paragraph before a new
// heading, so we can always count on this to return without skipping headings.
- Some(ev @ Event::Start(Tag::Heading(1))) => {
+ Some(ev @ Event::Start(Tag::Heading(HeadingLevel::H1, ..))) => {
// we're starting a new part
self.back(ev);
break;
@@ -527,15 +527,19 @@ impl<'a> SummaryParser<'a> {
fn parse_title(&mut self) -> Option {
loop {
match self.next_event() {
- Some(Event::Start(Tag::Heading(1))) => {
+ Some(Event::Start(Tag::Heading(HeadingLevel::H1, ..))) => {
debug!("Found a h1 in the SUMMARY");
- let tags = collect_events!(self.stream, end Tag::Heading(1));
+ let tags = collect_events!(self.stream, end Tag::Heading(HeadingLevel::H1, ..));
return Some(stringify_events(tags));
}
// Skip a HTML element such as a comment line.
Some(Event::Html(_)) => {}
// Otherwise, no title.
+ Some(ev) => {
+ self.back(ev);
+ return None;
+ }
_ => return None,
}
}
@@ -647,6 +651,18 @@ mod tests {
assert_eq!(got, should_be);
}
+ #[test]
+ fn no_initial_title() {
+ let src = "[Link]()";
+ let mut parser = SummaryParser::new(src);
+
+ assert!(parser.parse_title().is_none());
+ assert!(matches!(
+ parser.next_event(),
+ Some(Event::Start(Tag::Paragraph))
+ ));
+ }
+
#[test]
fn parse_title_with_styling() {
let src = "# My **Awesome** Summary";
diff --git a/src/cmd/build.rs b/src/cmd/build.rs
index e9112f9b..dacf45cf 100644
--- a/src/cmd/build.rs
+++ b/src/cmd/build.rs
@@ -1,23 +1,29 @@
use crate::{get_book_dir, open};
-use clap::{App, ArgMatches, SubCommand};
+use clap::{arg, App, Arg, ArgMatches};
use mdbook::errors::Result;
use mdbook::MDBook;
use std::path::Path;
// Create clap subcommand arguments
-pub fn make_subcommand<'a, 'b>() -> App<'a, 'b> {
- SubCommand::with_name("build")
+pub fn make_subcommand<'help>() -> App<'help> {
+ App::new("build")
.about("Builds a book from its markdown files")
- .arg_from_usage(
- "-d, --dest-dir=[dest-dir] 'Output directory for the book{n}\
- Relative paths are interpreted relative to the book's root directory.{n}\
- If omitted, mdBook uses build.build-dir from book.toml or defaults to `./book`.'",
+ .arg(
+ Arg::new("dest-dir")
+ .short('d')
+ .long("dest-dir")
+ .value_name("dest-dir")
+ .help(
+ "Output directory for the book{n}\
+ Relative paths are interpreted relative to the book's root directory.{n}\
+ If omitted, mdBook uses build.build-dir from book.toml or defaults to `./book`.",
+ ),
)
- .arg_from_usage(
- "[dir] 'Root directory for the book{n}\
- (Defaults to the Current Directory when omitted)'",
- )
- .arg_from_usage("-o, --open 'Opens the compiled book in a web browser'")
+ .arg(arg!([dir]
+ "Root directory for the book{n}\
+ (Defaults to the Current Directory when omitted)"
+ ))
+ .arg(arg!(-o --open "Opens the compiled book in a web browser"))
}
// Build command implementation
diff --git a/src/cmd/clean.rs b/src/cmd/clean.rs
index b58f937e..0569726e 100644
--- a/src/cmd/clean.rs
+++ b/src/cmd/clean.rs
@@ -1,23 +1,28 @@
use crate::get_book_dir;
use anyhow::Context;
-use clap::{App, ArgMatches, SubCommand};
+use clap::{arg, App, Arg, ArgMatches};
use mdbook::MDBook;
use std::fs;
// Create clap subcommand arguments
-pub fn make_subcommand<'a, 'b>() -> App<'a, 'b> {
- SubCommand::with_name("clean")
+pub fn make_subcommand<'help>() -> App<'help> {
+ App::new("clean")
.about("Deletes a built book")
- .arg_from_usage(
- "-d, --dest-dir=[dest-dir] 'Output directory for the book{n}\
- Relative paths are interpreted relative to the book's root directory.{n}\
- Running this command deletes this directory.{n}\
- If omitted, mdBook uses build.build-dir from book.toml or defaults to `./book`.'",
- )
- .arg_from_usage(
- "[dir] 'Root directory for the book{n}\
- (Defaults to the Current Directory when omitted)'",
+ .arg(
+ Arg::new("dest-dir")
+ .short('d')
+ .long("dest-dir")
+ .value_name("dest-dir")
+ .help(
+ "Output directory for the book{n}\
+ Relative paths are interpreted relative to the book's root directory.{n}\
+ If omitted, mdBook uses build.build-dir from book.toml or defaults to `./book`.",
+ ),
)
+ .arg(arg!([dir]
+ "Root directory for the book{n}\
+ (Defaults to the Current Directory when omitted)"
+ ))
}
// Clean command implementation
diff --git a/src/cmd/init.rs b/src/cmd/init.rs
index ed0aa17d..1ee5ff21 100644
--- a/src/cmd/init.rs
+++ b/src/cmd/init.rs
@@ -1,5 +1,5 @@
use crate::get_book_dir;
-use clap::{App, Arg, ArgMatches, SubCommand};
+use clap::{arg, App, Arg, ArgMatches};
use mdbook::config;
use mdbook::errors::Result;
use mdbook::MDBook;
@@ -8,25 +8,25 @@ use std::io::Write;
use std::process::Command;
// Create clap subcommand arguments
-pub fn make_subcommand<'a, 'b>() -> App<'a, 'b> {
- SubCommand::with_name("init")
+pub fn make_subcommand<'help>() -> App<'help> {
+ App::new("init")
.about("Creates the boilerplate structure and files for a new book")
// the {n} denotes a newline which will properly aligned in all help messages
- .arg_from_usage(
- "[dir] 'Directory to create the book in{n}\
- (Defaults to the Current Directory when omitted)'",
- )
- .arg_from_usage("--theme 'Copies the default theme into your source folder'")
- .arg_from_usage("--force 'Skips confirmation prompts'")
+ .arg(arg!([dir]
+ "Directory to create the book in{n}\
+ (Defaults to the Current Directory when omitted)"
+ ))
+ .arg(arg!(--theme "Copies the default theme into your source folder"))
+ .arg(arg!(--force "Skips confirmation prompts"))
.arg(
- Arg::with_name("title")
+ Arg::new("title")
.long("title")
.takes_value(true)
.help("Sets the book title")
.required(false),
)
.arg(
- Arg::with_name("ignore")
+ Arg::new("ignore")
.long("ignore")
.takes_value(true)
.possible_values(&["none", "git"])
diff --git a/src/cmd/serve.rs b/src/cmd/serve.rs
index c5394f8a..bafbfd52 100644
--- a/src/cmd/serve.rs
+++ b/src/cmd/serve.rs
@@ -1,7 +1,7 @@
#[cfg(feature = "watch")]
use super::watch;
use crate::{get_book_dir, open};
-use clap::{App, Arg, ArgMatches, SubCommand};
+use clap::{arg, App, Arg, ArgMatches};
use futures_util::sink::SinkExt;
use futures_util::StreamExt;
use mdbook::errors::*;
@@ -18,37 +18,43 @@ use warp::Filter;
const LIVE_RELOAD_ENDPOINT: &str = "__livereload";
// Create clap subcommand arguments
-pub fn make_subcommand<'a, 'b>() -> App<'a, 'b> {
- SubCommand::with_name("serve")
+pub fn make_subcommand<'help>() -> App<'help> {
+ App::new("serve")
.about("Serves a book at http://localhost:3000, and rebuilds it on changes")
- .arg_from_usage(
- "-d, --dest-dir=[dest-dir] 'Output directory for the book{n}\
- Relative paths are interpreted relative to the book's root directory.{n}\
- If omitted, mdBook uses build.build-dir from book.toml or defaults to `./book`.'",
- )
- .arg_from_usage(
- "[dir] 'Root directory for the book{n}\
- (Defaults to the Current Directory when omitted)'",
- )
.arg(
- Arg::with_name("hostname")
- .short("n")
+ Arg::new("dest-dir")
+ .short('d')
+ .long("dest-dir")
+ .value_name("dest-dir")
+ .help(
+ "Output directory for the book{n}\
+ Relative paths are interpreted relative to the book's root directory.{n}\
+ If omitted, mdBook uses build.build-dir from book.toml or defaults to `./book`.",
+ ),
+ )
+ .arg(arg!([dir]
+ "Root directory for the book{n}\
+ (Defaults to the Current Directory when omitted)"
+ ))
+ .arg(
+ Arg::new("hostname")
+ .short('n')
.long("hostname")
.takes_value(true)
.default_value("localhost")
- .empty_values(false)
+ .forbid_empty_values(true)
.help("Hostname to listen on for HTTP connections"),
)
.arg(
- Arg::with_name("port")
- .short("p")
+ Arg::new("port")
+ .short('p')
.long("port")
.takes_value(true)
.default_value("3000")
- .empty_values(false)
+ .forbid_empty_values(true)
.help("Port to use for HTTP connections"),
)
- .arg_from_usage("-o, --open 'Opens the book server in a web browser'")
+ .arg(arg!(-o --open "Opens the compiled book in a web browser"))
}
// Serve command implementation
@@ -62,11 +68,10 @@ pub fn execute(args: &ArgMatches) -> Result<()> {
let address = format!("{}:{}", hostname, port);
- let livereload_url = format!("ws://{}/{}", address, LIVE_RELOAD_ENDPOINT);
let update_config = |book: &mut MDBook| {
book.config
- .set("output.html.livereload-url", &livereload_url)
- .expect("livereload-url update failed");
+ .set("output.html.live-reload-endpoint", &LIVE_RELOAD_ENDPOINT)
+ .expect("live-reload-endpoint update failed");
if let Some(dest_dir) = args.value_of("dest-dir") {
book.config.build.build_dir = dest_dir.into();
}
diff --git a/src/cmd/test.rs b/src/cmd/test.rs
index f6d97aa6..02f982a4 100644
--- a/src/cmd/test.rs
+++ b/src/cmd/test.rs
@@ -1,29 +1,37 @@
use crate::get_book_dir;
-use clap::{App, Arg, ArgMatches, SubCommand};
+use clap::{arg, App, Arg, ArgMatches};
use mdbook::errors::Result;
use mdbook::MDBook;
// Create clap subcommand arguments
-pub fn make_subcommand<'a, 'b>() -> App<'a, 'b> {
- SubCommand::with_name("test")
+pub fn make_subcommand<'help>() -> App<'help> {
+ App::new("test")
.about("Tests that a book's Rust code samples compile")
- .arg_from_usage(
- "-d, --dest-dir=[dest-dir] 'Output directory for the book{n}\
- Relative paths are interpreted relative to the book's root directory.{n}\
- If omitted, mdBook uses build.build-dir from book.toml or defaults to `./book`.'",
+ .arg(
+ Arg::new("dest-dir")
+ .short('d')
+ .long("dest-dir")
+ .value_name("dest-dir")
+ .help(
+ "Output directory for the book{n}\
+ Relative paths are interpreted relative to the book's root directory.{n}\
+ If omitted, mdBook uses build.build-dir from book.toml or defaults to `./book`.",
+ ),
)
- .arg_from_usage(
- "[dir] 'Root directory for the book{n}\
- (Defaults to the Current Directory when omitted)'",
- )
- .arg(Arg::with_name("library-path")
- .short("L")
+ .arg(arg!([dir]
+ "Root directory for the book{n}\
+ (Defaults to the Current Directory when omitted)"
+ ))
+ .arg(Arg::new("library-path")
+ .short('L')
.long("library-path")
.value_name("dir")
.takes_value(true)
+ .use_delimiter(true)
.require_delimiter(true)
- .multiple(true)
- .empty_values(false)
+ .multiple_values(true)
+ .multiple_occurrences(true)
+ .forbid_empty_values(true)
.help("A comma-separated list of directories to add to {n}the crate search path when building tests"))
}
diff --git a/src/cmd/watch.rs b/src/cmd/watch.rs
index b27516b0..78ae1968 100644
--- a/src/cmd/watch.rs
+++ b/src/cmd/watch.rs
@@ -1,5 +1,5 @@
use crate::{get_book_dir, open};
-use clap::{App, ArgMatches, SubCommand};
+use clap::{arg, App, Arg, ArgMatches};
use mdbook::errors::Result;
use mdbook::utils;
use mdbook::MDBook;
@@ -10,19 +10,25 @@ use std::thread::sleep;
use std::time::Duration;
// Create clap subcommand arguments
-pub fn make_subcommand<'a, 'b>() -> App<'a, 'b> {
- SubCommand::with_name("watch")
+pub fn make_subcommand<'help>() -> App<'help> {
+ App::new("watch")
.about("Watches a book's files and rebuilds it on changes")
- .arg_from_usage(
- "-d, --dest-dir=[dest-dir] 'Output directory for the book{n}\
- Relative paths are interpreted relative to the book's root directory.{n}\
- If omitted, mdBook uses build.build-dir from book.toml or defaults to `./book`.'",
+ .arg(
+ Arg::new("dest-dir")
+ .short('d')
+ .long("dest-dir")
+ .value_name("dest-dir")
+ .help(
+ "Output directory for the book{n}\
+ Relative paths are interpreted relative to the book's root directory.{n}\
+ If omitted, mdBook uses build.build-dir from book.toml or defaults to `./book`.",
+ ),
)
- .arg_from_usage(
- "[dir] 'Root directory for the book{n}\
- (Defaults to the Current Directory when omitted)'",
- )
- .arg_from_usage("-o, --open 'Open the compiled book in a web browser'")
+ .arg(arg!([dir]
+ "Root directory for the book{n}\
+ (Defaults to the Current Directory when omitted)"
+ ))
+ .arg(arg!(-o --open "Opens the compiled book in a web browser"))
}
// Watch command implementation
diff --git a/src/config.rs b/src/config.rs
index bf4aabbb..951957bd 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -533,14 +533,14 @@ pub struct HtmlConfig {
/// directly jumping to editing the currently viewed page.
/// Contains {path} that is replaced with chapter source file path
pub edit_url_template: Option,
- /// This is used as a bit of a workaround for the `mdbook serve` command.
- /// Basically, because you set the websocket port from the command line, the
- /// `mdbook serve` command needs a way to let the HTML renderer know where
- /// to point livereloading at, if it has been enabled.
+ /// Endpoint of websocket, for livereload usage. Value loaded from .toml file
+ /// is ignored, because our code overrides this field with the value [`LIVE_RELOAD_ENDPOINT`]
+ ///
+ /// [`LIVE_RELOAD_ENDPOINT`]: cmd::serve::LIVE_RELOAD_ENDPOINT
///
/// This config item *should not be edited* by the end user.
#[doc(hidden)]
- pub livereload_url: Option,
+ pub live_reload_endpoint: Option,
/// The mapping from old pages to new pages/URLs to use when generating
/// redirects.
pub redirect: HashMap,
@@ -569,7 +569,7 @@ impl Default for HtmlConfig {
input_404: None,
site_url: None,
cname: None,
- livereload_url: None,
+ live_reload_endpoint: None,
redirect: HashMap::new(),
}
}
@@ -588,15 +588,20 @@ impl HtmlConfig {
/// Configuration for how to render the print icon, print.html, and print.css.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
-#[serde(rename_all = "kebab-case")]
+#[serde(default, rename_all = "kebab-case")]
pub struct Print {
/// Whether print support is enabled.
pub enable: bool,
+ /// Insert page breaks between chapters. Default: `true`.
+ pub page_break: bool,
}
impl Default for Print {
fn default() -> Self {
- Self { enable: true }
+ Self {
+ enable: true,
+ page_break: true,
+ }
}
}
@@ -625,6 +630,8 @@ pub struct Playground {
pub copy_js: bool,
/// Display line numbers on playground snippets. Default: `false`.
pub line_numbers: bool,
+ /// Display the run button. Default: `true`
+ pub runnable: bool,
}
impl Default for Playground {
@@ -634,6 +641,7 @@ impl Default for Playground {
copyable: true,
copy_js: true,
line_numbers: false,
+ runnable: true,
}
}
}
@@ -776,6 +784,7 @@ mod tests {
copyable: true,
copy_js: true,
line_numbers: false,
+ runnable: true,
};
let html_should_be = HtmlConfig {
curly_quotes: true,
@@ -806,6 +815,22 @@ mod tests {
assert_eq!(got.html_config().unwrap(), html_should_be);
}
+ #[test]
+ fn disable_runnable() {
+ let src = r#"
+ [book]
+ title = "Some Book"
+ description = "book book book"
+ authors = ["Shogo Takata"]
+
+ [output.html.playground]
+ runnable = false
+ "#;
+
+ let got = Config::from_str(src).unwrap();
+ assert_eq!(got.html_config().unwrap().playground.runnable, false);
+ }
+
#[test]
fn edition_2015() {
let src = r#"
@@ -1150,4 +1175,24 @@ mod tests {
Config::from_str(src).unwrap();
}
+
+ #[test]
+ fn print_config() {
+ let src = r#"
+ [output.html.print]
+ enable = false
+ "#;
+ let got = Config::from_str(src).unwrap();
+ let html_config = got.html_config().unwrap();
+ assert_eq!(html_config.print.enable, false);
+ assert_eq!(html_config.print.page_break, true);
+ let src = r#"
+ [output.html.print]
+ page-break = false
+ "#;
+ let got = Config::from_str(src).unwrap();
+ let html_config = got.html_config().unwrap();
+ assert_eq!(html_config.print.enable, true);
+ assert_eq!(html_config.print.page_break, false);
+ }
}
diff --git a/src/main.rs b/src/main.rs
index 1f286d2d..35562e64 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -5,7 +5,8 @@ extern crate log;
use anyhow::anyhow;
use chrono::Local;
-use clap::{App, AppSettings, Arg, ArgMatches, Shell, SubCommand};
+use clap::{App, AppSettings, Arg, ArgMatches};
+use clap_complete::Shell;
use env_logger::Builder;
use log::LevelFilter;
use mdbook::utils;
@@ -25,25 +26,31 @@ fn main() {
// Check which subcomamnd the user ran...
let res = match app.get_matches().subcommand() {
- ("init", Some(sub_matches)) => cmd::init::execute(sub_matches),
- ("build", Some(sub_matches)) => cmd::build::execute(sub_matches),
- ("clean", Some(sub_matches)) => cmd::clean::execute(sub_matches),
+ Some(("init", sub_matches)) => cmd::init::execute(sub_matches),
+ Some(("build", sub_matches)) => cmd::build::execute(sub_matches),
+ Some(("clean", sub_matches)) => cmd::clean::execute(sub_matches),
#[cfg(feature = "watch")]
- ("watch", Some(sub_matches)) => cmd::watch::execute(sub_matches),
+ Some(("watch", sub_matches)) => cmd::watch::execute(sub_matches),
#[cfg(feature = "serve")]
- ("serve", Some(sub_matches)) => cmd::serve::execute(sub_matches),
- ("test", Some(sub_matches)) => cmd::test::execute(sub_matches),
- ("completions", Some(sub_matches)) => (|| {
+ Some(("serve", sub_matches)) => cmd::serve::execute(sub_matches),
+ Some(("test", sub_matches)) => cmd::test::execute(sub_matches),
+ Some(("completions", sub_matches)) => (|| {
let shell: Shell = sub_matches
.value_of("shell")
.ok_or_else(|| anyhow!("Shell name missing."))?
.parse()
.map_err(|s| anyhow!("Invalid shell: {}", s))?;
- create_clap_app().gen_completions_to("mdbook", shell, &mut std::io::stdout().lock());
+ let mut complete_app = create_clap_app();
+ clap_complete::generate(
+ shell,
+ &mut complete_app,
+ "mdbook",
+ &mut std::io::stdout().lock(),
+ );
Ok(())
})(),
- (_, _) => unreachable!(),
+ _ => unreachable!(),
};
if let Err(e) = res {
@@ -54,14 +61,13 @@ fn main() {
}
/// Create a list of valid arguments and sub-commands
-fn create_clap_app<'a, 'b>() -> App<'a, 'b> {
+fn create_clap_app() -> App<'static> {
let app = App::new(crate_name!())
.about(crate_description!())
.author("Mathieu David ")
.version(VERSION)
- .setting(AppSettings::GlobalVersion)
+ .setting(AppSettings::PropagateVersion)
.setting(AppSettings::ArgRequiredElseHelp)
- .setting(AppSettings::ColoredHelp)
.after_help(
"For more information about a specific command, try `mdbook --help`\n\
The source code for mdBook is available at: https://github.com/rust-lang/mdBook",
@@ -71,12 +77,12 @@ fn create_clap_app<'a, 'b>() -> App<'a, 'b> {
.subcommand(cmd::test::make_subcommand())
.subcommand(cmd::clean::make_subcommand())
.subcommand(
- SubCommand::with_name("completions")
+ App::new("completions")
.about("Generate shell completions for your shell to stdout")
.arg(
- Arg::with_name("shell")
+ Arg::new("shell")
.takes_value(true)
- .possible_values(&Shell::variants())
+ .possible_values(Shell::possible_values())
.help("the shell to generate completions for")
.value_name("SHELL")
.required(true),
@@ -137,3 +143,8 @@ fn open>(path: P) {
error!("Error opening web browser: {}", e);
}
}
+
+#[test]
+fn verify_app() {
+ create_clap_app().debug_assert();
+}
diff --git a/src/renderer/html_handlebars/hbs_renderer.rs b/src/renderer/html_handlebars/hbs_renderer.rs
index e8da5b4a..3d2d1afe 100644
--- a/src/renderer/html_handlebars/hbs_renderer.rs
+++ b/src/renderer/html_handlebars/hbs_renderer.rs
@@ -56,7 +56,7 @@ impl HtmlHandlebars {
let fixed_content =
utils::render_markdown_with_path(&ch.content, ctx.html_config.curly_quotes, Some(path));
- if !ctx.is_index {
+ if !ctx.is_index && ctx.html_config.print.page_break {
// Add page break between chapters
// See https://developer.mozilla.org/en-US/docs/Web/CSS/break-before and https://developer.mozilla.org/en-US/docs/Web/CSS/page-break-before
// Add both two CSS properties because of the compatibility issue
@@ -170,6 +170,13 @@ impl HtmlHandlebars {
// Set a dummy path to ensure other paths (e.g. in the TOC) are generated correctly
data_404.insert("path".to_owned(), json!("404.md"));
data_404.insert("content".to_owned(), json!(html_content_404));
+
+ let mut title = String::from("Page not found");
+ if let Some(book_title) = &ctx.config.book.title {
+ title.push_str(" - ");
+ title.push_str(book_title);
+ }
+ data_404.insert("title".to_owned(), json!(title));
let rendered = handlebars.render("index", &data_404)?;
let rendered =
@@ -606,8 +613,11 @@ fn make_data(
if theme.favicon_svg.is_some() {
data.insert("favicon_svg".to_owned(), json!("favicon.svg"));
}
- if let Some(ref livereload) = html_config.livereload_url {
- data.insert("livereload".to_owned(), json!(livereload));
+ if let Some(ref live_reload_endpoint) = html_config.live_reload_endpoint {
+ data.insert(
+ "live_reload_endpoint".to_owned(),
+ json!(live_reload_endpoint),
+ );
}
let default_theme = match html_config.default_theme {
@@ -768,16 +778,7 @@ fn insert_link_into_header(
content: &str,
id_counter: &mut HashMap,
) -> String {
- let raw_id = utils::id_from_content(content);
-
- let id_count = id_counter.entry(raw_id.clone()).or_insert(0);
-
- let id = match *id_count {
- 0 => raw_id,
- other => format!("{}-{}", raw_id, other),
- };
-
- *id_count += 1;
+ let id = utils::unique_id_from_content(content, id_counter);
format!(
r##"{text}"##,
@@ -828,7 +829,8 @@ fn add_playground_pre(
if classes.contains("language-rust") {
if (!classes.contains("ignore")
&& !classes.contains("noplayground")
- && !classes.contains("noplaypen"))
+ && !classes.contains("noplaypen")
+ && playground_config.runnable)
|| classes.contains("mdbook-runnable")
{
let contains_e2015 = classes.contains("edition2015");
diff --git a/src/renderer/html_handlebars/search.rs b/src/renderer/html_handlebars/search.rs
index 2dc717fb..5dd063da 100644
--- a/src/renderer/html_handlebars/search.rs
+++ b/src/renderer/html_handlebars/search.rs
@@ -97,9 +97,10 @@ fn render_item(
breadcrumbs.push(chapter.name.clone());
+ let mut id_counter = HashMap::new();
while let Some(event) = p.next() {
match event {
- Event::Start(Tag::Heading(i)) if i <= max_section_depth => {
+ Event::Start(Tag::Heading(i, ..)) if i as u32 <= max_section_depth => {
if !heading.is_empty() {
// Section finished, the next heading is following now
// Write the data to the index, and clear it for the next section
@@ -118,9 +119,9 @@ fn render_item(
in_heading = true;
}
- Event::End(Tag::Heading(i)) if i <= max_section_depth => {
+ Event::End(Tag::Heading(i, ..)) if i as u32 <= max_section_depth => {
in_heading = false;
- section_id = Some(utils::id_from_content(&heading));
+ section_id = Some(utils::unique_id_from_content(&heading, &mut id_counter));
breadcrumbs.push(heading.clone());
}
Event::Start(Tag::FootnoteDefinition(name)) => {
diff --git a/src/theme/index.hbs b/src/theme/index.hbs
index 966eedbc..18d984a2 100644
--- a/src/theme/index.hbs
+++ b/src/theme/index.hbs
@@ -219,10 +219,12 @@
- {{#if livereload}}
+ {{#if live_reload_endpoint}}