add link resolution to markdown renderer

This commit is contained in:
Daniel Fichtinger 2025-06-21 23:50:27 -04:00
parent 070c23720b
commit 2c4de0b72d
2 changed files with 40 additions and 8 deletions

View file

@ -83,9 +83,11 @@ def discover(root: Path, out_dir: Path) -> list[Item]:
def build(root: Path, items: list[Item]):
templater = Templater(root / "templates")
for item in items:
item_map = {item.source.resolve(): item for item in items}
# print(item_map)
for item in item_map.values():
dst = item.destination
print(item)
# print(item)
# create parent dirs if needed
if item.type == ItemType.MARKDOWN:
assert item.content is not None

View file

@ -1,19 +1,42 @@
from typing import Any, override
from pathlib import Path
from marko import Markdown
from marko.inline import Link, Image
from marko.html_renderer import HTMLRenderer
from marko.parser import Parser
from zona.models import Item
class ZonaRenderer(HTMLRenderer):
def __init__(
self,
resolve: bool = False,
source: Path | None = None,
item_map: dict[Path, Item] | None = None,
):
super().__init__()
self.resolve: bool = resolve
if self.resolve:
assert source is not None
assert item_map is not None
self.source: Path = source.resolve()
self.map: dict[Path, Item] = item_map
# TODO: resolve relative links and replace with url?
@override
def render_link(self, element: Link):
href = element.dest
assert isinstance(href, str)
if href.endswith(".md") and not href.startswith("http"):
href = href[:-3] + ".html"
if self.resolve:
cur = Path(href)
# TODO: fix relative path issue
if not href.startswith(("http", "https")) and cur.is_relative_to(
self.source
):
href = self.map[self.source].url
body: Any = self.render_children(element)
return f'<a href="{href}" target="_blank"{body}</a>'
return f'<a href="{href}" target="_blank">{body}</a>'
@override
def render_image(self, element: Image):
@ -29,6 +52,13 @@ class ZonaRenderer(HTMLRenderer):
)
def md_to_html(content: str) -> str:
md = Markdown(renderer=ZonaRenderer)
return md.convert(content)
def md_to_html(
content: str,
resolve_links: bool = False,
source: Path | None = None,
item_map: dict[Path, Item] | None = None,
) -> str:
parser = Parser()
ast = parser.parse(content)
renderer = ZonaRenderer(resolve_links, source, item_map)
return renderer.render(ast)