#!/usr/bin/env python3 """Generate bot documentation HTML pages from docs/*.md.""" import os import re import sys BOTS = [ ("alfred", "Server management, bot control, file hosting, soju bouncer"), ("osterman", "Channel moderation, auto-modes, idle tracking"), ("daffy", "Duck hunting game"), ("contessa", "Recipe suggestions"), ("shireen", "News headlines and weather"), ("daft", "YouTube playlist manager"), ("herald", "Owner-follow bot and keyword responder"), ("salvador", "Image-to-mIRC-art renderer"), ] STYLE = """\ @font-face { font-family: "Kawkab Mono"; src: url(/fonts/KawkabMono-Regular.woff2); font-weight: normal; } @font-face { font-family: "Kawkab Mono"; src: url(/fonts/KawkabMono-Bold.woff2); font-weight: bold; } * { unicode-bidi: plaintext; box-sizing: border-box; } html { color: black; background-color: white; } body { font-family: "Kawkab Mono"; font-size: 16px; line-height: 1.4; margin: 0; padding: 4rem 0; min-height: 100%; overflow-wrap: break-word; } main, header, footer { max-width: 800px; margin-inline: auto; padding: 0 2rem; } h1, header, footer { text-align: center; } main { text-align: left; } p, h2, h3, h4 { margin: 1em 0 0 0; } table { margin: auto; border-collapse: collapse; } th, td { border: 1px solid; padding: 0.3em 0.8em; } pre { background: rgba(128,128,128,0.08); padding: 1em; overflow-x: auto; margin: 1em 0; } code { font-size: 85%; } header { margin-bottom: 1em; } footer { margin-top: 3em; } a { color: inherit; } @media (max-width: 600px) { body { font-size: 0.9em; } h1 { font-size: 1.8em; } } @media (max-width: 400px) { body { font-size: 0.8em; } h1 { font-size: 1.6em; } } @media (prefers-color-scheme: dark) { html { filter: invert(1); } img { filter: invert(1); } }""" FOOTER = "" def page(title, header_html, content_html): return f"""
{chr(10).join(code_lines)}")
i += 1
continue
# ATX headers
m = re.match(r'^(#{1,4})\s+(.*)', line)
if m:
level = len(m.group(1))
out.append(f"{_inline(' '.join(para))}
") return "\n".join(out) def _table(rows): html = ["\1', text)
# links
text = re.sub(r'\[([^\]]+)\]\(([^)]+)\)', r'\1', text)
return text
def _esc(text):
return text.replace("&", "&").replace("<", "<").replace(">", ">")
def build(src_dir, out_dir):
os.makedirs(out_dir, exist_ok=True)
# Copy fonts
fonts_src = os.path.join(src_dir, "fonts")
fonts_dst = os.path.join(out_dir, "fonts")
if os.path.isdir(fonts_src):
os.makedirs(fonts_dst, exist_ok=True)
for f in os.listdir(fonts_src):
src = os.path.join(fonts_src, f)
dst = os.path.join(fonts_dst, f)
with open(src, "rb") as fh:
data = fh.read()
with open(dst, "wb") as fh:
fh.write(data)
# Per-bot pages
for name, desc in BOTS:
doc_path = os.path.join(src_dir, "docs", f"{name}.md")
if not os.path.exists(doc_path):
continue
with open(doc_path) as f:
md = f.read()
content = md_to_html(md)
html = page(
f"{name} — irc.gumx.cc",
f'| bot | purpose |
|---|
All bots run Sopel. Source: git.gumx.cc/irc-bots.
""" index_html = page( "irc bots — irc.gumx.cc", '