#!/usr/bin/env python3 """Convert markdown files in spec directories to HTML. Uses cmark-gfm for full GitHub Flavored Markdown rendering, then post-processes the output to convert GFM alert syntax (> [!NOTE], etc.) into styled admonition blocks. """ import glob import os import re import subprocess ADMONITION_TYPES = {"NOTE", "TIP", "IMPORTANT", "WARNING", "CAUTION"} TEMPLATE = """\ {title} {body} """ # cmark-gfm renders > [!NOTE]\n> text as: #
\n

[!NOTE]\ntext

\n
# We convert these to styled admonition divs. ADMONITION_RE = re.compile( r"
\n

\[!(NOTE|TIP|IMPORTANT|WARNING|CAUTION)\]\n" r"(.*?)

\n
", re.DOTALL, ) def convert_admonitions(html): def replace(m): kind = m.group(1).lower() body = m.group(2) title = m.group(1).capitalize() return ( f'
\n' f'

{title}

\n' f"

{body}

\n" f"
" ) return ADMONITION_RE.sub(replace, html) def extract_title(text): m = re.search(r"^#\s+(.+)", text, re.MULTILINE) return m.group(1).strip() if m else "Untitled" def render_markdown(text): proc = subprocess.run( ["cmark-gfm", "--extension", "table", "--extension", "autolink", "--extension", "strikethrough", "--extension", "tasklist"], input=text, capture_output=True, encoding="utf-8", ) if proc.returncode != 0: raise RuntimeError(f"cmark-gfm failed: {proc.stderr}") return convert_admonitions(proc.stdout) def main(): for md_file in sorted(glob.glob("*/*.md")): if md_file.startswith("."): continue html_file = os.path.splitext(md_file)[0] + ".html" if os.path.exists(html_file): continue with open(md_file, encoding="utf-8") as f: text = f.read() title = extract_title(text) body = render_markdown(text) with open(html_file, "w", encoding="utf-8") as f: f.write(TEMPLATE.format(title=title, body=body)) print(f" {html_file}") if __name__ == "__main__": main()