80ce71e236
Mention FTS and TLSRPT and explain what these setups are good for and when they might be required.
115 lines
2.7 KiB
Python
115 lines
2.7 KiB
Python
import json
|
|
import sys
|
|
from textwrap import indent
|
|
from typing import Any, Mapping
|
|
|
|
header = """
|
|
# Mailserver options
|
|
|
|
## `mailserver`
|
|
|
|
"""
|
|
|
|
template = """
|
|
({key})=
|
|
`````{{option}} {key}
|
|
{description}
|
|
|
|
{type}
|
|
{default}
|
|
{example}
|
|
`````
|
|
"""
|
|
|
|
f = open(sys.argv[1])
|
|
options = json.load(f)
|
|
|
|
groups = [
|
|
"mailserver.loginAccounts",
|
|
"mailserver.x509",
|
|
"mailserver.dkim",
|
|
"mailserver.srs",
|
|
"mailserver.dmarcReporting",
|
|
"mailserver.tlsrpt",
|
|
"mailserver.fullTextSearch",
|
|
"mailserver.redis",
|
|
"mailserver.ldap",
|
|
"mailserver.monitoring",
|
|
"mailserver.backup",
|
|
"mailserver.borgbackup",
|
|
]
|
|
|
|
|
|
def md_literal(value: str) -> str:
|
|
return f"`{value}`"
|
|
|
|
|
|
def md_codefence(value: str, language: str = "nix") -> str:
|
|
return indent(
|
|
f"\n```{language}\n{value}\n```",
|
|
prefix=2 * " ",
|
|
)
|
|
|
|
|
|
def render_option_value(option: Mapping[str, Any], key: str) -> str:
|
|
if key not in option:
|
|
return ""
|
|
|
|
if isinstance(option[key], dict) and "_type" in option[key]:
|
|
if option[key]["_type"] == "literalExpression":
|
|
# multi-line codeblock
|
|
if "\n" in option[key]["text"]:
|
|
text = option[key]["text"].rstrip("\n")
|
|
value = md_codefence(text)
|
|
# inline codeblock
|
|
else:
|
|
value = md_literal(option[key]["text"])
|
|
# literal markdown
|
|
elif option[key]["_type"] == "literalMD":
|
|
value = option[key]["text"]
|
|
else:
|
|
assert RuntimeError(f"Unhandled option type {option[key]['_type']}")
|
|
else:
|
|
text = str(option[key])
|
|
if text == "":
|
|
value = md_literal('""')
|
|
elif "\n" in text:
|
|
value = md_codefence(text.rstrip("\n"))
|
|
else:
|
|
value = md_literal(text)
|
|
|
|
return f"- {key}: {value}" # type: ignore
|
|
|
|
|
|
def print_option(option):
|
|
if (
|
|
isinstance(option["description"], dict) and "_type" in option["description"]
|
|
): # mdDoc
|
|
description = option["description"]["text"]
|
|
else:
|
|
description = option["description"]
|
|
print(
|
|
template.format(
|
|
key=option["name"],
|
|
description=description or "",
|
|
type=f"- type: {md_literal(option['type'])}",
|
|
default=render_option_value(option, "defaultText")
|
|
if "defaultText" in option
|
|
else render_option_value(option, "default"),
|
|
example=render_option_value(option, "example"),
|
|
)
|
|
)
|
|
|
|
|
|
print(header)
|
|
for opt in options:
|
|
if any([opt["name"].startswith(c) for c in groups]):
|
|
continue
|
|
print_option(opt)
|
|
|
|
for c in groups:
|
|
print(f"## `{c}`\n")
|
|
for opt in options:
|
|
if opt["name"].startswith(c):
|
|
print_option(opt)
|