Files
kumomta/docs/generate-toc.py
T
Wez Furlong 3a1b1053bd docs: add link checking
Ideally there would be a good mkdocs based checker, but the
one that is out there only validate absolute URLs, which makes
it unsuitable for checking local relative links in the docs.

Adjust the doc build so that we also generate the SUMMARY.md
for mdbook, and use mdbook's link checker to check the links.

Fixup the couple of broken links that it found.
2023-03-13 12:01:07 -07:00

236 lines
8.1 KiB
Python
Executable File

#!/usr/bin/env python3
import base64
import glob
import json
import os
import re
import subprocess
import sys
class Page(object):
"""A page in the TOC, and its optional children"""
def __init__(self, title, filename, children=None):
self.title = title
self.filename = filename
self.children = children or []
def render(self, output, depth=0, mode="mdbook"):
indent = " " * depth
bullet = "- " if depth > 0 else ""
if mode == "mdbook":
if self.filename:
output.write(f"{indent}{bullet}[{self.title}]({self.filename})\n")
elif mode == "mkdocs":
if depth > 0:
if len(self.children) == 0:
output.write(f'{indent}{bullet}"{self.title}": {self.filename}\n')
else:
output.write(f'{indent}{bullet}"{self.title}":\n')
if self.filename:
output.write(
f'{indent} {bullet}"{self.title}": {self.filename}\n'
)
for kid in self.children:
kid.render(output, depth + 1, mode)
class Gen(object):
"""autogenerate an index page from the contents of a directory"""
def __init__(self, title, dirname, index=None, extract_title=False, reverse=False):
self.title = title
self.dirname = dirname
self.index = index
self.extract_title = extract_title
self.reverse = reverse
def render(self, output, depth=0, mode="mdbook"):
names = sorted(glob.glob(f"{self.dirname}/*.md"), reverse=self.reverse)
children = []
for filename in names:
title = os.path.basename(filename).rsplit(".", 1)[0]
if title == "index" or title == "_index":
continue
if self.extract_title:
with open(filename, "r") as f:
title = f.readline().strip("#").strip()
children.append(Page(title, filename))
index_filename = f"{self.dirname}/index.md"
index_page = Page(self.title, index_filename, children=children)
index_page.render(output, depth, mode)
with open(index_filename, "w") as idx:
if self.index:
idx.write(self.index)
idx.write("\n\n")
else:
try:
with open(f"{self.dirname}/_index.md", "r") as f:
idx.write(f.read())
idx.write("\n\n")
except FileNotFoundError:
pass
for page in children:
idx.write(f" - [{page.title}]({os.path.basename(page.filename)})\n")
TOC = [
Page(
"Tutorial",
None,
children=[
Page("Getting Started", "tutorial/getting_started.md"),
Page(
"Environmental Considerations",
"tutorial/environment_consideration.md",
),
Page("System Preparation", "tutorial/system_preparation.md"),
Page(
"Installing with Docker Containers",
"tutorial/install_with_docker.md",
),
Page(
"Building from Source",
"tutorial/install_from_source.md",
),
Page("Your First Email", "tutorial/your_first_email.md"),
Page(
"Beyond Basics",
"tutorial/beyond_basics.md",
children=[
Page("Configuring DKIM", "tutorial/dkim.md"),
Page("Configuring TLS", "tutorial/tls.md"),
],
),
Page(
"Advanced Configurations",
"tutorial/advanced_config.md",
children=[
Page("Lua Resources", "tutorial/lua_resources.md"),
Page("Lua Functions", "tutorial/lua_functions.md"),
],
),
],
),
Page(
"User Guide",
"userguide/index.md",
children=[
Page(
"General",
None,
children=[
Page("Preface and Legal Notices", "userguide/general/preface.md"),
Page("About This Manual", "userguide/general/about.md"),
Page(
"How to Report Bugs or Get Help", "userguide/general/report.md"
),
Page("Credits", "userguide/general/credits.md"),
Page("History", "userguide/general/history.md"),
Page("Architecture", "userguide/general/architecture.md"),
],
),
Page(
"Installation",
"userguide/installation/index.md",
children=[
Page(
"Deployment Architecture",
"userguide/installation/deployment.md",
),
Page("Server Environment", "userguide/installation/environment.md"),
Page("Server Hardware", "userguide/installation/hardware.md"),
Page(
"Operating System", "userguide/installation/operatingsystem.md"
),
Page("Installing in Docker", "userguide/installation/docker.md"),
Page("Installing on Linux", "userguide/installation/linux.md"),
Page("Upgrading", "userguide/installation/upgrading.md"),
],
),
Page(
"Configuration",
"userguide/configuration/index.md",
children=[
Page(
"Configuration Concepts", "userguide/configuration/concepts.md"
),
Page(
"An Example Configuration", "userguide/configuration/example.md"
),
Page("Configuring Spooling", "userguide/configuration/spool.md"),
Page(
"Configuring Listeners",
"userguide/configuration/smtplisteners.md",
),
Page(
"Configuring Traffic Shaping",
"userguide/configuration/trafficshaping.md",
),
Page("Configuring Logging", "userguide/configuration/logging.md"),
Page(
"Configuring HTTP Listeners",
"userguide/configuration/httplisteners.md",
),
],
),
],
),
Page(
"Reference Manual",
"reference/index.md",
children=[
Page("Queues", "reference/queues.md"),
Gen(
"module: kumo",
"reference/kumo",
),
Gen(
"module: kumo.dkim",
"reference/kumo.dkim",
),
Gen(
"module: sqlite",
"reference/sqlite",
),
Gen(
"module: redis",
"reference/redis",
),
Gen(
"object: address",
"reference/address",
),
Gen(
"object: message",
"reference/message",
),
Gen(
"events",
"reference/events",
),
Gen("HTTP API", "reference/http", extract_title=True),
],
),
Gen("Changelog", "changelog", extract_title=True, reverse=True),
]
os.chdir("docs")
with open("../mkdocs.yml", "w") as f:
f.write("# this is auto-generated by docs/generate-toc.py, do not edit\n")
f.write("INHERIT: mkdocs-base.yml\n")
f.write("nav:\n")
for page in TOC:
page.render(f, depth=1, mode="mkdocs")
with open("SUMMARY.md", "w") as f:
f.write("<!-- this is auto-generated by docs/generate-toc.py, do not edit -->\n")
f.write("[Home](index.md)\n")
for page in TOC:
page.render(f, depth=1, mode="mdbook")