Markdown to HTML with fenced code, codehilite, toc and tables: working versions (tested 2026-10-16)
Render Markdown with Python-Markdown extensions and Pygments highlighting, extract a nested table of contents, and generate the matching Pygments CSS.
passed6 passed · 0 failed2026-10-16 21:57 UTC- Status
- passed
- Last passed
- 2026-10-16 21:57 UTC
- Tests
- 6 / 6
- Language
- Python
- Runtime
- Python 3.13.16
pinned versions3
markdown@3.11.1pygments@2.21.0pytest@9.1.1
run it
uv venv -q .venv && uv pip install -q --python .venv/bin/python -r requirements.txt .venv/bin/python -m pytest -q
test environment
Python 3.13.16 linux 6.17.0-1022-azure x64 runner: github-actions 38972656245
The code
Exactly the files that passed. Your agent can pull them with get_recipe("markdown-pygments-codehilite") (install), or see them on GitHub.
requirements.txt
markdown==3.11.1 pygments==2.21.0 pytest==9.1.1
renderer.py
import markdown
from pygments.formatters import HtmlFormatter
EXTENSIONS = ["fenced_code", "codehilite", "toc", "tables"]
EXTENSION_CONFIGS = {
"codehilite": {"guess_lang": False, "css_class": "codehilite"},
"toc": {"permalink": False},
}
def make_markdown() -> markdown.Markdown:
return markdown.Markdown(
extensions=EXTENSIONS, extension_configs=EXTENSION_CONFIGS
)
def render(text: str) -> str:
return make_markdown().convert(text)
def toc_tokens(text: str) -> list[dict]:
md = make_markdown()
md.convert(text)
return md.toc_tokens
def toc_html(text: str) -> str:
md = make_markdown()
md.convert(text)
return md.toc
def pygments_css(style: str = "default", css_class: str = "codehilite") -> str:
return HtmlFormatter(style=style).get_style_defs(f".{css_class}")
tests/test_renderer.py
from renderer import make_markdown, pygments_css, render, toc_html, toc_tokens
def test_fenced_python_is_highlighted():
html = render("```python\ndef add(x, y):\n return x + y\n```")
assert 'class="codehilite"' in html
assert '<span class="k">def</span>' in html
def test_unlabeled_fence_is_not_guessed():
html = render("```\nclass Foo:\n bar = 1\n```")
assert 'class="codehilite"' in html
assert 'class="k"' not in html
def test_toc_tokens_are_nested_and_slugified():
tokens = toc_tokens("# Title\n## Child Section\n### Deep\n## Sibling")
assert tokens[0]["id"] == "title"
children = tokens[0]["children"]
assert [c["id"] for c in children] == ["child-section", "sibling"]
assert children[0]["children"][0]["level"] == 3
assert toc_html("# Title").count("<li>") == 1
def test_reusing_instance_resets_toc():
md = make_markdown()
md.convert("# One")
md.convert("# Two")
assert [t["id"] for t in md.toc_tokens] == ["two"]
def test_tables_and_code_are_escaped():
html = render("| a | b |\n|---|---|\n| 1 | 2 |\n\n```\n<script>alert(1)</script>\n```")
assert "<table>" in html
assert "<script>" not in html
assert "<script>" in html
def test_pygments_css_prefix_matches_the_css_class():
assert ".codehilite .k" in pygments_css()
assert ".highlight .k" in pygments_css(css_class="highlight")
assert ".codehilite .k" not in pygments_css(css_class="highlight")
pytest.ini
[pytest] pythonpath = .
Connect to ProvenPin
Add the free MCP server so your agent can pull this recipe and others like it. Same setup as the docs.
terminal
claude mcp add --transport http provenpin https://mcp.provenpin.com/mcp
~/.cursor/mcp.json
{ "mcpServers": { "provenpin": { "url": "https://mcp.provenpin.com/mcp" } } }.vscode/mcp.json
{ "servers": { "provenpin": { "type": "http", "url": "https://mcp.provenpin.com/mcp" } } }~/.codeium/windsurf/mcp_config.json
{ "mcpServers": { "provenpin": { "serverUrl": "https://mcp.provenpin.com/mcp" } } }MCP settings
{ "mcpServers": { "provenpin": { "type": "streamableHttp", "url": "https://mcp.provenpin.com/mcp" } } }Any other MCP client: Streamable HTTP at https://mcp.provenpin.com/mcp. No API key, no signup.