diff options
| author | Daiderd Jordan <daiderd@gmail.com> | 2019-05-04 15:36:05 +0200 |
|---|---|---|
| committer | Daiderd Jordan <daiderd@gmail.com> | 2019-05-04 15:38:01 +0200 |
| commit | b85b9a4206a1d556d1d12babb35dc3887a6bdc58 (patch) | |
| tree | c8ade5ab8c5050500f9667047750919ca12dcdd3 /doc | |
| parent | 631fd857aa2bbceaa5376f84a837db5e4cf0990d (diff) | |
doc: add manual build for module options
Diffstat (limited to 'doc')
| -rw-r--r-- | doc/manual/default.nix | 344 | ||||
| -rw-r--r-- | doc/manual/man-pages.xml | 42 | ||||
| -rw-r--r-- | doc/manual/manual.xml | 21 | ||||
| -rw-r--r-- | doc/manual/options-to-docbook.xsl | 229 | ||||
| -rw-r--r-- | doc/manual/overrides.css | 9 | ||||
| -rw-r--r-- | doc/manual/postprocess-option-descriptions.xsl | 115 | ||||
| -rw-r--r-- | doc/manual/style.css | 291 |
7 files changed, 1051 insertions, 0 deletions
diff --git a/doc/manual/default.nix b/doc/manual/default.nix new file mode 100644 index 0000000..b5bdf6f --- /dev/null +++ b/doc/manual/default.nix @@ -0,0 +1,344 @@ +{ pkgs, options, config, version, revision, extraSources ? [] }: + +with pkgs; + +let + lib = pkgs.lib; + + # Remove invisible and internal options. + optionsListVisible = lib.filter (opt: opt.visible && !opt.internal) (lib.optionAttrSetToDocList options); + + # Replace functions by the string <function> + substFunction = x: + if builtins.isAttrs x then lib.mapAttrs (name: substFunction) x + else if builtins.isList x then map substFunction x + else if lib.isFunction x then "<function>" + else x; + + # Generate DocBook documentation for a list of packages. This is + # what `relatedPackages` option of `mkOption` from + # ../../../lib/options.nix influences. + # + # Each element of `relatedPackages` can be either + # - a string: that will be interpreted as an attribute name from `pkgs`, + # - a list: that will be interpreted as an attribute path from `pkgs`, + # - an attrset: that can specify `name`, `path`, `package`, `comment` + # (either of `name`, `path` is required, the rest are optional). + genRelatedPackages = packages: + let + unpack = p: if lib.isString p then { name = p; } + else if lib.isList p then { path = p; } + else p; + describe = args: + let + title = args.title or null; + name = args.name or (lib.concatStringsSep "." args.path); + path = args.path or [ args.name ]; + package = args.package or (lib.attrByPath path (throw "Invalid package attribute path `${toString path}'") pkgs); + in "<listitem>" + + "<para><literal>${lib.optionalString (title != null) "${title} aka "}pkgs.${name} (${package.meta.name})</literal>" + + lib.optionalString (!package.meta.available) " <emphasis>[UNAVAILABLE]</emphasis>" + + ": ${package.meta.description or "???"}.</para>" + + lib.optionalString (args ? comment) "\n<para>${args.comment}</para>" + # Lots of `longDescription's break DocBook, so we just wrap them into <programlisting> + + lib.optionalString (package.meta ? longDescription) "\n<programlisting>${package.meta.longDescription}</programlisting>" + + "</listitem>"; + in "<itemizedlist>${lib.concatStringsSep "\n" (map (p: describe (unpack p)) packages)}</itemizedlist>"; + + optionsListDesc = lib.flip map optionsListVisible (opt: opt // { + # Clean up declaration sites to not refer to the NixOS source tree. + declarations = map stripAnyPrefixes opt.declarations; + } + // lib.optionalAttrs (opt ? example) { example = substFunction opt.example; } + // lib.optionalAttrs (opt ? default) { default = substFunction opt.default; } + // lib.optionalAttrs (opt ? type) { type = substFunction opt.type; } + // lib.optionalAttrs (opt ? relatedPackages && opt.relatedPackages != []) { relatedPackages = genRelatedPackages opt.relatedPackages; }); + + # We need to strip references to /nix/store/* from options, + # including any `extraSources` if some modules came from elsewhere, + # or else the build will fail. + # + # E.g. if some `options` came from modules in ${pkgs.customModules}/nix, + # you'd need to include `extraSources = [ pkgs.customModules ]` + prefixesToStrip = map (p: "${toString p}/") ([ ../../.. ] ++ extraSources); + stripAnyPrefixes = lib.flip (lib.fold lib.removePrefix) prefixesToStrip; + + # Custom "less" that pushes up all the things ending in ".enable*" + # and ".package*" + optionLess = a: b: + let + ise = lib.hasPrefix "enable"; + isp = lib.hasPrefix "package"; + cmp = lib.splitByAndCompare ise lib.compare + (lib.splitByAndCompare isp lib.compare lib.compare); + in lib.compareLists cmp a.loc b.loc < 0; + + # Customly sort option list for the man page. + optionsList = lib.sort optionLess optionsListDesc; + + # Convert the list of options into an XML file. + optionsXML = builtins.toFile "options.xml" (builtins.toXML optionsList); + + optionsDocBook = runCommand "options-db.xml" {} '' + optionsXML=${optionsXML} + if grep /darwin/modules $optionsXML; then + echo "The manual appears to depend on the location of Darwin, which is bad" + echo "since this prevents sharing via a channel. This is typically" + echo "caused by an option default that refers to a relative path (see above" + echo "for hints about the offending path)." + exit 1 + fi + ${buildPackages.libxslt.bin}/bin/xsltproc \ + --stringparam revision '${revision}' \ + -o intermediate.xml ${./options-to-docbook.xsl} $optionsXML + ${buildPackages.libxslt.bin}/bin/xsltproc \ + -o "$out" ${./postprocess-option-descriptions.xsl} intermediate.xml + ''; + + sources = lib.sourceFilesBySuffices ./. [".xml"]; + + modulesDoc = builtins.toFile "modules.xml" '' + <section xmlns:xi="http://www.w3.org/2001/XInclude" id="modules"> + ${(lib.concatMapStrings (path: '' + <xi:include href="${path}" /> + '') (lib.catAttrs "value" (config.meta.doc or [])))} + </section> + ''; + + generatedSources = runCommand "generated-docbook" {} '' + mkdir $out + ln -s ${modulesDoc} $out/modules.xml + ln -s ${optionsDocBook} $out/options-db.xml + printf "%s" "${version}" > $out/version + ''; + + copySources = + '' + cp -prd $sources/* . || true + ln -s ${generatedSources} ./generated + chmod -R u+w . + ''; + + toc = builtins.toFile "toc.xml" + '' + <toc role="chunk-toc"> + <d:tocentry xmlns:d="http://docbook.org/ns/docbook" linkend="book-darwin-manual"><?dbhtml filename="index.html"?> + <d:tocentry linkend="ch-options"><?dbhtml filename="options.html"?></d:tocentry> + <d:tocentry linkend="ch-release-notes"><?dbhtml filename="release-notes.html"?></d:tocentry> + </d:tocentry> + </toc> + ''; + + manualXsltprocOptions = toString [ + "--param section.autolabel 1" + "--param section.label.includes.component.label 1" + "--stringparam html.stylesheet 'style.css overrides.css highlightjs/mono-blue.css'" + "--stringparam html.script './highlightjs/highlight.pack.js ./highlightjs/loader.js'" + "--param xref.with.number.and.title 1" + "--param toc.section.depth 3" + "--stringparam admon.style ''" + "--stringparam callout.graphics.extension .svg" + "--stringparam current.docid manual" + "--param chunk.section.depth 0" + "--param chunk.first.sections 1" + "--param use.id.as.filename 1" + "--stringparam generate.toc 'book toc appendix toc'" + "--stringparam chunk.toc ${toc}" + ]; + + manual-combined = runCommand "darwin-manual-combined" + { inherit sources; + nativeBuildInputs = [ buildPackages.libxml2.bin buildPackages.libxslt.bin ]; + meta.description = "The NixOS manual as plain docbook XML"; + } + '' + ${copySources} + + xmllint --xinclude --output ./manual-combined.xml ./manual.xml + xmllint --xinclude --noxincludenode \ + --output ./man-pages-combined.xml ./man-pages.xml + + # outputs the context of an xmllint error output + # LEN lines around the failing line are printed + function context { + # length of context + local LEN=6 + # lines to print before error line + local BEFORE=4 + + # xmllint output lines are: + # file.xml:1234: there was an error on line 1234 + while IFS=':' read -r file line rest; do + echo + if [[ -n "$rest" ]]; then + echo "$file:$line:$rest" + local FROM=$(($line>$BEFORE ? $line - $BEFORE : 1)) + # number lines & filter context + nl --body-numbering=a "$file" | sed -n "$FROM,+$LEN p" + else + if [[ -n "$line" ]]; then + echo "$file:$line" + else + echo "$file" + fi + fi + done + } + + function lintrng { + xmllint --debug --noout --nonet \ + --relaxng ${docbook5}/xml/rng/docbook/docbook.rng \ + "$1" \ + 2>&1 | context 1>&2 + # ^ redirect assumes xmllint doesn’t print to stdout + } + + lintrng manual-combined.xml + lintrng man-pages-combined.xml + + mkdir $out + cp manual-combined.xml $out/ + cp man-pages-combined.xml $out/ + ''; + + olinkDB = runCommand "manual-olinkdb" + { inherit sources; + nativeBuildInputs = [ buildPackages.libxml2.bin buildPackages.libxslt.bin ]; + } + '' + xsltproc \ + ${manualXsltprocOptions} \ + --stringparam collect.xref.targets only \ + --stringparam targets.filename "$out/manual.db" \ + --nonet \ + ${docbook_xsl_ns}/xml/xsl/docbook/xhtml/chunktoc.xsl \ + ${manual-combined}/manual-combined.xml + + cat > "$out/olinkdb.xml" <<EOF + <?xml version="1.0" encoding="utf-8"?> + <!DOCTYPE targetset SYSTEM + "file://${docbook_xsl_ns}/xml/xsl/docbook/common/targetdatabase.dtd" [ + <!ENTITY manualtargets SYSTEM "file://$out/manual.db"> + ]> + <targetset> + <targetsetinfo> + Allows for cross-referencing olinks between the manpages + and manual. + </targetsetinfo> + + <document targetdoc="manual">&manualtargets;</document> + </targetset> + EOF + ''; + +in rec { + inherit generatedSources; + + # The NixOS options in JSON format. + optionsJSON = runCommand "options-json" + { meta.description = "List of NixOS options in JSON format"; + } + '' + # Export list of options in different format. + dst=$out/share/doc/darwin + mkdir -p $dst + + cp ${builtins.toFile "options.json" (builtins.unsafeDiscardStringContext (builtins.toJSON + (builtins.listToAttrs (map (o: { name = o.name; value = removeAttrs o ["name" "visible" "internal"]; }) optionsList)))) + } $dst/options.json + + mkdir -p $out/nix-support + echo "file json $dst/options.json" >> $out/nix-support/hydra-build-products + ''; # */ + + # Generate the NixOS manual. + manualHTML = runCommand "darwin-manual-html" + { inherit sources; + nativeBuildInputs = [ buildPackages.libxml2.bin buildPackages.libxslt.bin ]; + meta.description = "The Darwin manual in HTML format"; + allowedReferences = ["out"]; + } + '' + # Generate the HTML manual. + dst=$out/share/doc/darwin + mkdir -p $dst + xsltproc \ + ${manualXsltprocOptions} \ + --stringparam target.database.document "${olinkDB}/olinkdb.xml" \ + --stringparam id.warnings "1" \ + --nonet --output $dst/ \ + ${docbook_xsl_ns}/xml/xsl/docbook/xhtml/chunktoc.xsl \ + ${manual-combined}/manual-combined.xml \ + |& tee xsltproc.out + grep "^ID recommended on" xsltproc.out &>/dev/null && echo "error: some IDs are missing" && false + rm xsltproc.out + + mkdir -p $dst/images/callouts + cp ${docbook_xsl_ns}/xml/xsl/docbook/images/callouts/*.svg $dst/images/callouts/ + + cp ${./style.css} $dst/style.css + cp ${./overrides.css} $dst/overrides.css + cp -r ${pkgs.documentation-highlighter} $dst/highlightjs + + mkdir -p $out/nix-support + echo "nix-build out $out" >> $out/nix-support/hydra-build-products + echo "doc manual $dst" >> $out/nix-support/hydra-build-products + ''; # */ + + # Alias for backward compatibility. TODO(@oxij): remove eventually. + manual = manualHTML; + + # Index page of the NixOS manual. + manualHTMLIndex = "${manualHTML}/share/doc/darwin/index.html"; + + manualEpub = runCommand "darwin-manual-epub" + { inherit sources; + buildInputs = [ libxml2.bin libxslt.bin zip ]; + } + '' + # Generate the epub manual. + dst=$out/share/doc/darwin + + xsltproc \ + ${manualXsltprocOptions} \ + --stringparam target.database.document "${olinkDB}/olinkdb.xml" \ + --nonet --xinclude --output $dst/epub/ \ + ${docbook_xsl_ns}/xml/xsl/docbook/epub/docbook.xsl \ + ${manual-combined}/manual-combined.xml + + mkdir -p $dst/epub/OEBPS/images/callouts + cp -r ${docbook_xsl_ns}/xml/xsl/docbook/images/callouts/*.svg $dst/epub/OEBPS/images/callouts # */ + echo "application/epub+zip" > mimetype + manual="$dst/darwin-manual.epub" + zip -0Xq "$manual" mimetype + cd $dst/epub && zip -Xr9D "$manual" * + + rm -rf $dst/epub + + mkdir -p $out/nix-support + echo "doc-epub manual $manual" >> $out/nix-support/hydra-build-products + ''; + + + # Generate the NixOS manpages. + manpages = runCommand "darwin-manpages" + { inherit sources; + nativeBuildInputs = [ buildPackages.libxml2.bin buildPackages.libxslt.bin ]; + allowedReferences = ["out"]; + } + '' + # Generate manpages. + mkdir -p $out/share/man + xsltproc --nonet \ + --maxdepth 6000 \ + --param man.output.in.separate.dir 1 \ + --param man.output.base.dir "'$out/share/man/'" \ + --param man.endnotes.are.numbered 0 \ + --param man.break.after.slash 1 \ + --stringparam target.database.document "${olinkDB}/olinkdb.xml" \ + ${docbook_xsl_ns}/xml/xsl/docbook/manpages/docbook.xsl \ + ${manual-combined}/man-pages-combined.xml + ''; + +} + diff --git a/doc/manual/man-pages.xml b/doc/manual/man-pages.xml new file mode 100644 index 0000000..2490f63 --- /dev/null +++ b/doc/manual/man-pages.xml @@ -0,0 +1,42 @@ +<reference xmlns="http://docbook.org/ns/docbook" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:xi="http://www.w3.org/2001/XInclude"> + <title>Darwin Reference Pages</title> + <info> + <author><personname><firstname>Daiderd</firstname><surname>Jordan</surname></personname> + <contrib>Author</contrib> + </author> + <copyright><year>2016-2019</year><holder>Daiderd Jordan</holder> + </copyright> + </info> + + <refentry> + <refmeta> + <refentrytitle><filename>configuration.nix</filename> + </refentrytitle><manvolnum>5</manvolnum> + <refmiscinfo class="source">Darwin</refmiscinfo> + <!-- <refmiscinfo class="version"><xi:include href="version.txt" parse="text"/></refmiscinfo> --> + </refmeta> + <refnamediv> + <refname><filename>configuration.nix</filename> + </refname><refpurpose>Darwin system configuration specification</refpurpose> + </refnamediv> + <refsection> + <title>Description</title> + <para> + The file <filename>configuration.nix</filename> contains the + declarative specification of your Darwin system configuration. The command + <command>darwin-rebuild</command> takes this file and realises the system + configuration specified therein. + </para> + </refsection> + <refsection> + <title>Options</title> + <para> + You can use the following options in <filename>configuration.nix</filename>. + </para> + <xi:include href="./generated/options-db.xml" + xpointer="configuration-variable-list" /> + </refsection> + </refentry> +</reference> diff --git a/doc/manual/manual.xml b/doc/manual/manual.xml new file mode 100644 index 0000000..a334342 --- /dev/null +++ b/doc/manual/manual.xml @@ -0,0 +1,21 @@ +<book xmlns="http://docbook.org/ns/docbook" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:xi="http://www.w3.org/2001/XInclude" + version="5.0" + xml:id="book-darwin-manual"> + <info> + <title>Darwin Manual</title> + <subtitle>Version <xi:include href="./generated/version" parse="text" /> + </subtitle> + </info> + <preface xml:id="preface"> + <title>Preface</title> + <para>Nix modules for darwin.</para> + </preface> + <chapter xml:id="sec-options"> + <title>Configuration Options</title> + <xi:include href="./generated/options-db.xml" + xpointer="configuration-variable-list" /> + </chapter> +</book> + diff --git a/doc/manual/options-to-docbook.xsl b/doc/manual/options-to-docbook.xsl new file mode 100644 index 0000000..09f5e08 --- /dev/null +++ b/doc/manual/options-to-docbook.xsl @@ -0,0 +1,229 @@ +<?xml version="1.0"?> + +<xsl:stylesheet version="1.0" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:str="http://exslt.org/strings" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:nixos="tag:nixos.org" + xmlns="http://docbook.org/ns/docbook" + extension-element-prefixes="str" + > + + <xsl:output method='xml' encoding="UTF-8" /> + + <xsl:param name="revision" /> + <xsl:param name="program" /> + + <xsl:template match="/expr/list"> + <appendix xml:id="appendix-configuration-options"> + <title>Configuration Options</title> + <variablelist xml:id="configuration-variable-list"> + <xsl:for-each select="attrs"> + <xsl:variable name="id" select="concat('opt-', str:replace(str:replace(str:replace(str:replace(attr[@name = 'name']/string/@value, '*', '_'), '<', '_'), '>', '_'), '?', '_'))" /> + <varlistentry> + <term xlink:href="#{$id}"> + <xsl:attribute name="xml:id"><xsl:value-of select="$id"/></xsl:attribute> + <option> + <xsl:value-of select="attr[@name = 'name']/string/@value" /> + </option> + </term> + + <listitem> + + <nixos:option-description> + <para> + <xsl:value-of disable-output-escaping="yes" + select="attr[@name = 'description']/string/@value" /> + </para> + </nixos:option-description> + + <xsl:if test="attr[@name = 'type']"> + <para> + <emphasis>Type:</emphasis> + <xsl:text> </xsl:text> + <xsl:value-of select="attr[@name = 'type']/string/@value"/> + <xsl:if test="attr[@name = 'readOnly']/bool/@value = 'true'"> + <xsl:text> </xsl:text> + <emphasis>(read only)</emphasis> + </xsl:if> + </para> + </xsl:if> + + <xsl:if test="attr[@name = 'default']"> + <para> + <emphasis>Default:</emphasis> + <xsl:text> </xsl:text> + <xsl:apply-templates select="attr[@name = 'default']" mode="top" /> + </para> + </xsl:if> + + <xsl:if test="attr[@name = 'example']"> + <para> + <emphasis>Example:</emphasis> + <xsl:text> </xsl:text> + <xsl:choose> + <xsl:when test="attr[@name = 'example']/attrs[attr[@name = '_type' and string[@value = 'literalExample']]]"> + <programlisting><xsl:value-of select="attr[@name = 'example']/attrs/attr[@name = 'text']/string/@value" /></programlisting> + </xsl:when> + <xsl:otherwise> + <xsl:apply-templates select="attr[@name = 'example']" mode="top" /> + </xsl:otherwise> + </xsl:choose> + </para> + </xsl:if> + + <xsl:if test="attr[@name = 'relatedPackages']"> + <para> + <emphasis>Related packages:</emphasis> + <xsl:text> </xsl:text> + <xsl:value-of disable-output-escaping="yes" + select="attr[@name = 'relatedPackages']/string/@value" /> + </para> + </xsl:if> + + <xsl:if test="count(attr[@name = 'declarations']/list/*) != 0"> + <para> + <emphasis>Declared by:</emphasis> + </para> + <xsl:apply-templates select="attr[@name = 'declarations']" /> + </xsl:if> + + <xsl:if test="count(attr[@name = 'definitions']/list/*) != 0"> + <para> + <emphasis>Defined by:</emphasis> + </para> + <xsl:apply-templates select="attr[@name = 'definitions']" /> + </xsl:if> + + </listitem> + + </varlistentry> + + </xsl:for-each> + + </variablelist> + </appendix> + </xsl:template> + + + <xsl:template match="*" mode="top"> + <xsl:choose> + <xsl:when test="string[contains(@value, '
')]"> +<programlisting> +<xsl:text>'' +</xsl:text><xsl:value-of select='str:replace(string/@value, "${", "''${")' /><xsl:text>''</xsl:text></programlisting> + </xsl:when> + <xsl:otherwise> + <literal><xsl:apply-templates /></literal> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + + <xsl:template match="null"> + <xsl:text>null</xsl:text> + </xsl:template> + + + <xsl:template match="string"> + <xsl:choose> + <xsl:when test="(contains(@value, '"') or contains(@value, '\')) and not(contains(@value, '
'))"> + <xsl:text>''</xsl:text><xsl:value-of select='str:replace(@value, "${", "''${")' /><xsl:text>''</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:text>"</xsl:text><xsl:value-of select="str:replace(str:replace(str:replace(str:replace(@value, '\', '\\'), '"', '\"'), '
', '\n'), '$', '\$')" /><xsl:text>"</xsl:text> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + + <xsl:template match="int"> + <xsl:value-of select="@value" /> + </xsl:template> + + + <xsl:template match="bool[@value = 'true']"> + <xsl:text>true</xsl:text> + </xsl:template> + + + <xsl:template match="bool[@value = 'false']"> + <xsl:text>false</xsl:text> + </xsl:template> + + + <xsl:template match="list"> + [ + <xsl:for-each select="*"> + <xsl:apply-templates select="." /> + <xsl:text> </xsl:text> + </xsl:for-each> + ] + </xsl:template> + + + <xsl:template match="attrs[attr[@name = '_type' and string[@value = 'literalExample']]]"> + <xsl:value-of select="attr[@name = 'text']/string/@value" /> + </xsl:template> + + + <xsl:template match="attrs"> + { + <xsl:for-each select="attr"> + <xsl:value-of select="@name" /> + <xsl:text> = </xsl:text> + <xsl:apply-templates select="*" /><xsl:text>; </xsl:text> + </xsl:for-each> + } + </xsl:template> + + + <xsl:template match="derivation"> + <replaceable>(build of <xsl:value-of select="attr[@name = 'name']/string/@value" />)</replaceable> + </xsl:template> + + <xsl:template match="attr[@name = 'declarations' or @name = 'definitions']"> + <simplelist> + <xsl:for-each select="list/string"> + <member><filename> + <!-- Hyperlink the filename either to the NixOS Subversion + repository (if it’s a module and we have a revision number), + or to the local filesystem. --> + <xsl:choose> + <xsl:when test="not(starts-with(@value, '/'))"> + <xsl:choose> + <xsl:when test="$revision = 'local'"> + <xsl:attribute name="xlink:href">https://github.com/LnL7/nix-darwin/blob/master/<xsl:value-of select="@value"/></xsl:attribute> + </xsl:when> + <xsl:otherwise> + <xsl:attribute name="xlink:href">https://github.com/LnL7/nix-darwin/blob/<xsl:value-of select="$revision"/>/<xsl:value-of select="@value"/></xsl:attribute> + </xsl:otherwise> + </xsl:choose> + </xsl:when> + <xsl:otherwise> + <xsl:attribute name="xlink:href">file://<xsl:value-of select="@value"/></xsl:attribute> + </xsl:otherwise> + </xsl:choose> + <!-- Print the filename and make it user-friendly by replacing the + /nix/store/<hash> prefix by the default location of darwin + sources. --> + <xsl:choose> + <xsl:when test="not(starts-with(@value, '/'))"> + <<xsl:value-of select="@value"/>> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="@value" /> + </xsl:otherwise> + </xsl:choose> + </filename></member> + </xsl:for-each> + </simplelist> + </xsl:template> + + + <xsl:template match="function"> + <xsl:text>λ</xsl:text> + </xsl:template> + + +</xsl:stylesheet> diff --git a/doc/manual/overrides.css b/doc/manual/overrides.css new file mode 100644 index 0000000..4c7d4a3 --- /dev/null +++ b/doc/manual/overrides.css @@ -0,0 +1,9 @@ +.docbook .xref img[src^=images\/callouts\/], +.screen img, +.programlisting img { + width: 1em; +} + +.calloutlist img { + width: 1.5em; +} diff --git a/doc/manual/postprocess-option-descriptions.xsl b/doc/manual/postprocess-option-descriptions.xsl new file mode 100644 index 0000000..1201c76 --- /dev/null +++ b/doc/manual/postprocess-option-descriptions.xsl @@ -0,0 +1,115 @@ +<?xml version="1.0"?> + +<xsl:stylesheet version="1.0" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:str="http://exslt.org/strings" + xmlns:exsl="http://exslt.org/common" + xmlns:db="http://docbook.org/ns/docbook" + xmlns:nixos="tag:nixos.org" + extension-element-prefixes="str exsl"> + <xsl:output method='xml' encoding="UTF-8" /> + + <xsl:template match="@*|node()"> + <xsl:copy> + <xsl:apply-templates select="@*|node()" /> + </xsl:copy> + </xsl:template> + + <xsl:template name="break-up-description"> + <xsl:param name="input" /> + <xsl:param name="buffer" /> + + <!-- Every time we have two newlines following each other, we want to + break it into </para><para>. --> + <xsl:variable name="parbreak" select="'

'" /> + + <!-- Similar to "(head:tail) = input" in Haskell. --> + <xsl:variable name="head" select="$input[1]" /> + <xsl:variable name="tail" select="$input[position() > 1]" /> + + <xsl:choose> + <xsl:when test="$head/self::text() and contains($head, $parbreak)"> + <!-- If the haystack provided to str:split() directly starts or + ends with $parbreak, it doesn't generate a <token/> for that, + so we are doing this here. --> + <xsl:variable name="splitted-raw"> + <xsl:if test="starts-with($head, $parbreak)"><token /></xsl:if> + <xsl:for-each select="str:split($head, $parbreak)"> + <token><xsl:value-of select="node()" /></token> + </xsl:for-each> + <!-- Something like ends-with($head, $parbreak), but there is + no ends-with() in XSLT, so we need to use substring(). --> + <xsl:if test=" + substring($head, string-length($head) - + string-length($parbreak) + 1) = $parbreak + "><token /></xsl:if> + </xsl:variable> + <xsl:variable name="splitted" + select="exsl:node-set($splitted-raw)/token" /> + <!-- The buffer we had so far didn't contain any text nodes that + contain a $parbreak, so we can put the buffer along with the + first token of $splitted into a para element. --> + <para xmlns="http://docbook.org/ns/docbook"> + <xsl:apply-templates select="exsl:node-set($buffer)" /> + <xsl:apply-templates select="$splitted[1]/node()" /> + </para> + <!-- We have already emitted the first splitted result, so the + last result is going to be set as the new $buffer later + because its contents may not be directly followed up by a + $parbreak. --> + <xsl:for-each select="$splitted[position() > 1 + and position() < last()]"> + <para xmlns="http://docbook.org/ns/docbook"> + <xsl:apply-templates select="node()" /> + </para> + </xsl:for-each> + <xsl:call-template name="break-up-description"> + <xsl:with-param name="input" select="$tail" /> + <xsl:with-param name="buffer" select="$splitted[last()]/node()" /> + </xsl:call-template> + </xsl:when> + <!-- Either non-text node or one without $parbreak, which we just + want to buffer and continue recursing. --> + <xsl:when test="$input"> + <xsl:call-template name="break-up-description"> + <xsl:with-param name="input" select="$tail" /> + <!-- This essentially appends $head to $buffer. --> + <xsl:with-param name="buffer"> + <xsl:if test="$buffer"> + <xsl:for-each select="exsl:node-set($buffer)"> + <xsl:apply-templates select="." /> + </xsl:for-each> + </xsl:if> + <xsl:apply-templates select="$head" /> + </xsl:with-param> + </xsl:call-template> + </xsl:when> + <!-- No more $input, just put the remaining $buffer in a para. --> + <xsl:otherwise> + <para xmlns="http://docbook.org/ns/docbook"> + <xsl:apply-templates select="exsl:node-set($buffer)" /> + </para> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template match="nixos:option-description"> + <xsl:choose> + <!-- + Only process nodes that are comprised of a single <para/> element, + because if that's not the case the description already contains + </para><para> in between and we need no further processing. + --> + <xsl:when test="count(db:para) > 1"> + <xsl:apply-templates select="node()" /> + </xsl:when> + <xsl:otherwise> + <xsl:call-template name="break-up-description"> + <xsl:with-param name="input" + select="exsl:node-set(db:para/node())" /> + </xsl:call-template> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + +</xsl:stylesheet> diff --git a/doc/manual/style.css b/doc/manual/style.css new file mode 100644 index 0000000..474dd32 --- /dev/null +++ b/doc/manual/style.css @@ -0,0 +1,291 @@ +/* Copied from http://bakefile.sourceforge.net/, which appears + licensed under the GNU GPL. */ + + +/*************************************************************************** + Basic headers and text: + ***************************************************************************/ + +body +{ + font-family: "Nimbus Sans L", sans-serif; + font-size: 1em; + background: white; + margin: 2em 1em 2em 1em; +} + +h1, h2, h3, h4 +{ + color: #005aa0; +} + +h1 /* title */ +{ + font-size: 200%; +} + +h2 /* chapters, appendices, subtitle */ +{ + font-size: 180%; +} + +div.book +{ + text-align: center; +} + +div.book > div +{ + /* + * based on https://medium.com/@zkareemz/golden-ratio-62b3b6d4282a + * we do 70 characters per line to fit code listings better + * 70 * (font-size / 1.618) + * expression for emacs: + * (* 70 (/ 1 1.618)) + */ + max-width: 43.2em; + text-align: left; + margin: auto; +} + +/* Extra space between chapters, appendices. */ +div.chapter > div.titlepage h2, div.appendix > div.titlepage h2 +{ + margin-top: 1.5em; +} + +div.section > div.titlepage h2 /* sections */ +{ + font-size: 150%; + margin-top: 1.5em; +} + +h3 /* subsections */ +{ + font-size: 125%; +} + +div.simplesect h2 +{ + font-size: 110%; +} + +div.appendix h3 +{ + font-size: 150%; + margin-top: 1.5em; +} + +div.refnamediv h2, div.refsynopsisdiv h2, div.refsection h2 /* refentry parts */ +{ + margin-top: 1.4em; + font-size: 125%; +} + +div.refsection h3 +{ + font-size: 110%; +} + + +/*************************************************************************** + Examples: + ***************************************************************************/ + +div.example +{ + border: 1px solid #b0b0b0; + padding: 6px 6px; + margin-left: 1.5em; + margin-right: 1.5em; + background: #f4f4f8; + border-radius: 0.4em; + box-shadow: 0.4em 0.4em 0.5em #e0e0e0; +} + +div.example p.title +{ + margin-top: 0em; +} + +div.example pre +{ + box-shadow: none; +} + + +/*************************************************************************** + Screen dumps: + ***************************************************************************/ + +pre.screen, pre.programlisting +{ + border: 1px solid #b0b0b0; + padding: 3px 3px; + margin-left: 0.5em; + margin-right: 0.5em; + + background: #f4f4f8; + font-family: monospace; + border-radius: 0.4em; + box-shadow: 0.4em 0.4em 0.5em #e0e0e0; +} + +div.example pre.programlisting +{ + border: 0px; + padding: 0 0; + margin: 0 0 0 0; +} + +/*************************************************************************** + Notes, warnings etc: + ***************************************************************************/ + +.note, .warning +{ + border: 1px solid #b0b0b0; + padding: 3px 3px; + margin-left: 1.5em; + margin-right: 1.5em; + margin-bottom: 1em; + padding: 0.3em 0.3em 0.3em 0.3em; + background: #fffff5; + border-radius: 0.4em; + box-shadow: 0.4em 0.4em 0.5em #e0e0e0; +} + +div.note, div.warning +{ + font-style: italic; +} + +div.note h3, div.warning h3 +{ + color: red; + font-size: 100%; + padding-right: 0.5em; + display: inline; +} + +div.note p, div.warning p +{ + margin-bottom: 0em; +} + +div.note h3 + p, div.warning h3 + p +{ + display: inline; +} + +div.note h3 +{ + color: blue; + font-size: 100%; +} + +div.navfooter * +{ + font-size: 90%; +} + + +/*************************************************************************** + Links colors and highlighting: + ***************************************************************************/ + +a { text-decoration: none; } +a:hover { text-decoration: underline; } +a:link { color: #0048b3; } +a:visited { color: #002a6a; } + + +/*************************************************************************** + Table of contents: + ***************************************************************************/ + +div.toc +{ + font-size: 90%; +} + +div.toc dl +{ + margin-top: 0em; + margin-bottom: 0em; +} + + +/*************************************************************************** + Special elements: + ***************************************************************************/ + +tt, code +{ + color: #400000; +} + +.term +{ + font-weight: bold; + +} + +div.variablelist dd p, div.glosslist dd p +{ + margin-top: 0em; +} + +div.variablelist dd, div.glosslist dd +{ + margin-left: 1.5em; +} + +div.glosslist dt +{ + font-style: italic; +} + +.varname +{ + color: #400000; +} + +span.command strong +{ + font-weight: normal; + color: #400000; +} + +div.calloutlist table +{ + box-shadow: none; +} + +table +{ + border-collapse: collapse; + box-shadow: 0.4em 0.4em 0.5em #e0e0e0; +} + +table.simplelist +{ + text-align: left; + color: #005aa0; + border: 0; + padding: 5px; + background: #fffff5; + font-weight: normal; + font-style: italic; + box-shadow: none; + margin-bottom: 1em; +} + +div.navheader table, div.navfooter table { + box-shadow: none; +} + +div.affiliation +{ + font-style: italic; +} |
