relative link resolution working
This commit is contained in:
parent
2c4de0b72d
commit
3b9a653e34
4 changed files with 43 additions and 17 deletions
|
@ -1,5 +1,5 @@
|
|||
from rich import print
|
||||
from zona.models import Item, Metadata, ItemType
|
||||
from zona.models import Item, Metadata, ItemType, BuildCtx
|
||||
from zona import markdown as zmd
|
||||
from zona.templates import Templater
|
||||
from zona import util
|
||||
|
@ -82,17 +82,23 @@ def discover(root: Path, out_dir: Path) -> list[Item]:
|
|||
|
||||
|
||||
def build(root: Path, items: list[Item]):
|
||||
ctx = BuildCtx(root=root)
|
||||
templater = Templater(root / "templates")
|
||||
item_map = {item.source.resolve(): item for item in items}
|
||||
ctx.item_map = {item.source.resolve(): item for item in items}
|
||||
# print(item_map)
|
||||
for item in item_map.values():
|
||||
for item in ctx.item_map.values():
|
||||
dst = item.destination
|
||||
# print(item)
|
||||
# create parent dirs if needed
|
||||
if item.type == ItemType.MARKDOWN:
|
||||
assert item.content is not None
|
||||
# parse markdown and render as html
|
||||
raw_html = zmd.md_to_html(item.content)
|
||||
raw_html = zmd.md_to_html(
|
||||
content=item.content,
|
||||
resolve_links=True,
|
||||
source=item.source,
|
||||
ctx=ctx,
|
||||
)
|
||||
# TODO: test this
|
||||
rendered = templater.render_item(item, raw_html)
|
||||
util.ensure_parents(dst)
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
from rich import print
|
||||
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
|
||||
from zona.models import BuildCtx, Item
|
||||
from zona import util
|
||||
|
||||
|
||||
class ZonaRenderer(HTMLRenderer):
|
||||
|
@ -13,28 +14,31 @@ class ZonaRenderer(HTMLRenderer):
|
|||
self,
|
||||
resolve: bool = False,
|
||||
source: Path | None = None,
|
||||
item_map: dict[Path, Item] | None = None,
|
||||
ctx: BuildCtx | None = None,
|
||||
):
|
||||
# print("Zona renderer initializing...")
|
||||
super().__init__()
|
||||
self.resolve: bool = resolve
|
||||
if self.resolve:
|
||||
# print("Resolve is set")
|
||||
assert source is not None
|
||||
assert item_map is not None
|
||||
assert ctx is not None
|
||||
self.source: Path = source.resolve()
|
||||
self.map: dict[Path, Item] = item_map
|
||||
self.ctx: BuildCtx = ctx
|
||||
|
||||
# TODO: resolve relative links and replace with url?
|
||||
@override
|
||||
def render_link(self, element: Link):
|
||||
href = element.dest
|
||||
print(f"Rendering link, original: {href}")
|
||||
assert isinstance(href, str)
|
||||
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
|
||||
_href = href
|
||||
resolved = (self.source.parent / cur).resolve()
|
||||
if resolved.exists():
|
||||
href = util.normalize_url(self.ctx.item_map[resolved].url)
|
||||
print(f"Link in file {self.source}: {_href} resolved to {href}")
|
||||
body: Any = self.render_children(element)
|
||||
return f'<a href="{href}" target="_blank">{body}</a>'
|
||||
|
||||
|
@ -56,9 +60,13 @@ def md_to_html(
|
|||
content: str,
|
||||
resolve_links: bool = False,
|
||||
source: Path | None = None,
|
||||
item_map: dict[Path, Item] | None = None,
|
||||
ctx: BuildCtx | None = None,
|
||||
) -> str:
|
||||
if resolve_links and (source is None or ctx is None):
|
||||
raise TypeError(
|
||||
"md_to_html() missing source and ctx when resolve_links is true"
|
||||
)
|
||||
parser = Parser()
|
||||
ast = parser.parse(content)
|
||||
renderer = ZonaRenderer(resolve_links, source, item_map)
|
||||
renderer = ZonaRenderer(resolve_links, source, ctx)
|
||||
return renderer.render(ast)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from pathlib import Path
|
||||
from enum import Enum
|
||||
from datetime import date
|
||||
from dataclasses import dataclass
|
||||
from dataclasses import dataclass, field
|
||||
|
||||
|
||||
@dataclass
|
||||
|
@ -30,3 +30,9 @@ class Item:
|
|||
content: str | None = None
|
||||
type: ItemType | None = None
|
||||
copy: bool = True
|
||||
|
||||
|
||||
@dataclass
|
||||
class BuildCtx:
|
||||
root: Path
|
||||
item_map: dict[Path, Item] = field(default_factory=dict)
|
||||
|
|
|
@ -18,3 +18,9 @@ def filename_to_title(path: Path) -> str:
|
|||
name = path.stem
|
||||
words = name.replace("-", " ").replace("_", " ")
|
||||
return string.capwords(words)
|
||||
|
||||
|
||||
def normalize_url(url: str) -> str:
|
||||
if not url.startswith("/"):
|
||||
url = "/" + url
|
||||
return url
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue