add builder
This commit is contained in:
parent
d558d1c5e1
commit
b045739b45
4 changed files with 93 additions and 15 deletions
|
@ -1,4 +1,6 @@
|
||||||
from zona.models import Item, Metadata
|
from zona.models import Item, Metadata, ItemType
|
||||||
|
from zona import markdown as zmd
|
||||||
|
from zona import util
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import frontmatter
|
import frontmatter
|
||||||
from dacite import from_dict
|
from dacite import from_dict
|
||||||
|
@ -29,20 +31,35 @@ def discover(root: Path, out_dir: Path) -> list[Item]:
|
||||||
for path in base.rglob("*"):
|
for path in base.rglob("*"):
|
||||||
if path.is_file():
|
if path.is_file():
|
||||||
print(f"{subdir}: {path.relative_to(root)}")
|
print(f"{subdir}: {path.relative_to(root)}")
|
||||||
if path.name.endswith(".md") and not path.is_relative_to(
|
# we only parse markdown files not in static/
|
||||||
root / "content" / "static"
|
|
||||||
):
|
|
||||||
meta, content = split_metadata(path)
|
|
||||||
else:
|
|
||||||
meta = None
|
|
||||||
content = path.read_bytes()
|
|
||||||
destination = out_dir / path.relative_to(base)
|
destination = out_dir / path.relative_to(base)
|
||||||
item = Item(
|
item = Item(
|
||||||
source=path,
|
source=path,
|
||||||
destination=destination,
|
destination=destination,
|
||||||
url=str(destination.relative_to(out_dir)),
|
url=str(destination.relative_to(out_dir)),
|
||||||
metadata=meta,
|
|
||||||
content=content,
|
|
||||||
)
|
)
|
||||||
|
if path.name.endswith(".md") and not path.is_relative_to(
|
||||||
|
root / "content" / "static"
|
||||||
|
):
|
||||||
|
item.metadata, item.content = split_metadata(path)
|
||||||
|
item.type = ItemType.MARKDOWN
|
||||||
|
item.copy = False
|
||||||
|
item.destination = destination.with_suffix(".html")
|
||||||
items.append(item)
|
items.append(item)
|
||||||
return items
|
return items
|
||||||
|
|
||||||
|
|
||||||
|
def build(items: list[Item]):
|
||||||
|
for item in items:
|
||||||
|
dst = item.destination
|
||||||
|
# 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: apply to template here
|
||||||
|
util.ensure_parents(dst)
|
||||||
|
dst.write_text(raw_html, encoding="utf-8")
|
||||||
|
else:
|
||||||
|
if item.copy:
|
||||||
|
util.copy_static_file(item.source, dst)
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from enum import Enum
|
||||||
from datetime import date
|
from datetime import date
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
from typing import Literal
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
|
@ -11,10 +13,18 @@ class Metadata:
|
||||||
# add more options later...
|
# add more options later...
|
||||||
|
|
||||||
|
|
||||||
|
class ItemType(Enum):
|
||||||
|
MARKDOWN = "markdown"
|
||||||
|
HTML = "html"
|
||||||
|
IMAGE = "image"
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Item:
|
class Item:
|
||||||
source: Path
|
source: Path
|
||||||
destination: Path
|
destination: Path
|
||||||
url: str # relative to site root
|
url: str # relative to site root
|
||||||
metadata: Metadata | None # frontmatter
|
metadata: Metadata | None = None # frontmatter
|
||||||
content: str | bytes
|
content: str | None = None
|
||||||
|
type: ItemType | None = None
|
||||||
|
copy: bool = True
|
||||||
|
|
13
src/zona/util.py
Normal file
13
src/zona/util.py
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
from pathlib import Path
|
||||||
|
from shutil import copy2
|
||||||
|
|
||||||
|
|
||||||
|
def ensure_parents(target: Path):
|
||||||
|
"""Ensure the target's parent directories exist."""
|
||||||
|
target.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
|
||||||
|
def copy_static_file(src: Path, dst: Path):
|
||||||
|
"""Copy a static file from one location to another."""
|
||||||
|
ensure_parents(dst)
|
||||||
|
copy2(src, dst)
|
|
@ -1,6 +1,6 @@
|
||||||
from datetime import date
|
from datetime import date
|
||||||
from zona.models import Metadata
|
from zona.models import Metadata
|
||||||
from zona.builder import split_metadata, discover
|
from zona.builder import split_metadata, discover, build
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
@ -43,12 +43,13 @@ description: This is a test.
|
||||||
""")
|
""")
|
||||||
|
|
||||||
style = staticd / "style.css"
|
style = staticd / "style.css"
|
||||||
style.write_text("""
|
style_content = """
|
||||||
p {
|
p {
|
||||||
color: red;
|
color: red;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
""")
|
"""
|
||||||
|
style.write_text(style_content)
|
||||||
|
|
||||||
items = discover(tmp_path, outd)
|
items = discover(tmp_path, outd)
|
||||||
|
|
||||||
|
@ -61,6 +62,7 @@ p {
|
||||||
assert md_item.url == "post.md"
|
assert md_item.url == "post.md"
|
||||||
assert isinstance(md_item.metadata, Metadata)
|
assert isinstance(md_item.metadata, Metadata)
|
||||||
assert md_item.metadata.title == "Test Post"
|
assert md_item.metadata.title == "Test Post"
|
||||||
|
assert md_item.content is not None
|
||||||
assert md_item.content.strip() == "# Hello World"
|
assert md_item.content.strip() == "# Hello World"
|
||||||
|
|
||||||
st_item = items[1]
|
st_item = items[1]
|
||||||
|
@ -69,3 +71,39 @@ p {
|
||||||
assert st_item.destination.is_relative_to(outd)
|
assert st_item.destination.is_relative_to(outd)
|
||||||
assert st_item.url == "static/style.css"
|
assert st_item.url == "static/style.css"
|
||||||
assert st_item.metadata is None
|
assert st_item.metadata is None
|
||||||
|
|
||||||
|
|
||||||
|
def test_build(tmp_path: Path):
|
||||||
|
contentd = tmp_path / "content"
|
||||||
|
staticd = contentd / "static"
|
||||||
|
templatesd = tmp_path / "templates"
|
||||||
|
outd = tmp_path / "out"
|
||||||
|
|
||||||
|
for d in [contentd, staticd, templatesd, outd]:
|
||||||
|
d.mkdir()
|
||||||
|
md_file = contentd / "post.md"
|
||||||
|
md_content = """---
|
||||||
|
title: Test Post
|
||||||
|
date: 2025-06-03
|
||||||
|
description: This is a test.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Hello World
|
||||||
|
"""
|
||||||
|
md_file.write_text(md_content)
|
||||||
|
|
||||||
|
style = staticd / "style.css"
|
||||||
|
style_content = """
|
||||||
|
p {
|
||||||
|
color: red;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
style.write_text(style_content)
|
||||||
|
|
||||||
|
items = discover(tmp_path, outd)
|
||||||
|
build(items)
|
||||||
|
html = (outd / "post.html").read_text()
|
||||||
|
assert html.strip() == "<h1>Hello World</h1>"
|
||||||
|
s = (outd / "static" / "style.css").read_text()
|
||||||
|
assert s.strip() == style_content.strip()
|
Loading…
Add table
Add a link
Reference in a new issue