#!/usr/bin/env python3 """Render a canon markdown document into a styled, self-contained artifact page. Single source of truth: the markdown. The page is generated, never hand-edited, so the two cannot diverge. Design devices are recognised from conventions already present in the markdown rather than from extra markup, so the source stays a readable document: * a table whose first column is `**X0**`/`**X1**`... renders as a level ladder * a table whose first header cell is `Threat` renders as a threat matrix * a table with a `Kind` column renders with mechanical/adversarial chips * a table whose first header cell is `E \\ P` renders as the E x P matrix * a blockquote renders as a pull quote * `**Decision N.N...**` at the start of a paragraph renders as a decision * `## N. Title` headings build the section rail Stdlib only, per the estate's structure-not-tooling stance: a publishing step that needs its own toolchain is a publishing step that stops being run. Usage: python3 tools/render.py --output \\ [--title "Name"] [--subtitle "..."] """ from __future__ import annotations import argparse import html import pathlib import re import sys STYLE = pathlib.Path(__file__).parent / "style.css" INLINE_CODE = re.compile(r"`([^`]+)`") BOLD = re.compile(r"\*\*([^*]+)\*\*") EM = re.compile(r"(? str: """Escape, then apply inline markdown. Order matters: code first.""" slots: list[str] = [] def stash(rendered: str) -> str: slots.append(rendered) return f"\x00{len(slots) - 1}\x00" text = INLINE_CODE.sub(lambda m: stash(f"{html.escape(m.group(1))}"), text) text = html.escape(text, quote=False) text = LINK.sub( lambda m: f'{m.group(1)}', text ) text = BOLD.sub(r"\1", text) text = EM.sub(r"\1", text) for i, rendered in enumerate(slots): text = text.replace(f"\x00{i}\x00", rendered) return text def split_frontmatter(source: str) -> tuple[dict, str]: if not source.startswith("---\n"): return {}, source end = source.index("\n---\n", 4) meta = {} for line in source[4:end].splitlines(): if ":" in line and not line.startswith((" ", "-")): key, _, value = line.partition(":") meta[key.strip()] = value.strip().strip('"') return meta, source[end + 5 :] def parse_table(lines: list[str], start: int) -> tuple[list[list[str]], int]: rows, i = [], start while i < len(lines) and lines[i].lstrip().startswith("|"): cells = [c.strip() for c in lines[i].strip().strip("|").split("|")] if not all(set(c) <= set("-: ") for c in cells): rows.append(cells) i += 1 return rows, i # --- table renderers ------------------------------------------------------- def render_ladder(rows: list[list[str]]) -> str: """A level table becomes a stepped scale. Colour depth encodes strength.""" body = rows[1:] axis = LEVEL_CELL.match(body[0][0]).group(1) names = { "I": "Identity", "A": "Authorization", "E": "Enforcement", "P": "Placement", "R": "Retention", "V": "Availability", } rungs = [] for cells in body: match = LEVEL_CELL.match(cells[0]) if not match: continue n = int(match.group(2)) text = cells[1] if len(cells) > 1 else "" rungs.append( f'
{axis}{n}' f'{inline(text)}
' ) while len(rungs) < 5: rungs.append('
' f'Ladder ends at {axis}{len(rungs) - 1}.
') return ( '
' f'{names.get(axis, axis)}axis {axis}
' f'
{"".join(rungs)}
' ) def render_threat(rows: list[list[str]]) -> str: head = "".join(f"{inline(c)}" for c in rows[0]) body = [] for cells in rows[1:]: tds = [f"{inline(cells[0])}"] for c in cells[1:]: cls = "yes" if "✓" in c else "no" if "✗" in c else "" tds.append(f'{inline(c)}') body.append(f"{''.join(tds)}") return (f'
{head}' f'{"".join(body)}
') def render_matrix(rows: list[list[str]]) -> str: """`E \\ P` table becomes the two-axis grid. Cells hold pins or markers.""" cols = rows[0][1:] cells = ['
'] for cells_row in rows[1:]: e = cells_row[0].strip("*") level = int(e[1]) if len(e) > 1 and e[1].isdigit() else 0 cells.append(f'
{html.escape(e)}
') for value in cells_row[1:]: v = value.strip() if v == "—": cells.append('
') continue tint = f" tint{level}" if level else "" pins = "" for entry in (p.strip() for p in v.split("
") if p.strip()): ghost = " ghost" if entry.startswith("(") else "" pins += f'{inline(entry.strip("()"))}' cells.append(f'
{pins}
') cells.append('
') cells.extend(f'
{html.escape(c)}
' for c in cols) cells.append("
") return ( '
Enforcement →
' + "".join(cells) + "
" '
' 'Where a service sits today' 'Target or default' 'Unreachable at this placement' "
" ) def render_table(rows: list[list[str]]) -> str: if not rows: return "" header = [c.strip() for c in rows[0]] first = header[0].lower() if first.replace(" ", "") in {"e\\p", "e\\p"}: return render_matrix(rows) if first == "threat": return render_threat(rows) kind_col = header.index("Kind") if "Kind" in header else None # A level table is a ladder. The evidence table also leads with `Level` but # carries a `Kind` column, and is a table of artifacts, not of rungs. if first == "level" and kind_col is None and len(rows) > 1 and LEVEL_CELL.match(rows[1][0]): return render_ladder(rows) head = "".join(f"{inline(c)}" for c in header) body = [] for cells in rows[1:]: tds = [] for i, c in enumerate(cells): if i == kind_col: adv = "adv" if "adversarial" in c.lower() else "" label = re.sub(r"[*_]", "", c).strip() tds.append(f'{html.escape(label)}') else: tds.append(f"{inline(c)}") body.append(f"{''.join(tds)}") return (f'
{head}' f'{"".join(body)}
') # --- document --------------------------------------------------------------- def render_body(markdown: str) -> tuple[str, list[tuple[str, str, str]]]: lines = markdown.splitlines() out: list[str] = [] rail: list[tuple[str, str, str]] = [] open_section = False ladders_open = False i = 0 def close_ladders() -> None: nonlocal ladders_open if ladders_open: out.append("") ladders_open = False while i < len(lines): line = lines[i] stripped = line.strip() if not stripped: i += 1 continue heading = HEADING.match(stripped) if heading: level, text = len(heading.group(1)), heading.group(2) if level == 1: i += 1 continue if level == 2: close_ladders() if open_section: out.append("") match = SECTION_NO.match(text) if match: num, title = match.group(1), match.group(2) anchor = f"s{num}" rail.append((anchor, num, title)) out.append( f'

' f'{int(num):02d}{inline(title)}

' ) else: anchor = re.sub(r"[^a-z0-9]+", "-", text.lower()).strip("-") rail.append((anchor, "·", text)) out.append(f'

{inline(text)}

') open_section = True else: close_ladders() out.append(f"

{inline(text)}

") i += 1 continue if stripped.startswith("|"): rows, i = parse_table(lines, i) rendered = render_table(rows) if 'class="ladder"' in rendered: if not ladders_open: out.append('
') ladders_open = True out.append(rendered) else: close_ladders() out.append(rendered) continue close_ladders() if stripped.startswith("```"): block = [] i += 1 while i < len(lines) and not lines[i].strip().startswith("```"): block.append(lines[i]) i += 1 out.append(f"
{html.escape(chr(10).join(block))}
") i += 1 continue if stripped.startswith(">"): quote = [] while i < len(lines) and lines[i].strip().startswith(">"): quote.append(lines[i].strip().lstrip(">").strip()) i += 1 out.append(f'

{inline(" ".join(quote))}

') continue if re.match(r"^[-*]\s+", stripped) or re.match(r"^\d+\.\s+", stripped): ordered = bool(re.match(r"^\d+\.\s+", stripped)) items = [] while i < len(lines): s = lines[i].strip() if re.match(r"^[-*]\s+", s) or re.match(r"^\d+\.\s+", s): items.append(re.sub(r"^([-*]|\d+\.)\s+", "", s)) elif s and lines[i].startswith((" ", "\t")) and items: items[-1] += " " + s else: break i += 1 tag = "ol" if ordered else "ul" body = "".join(f"
  • {inline(t)}
  • " for t in items) out.append(f"<{tag}>{body}") continue if set(stripped) <= set("-") and len(stripped) >= 3: i += 1 continue para = [stripped] i += 1 while i < len(lines) and lines[i].strip() and not re.match( r"^(\||>|```|#{1,4}\s|[-*]\s|\d+\.\s|---)", lines[i].strip() ): para.append(lines[i].strip()) i += 1 text = " ".join(para) decision = DECISION.match(text) if decision: out.append( f'

    {inline(decision.group(1))}' f"{inline(decision.group(2))}

    " ) else: out.append(f"

    {inline(text)}

    ") close_ladders() if open_section: out.append("
    ") return "\n".join(out), rail def render_page( source: pathlib.Path, *, title: str | None = None, subtitle: str = "", publication: dict[str, str] | None = None, ) -> tuple[str, dict, int]: meta, markdown = split_frontmatter(source.read_text(encoding="utf-8")) body, rail = render_body(markdown) resolved_title = title or meta.get("title", source.stem) display = resolved_title.split(":")[0].strip() eyebrow = " ".join( f"{html.escape(v)}" for k, v in ( ("id", meta.get("id", "")), ("status", f"{meta.get('status', '')} · {meta.get('revision', '')}".strip(" ·")), ("owner", meta.get("owner", "")), ( "review", f"reviewed {meta.get('last_reviewed', '')}" if meta.get("last_reviewed") else "", ), ) if v ) rail_html = "".join( f'
  • {n}{html.escape(t)}
  • ' for a, n, t in rail ) publication = publication or {} source_note = " · ".join( item for item in ( publication.get("source_repo", ""), publication.get("source_path", ""), publication.get("source_revision", ""), ) if item ) source_line = ( f'

    Source: {html.escape(source_note)}

    ' if source_note else "" ) review_due = publication.get("review_due", "") review_line = ( f'

    Review due: {html.escape(review_due)}

    ' if review_due else "" ) lifecycle = publication.get("lifecycle", "active") successor = publication.get("successor", "") lifecycle_notice = "" if lifecycle == "superseded": successor_link = ( f' Read its successor.' if successor else "" ) lifecycle_notice = ( '

    Superseded.' f" This address is retained as part of the policy record.{successor_link}

    " ) elif lifecycle == "withdrawn": lifecycle_notice = ( '

    Withdrawn. ' "This document is retained for historical reference and is not current policy." "

    " ) currency_notice = ( '

    Review overdue. ' f"This document was due for review on {html.escape(review_due)}.

    " if review_due and publication.get("stale") == "true" else "" ) source_revision_meta = ( f'\n' if publication.get("source_revision") else "" ) source_digest_meta = ( f'\n' if publication.get("source_digest") else "" ) page = ( "\n\n" + source_revision_meta + source_digest_meta + f"{html.escape(display)}\n" f"\n" '
    ' f'
    {eyebrow}generated from canonical source — do not edit
    ' f"

    {html.escape(display)}

    " + (f'

    {html.escape(subtitle)}

    ' if subtitle else "") + source_line + review_line + '
    ' f'' f"
    {lifecycle_notice}{currency_notice}{body}" f'" "
    \n" ) return page, meta, len(rail) def main() -> int: ap = argparse.ArgumentParser() ap.add_argument("source", type=pathlib.Path) ap.add_argument("--output", required=True, type=pathlib.Path) ap.add_argument("--title", default=None) ap.add_argument("--subtitle", default="") args = ap.parse_args() page, _meta, section_count = render_page( args.source, title=args.title, subtitle=args.subtitle, ) args.output.parent.mkdir(parents=True, exist_ok=True) args.output.write_text(page, encoding="utf-8") print(f"{args.output}: {section_count} sections, {len(page)} bytes") return 0 if __name__ == "__main__": raise SystemExit(main())