diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index bbf61959..49183147 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -17,3 +17,9 @@ jobs: nix run .#fmt nix run .#lint git diff --exit-code + - name: Check mdbook-admonish changes are not committed + run: | + if grep -q "do not edit: managed by \`mdbook-admonish install\`" docs/book.toml; then + echo "remove generated mdbook-admonish lines from docs/books.toml" >&2 + exit 1 + fi diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..0baf0152 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/_site diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 00000000..5b2a6158 --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1,7 @@ +book + +# generated by the build script +src/README.md +src/modules.md +src/options.md +mdbook-admonish.css diff --git a/docs/book.toml b/docs/book.toml new file mode 100644 index 00000000..61c7d18f --- /dev/null +++ b/docs/book.toml @@ -0,0 +1,17 @@ +[book] +title = "nixfiles" +authors = ["Michael Walker (barrucadu)"] +description = "My NixOS configuration and assorted other crap, powered by flakes." +language = "en" +multilingual = false + +[build] +create-missing = false + +[output.html] +git-repository-url = "https://github.com/barrucadu/nixfiles" +cname = "nixfiles.docs.barrucadu.co.uk" + +[preprocessor.admonish] +on_failure = "bail" +command = "mdbook-admonish" diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md new file mode 100644 index 00000000..bd2aa934 --- /dev/null +++ b/docs/src/SUMMARY.md @@ -0,0 +1,8 @@ +# Summary + +- [README](./README.md) + +# Reference + +- [Modules](./modules.md) +- [Options](./options.md) diff --git a/flake.nix b/flake.nix index b42d0ea5..a719182d 100644 --- a/flake.nix +++ b/flake.nix @@ -89,7 +89,7 @@ ${pkgs.lib.fileContents ./scripts/secrets.sh} ''; - option-docs = + documentation = let eval = pkgs.lib.evalModules { modules = [ @@ -115,15 +115,11 @@ warningsAreErrors = false; }; in - mkApp "options-json" '' - case "$1" in - "json") - cat ${optionsDoc.optionsJSON}/share/doc/nixos/options.json - ;; - *) - cat ${optionsDoc.optionsCommonMark} - ;; - esac + mkApp "documentation" '' + PATH=${with pkgs; lib.makeBinPath [ coreutils mdbook mdbook-admonish python3 ]} + export NIXOS_OPTIONS_JSON="${optionsDoc.optionsJSON}/share/doc/nixos/options.json" + + ${pkgs.lib.fileContents ./scripts/documentation.sh} ''; }; }; diff --git a/scripts/documentation.sh b/scripts/documentation.sh new file mode 100644 index 00000000..a9c518fc --- /dev/null +++ b/scripts/documentation.sh @@ -0,0 +1,82 @@ +set -e + +pushd docs +mdbook-admonish install +popd + +cp README.markdown docs/src/README.md + +python3 - <<'EOF' > docs/src/modules.md +import json +import os + +print("# Modules") +print("") + +with open(os.getenv("NIXOS_OPTIONS_JSON"), "r") as f: + options = json.load(f) + +modules = {} +for key, defn in options.items(): + module_name = defn["declarations"][0].split("/shared/")[1].replace("/options.nix", "") + if module_name == "options.nix": + # this is the top-level `shared` file + module_name = "" + modules.setdefault(module_name, []).append(key) + +for module in sorted(modules.keys()): + module_name = "<shared>" if module == "" else module + source_file = f"shared/{module}/default.nix".replace("//", "/") + + print(f"## {module_name}") + + print(f"\n**Description:**") + has_doc = False + with open(source_file, "r") as f: + for line in f: + if line.startswith("# "): + has_doc = True + print(line[2:].strip()) + else: + break + if not has_doc: + print("This module has no description.") + + print("\n**Options:**\n") + for option in modules[module]: + anchor = "".join(c for c in option if c.isalpha() or c == "-") + print(f"- [`{option}`](./options.md#{anchor})") + print(f"\n**Declared in:** [{source_file}](https://github.com/barrucadu/nixfiles/blob/master/{source_file})") + print("") +EOF + +python3 - <<'EOF' > docs/src/options.md +import json +import os + +print("# Options") +print("") + +with open(os.getenv("NIXOS_OPTIONS_JSON"), "r") as f: + options = json.load(f) + +for option in sorted(options.keys()): + defn = options[option] + option_name = option.replace("*", "\\*").replace("<", "<").replace(">", ">") + source_file = "shared/" + defn["declarations"][0].split("/shared/")[1] + + print(f"## {option_name}") + print(f"\n**Description:** {defn['description']}") + print(f"\n**Type:** `{defn['type']}`") + if "default" in defn: + print(f"\n**Default:** `{defn['default']['text']}`") + print(f"\n**Declared in:** [{source_file}](https://github.com/barrucadu/nixfiles/blob/master/{source_file})") + print("") +EOF + +mdbook build docs +mv docs/book _site + +chmod -c -R +rX _site | while read -r line; do + echo "::warning title=Invalid file permissions automatically fixed::$line" +done