Some prelim work on builder api.
[librarian.git] / src / librarian / builders / html.py
index f2177ae..66db675 100644 (file)
@@ -9,7 +9,45 @@ from librarian.html import add_table_of_contents, add_table_of_themes, add_image
 from librarian import OutputFile
 
 
 from librarian import OutputFile
 
 
-class HtmlBuilder:
+class TreeBuilder:
+    @property
+    def cursor(self):
+        return self.current_cursors[-1]
+
+    def enter_fragment(self, fragment):
+        cursor = self.cursors.get(fragment, self.cursor)
+        self.current_cursors.append(cursor)
+
+    def exit_fragment(self):
+        self.current_cursors.pop()
+
+    def create_fragment(self, name, element):
+        assert name not in self.cursors
+        self.cursors[name] = element
+
+    def forget_fragment(self, name):
+        del self.cursors[name]
+
+    def start_element(self, tag, attrib=None):
+        self.current_cursors.append(etree.SubElement(
+            self.cursor,
+            tag,
+            **(attrib or {})
+        ))
+
+    def end_element(self):
+        self.current_cursors.pop()
+
+    def push_text(self, text):
+        cursor = self.cursor
+        if len(cursor):
+            cursor[-1].tail = (cursor[-1].tail or '') + text
+        else:
+            cursor.text = (cursor.text or '') + text
+
+
+class HtmlBuilder(TreeBuilder):
+    build_method_fn = 'html_build'
     file_extension = "html"
     with_themes = True
     with_toc = True
     file_extension = "html"
     with_themes = True
     with_toc = True
@@ -32,7 +70,6 @@ class HtmlBuilder:
         self.header = etree.Element('h1')
 
         self.footnotes = etree.Element('div', id='footnotes')
         self.header = etree.Element('h1')
 
         self.footnotes = etree.Element('div', id='footnotes')
-        self.counters = defaultdict(lambda: 1)
 
         self.nota_red = etree.Element('div', id='nota_red')
 
 
         self.nota_red = etree.Element('div', id='nota_red')
 
@@ -51,28 +88,9 @@ class HtmlBuilder:
         else:
             return 'https://wolnelektury.pl/media/book/pictures/{}/'.format(self.document.meta.url.slug)
 
         else:
             return 'https://wolnelektury.pl/media/book/pictures/{}/'.format(self.document.meta.url.slug)
 
-    @property
-    def cursor(self):
-        return self.current_cursors[-1]
-
-    def enter_fragment(self, fragment):
-        cursor = self.cursors.get(fragment, self.cursor)
-        self.current_cursors.append(cursor)
-
-    def exit_fragment(self):
-        self.current_cursors.pop()
-
-    def create_fragment(self, name, element):
-        assert name not in self.cursors
-        self.cursors[name] = element
-
-    def forget_fragment(self, name):
-        del self.cursors[name]
-
     def build(self, document, element=None, **kwargs):
         self.document = document
     def build(self, document, element=None, **kwargs):
         self.document = document
-
-        self.assign_ids(self.document.tree)
+        self.document.assign_ids()
         self.prepare_images()
 
         if element is None:
         self.prepare_images()
 
         if element is None:
@@ -82,12 +100,6 @@ class HtmlBuilder:
         self.postprocess(document)
         return self.output()
 
         self.postprocess(document)
         return self.output()
 
-    def assign_ids(self, tree):
-        # Assign IDs depth-first, to account for any <numeracja> inside.
-        for _e, elem in etree.iterwalk(tree, events=('end',)):
-            if getattr(elem, 'NUMBERING', None):
-                elem.assign_id(self)
-
     def prepare_images(self):
         # Temporarily use the legacy method, before transitioning to external generators.
         if self.gallery_path is None:
     def prepare_images(self):
         # Temporarily use the legacy method, before transitioning to external generators.
         if self.gallery_path is None:
@@ -135,29 +147,12 @@ class HtmlBuilder:
         if self.with_toc:
             add_table_of_contents(self.tree)
 
         if self.with_toc:
             add_table_of_contents(self.tree)
 
-        if self.counters['fn'] > 1:
+        if len(self.footnotes):
             fnheader = etree.Element("h3")
             fnheader.text = _("Footnotes")
             self.footnotes.insert(0, fnheader)
             self.tree.append(self.footnotes)
 
             fnheader = etree.Element("h3")
             fnheader.text = _("Footnotes")
             self.footnotes.insert(0, fnheader)
             self.tree.append(self.footnotes)
 
-    def start_element(self, tag, attrib=None):
-        self.current_cursors.append(etree.SubElement(
-            self.cursor,
-            tag,
-            **(attrib or {})
-        ))
-
-    def end_element(self):
-        self.current_cursors.pop()
-
-    def push_text(self, text):
-        cursor = self.cursor
-        if len(cursor):
-            cursor[-1].tail = (cursor[-1].tail or '') + text
-        else:
-            cursor.text = (cursor.text or '') + text
-
     def add_visible_number(self, element):
         assert '_id' in element.attrib, etree.tostring(element)
         self.start_element('a', {
     def add_visible_number(self, element):
         assert '_id' in element.attrib, etree.tostring(element)
         self.start_element('a', {
@@ -240,6 +235,8 @@ class AbstraktHtmlBuilder(HtmlBuilder):
     def build(self, document, element=None, **kwargs):
         if element is None:
             element = document.tree.find('//abstrakt')
     def build(self, document, element=None, **kwargs):
         if element is None:
             element = document.tree.find('//abstrakt')
+        if element is None:
+            return OutputFile.from_bytes(b'')
         element.attrib['_force'] = '1'
         return super().build(document, element, **kwargs)
 
         element.attrib['_force'] = '1'
         return super().build(document, element, **kwargs)