#mdbook #summary #generator #book #directory-structure

bin+lib mdbook-autosummary

Generate SUMMARY.md files based on your book's file structure

9 releases

0.1.8 Jun 10, 2024
0.1.7 Jun 2, 2024
0.1.6 Feb 1, 2024
0.1.5 Dec 7, 2023
0.1.2 Sep 26, 2023

#269 in Filesystem

Download history 86/week @ 2024-07-27 1/week @ 2024-08-03 4/week @ 2024-08-17 22/week @ 2024-08-24 23/week @ 2024-08-31 19/week @ 2024-09-07 5/week @ 2024-09-14 27/week @ 2024-09-21 32/week @ 2024-09-28 37/week @ 2024-10-05 21/week @ 2024-10-12 14/week @ 2024-10-19 25/week @ 2024-10-26 10/week @ 2024-11-02

75 downloads per month

MPL-2.0 license

29KB
411 lines

mdbook-autosummary

Generate a SUMMARY.md for your mdBook based on your folder structure!

[!WARNING] The implementation is hacky and has several limitations, see below for more info.

Example

src
├── bar
│   ├── chapter_5.md
│   ├── chapter_6.md
│   └── index.md
├── chapter_1.md
├── chapter_2.md
├── foo
│   ├── baz
│   │   ├── chapter_7.md
│   │   └── index.md
│   ├── chapter_3.md
│   ├── chapter_4.md
│   └── index.md
├── index.md
└── SUMMARY.md

is turned into

<!-- Generated by mdbook-autosummary v0.1.0 - do not edit manually! -->

[Home](index.md)
[Chapter 1](chapter_1.md)
[Chapter 2](chapter_2.md)
- [Section Bar](bar/index.md)
  - [Chapter 5](bar/chapter_5.md)
  - [Chapter 6](bar/chapter_6.md)
- [Section Foo](foo/index.md)
  - [Chapter 3](foo/chapter_3.md)
  - [Chapter 4](foo/chapter_4.md)
  - [Section Baz](foo/baz/index.md)
    - [Chapter 7](foo/baz/chapter_7.md)

Installation

Binaries

The binaries are available in the GitHub releases section for all major platforms.

From source

To install from source, you need a working installation of the Rust toolchain

After installing the toolchain, run:

cargo install mdbook-autosummary

Usage

To use the preprocessor, add the following to your book.toml file:

[preprocessor.autosummary]

# This is so that mdBook doesn't start regenerating 
# deleted folders before autosummary can remove them from SUMMARY.md
[build]
create-missing = false

It is additionally recommended to add SUMMARY.md to .gitignore.

Requirements

  • All folders that you want to be included in the SUMMARY.md must have an index.md (or equivalent) file in them. This is the file that will be linked to in the SUMMARY.md.
    • Folders that do not have index.md (or equivalent) in them will be ignored.
  • All files should begin with an h1 (# ) heading that will be used as the title of the page in the SUMMARY.md.
    • The file/folder's name will be used as fallback if no h1 heading is found.

Usage with other preprocessors

[!WARNING] This must be the first preprocessor to run, otherwise the outputs of other preprocessors may be ignored!

To ensure this, add the following to the other preprocessors in your book.toml file:

[preprocessor.foo]
after = ["autosummary"]

Configuration

All configuration options are optional and go under the preprocessor.autosummary table in book.toml.

[preprocessor.autosummary]
# Controls the name of the index.md file that is looked for in each folder.
index-name = "index.md"
# If true, files that start with . or _ are ignored.
ignore-hidden = true

Limitations

If a SUMMARY.md doesn't exist when mdbook build is run or is invalid, mdBook by default fails the build before calling any preprocessors.

This has the following implications:

  • When deleting files or folders that were in SUMMARY.md before, SUMMARY.md has to be emptied/truncated manually to force regeneration.
  • A SUMMARY.md must exist, even if it is empty, before running mdbook build.

Therefore it is recommended to not commit SUMMARY.md to source control and adding it to .gitignore. In addition, in CI/CD, an empty SUMMARY.md must be created before running mdbook build, even with this preprocessor active.

How does it work?

The way it works internally is a bit hacky due to the fact that preprocessors are not supposed to modify SUMMARY.md directly.

When the preprocessor is invoked, it generates a new SUMMARY.md in memory & compares it to the existing one. If they do not match, the generated one overwrites to existing one, and the book is reloaded from disk entirely. If they do match, the preprocessor does nothing. To my knowledge this is the only way to force mdBook to reparse the SUMMARY.md file, short of parsing & building a Book object yourself from scratch.

The side-effects of this approach are that mdBook is forced to reload the entire book when SUMMARY.md changes, and possibly invoke some preprocessors multiple times as well. (If they are defined before mdbook-autosummary) Also since this is a preprocessor, it is invoked for every backend that is built, although filehash comparisons are used to avoid unnecessary work.

Why not just tell mdBook to use the new Summary you generate?

The function to do that exists in mdBook but is unfortunately private. Given the hacky nature of this preprocessor, I don't think it's worth the effort to make a PR to mdBook to make it public, instead, alternative approaches to this problem should be explored. (For example adding the ability to specify the source of a summary to be an extension/preprocessor rather than a file)

Contributing

Contributions are welcome! Please open an issue or a PR if you have any suggestions or improvements.

Creating new releases

  1. Update the version in Cargo.toml
  2. Update CHANGELOG.md
  3. Push a new tag with the version number, prefixed with v (e.g. v0.1.0)
  4. CD will automatically build & publish the new version to crates.io & github

Dependencies

~12–23MB
~342K SLoC