mirror of
https://github.com/rust-lang/mdBook.git
synced 2025-12-28 17:21:52 -05:00
Compare commits
32 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6425c29893 | ||
|
|
d0bb830491 | ||
|
|
d325c601bb | ||
|
|
e9e889f523 | ||
|
|
05edc4421b | ||
|
|
22ea5fe335 | ||
|
|
714c5fb81e | ||
|
|
56ceb627b8 | ||
|
|
c1b2bec7d7 | ||
|
|
8201b411ab | ||
|
|
836546cf0d | ||
|
|
fcf8f938d2 | ||
|
|
60aaa7ae31 | ||
|
|
aa4cb9465f | ||
|
|
89a2e39b80 | ||
|
|
3c2b8cd10f | ||
|
|
6b0b42ebcc | ||
|
|
7a3513200f | ||
|
|
3db0c0b9a1 | ||
|
|
2c7aac6d7a | ||
|
|
3ee22fb430 | ||
|
|
7e7e779ef7 | ||
|
|
b364e8ea2c | ||
|
|
78325aaccb | ||
|
|
1411ea967a | ||
|
|
d147a85006 | ||
|
|
0f0dce8d6c | ||
|
|
379574dc61 | ||
|
|
6a7de13c6f | ||
|
|
b21446898a | ||
|
|
5b7abf4714 | ||
|
|
d0ef70e574 |
2
.github/workflows/main.yml
vendored
2
.github/workflows/main.yml
vendored
@@ -31,7 +31,7 @@ jobs:
|
||||
rust: stable
|
||||
- build: msrv
|
||||
os: ubuntu-latest
|
||||
rust: 1.39.0
|
||||
rust: 1.42.0
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- name: Install Rust
|
||||
|
||||
20
CHANGELOG.md
20
CHANGELOG.md
@@ -1,5 +1,25 @@
|
||||
# Changelog
|
||||
|
||||
## mdBook 0.4.9
|
||||
[7e01cf9...d325c60](https://github.com/rust-lang/mdBook/compare/7e01cf9...d325c60)
|
||||
|
||||
### Changed
|
||||
- Updated all dependencies and raised the minimum Rust version to 1.42.
|
||||
[#1528](https://github.com/rust-lang/mdBook/pull/1528)
|
||||
- Added more detail to error message when a preprocessor fails.
|
||||
[#1526](https://github.com/rust-lang/mdBook/pull/1526)
|
||||
- Set max-width of HTML video tags to 100% to match img tags.
|
||||
[#1542](https://github.com/rust-lang/mdBook/pull/1542)
|
||||
|
||||
### Fixed
|
||||
- Type errors when parsing `book.toml` are no longer ignored.
|
||||
[#1539](https://github.com/rust-lang/mdBook/pull/1539)
|
||||
- Better handling if `mdbook serve` fails to start the http server.
|
||||
[#1555](https://github.com/rust-lang/mdBook/pull/1555)
|
||||
- Fixed the path for `edit-url-template` if the book used a source directory
|
||||
other than `src`.
|
||||
[#1554](https://github.com/rust-lang/mdBook/pull/1554)
|
||||
|
||||
## mdBook 0.4.8
|
||||
[fcceee4...b592b10](https://github.com/rust-lang/mdBook/compare/fcceee4...b592b10)
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ For more information, such as running it from your favourite editor, please see
|
||||
|
||||
#### Finding Issues with Clippy
|
||||
|
||||
Clippy is a code analyser/linter detecting mistakes, and therfore helps to improve your code.
|
||||
Clippy is a code analyser/linter detecting mistakes, and therefore helps to improve your code.
|
||||
Like formatting your code with `rustfmt`, running clippy regularly and before your Pull Request will
|
||||
help us maintain awesome code.
|
||||
|
||||
|
||||
865
Cargo.lock
generated
865
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "mdbook"
|
||||
version = "0.4.8"
|
||||
version = "0.4.9"
|
||||
authors = [
|
||||
"Mathieu David <mathieudavid@mathieudavid.org>",
|
||||
"Michael-F-Bryan <michaelfbryan@gmail.com>",
|
||||
@@ -49,6 +49,7 @@ ammonia = { version = "3", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
select = "0.5"
|
||||
semver = "0.11.0"
|
||||
pretty_assertions = "0.6"
|
||||
walkdir = "2.0"
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ use clap::{App, Arg, ArgMatches, SubCommand};
|
||||
use mdbook::book::Book;
|
||||
use mdbook::errors::Error;
|
||||
use mdbook::preprocess::{CmdPreprocessor, Preprocessor, PreprocessorContext};
|
||||
use semver::{Version, VersionReq};
|
||||
use std::io;
|
||||
use std::process;
|
||||
|
||||
@@ -33,9 +34,10 @@ fn main() {
|
||||
fn handle_preprocessing(pre: &dyn Preprocessor) -> Result<(), Error> {
|
||||
let (ctx, book) = CmdPreprocessor::parse_input(io::stdin())?;
|
||||
|
||||
if ctx.mdbook_version != mdbook::MDBOOK_VERSION {
|
||||
// We should probably use the `semver` crate to check compatibility
|
||||
// here...
|
||||
let book_version = Version::parse(&ctx.mdbook_version)?;
|
||||
let version_req = VersionReq::parse(mdbook::MDBOOK_VERSION)?;
|
||||
|
||||
if version_req.matches(&book_version) != true {
|
||||
eprintln!(
|
||||
"Warning: The {} plugin was built against version {} of mdbook, \
|
||||
but we're being called from version {}",
|
||||
|
||||
@@ -25,3 +25,6 @@ boost-hierarchy = 2
|
||||
boost-paragraph = 1
|
||||
expand = true
|
||||
heading-split-level = 2
|
||||
|
||||
[output.html.redirect]
|
||||
"/format/config.html" = "configuration/index.html"
|
||||
|
||||
@@ -11,7 +11,11 @@
|
||||
- [Format](format/README.md)
|
||||
- [SUMMARY.md](format/summary.md)
|
||||
- [Draft chapter]()
|
||||
- [Configuration](format/config.md)
|
||||
- [Configuration](format/configuration/README.md)
|
||||
- [General](format/configuration/general.md)
|
||||
- [Preprocessors](format/configuration/preprocessors.md)
|
||||
- [Renderers](format/configuration/renderers.md)
|
||||
- [Environment Variables](format/configuration/environment-variables.md)
|
||||
- [Theme](format/theme/README.md)
|
||||
- [index.hbs](format/theme/index-hbs.md)
|
||||
- [Syntax highlighting](format/theme/syntax-highlighting.md)
|
||||
|
||||
@@ -7,7 +7,8 @@ mdbook build
|
||||
```
|
||||
|
||||
It will try to parse your `SUMMARY.md` file to understand the structure of your
|
||||
book and fetch the corresponding files.
|
||||
book and fetch the corresponding files. Note that files mentioned in `SUMMARY.md`
|
||||
but not present will be created.
|
||||
|
||||
The rendered output will maintain the same directory structure as the source for
|
||||
convenience. Large books will therefore remain structured when rendered.
|
||||
|
||||
@@ -8,7 +8,8 @@ mdbook serve
|
||||
```
|
||||
|
||||
The `serve` command watches the book's `src` directory for
|
||||
changes, rebuilding the book and refreshing clients for each change. A websocket
|
||||
changes, rebuilding the book and refreshing clients for each change; this includes
|
||||
re-creating deleted files still mentioned in `SUMMARY.md`! A websocket
|
||||
connection is used to trigger the client-side refresh.
|
||||
|
||||
***Note:*** *The `serve` command is for testing a book's HTML output, and is not
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
The `watch` command is useful when you want your book to be rendered on every
|
||||
file change. You could repeatedly issue `mdbook build` every time a file is
|
||||
changed. But using `mdbook watch` once will watch your files and will trigger a
|
||||
build automatically whenever you modify a file.
|
||||
build automatically whenever you modify a file; this includes re-creating
|
||||
deleted files still mentioned in `SUMMARY.md`!
|
||||
|
||||
#### Specify a directory
|
||||
|
||||
|
||||
12
guide/src/format/configuration/README.md
Normal file
12
guide/src/format/configuration/README.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# Configuration
|
||||
|
||||
This section details the configuration options available in the ***book.toml***:
|
||||
- **[General]** configuration including the `book`, `rust`, `build` sections
|
||||
- **[Preprocessor]** configuration for default and custom book preprocessors
|
||||
- **[Renderer]** configuration for the HTML, Markdown and custom renderers
|
||||
- **[Environment Variable]** configuration for overriding configuration options in your environment
|
||||
|
||||
[General]: general.md
|
||||
[Preprocessor]: preprocessors.md
|
||||
[Renderer]: renderers.md
|
||||
[Environment Variable]: environment-variables.md
|
||||
38
guide/src/format/configuration/environment-variables.md
Normal file
38
guide/src/format/configuration/environment-variables.md
Normal file
@@ -0,0 +1,38 @@
|
||||
# Environment Variables
|
||||
|
||||
All configuration values can be overridden from the command line by setting the
|
||||
corresponding environment variable. Because many operating systems restrict
|
||||
environment variables to be alphanumeric characters or `_`, the configuration
|
||||
key needs to be formatted slightly differently to the normal `foo.bar.baz` form.
|
||||
|
||||
Variables starting with `MDBOOK_` are used for configuration. The key is created
|
||||
by removing the `MDBOOK_` prefix and turning the resulting string into
|
||||
`kebab-case`. Double underscores (`__`) separate nested keys, while a single
|
||||
underscore (`_`) is replaced with a dash (`-`).
|
||||
|
||||
For example:
|
||||
|
||||
- `MDBOOK_foo` -> `foo`
|
||||
- `MDBOOK_FOO` -> `foo`
|
||||
- `MDBOOK_FOO__BAR` -> `foo.bar`
|
||||
- `MDBOOK_FOO_BAR` -> `foo-bar`
|
||||
- `MDBOOK_FOO_bar__baz` -> `foo-bar.baz`
|
||||
|
||||
So by setting the `MDBOOK_BOOK__TITLE` environment variable you can override the
|
||||
book's title without needing to touch your `book.toml`.
|
||||
|
||||
> **Note:** To facilitate setting more complex config items, the value of an
|
||||
> environment variable is first parsed as JSON, falling back to a string if the
|
||||
> parse fails.
|
||||
>
|
||||
> This means, if you so desired, you could override all book metadata when
|
||||
> building the book with something like
|
||||
>
|
||||
> ```shell
|
||||
> $ export MDBOOK_BOOK="{'title': 'My Awesome Book', authors: ['Michael-F-Bryan']}"
|
||||
> $ mdbook build
|
||||
> ```
|
||||
|
||||
The latter case may be useful in situations where `mdbook` is invoked from a
|
||||
script or CI, where it sometimes isn't possible to update the `book.toml` before
|
||||
building.
|
||||
97
guide/src/format/configuration/general.md
Normal file
97
guide/src/format/configuration/general.md
Normal file
@@ -0,0 +1,97 @@
|
||||
# General Configuration
|
||||
|
||||
You can configure the parameters for your book in the ***book.toml*** file.
|
||||
|
||||
Here is an example of what a ***book.toml*** file might look like:
|
||||
|
||||
```toml
|
||||
[book]
|
||||
title = "Example book"
|
||||
author = "John Doe"
|
||||
description = "The example book covers examples."
|
||||
|
||||
[rust]
|
||||
edition = "2018"
|
||||
|
||||
[build]
|
||||
build-dir = "my-example-book"
|
||||
create-missing = false
|
||||
|
||||
[preprocessor.index]
|
||||
|
||||
[preprocessor.links]
|
||||
|
||||
[output.html]
|
||||
additional-css = ["custom.css"]
|
||||
|
||||
[output.html.search]
|
||||
limit-results = 15
|
||||
```
|
||||
|
||||
## Supported configuration options
|
||||
|
||||
It is important to note that **any** relative path specified in the
|
||||
configuration will always be taken relative from the root of the book where the
|
||||
configuration file is located.
|
||||
|
||||
### General metadata
|
||||
|
||||
This is general information about your book.
|
||||
|
||||
- **title:** The title of the book
|
||||
- **authors:** The author(s) of the book
|
||||
- **description:** A description for the book, which is added as meta
|
||||
information in the html `<head>` of each page
|
||||
- **src:** By default, the source directory is found in the directory named
|
||||
`src` directly under the root folder. But this is configurable with the `src`
|
||||
key in the configuration file.
|
||||
- **language:** The main language of the book, which is used as a language attribute `<html lang="en">` for example.
|
||||
|
||||
**book.toml**
|
||||
```toml
|
||||
[book]
|
||||
title = "Example book"
|
||||
authors = ["John Doe", "Jane Doe"]
|
||||
description = "The example book covers examples."
|
||||
src = "my-src" # the source files will be found in `root/my-src` instead of `root/src`
|
||||
language = "en"
|
||||
```
|
||||
|
||||
### Rust options
|
||||
|
||||
Options for the Rust language, relevant to running tests and playground
|
||||
integration.
|
||||
|
||||
- **edition**: Rust edition to use by default for the code snippets. Default
|
||||
is "2015". Individual code blocks can be controlled with the `edition2015`
|
||||
or `edition2018` annotations, such as:
|
||||
|
||||
~~~text
|
||||
```rust,edition2015
|
||||
// This only works in 2015.
|
||||
let try = true;
|
||||
```
|
||||
~~~
|
||||
|
||||
### Build options
|
||||
|
||||
This controls the build process of your book.
|
||||
|
||||
- **build-dir:** The directory to put the rendered book in. By default this is
|
||||
`book/` in the book's root directory.
|
||||
- **create-missing:** By default, any missing files specified in `SUMMARY.md`
|
||||
will be created when the book is built (i.e. `create-missing = true`). If this
|
||||
is `false` then the build process will instead exit with an error if any files
|
||||
do not exist.
|
||||
- **use-default-preprocessors:** Disable the default preprocessors of (`links` &
|
||||
`index`) by setting this option to `false`.
|
||||
|
||||
If you have the same, and/or other preprocessors declared via their table
|
||||
of configuration, they will run instead.
|
||||
|
||||
- For clarity, with no preprocessor configuration, the default `links` and
|
||||
`index` will run.
|
||||
- Setting `use-default-preprocessors = false` will disable these
|
||||
default preprocessors from running.
|
||||
- Adding `[preprocessor.links]`, for example, will ensure, regardless of
|
||||
`use-default-preprocessors` that `links` it will run.
|
||||
58
guide/src/format/configuration/preprocessors.md
Normal file
58
guide/src/format/configuration/preprocessors.md
Normal file
@@ -0,0 +1,58 @@
|
||||
# Configuring Preprocessors
|
||||
|
||||
The following preprocessors are available and included by default:
|
||||
|
||||
- `links`: Expand the `{{ #playground }}`, `{{ #include }}`, and `{{ #rustdoc_include }}` handlebars
|
||||
helpers in a chapter to include the contents of a file.
|
||||
- `index`: Convert all chapter files named `README.md` into `index.md`. That is
|
||||
to say, all `README.md` would be rendered to an index file `index.html` in the
|
||||
rendered book.
|
||||
|
||||
|
||||
**book.toml**
|
||||
```toml
|
||||
[build]
|
||||
build-dir = "build"
|
||||
create-missing = false
|
||||
|
||||
[preprocessor.links]
|
||||
|
||||
[preprocessor.index]
|
||||
```
|
||||
|
||||
### Custom Preprocessor Configuration
|
||||
|
||||
Like renderers, preprocessor will need to be given its own table (e.g.
|
||||
`[preprocessor.mathjax]`). In the section, you may then pass extra
|
||||
configuration to the preprocessor by adding key-value pairs to the table.
|
||||
|
||||
For example
|
||||
|
||||
```toml
|
||||
[preprocessor.links]
|
||||
# set the renderers this preprocessor will run for
|
||||
renderers = ["html"]
|
||||
some_extra_feature = true
|
||||
```
|
||||
|
||||
#### Locking a Preprocessor dependency to a renderer
|
||||
|
||||
You can explicitly specify that a preprocessor should run for a renderer by
|
||||
binding the two together.
|
||||
|
||||
```toml
|
||||
[preprocessor.mathjax]
|
||||
renderers = ["html"] # mathjax only makes sense with the HTML renderer
|
||||
```
|
||||
|
||||
### Provide Your Own Command
|
||||
|
||||
By default when you add a `[preprocessor.foo]` table to your `book.toml` file,
|
||||
`mdbook` will try to invoke the `mdbook-foo` executable. If you want to use a
|
||||
different program name or pass in command-line arguments, this behaviour can
|
||||
be overridden by adding a `command` field.
|
||||
|
||||
```toml
|
||||
[preprocessor.random]
|
||||
command = "python random.py"
|
||||
```
|
||||
@@ -1,161 +1,4 @@
|
||||
# Configuration
|
||||
|
||||
You can configure the parameters for your book in the ***book.toml*** file.
|
||||
|
||||
Here is an example of what a ***book.toml*** file might look like:
|
||||
|
||||
```toml
|
||||
[book]
|
||||
title = "Example book"
|
||||
author = "John Doe"
|
||||
description = "The example book covers examples."
|
||||
|
||||
[rust]
|
||||
edition = "2018"
|
||||
|
||||
[build]
|
||||
build-dir = "my-example-book"
|
||||
create-missing = false
|
||||
|
||||
[preprocessor.index]
|
||||
|
||||
[preprocessor.links]
|
||||
|
||||
[output.html]
|
||||
additional-css = ["custom.css"]
|
||||
|
||||
[output.html.search]
|
||||
limit-results = 15
|
||||
```
|
||||
|
||||
## Supported configuration options
|
||||
|
||||
It is important to note that **any** relative path specified in the
|
||||
configuration will always be taken relative from the root of the book where the
|
||||
configuration file is located.
|
||||
|
||||
### General metadata
|
||||
|
||||
This is general information about your book.
|
||||
|
||||
- **title:** The title of the book
|
||||
- **authors:** The author(s) of the book
|
||||
- **description:** A description for the book, which is added as meta
|
||||
information in the html `<head>` of each page
|
||||
- **src:** By default, the source directory is found in the directory named
|
||||
`src` directly under the root folder. But this is configurable with the `src`
|
||||
key in the configuration file.
|
||||
- **language:** The main language of the book, which is used as a language attribute `<html lang="en">` for example.
|
||||
|
||||
**book.toml**
|
||||
```toml
|
||||
[book]
|
||||
title = "Example book"
|
||||
authors = ["John Doe", "Jane Doe"]
|
||||
description = "The example book covers examples."
|
||||
src = "my-src" # the source files will be found in `root/my-src` instead of `root/src`
|
||||
language = "en"
|
||||
```
|
||||
|
||||
### Rust options
|
||||
|
||||
Options for the Rust language, relevant to running tests and playground
|
||||
integration.
|
||||
|
||||
- **edition**: Rust edition to use by default for the code snippets. Default
|
||||
is "2015". Individual code blocks can be controlled with the `edition2015`
|
||||
or `edition2018` annotations, such as:
|
||||
|
||||
~~~text
|
||||
```rust,edition2015
|
||||
// This only works in 2015.
|
||||
let try = true;
|
||||
```
|
||||
~~~
|
||||
|
||||
### Build options
|
||||
|
||||
This controls the build process of your book.
|
||||
|
||||
- **build-dir:** The directory to put the rendered book in. By default this is
|
||||
`book/` in the book's root directory.
|
||||
- **create-missing:** By default, any missing files specified in `SUMMARY.md`
|
||||
will be created when the book is built (i.e. `create-missing = true`). If this
|
||||
is `false` then the build process will instead exit with an error if any files
|
||||
do not exist.
|
||||
- **use-default-preprocessors:** Disable the default preprocessors of (`links` &
|
||||
`index`) by setting this option to `false`.
|
||||
|
||||
If you have the same, and/or other preprocessors declared via their table
|
||||
of configuration, they will run instead.
|
||||
|
||||
- For clarity, with no preprocessor configuration, the default `links` and
|
||||
`index` will run.
|
||||
- Setting `use-default-preprocessors = false` will disable these
|
||||
default preprocessors from running.
|
||||
- Adding `[preprocessor.links]`, for example, will ensure, regardless of
|
||||
`use-default-preprocessors` that `links` it will run.
|
||||
|
||||
## Configuring Preprocessors
|
||||
|
||||
The following preprocessors are available and included by default:
|
||||
|
||||
- `links`: Expand the `{{ #playground }}`, `{{ #include }}`, and `{{ #rustdoc_include }}` handlebars
|
||||
helpers in a chapter to include the contents of a file.
|
||||
- `index`: Convert all chapter files named `README.md` into `index.md`. That is
|
||||
to say, all `README.md` would be rendered to an index file `index.html` in the
|
||||
rendered book.
|
||||
|
||||
|
||||
**book.toml**
|
||||
```toml
|
||||
[build]
|
||||
build-dir = "build"
|
||||
create-missing = false
|
||||
|
||||
[preprocessor.links]
|
||||
|
||||
[preprocessor.index]
|
||||
```
|
||||
|
||||
### Custom Preprocessor Configuration
|
||||
|
||||
Like renderers, preprocessor will need to be given its own table (e.g.
|
||||
`[preprocessor.mathjax]`). In the section, you may then pass extra
|
||||
configuration to the preprocessor by adding key-value pairs to the table.
|
||||
|
||||
For example
|
||||
|
||||
```toml
|
||||
[preprocessor.links]
|
||||
# set the renderers this preprocessor will run for
|
||||
renderers = ["html"]
|
||||
some_extra_feature = true
|
||||
```
|
||||
|
||||
#### Locking a Preprocessor dependency to a renderer
|
||||
|
||||
You can explicitly specify that a preprocessor should run for a renderer by
|
||||
binding the two together.
|
||||
|
||||
```toml
|
||||
[preprocessor.mathjax]
|
||||
renderers = ["html"] # mathjax only makes sense with the HTML renderer
|
||||
```
|
||||
|
||||
### Provide Your Own Command
|
||||
|
||||
By default when you add a `[preprocessor.foo]` table to your `book.toml` file,
|
||||
`mdbook` will try to invoke the `mdbook-foo` executable. If you want to use a
|
||||
different program name or pass in command-line arguments, this behaviour can
|
||||
be overridden by adding a `command` field.
|
||||
|
||||
```toml
|
||||
[preprocessor.random]
|
||||
command = "python random.py"
|
||||
```
|
||||
|
||||
## Configuring Renderers
|
||||
# Configuring Renderers
|
||||
|
||||
### HTML renderer options
|
||||
|
||||
@@ -175,7 +18,7 @@ The following configuration options are available:
|
||||
CSS media query. Defaults to `navy`.
|
||||
- **curly-quotes:** Convert straight quotes to curly quotes, except for those
|
||||
that occur in code blocks and code spans. Defaults to `false`.
|
||||
- **mathjax-support:** Adds support for [MathJax](mathjax.md). Defaults to
|
||||
- **mathjax-support:** Adds support for [MathJax](../mathjax.md). Defaults to
|
||||
`false`.
|
||||
- **copy-fonts:** Copies fonts.css and respective font files to the output directory and use them in the default theme. Defaults to `true`.
|
||||
- **google-analytics:** If you use Google Analytics, this option lets you enable
|
||||
@@ -215,7 +58,7 @@ The following configuration options are available:
|
||||
`/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 misssing files.
|
||||
- **input-404:** The name of the markdown file used for missing files.
|
||||
The corresponding output file will be the same, with the extension replaced with `html`.
|
||||
Defaults to `404.md`.
|
||||
- **site-url:** The url where the book will be hosted. This is required to ensure
|
||||
@@ -363,43 +206,4 @@ anything under `[output.foo]`). mdBook checks for two common fields:
|
||||
- **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
|
||||
|
||||
## Environment Variables
|
||||
|
||||
All configuration values can be overridden from the command line by setting the
|
||||
corresponding environment variable. Because many operating systems restrict
|
||||
environment variables to be alphanumeric characters or `_`, the configuration
|
||||
key needs to be formatted slightly differently to the normal `foo.bar.baz` form.
|
||||
|
||||
Variables starting with `MDBOOK_` are used for configuration. The key is created
|
||||
by removing the `MDBOOK_` prefix and turning the resulting string into
|
||||
`kebab-case`. Double underscores (`__`) separate nested keys, while a single
|
||||
underscore (`_`) is replaced with a dash (`-`).
|
||||
|
||||
For example:
|
||||
|
||||
- `MDBOOK_foo` -> `foo`
|
||||
- `MDBOOK_FOO` -> `foo`
|
||||
- `MDBOOK_FOO__BAR` -> `foo.bar`
|
||||
- `MDBOOK_FOO_BAR` -> `foo-bar`
|
||||
- `MDBOOK_FOO_bar__baz` -> `foo-bar.baz`
|
||||
|
||||
So by setting the `MDBOOK_BOOK__TITLE` environment variable you can override the
|
||||
book's title without needing to touch your `book.toml`.
|
||||
|
||||
> **Note:** To facilitate setting more complex config items, the value of an
|
||||
> environment variable is first parsed as JSON, falling back to a string if the
|
||||
> parse fails.
|
||||
>
|
||||
> This means, if you so desired, you could override all book metadata when
|
||||
> building the book with something like
|
||||
>
|
||||
> ```shell
|
||||
> $ export MDBOOK_BOOK="{'title': 'My Awesome Book', authors: ['Michael-F-Bryan']}"
|
||||
> $ mdbook build
|
||||
> ```
|
||||
|
||||
The latter case may be useful in situations where `mdbook` is invoked from a
|
||||
script or CI, where it sometimes isn't possible to update the `book.toml` before
|
||||
building.
|
||||
[alternative backends]: ../../for_developers/backends.md
|
||||
@@ -4,66 +4,96 @@ The summary file is used by mdBook to know what chapters to include, in what
|
||||
order they should appear, what their hierarchy is and where the source files
|
||||
are. Without this file, there is no book.
|
||||
|
||||
Even though `SUMMARY.md` is a markdown file, the formatting is very strict to
|
||||
allow for easy parsing. Let's see how you should format your `SUMMARY.md` file.
|
||||
This markdown file must be named `SUMMARY.md`. Its formatting
|
||||
is very strict and must follow the structure outlined below to allow for easy
|
||||
parsing. Any element not specified below, be it formatting or textual, is likely
|
||||
to be ignored at best, or may cause an error when attempting to build the book.
|
||||
|
||||
#### Structure
|
||||
### Structure
|
||||
|
||||
1. ***Title*** It's common practice to begin with a title, generally <code
|
||||
class="language-markdown"># Summary</code>. But it is not mandatory, the
|
||||
parser just ignores it. So you can too if you feel like it.
|
||||
|
||||
2. ***Prefix Chapter*** Before the main numbered chapters you can add a couple
|
||||
of elements that will not be numbered. This is useful for forewords,
|
||||
introductions, etc. There are however some constraints. You can not nest
|
||||
prefix chapters, they should all be on the root level. And you can not add
|
||||
prefix chapters once you have added numbered chapters.
|
||||
1. ***Title*** - While optional, it's common practice to begin with a title, generally <code
|
||||
class="language-markdown"># Summary</code>. This is ignored by the parser however, and
|
||||
can be ommitted.
|
||||
```markdown
|
||||
[Title of prefix element](relative/path/to/markdown.md)
|
||||
# Summary
|
||||
```
|
||||
|
||||
3. ***Part Title:*** Headers can be used as a title for the following numbered
|
||||
1. ***Prefix Chapter*** - Before the main numbered chapters, prefix chapters can be added
|
||||
that will not be numbered. This is useful for forewords,
|
||||
introductions, etc. There are, however, some constraints. Prefix chapters cannot be
|
||||
nested; they should all be on the root level. And you can not add
|
||||
prefix chapters once you have added numbered chapters.
|
||||
```markdown
|
||||
[A Prefix Chapter](relative/path/to/markdown.md)
|
||||
|
||||
- [First Chapter](relative/path/to/markdown2.md)
|
||||
```
|
||||
|
||||
1. ***Part Title*** - Headers can be used as a title for the following numbered
|
||||
chapters. This can be used to logically separate different sections
|
||||
of book. The title is rendered as unclickable text.
|
||||
of the book. The title is rendered as unclickable text.
|
||||
Titles are optional, and the numbered chapters can be broken into as many
|
||||
parts as desired.
|
||||
```markdown
|
||||
# My Part Tile
|
||||
|
||||
4. ***Numbered Chapter*** Numbered chapters are the main content of the book,
|
||||
they will be numbered and can be nested, resulting in a nice hierarchy
|
||||
(chapters, sub-chapters, etc.)
|
||||
- [First Chapter](relative/path/to/markdown.md)
|
||||
```
|
||||
|
||||
1. ***Numbered Chapter*** - Numbered chapters outline the main content of the book
|
||||
and can be nested, resulting in a nice hierarchy
|
||||
(chapters, sub-chapters, etc.).
|
||||
```markdown
|
||||
# Title of Part
|
||||
|
||||
- [Title of the first Chapter](relative/path/to/markdown.md)
|
||||
- [Title of the second Chapter](relative/path/to/markdown2.md)
|
||||
- [Title of a sub Chapter](relative/path/to/markdown3.md)
|
||||
|
||||
- [First Chapter](relative/path/to/markdown.md)
|
||||
- [Second Chapter](relative/path/to/markdown2.md)
|
||||
- [Sub Chapter](relative/path/to/markdown3.md)
|
||||
|
||||
# Title of Another Part
|
||||
|
||||
- [More Chapters](relative/path/to/markdown4.md)
|
||||
- [Another Chapter](relative/path/to/markdown4.md)
|
||||
```
|
||||
You can either use `-` or `*` to indicate a numbered chapter.
|
||||
Numbered chapters can be denoted with either `-` or `*`.
|
||||
|
||||
5. ***Suffix Chapter*** After the numbered chapters you can add a couple of
|
||||
non-numbered chapters. They are the same as prefix chapters but come after
|
||||
the numbered chapters instead of before.
|
||||
1. ***Suffix Chapter*** - Like prefix chapters, suffix chapters are unnumbered, but they come after
|
||||
numbered chapters.
|
||||
```markdown
|
||||
- [Last Chapter](relative/path/to/markdown.md)
|
||||
|
||||
All other elements are unsupported and will be ignored at best or result in an
|
||||
error.
|
||||
[Title of Suffix Chapter](relative/path/to/markdown2.md)
|
||||
```
|
||||
|
||||
#### Other elements
|
||||
1. ***Draft chapters*** - Draft chapters are chapters without a file and thus content.
|
||||
The purpose of a draft chapter is to signal future chapters still to be written.
|
||||
Or when still laying out the structure of the book to avoid creating the files
|
||||
while you are still changing the structure of the book a lot.
|
||||
Draft chapters will be rendered in the HTML renderer as disabled links in the table
|
||||
of contents, as you can see for the next chapter in the table of contents on the left.
|
||||
Draft chapters are written like normal chapters but without writing the path to the file.
|
||||
```markdown
|
||||
- [Draft Chapter]()
|
||||
```
|
||||
|
||||
- ***Separators*** In between chapters you can add a separator. In the HTML renderer
|
||||
this will result in a line being rendered in the table of contents. A separator is
|
||||
a line containing exclusively dashes and at least three of them: `---`.
|
||||
- ***Draft chapters*** Draft chapters are chapters without a file and thus content.
|
||||
The purpose of a draft chapter is to signal future chapters still to be written.
|
||||
Or when still laying out the structure of the book to avoid creating the files
|
||||
while you are still changing the structure of the book a lot.
|
||||
Draft chapters will be rendered in the HTML renderer as disabled links in the table
|
||||
of contents, as you can see for the next chapter in the table of contents on the left.
|
||||
Draft chapters are written like normal chapters but without writing the path to the file
|
||||
```markdown
|
||||
- [Draft chapter]()
|
||||
```
|
||||
1. ***Separators*** - Separators can be added before, in between, and after any other element. They result
|
||||
in an HTML rendered line in the built table of contents. A separator is
|
||||
a line containing exclusively dashes and at least three of them: `---`.
|
||||
```markdown
|
||||
# My Part Title
|
||||
|
||||
[A Prefix Chapter](relative/path/to/markdown.md)
|
||||
|
||||
---
|
||||
|
||||
- [First Chapter](relative/path/to/markdown2.md)
|
||||
```
|
||||
|
||||
|
||||
### Example
|
||||
|
||||
Below is the markdown source for the `SUMMARY.md` for this guide, with the resulting table
|
||||
of contents as rendered to the left.
|
||||
|
||||
```markdown
|
||||
{{#include ../SUMMARY.md}}
|
||||
```
|
||||
|
||||
@@ -42,5 +42,5 @@ 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.
|
||||
|
||||
[`output.html.preferred-dark-theme`]: ../config.md#html-renderer-options
|
||||
[`output.html.preferred-dark-theme`]: ../configuration/renderers.md#html-renderer-options
|
||||
[newer browsers]: https://caniuse.com/#feat=link-icon-svg
|
||||
|
||||
@@ -33,7 +33,7 @@ Note the new `Undo Changes` button in the editable playgrounds.
|
||||
## Customizing the Editor
|
||||
|
||||
By default, the editor is the [Ace](https://ace.c9.io/) editor, but, if desired,
|
||||
the functionality may be overriden by providing a different folder:
|
||||
the functionality may be overridden by providing a different folder:
|
||||
|
||||
```toml
|
||||
[output.html.playground]
|
||||
@@ -42,5 +42,5 @@ editor = "/path/to/editor"
|
||||
```
|
||||
|
||||
Note that for the editor changes to function correctly, the `book.js` inside of
|
||||
the `theme` folder will need to be overriden as it has some couplings with the
|
||||
the `theme` folder will need to be overridden as it has some couplings with the
|
||||
default Ace editor.
|
||||
|
||||
@@ -74,10 +74,10 @@ fn create_missing(src_dir: &Path, summary: &Summary) -> Result<()> {
|
||||
/// [`iter()`]: #method.iter
|
||||
/// [`for_each_mut()`]: #method.for_each_mut
|
||||
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
|
||||
#[non_exhaustive]
|
||||
pub struct Book {
|
||||
/// The sections in this book.
|
||||
pub sections: Vec<BookItem>,
|
||||
__non_exhaustive: (),
|
||||
}
|
||||
|
||||
impl Book {
|
||||
@@ -200,10 +200,7 @@ impl Chapter {
|
||||
|
||||
/// Check if the chapter is a draft chapter, meaning it has no path to a source markdown file.
|
||||
pub fn is_draft_chapter(&self) -> bool {
|
||||
match self.path {
|
||||
Some(_) => false,
|
||||
None => true,
|
||||
}
|
||||
self.path.is_none()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,10 +225,7 @@ pub(crate) fn load_book_from_disk<P: AsRef<Path>>(summary: &Summary, src_dir: P)
|
||||
chapters.push(chapter);
|
||||
}
|
||||
|
||||
Ok(Book {
|
||||
sections: chapters,
|
||||
__non_exhaustive: (),
|
||||
})
|
||||
Ok(Book { sections: chapters })
|
||||
}
|
||||
|
||||
fn load_summary_item<P: AsRef<Path> + Clone>(
|
||||
|
||||
@@ -173,7 +173,7 @@ struct SummaryParser<'a> {
|
||||
/// `Event::End` is encountered which matches the `$delimiter` pattern.
|
||||
///
|
||||
/// This is the equivalent of doing
|
||||
/// `$stream.take_while(|e| e != $delimeter).collect()` but it allows you to
|
||||
/// `$stream.take_while(|e| e != $delimiter).collect()` but it allows you to
|
||||
/// use pattern matching and you won't get errors because `take_while()`
|
||||
/// moves `$stream` out of self.
|
||||
macro_rules! collect_events {
|
||||
|
||||
@@ -161,5 +161,12 @@ async fn serve(
|
||||
let fallback_route = warp::fs::file(build_dir.join(file_404))
|
||||
.map(|reply| warp::reply::with_status(reply, warp::http::StatusCode::NOT_FOUND));
|
||||
let routes = livereload.or(book_route).or(fallback_route);
|
||||
|
||||
std::panic::set_hook(Box::new(move |panic_info| {
|
||||
// exit if serve panics
|
||||
error!("Unable to serve: {}", panic_info);
|
||||
std::process::exit(1);
|
||||
}));
|
||||
|
||||
warp::serve(routes).run(address).await;
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ pub fn execute(args: &ArgMatches) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn remove_ignored_files(book_root: &PathBuf, paths: &[PathBuf]) -> Vec<PathBuf> {
|
||||
fn remove_ignored_files(book_root: &Path, paths: &[PathBuf]) -> Vec<PathBuf> {
|
||||
if paths.is_empty() {
|
||||
return vec![];
|
||||
}
|
||||
@@ -81,7 +81,7 @@ fn remove_ignored_files(book_root: &PathBuf, paths: &[PathBuf]) -> Vec<PathBuf>
|
||||
}
|
||||
}
|
||||
|
||||
fn find_gitignore(book_root: &PathBuf) -> Option<PathBuf> {
|
||||
fn find_gitignore(book_root: &Path) -> Option<PathBuf> {
|
||||
book_root
|
||||
.ancestors()
|
||||
.map(|p| p.join(".gitignore"))
|
||||
|
||||
@@ -294,6 +294,7 @@ impl Default for Config {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for Config {
|
||||
fn deserialize<D: Deserializer<'de>>(de: D) -> std::result::Result<Self, D::Error> {
|
||||
let raw = Value::deserialize(de)?;
|
||||
@@ -310,10 +311,10 @@ impl<'de> Deserialize<'de> for Config {
|
||||
return Ok(Config::from_legacy(raw));
|
||||
}
|
||||
|
||||
use serde::de::Error;
|
||||
let mut table = match raw {
|
||||
Value::Table(t) => t,
|
||||
_ => {
|
||||
use serde::de::Error;
|
||||
return Err(D::Error::custom(
|
||||
"A config file should always be a toml table",
|
||||
));
|
||||
@@ -322,17 +323,20 @@ impl<'de> Deserialize<'de> for Config {
|
||||
|
||||
let book: BookConfig = table
|
||||
.remove("book")
|
||||
.and_then(|value| value.try_into().ok())
|
||||
.map(|book| book.try_into().map_err(D::Error::custom))
|
||||
.transpose()?
|
||||
.unwrap_or_default();
|
||||
|
||||
let build: BuildConfig = table
|
||||
.remove("build")
|
||||
.and_then(|value| value.try_into().ok())
|
||||
.map(|build| build.try_into().map_err(D::Error::custom))
|
||||
.transpose()?
|
||||
.unwrap_or_default();
|
||||
|
||||
let rust: RustConfig = table
|
||||
.remove("rust")
|
||||
.and_then(|value| value.try_into().ok())
|
||||
.map(|rust| rust.try_into().map_err(D::Error::custom))
|
||||
.transpose()?
|
||||
.unwrap_or_default();
|
||||
|
||||
Ok(Config {
|
||||
@@ -571,7 +575,7 @@ impl Default for HtmlConfig {
|
||||
impl HtmlConfig {
|
||||
/// Returns the directory of theme from the provided root directory. If the
|
||||
/// directory is not present it will append the default directory of "theme"
|
||||
pub fn theme_dir(&self, root: &PathBuf) -> PathBuf {
|
||||
pub fn theme_dir(&self, root: &Path) -> PathBuf {
|
||||
match self.theme {
|
||||
Some(ref d) => root.join(d),
|
||||
None => root.join("theme"),
|
||||
@@ -656,7 +660,7 @@ pub struct Search {
|
||||
pub boost_paragraph: u8,
|
||||
/// True if the searchword `micro` should match `microwave`. Default: `true`.
|
||||
pub expand: bool,
|
||||
/// Documents are split into smaller parts, seperated by headings. This defines, until which
|
||||
/// Documents are split into smaller parts, separated by headings. This defines, until which
|
||||
/// level of heading documents should be split. Default: `3`. (`### This is a level 3 heading`)
|
||||
pub heading_split_level: u8,
|
||||
/// Copy JavaScript files for the search functionality to the output directory?
|
||||
@@ -1070,4 +1074,57 @@ mod tests {
|
||||
assert_eq!(html_config.input_404, Some("missing.md".to_string()));
|
||||
assert_eq!(&get_404_output_file(&html_config.input_404), "missing.html");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "Invalid configuration file")]
|
||||
fn invalid_language_type_error() {
|
||||
let src = r#"
|
||||
[book]
|
||||
title = "mdBook Documentation"
|
||||
language = ["en", "pt-br"]
|
||||
description = "Create book from markdown files. Like Gitbook but implemented in Rust"
|
||||
authors = ["Mathieu David"]
|
||||
src = "./source"
|
||||
"#;
|
||||
|
||||
Config::from_str(src).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "Invalid configuration file")]
|
||||
fn invalid_title_type() {
|
||||
let src = r#"
|
||||
[book]
|
||||
title = 20
|
||||
language = "en"
|
||||
description = "Create book from markdown files. Like Gitbook but implemented in Rust"
|
||||
authors = ["Mathieu David"]
|
||||
src = "./source"
|
||||
"#;
|
||||
|
||||
Config::from_str(src).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "Invalid configuration file")]
|
||||
fn invalid_build_dir_type() {
|
||||
let src = r#"
|
||||
[build]
|
||||
build-dir = 99
|
||||
create-missing = false
|
||||
"#;
|
||||
|
||||
Config::from_str(src).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "Invalid configuration file")]
|
||||
fn invalid_rust_edition() {
|
||||
let src = r#"
|
||||
[rust]
|
||||
edition = "1999"
|
||||
"#;
|
||||
|
||||
Config::from_str(src).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,18 +109,28 @@ impl Preprocessor for CmdPreprocessor {
|
||||
|
||||
self.write_input_to_child(&mut child, &book, ctx);
|
||||
|
||||
let output = child
|
||||
.wait_with_output()
|
||||
.with_context(|| "Error waiting for the preprocessor to complete")?;
|
||||
let output = child.wait_with_output().with_context(|| {
|
||||
format!(
|
||||
"Error waiting for the \"{}\" preprocessor to complete",
|
||||
self.name
|
||||
)
|
||||
})?;
|
||||
|
||||
trace!("{} exited with output: {:?}", self.cmd, output);
|
||||
ensure!(
|
||||
output.status.success(),
|
||||
"The preprocessor exited unsuccessfully"
|
||||
format!(
|
||||
"The \"{}\" preprocessor exited unsuccessfully with {} status",
|
||||
self.name, output.status
|
||||
)
|
||||
);
|
||||
|
||||
serde_json::from_slice(&output.stdout)
|
||||
.with_context(|| "Unable to parse the preprocessed book")
|
||||
serde_json::from_slice(&output.stdout).with_context(|| {
|
||||
format!(
|
||||
"Unable to parse the preprocessed book from \"{}\" processor",
|
||||
self.name
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
fn supports_renderer(&self, renderer: &str) -> bool {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::book::{Book, BookItem};
|
||||
use crate::config::{Config, HtmlConfig, Playground, RustEdition};
|
||||
use crate::config::{BookConfig, Config, HtmlConfig, Playground, RustEdition};
|
||||
use crate::errors::*;
|
||||
use crate::renderer::html_handlebars::helpers;
|
||||
use crate::renderer::{RenderContext, Renderer};
|
||||
@@ -38,12 +38,14 @@ impl HtmlHandlebars {
|
||||
};
|
||||
|
||||
if let Some(ref edit_url_template) = ctx.html_config.edit_url_template {
|
||||
let full_path = "src/".to_owned()
|
||||
let full_path = ctx.book_config.src.to_str().unwrap_or_default().to_owned()
|
||||
+ "/"
|
||||
+ ch.source_path
|
||||
.clone()
|
||||
.unwrap_or_default()
|
||||
.to_str()
|
||||
.unwrap_or_default();
|
||||
|
||||
let edit_url = edit_url_template.replace("{path}", &full_path);
|
||||
ctx.data
|
||||
.insert("git_repository_edit_url".to_owned(), json!(edit_url));
|
||||
@@ -131,7 +133,7 @@ impl HtmlHandlebars {
|
||||
&self,
|
||||
ctx: &RenderContext,
|
||||
html_config: &HtmlConfig,
|
||||
src_dir: &PathBuf,
|
||||
src_dir: &Path,
|
||||
handlebars: &mut Handlebars<'_>,
|
||||
data: &mut serde_json::Map<String, serde_json::Value>,
|
||||
) -> Result<()> {
|
||||
@@ -458,6 +460,7 @@ impl Renderer for HtmlHandlebars {
|
||||
}
|
||||
|
||||
fn render(&self, ctx: &RenderContext) -> Result<()> {
|
||||
let book_config = &ctx.config.book;
|
||||
let html_config = ctx.config.html_config().unwrap_or_default();
|
||||
let src_dir = ctx.root.join(&ctx.config.book.src);
|
||||
let destination = &ctx.destination;
|
||||
@@ -520,6 +523,7 @@ impl Renderer for HtmlHandlebars {
|
||||
destination: destination.to_path_buf(),
|
||||
data: data.clone(),
|
||||
is_index,
|
||||
book_config: book_config.clone(),
|
||||
html_config: html_config.clone(),
|
||||
edition: ctx.config.rust.edition,
|
||||
chapter_titles: &ctx.chapter_titles,
|
||||
@@ -936,6 +940,7 @@ struct RenderItemContext<'a> {
|
||||
destination: PathBuf,
|
||||
data: serde_json::Map<String, serde_json::Value>,
|
||||
is_index: bool,
|
||||
book_config: BookConfig,
|
||||
html_config: HtmlConfig,
|
||||
edition: Option<RustEdition>,
|
||||
chapter_titles: &'a HashMap<PathBuf, String>,
|
||||
|
||||
@@ -141,7 +141,7 @@ fn render_item(
|
||||
body.push_str(&clean_html(&html_block));
|
||||
}
|
||||
Event::Start(_) | Event::End(_) | Event::Rule | Event::SoftBreak | Event::HardBreak => {
|
||||
// Insert spaces where HTML output would usually seperate text
|
||||
// Insert spaces where HTML output would usually separate text
|
||||
// to ensure words don't get merged together
|
||||
if in_heading {
|
||||
heading.push(' ');
|
||||
|
||||
@@ -166,7 +166,7 @@ impl CmdRenderer {
|
||||
} else {
|
||||
// Let this bubble through to later be handled by
|
||||
// handle_render_command_error.
|
||||
abs_exe.to_path_buf()
|
||||
abs_exe
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -92,7 +92,7 @@ h6:target::before {
|
||||
.content ul { line-height: 1.45em; }
|
||||
.content a { text-decoration: none; }
|
||||
.content a:hover { text-decoration: underline; }
|
||||
.content img { max-width: 100%; }
|
||||
.content img, .content video { max-width: 100%; }
|
||||
.content .header:link,
|
||||
.content .header:visited {
|
||||
color: var(--fg);
|
||||
|
||||
@@ -4,7 +4,7 @@ use std::fs::{self, File};
|
||||
use std::io::Write;
|
||||
use std::path::{Component, Path, PathBuf};
|
||||
|
||||
/// Naively replaces any path seperator with a forward-slash '/'
|
||||
/// Naively replaces any path separator with a forward-slash '/'
|
||||
pub fn normalize_path(path: &str) -> String {
|
||||
use std::path::is_separator;
|
||||
path.chars()
|
||||
|
||||
@@ -541,6 +541,57 @@ fn redirects_are_emitted_correctly() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn edit_url_has_default_src_dir_edit_url() {
|
||||
let temp = DummyBook::new().build().unwrap();
|
||||
let book_toml = r#"
|
||||
[book]
|
||||
title = "implicit"
|
||||
|
||||
[output.html]
|
||||
edit-url-template = "https://github.com/rust-lang/mdBook/edit/master/guide/{path}"
|
||||
"#;
|
||||
|
||||
write_file(&temp.path(), "book.toml", book_toml.as_bytes()).unwrap();
|
||||
|
||||
let md = MDBook::load(temp.path()).unwrap();
|
||||
md.build().unwrap();
|
||||
|
||||
let index_html = temp.path().join("book").join("index.html");
|
||||
assert_contains_strings(
|
||||
index_html,
|
||||
&vec![
|
||||
r#"href="https://github.com/rust-lang/mdBook/edit/master/guide/src/README.md" title="Suggest an edit""#,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn edit_url_has_configured_src_dir_edit_url() {
|
||||
let temp = DummyBook::new().build().unwrap();
|
||||
let book_toml = r#"
|
||||
[book]
|
||||
title = "implicit"
|
||||
src = "src2"
|
||||
|
||||
[output.html]
|
||||
edit-url-template = "https://github.com/rust-lang/mdBook/edit/master/guide/{path}"
|
||||
"#;
|
||||
|
||||
write_file(&temp.path(), "book.toml", book_toml.as_bytes()).unwrap();
|
||||
|
||||
let md = MDBook::load(temp.path()).unwrap();
|
||||
md.build().unwrap();
|
||||
|
||||
let index_html = temp.path().join("book").join("index.html");
|
||||
assert_contains_strings(
|
||||
index_html,
|
||||
&vec![
|
||||
r#"href="https://github.com/rust-lang/mdBook/edit/master/guide/src2/README.md" title="Suggest an edit""#,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
fn remove_absolute_components(path: &Path) -> impl Iterator<Item = Component> + '_ {
|
||||
path.components().skip_while(|c| match c {
|
||||
Component::Prefix(_) | Component::RootDir => true,
|
||||
|
||||
Reference in New Issue
Block a user