diff --git a/build.py b/build.py
index 3e8b1db..f86c6e7 100644
--- a/build.py
+++ b/build.py
@@ -16,6 +16,7 @@ dl.download_edition("N")
dl.download_question_metadata()
dl.download_pictures()
dl.download_photos()
+dl.download_includes()
dl.download_snippets()
dl.download_content()
diff --git a/renderer/fifty_ohm_html_renderer.py b/renderer/fifty_ohm_html_renderer.py
index 72f929a..c2e9c1e 100644
--- a/renderer/fifty_ohm_html_renderer.py
+++ b/renderer/fifty_ohm_html_renderer.py
@@ -8,6 +8,7 @@ from mistletoe import Document, HtmlRenderer
from .comment import BlockComment
from .dash import Dash
from .halfwidth_spaces import HalfwidthSpaces
+from .include import Include
from .morse import Morse
from .nonbreaking_spaces import NonbreakingSpaces, NonbreakingSpacesDots
from .photo import Photo
@@ -30,7 +31,14 @@ class FiftyOhmHtmlRenderer(HtmlRenderer):
section_url = "section.html"
ref_id = 0
- def __init__(self, *extras, question_renderer=None, picture_handler=None, photo_handler=None):
+ def __init__(
+ self,
+ *extras,
+ question_renderer=None,
+ picture_handler=None,
+ photo_handler=None,
+ include_handler=None
+ ):
final_extras = chain(extras,(
Dash,
@@ -49,6 +57,7 @@ class FiftyOhmHtmlRenderer(HtmlRenderer):
Photo,
Table,
Qso,
+ Include,
))
super().__init__(*final_extras)
@@ -56,6 +65,7 @@ class FiftyOhmHtmlRenderer(HtmlRenderer):
self.question_renderer = question_renderer
self.picture_handler = picture_handler
self.photo_handler = photo_handler
+ self.include_handler = include_handler
def render_dash(self, token):
return " – "
@@ -233,3 +243,6 @@ class FiftyOhmHtmlRenderer(HtmlRenderer):
table += ""
return table
+
+ def render_include(self, token):
+ return self.include_handler(token.ident)
diff --git a/renderer/include.py b/renderer/include.py
new file mode 100644
index 0000000..9f2a690
--- /dev/null
+++ b/renderer/include.py
@@ -0,0 +1,24 @@
+import re
+
+from mistletoe.block_token import BlockToken
+
+
+class Include(BlockToken):
+ """
+ Block token ("[include:ident]").
+ Includes raw html or javascript code from a file with the given identifier.
+ """
+
+ @staticmethod
+ def start(line):
+ return re.match(r"^\s*\[include:\s*[^\]]+\]", line)
+
+ @classmethod
+ def read(cls, lines):
+ re.compile(r'')
+ line = next(lines) # Consume the line with the include directive
+ ident = re.match(r"^\s*\[include:\s*([^\]]+)\]", line).group(1)
+ return ident
+
+ def __init__(self, match):
+ self.ident = match
\ No newline at end of file
diff --git a/src/build.py b/src/build.py
index ea9364a..d915ce9 100644
--- a/src/build.py
+++ b/src/build.py
@@ -138,6 +138,11 @@ class Build:
result = self.__build_page(result, course_wrapper=True)
file.write(result)
+ def __include_handler(self, include):
+ with open("data/includes.json") as file:
+ includes = json.load(file)
+ return includes.get(include)
+
# cached
def __build_section(self, edition, edition_name, section, section_id, chapter, next_section=None, next_chapter=None):
section_template = self.env.get_template("html/section.html")
@@ -148,7 +153,8 @@ class Build:
with FiftyOhmHtmlRenderer(
question_renderer=self.__build_question,
picture_handler=self.__picture_handler,
- photo_handler=self.__photo_handler
+ photo_handler=self.__photo_handler,
+ include_handler=self.__include_handler
) as renderer:
section["content"] = renderer.render(Document(section["content"]))
@@ -182,34 +188,8 @@ class Build:
with FiftyOhmHtmlSlideRenderer(
question_renderer=self.__build_question_slide,
picture_handler=self.__picture_handler,
- photo_handler=self.__photo_handler
- ) as renderer:
- result = "\n"
- result += f'\n'
- result += help_template.render()
- result += "\n"
- for section in sections:
- tmp = f'\n'
- tmp += renderer.render_wrapper(section["slide"])
- result += f"\n"
- result += next_template.render(
- edition=edition,
- next_chapter=next_chapter,
- chapter=chapter,
- )
-
- result = slide_template.render(content=result)
- file.write(result)
-
- def __build_chapter_slidedeck(self, edition, chapter, sections, next_chapter):
- with open(f'build/{edition}_slide_{chapter["ident"]}.html', 'w') as file:
- slide_template = self.env.get_template("slide/slide.html")
- help_template = self.env.get_template("slide/help.html")
- next_template = self.env.get_template("slide/next.html")
- with FiftyOhmHtmlSlideRenderer(
- question_renderer=self.__build_question_slide,
- picture_handler=self.__picture_handler,
- photo_handler=self.__photo_handler
+ photo_handler=self.__photo_handler,
+ include_handler=self.__include_handler
) as renderer:
result = "\n"
result += f'\n'
@@ -286,7 +266,8 @@ class Build:
with FiftyOhmHtmlRenderer(
question_renderer=self.__build_question,
picture_handler=self.__picture_handler,
- photo_handler=self.__photo_handler
+ photo_handler=self.__photo_handler,
+ include_handler=self.__include_handler
) as renderer:
for key, value in snippets.items():
snippets[key] = renderer.render_inner(Document(value))
diff --git a/src/download.py b/src/download.py
index 0488f11..9295825 100644
--- a/src/download.py
+++ b/src/download.py
@@ -133,6 +133,16 @@ class Download:
delayed(build_picture)(picture) for picture in tqdm(pictures, desc="Build All Pictures")
)
+ def download_includes(self):
+ includes = self.api.get("items/include", params={"limit": -1})
+
+ result = {}
+ for include in tqdm(includes, desc="Downloading includes"):
+ result[include["ident"]] = include["content"]
+
+ with open("data/includes.json", "w") as f:
+ json.dump(result, f, indent=4)
+
def download_snippets(self):
snippets = {}
for snippet in tqdm(self.content_api.get("items/snippet"), desc="Downloading snippets"):
@@ -152,4 +162,4 @@ class Download:
)
with open("data/content.json", "w", encoding="utf-8") as file:
- json.dump(contents, file, ensure_ascii=False, indent=4)
\ No newline at end of file
+ json.dump(contents, file, ensure_ascii=False, indent=4)
diff --git a/test/acceptanceTest.md b/test/acceptanceTest.md
index 97e5bcd..0fb2698 100644
--- a/test/acceptanceTest.md
+++ b/test/acceptanceTest.md
@@ -1,5 +1,7 @@
% Kommentar: DARC-DOWN-TEST
+[include:test]
+
Das ist eine Item-Liste:
* Erster Eintrag
diff --git a/test/test_html.py b/test/test_html.py
index ec20f45..05b8964 100644
--- a/test/test_html.py
+++ b/test/test_html.py
@@ -69,12 +69,19 @@ def question_stub(input):
answer_pictures=answer_pictures,
)
+def include_stub(include):
+ with open("data/includes.json") as file:
+ includes = json.load(file)
+ return includes.get(include)
def test_html(capsys):
with capsys.disabled():
with open("test/acceptanceTest.md") as file:
content = file.read()
- with FiftyOhmHtmlRenderer(question_renderer=question_stub) as renderer:
+ with FiftyOhmHtmlRenderer(
+ question_renderer=question_stub,
+ include_handler=include_stub,
+ ) as renderer:
output = renderer.render(Document(content))
with open("test/acceptanceTest.html", "w") as output_file:
pretty = BeautifulSoup(output, "html.parser").prettify()
diff --git a/test/test_include.py b/test/test_include.py
new file mode 100644
index 0000000..24c02f7
--- /dev/null
+++ b/test/test_include.py
@@ -0,0 +1,18 @@
+import pytest
+from mistletoe import Document
+
+from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
+
+
+@pytest.mark.html
+def test_include_html():
+ assertions = {
+ '[include:ident]': "ident\n",
+ }
+
+ def test_function(input):
+ return f"{input}"
+
+ with FiftyOhmHtmlRenderer(include_handler=test_function) as renderer:
+ for assertion in assertions:
+ assert renderer.render(Document(assertion)) == assertions[assertion]
\ No newline at end of file