b3f686995f
We make use of the -O man=… option of mandoc(1) which allows to convert cross references via the .Xr macro into actual hyperlinks in the output. This can be disabled (by passing "none") or done in two modes: * all: links all .Xr cross references as if they were in $out/%N.%S.html. This will lead to broken links of course. * inManDir: only link to files in $out if the man page is found in manDir, use the template defined in linkXrFallback if not. all is the default, since we don't require all man pages to be in manDir, so it would be potentially confusing if the path attribute was used in the pages list. linkXrFallback uses the debian online man viewer by default currently, since it can be decently hyperlinked and debian has a lot of packages. Other options would be: * https://manpages.ubuntu.com/manpages/latest/en/man%S/%N.%S.html * https://man.archlinux.org/man/%N.%S.en * https://man.openbsd.org/%N.%S * https://www.man7.org/linux/man-pages/man%S/%N.%S.html Change-Id: I1363b9dfdda25cb7383c7310b8115c335444bd3d Reviewed-on: https://cl.tvl.fyi/c/depot/+/2597 Tested-by: BuildkiteCI Reviewed-by: sterni <sternenseemann@systemli.org>
234 lines
6.2 KiB
Nix
234 lines
6.2 KiB
Nix
{ depot, lib, pkgs, ... }:
|
|
|
|
let
|
|
inherit (depot.nix)
|
|
getBins
|
|
runExecline
|
|
yants
|
|
;
|
|
|
|
inherit (depot.tools)
|
|
cheddar
|
|
;
|
|
|
|
inherit (pkgs)
|
|
mandoc
|
|
coreutils
|
|
fetchurl
|
|
writers
|
|
;
|
|
|
|
bins = getBins cheddar [ "cheddar" ]
|
|
// getBins mandoc [ "mandoc" ]
|
|
// getBins coreutils [ "cat" "mv" "mkdir" ]
|
|
;
|
|
|
|
normalizeDrv = fetchurl {
|
|
url = "https://necolas.github.io/normalize.css/8.0.1/normalize.css";
|
|
sha256 = "04jmvybwh2ks4dlnfa70sb3a3z3ig4cv0ya9rizjvm140xq1h22q";
|
|
};
|
|
|
|
execlineStdoutInto = target: line: [
|
|
"redirfd" "-w" "1" target
|
|
] ++ line;
|
|
|
|
# I will not write a pure nix markdown renderer
|
|
# I will not write a pure nix markdown renderer
|
|
# I will not write a pure nix markdown renderer
|
|
# I will not write a pure nix markdown renderer
|
|
# I will not write a pure nix markdown renderer
|
|
markdown = md:
|
|
let
|
|
html = runExecline.local "rendered-markdown" {
|
|
stdin = md;
|
|
} ([
|
|
"importas" "-iu" "out" "out"
|
|
] ++ execlineStdoutInto "$out" [
|
|
bins.cheddar "--about-filter" "description.md"
|
|
]);
|
|
in builtins.readFile html;
|
|
|
|
indexTemplate = { title, description, pages ? [] }: ''
|
|
<!doctype html>
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<title>${title}</title>
|
|
<link rel="stylesheet" type="text/css" href="style.css"/>
|
|
</head>
|
|
<body>
|
|
<div class="index-text">
|
|
<h1>${title}</h1>
|
|
${markdown description}
|
|
<h2>man pages</h2>
|
|
<ul>
|
|
${lib.concatMapStrings ({ name, section, ... }: ''
|
|
<li><a href="${name}.${toString section}.html">${name}(${toString section})</a></li>
|
|
'') pages}
|
|
</ul>
|
|
</div>
|
|
</body>
|
|
</html>
|
|
'';
|
|
|
|
defaultStyle = import ./defaultStyle.nix { };
|
|
|
|
# This deploy script automatically copies the build result into
|
|
# a TARGET directory and marks it as writeable optionally.
|
|
# It is exposed as the deploy attribute of the result of
|
|
# htmlman, so an htmlman expression can be used like this:
|
|
# nix-build -A deploy htmlman.nix && ./result target_dir
|
|
deployScript = title: drv: writers.writeDash "deploy-${title}" ''
|
|
usage() {
|
|
printf 'Usage: %s [-w] TARGET\n\n' "$0"
|
|
printf 'Deploy htmlman documentation to TARGET directory.\n\n'
|
|
printf ' -h Display this help message\n'
|
|
printf ' -w Make TARGET directory writeable\n'
|
|
}
|
|
|
|
if test "$#" -lt 1; then
|
|
usage
|
|
exit 100
|
|
fi
|
|
|
|
writeable=false
|
|
|
|
while test "$#" -gt 0; do
|
|
case "$1" in
|
|
-h)
|
|
usage
|
|
exit 0
|
|
;;
|
|
-w)
|
|
writeable=true
|
|
;;
|
|
-*)
|
|
usage
|
|
exit 100
|
|
;;
|
|
*)
|
|
if test -z "$target"; then
|
|
target="$1"
|
|
else
|
|
echo "Too many arguments"
|
|
exit 100
|
|
fi
|
|
;;
|
|
esac
|
|
|
|
shift
|
|
done
|
|
|
|
if test -z "$target"; then
|
|
echo "Missing TARGET"
|
|
usage
|
|
exit 100
|
|
fi
|
|
|
|
set -ex
|
|
|
|
mkdir -p "$target"
|
|
cp -RTL --reflink=auto "${drv}" "$target"
|
|
|
|
if $writeable; then
|
|
chmod -R +w "$target"
|
|
fi
|
|
'';
|
|
|
|
htmlman =
|
|
{ title
|
|
# title of the index page
|
|
, description ? ""
|
|
# description which is displayed after
|
|
# the main heading on the index page
|
|
, pages ? []
|
|
# man pages of the following structure:
|
|
# {
|
|
# name : string;
|
|
# section : int;
|
|
# path : either path string;
|
|
# }
|
|
# path is optional, if it is not given,
|
|
# the man page source must be located at
|
|
# "${manDir}/${name}.${toString section}"
|
|
, manDir ? null
|
|
# directory in which man page sources are located
|
|
, style ? defaultStyle
|
|
# CSS to use as a string
|
|
, normalizeCss ? true
|
|
# whether to include normalize.css before the custom CSS
|
|
, linkXr ? "all"
|
|
# How to handle cross references in the html output:
|
|
#
|
|
# * none: don't convert cross references into hyperlinks
|
|
# * all: link all cross references as if they were
|
|
# rendered into $out by htmlman
|
|
# * inManDir: link to all man pages which have their source
|
|
# in `manDir` and use the format string defined
|
|
# in linkXrFallback for all other cross references.
|
|
, linkXrFallback ? "https://manpages.debian.org/unstable/%N.%S.en.html"
|
|
# fallback link to use if linkXr == "inManDir" and the man
|
|
# page is not in ${manDir}. Placeholders %N (name of page)
|
|
# and %S (section of page) can be used. See mandoc(1) for
|
|
# more information.
|
|
}:
|
|
|
|
let
|
|
linkXrEnum = yants.enum "linkXr" [ "all" "inManDir" "none" ];
|
|
|
|
index = indexTemplate {
|
|
inherit title description pages;
|
|
};
|
|
|
|
resolvePath = { path ? null, name, section }:
|
|
if path != null
|
|
then path
|
|
else "${manDir}/${name}.${toString section}";
|
|
|
|
mandocOpts = lib.concatStringsSep "," ([
|
|
"style=style.css"
|
|
] ++ linkXrEnum.match linkXr {
|
|
all = [ "man=./%N.%S.html" ];
|
|
inManDir = [ "man=./%N.%S.html;${linkXrFallback}" ];
|
|
none = [ ];
|
|
});
|
|
|
|
html =
|
|
runExecline.local "htmlman-${title}" {
|
|
derivationArgs = {
|
|
inherit index style;
|
|
passAsFile = [ "index" "style" ];
|
|
};
|
|
} ([
|
|
"multisubstitute" [
|
|
"importas" "-iu" "out" "out"
|
|
"importas" "-iu" "index" "indexPath"
|
|
"importas" "-iu" "style" "stylePath"
|
|
]
|
|
"if" [ bins.mkdir "-p" "$out" ]
|
|
"if" [ bins.mv "$index" "\${out}/index.html" ]
|
|
"if" (execlineStdoutInto "\${out}/style.css" [
|
|
"if" ([
|
|
bins.cat
|
|
] ++ lib.optional normalizeCss normalizeDrv
|
|
++ [
|
|
"$style"
|
|
])
|
|
])
|
|
# let mandoc check for available man pages
|
|
"execline-cd" "${manDir}"
|
|
] ++ lib.concatMap ({ name, section, ... }@p:
|
|
execlineStdoutInto "\${out}/${name}.${toString section}.html" [
|
|
"if" [
|
|
bins.mandoc
|
|
"-mdoc"
|
|
"-T" "html"
|
|
"-O" mandocOpts
|
|
(resolvePath p)
|
|
]
|
|
]) pages);
|
|
in html // {
|
|
deploy = deployScript title html;
|
|
};
|
|
in
|
|
htmlman
|