chore(docs): add mdbook mermaid build processor for diagrams support#6933
Conversation
WalkthroughThis PR adds Mermaid diagram support to the mdBook documentation with theme synchronization. The Estimated code review effort🎯 2 (Simple) | ⏱️ ~8 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Tip 💬 Introducing Slack Agent: The best way for teams to turn conversations into code.Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.
Built for teams:
One agent for your entire SDLC. Right inside Slack. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
| model | device_test | click_test | persistence_test |
|---|---|---|---|
| T2T1 | test(all) main(all) ![]() |
test(all) main(all) ![]() |
test(all) main(all) ![]() |
| T3B1 | test(all) main(all) ![]() |
test(all) main(all) ![]() |
test(all) main(all) ![]() |
| T3T1 | test(all) main(all) ![]() |
test(all) main(all) ![]() |
test(all) main(all) ![]() |
| T3W1 | test(all) main(all) ![]() |
test(all) main(all) ![]() |
test(all) main(all) ![]() |
Latest CI run: 25909876897
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/book.toml`:
- Around line 10-13: The book.toml currently enables the mdbook-mermaid
preprocessor (preprocessor.mermaid / "mdbook-mermaid") but there is no developer
guidance or CI to build docs; either remove that preprocessor block if docs are
built externally, or add local + CI support: update documentation
(CONTRIBUTING.md) with exact install steps to add mdbook and mdbook-mermaid and
how to build the book locally, add mdbook and mdbook-mermaid to project dev
dependencies or a tooling script, and add a GitHub Actions workflow job that
runs mdbook build (so mermaid diagrams in docs/common/thp/specification.md
render in CI). Ensure the chosen option updates book.toml and contributing docs
consistently.
In `@docs/mermaid-init.js`:
- Around line 28-34: The loop attaching click handlers to elements in
lightThemes should guard against missing DOM nodes: before calling
addEventListener on document.getElementById(lightTheme) check the result for
null; if the element exists, attach the listener that checks lastThemeWasLight
and triggers window.location.reload() if needed. Update the loop that iterates
over lightThemes and uses document.getElementById(lightTheme) to perform a
null/undefined check (or early continue) so addEventListener is only called on a
real element.
- Around line 1-16: The IIFE assumes DOM readiness and the global mermaid
object; update it to first ensure the document is ready (check
document.readyState or listen for DOMContentLoaded) and that
document.getElementsByTagName('html')[0] exists before using classList, then
compute theme using darkThemes/lightThemes and lastThemeWasLight as before but
only call mermaid.initialize(...) if window.mermaid (or global mermaid) is
defined; if mermaid is missing, either defer initialization until mermaid is
available or bail out with a safe no-op to avoid ReferenceError.
- Around line 20-26: The loops that call document.getElementById(darkTheme) and
document.getElementById(lightTheme) can return null and currently call
addEventListener directly; update both loops to guard against null by first
retrieving the element into a local (e.g., const el =
document.getElementById(darkTheme)) and only calling el.addEventListener(...) if
el is truthy, preserving the existing callback logic that references
lastThemeWasLight; do the same for the lightThemes loop to prevent runtime
errors when elements are absent.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: a528583e-22ca-4ab9-919a-5a94d2a87a00
⛔ Files ignored due to path filters (1)
docs/mermaid.min.jsis excluded by!**/*.min.js
📒 Files selected for processing (2)
docs/book.tomldocs/mermaid-init.js
| [preprocessor] | ||
|
|
||
| [preprocessor.mermaid] | ||
| command = "mdbook-mermaid" |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Description: Verify mdbook-mermaid is available and check version
# Check if mdbook-mermaid is available
if command -v mdbook-mermaid &> /dev/null; then
echo "mdbook-mermaid is available"
mdbook-mermaid --version || echo "Version command not supported"
else
echo "mdbook-mermaid is NOT available"
exit 1
fi
# Check if it's documented in setup/installation files
fd -t f 'README|INSTALL|SETUP|requirements' -x rg -l 'mdbook-mermaid'Repository: trezor/trezor-firmware
Length of output: 98
🏁 Script executed:
# Search for documentation about mdbook-mermaid installation
fd -t f 'README|INSTALL|SETUP|requirements|Makefile' | head -20Repository: trezor/trezor-firmware
Length of output: 611
🏁 Script executed:
# Check if there's a Cargo.toml or similar dependency manifest
fd -t f 'Cargo.toml|package.json|requirements.txt|setup.py|.github/workflows' | head -20Repository: trezor/trezor-firmware
Length of output: 366
🏁 Script executed:
# Look for CI/CD configuration that builds documentation
find .github/workflows -type f 2>/dev/null | head -10Repository: trezor/trezor-firmware
Length of output: 407
🏁 Script executed:
# Check for any mentions of mdbook-mermaid in the repository
rg 'mdbook-mermaid' -t toml -t md -t sh -t yml -t yamlRepository: trezor/trezor-firmware
Length of output: 94
🏁 Script executed:
# Check the docs directory structure
fd -t f . docs/ | head -30Repository: trezor/trezor-firmware
Length of output: 1047
🏁 Script executed:
# Search for mdbook-mermaid in all file types (correcting yaml syntax)
rg 'mdbook-mermaid'Repository: trezor/trezor-firmware
Length of output: 108
🏁 Script executed:
# Check the root Makefile for documentation targets
cat -n Makefile | head -50Repository: trezor/trezor-firmware
Length of output: 2114
🏁 Script executed:
# Look at the root README to see build/setup instructions
head -100 README.mdRepository: trezor/trezor-firmware
Length of output: 2040
🏁 Script executed:
# Search for documentation build targets in Makefile
rg 'docs|book' MakefileRepository: trezor/trezor-firmware
Length of output: 355
🏁 Script executed:
# Check for CI workflows that might build documentation
rg 'mdbook|docs' .github/workflows/*.yaml 2>/dev/null | head -50Repository: trezor/trezor-firmware
Length of output: 48
🏁 Script executed:
# Look at the book.toml file completely
cat -n docs/book.tomlRepository: trezor/trezor-firmware
Length of output: 484
🏁 Script executed:
# Check docs directory for setup/build instructions
rg 'mdbook|build|setup|install' docs/ -t md | head -40Repository: trezor/trezor-firmware
Length of output: 4436
🏁 Script executed:
# Search for any documentation about the docs site or how it's built
rg 'docs.trezor.io|mdbook|documentation' . --type md --type txt | grep -v '.github' | head -30Repository: trezor/trezor-firmware
Length of output: 3859
🏁 Script executed:
# Check if there's a separate docs repo or build process mentioned
git remote -v 2>/dev/null || echo "No git remotes or git not available"Repository: trezor/trezor-firmware
Length of output: 199
🏁 Script executed:
# Look for any setup.py, requirements.txt, or similar that might specify mdbook
find . -name 'requirements*.txt' -o -name 'setup.py' -o -name 'pyproject.toml' | head -10 | xargs grep -l 'mdbook' 2>/dev/null || echo "No mdbook in dependency files"Repository: trezor/trezor-firmware
Length of output: 96
🏁 Script executed:
# Check if there's documentation on contributing that mentions building docs
cat -n docs/misc/contributing.md 2>/dev/null | head -80Repository: trezor/trezor-firmware
Length of output: 3020
🏁 Script executed:
# Search all GitHub workflow files for documentation building
find .github/workflows -name "*.yaml" -o -name "*.yml" | xargs cat 2>/dev/null | grep -i -A 5 -B 5 'docs\|book\|mdbook' | head -100Repository: trezor/trezor-firmware
Length of output: 1376
🏁 Script executed:
# Check if there's a separate docs publication workflow or if docs are published from elsewhere
cat .github/workflows/*.yaml 2>/dev/null | grep -i 'publish\|deploy\|pages' | head -20Repository: trezor/trezor-firmware
Length of output: 48
🏁 Script executed:
# Look at the full docs directory structure to understand if this is the primary source
find docs -type f -name '*.md' | wc -lRepository: trezor/trezor-firmware
Length of output: 69
🏁 Script executed:
# Check git history or comments in book.toml to understand intent
head -20 docs/book.toml && echo "---" && tail -5 docs/book.tomlRepository: trezor/trezor-firmware
Length of output: 441
🏁 Script executed:
# Search for any additional preprocessor or output configuration that might indicate active use
rg 'mermaid|preprocessor|output' docs/book.toml -A 2 -B 2Repository: trezor/trezor-firmware
Length of output: 235
🏁 Script executed:
# Check if the mermaid JS files referenced in book.toml actually exist
ls -la docs/mermaid.min.js docs/mermaid-init.js 2>&1Repository: trezor/trezor-firmware
Length of output: 211
🏁 Script executed:
# Search for any mermaid diagrams in the documentation
rg '```mermaid' docs/ --type mdRepository: trezor/trezor-firmware
Length of output: 764
🏁 Script executed:
# Check if there's a notes or comments about the mdbook setup
rg -i 'note|todo|fixme|wip' docs/book.toml docs/SUMMARY.md 2>/dev/nullRepository: trezor/trezor-firmware
Length of output: 191
🏁 Script executed:
# Look for any GitHub discussion or comments about docs building
find .github -name "*.md" -o -name "*.txt" | xargs cat 2>/dev/null | grep -i 'doc\|book' | head -20Repository: trezor/trezor-firmware
Length of output: 48
The mdbook-mermaid preprocessor is configured but not documented for local development, and no CI/CD pipeline builds the documentation.
The book.toml references mdbook-mermaid, and mermaid diagrams do exist in the documentation (15+ in docs/common/thp/specification.md). However, since no GitHub Actions workflow builds the docs, mdbook is not listed as a dependency, and the contributing guide doesn't mention documentation building, it's unclear if this configuration is actively maintained or intended for local development.
Either remove the preprocessor configuration if the documentation is built externally only, or add setup instructions and a CI target if local building should be supported.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/book.toml` around lines 10 - 13, The book.toml currently enables the
mdbook-mermaid preprocessor (preprocessor.mermaid / "mdbook-mermaid") but there
is no developer guidance or CI to build docs; either remove that preprocessor
block if docs are built externally, or add local + CI support: update
documentation (CONTRIBUTING.md) with exact install steps to add mdbook and
mdbook-mermaid and how to build the book locally, add mdbook and mdbook-mermaid
to project dev dependencies or a tooling script, and add a GitHub Actions
workflow job that runs mdbook build (so mermaid diagrams in
docs/common/thp/specification.md render in CI). Ensure the chosen option updates
book.toml and contributing docs consistently.
| (() => { | ||
| const darkThemes = ['ayu', 'navy', 'coal']; | ||
| const lightThemes = ['light', 'rust']; | ||
|
|
||
| const classList = document.getElementsByTagName('html')[0].classList; | ||
|
|
||
| let lastThemeWasLight = true; | ||
| for (const cssClass of classList) { | ||
| if (darkThemes.includes(cssClass)) { | ||
| lastThemeWasLight = false; | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| const theme = lastThemeWasLight ? 'default' : 'dark'; | ||
| mermaid.initialize({ startOnLoad: true, theme }); |
There was a problem hiding this comment.
Add defensive checks for script dependencies and DOM readiness.
The script has several assumptions that could cause runtime errors:
-
Mermaid availability (line 16):
mermaid.initialize()assumes themermaidglobal object exists. Ifmermaid.min.jsfails to load or loads after this script, it will throwReferenceError: mermaid is not defined. -
DOM readiness (line 5): The IIFE executes immediately. If the script tag is placed in
<head>,document.getElementsByTagName('html')[0]should work, but the theme selector elements queried later may not exist yet.
🛡️ Proposed fix to add defensive checks
(() => {
+ // Ensure mermaid is loaded
+ if (typeof mermaid === 'undefined') {
+ console.error('Mermaid library not loaded');
+ return;
+ }
+
const darkThemes = ['ayu', 'navy', 'coal'];
const lightThemes = ['light', 'rust'];
- const classList = document.getElementsByTagName('html')[0].classList;
+ const htmlElement = document.documentElement || document.getElementsByTagName('html')[0];
+ const classList = htmlElement.classList;
let lastThemeWasLight = true;
for (const cssClass of classList) {Additionally, consider wrapping the event listener setup in a DOMContentLoaded check or placing the script at the end of <body> to ensure theme selector elements exist.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/mermaid-init.js` around lines 1 - 16, The IIFE assumes DOM readiness and
the global mermaid object; update it to first ensure the document is ready
(check document.readyState or listen for DOMContentLoaded) and that
document.getElementsByTagName('html')[0] exists before using classList, then
compute theme using darkThemes/lightThemes and lastThemeWasLight as before but
only call mermaid.initialize(...) if window.mermaid (or global mermaid) is
defined; if mermaid is missing, either defer initialization until mermaid is
available or bail out with a safe no-op to avoid ReferenceError.
| for (const darkTheme of darkThemes) { | ||
| document.getElementById(darkTheme).addEventListener('click', () => { | ||
| if (lastThemeWasLight) { | ||
| window.location.reload(); | ||
| } | ||
| }); | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Description: Check mdBook's generated HTML for theme selector element IDs
# Build the documentation to generate HTML
cd docs && mdbook build 2>/dev/null || echo "mdbook build may require setup"
# Search for theme selector elements in generated HTML
if [ -d "docs/mdbook" ]; then
echo "Searching for theme selector IDs in generated HTML..."
rg -i 'id=["\']?(ayu|navy|coal|light|rust)["\']?' docs/mdbook/ -A2 -B2 || echo "No matching IDs found"
echo -e "\nSearching for theme-related class or button elements..."
rg -i 'theme.*button|theme.*select' docs/mdbook/ -A2 -B2 | head -20
fiRepository: trezor/trezor-firmware
Length of output: 311
🏁 Script executed:
# Find and examine the mermaid-init.js file
find . -name "mermaid-init.js" -type fRepository: trezor/trezor-firmware
Length of output: 89
🏁 Script executed:
# Also look at the structure of the docs directory
ls -la docs/ 2>/dev/null | head -20Repository: trezor/trezor-firmware
Length of output: 1115
🏁 Script executed:
# Search for mdbook configuration
find docs -name "book.toml" -type f 2>/dev/nullRepository: trezor/trezor-firmware
Length of output: 81
🏁 Script executed:
# Read the full mermaid-init.js file
cat -n docs/mermaid-init.jsRepository: trezor/trezor-firmware
Length of output: 1369
🏁 Script executed:
# Read the book.toml to understand theme configuration
cat -n docs/book.tomlRepository: trezor/trezor-firmware
Length of output: 484
🏁 Script executed:
# Search for any custom HTML templates or theme references
find docs -name "*.html" -o -name "*.hbs" -o -name "*.handlebars" 2>/dev/nullRepository: trezor/trezor-firmware
Length of output: 48
🏁 Script executed:
# Search for any references to theme selectors or configuration
rg -i "theme" docs/ --type md --type toml | head -20Repository: trezor/trezor-firmware
Length of output: 157
🏁 Script executed:
# Check if there are any build outputs or HTML files
find . -name "*.html" -path "*/docs/*" 2>/dev/null | head -10Repository: trezor/trezor-firmware
Length of output: 48
🌐 Web query:
mdBook theme selector HTML structure element IDs ayu navy coal light rust
💡 Result:
In mdBook, the theme selector HTML structure uses specific IDs for the theme options. The naming convention for these IDs depends on the version of mdBook being used [1]. For mdBook v0.5.x and later, the theme selector elements use a prefixed ID format: - ayu: mdbook-theme-ayu - navy: mdbook-theme-navy - coal: mdbook-theme-coal - light: mdbook-theme-light - rust: mdbook-theme-rust For older versions (mdBook v0.4.x), the IDs do not include the prefix and are simply: - ayu: ayu - navy: navy - coal: coal - light: light - rust: rust These IDs are typically found within the theme selector dropdown or list in the rendered HTML (often within index.hbs) and are used by the theme switcher JavaScript to apply the corresponding CSS class to the document body [2][1]. When adding custom themes, it is important to follow the version-appropriate ID convention to ensure the theme switcher functions correctly [1].
Citations:
- 1: https://gist.github.com/sspaeti/1856cf717357f54e07f989884368d994
- 2: https://crisal.io/tmp/book-example/book/format/theme/index.html
🏁 Script executed:
# Check for mdBook version in various config files
rg "mdbook" . --type toml --type json -i | head -20Repository: trezor/trezor-firmware
Length of output: 148
🏁 Script executed:
# Check if there's a package.json or similar
find . -maxdepth 2 -name "package.json" -o -name "Cargo.toml" -o -name "requirements.txt" | xargs grep -l "mdbook" 2>/dev/nullRepository: trezor/trezor-firmware
Length of output: 50
🏁 Script executed:
# Look for any CI/CD configuration that might specify mdBook version
find . -maxdepth 2 \( -name ".github" -o -name ".gitlab-ci.yml" -o -name "tox.ini" \) -type d 2>/dev/nullRepository: trezor/trezor-firmware
Length of output: 76
🏁 Script executed:
# Check GitHub workflows for mdBook version
find .github -type f \( -name "*.yml" -o -name "*.yaml" \) -exec cat {} \; | head -100Repository: trezor/trezor-firmware
Length of output: 4274
🏁 Script executed:
# Alternative: search for mdbook in workflow files
rg "mdbook" .github/ -A 2 -B 2Repository: trezor/trezor-firmware
Length of output: 48
🏁 Script executed:
# Final check: look for any documentation about mdBook version or theme selector compatibility
rg -i "version|mdbook|theme" docs/ --type md | grep -i "mdbook\|version" | head -10Repository: trezor/trezor-firmware
Length of output: 1261
Add null checks before attaching event listeners.
document.getElementById(darkTheme) and document.getElementById(lightTheme) may return null, especially with mdBook v0.5.x+, which uses prefixed IDs like mdbook-theme-ayu instead of unprefixed ones. Calling addEventListener on null will throw a runtime error and break the page.
🐛 Proposed fix to add null checks
for (const darkTheme of darkThemes) {
- document.getElementById(darkTheme).addEventListener('click', () => {
+ const themeButton = document.getElementById(darkTheme);
+ if (!themeButton) continue;
+ themeButton.addEventListener('click', () => {
if (lastThemeWasLight) {
window.location.reload();
}
});
}Apply the same pattern to the light themes loop (lines 28-34).
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| for (const darkTheme of darkThemes) { | |
| document.getElementById(darkTheme).addEventListener('click', () => { | |
| if (lastThemeWasLight) { | |
| window.location.reload(); | |
| } | |
| }); | |
| } | |
| for (const darkTheme of darkThemes) { | |
| const themeButton = document.getElementById(darkTheme); | |
| if (!themeButton) continue; | |
| themeButton.addEventListener('click', () => { | |
| if (lastThemeWasLight) { | |
| window.location.reload(); | |
| } | |
| }); | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/mermaid-init.js` around lines 20 - 26, The loops that call
document.getElementById(darkTheme) and document.getElementById(lightTheme) can
return null and currently call addEventListener directly; update both loops to
guard against null by first retrieving the element into a local (e.g., const el
= document.getElementById(darkTheme)) and only calling el.addEventListener(...)
if el is truthy, preserving the existing callback logic that references
lastThemeWasLight; do the same for the lightThemes loop to prevent runtime
errors when elements are absent.
| for (const lightTheme of lightThemes) { | ||
| document.getElementById(lightTheme).addEventListener('click', () => { | ||
| if (!lastThemeWasLight) { | ||
| window.location.reload(); | ||
| } | ||
| }); | ||
| } |
There was a problem hiding this comment.
Add null checks before attaching event listeners.
Same issue as the dark theme handlers: document.getElementById(lightTheme) may return null, causing a runtime error.
🐛 Proposed fix to add null checks
for (const lightTheme of lightThemes) {
- document.getElementById(lightTheme).addEventListener('click', () => {
+ const themeButton = document.getElementById(lightTheme);
+ if (!themeButton) continue;
+ themeButton.addEventListener('click', () => {
if (!lastThemeWasLight) {
window.location.reload();
}
});
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| for (const lightTheme of lightThemes) { | |
| document.getElementById(lightTheme).addEventListener('click', () => { | |
| if (!lastThemeWasLight) { | |
| window.location.reload(); | |
| } | |
| }); | |
| } | |
| for (const lightTheme of lightThemes) { | |
| const themeButton = document.getElementById(lightTheme); | |
| if (!themeButton) continue; | |
| themeButton.addEventListener('click', () => { | |
| if (!lastThemeWasLight) { | |
| window.location.reload(); | |
| } | |
| }); | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/mermaid-init.js` around lines 28 - 34, The loop attaching click handlers
to elements in lightThemes should guard against missing DOM nodes: before
calling addEventListener on document.getElementById(lightTheme) check the result
for null; if the element exists, attach the listener that checks
lastThemeWasLight and triggers window.location.reload() if needed. Update the
loop that iterates over lightThemes and uses document.getElementById(lightTheme)
to perform a null/undefined check (or early continue) so addEventListener is
only called on a real element.
|
The purpose of this PR is so that mermaid diagrams are rendered in the web version of docs. Example: https://docs.trezor.io/trezor-firmware/common/thp/specification.html#connection-process-diagram. Note: mermaid diagrams are rendered in the GitHub version of the docs (https://github.com/trezor/trezor-firmware/blob/main/docs/common/thp/specification.md#connection-process-diagram).
The js code is automatically generated using |
M1nd3r
left a comment
There was a problem hiding this comment.
Tested - the following commands yield the same changes:
nix-shell -p mdbook mdbook-mermaid
uv sync
uv source .venv/bin/activate
cd docs
mdbook-mermaid install .
mdbook build .




































No description provided.