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

Overview

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

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
You might also like...
Download a single file from a Git repository.

git-download Microservices architecture requires sharing service definition files like in protocol buffer, for clients to access the server. To share

Scans a given directory for software of unknown provinence (SOUP) and dumps them in a json-file

Scans a given directory for software of unknown provinence (SOUP) and writes them to a json-file. The json-file contains name, version and a meta property for each SOUP.

The utility is designed to check the availability of peers and automatically update them in the Yggdrasil configuration file, as well as using the admin API - addPeer method.

Yggrasil network peers checker / updater The utility is designed to check the availability of peers and automatically update them in the Yggdrasil con

A minimal and fast zero-copy parser for the PE32+ file format.

peview A minimal and fast zero-copy parser for the PE32+ file format. Goal This project aims to offer a more light weight and easier to use alternativ

A crate for converting an ASCII text string or file to a single unicode character

A crate for converting an ASCII text string or file to a single unicode character. Also provides a macro to embed encoded source code into a Rust source file. Can also do the same to Python code while still letting the code run as before by wrapping it in a decoder.

A parser for the .map file included in the aimware leak
A parser for the .map file included in the aimware leak

a utility I wrote to parse the map file included with the recent aimware self-leak. there is also an IDAPython script to import the symbol information into IDA.

Rust command-line tool to encrypt and decrypt files or directories with age

Bottle A Rust command-line tool that can compress and encrypt (and decrypt and extract) files or directories using age, gzip, and tar. Bottle has no c

Create archives of files within Garry's Mod

gm_zip Create archives of files within Garry's Mod. Note: The scope of this module only works accross the gmod installation files e.g from GarrysMod/g

CLI program written in Rust to anonymize DICOM files

dicom-anonymizer CLI program written in Rust to anonymize DICOM files anonymizer 0.1.0 Domenic Melcher USAGE: anonymizer [OPTIONS] FILE ARGS:

Releases(v0.1.4)
Owner
Hyper
Hyper
Generate rust structs & query functions from diesel schema files

dsync A utility to generate database structs and querying code from diesel schema files. Primarily built for create-rust-app. Currently, it's more adv

Haris 20 Feb 12, 2023
A procedural macro to generate a new function implementation for your struct.

Impl New ?? A procedural macro to generate a new function implementation for your struct. ?? Add to your project Add this to your Cargo.toml: [depende

Mohammed Alotaibi 4 Sep 8, 2023
Proof-of-concept for a memory-efficient data structure for zooming billion-event traces

Proof-of-concept for a gigabyte-scale trace viewer This repo includes: A memory-efficient representation for event traces An unusually simple and memo

Tristan Hume 59 Sep 5, 2022
A compact generational arena data structure for Rust.

Compact Generational Arena This crate provides Arena<T>, a contiguous growable container which assigns and returns IDs to values when they are added t

Chevy Ray Johnston 17 Dec 6, 2022
A Rust crate that implements a range map data structure backed by a Vec.

range_map_vec This crate implements a range map data structure backed by a Vec using binary search. Docs and usage can be found in the corresponding r

Microsoft 9 Sep 8, 2023
Send Youtube videos as audio podcasts to your personal Pocket Casts files section.

yttopocketcasts Send Youtube videos as audio podcasts to your personal Pocket Casts files section. Quick Start Prerequisites: Docker and Make must be

Anthony 3 Dec 18, 2022
A Matrix bot which can generate "This Week in X" like blog posts

hebbot A Matrix bot which can help to generate periodic / recurrent summary blog posts (also known as "This Week in X"). The bot was inspired by twim-

Häcker Felix 43 Dec 17, 2022
Generate voxel block meshes in Rust.

block-mesh Fast algorithms for generating voxel block meshes. Two algorithms are included: visible_block_faces: very fast but suboptimal meshes greedy

Duncan 89 Dec 24, 2022
This crate allows to generate a flat binary with the memory representation of an ELF.

flatelf Library This crate allows to generate a flat binary with the memory representation of an ELF. It also allows to generate a FLATELF with the fo

Roi Martin 3 Sep 29, 2022
Shows how to implement USB device on RP2040 in Rust, in a single file, with no hidden parts.

Rust RP2040 USB Device Example This is a worked example of implementing a USB device on the RP2040 microcontroller, in Rust. It is designed to be easy

Cliff L. Biffle 9 Dec 7, 2022