Skip to content

docs: experimental re-write #2884

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
11 changes: 8 additions & 3 deletions docs/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,13 @@ let
# The following pkgs attrs are required to eval nixvim, even for the docs:
inherit (pkgs)
_type
callPackage
formats
runCommand
runCommandLocal
stdenv
stdenvNoCC
symlinkJoin
runCommand
runCommandLocal
writeShellApplication
;
}
Expand Down Expand Up @@ -122,7 +124,10 @@ lib.fix (
# > sandbox-exec: pattern serialization length 69298 exceeds maximum (65535)
docs = pkgs.callPackage ./mdbook {
inherit evaledModules transformOptions;
inherit (self) search;
inherit (self) search beta-docs;
};

# Beta docs
beta-docs = evaledModules.config.docs.html.site;
}
)
12 changes: 12 additions & 0 deletions docs/mdbook/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
nixosOptionsDoc,
transformOptions,
search,
beta-docs,
# The root directory of the site
baseHref ? "/",
# A list of all available docs that should be linked to
Expand Down Expand Up @@ -375,6 +376,10 @@ pkgs.stdenv.mkDerivation (finalAttrs: {
cp -r ./book/* $dest
mkdir -p $dest/search
cp -r ${finalAttrs.passthru.search}/* $dest/search

# Also build the beta docs
mkdir -p $dest/beta
cp -r ${finalAttrs.passthru.beta-docs}/* $dest/beta
'';

inherit baseHref;
Expand Down Expand Up @@ -406,6 +411,11 @@ pkgs.stdenv.mkDerivation (finalAttrs: {
search = search.override {
baseHref = finalAttrs.baseHref + "search/";
};
beta-docs = beta-docs.override (old: {
settings = lib.recursiveUpdate old.settings {
output.html.site-url = "${baseHref}/beta";
};
});
docs-versions =
runCommand "docs-versions"
{
Expand Down Expand Up @@ -435,6 +445,8 @@ pkgs.stdenv.mkDerivation (finalAttrs: {

echo "- The $link, for use with nixpkgs \`$nixpkgs\`$suffix" >> "$out"
done
# link to beta-docs
echo "- The [beta-docs](./beta), for use with "
'';
user-configs = callPackage ../user-configs { };
};
Expand Down
31 changes: 31 additions & 0 deletions lib/plugins/utils.nix
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,24 @@
{ options, ... }:
let
opts = lib.getAttrFromPath loc options;
docsfile = lib.concatStringsSep "/" loc;
url =
if args.url or null == null then
opts.package.default.meta.homepage or (throw "unable to get URL for `${lib.showOption loc}`.")
else
args.url;
maintainersString =
let
toMD = m: if m ? github then "[${m.name}](https://github.com/${m.github})" else m.name;
names = builtins.map toMD (lib.unique maintainers);
count = builtins.length names;
in
if count == 1 then
builtins.head names
else if count == 2 then
lib.concatStringsSep " and " names
else
lib.concatMapStrings (name: "\n- ${name}") names;
in
{
meta = {
Expand All @@ -110,5 +123,23 @@
path = loc;
};
};

docs.pages.${docsfile}.text = lib.mkMerge (
[
"# ${lib.last loc}"
""
"**URL:** [${url}](${url})"
""
]
++ lib.optionals (maintainers != [ ]) [
"**Maintainers:** ${maintainersString}"
""
]
++ lib.optionals (description != null && description != "") [
"---"
""
description
]
);
};
}
7 changes: 6 additions & 1 deletion modules/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
# using this in a submodule nested within another nixvim config.
{
imports = [
./docs
./misc
./autocmd.nix
./clipboard.nix
./colorscheme.nix
./commands.nix
./diagnostics.nix
./doc.nix
./editorconfig.nix
./files.nix
./filetype.nix
Expand All @@ -23,4 +23,9 @@
./performance.nix
./plugins.nix
];

docs.optionPages.options = {
enable = true;
optionScopes = [ ];
};
}
8 changes: 0 additions & 8 deletions modules/doc.nix

This file was deleted.

74 changes: 74 additions & 0 deletions modules/docs/_utils.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
{ lib, ... }:
let
transformOption =
let
root = builtins.toString ../../.;
mkGitHubDeclaration = user: repo: branch: subpath: {
url = "https://github.com/${user}/${repo}/blob/${branch}/${subpath}";
name = "<${repo}/${subpath}>";
};
transformDeclaration =
decl:
if lib.hasPrefix root (builtins.toString decl) then
mkGitHubDeclaration "nix-community" "nixvim" "main" (
lib.removePrefix "/" (lib.strings.removePrefix root (builtins.toString decl))
)
else if decl == "lib/modules.nix" then
mkGitHubDeclaration "NixOS" "nixpkgs" "master" decl
else
decl;
in
opt: opt // { declarations = builtins.map transformDeclaration opt.declarations; };
in
{
options.docs._utils = lib.mkOption {
type = with lib.types; lazyAttrsOf raw;
description = "internal utils, modules, functions, etc";
default = { };
internal = true;
visible = false;
};

config.docs._utils = {
/**
Uses `lib.optionAttrSetToDocList` to produce a list of docs-options.

A doc-option has the following attrs, as expected by `nixos-render-docs`:

```
{
loc,
name, # rendered with `showOption loc`
description,
declarations,
internal,
visible, # normalised to a boolean
readOnly,
type, # normalised to `type.description`
default,? # rendered with `lib.options.renderOptionValue`
example,? # rendered with `lib.options.renderOptionValue`
relatedPackages,?
}
```

Additionally, sub-options are recursively flattened into the list,
unless `visible == "shallow"` or `visible == false`.

This function extends `lib.optionAttrSetToDocList` by also filtering out
invisible and internal options, and by applying Nixvim's `transformOption`
function.

The implementation is based on `pkgs.nixosOptionsDoc`:
https://github.com/NixOS/nixpkgs/blob/e2078ef3/nixos/lib/make-options-doc/default.nix#L117-L126
*/
mkOptionList = lib.flip lib.pipe [
(lib.flip builtins.removeAttrs [ "_module" ])
lib.optionAttrSetToDocList
(builtins.map transformOption)
(builtins.filter (opt: opt.visible && !opt.internal))
# TODO: consider supporting `relatedPackages`
# See https://github.com/NixOS/nixpkgs/blob/61235d44/lib/options.nix#L103-L104
# and https://github.com/NixOS/nixpkgs/blob/61235d44/nixos/lib/make-options-doc/default.nix#L128-L165
];
};
}
27 changes: 27 additions & 0 deletions modules/docs/collect-sources.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
lib,
runCommandLocal,
pages,
}:
# Implementation based on NixOS's /etc module
runCommandLocal "docs-sources" { } ''
set -euo pipefail

makeEntry() {
src="$1"
target="$2"
mkdir -p "$out/$(dirname "$target")"
cp "$src" "$out/$target"
}

mkdir -p "$out"
${lib.concatMapStringsSep "\n" (
{ target, source, ... }:
lib.escapeShellArgs [
"makeEntry"
# Force local source paths to be added to the store
"${source}"
target
]
) pages}
''
45 changes: 45 additions & 0 deletions modules/docs/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{ lib, pkgs, ... }:
let
# Convert links relative to github -> relative to docs
fixLinks = pkgs.callPackage ../../docs/fix-links { };
in
{
options.enableMan = lib.mkOption {
type = lib.types.bool;
default = true;
description = "Install the man pages for NixVim options.";
};

imports = [
./_utils.nix
./mdbook
./menu
./option-pages
./pages.nix
./platforms.nix
./user-guide
];

config.docs = {
pages."" = {
menu.section = "header";
menu.location = [ "Home" ];
source = pkgs.callPackage ./readme.nix {
inherit fixLinks;
# TODO: get `availableVersions` and `baseHref` from module options
};
};
pages.contributing = {
menu.section = "footer";
menu.location = [ "Contributing" ];
source = fixLinks ../../CONTRIBUTING.md;
};
optionPages.docs = {
optionScopes = [ "docs" ];
page.menu.location = [ "docs" ];
page.text = ''
Internal options used to construct these docs.
'';
};
};
}
50 changes: 50 additions & 0 deletions modules/docs/mdbook/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
{
lib,
config,
pkgs,
...
}:
let
settingsFormat = pkgs.formats.toml { };
defaultSettings = {
book = {
language = "en";
multilingual = false;
title = "nixvim docs";
};
build.create-missing = false;
output.html.site-url = "/";
output.html.fold = {
enable = true;
level = 0;
};
preprocessor.alerts = { };
};
in
{
options.docs.html = {
site = lib.mkOption {
type = lib.types.package;
description = "HTML docs rendered by mdbook.";
readOnly = true;
};
settings = lib.mkOption {
inherit (settingsFormat) type;
description = ''
Freeform settings written to `book.toml`.

See MDBook's [Configuration](https://rust-lang.github.io/mdBook/format/configuration/index.html) docs.
'';
defaultText = defaultSettings;
};
};
config.docs.html = {
site = pkgs.callPackage ./package.nix {
inherit (config.docs) src;
inherit (config.docs.html) settings;
menu = config.docs.menu.src;
writeTOML = settingsFormat.generate;
};
settings = defaultSettings;
};
}
33 changes: 33 additions & 0 deletions modules/docs/mdbook/package.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
mdbook,
mdbook-alerts,
runCommand,
writeTOML,
menu,
settings,
src,
}:
runCommand "html-docs"
{
inherit src;

nativeBuildInputs = [
mdbook
mdbook-alerts
];

settings = writeTOML "book.toml" settings;
menu = builtins.toFile "menu.md" (builtins.unsafeDiscardStringContext menu);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A comment would be nice to say what is discarded, I guess the why is that docs are "inert"?

Copy link
Member Author

@MattSturgeon MattSturgeon Feb 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I copied this from the nixos docs impl, and there was no comment to copy. I'll try come up with something.

However, yeah "string context" is how nix keeps track of a string's dependencies. E.g. if you do "${pkgs.hello}/bin/hello" then that string has some "context" so that nix knows it has a dependency on the pkgs.hello derivation.

Using unsafeDiscardStringContext drops that context, so unsafeDiscardStringContext "${pkgs.hello}/bin/hello" would have the same string value, but without the dependency on building the pkgs.hello derivation.

In the context of the docs, I believe this is mainly relevant for the "declared by" links, and maybe any default or example values that accidentally used a derivation in its value. I.e. we want the string value, but we don't want the dependency.

}
''
mkdir src
for input in $src/*; do
name=$(basename "$input")
ln -s "$input" "src/$name"
done
ln -s $settings book.toml
ln -s $menu src/SUMMARY.md

# Build the website
mdbook build --dest-dir $out
''
Loading