From 1f1037dd013171ea26ec260778e76601bf89ef7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Corentin=20S=C3=A9chet?= Date: Mon, 20 May 2024 12:14:09 +0200 Subject: [PATCH] feat: add Site class to render pages --- jwebsite/content.py | 3 ++- jwebsite/site.py | 28 ++++++++++++++++++++++++++++ pyproject.toml | 6 ++++-- tests/test_site.py | 19 +++++++++++++++++++ tests/test_site/content/otters.yml | 1 + tests/test_site/src/index.j2 | 3 +++ 6 files changed, 57 insertions(+), 3 deletions(-) create mode 100644 jwebsite/site.py create mode 100644 tests/test_site.py create mode 100644 tests/test_site/content/otters.yml create mode 100644 tests/test_site/src/index.j2 diff --git a/jwebsite/content.py b/jwebsite/content.py index eaf9e7f..bbad7fb 100644 --- a/jwebsite/content.py +++ b/jwebsite/content.py @@ -16,7 +16,8 @@ class Content: class ContentDirectory(Content): - def load(self, subpath: Path) -> Content: + def load(self, subpath: str | Path) -> Content: + subpath = Path(subpath) current: Content = self for part in subpath.parts: if not isinstance(current, ContentDirectory): diff --git a/jwebsite/site.py b/jwebsite/site.py new file mode 100644 index 0000000..61935de --- /dev/null +++ b/jwebsite/site.py @@ -0,0 +1,28 @@ +from pathlib import Path +from typing import Any + +from jinja2.environment import Environment +from jinja2.loaders import FileSystemLoader + +from jwebsite.content import ContentDirectory + + +class Site: + def __init__(self, root_directory: Path) -> None: + self.__root_directory = root_directory + self.__output_directory = root_directory / "build" + self.__environment = Environment(loader=FileSystemLoader(searchpath=root_directory / "src")) + self.__content = ContentDirectory(root_directory / "content") + + @property + def content(self) -> ContentDirectory: + return self.__content + + def render(self, source: str, output: str | Path, **context: Any) -> None: + self.__output_directory.mkdir(parents=True, exist_ok=True) + template = self.__environment.get_template(source) + content = template.render(site=self, **context) + output_path = self.__output_directory / output + + with open(output_path, "w") as output_file: + output_file.write(content) diff --git a/pyproject.toml b/pyproject.toml index c2b1713..892f75e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,16 +14,18 @@ dependencies = [ "click", "jinja2", "markdown", - "pyyaml", "markdown-full-yaml-metadata", + "marshmallow", + "pyyaml", ] [project.optional-dependencies] dev = [ "nox", + "pyfakefs", "pytest", - "pytest-datadir", "pytest-coverage", + "pytest-datadir", ] [project.scripts] diff --git a/tests/test_site.py b/tests/test_site.py new file mode 100644 index 0000000..6d00504 --- /dev/null +++ b/tests/test_site.py @@ -0,0 +1,19 @@ +from pathlib import Path + +from pyfakefs.fake_filesystem import FakeFilesystem +from pytest import fixture + +from jwebsite.site import Site + + +@fixture +def site_dir(datadir: Path, fs: FakeFilesystem): + fs.add_real_directory(datadir) + yield fs + + +def test_render_page(datadir: Path, site_dir: FakeFilesystem): + site = Site(datadir) + site.render("index.j2", "index.html") + with open(datadir / "build" / "index.html", encoding="utf-8") as ouput_file: + assert ouput_file.read() == "

Peter

Steven

" diff --git a/tests/test_site/content/otters.yml b/tests/test_site/content/otters.yml new file mode 100644 index 0000000..3826f38 --- /dev/null +++ b/tests/test_site/content/otters.yml @@ -0,0 +1 @@ +[Peter, Steven] diff --git a/tests/test_site/src/index.j2 b/tests/test_site/src/index.j2 new file mode 100644 index 0000000..33f66bd --- /dev/null +++ b/tests/test_site/src/index.j2 @@ -0,0 +1,3 @@ +{%- for otter in site.content.load('otters.yml') -%} +

{{ otter }}

+{%- endfor %}