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