138 lines
5.1 KiB
Python
138 lines
5.1 KiB
Python
from datetime import date
|
|
from zona.models import Item, ItemType
|
|
from zona.metadata import parse_metadata
|
|
from zona import markdown as zmd
|
|
from zona.templates import Templater
|
|
from zona.layout import Layout, discover_layout
|
|
from zona.config import ZonaConfig
|
|
from zona import util
|
|
from pathlib import Path
|
|
from rich import print
|
|
from zona.log import get_logger
|
|
|
|
logger = get_logger()
|
|
|
|
|
|
class ZonaBuilder:
|
|
def __init__(
|
|
self,
|
|
cli_root: Path | None = None,
|
|
cli_output: Path | None = None,
|
|
):
|
|
logger.debug("Initializing ZonaBuilder.")
|
|
self.layout: Layout = discover_layout(cli_root, cli_output)
|
|
self.config: ZonaConfig = ZonaConfig.from_file(
|
|
self.layout.root / "config.yml"
|
|
)
|
|
self.items: list[Item] = []
|
|
self.item_map: dict[Path, Item] = {}
|
|
|
|
def _discover(self):
|
|
layout = self.layout
|
|
items: list[Item] = []
|
|
|
|
base = layout.root / layout.content
|
|
logger.debug(f"Discovering content in {base}.")
|
|
for path in base.rglob("*"):
|
|
if path.is_file() and not util.should_ignore(
|
|
path, patterns=self.config.ignore, base=base
|
|
):
|
|
# we only parse markdown files not in static/
|
|
destination = layout.output / path.relative_to(base)
|
|
item = Item(
|
|
source=path,
|
|
destination=destination,
|
|
url=str(destination.relative_to(layout.output)),
|
|
)
|
|
if path.name.endswith(".md") and not path.is_relative_to(
|
|
layout.root / "content" / "static"
|
|
):
|
|
logger.debug(
|
|
f"Parsing {path.name} as Markdown document."
|
|
)
|
|
item.metadata, item.content = parse_metadata(path)
|
|
if item.metadata.post == True:
|
|
item.post = True
|
|
elif item.metadata.post is None:
|
|
# check if in posts dir?
|
|
blog_dir = base / Path(self.config.blog.dir)
|
|
if item.source.is_relative_to(blog_dir):
|
|
item.post = True
|
|
item.type = ItemType.MARKDOWN
|
|
item.copy = False
|
|
name = destination.stem
|
|
if name == "index":
|
|
item.destination = item.destination.with_suffix(
|
|
".html"
|
|
)
|
|
else:
|
|
relative = path.relative_to(base).with_suffix("")
|
|
name = relative.stem
|
|
item.destination = (
|
|
layout.output
|
|
/ relative.parent
|
|
/ name
|
|
/ "index.html"
|
|
)
|
|
rel_url = item.destination.parent.relative_to(
|
|
layout.output
|
|
)
|
|
item.url = (
|
|
"" if rel_url == Path(".") else rel_url.as_posix()
|
|
)
|
|
items.append(item)
|
|
# print(item)
|
|
self.items = items
|
|
|
|
def _build(self):
|
|
assert self.items
|
|
post_list: list[Item] = sorted(
|
|
[item for item in self.items if item.post],
|
|
key=lambda item: item.metadata.date
|
|
if item.metadata
|
|
else date.min,
|
|
reverse=True,
|
|
)
|
|
templater = Templater(
|
|
config=self.config,
|
|
template_dir=self.layout.templates,
|
|
post_list=post_list,
|
|
)
|
|
self.item_map = {
|
|
item.source.resolve(): item for item in self.items
|
|
}
|
|
|
|
# write code highlighting stylesheet
|
|
if self.config.markdown.syntax_highlighting.enabled:
|
|
pygments_style = zmd.get_style_defs(self.config)
|
|
pygments_path = self.layout.output / "static" / "pygments.css"
|
|
util.ensure_parents(pygments_path)
|
|
pygments_path.write_text(pygments_style)
|
|
for item in self.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(
|
|
config=self.config,
|
|
content=item.content,
|
|
resolve_links=True,
|
|
source=item.source,
|
|
layout=self.layout,
|
|
item_map=self.item_map,
|
|
)
|
|
# TODO: test this
|
|
rendered = templater.render_item(item, raw_html)
|
|
util.ensure_parents(dst)
|
|
dst.write_text(rendered, encoding="utf-8")
|
|
else:
|
|
if item.copy:
|
|
util.copy_static_file(item.source, dst)
|
|
|
|
def build(self):
|
|
logger.debug("Discovering...")
|
|
self._discover()
|
|
logger.debug("Building...")
|
|
self._build()
|