treewide: attempt at markdown option docs

This commit is contained in:
pennae 2022-06-03 21:47:57 +02:00
parent 2f00d7ac51
commit 320aa2a791
17 changed files with 329 additions and 143 deletions

View file

@ -27,6 +27,10 @@ function Code(elem)
content = '<refentrytitle>' .. title .. '</refentrytitle>' .. (volnum ~= nil and ('<manvolnum>' .. volnum .. '</manvolnum>') or '') content = '<refentrytitle>' .. title .. '</refentrytitle>' .. (volnum ~= nil and ('<manvolnum>' .. volnum .. '</manvolnum>') or '')
elseif elem.attributes['role'] == 'file' then elseif elem.attributes['role'] == 'file' then
tag = 'filename' tag = 'filename'
elseif elem.attributes['role'] == 'command' then
tag = 'command'
elseif elem.attributes['role'] == 'option' then
tag = 'option'
end end
if tag ~= nil then if tag ~= nil then

View file

@ -27,7 +27,7 @@ If the build succeeds, the manual will be in `./result/share/doc/nixpkgs/manual.
As per [RFC 0072](https://github.com/NixOS/rfcs/pull/72), all new documentation content should be written in [CommonMark](https://commonmark.org/) Markdown dialect. As per [RFC 0072](https://github.com/NixOS/rfcs/pull/72), all new documentation content should be written in [CommonMark](https://commonmark.org/) Markdown dialect.
Additionally, the following syntax extensions are currently used: Additional syntax extensions are available, though not all extensions can be used in NixOS option documentation. The following extensions are currently used:
- []{#ssec-contributing-markup-anchors} - []{#ssec-contributing-markup-anchors}
Explicitly defined **anchors** on headings, to allow linking to sections. These should be always used, to ensure the anchors can be linked even when the heading text changes, and to prevent conflicts between [automatically assigned identifiers](https://github.com/jgm/commonmark-hs/blob/master/commonmark-extensions/test/auto_identifiers.md). Explicitly defined **anchors** on headings, to allow linking to sections. These should be always used, to ensure the anchors can be linked even when the heading text changes, and to prevent conflicts between [automatically assigned identifiers](https://github.com/jgm/commonmark-hs/blob/master/commonmark-extensions/test/auto_identifiers.md).
@ -53,12 +53,22 @@ Additionally, the following syntax extensions are currently used:
This syntax is taken from [MyST](https://myst-parser.readthedocs.io/en/latest/using/syntax.html#targets-and-cross-referencing). This syntax is taken from [MyST](https://myst-parser.readthedocs.io/en/latest/using/syntax.html#targets-and-cross-referencing).
- []{#ssec-contributing-markup-inline-roles} - []{#ssec-contributing-markup-inline-roles}
If you want to link to a man page, you can use `` {manpage}`nix.conf(5)` ``, which will turn into {manpage}`nix.conf(5)`. If you want to link to a man page, you can use `` {manpage}`nix.conf(5)` ``, which will turn into {manpage}`nix.conf(5)`. The references will turn into links when a mapping exists in {file}`doc/build-aux/pandoc-filters/link-unix-man-references.lua`.
The references will turn into links when a mapping exists in {file}`doc/build-aux/pandoc-filters/link-unix-man-references.lua`. A few markups for other kinds of literals are also available:
- `` {command}`rm -rfi` `` turns into {command}`rm -rfi`
- `` {option}`networking.useDHCP` `` turns into {option}`networking.useDHCP`
- `` {file}`/etc/passwd` `` turns into {file}`/etc/passwd`
These literal kinds are used mostly in NixOS option documentation.
This syntax is taken from [MyST](https://myst-parser.readthedocs.io/en/latest/syntax/syntax.html#roles-an-in-line-extension-point). Though, the feature originates from [reStructuredText](https://www.sphinx-doc.org/en/master/usage/restructuredtext/roles.html#role-manpage) with slightly different syntax. This syntax is taken from [MyST](https://myst-parser.readthedocs.io/en/latest/syntax/syntax.html#roles-an-in-line-extension-point). Though, the feature originates from [reStructuredText](https://www.sphinx-doc.org/en/master/usage/restructuredtext/roles.html#role-manpage) with slightly different syntax.
::: {.note}
Inline roles are available for option documentation.
:::
- []{#ssec-contributing-markup-admonitions} - []{#ssec-contributing-markup-admonitions}
**Admonitions**, set off from the text to bring attention to something. **Admonitions**, set off from the text to bring attention to something.
@ -84,6 +94,10 @@ Additionally, the following syntax extensions are currently used:
- [`tip`](https://tdg.docbook.org/tdg/5.0/tip.html) - [`tip`](https://tdg.docbook.org/tdg/5.0/tip.html)
- [`warning`](https://tdg.docbook.org/tdg/5.0/warning.html) - [`warning`](https://tdg.docbook.org/tdg/5.0/warning.html)
::: {.note}
Admonitions are available for option documentation.
:::
- []{#ssec-contributing-markup-definition-lists} - []{#ssec-contributing-markup-definition-lists}
[**Definition lists**](https://github.com/jgm/commonmark-hs/blob/master/commonmark-extensions/test/definition_lists.md), for defining a group of terms: [**Definition lists**](https://github.com/jgm/commonmark-hs/blob/master/commonmark-extensions/test/definition_lists.md), for defining a group of terms:

View file

@ -131,7 +131,8 @@ let
getValues getFiles getValues getFiles
optionAttrSetToDocList optionAttrSetToDocList' optionAttrSetToDocList optionAttrSetToDocList'
scrubOptionValue literalExpression literalExample literalDocBook scrubOptionValue literalExpression literalExample literalDocBook
showOption showFiles unknownModule mkOption mkPackageOption; showOption showFiles unknownModule mkOption mkPackageOption
mdDoc literalMD;
inherit (self.types) isType setType defaultTypeMerge defaultFunctor inherit (self.types) isType setType defaultTypeMerge defaultFunctor
isOptionType mkOptionType; isOptionType mkOptionType;
inherit (self.asserts) inherit (self.asserts)

View file

@ -280,6 +280,21 @@ rec {
if ! isString text then throw "literalDocBook expects a string." if ! isString text then throw "literalDocBook expects a string."
else { _type = "literalDocBook"; inherit text; }; else { _type = "literalDocBook"; inherit text; };
/* Transition marker for documentation that's already migrated to markdown
syntax.
*/
mdDoc = text:
if ! isString text then throw "mdDoc expects a string."
else { _type = "mdDoc"; inherit text; };
/* For use in the `defaultText` and `example` option attributes. Causes the
given MD text to be inserted verbatim in the documentation, for when
a `literalExpression` would be too hard to read.
*/
literalMD = text:
if ! isString text then throw "literalMD expects a string."
else { _type = "literalMD"; inherit text; };
# Helper functions. # Helper functions.
/* Convert an option, described as a list of the option parts in to a /* Convert an option, described as a list of the option parts in to a

View file

@ -56,7 +56,14 @@ The function `mkOption` accepts the following arguments.
`description` `description`
: A textual description of the option, in DocBook format, that will be : A textual description of the option, in DocBook format, that will be
included in the NixOS manual. included in the NixOS manual. During the migration process from DocBook
to CommonMark the description may also be written in CommonMark, but has
to be wrapped in `lib.mdDoc` to differentiate it from DocBook. See
the nixpkgs manual for [the list of CommonMark extensions](
https://nixos.org/nixpkgs/manual/#sec-contributing-markup)
supported by NixOS documentation.
New documentation should preferably be written as CommonMark.
## Utility functions for common option patterns {#sec-option-declarations-util} ## Utility functions for common option patterns {#sec-option-declarations-util}

View file

@ -94,7 +94,17 @@ options = {
<listitem> <listitem>
<para> <para>
A textual description of the option, in DocBook format, that A textual description of the option, in DocBook format, that
will be included in the NixOS manual. will be included in the NixOS manual. During the migration
process from DocBook to CommonMark the description may also be
written in CommonMark, but has to be wrapped in
<literal>lib.mdDoc</literal> to differentiate it from DocBook.
See the nixpkgs manual for
<link xlink:href="https://nixos.org/nixpkgs/manual/#sec-contributing-markup">the
list of CommonMark extensions</link> supported by NixOS
documentation.
</para>
<para>
New documentation should preferably be written as CommonMark.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>

View file

@ -112,7 +112,15 @@ in rec {
optionsJSON = pkgs.runCommand "options.json" optionsJSON = pkgs.runCommand "options.json"
{ meta.description = "List of NixOS options in JSON format"; { meta.description = "List of NixOS options in JSON format";
buildInputs = [ pkgs.brotli ]; buildInputs = [
pkgs.brotli
(let
self = (pkgs.python3Minimal.override {
inherit self;
includeSiteCustomize = true;
});
in self.withPackages (p: [ p.mistune_2_0 ]))
];
options = builtins.toFile "options.json" options = builtins.toFile "options.json"
(builtins.unsafeDiscardStringContext (builtins.toJSON optionsNix)); (builtins.unsafeDiscardStringContext (builtins.toJSON optionsNix));
} }
@ -123,9 +131,13 @@ in rec {
${ ${
if baseOptionsJSON == null if baseOptionsJSON == null
then "cp $options $dst/options.json" then ''
# `cp $options $dst/options.json`, but with temporary
# markdown processing
python ${./mergeJSON.py} $options <(echo '{}') > $dst/options.json
''
else '' else ''
${pkgs.python3Minimal}/bin/python ${./mergeJSON.py} \ python ${./mergeJSON.py} \
${lib.optionalString warningsAreErrors "--warnings-are-errors"} \ ${lib.optionalString warningsAreErrors "--warnings-are-errors"} \
${baseOptionsJSON} $options \ ${baseOptionsJSON} $options \
> $dst/options.json > $dst/options.json

View file

@ -41,6 +41,150 @@ def unpivot(options: Dict[Key, Option]) -> Dict[str, JSON]:
result[opt.name] = opt.value result[opt.name] = opt.value
return result return result
# converts in-place!
def convertMD(options: Dict[str, Any]) -> str:
import mistune
import re
from xml.sax.saxutils import escape, quoteattr
admonitions = {
'.warning': 'warning',
'.important': 'important',
'.note': 'note'
}
class Renderer(mistune.renderers.BaseRenderer):
def _get_method(self, name):
try:
return super(Renderer, self)._get_method(name)
except AttributeError:
def not_supported(children, **kwargs):
raise NotImplementedError("md node not supported yet", name, children, **kwargs)
return not_supported
def text(self, text):
return escape(text)
def paragraph(self, text):
return text + "\n\n"
def codespan(self, text):
return f"<literal>{text}</literal>"
def block_code(self, text, info=None):
info = f" language={quoteattr(info)}" if info is not None else ""
return f"<programlisting{info}>\n{text}</programlisting>"
def link(self, link, text=None, title=None):
if link[0:1] == '#':
attr = "linkend"
link = quoteattr(link[1:])
else:
# try to faithfully reproduce links that were of the form <link href="..."/>
# in docbook format
if text == link:
text = ""
attr = "xlink:href"
link = quoteattr(link)
return f"<link {attr}={link}>{text}</link>"
def list(self, text, ordered, level, start=None):
if ordered:
raise NotImplementedError("ordered lists not supported yet")
return f"<itemizedlist>\n{text}\n</itemizedlist>"
def list_item(self, text, level):
return f"<listitem><para>{text}</para></listitem>\n"
def block_text(self, text):
return text
def emphasis(self, text):
return f"<emphasis>{text}</emphasis>"
def strong(self, text):
return f"<emphasis role=\"strong\">{text}</emphasis>"
def admonition(self, text, kind):
if kind not in admonitions:
raise NotImplementedError(f"admonition {kind} not supported yet")
tag = admonitions[kind]
# we don't keep whitespace here because usually we'll contain only
# a single paragraph and the original docbook string is no longer
# available to restore the trailer.
return f"<{tag}><para>{text.rstrip()}</para></{tag}>"
def command(self, text):
return f"<command>{escape(text)}</command>"
def option(self, text):
return f"<option>{escape(text)}</option>"
def file(self, text):
return f"<filename>{escape(text)}</filename>"
def manpage(self, page, section):
title = f"<refentrytitle>{escape(page)}</refentrytitle>"
vol = f"<manvolnum>{escape(section)}</manvolnum>"
return f"<citerefentry>{title}{vol}</citerefentry>"
def finalize(self, data):
return "".join(data)
plugins = []
COMMAND_PATTERN = r'\{command\}`(.*?)`'
def command(md):
def parse(self, m, state):
return ('command', m.group(1))
md.inline.register_rule('command', COMMAND_PATTERN, parse)
md.inline.rules.append('command')
plugins.append(command)
FILE_PATTERN = r'\{file\}`(.*?)`'
def file(md):
def parse(self, m, state):
return ('file', m.group(1))
md.inline.register_rule('file', FILE_PATTERN, parse)
md.inline.rules.append('file')
plugins.append(file)
OPTION_PATTERN = r'\{option\}`(.*?)`'
def option(md):
def parse(self, m, state):
return ('option', m.group(1))
md.inline.register_rule('option', OPTION_PATTERN, parse)
md.inline.rules.append('option')
plugins.append(option)
MANPAGE_PATTERN = r'\{manpage\}`(.*?)\((.+?)\)`'
def manpage(md):
def parse(self, m, state):
return ('manpage', m.group(1), m.group(2))
md.inline.register_rule('manpage', MANPAGE_PATTERN, parse)
md.inline.rules.append('manpage')
plugins.append(manpage)
ADMONITION_PATTERN = re.compile(r'^::: \{([^\n]*?)\}\n(.*?)^:::\n', flags=re.MULTILINE|re.DOTALL)
def admonition(md):
def parse(self, m, state):
return {
'type': 'admonition',
'children': self.parse(m.group(2), state),
'params': [ m.group(1) ],
}
md.block.register_rule('admonition', ADMONITION_PATTERN, parse)
md.block.rules.append('admonition')
plugins.append(admonition)
def convertString(text: str) -> str:
rendered = mistune.markdown(text, renderer=Renderer(), plugins=plugins)
# keep trailing spaces so we can diff the generated XML to check for conversion bugs.
return rendered.rstrip() + text[len(text.rstrip()):]
def optionIs(option: Dict[str, Any], key: str, typ: str) -> bool:
if key not in option: return False
if type(option[key]) != dict: return False
if '_type' not in option[key]: return False
return option[key]['_type'] == typ
for (name, option) in options.items():
if optionIs(option, 'description', 'mdDoc'):
option['description'] = convertString(option['description']['text'])
if optionIs(option, 'example', 'literalMD'):
docbook = convertString(option['example']['text'])
option['example'] = { '_type': 'literalDocBook', 'text': docbook }
if optionIs(option, 'default', 'literalMD'):
docbook = convertString(option['default']['text'])
option['default'] = { '_type': 'literalDocBook', 'text': docbook }
return options
warningsAreErrors = sys.argv[1] == "--warnings-are-errors" warningsAreErrors = sys.argv[1] == "--warnings-are-errors"
optOffset = 1 if warningsAreErrors else 0 optOffset = 1 if warningsAreErrors else 0
options = pivot(json.load(open(sys.argv[1 + optOffset], 'r'))) options = pivot(json.load(open(sys.argv[1 + optOffset], 'r')))
@ -92,4 +236,4 @@ if hasWarnings and warningsAreErrors:
file=sys.stderr) file=sys.stderr)
sys.exit(1) sys.exit(1)
json.dump(unpivot(options), fp=sys.stdout) json.dump(convertMD(unpivot(options)), fp=sys.stdout)

View file

@ -46,9 +46,9 @@ in
type = with types; either str path; type = with types; either str path;
default = "Lat2-Terminus16"; default = "Lat2-Terminus16";
example = "LatArCyrHeb-16"; example = "LatArCyrHeb-16";
description = '' description = mdDoc ''
The font used for the virtual consoles. Leave empty to use The font used for the virtual consoles. Leave empty to use
whatever the <command>setfont</command> program considers the whatever the {command}`setfont` program considers the
default font. default font.
Can be either a font name or a path to a PSF font file. Can be either a font name or a path to a PSF font file.
''; '';

View file

@ -9,21 +9,20 @@ with lib;
environment.enableDebugInfo = mkOption { environment.enableDebugInfo = mkOption {
type = types.bool; type = types.bool;
default = false; default = false;
description = '' description = mdDoc ''
Some NixOS packages provide debug symbols. However, these are Some NixOS packages provide debug symbols. However, these are
not included in the system closure by default to save disk not included in the system closure by default to save disk
space. Enabling this option causes the debug symbols to appear space. Enabling this option causes the debug symbols to appear
in <filename>/run/current-system/sw/lib/debug/.build-id</filename>, in {file}`/run/current-system/sw/lib/debug/.build-id`,
where tools such as <command>gdb</command> can find them. where tools such as {command}`gdb` can find them.
If you need debug symbols for a package that doesn't If you need debug symbols for a package that doesn't
provide them by default, you can enable them as follows: provide them by default, you can enable them as follows:
<programlisting>
nixpkgs.config.packageOverrides = pkgs: { nixpkgs.config.packageOverrides = pkgs: {
hello = pkgs.hello.overrideAttrs (oldAttrs: { hello = pkgs.hello.overrideAttrs (oldAttrs: {
separateDebugInfo = true; separateDebugInfo = true;
}); });
}; };
</programlisting>
''; '';
}; };

View file

@ -178,19 +178,12 @@ in
man.generateCaches = mkOption { man.generateCaches = mkOption {
type = types.bool; type = types.bool;
default = false; default = false;
description = '' description = mdDoc ''
Whether to generate the manual page index caches. Whether to generate the manual page index caches.
This allows searching for a page or This allows searching for a page or
keyword using utilities like keyword using utilities like {manpage}`apropos(1)`
<citerefentry> and the `-k` option of
<refentrytitle>apropos</refentrytitle> {manpage}`man(1)`.
<manvolnum>1</manvolnum>
</citerefentry>
and the <literal>-k</literal> option of
<citerefentry>
<refentrytitle>man</refentrytitle>
<manvolnum>1</manvolnum>
</citerefentry>.
''; '';
}; };
@ -216,16 +209,14 @@ in
dev.enable = mkOption { dev.enable = mkOption {
type = types.bool; type = types.bool;
default = false; default = false;
description = '' description = mdDoc ''
Whether to install documentation targeted at developers. Whether to install documentation targeted at developers.
<itemizedlist> * This includes man pages targeted at developers if {option}`documentation.man.enable` is
<listitem><para>This includes man pages targeted at developers if <option>documentation.man.enable</option> is set (this also includes "devman" outputs).
set (this also includes "devman" outputs).</para></listitem> * This includes info pages targeted at developers if {option}`documentation.info.enable`
<listitem><para>This includes info pages targeted at developers if <option>documentation.info.enable</option> is set (this also includes "devinfo" outputs).
is set (this also includes "devinfo" outputs).</para></listitem> * This includes other pages targeted at developers if {option}`documentation.doc.enable`
<listitem><para>This includes other pages targeted at developers if <option>documentation.doc.enable</option> is set (this also includes "devdoc" outputs).
is set (this also includes "devdoc" outputs).</para></listitem>
</itemizedlist>
''; '';
}; };

View file

@ -23,11 +23,11 @@ in
++ lib.optionals config.documentation.dev.enable [ "devman" ]; ++ lib.optionals config.documentation.dev.enable [ "devman" ];
ignoreCollisions = true; ignoreCollisions = true;
}; };
defaultText = lib.literalDocBook "all man pages in <option>config.environment.systemPackages</option>"; defaultText = lib.literalMD "all man pages in {option}`config.environment.systemPackages`";
description = '' description = lib.mdDoc ''
The manual pages to generate caches for if <option>documentation.man.generateCaches</option> The manual pages to generate caches for if {option}`documentation.man.generateCaches`
is enabled. Must be a path to a directory with man pages under is enabled. Must be a path to a directory with man pages under
<literal>/share/man</literal>; see the source for an example. `/share/man`; see the source for an example.
Advanced users can make this a content-addressed derivation to save a few rebuilds. Advanced users can make this a content-addressed derivation to save a few rebuilds.
''; '';
}; };

View file

@ -22,16 +22,17 @@ in {
options.confinement.fullUnit = lib.mkOption { options.confinement.fullUnit = lib.mkOption {
type = types.bool; type = types.bool;
default = false; default = false;
description = '' description = lib.mdDoc ''
Whether to include the full closure of the systemd unit file into the Whether to include the full closure of the systemd unit file into the
chroot, instead of just the dependencies for the executables. chroot, instead of just the dependencies for the executables.
<warning><para>While it may be tempting to just enable this option to ::: {.warning}
While it may be tempting to just enable this option to
make things work quickly, please be aware that this might add paths make things work quickly, please be aware that this might add paths
to the closure of the chroot that you didn't anticipate. It's better to the closure of the chroot that you didn't anticipate. It's better
to use <option>confinement.packages</option> to <emphasis to use {option}`confinement.packages` to **explicitly** add additional store paths to the
role="strong">explicitly</emphasis> add additional store paths to the chroot.
chroot.</para></warning> :::
''; '';
}; };

View file

@ -191,12 +191,12 @@ in {
settings = mkOption { settings = mkOption {
default = {}; default = {};
description = '' description = mdDoc ''
The primary synapse configuration. See the The primary synapse configuration. See the
<link xlink:href="https://github.com/matrix-org/synapse/blob/v${cfg.package.version}/docs/sample_config.yaml">sample configuration</link> [sample configuration](https://github.com/matrix-org/synapse/blob/v${cfg.package.version}/docs/sample_config.yaml)
for possible values. for possible values.
Secrets should be passed in by using the <literal>extraConfigFiles</literal> option. Secrets should be passed in by using the `extraConfigFiles` option.
''; '';
type = with types; submodule { type = with types; submodule {
freeformType = format.type; freeformType = format.type;
@ -230,23 +230,23 @@ in {
registration_shared_secret = mkOption { registration_shared_secret = mkOption {
type = types.nullOr types.str; type = types.nullOr types.str;
default = null; default = null;
description = '' description = mdDoc ''
If set, allows registration by anyone who also has the shared If set, allows registration by anyone who also has the shared
secret, even if registration is otherwise disabled. secret, even if registration is otherwise disabled.
Secrets should be passed in via <literal>extraConfigFiles</literal>! Secrets should be passed in via `extraConfigFiles`!
''; '';
}; };
macaroon_secret_key = mkOption { macaroon_secret_key = mkOption {
type = types.nullOr types.str; type = types.nullOr types.str;
default = null; default = null;
description = '' description = mdDoc ''
Secret key for authentication tokens. If none is specified, Secret key for authentication tokens. If none is specified,
the registration_shared_secret is used, if one is given; otherwise, the registration_shared_secret is used, if one is given; otherwise,
a secret key is derived from the signing key. a secret key is derived from the signing key.
Secrets should be passed in via <literal>extraConfigFiles</literal>! Secrets should be passed in via `extraConfigFiles`!
''; '';
}; };
@ -620,10 +620,10 @@ in {
example = literalExpression '' example = literalExpression ''
config.services.coturn.static-auth-secret config.services.coturn.static-auth-secret
''; '';
description = '' description = mdDoc ''
The shared secret used to compute passwords for the TURN server. The shared secret used to compute passwords for the TURN server.
Secrets should be passed in via <literal>extraConfigFiles</literal>! Secrets should be passed in via `extraConfigFiles`!
''; '';
}; };

View file

@ -54,10 +54,10 @@ let
hashedPassword = mkOption { hashedPassword = mkOption {
type = uniq (nullOr str); type = uniq (nullOr str);
default = null; default = null;
description = '' description = mdDoc ''
Specifies the hashed password for the MQTT User. Specifies the hashed password for the MQTT User.
To generate hashed password install <literal>mosquitto</literal> To generate hashed password install `mosquitto`
package and use <literal>mosquitto_passwd</literal>. package and use `mosquitto_passwd`.
''; '';
}; };
@ -65,11 +65,11 @@ let
type = uniq (nullOr types.path); type = uniq (nullOr types.path);
example = "/path/to/file"; example = "/path/to/file";
default = null; default = null;
description = '' description = mdDoc ''
Specifies the path to a file containing the Specifies the path to a file containing the
hashed password for the MQTT user. hashed password for the MQTT user.
To generate hashed password install <literal>mosquitto</literal> To generate hashed password install `mosquitto`
package and use <literal>mosquitto_passwd</literal>. package and use `mosquitto_passwd`.
''; '';
}; };
@ -155,24 +155,24 @@ let
options = { options = {
plugin = mkOption { plugin = mkOption {
type = path; type = path;
description = '' description = mdDoc ''
Plugin path to load, should be a <literal>.so</literal> file. Plugin path to load, should be a `.so` file.
''; '';
}; };
denySpecialChars = mkOption { denySpecialChars = mkOption {
type = bool; type = bool;
description = '' description = mdDoc ''
Automatically disallow all clients using <literal>#</literal> Automatically disallow all clients using `#`
or <literal>+</literal> in their name/id. or `+` in their name/id.
''; '';
default = true; default = true;
}; };
options = mkOption { options = mkOption {
type = attrsOf optionType; type = attrsOf optionType;
description = '' description = mdDoc ''
Options for the auth plugin. Each key turns into a <literal>auth_opt_*</literal> Options for the auth plugin. Each key turns into a `auth_opt_*`
line in the config. line in the config.
''; '';
default = {}; default = {};
@ -239,8 +239,8 @@ let
address = mkOption { address = mkOption {
type = nullOr str; type = nullOr str;
description = '' description = mdDoc ''
Address to listen on. Listen on <literal>0.0.0.0</literal>/<literal>::</literal> Address to listen on. Listen on `0.0.0.0`/`::`
when unset. when unset.
''; '';
default = null; default = null;
@ -248,10 +248,10 @@ let
authPlugins = mkOption { authPlugins = mkOption {
type = listOf authPluginOptions; type = listOf authPluginOptions;
description = '' description = mdDoc ''
Authentication plugin to attach to this listener. Authentication plugin to attach to this listener.
Refer to the <link xlink:href="https://mosquitto.org/man/mosquitto-conf-5.html"> Refer to the [mosquitto.conf documentation](https://mosquitto.org/man/mosquitto-conf-5.html)
mosquitto.conf documentation</link> for details on authentication plugins. for details on authentication plugins.
''; '';
default = []; default = [];
}; };
@ -472,10 +472,10 @@ let
includeDirs = mkOption { includeDirs = mkOption {
type = listOf path; type = listOf path;
description = '' description = mdDoc ''
Directories to be scanned for further config files to include. Directories to be scanned for further config files to include.
Directories will processed in the order given, Directories will processed in the order given,
<literal>*.conf</literal> files in the directory will be `*.conf` files in the directory will be
read in case-sensistive alphabetical order. read in case-sensistive alphabetical order.
''; '';
default = []; default = [];

View file

@ -72,39 +72,39 @@ in {
cert = mkOption { cert = mkOption {
type = types.nullOr types.str; type = types.nullOr types.str;
default = null; default = null;
description = '' description = mdDoc ''
Path to the <literal>cert.pem</literal> file, which will be copied into Syncthing's Path to the `cert.pem` file, which will be copied into Syncthing's
<link linkend="opt-services.syncthing.configDir">configDir</link>. [configDir](#opt-services.syncthing.configDir).
''; '';
}; };
key = mkOption { key = mkOption {
type = types.nullOr types.str; type = types.nullOr types.str;
default = null; default = null;
description = '' description = mdDoc ''
Path to the <literal>key.pem</literal> file, which will be copied into Syncthing's Path to the `key.pem` file, which will be copied into Syncthing's
<link linkend="opt-services.syncthing.configDir">configDir</link>. [configDir](#opt-services.syncthing.configDir).
''; '';
}; };
overrideDevices = mkOption { overrideDevices = mkOption {
type = types.bool; type = types.bool;
default = true; default = true;
description = '' description = mdDoc ''
Whether to delete the devices which are not configured via the Whether to delete the devices which are not configured via the
<link linkend="opt-services.syncthing.devices">devices</link> option. [devices](#opt-services.syncthing.devices) option.
If set to <literal>false</literal>, devices added via the web If set to `false`, devices added via the web
interface will persist and will have to be deleted manually. interface will persist and will have to be deleted manually.
''; '';
}; };
devices = mkOption { devices = mkOption {
default = {}; default = {};
description = '' description = mdDoc ''
Peers/devices which Syncthing should communicate with. Peers/devices which Syncthing should communicate with.
Note that you can still add devices manually, but those changes Note that you can still add devices manually, but those changes
will be reverted on restart if <link linkend="opt-services.syncthing.overrideDevices">overrideDevices</link> will be reverted on restart if [overrideDevices](#opt-services.syncthing.overrideDevices)
is enabled. is enabled.
''; '';
example = { example = {
@ -135,27 +135,27 @@ in {
id = mkOption { id = mkOption {
type = types.str; type = types.str;
description = '' description = mdDoc ''
The device ID. See <link xlink:href="https://docs.syncthing.net/dev/device-ids.html"/>. The device ID. See <https://docs.syncthing.net/dev/device-ids.html>.
''; '';
}; };
introducer = mkOption { introducer = mkOption {
type = types.bool; type = types.bool;
default = false; default = false;
description = '' description = mdDoc ''
Whether the device should act as an introducer and be allowed Whether the device should act as an introducer and be allowed
to add folders on this computer. to add folders on this computer.
See <link xlink:href="https://docs.syncthing.net/users/introducer.html"/>. See <https://docs.syncthing.net/users/introducer.html>.
''; '';
}; };
autoAcceptFolders = mkOption { autoAcceptFolders = mkOption {
type = types.bool; type = types.bool;
default = false; default = false;
description = '' description = mdDoc ''
Automatically create or share folders that this device advertises at the default path. Automatically create or share folders that this device advertises at the default path.
See <link xlink:href="https://docs.syncthing.net/users/config.html?highlight=autoaccept#config-file-format"/>. See <https://docs.syncthing.net/users/config.html?highlight=autoaccept#config-file-format>.
''; '';
}; };
@ -166,21 +166,21 @@ in {
overrideFolders = mkOption { overrideFolders = mkOption {
type = types.bool; type = types.bool;
default = true; default = true;
description = '' description = mdDoc ''
Whether to delete the folders which are not configured via the Whether to delete the folders which are not configured via the
<link linkend="opt-services.syncthing.folders">folders</link> option. [folders](#opt-services.syncthing.folders) option.
If set to <literal>false</literal>, folders added via the web If set to `false`, folders added via the web
interface will persist and will have to be deleted manually. interface will persist and will have to be deleted manually.
''; '';
}; };
folders = mkOption { folders = mkOption {
default = {}; default = {};
description = '' description = mdDoc ''
Folders which should be shared by Syncthing. Folders which should be shared by Syncthing.
Note that you can still add devices manually, but those changes Note that you can still add devices manually, but those changes
will be reverted on restart if <link linkend="opt-services.syncthing.overrideDevices">overrideDevices</link> will be reverted on restart if [overrideDevices](#opt-services.syncthing.overrideDevices)
is enabled. is enabled.
''; '';
example = literalExpression '' example = literalExpression ''
@ -231,18 +231,18 @@ in {
devices = mkOption { devices = mkOption {
type = types.listOf types.str; type = types.listOf types.str;
default = []; default = [];
description = '' description = mdDoc ''
The devices this folder should be shared with. Each device must The devices this folder should be shared with. Each device must
be defined in the <link linkend="opt-services.syncthing.devices">devices</link> option. be defined in the [devices](#opt-services.syncthing.devices) option.
''; '';
}; };
versioning = mkOption { versioning = mkOption {
default = null; default = null;
description = '' description = mdDoc ''
How to keep changed/deleted files with Syncthing. How to keep changed/deleted files with Syncthing.
There are 4 different types of versioning with different parameters. There are 4 different types of versioning with different parameters.
See <link xlink:href="https://docs.syncthing.net/users/versioning.html"/>. See <https://docs.syncthing.net/users/versioning.html>.
''; '';
example = literalExpression '' example = literalExpression ''
[ [
@ -284,17 +284,17 @@ in {
options = { options = {
type = mkOption { type = mkOption {
type = enum [ "external" "simple" "staggered" "trashcan" ]; type = enum [ "external" "simple" "staggered" "trashcan" ];
description = '' description = mdDoc ''
The type of versioning. The type of versioning.
See <link xlink:href="https://docs.syncthing.net/users/versioning.html"/>. See <https://docs.syncthing.net/users/versioning.html>.
''; '';
}; };
params = mkOption { params = mkOption {
type = attrsOf (either str path); type = attrsOf (either str path);
description = '' description = mdDoc ''
The parameters for versioning. Structure depends on The parameters for versioning. Structure depends on
<link linkend="opt-services.syncthing.folders._name_.versioning.type">versioning.type</link>. [versioning.type](#opt-services.syncthing.folders._name_.versioning.type).
See <link xlink:href="https://docs.syncthing.net/users/versioning.html"/>. See <https://docs.syncthing.net/users/versioning.html>.
''; '';
}; };
}; };
@ -345,9 +345,9 @@ in {
ignoreDelete = mkOption { ignoreDelete = mkOption {
type = types.bool; type = types.bool;
default = false; default = false;
description = '' description = mdDoc ''
Whether to skip deleting files that are deleted by peers. Whether to skip deleting files that are deleted by peers.
See <link xlink:href="https://docs.syncthing.net/advanced/folder-ignoredelete.html"/>. See <https://docs.syncthing.net/advanced/folder-ignoredelete.html>.
''; '';
}; };
}; };
@ -357,9 +357,9 @@ in {
extraOptions = mkOption { extraOptions = mkOption {
type = types.addCheck (pkgs.formats.json {}).type isAttrs; type = types.addCheck (pkgs.formats.json {}).type isAttrs;
default = {}; default = {};
description = '' description = mdDoc ''
Extra configuration options for Syncthing. Extra configuration options for Syncthing.
See <link xlink:href="https://docs.syncthing.net/users/config.html"/>. See <https://docs.syncthing.net/users/config.html>.
''; '';
example = { example = {
options.localAnnounceEnabled = false; options.localAnnounceEnabled = false;
@ -387,9 +387,9 @@ in {
type = types.str; type = types.str;
default = defaultUser; default = defaultUser;
example = "yourUser"; example = "yourUser";
description = '' description = mdDoc ''
The user to run Syncthing as. The user to run Syncthing as.
By default, a user named <literal>${defaultUser}</literal> will be created. By default, a user named `${defaultUser}` will be created.
''; '';
}; };
@ -397,9 +397,9 @@ in {
type = types.str; type = types.str;
default = defaultGroup; default = defaultGroup;
example = "yourGroup"; example = "yourGroup";
description = '' description = mdDoc ''
The group to run Syncthing under. The group to run Syncthing under.
By default, a group named <literal>${defaultGroup}</literal> will be created. By default, a group named `${defaultGroup}` will be created.
''; '';
}; };
@ -407,11 +407,11 @@ in {
type = with types; nullOr str; type = with types; nullOr str;
default = null; default = null;
example = "socks5://address.com:1234"; example = "socks5://address.com:1234";
description = '' description = mdDoc ''
Overwrites the all_proxy environment variable for the Syncthing process to Overwrites the all_proxy environment variable for the Syncthing process to
the given value. This is normally used to let Syncthing connect the given value. This is normally used to let Syncthing connect
through a SOCKS5 proxy server. through a SOCKS5 proxy server.
See <link xlink:href="https://docs.syncthing.net/users/proxying.html"/>. See <https://docs.syncthing.net/users/proxying.html>.
''; '';
}; };
@ -432,25 +432,13 @@ in {
The path where the settings and keys will exist. The path where the settings and keys will exist.
''; '';
default = cfg.dataDir + optionalString cond "/.config/syncthing"; default = cfg.dataDir + optionalString cond "/.config/syncthing";
defaultText = literalDocBook '' defaultText = literalMD ''
<variablelist> * if `stateVersion >= 19.03`:
<varlistentry>
<term><literal>stateVersion >= 19.03</literal></term> config.${opt.dataDir} + "/.config/syncthing"
<listitem> * otherwise:
<programlisting>
config.${opt.dataDir} + "/.config/syncthing" config.${opt.dataDir}
</programlisting>
</listitem>
</varlistentry>
<varlistentry>
<term>otherwise</term>
<listitem>
<programlisting>
config.${opt.dataDir}
</programlisting>
</listitem>
</varlistentry>
</variablelist>
''; '';
}; };

View file

@ -23,12 +23,12 @@ in
default = false; default = false;
type = types.bool; type = types.bool;
description = description =
'' mdDoc ''
Setting this option enables the Xen hypervisor, a Setting this option enables the Xen hypervisor, a
virtualisation technology that allows multiple virtual virtualisation technology that allows multiple virtual
machines, known as <emphasis>domains</emphasis>, to run machines, known as *domains*, to run
concurrently on the physical machine. NixOS runs as the concurrently on the physical machine. NixOS runs as the
privileged <emphasis>Domain 0</emphasis>. This option privileged *Domain 0*. This option
requires a reboot to take effect. requires a reboot to take effect.
''; '';
}; };