Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,21 @@ a streamlined variant of the [Keep a Changelog] spec. Notable changes are:

## [2.6.1]

### Added

- `ndg-builder` accepts `evaluatedModules` as an alternative to `rawModules`
when you already have evaluated module output.
- `ndg-builder` forwards `nixosOptionsDoc` options via `optionsDocArgs` and
supports `warningsAreErrors` configuration.
- `ndg-builder-docs` package for generating NDG docs via `ndg-builder`.

### Changed

- `ndg-builder` now writes a config file and invokes NDG with `--config-file`
for consistent CLI configuration.
- Improved default `title` and `description` values for `ndg-builder`
derivations.

### Fixed

- Fixed search index to properly include content from `{=include=}` directives.
Expand Down
41 changes: 38 additions & 3 deletions ndg/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ The primary interface of NDG is the `ndg` CLI utility. There are several
subcommands to handle different documentation tasks.

```console
$ ndg --help
$ ndg --help
NDG: Not a Docs Generator

Usage: ndg [OPTIONS] [COMMAND]
Expand Down Expand Up @@ -855,6 +855,28 @@ complexities at the cost of some performance overhead, and a more limited
interface. In the case your needs are modest, you may be interested in using
this option.

`ndg-builder` returns a derivation that builds your documentation in the Nix
store. You can expose it under `packages.${system}` and build it with
`nix build .#docs`, or use it as an input to other derivations.

Builder options worth knowing:

- `rawModules` and `evaluatedModules` are **mutually exclusive**. Use one or
the other.
- `checkModules`, `moduleArgs`, and `specialArgs` are forwarded into module
evaluation (via `lib.evalModules`).
- `transformOptions` rewrites `options.json` declarations into source links
using `basePath`, `repoPath`, and `moduleName`.
- `variablelistId` controls the ID used for the options list anchor.
- `optionsDocArgs` and `warningsAreErrors` are forwarded to `nixosOptionsDoc`.
- `inputDir = null` means "options-only" docs; the builder still generates
`options.json` and always passes `--module-options` to NDG.
- `generateSearch = true` and `highlightCode = true` are **builder defaults**
even if NDG defaults differ.
- `optionsDepth` maps to `--options-depth` (default `2`).
- `scripts`, `stylesheet`, and `manpageUrls` are forwarded as CLI flags.
- `verbose = true` passes `--verbose` to NDG by default.

```nix
{
inputs = {
Expand All @@ -872,6 +894,9 @@ this option.
inputDir = ./docs;
stylesheet = ./assets/style.css;
scripts = [ ./assets/custom.js ];
generateSearch = true;
highlightCode = true;
optionsDepth = 3;

# For module options
rawModules = [
Expand All @@ -888,13 +913,23 @@ this option.
})
];

# Optional: set the depth of options TOC
optionsDepth = 3;
# Source links for options declarations
moduleName = "myProject";
basePath = ./.;
repoPath = "https://github.com/your-org/your-repo/blob/main";

# Module evaluation knobs
checkModules = true;
specialArgs = { inherit pkgs; };
moduleArgs = { pkgs = pkgs; };
};
};
}
```

If you only want module option docs (no Markdown input), omit `inputDir` and
provide `rawModules` or `evaluatedModules` instead.

#### Manual Approach Using `runCommandLocal`

If you need more control, you can use `runCommandLocal` directly:
Expand Down
55 changes: 55 additions & 0 deletions nix/packages/ndg-builder-docs/package.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
{
pkgs,
ndg-builder,
}:
let
stagedDocs = pkgs.runCommandLocal "ndg-docs-src" {} ''
mkdir -p "$out"
cp -R ${./../../../ndg/docs}/. "$out/"
cp -f ${./../../../ndg/README.md} "$out/index.md"
'';
in
let
docs = ndg-builder.override {
title = "NDG Documentation";
description = "NDG documentation (ndg-builder)";
inputDir = stagedDocs;
rawModules = [];
optionsDepth = 2;
generateSearch = true;
highlightCode = true;
};
in
pkgs.runCommandLocal "ndg-builder-docs" {} ''
mkdir -p "$out/bin"
ln -s ${docs} "$out/docs"

cat > "$out/bin/ndg-builder-docs" <<'EOF'
#!/usr/bin/env sh
set -eu

out_dir="./build"
while [ "$#" -gt 0 ]; do
case "$1" in
-o|--out-dir)
out_dir="$2"
shift 2
;;
--print-path)
echo "${docs}"
exit 0
;;
*)
echo "usage: ndg-builder-docs [--out-dir PATH] [--print-path]" >&2
exit 2
;;
esac
done

mkdir -p "$out_dir"
cp -R "${docs}/." "$out_dir/"
echo "Docs copied to: $out_dir"
EOF

chmod +x "$out/bin/ndg-builder-docs"
''
95 changes: 90 additions & 5 deletions nix/packages/ndg-builder/package.nix
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
pkgs,
lib,
# Build Dependencies
ndg,
Expand All @@ -21,14 +22,80 @@
};
}
],
scrubDerivations ? namePrefix: pkgSet: let
inherit (builtins) isAttrs;
inherit (lib.attrs) mapAttrs optionalAttrs isDerivation;
in
mapAttrs (
name: value: let
wholeName = "${namePrefix}.${name}";
in
if isAttrs value
then
scrubDerivations wholeName value
// optionalAttrs (isDerivation value) {
inherit (value) drvPath;
outPath = "\${${wholeName}}";
}
else value
)
pkgSet,
moduleArgs ? {pkgs = lib.modules.mkForce (scrubDerivations "pkgs" pkgs);},
specialArgs ? {},
evaluatedModules ?
lib.evalModules {
modules = rawModules ++ [{_module.check = checkModules;}];
modules =
rawModules
++ [
{
options._module.args = lib.options.mkOption {
internal = true;
};
config._module = {
check = checkModules;
args = moduleArgs;
};
}
];
inherit specialArgs;
},
warningsAreErrors ? true,
moduleName ? "myModule",
variablelistId ? "${moduleName}-options",
basePath ? ./.,
repoPath ? "https://github.com/username/repo/blob/main",
transformOptions ? opt:
opt
// {
declarations = let
inherit (lib) hasPrefix removePrefix pipe;
basePathStr = toString basePath;
in
map
(decl: let
declStr = toString decl;
in
if hasPrefix basePathStr declStr
then
pipe declStr [
(removePrefix basePathStr)
(removePrefix "/")
(x: {
url = "${repoPath}/${x}";
name = "<${moduleName}/${x}>";
})
]
else if decl == "lib/modules.nix"
then {
url = "https://github.com/NixOS/nixpkgs/blob/master/${decl}";
name = "<nixpkgs/lib/modules.nix>";
}
else decl)
opt.declarations;
},
# Builder configuration
title ? "My Option Documentation",
title ? "Site created by NDG",
description ? "Generate static site docs of nix options",
optionsDocArgs ? {},
scripts ? [],
inputDir ? null,
Expand All @@ -37,6 +104,7 @@
manpageUrls ? null,
optionsDepth ? 2,
generateSearch ? true,
highlightCode ? true,
} @ args: let
inherit (lib.asserts) assertMsg;
in
Expand All @@ -47,16 +115,32 @@ in

configJSON =
(nixosOptionsDoc (
(removeAttrs optionsDocArgs ["options"])
{inherit transformOptions warningsAreErrors variablelistId;}
// (removeAttrs optionsDocArgs ["options"])
// {inherit (evaluatedModules) options;}
))
.optionsJSON;
in
runCommandLocal "ndg-builder" {nativeBuildInputs = [ndg];} (
runCommandLocal "ndg-builder" {
nativeBuildInputs = [ndg];
meta = {inherit description;};
} (
''
mkdir -p $out
config_path="$TMPDIR/ndg-builder.toml"
{
echo "output_dir = \"$out\""
''
+ optionalString (inputDir != null) ''
echo "input_dir = \"${toString inputDir}\""
''
+ optionalString (inputDir == null) ''
echo "module_options = \"${configJSON}/share/doc/nixos/options.json\""
''
+ ''
} > "$config_path"

ndg ${optionalString verbose "--verbose"} html \
ndg --config-file "$config_path" ${optionalString verbose "--verbose"} html \
--jobs $NIX_BUILD_CORES --output-dir "$out" --title "${title}" \
--module-options "${configJSON}/share/doc/nixos/options.json" \
''
Expand All @@ -65,5 +149,6 @@ in
+ optionalString (inputDir != null) ''--input-dir ${inputDir} \''
+ optionalString (manpageUrls != null) ''--manpage-urls ${manpageUrls} \''
+ optionalString generateSearch ''--generate-search \''
+ optionalString highlightCode ''--highlight-code \''
+ "--options-depth ${toString optionsDepth}"
)
41 changes: 41 additions & 0 deletions nix/packages/ndg-docs/package.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
pkgs,
ndg,
}:
pkgs.writeShellApplication {
name = "ndg-docs";
runtimeInputs = [
ndg
pkgs.cargo
pkgs.rustc
pkgs.clang
pkgs.llvmPackages.lld
];

text = ''
set -euo pipefail

if [ ! -f .github/ndg.toml ]; then
echo "error: run from repository root (missing .github/ndg.toml)" >&2
exit 1
fi

# Stage docs into a temp dir so the repo stays unchanged.
tmpdir=$(mktemp -d)
trap 'rm -rf "$tmpdir"' EXIT
mkdir -p "$tmpdir/docs"
cp -R ./ndg/docs/. "$tmpdir/docs/"
cp -f ./ndg/README.md "$tmpdir/docs/index.md"

extra_flags=()
if rustc -V | grep -q "nightly"; then
extra_flags+=("-Zunstable-options" "-Zrustdoc-scrape-examples")
fi

cargo doc --workspace --exclude xtask --no-deps --document-private-items "''${extra_flags[@]}"

ndg --config-file .github/ndg.toml html --input-dir "$tmpdir/docs"

echo "Docs generated: ./build (NDG HTML), ./target/doc (Rustdoc)"
'';
}
Loading