diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 37e8cd60..7301356c 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -14,6 +14,7 @@ on:
- "spec_files/**"
- "post_install_files/**"
- "press_kit/**"
+ - "docs/**"
- ".github/workflows/build_iso.yml"
push:
branches:
diff --git a/.github/workflows/deploy_docs.yml b/.github/workflows/deploy_docs.yml
new file mode 100644
index 00000000..0b869d8e
--- /dev/null
+++ b/.github/workflows/deploy_docs.yml
@@ -0,0 +1,184 @@
+name: Deploy documentation
+
+# Check for reference:
+# https://github.com/s1rius/ezlog/blob/20dce11e6d324bb18f57dc7c7c6d4a8bf40064de/.github/workflows/publish_pages.yml
+
+on:
+ schedule:
+ - cron: "40 03 */2 * *" # Runs at 03:40, every 2 days
+ push:
+ branches:
+ - main
+ paths:
+ - docs/**/*.md
+ - docs/**/*.png
+ - docs/**/*.jpg
+ - docs/**/*.jpeg
+ - docs/**/*.po
+ - .github/workflows/deploy_docs.yml
+ - .github/workflows/install-mdbook/action.yml
+ - README*.md
+ - docs/book.toml
+ pull_request:
+ branches:
+ - main
+ paths:
+ - docs/**/*.md
+ - docs/**/*.png
+ - docs/**/*.jpg
+ - docs/**/*.jpeg
+ - docs/**/*.po
+ - .github/workflows/deploy_docs.yml
+ - .github/workflows/install-mdbook/action.yml
+ - README*.md
+ - docs/book.toml
+ workflow_dispatch:
+
+concurrency:
+ group: pages
+ cancel-in-progress: true
+
+env:
+ runner: ubuntu-latest
+ cache-mdbook-name: cache-mdbook-bins
+ EXTRA_LANGUAGES:
+ SITE_URL: /bazzite/
+ MDBOOK_output__html__git_repository_url: "${{ github.server_url }}/${{ github.repository }}"
+ MDBOOK_output__html__edit_url_template: "${{ github.server_url }}/${{ github.repository }}/edit/${{ github.ref_name }}/docs/{path}"
+
+jobs:
+ deploy:
+ permissions:
+ contents: read # To push a branch
+ pages: write # To push to a GitHub Pages site
+ id-token: write # To update the deployment status
+
+ runs-on: ubuntu-latest
+ # environment:
+ # name: github-pages
+ # url: ${{ steps.deployment.outputs.page_url }}
+ defaults:
+ run:
+ working-directory: ./docs
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+
+ - uses: actions/setup-python@v5
+ with:
+ python-version: "3.12"
+
+ - name: Install python dependencies
+ run: |
+ pip install --user requests
+
+ - name: Cache mdbook
+ id: cache-mdbook
+ uses: actions/cache@v4
+ with:
+ path: |
+ ~/.cargo/bin
+ ~/.local/share/headless-chrome
+ key: ${{ runner.os }}-build-${{ env.cache-mdbook-name }}-${{ hashFiles('.github/workflows/install-mdbook/action.yml') }}
+
+ - name: Add mdbook to PATH
+ if: steps.cache-mdbook.outputs.cache-hit == 'true'
+ run: |
+ echo ~/.cargo/bin:$PATH >> $GITHUB_PATH
+
+ - name: Install mdbook
+ if: steps.cache-mdbook.outputs.cache-hit != 'true'
+ uses: ./.github/workflows/install-mdbook
+
+ # Necessary in order to have fetch_discourse_md.py available for mdbook-cmd
+ - name: Add docs/utils to PATH
+ run: |
+ echo $PWD/utils:$PATH >> $GITHUB_PATH
+
+ - name: Test fetch_discourse_md.py
+ run: |
+ echo "::group::Try fetching a post from discourse"
+ fetch_discourse_md.py -d "https://universal-blue.discourse.group/docs?topic=31" 2>&1 >/dev/null
+ echo "::endgroup::"
+
+ - name: Build book in English
+ env:
+ MDBOOK_output__html__site_url: ${{ env.SITE_URL }}
+ DEBUG: "1"
+ run: |
+ # This assumes your book is in the root of your repository.
+ # Just add a `cd` here if you need to change to another directory.
+ mdbook build -d $GITHUB_WORKSPACE/book
+ (
+ cd $GITHUB_WORKSPACE/book
+ shopt -s dotglob
+ mv {html,pdf}/* ./
+ )
+
+ - name: Build all translations
+ env:
+ DEBUG: "1"
+ run: |
+ for po_lang in ${{ env.EXTRA_LANGUAGES }}; do
+ echo "::group::Building $po_lang translation"
+ MDBOOK_BOOK__LANGUAGE=$po_lang \
+ MDBOOK_OUTPUT__HTML__SITE_URL=${{ env.SITE_URL }}$po_lang/ \
+ mdbook build -d $GITHUB_WORKSPACE/book/$po_lang
+ (
+ cd $GITHUB_WORKSPACE/book/$po_lang
+ shopt -s dotglob
+ mv {html,pdf}/* ./
+ )
+ echo "::endgroup::"
+ done
+
+ - name: Generate translation progress report
+ if: env.EXTRA_LANGUAGES != ''
+ continue-on-error: true
+ run: |
+ i18n-report report $GITHUB_WORKSPACE/book/i18n_report.html po/*.po
+
+ - name: Setup Pages
+ uses: actions/configure-pages@v4
+
+ - name: Upload artifact
+ uses: actions/upload-pages-artifact@v3
+ with:
+ path: ${{ github.workspace }}/book
+
+ - name: Deploy to GitHub Pages
+ id: deployment
+ uses: actions/deploy-pages@v4
+ with:
+ token: ${{ github.token }}
+
+ clean_cache:
+ needs: deploy
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ actions: write
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+
+ - name: Cache Cleanup
+ env:
+ GH_TOKEN: ${{ github.token }}
+ run: |
+ set -x
+ old_caches=($(gh cache list \
+ --repo ${{ github.repository }} \
+ --key "${{ runner.os }}-build-${{ env.cache-mdbook-name }}-" \
+ --sort created_at -O asc --json id | jq '.[:-1][].id'))
+ for id in "${old_caches[@]}"; do
+ gh cache delete $id
+ done
+ - name: Remove Page Artifacts
+ uses: remagpie/gha-remove-artifact@v1
+ with:
+ only-name: github-pages
+ max-age: 7776000 # 90 days
+ max-count: 50
diff --git a/.github/workflows/generate_changelog.yml b/.github/workflows/generate_changelog.yml
index a61d676b..18410987 100644
--- a/.github/workflows/generate_changelog.yml
+++ b/.github/workflows/generate_changelog.yml
@@ -1,5 +1,7 @@
on:
push:
+ paths-ignore:
+ - docs/**
branches:
- main
diff --git a/.github/workflows/install-mdbook/action.yml b/.github/workflows/install-mdbook/action.yml
new file mode 100644
index 00000000..efb4327d
--- /dev/null
+++ b/.github/workflows/install-mdbook/action.yml
@@ -0,0 +1,32 @@
+name: Install mdbook and dependencies
+
+description: Install mdbook with the dependencies we need.
+
+runs:
+ using: composite
+ steps:
+ - name: Install Rust
+ uses: dtolnay/rust-toolchain@stable
+ with:
+ toolchain: stable
+ # The --locked flag is important for reproducible builds. It also
+ # avoids breakage due to skews between mdbook and mdbook-svgbob.
+ - name: Install mdbook
+ run: cargo install --git https://github.com/HollowMan6/mdBook --rev b5ca7bc39ac2e8073dc2fb9d984c0e46c498c167 mdbook --locked
+ shell: bash
+
+ - name: Install mdbook-i18n-helpers
+ run: cargo install mdbook-i18n-helpers --locked --version 0.3.5
+ shell: bash
+
+ - name: Install i18n-report
+ run: cargo install i18n-report --locked --version 0.2.0
+ shell: bash
+
+ - name: Install mdbook-pdf
+ run: cargo install mdbook-pdf --locked --version 0.1.10 --features fetch
+ shell: bash
+
+ - name: Install mdbook-cmdrun
+ run: cargo install mdbook-cmdrun --locked --version 0.6.0
+ shell: bash
diff --git a/docs/.gitignore b/docs/.gitignore
new file mode 100644
index 00000000..a05ebd68
--- /dev/null
+++ b/docs/.gitignore
@@ -0,0 +1,178 @@
+book
+debug.txt
+# Created by https://www.toptal.com/developers/gitignore/api/python
+# Edit at https://www.toptal.com/developers/gitignore?templates=python
+
+### Python ###
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+*$py.class
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+wheels/
+share/python-wheels/
+*.egg-info/
+.installed.cfg
+*.egg
+MANIFEST
+
+# PyInstaller
+# Usually these files are written by a python script from a template
+# before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.nox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*.cover
+*.py,cover
+.hypothesis/
+.pytest_cache/
+cover/
+
+# Translations
+*.mo
+*.pot
+
+# Django stuff:
+*.log
+local_settings.py
+db.sqlite3
+db.sqlite3-journal
+
+# Flask stuff:
+instance/
+.webassets-cache
+
+# Scrapy stuff:
+.scrapy
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+.pybuilder/
+target/
+
+# Jupyter Notebook
+.ipynb_checkpoints
+
+# IPython
+profile_default/
+ipython_config.py
+
+# pyenv
+# For a library or package, you might want to ignore these files since the code is
+# intended to run in multiple environments; otherwise, check them in:
+# .python-version
+
+# pipenv
+# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
+# However, in case of collaboration, if having platform-specific dependencies or dependencies
+# having no cross-platform support, pipenv may install dependencies that don't work, or not
+# install all needed dependencies.
+#Pipfile.lock
+
+# poetry
+# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
+# This is especially recommended for binary packages to ensure reproducibility, and is more
+# commonly ignored for libraries.
+# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
+#poetry.lock
+
+# pdm
+# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
+#pdm.lock
+# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
+# in version control.
+# https://pdm.fming.dev/#use-with-ide
+.pdm.toml
+
+# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
+__pypackages__/
+
+# Celery stuff
+celerybeat-schedule
+celerybeat.pid
+
+# SageMath parsed files
+*.sage.py
+
+# Environments
+.env
+.venv
+env/
+venv/
+ENV/
+env.bak/
+venv.bak/
+
+# Spyder project settings
+.spyderproject
+.spyproject
+
+# Rope project settings
+.ropeproject
+
+# mkdocs documentation
+/site
+
+# mypy
+.mypy_cache/
+.dmypy.json
+dmypy.json
+
+# Pyre type checker
+.pyre/
+
+# pytype static type analyzer
+.pytype/
+
+# Cython debug symbols
+cython_debug/
+
+# PyCharm
+# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
+# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
+# and can be added to the global gitignore or merged into this file. For a more nuclear
+# option (not recommended) you can uncomment the following to ignore the entire idea folder.
+#.idea/
+
+### Python Patch ###
+# Poetry local configuration file - https://python-poetry.org/docs/configuration/#local-configuration
+poetry.toml
+
+# ruff
+.ruff_cache/
+
+# LSP config files
+pyrightconfig.json
+
+# End of https://www.toptal.com/developers/gitignore/api/python
diff --git a/docs/Justfile b/docs/Justfile
new file mode 100644
index 00000000..b02c4581
--- /dev/null
+++ b/docs/Justfile
@@ -0,0 +1,74 @@
+export PATH := justfile_directory() + "/utils:" + env("PATH")
+
+_default:
+ just --list
+
+# Install dependencies required for documentation stuff
+install_dependencies:
+ bash ./utils/install-deps.sh
+
+_build_messages_pot:
+ #!/usr/bin/bash
+ DEBUG=1 ./utils/pre-build.py -s src -o src.tmp
+ MDBOOK_BOOK__SRC="src.tmp" \
+ MDBOOK_OUTPUT='{"xgettext": {}}' \
+ mdbook build -d po
+ rm -r src.tmp
+
+# Check that a translation file exists, otherwise exit with 1
+_is_translation LANG:
+ [[ -f po/{{LANG}}.po ]] || { \
+ echo "ERROR: 'po/{{LANG}}.po' does not exist."; \
+ echo "Use 'just add_translation {{LANG}}' to create a new translation file"; \
+ exit 1; }
+
+# Add a language to translate
+add_translation LANG: _build_messages_pot
+ msginit -i po/messages.pot -l {{LANG}} -o po/{{LANG}}.po
+
+# Flatten a directory containing multiple mdbook outputs
+_flatten_outputs OUTPUTS_DIR="./book":
+ #!/usr/bin/bash
+ cd {{ OUTPUTS_DIR }}
+ to_flatten=( \
+ # Add here directories you want to flatten
+ $(ls -d "html" "pdf") \
+ ) || true
+ for dir in "${to_flatten[@]}"; do
+ (
+ shopt -s dotglob
+ mv $dir/* ./
+ )
+ done
+
+# Update a language with a fresh messages.pot
+update_translation LANG: (_is_translation LANG) _build_messages_pot
+ msgmerge --update po/{{LANG}}.po po/messages.pot
+
+# Equivalent to 'mdbook build'
+mdbook_build LANG="":
+ #!/usr/bin/bash
+ mdbook clean
+ mdbook build -d ./book && just _flatten_outputs
+ if [[ -n "{{LANG}}" ]]; then
+ MDBOOK_BOOK__LANGUAGE={{LANG}} mdbook build -d book/{{LANG}} && \
+ just _flatten_outputs book/{{LANG}}
+ fi
+
+_serve_http DIR="./book":
+ python -m http.server -d {{DIR}} -b 127.0.0.1 3000
+
+# Start a lightweight web server with a preview of the mdbook
+mdbook_serve LANG="":
+ #!/usr/bin/bash
+ set -meo pipefail
+ just mdbook_build {{LANG}}
+ just _serve_http &
+ sleep 1
+ printf '\n\n\n\n'
+ echo "Page ready at 'http://127.0.0.1:3000/{{LANG}}'"
+ fg
+
+# Same as 'mdbook_serve' but for a specific language
+preview_translation LANG: (_is_translation LANG)
+ just mdbook_serve {{LANG}}
\ No newline at end of file
diff --git a/docs/README.md b/docs/README.md
new file mode 100644
index 00000000..5c34e717
--- /dev/null
+++ b/docs/README.md
@@ -0,0 +1,237 @@
+# Contributing to Bazzite mdBook documentation
+
+## Introduction
+
+This is a guide that will show you:
+
+- How to write new documentation pages in mdBooks.
+- How to transcribe documentation, from Discourse forums (https://universal-blue.discourse.group/) to mdBook pages.
+
+## Brief explanation in how to work with mdBook
+
+> _mdBook is a command line tool to create books with Markdown. It is ideal for creating product or API documentation, tutorials, course materials or anything that requires a clean, easily navigable and customizable presentation_
+>
+> Source ~ https://rust-lang.github.io/mdBook/
+
+**TL;DR**: Its a fancy way tool that allows us to create a documentation website with basic [Markdown](https://commonmark.org/help/).
+
+---
+
+The essential part that cant be missing in a mdBook is the `SUMMARY.md` file.
+
+```md
+
+
+# General
+
+- [📜 Bazzite's README](Bazzite_README.md)
+- [❓️ FAQ](General/FAQ.md)
+- [📖 Installation Guide](General/Installation_Guide/index.md)
+- [📝 Desktop Environment Tweaks](General/Desktop_Environment_Tweaks.md)
+- [🤝 Contributing to Bazzite](General/Contributing_to_Bazzite.md)
+- [🎲 Gaming](Gaming/index.md)
+ - [Game Launchers](Gaming/Game_Launchers.md)
+
+# Steam Gaming Mode / Handheld & HTPC Hardware
+
+- [📺️ Steam Gaming Mode Overview](Handheld_and_HTPC_edition/Steam_Gaming_Mode/index.md)
+ - [Change Physical Keyboard Layout for Steam Gaming Mode](Handheld_and_HTPC_edition/Change_Physical_Keyboard_Layout_for_Steam_Gaming_Mode.md)
+```
+
+`SUMMARY.md` acts not only as a nice looking table of contents, but as indexer as well.
+
+**If a page is not listed in `SUMMARY.md`, it wont be included in the mdBook**\*
+
+\* Just so you are aware
+
+---
+
+## Transcribe Discourse docs to mdBooks
+
+Requirements:
+
+- Markdown compatible code editor (ex.: Visual Studio Code)
+- mdBook (can be installed with Homebrew\*)
+- Git
+
+\* If you are using Bazzite or [similar](https://universal-blue.org/), chances are that you already have it installed.
+
+---
+
+Best way to learn is with a real life example. We will transcribe https://universal-blue.discourse.group/docs?topic=2743
+
+### 1. Basic preparation
+
+We will start with getting our utilities ready:
+
+1. A web browser with the Discourse doc page we want to transcribe. We will use for this example.
+2. Our code editor.
+3. A terminal open in the `docs` directory
+
+ ```sh
+ $ cd docs
+ ```
+
+ Get sure we have `fetch_discourse_md.py` in there, we will need it
+
+ ```sh
+ $ ls ./utils/fetch_discourse_md.py
+ ./utils/fetch_discourse_md.py
+ ```
+
+### 2. Copy the post
+
+`fetch_discourse_md.py` is your friend for this task.
+
+1. Copy the URL of the document
+2. In the terminal, pass the URL to `fetch_discourse_md.py`
+
+ ```sh
+ $ ./utils/fetch_discourse_md.py "https://universal-blue.discourse.group/docs?topic=2743" | wl-copy
+ ```
+
+ Normally, `fetch_discourse_md.py` would dump the resulting markdown doc in the terminal output, with `wl-copy` we store it in our clipboard for now.
+
+3. Create the markdown file where we will store our document. The title of the post is "_Dual Boot Preliminary Setup and Post-Setup Guide_", so somewhere under "Advanced" should be fitting.
+
+ > ⚠️ WARNING
+ >
+ > Just remember, ⚠️**DO NOT USE SPACES IN THE FILE NAME**⚠️. Is really important, spaces in filenames is going to bit us later in a future.
+ > Instead, use underscores `_`
+
+ 
+
+### 4. Paste the document in the file
+
+
+
+### 5. Rewrite URLs
+
+We are almost done. The problem is `fetch_discourse_md.py` only will give us a dumped version of the Discourse document.
+
+There is posibly URLs that are pointing to other documentation posts in Discourse that we might have already in our mdBook.
+
+
+
+The url in the image above is pointing to the _Steam Gaming Mode Overview (Handheld/HTPC)_ post.
+At the time of writting this, we have that post avaliable in our mdBook, so we can simply replace that URL with ours
+
+
+
+In our case, the post is located in `../Handheld_and_HTPC_edition/Steam_Gaming_Mode/index.md`
+
+### 6. Link back in `SUMMARY.md`
+
+We can check how our post looks in mdBook, run in the terminal
+
+```sh
+mdbook serve --open
+```
+
+Now, more likely you wont find our new added post.
+
+
+
+If you take a look at [the brief explanation](#brief-explanation-in-how-to-work-with-mdbook), you will read about `SUMMARY.md`. Files not listed in there wont be processed by mdBook.
+
+Lets add our file there.
+
+
+
+And now our post is ready.
+
+
+
+## Translate documentation
+
+> ⚠️ WARNING
+>
+> It is better to start translation once [transcription](#transcribe-discourse-docs-to-mdbooks) is settled to keep up.
+
+Translation isnt so straightforward as copying a markdown file and start working.
+
+We rely in [mdbook-i18n-helpers](https://github.com/google/mdbook-i18n-helpers) for translation, which uses [GNU Gettext](https://www.gnu.org/software/gettext/manual/html_node/index.html).
+
+We need some more dependencies in order to do translations, which can be installed with this script:
+
+```sh
+bash docs/utils/install-deps.sh
+```
+
+
+
+Dependencies list
+Ignore if using install-deps.sh
+
+
+- `.po` file editor (like [Poedit](https://flathub.org/apps/net.poedit.Poedit))
+- Rust's `cargo` (you can install rust by running
+ `brew install rustup; rustup-init`)
+- `mdbook-i18n-helpers` (after installing rust,
+ `cargo install mdbook-i18n-helpers`)
+
+
+
+### 1. Basic preparation
+
+Move to `docs`, then build the `.pot` file
+
+```sh
+cd docs
+just build_messages_pot
+```
+
+This will create `po/messages.pot`, which acts as an index of text fragments
+from all our markdown files.
+
+### 2. (Optional) Add a new language
+
+All translations files are stored in `docs/po/` in the form of `xx.po` files, `xx` referencing the language code following [ISO 639][ISO]. Per example, `es.po` would be an Spanish translation
+file.
+
+To add a new language to the documentation, follows these steps:
+
+1. Get sure you did the [basic preparation](#1-basic-preparation-1)
+2. Then run this, replacing `XX` with the [language code][ISO]:
+
+ ```sh
+ just add_translation XX
+ ```
+
+ In my case, I'm going to create an Spanish translation file:
+
+ ```sh
+ just add_translation es
+ ls po/
+ # es.po messages.pot
+ ```
+
+### 3. Working with a translation file
+
+
+
+We will now open that `.po` file with our po editor (in my case is Poedit).
+
+We make some changes, hit Ctrl+S to save.
+
+Lets see the changes we had done with a preview. Run this:
+
+```sh
+just preview_translation XX
+```
+
+In my case is `es`
+
+```sh
+just preview_translation es
+```
+
+And there it is!
+
+
+
+## Write new documentation
+
+WIP
+
+[ISO]: https://en.wikipedia.org/wiki/List_of_ISO_639_language_codes
diff --git a/docs/book.toml b/docs/book.toml
new file mode 100644
index 00000000..15ff352d
--- /dev/null
+++ b/docs/book.toml
@@ -0,0 +1,42 @@
+[book]
+authors = ["nicknamenamenick", "Zeglius"]
+language = "en"
+multilingual = false
+src = "src"
+title = "Bazzite Documentation"
+
+[build]
+use-default-preprocessors = false
+create-missing = false
+
+[preprocessor.links]
+
+[output.html]
+git-repository-url = "https://github.com/ublue-os/bazzite"
+edit-url-template = "https://github.com/ublue-os/bazzite/edit/main/docs/{path}"
+default-theme = "navy"
+preferred-dark-theme = "navy"
+additional-css = ["custom.css"]
+
+[output.html.fold]
+enable = true
+
+[preprocessor.youtube-embed]
+command = "python ./preprocessors/youtube-embed.py"
+
+[preprocessor.replace-urls]
+command = "python ./preprocessors/replace-urls.py"
+after = ["youtube-embed", "links"]
+ignore = ["Introduction*"]
+
+[preprocessor.gettext]
+after = ["links", "cmdrun"]
+
+[preprocessor.cmdrun]
+before = ["replace-urls"]
+
+[output.pdf]
+
+[preprocessor.replace-urls.mappings]
+# Here we add urls to be overriden
+"https://universal-blue.discourse.group/docs?topic=561" = "/Introduction"
diff --git a/docs/custom.css b/docs/custom.css
new file mode 100644
index 00000000..f7f91971
--- /dev/null
+++ b/docs/custom.css
@@ -0,0 +1,8 @@
+h1.menu-title::before {
+ content: "";
+ background-image: url("./favicon.svg");
+ padding: 1em;
+ background-position: center center;
+ background-size: 1.5em;
+ background-repeat: no-repeat;
+}
\ No newline at end of file
diff --git a/docs/preprocessors/format-author.py b/docs/preprocessors/format-author.py
new file mode 100644
index 00000000..96a5f41f
--- /dev/null
+++ b/docs/preprocessors/format-author.py
@@ -0,0 +1,88 @@
+__doc__ = """Example of a mdbook preprocessor"""
+
+import datetime
+import json
+import os
+import re
+import sys
+from typing import Any
+
+
+_DEBUG = os.getenv("DEBUG", "")
+
+
+def debug(*obj) -> Any:
+ return obj
+
+
+if _DEBUG in ["1", "yes"]:
+ _DEBUG_OUTPUT = "./debug.txt"
+ if os.path.exists(_DEBUG_OUTPUT):
+ os.truncate(_DEBUG_OUTPUT, 0)
+
+ def debug(*obj) -> Any:
+ with open(_DEBUG_OUTPUT, "+a") as stdout:
+ print(f"DEBUG[{datetime.date.today()}]:", *obj, file=stdout)
+ return obj
+
+
+def modify_content(content: str) -> str | None:
+ ############## MODIFY 'content' HERE ##############
+ """Alter the contents of each chapter
+
+ Args:
+ content (str): The contents of a chapter received. Is in markdown format.
+
+ Returns:
+ str | None: The chapter contents modified.
+ If `None`, the original content will be used instead
+ """
+
+ author_template = "