feat: Prepare mdBook workflow for documentation (#1441)

* feat: add mdbook docs

* chore: add several articles to docs

* docs: add documentation at surface level

Using Discourse urls as fallback for missing content for now

docs: add missing image files

* docs: Add missing chapter emojis

docs: Add missing warning in Advanced docs in summary

docs: add missing waydroid guide

docs: rename files to avoid spaces

docs: fix badly set docs build params

docs: remove unnecesary placeholders

* docs: Realocate 'Gaming' section under 'General'

* docs: Add 'Introduction' section

This section contains a table of contents of the documentation

* docs: Add unstable documentation warning

* docs: Add missing github url

docs: add missing symlink to resources

* docs: Add discourse scrapper utility

* docs: minor discourse scrapper docs changes

* docs: Add youtube embeding preprocessor

* minor reformat for youtube-embed

* docs: Add mdbook preprocessor template

* docs: add format-author preprocessor

* docs: add git lib to mdbook toolset

* docs: Always fetch the highest quality image by fetch_discourse_md

* docs: fix youtube-embed ignoring new line requirement

* docs: Add documentation transcription guide

* docs: Missing url in transcription guide

* docs: Remove YAML header from doc guide

* docs: Minor tweaks to transcription guide

* docs: Add utilities preprocessor module

docs: Move debug preprocessor util to utils

* docs: tweak debug function

* docs: Add 'replace-urls' preprocessor

* chore: Move mappings parameter in replace-urls preprocessor

* docs: add ignore field to replace-urls

* docs: add Mdbook python types

* docs: Add ignore field to replace-urls

Now we can exclude files from being processed with blob patterns

* chore(ci): add deploy_docs

* chore(ci): Add dynamic edit url template to deploy_docs

* chore(ci): Add html.site-url to deploy_docs

* chore(readme): Use relative paths for repo_content

* chore(ci): Add README to included paths for deploy_docs

* chore(ci): Disable deploy_docs

* chore(ci): Use main in deploy_docs.on.push.branches

* docs: Rephrase unstable docs warning

* chore(ci): Exclude docs from triggering build workflow

* chore(ci): Enable deploy_docs

* fix(docs): Remove unnecessary imports in preprocessors

* docs: Move unstable docs warning to index.hbs

* docs: Add page metadata inclusion with fetch_discourse_md.py

* docs: Move fetch_discourse_md.py to docs/utils

* docs: Add 'fetched_at' metadata field in fetch_discourse_md.py

* docs: Update fetch_discourse_md.py to format metadata in json

* Revert "chore(readme): Use relative paths for repo_content"

This reverts commit 6a781c659607e0c83c19248241684c5785c7e93b.

* docs: Replace include with an url to repo README

* ci(docs): Add multilanguage doc build support

* docs: add Justfile utility

* docs: update Justfile utility

* ci(docs): Add stricter workflow trigger to deploy_docs

* docs: add 'preview_translation' to Justfile

* docs: add documentation translation guide

* ci(docs): Add mdbook cache

* ci(docs): Add i18n-report

* ci(docs): tweak deploy_docs workflow triggers

* ci(docs): remove unnecessary slash at build.yml

* ci(docs): remove unnecessary slash at deploy_docs.yml

* ci(docs): add docs/book.toml to deploy_docs trigger

* ci(docs): Add schedule trigger

* ci(docs): add github-pages cleaning

* ci(docs): Exclude docs from generate_changelog

* docs: Add dependencies installation script

* ci(docs): Add mdbook pdf build

* docs: Tweak Justfile to support pdf generation

* Revert "docs: Always fetch the highest quality image by fetch_discourse_md"

This reverts commit 74130ee1fe9264dc7a4c4c49fb416ef3dc12e322.

* ci(docs): Exclude deploy_docs.yml from cache-mdbook keys

* docs: Add 'mdbook_build' to Justfile

* docs: Add 'mdbook_serve' to Justfile

* docs: Add debug flag to fetch_discourse_md

* docs: Automate discourse documentation scrapping

* docs: Add flock to fetch_discourse_md

* docs: Add translation file generation with Justfile

* docs: Prefix url replacements with site-url in replace-urls.py preprocessor

* docs: Add installation guides

docs: Replace print button

* Revert "docs: Prefix url replacements with site-url in replace-urls.py preprocessor"

This reverts commit a685de4dce54debc900607d743069b79202a26ac.

* Reapply "docs: Prefix url replacements with site-url in replace-urls.py preprocessor"

This reverts commit 777d8055eac7543001200834939c960fb490e666.

* docs: fix replace-urls.py

* docs: fix fetch_discourse_md.py hitting discourse ip_10_secs_limit

* ci(docs): Remove duplicate '/' in build translation step

* ci(docs): Update actions/cache

* ci(docs): Reduce deploy_docs schedule timespan between triggers

* docs: update install-deps.sh

* docs: Update Advanced docs

* docs: Add favicon

* docs: Reword unstable documentation warning

* docs: Change default theme to 'navy'

* ci(docs): Move permisions to job scope
This commit is contained in:
Zeglius 2024-08-21 20:56:12 +02:00 committed by GitHub
parent 9729406137
commit 181497bc17
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
129 changed files with 2286 additions and 0 deletions

View File

@ -14,6 +14,7 @@ on:
- "spec_files/**" - "spec_files/**"
- "post_install_files/**" - "post_install_files/**"
- "press_kit/**" - "press_kit/**"
- "docs/**"
- ".github/workflows/build_iso.yml" - ".github/workflows/build_iso.yml"
push: push:
branches: branches:

184
.github/workflows/deploy_docs.yml vendored Normal file
View File

@ -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

View File

@ -1,5 +1,7 @@
on: on:
push: push:
paths-ignore:
- docs/**
branches: branches:
- main - main

View File

@ -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

178
docs/.gitignore vendored Normal file
View File

@ -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

74
docs/Justfile Normal file
View File

@ -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}}

237
docs/README.md Normal file
View File

@ -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
<!-- Example of SUMMARY.md contents -->
# 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**\*
<small>\* Just so you are aware </small>
---
## Transcribe Discourse docs to mdBooks
Requirements:
- Markdown compatible code editor (ex.: Visual Studio Code)
- mdBook (can be installed with Homebrew\*)
- Git
<small>\* If you are using Bazzite or [similar](https://universal-blue.org/), chances are that you already have it installed.</small>
---
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 <https://universal-blue.discourse.group/docs?topic=2743> 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 `_`
![](./src/img/doc_guide_filename.jpg)
### 4. Paste the document in the file
![](./src/img/doc_guide_paste.jpg)
### 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.
![](./src/img/doc_guide_discourse_url.jpg)
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
![](./src/img/doc_guide_rewrite_url.jpg)
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.
![](./src/img/doc_guide_where_did_go.jpg)
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.
![](./src/img/doc_guide_add_summary.jpg)
And now our post is ready.
![](./src/img/doc_guide_there_you_are.jpg)
## 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
```
<details>
<summary>
<big>Dependencies list</big><br>
<sup>Ignore if using install-deps.sh</sup>
</summary>
- `.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`)
</details>
### 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
![Poedit](./src/img/poedit.jpg)
We will now open that `.po` file with our po editor (in my case is Poedit).
We make some changes, hit <kbd>Ctrl</kbd>+<kbd>S</kbd> 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!
![](./src/img/translation_example.jpg)
## Write new documentation
WIP
[ISO]: https://en.wikipedia.org/wiki/List_of_ISO_639_language_codes

42
docs/book.toml Normal file
View File

@ -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"

8
docs/custom.css Normal file
View File

@ -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;
}

View File

@ -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 = "<div>" + r"""Publisher: \g<username>""" + "</div>"
author_pattern = r"\A(?P<username>\w+)\s\|\s(?P<date>(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2}))\s(?P<time>(?P<hour>\d{2}):(?P<min>\d{2}):(?P<sec>\d{2})\s(?P<zone>\w+))\s\|\s#\d+"
if re.match(author_pattern, content, re.MULTILINE):
content = re.sub(author_pattern, author_template, content)
return content
###################################################
#
#
#
#
#
#
#
#
#
#
#
#
if __name__ == "__main__":
if len(sys.argv) > 1:
if sys.argv[1] == "supports":
sys.exit(0)
context, book = json.load(sys.stdin)
book: dict[str, list]
context: dict
debug(f"context: {context}")
sections = book["sections"]
for i, section in enumerate(sections):
section: dict
if not section.get("Chapter"):
continue
for chapter in section.values():
chapter: dict
debug(chapter)
content: str = chapter["content"]
if type(content) is str and (res := modify_content(content)):
content = res
chapter.update({"content": content})
debug(book)
print(json.dumps(book))

View File

View File

@ -0,0 +1,41 @@
from collections import namedtuple
import os
from pathlib import Path, PurePath
import shlex
import subprocess
class Git:
"""Use git commands in mdbook preprocessors"""
def __init__(self, cwd: PurePath | str) -> None:
self._cwd = Path(cwd)
self._environ = os.environ.copy()
self._environ["LC_ALL"] = "C"
class CommandOutput(namedtuple("CommandOutput", ["stdout", "stderr"])):
def __str__(self) -> str:
return self.stdout
def _git(self, commands: list[str] | str) -> CommandOutput:
"""Run a git command
Args:
commands (list[str] | str): commands and args passed to git.
Returns:
CommandOutput: Tuple containing `stdout` and `stderr`
"""
if type(commands) is str:
commands = shlex.split(commands)
proc = subprocess.run(
["git", *commands],
capture_output=True,
text=True,
env=self._environ,
cwd=self._cwd,
)
return self.CommandOutput(stdout=proc.stdout, stderr=proc.stderr)
def log(self, *args: str) -> CommandOutput:
return self._git(["log", *args])

View File

@ -0,0 +1,101 @@
from typing import Any, Dict, List, Optional
class MdChapter:
def __init__(self, data: Dict[str, Any]):
self._data = data
@property
def name(self) -> str:
return self._data["name"]
@name.setter
def name(self, value: str):
self._data["name"] = value
@property
def content(self) -> str:
return self._data["content"]
@content.setter
def content(self, value: str):
self._data["content"] = value
@property
def number(self) -> List[int]:
return self._data["number"]
@number.setter
def number(self, value: List[int]):
self._data["number"] = value
@property
def sub_items(self) -> List[Any]:
return self._data["sub_items"]
@sub_items.setter
def sub_items(self, value: List[Any]):
self._data["sub_items"] = value
@property
def path(self) -> str:
return self._data["path"]
@path.setter
def path(self, value: str):
self._data["path"] = value
@property
def source_path(self) -> str:
return self._data["source_path"]
@source_path.setter
def source_path(self, value: str):
self._data["source_path"] = value
@property
def parent_names(self) -> List[Any]:
return self._data["parent_names"]
@parent_names.setter
def parent_names(self, value: List[Any]):
self._data["parent_names"] = value
class MdSection:
def __init__(self, data: Dict[str, Any]):
self._data = data
@property
def chapter(self) -> Optional[MdChapter]:
if "Chapter" in self._data:
return MdChapter(self._data["Chapter"])
return None
@property
def part_title(self) -> Optional[str]:
return self._data.get("PartTitle")
class MdBook:
def __init__(self, data: Dict[str, Any]):
self._data = data
@property
def sections(self) -> List[MdSection]:
return [MdSection(section) for section in self._data.get("sections", [])]
@sections.setter
def sections(self, value: List[Dict[str, Any]]):
self._data["sections"] = value
@property
def non_exhaustive(self) -> Any:
return self._data["__non_exhaustive"]
@non_exhaustive.setter
def non_exhaustive(self, value: Any):
self._data["__non_exhaustive"] = value
__all__ = ["MdBook", "MdChapter", "MdSection"]

View File

@ -0,0 +1,69 @@
import datetime
import os
from pathlib import Path
from typing import Any, Optional
# Example mdBook context
example_ctx = {
"root": "/var/home/zeglius/Documentos/Github/bazzite_mdbook/docs",
"config": {
"book": {
"authors": ["nicknamenamenick", "Zeglius"],
"language": "en",
"multilingual": False,
"src": "src",
"title": "Bazzite Documentation",
},
"build": {
"build-dir": "book",
"create-missing": False,
"extra-watch-dirs": [],
"use-default-preprocessors": False,
},
"output": {
"html": {
"edit-url-template": "https://github.com/ublue-os/bazzite/edit/main/docs/{path}",
"git-repository-url": "https://github.com/ublue-os/bazzite",
}
},
"preprocessor": {
"links": {},
"youtube-embed": {"command": "python ./preprocessors/youtube-embed.py"},
},
},
"renderer": "html",
"mdbook_version": "0.4.40",
}
class Utils:
@staticmethod
def get_config_from_ctx(preprocessor_name: str, ctx: dict) -> Optional[dict]:
"""Get the config from mdBook context
Returns:
"""
ctx.get("")
return ctx["config"]["preprocessor"][preprocessor_name]
####################### DEBUG UTILS #######################
_DEBUG = os.getenv("DEBUG", "")
_DEBUG_OUTPUT = Path("./debug.txt")
def debug(*obj: object):
"""Dump info into a debug.txt if env var DEBUG=1"""
if _DEBUG in ["1", "yes"]:
with open(_DEBUG_OUTPUT, "+a") as stdout:
print(f"DEBUG[{datetime.date.today()}]:", *obj, file=stdout)
###########################################################
__all__ = ["Utils", "debug"]

View File

@ -0,0 +1,63 @@
__doc__ = """Example of a mdbook preprocessor"""
import json
import sys
from libs.utils import debug
# TODO: This needs to be rewritten
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
"""
return content
###################################################
#
#
#
#
#
#
#
#
#
#
#
#
if __name__ == "__main__":
if len(sys.argv) > 1:
if sys.argv[1] == "supports":
sys.exit(0)
context, book = json.load(sys.stdin)
book: dict[str, list]
context: dict
debug(f"context: {context}")
sections = book["sections"]
for i, section in enumerate(sections):
section: dict
if not section.get("Chapter"):
continue
for chapter in section.values():
chapter: dict
debug(chapter)
content: str = chapter["content"]
if type(content) is str and (res := modify_content(content)):
content = res
chapter.update({"content": content})
debug(book)
print(json.dumps(book))

View File

@ -0,0 +1,109 @@
__doc__ = """Replace urls across the entire book"""
import glob
import json
from pathlib import Path
import sys
from typing import List, cast
from urllib.parse import urljoin, urlparse
from libs.utils import debug as _debug
from libs.types import MdBook
PREPROCESSOR_NAME = "replace-urls"
def debug(*obj):
return _debug("REPLACE-URLS:", *obj)
_IGNORE_STRINGS = [
"before",
"after",
"command",
"renderers",
]
def is_url(url) -> bool:
res: bool = False
try:
tmp = urlparse(url)
res = tmp.netloc != "" and tmp.scheme != ""
except Exception as _:
res = False
return res
def main():
if len(sys.argv) > 1:
if sys.argv[1] == "supports":
sys.exit(0)
context, book = json.load(sys.stdin)
book = MdBook(book)
config = context["config"]["preprocessor"][PREPROCESSOR_NAME]
if not config:
print(json.dumps(book._data))
exit(0)
elif not isinstance(config, dict):
print(json.dumps(book._data))
exit(0)
book_src = cast(str, context["config"]["book"]["src"])
# Prefix to append to replaced urls if output.html.site-url is set and the replacement starts with `/`
try:
site_url_prefix = cast(str, context["config"]["output"]["html"]["site-url"])
except Exception as _:
site_url_prefix = ""
ignore_paths_list_globs = cast(list[str], list(config.get("ignore") or []))
ignore_paths: List[str] = list()
root_dir = Path(context["root"], book_src)
for p in ignore_paths_list_globs:
ignore_paths += glob.glob(p, root_dir=root_dir)
debug("My ignored paths:", ignore_paths)
config_mappings: dict = config["mappings"]
# Get the url mappings
# If replacement starts with `/`, prepend
url_mappings: list[tuple[str, str]] = [
(k, v)
for k, v in config_mappings.items()
if k not in _IGNORE_STRINGS and is_url(k)
]
# Replace the urls
# book_s = json.dumps(book)
# for mapp_old, map_new in url_mappings:
# book_s = book_s.replace(mapp_old, map_new)
for section in book.sections:
if not section.chapter:
debug("Section skipped, was parttitle:", section.part_title)
continue
debug("section.chapter.path =", section.chapter.path)
if section.chapter.path in ignore_paths:
debug("Section skipped, was in ignore_paths:", section.chapter.path)
continue
for old_url, new_url in url_mappings:
if new_url.startswith("/"):
new_url_aux = urljoin(site_url_prefix, new_url.lstrip("/"))
else:
new_url_aux = new_url
section.chapter.content = section.chapter.content.replace(
old_url, new_url_aux
)
print(json.dumps(book._data))
if __name__ == "__main__":
main()

View File

@ -0,0 +1,52 @@
__doc__ = """Transcribe youtube URLS into embededs iframes"""
import json
import re
import sys
from libs.utils import debug
######################## CONFIGURATION PARAMETERS ########################
YOUUTUBE_EMBED_WIDTH = 600
YOUUTUBE_EMBED_HEIGHT = YOUUTUBE_EMBED_WIDTH / (16 / 9)
##########################################################################
YOUTUBE_URL_PATTERN = r"^(?:\s|\t)*(?<!<)https:\/\/(?:www\.youtube\.com\/watch\?v=|youtu\.be\/(?!watch))(?P<id>[a-zA-Z0-9_-]{11})$"
YOUTUBE_EMBED_TEMPLATE = (
f"""<iframe width="{YOUUTUBE_EMBED_WIDTH}" height="{YOUUTUBE_EMBED_HEIGHT}" src="https://www.youtube-nocookie.com/embed/\\g<id>" """
+ """frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" """
+ """referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>"""
)
YOUTUBE_EMBED_TEMPLATE = f"<center>{YOUTUBE_EMBED_TEMPLATE}</center>"
if __name__ == "__main__":
if len(sys.argv) > 1:
if sys.argv[1] == "supports":
sys.exit(0)
context, book = json.load(sys.stdin)
book: dict[str, list]
context: dict
debug(f"context: {context}")
sections = book["sections"]
for i, section in enumerate(sections):
section: dict
if not section.get("Chapter"):
continue
for chapter in section.values():
chapter: dict
debug(chapter)
content: str = chapter["content"]
chapter.update(
{
"content": re.sub(
YOUTUBE_URL_PATTERN, YOUTUBE_EMBED_TEMPLATE, content
)
}
)
debug(book)
print(json.dumps(book))

View File

@ -0,0 +1 @@
<!-- cmdrun fetch_discourse_md.py "https://universal-blue.discourse.group/docs?topic=970" -->

View File

@ -0,0 +1 @@
<!-- cmdrun fetch_discourse_md.py "https://universal-blue.discourse.group/docs?topic=38" -->

View File

@ -0,0 +1 @@
<!-- cmdrun fetch_discourse_md.py "https://universal-blue.discourse.group/docs?topic=161" -->

View File

@ -0,0 +1 @@
See <https://github.com/ublue-os/bazzite/blob/main/README.md>

View File

@ -0,0 +1 @@
<!-- cmdrun fetch_discourse_md.py "https://universal-blue.discourse.group/docs?topic=2656" -->

1
docs/src/Gaming/index.md Normal file
View File

@ -0,0 +1 @@
<!-- cmdrun fetch_discourse_md.py "https://universal-blue.discourse.group/docs?topic=31" -->

View File

@ -0,0 +1 @@
<!-- cmdrun fetch_discourse_md.py "https://universal-blue.discourse.group/docs?topic=38" -->

View File

@ -0,0 +1 @@
<!-- cmdrun fetch_discourse_md.py "https://universal-blue.discourse.group/docs?topic=574" -->

3
docs/src/General/FAQ.md Normal file
View File

@ -0,0 +1,3 @@
{{#title FAQ}}
<!-- cmdrun fetch_discourse_md.py "https://universal-blue.discourse.group/docs?topic=33" -->

View File

@ -0,0 +1 @@
<!-- cmdrun fetch_discourse_md.py "https://universal-blue.discourse.group/docs?topic=1818" -->

View File

@ -0,0 +1 @@
<!-- cmdrun fetch_discourse_md.py "https://universal-blue.discourse.group/docs?topic=1146" -->

View File

@ -0,0 +1 @@
<!-- cmdrun fetch_discourse_md.py "https://universal-blue.discourse.group/docs?topic=1819" -->

View File

@ -0,0 +1 @@
<!-- cmdrun fetch_discourse_md.py "https://universal-blue.discourse.group/docs?topic=1145" -->

View File

@ -0,0 +1 @@
<!-- cmdrun fetch_discourse_md.py "https://universal-blue.discourse.group/docs?topic=1144" -->

View File

@ -0,0 +1 @@
<!-- cmdrun fetch_discourse_md.py "https://universal-blue.discourse.group/docs?topic=1143" -->

View File

@ -0,0 +1,3 @@
{{#title Installation Guide}}
<!-- cmdrun fetch_discourse_md.py "https://universal-blue.discourse.group/docs?topic=30" -->

View File

@ -0,0 +1 @@
<!-- cmdrun fetch_discourse_md.py "https://universal-blue.discourse.group/docs?topic=816" -->

View File

@ -0,0 +1 @@
<!-- cmdrun fetch_discourse_md.py "https://universal-blue.discourse.group/docs?topic=2414" -->

View File

@ -0,0 +1 @@
<!-- cmdrun fetch_discourse_md.py "https://universal-blue.discourse.group/docs?topic=2417" -->

View File

@ -0,0 +1 @@
<!-- cmdrun fetch_discourse_md.py "https://universal-blue.discourse.group/docs?topic=2416" -->

View File

@ -0,0 +1 @@
<!-- cmdrun fetch_discourse_md.py "https://universal-blue.discourse.group/docs?topic=2418" -->

View File

@ -0,0 +1 @@
<!-- cmdrun fetch_discourse_md.py "https://universal-blue.discourse.group/docs?topic=2413" -->

View File

@ -0,0 +1 @@
<!-- cmdrun fetch_discourse_md.py "https://universal-blue.discourse.group/docs?topic=2415" -->

View File

@ -0,0 +1 @@
<!-- cmdrun fetch_discourse_md.py "https://universal-blue.discourse.group/docs?topic=1849" -->

View File

@ -0,0 +1 @@
<!-- cmdrun fetch_discourse_md.py "https://universal-blue.discourse.group/docs?topic=1038" -->

View File

@ -0,0 +1 @@
<!-- cmdrun fetch_discourse_md.py "https://universal-blue.discourse.group/docs?topic=37" -->

View File

@ -0,0 +1 @@
<!-- cmdrun fetch_discourse_md.py "https://universal-blue.discourse.group/docs?topic=2641" -->

View File

@ -0,0 +1 @@
<!-- cmdrun fetch_discourse_md.py "https://universal-blue.discourse.group/docs?topic=2640" -->

View File

@ -0,0 +1 @@
<!-- cmdrun fetch_discourse_md.py "https://universal-blue.discourse.group/docs?topic=2636" -->

View File

@ -0,0 +1 @@
<!-- cmdrun fetch_discourse_md.py "https://universal-blue.discourse.group/docs?topic=2639" -->

View File

@ -0,0 +1 @@
<!-- cmdrun fetch_discourse_md.py "https://universal-blue.discourse.group/docs?topic=36" -->

View File

@ -0,0 +1 @@
<!-- cmdrun fetch_discourse_md.py "https://universal-blue.discourse.group/docs?topic=32" -->

View File

@ -0,0 +1 @@
<!-- cmdrun fetch_discourse_md.py "https://universal-blue.discourse.group/docs?topic=35" -->

View File

@ -0,0 +1 @@
<!-- cmdrun fetch_discourse_md.py "https://universal-blue.discourse.group/docs?topic=2642" -->

View File

@ -0,0 +1 @@
<!-- cmdrun fetch_discourse_md.py "https://universal-blue.discourse.group/docs?topic=2638" -->

3
docs/src/Introduction.md Normal file
View File

@ -0,0 +1,3 @@
{{#title Bazzite Documentation}}
{{#include SUMMARY.md}}

59
docs/src/SUMMARY.md Normal file
View File

@ -0,0 +1,59 @@
<div class="hidden">
[Introduction](Introduction.md)
</div>
# General
- [📜 Bazzite's README](Bazzite_README.md)
- [❓️ FAQ](General/FAQ.md)
- [📖 Installation Guide](General/Installation_Guide/index.md)
- [🖥️ Installing Bazzite for Desktop/Laptop Hardware](General/Installation_Guide/Installing_Bazzite_for_Desktop_or_Laptop_Hardware.md)
- [⚙️ Installing Bazzite for Framework Laptop 16](General/Installation_Guide/Installing_Bazzite_for_Framework_Laptop_16.md)
- [💻️ Installing Bazzite for Framework Laptop 13 (AMD/Intel GPU)](General/Installation_Guide/Installing_Bazzite_Framework_Laptop_13.md)
- [🎮️ Installing Bazzite for Home Theater PC (HTPC) Setups](General/Installation_Guide/Installing_Bazzite_for_HTPC_Setups.md)\*
- [🚂 Installing Bazzite on the Steam Deck](General/Installation_Guide/Installing_Bazzite_for_Steam_Deck.md)\*
- [📟️ Installing Bazzite on Handheld PCs](General/Installation_Guide/Installing_Bazzite_for_Handheld_PCs.md)\*
\* _Indicates that Steam Gaming Mode is intended for this device and ships with the ISO._
- [📝 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)
- [Handheld Wiki](Handheld_and_HTPC_edition/Handheld_Wiki/index.md)
- [Steam Deck](Handheld_and_HTPC_edition/Handheld_Wiki/Steam_Deck.md)
- [Lenovo Legion Go](Handheld_and_HTPC_edition/Handheld_Wiki/Lenovo_Legion_Go.md)
- [ASUS ROG Ally](Handheld_and_HTPC_edition/Handheld_Wiki/ASUS_ROG_Ally.md)
- [Ayn Handhelds](Handheld_and_HTPC_edition/Handheld_Wiki/Ayn_Handhelds.md)
- [GPD Handhelds](Handheld_and_HTPC_edition/Handheld_Wiki/GPD_Handhelds.md)
- [Ayaneo Handhelds](Handheld_and_HTPC_edition/Handheld_Wiki/Ayaneo_Handhelds.md)
- [Other Handhelds](Handheld_and_HTPC_edition/Handheld_Wiki/Other_Handhelds.md)
# Software
- [Installing and Managing Software](Installing_and_Managing_Software/index.md)
- [Flatpak](Installing_and_Managing_Software/Flatpak.md)
- [ujust](Installing_and_Managing_Software/ujust.md)
- [Homebrew](Installing_and_Managing_Software/Homebrew.md)
- [Distrobox](Installing_and_Managing_Software/Distrobox.md)
- [Appimage](Installing_and_Managing_Software/AppImage.md)
- [rpm-ostree](Installing_and_Managing_Software/rpm-ostree.md)
- [Waydroid Setup Guide](Installing_and_Managing_Software/Waydroid_Setup_Guide.md)
- [Tutorials for Installing Other Software](Installing_and_Managing_Software/index.md)
- [Updates, Rollbacks, & Rebasing](Installing_and_Managing_Software/Updates_Rollbacks_&_Rebasing.md)
# Advanced
##### **_Follow the documentation below at your own risk!_**
- [Auto-Mounting Secondary Drives](Advanced/Auto-Mounting_Secondary_Drives.md)
- [Reset User Password](Advanced/Reset_User_Password.md)
- [Contributing to Bazzite](Advanced/Contributing_to_bazzite.md)

BIN
docs/src/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

64
docs/src/favicon.svg Normal file
View File

@ -0,0 +1,64 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="500"
height="500"
viewBox="0 0 500 500"
fill="none"
version="1.1"
id="svg8"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<path
d="M 0,100 C 0,44.7715 44.7715,0 100,0 h 150 c 138.071,0 250,111.929 250,250 v 0 c 0,138.071 -111.929,250 -250,250 v 0 C 111.929,500 0,388.071 0,250 Z"
fill="url(#paint0_linear_1016_105)"
id="path1"
style="fill:url(#paint0_linear_1016_105)" />
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="m 128,0 h 64 V 128 H 326.185 C 382.416,128 428,173.584 428,229.815 428,339.269 339.27,428 229.815,428 173.584,428 128,382.416 128,326.185 V 192 H 0 v -64 h 128 z m 64,192 V 326.185 C 192,347.07 208.93,364 229.815,364 303.923,364 364,303.923 364,229.815 364,208.93 347.07,192 326.185,192 Z"
fill="#ffffff"
fill-opacity="0.5"
id="path2" />
<path
d="M 192,60 C 192,43.4315 178.569,30 162,30 h -4 c -16.569,0 -30,13.4315 -30,30 v 68 H 60 c -16.5685,0 -30,13.431 -30,30 v 4 c 0,16.569 13.4315,30 30,30 h 68 v 68 c 0,16.569 13.431,30 30,30 h 4 c 16.569,0 30,-13.431 30,-30 v -68 h 68 c 16.569,0 30,-13.431 30,-30 v -4 c 0,-16.569 -13.431,-30 -30,-30 h -68 z"
fill="#ffffff"
fill-opacity="0.7"
id="path3" />
<path
d="m 262.5,155.67 c 3.333,1.924 3.333,6.736 0,8.66 l -21,12.124 c -3.333,1.925 -7.5,-0.481 -7.5,-4.33 v -24.248 c 0,-3.849 4.167,-6.255 7.5,-4.33 z"
fill="#ffffff"
id="path4" />
<path
d="m 164.33,262.5 c -1.924,3.333 -6.736,3.333 -8.66,0 l -12.124,-21 c -1.925,-3.333 0.481,-7.5 4.33,-7.5 h 24.248 c 3.849,0 6.255,4.167 4.33,7.5 z"
fill="#ffffff"
id="path5" />
<path
d="m 155.67,57.5 c 1.924,-3.333 6.736,-3.333 8.66,0 l 12.124,21 c 1.925,3.333 -0.481,7.5 -4.33,7.5 h -24.248 c -3.849,0 -6.255,-4.167 -4.33,-7.5 z"
fill="#ffffff"
id="path6" />
<path
d="m 57.5,164.33 c -3.333,-1.924 -3.333,-6.736 0,-8.66 l 21,-12.124 c 3.333,-1.925 7.5,0.481 7.5,4.33 v 24.248 c 0,3.849 -4.167,6.255 -7.5,4.33 z"
fill="#ffffff"
id="path7" />
<defs
id="defs8">
<linearGradient
id="paint0_linear_1016_105"
x1="50"
y1="50"
x2="550"
y2="550"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(-50,-50)">
<stop
offset="0.0684898"
stop-color="#0047AB"
id="stop7" />
<stop
offset="0.741212"
stop-color="#8A2BE2"
id="stop8" />
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

BIN
docs/src/img/AppImage.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

BIN
docs/src/img/BoxBuddy.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
docs/src/img/Commands.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

BIN
docs/src/img/Discover.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 159 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 390 KiB

BIN
docs/src/img/Flatseal.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

BIN
docs/src/img/GRUB_Menu.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

BIN
docs/src/img/Gear_Lever.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 283 KiB

BIN
docs/src/img/Homebrew.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

BIN
docs/src/img/Loki_Max.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 KiB

BIN
docs/src/img/OK.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

BIN
docs/src/img/Overlay.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 KiB

BIN
docs/src/img/RGB.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 KiB

BIN
docs/src/img/ROG_Ally_X.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 250 KiB

BIN
docs/src/img/Reboot.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 399 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

BIN
docs/src/img/TDP.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 KiB

BIN
docs/src/img/Warehouse.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

BIN
docs/src/img/Waydroid.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

BIN
docs/src/img/ally.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 319 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 161 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
docs/src/img/distrobox.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Some files were not shown because too many files have changed in this diff Show More