An mdbook preprocessor that allows you to include filtered lines from other files in your markdown documents based on hashtags (#tag) and persona mentions (@person).
I wrote this filter to use mdbook as an easy project planner: you can take note of tasks and people while keeping track of your own and others’ tasks.
And you can summarize task an people in a dedicated page.
This preprocessor extends mdbook's functionality by enabling selective inclusion of content from source files. Instead of including entire files, you can filter specific lines based on:
- Hashtags: Lines containing specific
#hashtagpatterns - Persona mentions: Lines containing specific
@personpatterns - Combined filters: Both hashtag and persona criteria must match
First, ensure you have Rust and Cargo installed on your system:
# Download and install Rust using rustup
Invoke-WebRequest -Uri "https://win.rustup.rs/" -OutFile "rustup-init.exe"
.\rustup-init.exe
# Follow the on-screen instructions, then restart your terminal# Install Rust (if not already installed)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source $HOME/.cargo/envcargo --version- Clone this repository:
git clone <repository-url>
cd mdbook-include-filter- Build the project:
cargo build --release- Install the binary:
cargo install --path .Add the preprocessor to your book.toml file:
[book]
title = "My Book"
authors = ["Your Name"]
[preprocessor.include-filter]
command = "mdbook-include-filter"Use HTML comments in your markdown files to specify include directives:
<!-- include-filter: file=path/to/file.txt, hashtags=tag1,tag2, mentions=person1,person2 -->The file parameter supports glob patterns to include content from multiple files:
*.md- All .md files in the current directorysrc/*.rs- All .rs files in the src directory**/*.txt- All .txt files recursively in all subdirectoriesnotes*.md- All .md files starting with "notes"
<!-- include-filter: file=src/example.rs, hashtags=todo,fixme -->This will include all lines from src/example.rs that contain #todo or #fixme.
<!-- include-filter: file=notes.md, mentions=john,mary -->This will include all lines from notes.md that contain @john or @mary.
<!-- include-filter: file=comments.txt, hashtags=important, mentions=reviewer -->This will include lines that contain both #important AND @reviewer.
<!-- include-filter: file=data.txt -->This will include all lines from data.txt.
<!-- include-filter: file=*.md, hashtags=todo -->This will include all lines containing #todo from all .md files in the current directory.
<!-- include-filter: file=src/**/*.rs, mentions=reviewer -->This will include all lines containing @reviewer from all .rs files in the src directory and its subdirectories.
<!-- include-filter: file=notes*.txt, hashtags=important, mentions=team -->This will include lines that contain both #important AND @team from all .txt files whose names start with "notes".
The preprocessor supports various glob patterns for flexible file selection:
| Pattern | Description | Example Files Matched |
|---|---|---|
*.md |
All .md files in current directory | notes.md, readme.md |
**/*.txt |
All .txt files in all subdirectories | src/notes.txt, docs/help.txt |
chapter?.md |
Files with single character wildcard | chapter1.md, chapter2.md |
src/**/*.rs |
All .rs files in src and subdirectories | src/main.rs, src/lib/mod.rs |
{notes,docs}/*.md |
Files in specific directories | notes/todo.md, docs/api.md |
Note: When multiple files are matched, each file's content is prefixed with a comment showing the file path, and empty lines separate content from different files.
Your source files can be any text format. The preprocessor will scan each line for:
- Hashtags:
#wordpatterns (alphanumeric characters only) - Mentions:
@wordpatterns (alphanumeric characters only)
This is a general note.
This line has a #todo item that needs attention. @alice
Meeting scheduled with client. #meeting @bob @charlie
Code review completed. #done @reviewer
Another general note without tags.
Documentation update required. #docs @team
The filtered lines are included in code blocks in your markdown:
<!-- Original directive -->
<!-- include-filter: file=notes.txt, hashtags=todo,meeting -->
<!-- Gets replaced with -->
This line has a #todo item that needs attention. @alice
Meeting scheduled with client. #meeting @bob @charlieWhen using glob patterns that match multiple files, the output includes file headers to show the source of each group of lines:
<!-- Original directive -->
<!-- include-filter: file=*.md, hashtags=urgent -->
<!-- Gets replaced with -->
# From: /path/to/notes1.md
Critical bug needs fixing. #urgent @developer
# From: /path/to/notes2.md
Urgent client request. #urgent @managercargo testcargo fmtcargo clippycargo doc --open- Fork the repository
- Create a feature branch
- Make your changes
- Add tests for new functionality
- Ensure all tests pass
- Submit a pull request
This project is licensed under either of
- Apache License, Version 2.0, (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
- Preprocessor not found: Ensure the binary is in your PATH or specify the full path in
book.toml - File not found: Check that file paths in include directives are relative to your book root
- No content included: Verify that your source files contain the specified hashtags or mentions
Enable verbose logging by setting the RUST_LOG environment variable:
RUST_LOG=debug mdbook build