add header/footer template

This commit is contained in:
Daniel Fichtinger 2025-06-21 22:57:23 -04:00
parent d8b491bc33
commit 070c23720b
6 changed files with 54 additions and 17 deletions

View file

@ -12,6 +12,7 @@ dependencies = [
"jinja2>=3.1.6",
"marko[codehilite]>=2.1.4",
"python-frontmatter>=1.1.0",
"rich>=14.0.0",
"starlette>=0.47.1",
"typer>=0.16.0",
"uvicorn>=0.34.3",

View file

@ -1,6 +1,7 @@
from rich import print
from zona.models import Item, Metadata, ItemType
from zona import markdown as zmd
from zona import templates as tmpl
from zona.templates import Templater
from zona import util
from pathlib import Path
import frontmatter
@ -74,21 +75,24 @@ def discover(root: Path, out_dir: Path) -> list[Item]:
item.destination = (
out_dir / relative.parent / name / "index.html"
)
rel_url = item.destination.parent.relative_to(out_dir)
item.url = "" if rel_url == Path(".") else rel_url.as_posix()
items.append(item)
return items
def build(root: Path, items: list[Item]):
env = tmpl.init_templates(root / "templates")
templater = Templater(root / "templates")
for item in items:
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)
# TODO: test this
rendered = tmpl.render_item(item, raw_html, env)
rendered = templater.render_item(item, raw_html)
util.ensure_parents(dst)
dst.write_text(rendered, encoding="utf-8")
else:

View file

@ -9,9 +9,10 @@ class Metadata:
title: str
date: date
description: str | None
style: str | None = "static/style.css"
style: str | None = "/static/style.css"
header: bool = True
footer: bool = True
template: str = "page.html"
class ItemType(Enum):

View file

@ -1,19 +1,48 @@
from pathlib import Path
from jinja2 import Environment, FileSystemLoader, select_autoescape
from zona.models import Item
from zona.markdown import md_to_html
def init_templates(template_dir: Path) -> Environment:
return Environment(
loader=FileSystemLoader(template_dir),
autoescape=select_autoescape(["html", "xml"]),
)
def get_header(template_dir: Path) -> str | None:
md_header = template_dir / "header.md"
html_header = template_dir / "header.html"
if md_header.exists():
return md_to_html(md_header.read_text())
elif html_header.exists():
return html_header.read_text()
def render_item(item: Item, content: str, env: Environment) -> str:
template = env.get_template("post.html")
meta = item.metadata
assert meta is not None
return template.render(
title=meta.title, content=content, url=item.url, metadata=meta
)
def get_footer(template_dir: Path) -> str | None:
md_footer = template_dir / "footer.md"
html_footer = template_dir / "footer.html"
if md_footer.exists():
return md_to_html(md_footer.read_text())
elif html_footer.exists():
return html_footer.read_text()
class Templater:
def __init__(self, template_dir: Path):
self.env: Environment = Environment(
loader=FileSystemLoader(template_dir),
autoescape=select_autoescape(["html", "xml"]),
)
self.template_dir: Path = template_dir
self.header: str | None = get_header(template_dir)
self.footer: str | None = get_footer(template_dir)
def render_item(self, item: Item, content: str) -> str:
env = self.env
meta = item.metadata
assert meta is not None
template = env.get_template(meta.template)
header = self.header if self.header and meta.header else False
footer = self.footer if self.footer and meta.footer else False
return template.render(
content=content,
url=item.url,
metadata=meta,
header=header,
footer=footer,
)

View file

@ -147,7 +147,7 @@ p {
style.write_text(style_content)
items = discover(tmp_path, outd)
build(items)
build(tmp_path, items)
html = (outd / "post" / "index.html").read_text()
assert html.strip() == "<h1>Hello World</h1>"
s = (outd / "static" / "style.css").read_text()

2
uv.lock generated
View file

@ -382,6 +382,7 @@ dependencies = [
{ name = "jinja2" },
{ name = "marko", extra = ["codehilite"] },
{ name = "python-frontmatter" },
{ name = "rich" },
{ name = "starlette" },
{ name = "typer" },
{ name = "uvicorn" },
@ -400,6 +401,7 @@ requires-dist = [
{ name = "jinja2", specifier = ">=3.1.6" },
{ name = "marko", extras = ["codehilite"], specifier = ">=2.1.4" },
{ name = "python-frontmatter", specifier = ">=1.1.0" },
{ name = "rich", specifier = ">=14.0.0" },
{ name = "starlette", specifier = ">=0.47.1" },
{ name = "typer", specifier = ">=0.16.0" },
{ name = "uvicorn", specifier = ">=0.34.3" },