docs: overhaul reference documentation pipeline

- use nixosOptionsDoc commonMark output
- simplify a lot of things
- redesign towards a future generic standalon nixosOptionsWebsite function
This commit is contained in:
DavHau 2024-04-04 14:57:30 +07:00
parent 26a6c3a340
commit 2fc4ef33cc
36 changed files with 315 additions and 698 deletions

View File

@ -57,6 +57,24 @@
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1692799911,
"narHash": "sha256-3eihraek4qL744EvQXsK1Ha6C3CR7nnT8X2qWap4RNk=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "f9e7cf818399d17d347f847525c5a5a8032e4e44",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_2": {
"inputs": {
"systems": "systems_2"
},
"locked": {
"lastModified": 1689068808,
"narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=",
@ -71,7 +89,61 @@
"type": "github"
}
},
"mdbook-toc": {
"inputs": {
"flake-utils": "flake-utils",
"naersk": "naersk",
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1712225484,
"narHash": "sha256-hofT/8DVI6XFYsHdsN6qInks4xrS7R1nIkDtEdJe4c0=",
"owner": "DavHau",
"repo": "mdbook-toc",
"rev": "1aff15c55de1ee6127291d9891eaf25c9fda13c2",
"type": "github"
},
"original": {
"owner": "DavHau",
"repo": "mdbook-toc",
"type": "github"
}
},
"naersk": {
"inputs": {
"nixpkgs": "nixpkgs"
},
"locked": {
"lastModified": 1692351612,
"narHash": "sha256-KTGonidcdaLadRnv9KFgwSMh1ZbXoR/OBmPjeNMhFwU=",
"owner": "nix-community",
"repo": "naersk",
"rev": "78789c30d64dea2396c9da516bbcc8db3a475207",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "naersk",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1692808169,
"narHash": "sha256-x9Opq06rIiwdwGeK2Ykj69dNc2IvUH1fY55Wm7atwrE=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "9201b5ff357e781bf014d0330d18555695df7ba8",
"type": "github"
},
"original": {
"id": "nixpkgs",
"type": "indirect"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1711624657,
"narHash": "sha256-IViG6BKCJY/I6oRNfAANf/QitYylepQSCzgam0TF+bs=",
@ -88,7 +160,7 @@
},
"pre-commit-hooks": {
"inputs": {
"flake-utils": "flake-utils",
"flake-utils": "flake-utils_2",
"nixpkgs": [
"nixpkgs"
]
@ -112,7 +184,8 @@
"devshell": "devshell",
"flake-compat": "flake-compat",
"flake-parts": "flake-parts",
"nixpkgs": "nixpkgs",
"mdbook-toc": "mdbook-toc",
"nixpkgs": "nixpkgs_2",
"pre-commit-hooks": "pre-commit-hooks"
}
},
@ -130,6 +203,21 @@
"repo": "default",
"type": "github"
}
},
"systems_2": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
"root": "root",

View File

@ -15,6 +15,10 @@
flake-compat.url = "github:nix-community/flake-compat/pull/4/head";
flake-compat.flake = false;
# TODO: remove once merged: https://github.com/badboy/mdbook-toc/pull/52
mdbook-toc.url = "github:DavHau/mdbook-toc";
mdbook-toc.inputs.nixpkgs.follows = "nixpkgs";
pre-commit-hooks.url = "github:cachix/pre-commit-hooks.nix";
pre-commit-hooks.inputs.nixpkgs.follows = "nixpkgs";

View File

@ -0,0 +1,200 @@
{
self,
inputs,
...
}: {
perSystem = {
pkgs,
lib,
system,
...
}: let
modules' = self.modules.dream2nix;
modules = lib.filterAttrs (name: _: ! lib.elem name excludes) modules';
dream2nixRoot = ../../../.;
dream2nix = import dream2nixRoot;
excludes = [
# NOT WORKING
# TODO: fix those
"core"
"ui"
"docs"
"assertions"
"nixpkgs-overrides"
# doesn't need to be rendered
"_template"
];
public = lib.genAttrs [
"nodejs-granular-v3"
"nodejs-package-lock-v3"
"php-composer-lock"
"php-granular"
"pip"
"rust-cargo-lock"
"rust-crane"
] (name: null);
# interface
sourcePathStr = toString dream2nix;
baseUrl = "https://github.com/nix-community/dream2nix/blob/master";
specialArgs = {
inherit dream2nix;
packageSets.nixpkgs = pkgs;
};
transformOptions = opt:
opt
// {
declarations =
map
(
decl: let
subpath = lib.removePrefix sourcePathStr (toString decl);
in {
url = baseUrl + subpath;
name = "dream2nix" + subpath;
}
)
opt.declarations;
};
# 0 = no chapters, 1 = one level of chapters, 2 = two levels of chapters ...
chaptersNesting = 1;
# A tree where nodes are (sub)chapters and leafs are options.
# Nesting can be arbitrary
chaptersTree = {
"Modules" =
lib.filterAttrs (name: _: public ? ${name}) optionsTree;
"Modules (Internal + Experimental)" =
lib.filterAttrs (name: _: ! public ? ${name}) optionsTree;
};
optionsTree = lib.flip lib.mapAttrs modules (
name: module: let
evaluated = lib.evalModules {
inherit specialArgs;
modules = [module];
};
in
# lib.trace "Rendering Module ${name}"
(builtins.removeAttrs evaluated.options ["_module"])
);
# implementation
highlight-js = let
highlight-core = pkgs.fetchurl {
url = "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js";
hash = "sha256-g3pvpbDHNrUrveKythkPMF2j/J7UFoHbUyFQcFe1yEY=";
};
highlight-nix = pkgs.fetchurl {
url = "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/nix.min.js";
hash = "sha256-BLoZ+/OroDAxMsdZ4GFZtQfsg6ZJeLVNeBzN/82dYgk=";
};
in
pkgs.runCommand "highlight-js" {} ''
cat ${highlight-core} > $out
cat ${highlight-nix} >> $out
'';
highlight-style = pkgs.fetchurl {
url = "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/vs.min.css";
hash = "sha256-E1kfafj5iO+Tw/04hxdSG+OnvczojOXK2K0iCEYfzSw=";
};
optionsToMdFile = options: let
docs = pkgs.nixosOptionsDoc {
inherit options;
inherit transformOptions;
warningsAreErrors = false;
};
in
docs.optionsCommonMark;
mdFiles = nesting: chapters:
if nesting == 0
then lib.mapAttrs (name: optionsToMdFile) chapters
else lib.concatMapAttrs (name: mdFiles (nesting - 1)) chapters;
mdFilesDir = pkgs.runCommand "md-files-dir" {} ''
mkdir -p $out
cp -r ${lib.concatStringsSep "\n cp -r " (lib.mapAttrsToList (name: file: "${file} $out/${name}.md") (mdFiles chaptersNesting chaptersTree))}
'';
spacing = depth:
if depth == 0
then "- "
else " " + spacing (depth - 1);
# returns "" for chapters with nesting or an md file for chapters with options
chapterUrl = nesting: name:
if nesting == 0
then "options/${name}.md"
else "";
renderChapters = depth: nesting: chapters:
lib.concatStringsSep "\n"
(lib.flip lib.mapAttrsToList chapters (
name: chapter:
"${spacing depth}[${name}](${chapterUrl nesting name})"
+ lib.optionalString (nesting > 0) (renderChapters (depth + 1) (nesting - 1) chapter)
));
summaryMdFile =
pkgs.writeText "summary.md"
(renderChapters 0 chaptersNesting chaptersTree);
mdBookSource = pkgs.runCommand "website-src" {} ''
mkdir -p $out/options
cp ${summaryMdFile} $out/SUMMARY.md
cp -r ${mdFilesDir}/* $out/options/
# add table of contents for each md file
for file in $out/options/*.md; do
name="$(basename "$file")"
name="''${name%.md}"
echo "# $name - options" > "$file.tmp"
echo '<!-- toc -->' | cat - "$file" >> "$file.tmp"
mv $file.tmp $file
done
'';
website =
pkgs.runCommand "website" {
nativeBuildInputs = [
pkgs.mdbook
pkgs.mdbook-linkcheck
# This inserts a table of contents at each '<!-- toc -->'
inputs.mdbook-toc.defaultPackage.${system}
];
} ''
cp -rL --no-preserve=mode ${dream2nixRoot}/website/* ./
cp -r ${mdBookSource}/* src/
# insert highlight.js
cp ${highlight-js} ./src/highlight.js
cp ${highlight-style} ./src/highlight.css
# merge original and generated SUMMARY.md
cp ${dream2nixRoot}/website/src/SUMMARY.md SUMMARY.md.orig
{
while read ln; do
case "$ln" in
"# Modules Reference")
echo "# Modules Reference"
cat ${mdBookSource}/SUMMARY.md
;;
*)
echo "$ln"
;;
esac
done
} < SUMMARY.md.orig > src/SUMMARY.md
# insert icon
mkdir -p ./theme
cp ${../../../modules/dream2nix/core/docs/theme/favicon.png} ./theme/favicon.png
${pkgs.mdbook}/bin/mdbook build --dest-dir out
mv out/html $out
'';
in {
packages.website = website;
packages.docs-generated-mdbook-src = mdBookSource;
};
}

View File

@ -1,67 +0,0 @@
{
self,
lib,
...
}: {
imports = [
./render
./site
];
perSystem = {
config,
self',
inputs',
pkgs,
...
}: let
excludes = [
# NOT WORKING
# TODO: fix those
"core"
"ui"
"docs"
"assertions"
"nixpkgs-overrides"
# doesn't need to be rendered
"_template"
];
public = lib.genAttrs [
"nodejs-granular-v3"
"nodejs-package-lock-v3"
"php-composer-lock"
"php-granular"
"pip"
"rust-cargo-lock"
"rust-crane"
] (name: null);
in {
render.inputs =
lib.flip lib.mapAttrs
(lib.filterAttrs
(name: module:
! (lib.elem name excludes))
(self.modules.dream2nix))
(name: module: {
inherit module;
title = name;
sourcePath = self;
attributePath = [
"dream2nix"
"modules"
"dream2nix"
(lib.strings.escapeNixIdentifier name)
];
intro =
if lib.pathExists ../dream2nix/${name}/README.md
then lib.readFile ../dream2nix/${name}/README.md
else "";
baseUrl = "https://github.com/nix-community/dream2nix/blob/master";
separateEval = true;
chapter =
if public ? ${name}
then "Modules"
else "Modules (Internal + Experimental)";
});
};
}

View File

@ -1,439 +0,0 @@
{
config,
inputs,
lib,
flake-parts-lib,
self,
...
}: let
inherit
(lib)
mkOption
types
concatMap
concatLists
mapAttrsToList
attrValues
hasPrefix
removePrefix
;
failPkgAttr = name: _v:
throw ''
Most nixpkgs attributes are not supported when generating documentation.
Please check with `--show-trace` to see which option leads to this `pkgs.${lib.strings.escapeNixIdentifier name}` reference. Often it can be cut short with a `defaultText` argument to `lib.mkOption`, or by escaping an option `example` using `lib.literalExpression`.
'';
in {
options.perSystem = flake-parts-lib.mkPerSystemOption ({
config,
pkgs,
lib,
...
}: let
cfg = config.render;
pkgsStub = lib.mapAttrs failPkgAttr pkgs;
fixups = {
lib,
flake-parts-lib,
...
}: {
options.perSystem = flake-parts-lib.mkPerSystemOption {
config = {
_module.args.pkgs =
pkgsStub
// {
_type = "pkgs";
inherit lib;
formats =
lib.mapAttrs
(
formatName: formatFn: formatArgs: let
result = formatFn formatArgs;
stubs =
lib.mapAttrs
(
name: _:
throw "The attribute `(pkgs.formats.${lib.strings.escapeNixIdentifier formatName} x).${lib.strings.escapeNixIdentifier name}` is not supported during documentation generation. Please check with `--show-trace` to see which option leads to this `${lib.strings.escapeNixIdentifier name}` reference. Often it can be cut short with a `defaultText` argument to `lib.mkOption`, or by escaping an option `example` using `lib.literalExpression`."
)
result;
in
stubs
// {
inherit (result) type;
}
)
pkgs.formats;
};
};
};
};
eval = evalWith {
modules = concatLists (mapAttrsToList (name: inputCfg: [inputCfg.module]) cfg.inputs);
};
evalWith = {modules}:
lib.evalModules {
modules =
modules
++ [
# {
# name = "dummy-name";
# version = "dummy-version";
# }
];
specialArgs.dream2nix =
# trace website modules
# lib.trace modules
self;
specialArgs.packageSets.nixpkgs = pkgs;
};
# inputs.flake-parts.lib.evalFlakeModule
# {
# inputs = {
# inherit (inputs) nixpkgs;
# self =
# eval.config.flake
# // {
# outPath =
# throw "The `self.outPath` attribute is not available when generating documentation, because the documentation should not depend on the specifics of the flake files where it is loaded. This error is generally caused by a missing `defaultText` on one or more options in the trace. Please run this evaluation with `--show-trace`, and look for `while evaluating the default value of option` and add a `defaultText` to one or more of the options involved.";
# };
# };
# }
# {
# imports =
# modules
# ++ [
# fixups
# ];
# systems = [(throw "The `systems` option value is not available when generating documentation. This is generally caused by a missing `defaultText` on one or more options in the trace. Please run this evaluation with `--show-trace`, look for `while evaluating the default value of option` and add a `defaultText` to the one or more of the options involved.")];
# };
opts = eval.options;
# coreOptDecls = config.render.inputs.flake-parts._nixosOptionsDoc.optionsNix;
filterTransformOptions = {
sourceName,
sourcePath,
baseUrl,
module,
# coreOptDecls,
}: let
sourcePathStr = toString sourcePath;
moduleDir =
if ! lib.isPath module
then throw "module must be a string"
else if lib.hasSuffix ".nix" module
then builtins.dirOf module
else module;
# get the topLevel option names by inspecting the interface.nix
interfaceModuleFile = moduleDir + "/interface.nix";
interfaceModule = import interfaceModuleFile;
# call module with fake args just to get the top-level options
interface = interfaceModule (
(
lib.functionArgs interfaceModule
)
// {inherit lib;}
);
topLevelOptions =
if lib.pathExists interfaceModuleFile
then interface.options
else {};
in
opt: let
declarations =
concatMap
(
decl: let
subpath = removePrefix sourcePathStr (toString decl);
in [
{
url = baseUrl + subpath;
name = "dream2nix" + subpath;
}
]
)
opt.declarations;
in
opt // {inherit declarations;};
inputModule = {
config,
name,
...
}: {
options = {
module = mkOption {
type = types.raw;
description = ''
A Module.
'';
};
sourcePath = mkOption {
type = types.path;
description = ''
Source path in which the modules are contained.
'';
};
title = mkOption {
type = types.str;
description = ''
Title of the markdown page.
'';
default = name;
};
flakeRef = mkOption {
type = types.str;
default =
# This only works for github for now, but we can set a non-default
# value in the list just fine.
let
match = builtins.match "https://github.com/([^/]*)/([^/]*)/blob/([^/]*)" config.baseUrl;
owner = lib.elemAt match 0;
repo = lib.elemAt match 1;
branch = lib.elemAt match 2; # ignored for now because they're all default branches
in
if match != null
then "github:${owner}/${repo}"
else throw "Couldn't figure out flakeref for ${name}: ${config.baseUrl}";
};
preface = mkOption {
type = types.str;
description = ''
Stuff between the title and the options.
'';
default = ''
${config.intro}
${config.installation}
'';
};
intro = mkOption {
type = types.str;
description = ''
Introductory paragraph between title and installation.
'';
};
installationDeclareInput = mkOption {
type = types.bool;
description = ''
Whether to show how to declare the input.
'';
default = true;
};
installation = mkOption {
type = types.str;
description = ''
Paragraph between import and options.
'';
default = ''
## Import
To import this module into your dream2nix package:
```nix
imports = [
${lib.concatMapStringsSep "." lib.strings.escapeNixIdentifier config.attributePath}
];
```
'';
};
sourceName = mkOption {
type = types.str;
description = ''
Name by which the source is shown in the list of declarations.
'';
default = name;
};
baseUrl = mkOption {
type = types.str;
description = ''
URL prefix for source location links.
'';
};
attributePath = mkOption {
type = types.listOf types.str;
description = ''
Flake output attribute path to import.
'';
default = ["flakeModule"];
};
rendered = mkOption {
type = types.package;
description = ''
Built Markdown docs.
'';
readOnly = true;
};
_nixosOptionsDoc = mkOption {};
separateEval = mkOption {
type = types.bool;
default = false;
description = ''
Whether to include this in the main evaluation.
'';
};
filterTransformOptions = mkOption {
default = filterTransformOptions;
description = ''
Function to customize the set of options to render for this input.
'';
};
killLinks = mkOption {
type = types.bool;
default = false;
description = ''
Remove local anchor links, a workaround for proper {option}`` support in the doc tooling.
'';
};
chapter = mkOption {
type = types.str;
default = "Chapter";
description = ''
Name of the chapter to put this modules docs in.
'';
};
};
config = {
_nixosOptionsDoc = pkgs.nixosOptionsDoc {
options =
if config.separateEval
then
(evalWith {
modules = [config.module];
})
.options
else opts;
documentType = "none";
transformOptions = config.filterTransformOptions {
inherit (config) sourceName baseUrl sourcePath module;
# inherit coreOptDecls;
};
warningsAreErrors = false; # not sure if feasible long term
markdownByDefault = true;
};
rendered =
pkgs.runCommand "option-doc-${config.sourceName}"
{
nativeBuildInputs = [pkgs.libxslt.bin pkgs.pandoc];
inputDoc = config._nixosOptionsDoc.optionsDocBook;
inherit (config) title preface;
} ''
xsltproc --stringparam title "$title" \
--stringparam killLinks '${lib.boolToString config.killLinks}' \
-o options.db.xml ${./options.xsl} \
"$inputDoc"
mkdir $out
pandoc --verbose --from docbook --to html options.db.xml >options.html
substitute options.html $out/options.html --replace '<p>@intro@</p>' "$preface"
grep -v '@intro@' <$out/options.html >/dev/null || {
grep '@intro@' <$out/options.html
echo intro replacement failed; exit 1;
}
'';
};
};
in {
options = {
render = {
inputs = mkOption {
description = "Which modules to render.";
type = types.attrsOf (types.submodule inputModule);
};
};
generated-docs = mkOption {
type = types.raw;
description = "Generated documentation.";
readOnly = true;
};
};
config = {
generated-docs =
lib.mapAttrs' (name: inputCfg: {
name = "generated-docs-${name}";
value = inputCfg.rendered;
})
cfg.inputs
// {
# generate markdown file like:
# Summary
# - [Reference Documentation]()
# - [core (built in)](./options/core.md)
generated-summary-md = let
chapters = lib.zipAttrs (
lib.mapAttrsToList
(name: inputCfg: {
${inputCfg.chapter} = inputCfg // {inherit name;};
})
cfg.inputs
);
in
pkgs.writeText "SUMMARY.md" ''
${
lib.concatStringsSep "\n"
(
lib.flatten (
lib.mapAttrsToList
(
chapter: inputs:
[" - [${chapter}]()"]
++ (map
(inputCfg: " - [${inputCfg.sourceName}](./options/${inputCfg.name}.md)")
inputs)
)
chapters
)
)
}
'';
generated-docs =
pkgs.runCommand "generated-docs"
{
passthru = {
inherit config;
inherit eval;
# This won't be in sync with the actual nixosOptionsDoc
# invocations, but it's useful for troubleshooting.
allOptionsPerhaps =
(pkgs.nixosOptionsDoc {
options = opts;
})
.optionsNix;
};
}
''
mkdir $out
${
lib.concatStringsSep "\n"
(lib.mapAttrsToList
(name: inputCfg: ''
cp ${inputCfg.rendered}/options.html $out/${name}.html
'')
cfg.inputs)
}
'';
};
};
});
}

View File

@ -1,66 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
version="1.0"
xmlns="http://docbook.org/ns/docbook"
xmlns:db="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="db:link">
<xsl:choose>
<xsl:when test="$killLinks = 'true'">
<xsl:copy-of select="./node()"/>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="."/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="db:variablelist">
<chapter>
<title>
<xsl:value-of select="$title"/>
</title>
<para>@intro@</para>
<section><title>Options</title>
<xsl:for-each select="db:varlistentry">
<para><link xlink:href="#{db:term/@xml:id}"><xsl:copy-of select="db:term/db:option"/></link></para>
</xsl:for-each>
</section>
<xsl:apply-templates />
</chapter>
</xsl:template>
<xsl:template match="db:varlistentry">
<section>
<title>
<link xlink:href="#{db:term/@xml:id}" xml:id="{db:term/@xml:id}"><xsl:copy-of select="db:term/db:option"/></link>
</title>
<xsl:apply-templates select="db:listitem/*"/>
</section>
</xsl:template>
<!-- Pandoc doesn't like block-level simplelist -->
<!-- https://github.com/jgm/pandoc/issues/8086 -->
<xsl:template match="db:simplelist">
<para>
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</para>
</xsl:template>
<!-- Turn filename tags with href attrs into explicit links -->
<xsl:template match="db:filename">
<link xlink:href="{@xlink:href}">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</link>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>

View File

@ -1 +0,0 @@
book

View File

@ -1 +0,0 @@
/getting-things.html /cheat-sheet.html

View File

@ -1,119 +0,0 @@
{
inputs,
self,
...
}: {
perSystem = {
config,
self',
inputs',
pkgs,
lib,
system,
...
}: let
highlight-js = let
highlight-core = pkgs.fetchurl {
url = "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js";
hash = "sha256-g3pvpbDHNrUrveKythkPMF2j/J7UFoHbUyFQcFe1yEY=";
};
highlight-nix = pkgs.fetchurl {
url = "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/nix.min.js";
hash = "sha256-BLoZ+/OroDAxMsdZ4GFZtQfsg6ZJeLVNeBzN/82dYgk=";
};
in
pkgs.runCommand "highlight-js" {} ''
cat ${highlight-core} > $out
cat ${highlight-nix} >> $out
'';
highlight-style = pkgs.fetchurl {
url = "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/vs.min.css";
hash = "sha256-E1kfafj5iO+Tw/04hxdSG+OnvczojOXK2K0iCEYfzSw=";
};
in {
/*
Check the links, including anchors (not currently supported by mdbook)
Putting this in a separate check has the benefits that
- output can always be inspect with browser
- this slow check (1 minute) is not part of the iteration cycle
Ideally https://github.com/linkchecker/linkchecker/pull/661 is merged
upstream, so that it's quick and can run often without blocking the
iteration cycle unnecessarily.
*/
# checks.linkcheck =
# pkgs.runCommand "linkcheck"
# {
# nativeBuildInputs = [pkgs.linkchecker pkgs.python3];
# site = config.packages.website;
# } ''
# # https://linkchecker.github.io/linkchecker/man/linkcheckerrc.html
# cat >>$TMPDIR/linkcheckrc <<EOF
# [checking]
# threads=100
# [AnchorCheck]
# EOF
# echo Checking $site
# linkchecker -f $TMPDIR/linkcheckrc $site/
# touch $out
# '';
packages = lib.optionalAttrs (system == "x86_64-linux") {
website = pkgs.stdenvNoCC.mkDerivation {
name = "website";
nativeBuildInputs = [pkgs.mdbook pkgs.mdbook-linkcheck];
src = ./.;
buildPhase = ''
runHook preBuild
rm ./src/intro.md
cp ${../../../../README.md} ./src/intro.md
# insert highlight.js
cp ${highlight-js} ./src/highlight.js
cp ${highlight-style} ./src/highlight.css
# insert the generated part of the summary into the origin SUMMARY.md
cp ./src/SUMMARY.md SUMMARY.md.orig
{
while read ln; do
case "$ln" in
"# Modules Reference")
echo "# Modules Reference"
cat ${config.generated-docs.generated-summary-md}
;;
*)
echo "$ln"
;;
esac
done
} < SUMMARY.md.orig > src/SUMMARY.md
mkdir -p ./theme
cp ${../../../dream2nix/core/docs/theme/favicon.png} ./theme/favicon.png
mkdir -p src/options
for f in ${config.generated-docs.generated-docs}/*.html; do
cp "$f" "src/options/$(basename "$f" .html).md"
done
mdbook build --dest-dir $TMPDIR/out
cp -r $TMPDIR/out/html $out
cp _redirects $out
# TODO: point to something else than public.html
echo '<html><head><script>window.location.pathname = window.location.pathname.replace(/options.html$/, "") + "options/public.html"</script></head><body><a href="options/public.html">to the options</a></body></html>' \
>$out/options.html
runHook postBuild
'';
dontInstall = true;
};
};
};
}

View File

@ -1 +0,0 @@
../../../../README.md

10
website/README.md Normal file
View File

@ -0,0 +1,10 @@
# Website
This directory contains markdown pages under ./src which are rendered to an html website using the tool mdbook.
The website can be built via:
```shellSession
$ nix build .#website
```
In addition to what's already in ./src, this derivation generates and inserts reference documentation pages. One for each dream2nix module in /modules/dream2nix.

View File

@ -8,12 +8,16 @@ title = "dream2nix"
[output.html]
git-repository-url = "https://github.com/nix-community/dream2nix"
edit-url-template = "https://github.com/nix-community/dream2nix/edit/main/modules/dream2nix/{path}"
additional-js = [ "no-edit-options.js" ]
additional-css = [ "flake-parts.css" ]
no-section-label = true
additional-css = [ "style.css" ]
additional-js = [ "no-edit-options.js" ]
[output.html.print]
enable = false # big single page; don't need that
[output.linkcheck]
follow-web-links = false # no Internet during the build
[preprocessor.toc]
command = "mdbook-toc"
renderer = ["html"]

1
website/src/intro.md Symbolic link
View File

@ -0,0 +1 @@
../../README.md

View File

@ -25,3 +25,7 @@ h1.menu-title::before {
background-color: #1d1f21;
}
}
/* prevents chapters without links to be grey */
.chapter li {
color: #000;
}