feat(rex/comments): render combined.md → HTML for Zotero notes
Pure function over (str)→str. Reuses combine.parse_combined to peel off the YAML frontmatter, runs the body through markdown-it-py with table support enabled (CMS comments lean on tabular data). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
26
src/rex/comments/render.py
Normal file
26
src/rex/comments/render.py
Normal file
@@ -0,0 +1,26 @@
|
||||
"""Render combined.md → HTML for Zotero notes.
|
||||
|
||||
combined.md is the per-comment aggregate written by ``combine.extract_comment``:
|
||||
a YAML frontmatter block followed by an inline-body section and one H2 section
|
||||
per attachment. Zotero notes accept HTML, so we strip the frontmatter and run
|
||||
the body through markdown-it-py.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from markdown_it import MarkdownIt
|
||||
|
||||
from rex.comments.combine import parse_combined
|
||||
|
||||
_MD = MarkdownIt("commonmark", {"html": False, "breaks": False, "linkify": True})
|
||||
_MD.enable("table")
|
||||
|
||||
|
||||
def render_combined_md(text: str) -> str:
|
||||
"""Strip combined.md's YAML frontmatter, render body to HTML.
|
||||
|
||||
Raises ValueError if the input is missing frontmatter — combined.md
|
||||
always has it, so a missing block means the input isn't combined.md.
|
||||
"""
|
||||
_, body = parse_combined(text)
|
||||
return _MD.render(body)
|
||||
51
tests/rex/comments/test_render.py
Normal file
51
tests/rex/comments/test_render.py
Normal file
@@ -0,0 +1,51 @@
|
||||
"""rex.comments.render — combined.md → Zotero-edible HTML."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from rex.comments.render import render_combined_md
|
||||
|
||||
|
||||
def test_strips_frontmatter():
|
||||
md = "---\ncomment_id: CMS-2024-0001-0001\nstatus: ok\n---\n\n# Heading\n\nbody\n"
|
||||
html = render_combined_md(md)
|
||||
assert "comment_id" not in html
|
||||
assert "status: ok" not in html
|
||||
assert "<h1>Heading</h1>" in html
|
||||
assert "<p>body</p>" in html
|
||||
|
||||
|
||||
def test_renders_basic_markdown():
|
||||
md = "---\nstatus: ok\n---\n\n## Section\n\nText with **bold** and *italic*.\n"
|
||||
html = render_combined_md(md)
|
||||
assert "<h2>Section</h2>" in html
|
||||
assert "<strong>bold</strong>" in html
|
||||
assert "<em>italic</em>" in html
|
||||
|
||||
|
||||
def test_renders_tables():
|
||||
md = (
|
||||
"---\nstatus: ok\n---\n\n"
|
||||
"| Col A | Col B |\n"
|
||||
"| --- | --- |\n"
|
||||
"| a1 | b1 |\n"
|
||||
"| a2 | b2 |\n"
|
||||
)
|
||||
html = render_combined_md(md)
|
||||
assert "<table>" in html
|
||||
assert "<th>Col A</th>" in html
|
||||
assert "<td>a1</td>" in html
|
||||
|
||||
|
||||
def test_handles_empty_body():
|
||||
md = "---\nstatus: ok\n---\n\n"
|
||||
html = render_combined_md(md)
|
||||
assert html == "" or html.strip() == ""
|
||||
|
||||
|
||||
def test_raises_on_missing_frontmatter():
|
||||
"""combined.md is always written with frontmatter — guard against
|
||||
silently ingesting malformed input."""
|
||||
import pytest
|
||||
|
||||
with pytest.raises(ValueError, match="frontmatter"):
|
||||
render_combined_md("# No frontmatter here\n")
|
||||
Reference in New Issue
Block a user