feat: documentation generation

This commit is contained in:
Sk7Str1p3 2026-04-19 22:58:59 +03:00
parent 9aba1ea72d
commit 01f701cb1b
No known key found for this signature in database
GPG key ID: 4DD995933D06D43B
5 changed files with 160 additions and 0 deletions

5
docs/book.toml Normal file
View file

@ -0,0 +1,5 @@
[book]
title = "SkyOS Documentation"
authors = ["Sk7Str1p3"]
description = "Documentation for Sk7Str1p3's custom NixOS configuration"
language = "en"

29
docs/default.nix Normal file
View file

@ -0,0 +1,29 @@
# Documentation
/**
Docs are generated from comments in `.nix` files.
This results in kind of weird config format, but
makes it easier to track configuration changes
and add/remove docs as required.
## How docs are generated
`nixdoc` utility enables us to generate documentation
from comments in `.nix` file, like `doxygen` and `rustdoc` do.
`nixdoc` requires this flags:
- category (derived from file's path)
- description (derived from file's first line if it's commented)
most hard part is to generate SUMMARY.md.
generator uses orderKey of type "{num}|{mdPath}" and derives indentation from path's depth,
so chapters have proper order.
run `nix build .#docBuild` to build documentation
*/
{
perSystem =
{ pkgs, ... }:
rec {
packages.docBuild = pkgs.callPackage ../docs/docgen.nix { };
};
}

122
docs/docgen.nix Normal file
View file

@ -0,0 +1,122 @@
{
stdenvNoCC,
mdbook,
nixdoc,
lib,
}:
stdenvNoCC.mkDerivation {
name = "SkyOS-book";
src = ./.;
buildInputs = [
mdbook
nixdoc
];
patchPhase =
let
excluded = [
".*flake\\.nix$"
"docs/docgen.nix"
];
shouldExclude = relPath: lib.any (pattern: builtins.match pattern relPath != null) excluded;
nixFiles =
with lib.fileset;
let
allFiles = toList (fileFilter (f: f.hasExt "nix") ../.);
in
lib.filter (
file:
let
relPath = lib.removePrefix (toString ../. + "/") (toString file);
in
!shouldExclude relPath
) allFiles;
chapters = lib.sort (a: b: a.sortKey < b.sortKey) (
map (
file:
let
relPath = lib.removePrefix (toString ../. + "/") (toString file);
mdPath =
(
if baseNameOf file == "default.nix" then
lib.removeSuffix "/" (dirOf relPath)
else
lib.removeSuffix ".nix" relPath
)
+ ".md";
orderMap = {
docs = 0;
flake = 1;
devShells = 2;
};
order = orderMap.${lib.head (lib.splitString "/" relPath)};
category = lib.removeSuffix ".md" (lib.replaceStrings [ "/" ] [ "." ] mdPath);
title =
let
head = builtins.head (lib.splitString "\n" (builtins.readFile file));
in
if builtins.match "^# (.*)" head != null then
lib.trim (lib.removePrefix "#" head)
else
lib.removeSuffix ".nix" (baseNameOf file);
depth =
let
dirPart = dirOf mdPath;
in
if dirPart == "." then 0 else lib.length (lib.splitString "/" dirPart);
indent = lib.concatStringsSep "" (lib.genList (x: " ") depth);
in
{
script = ''
mkdir -p "src/${dirOf mdPath}"
nixdoc \
--prefix "" \
--category "${category}" \
--description "${title}" \
--anchor-prefix "" \
--file "${file}" > "src/${mdPath}"
'';
summaryLine = "${indent}- [${title}](${mdPath})";
sortKey = builtins.toString order + mdPath;
}
) nixFiles
);
summaryContent =
"# Summary\n\n"
+ "[Introduction](README.md)\n"
+ builtins.concatStringsSep "\n" (map (c: c.summaryLine) chapters)
+ "\n";
nixdocScripts = builtins.concatStringsSep "\n" (map (c: c.script) chapters);
in
''
cp ${../README.md} src/README.md
cp -r ${../assets} src/assets
cp src/assets/logo.png theme/favicon.png
${nixdocScripts}
cat > src/SUMMARY.md <<EOF
${summaryContent}
EOF
'';
buildPhase = ''
runHook preBuild
mdbook build
runHook postBuild
'';
postBuild = ''
mkdir -p $out
cp -r book/* $out
'';
}

3
docs/src/404.md Normal file
View file

@ -0,0 +1,3 @@
# 404((
This URL is invalid, sorry.