1 # This file is part of Librarian, licensed under GNU Affero GPLv3 or later.
2 # Copyright © Fundacja Wolne Lektury. See NOTICE for more information.
4 from urllib.request import urlopen
6 from librarian.html import add_anchors, add_table_of_contents, add_table_of_themes
7 from librarian import OutputFile
11 file_extension = "html"
17 no_externalities = False
20 def __init__(self, base_url=None):
21 self._base_url = base_url
23 self.tree = text = etree.Element('div', **{'id': 'book-text'})
24 self.header = etree.Element('h1')
26 self.footnotes = etree.Element('div', id='footnotes')
27 self.footnote_counter = 0
29 self.nota_red = etree.Element('div', id='nota_red')
33 'header': self.header,
34 'footnotes': self.footnotes,
35 'nota_red': self.nota_red,
37 self.current_cursors = [text]
41 if self._base_url is not None:
44 return 'https://wolnelektury.pl/media/book/pictures/{}/'.format(self.document.meta.url.slug)
48 return self.current_cursors[-1]
50 def enter_fragment(self, fragment):
51 cursor = self.cursors.get(fragment, self.cursor)
52 self.current_cursors.append(cursor)
54 def exit_fragment(self):
55 self.current_cursors.pop()
57 def create_fragment(self, name, element):
58 assert name not in self.cursors
59 self.cursors[name] = element
61 def forget_fragment(self, name):
62 del self.cursors[name]
64 def preprocess(self, document):
65 document._compat_assign_ordered_ids()
66 document._compat_assign_section_ids()
68 def build(self, document, **kwargs):
69 self.document = document
71 self.preprocess(document)
72 document.tree.getroot().html_build(self)
73 self.postprocess(document)
77 return OutputFile.from_bytes(
86 def postprocess(self, document):
87 _ = document.tree.getroot().master.gettext
89 if document.meta.translators:
90 self.enter_fragment('header')
91 self.start_element('span', {'class': 'translator'})
92 self.push_text(_("translated by") + " ")
96 for translator in document.meta.translators
102 self.tree.insert(0, self.header)
104 if self.with_anchors:
105 add_anchors(self.tree)
106 if self.with_nota_red and len(self.nota_red):
107 self.tree.append(self.nota_red)
109 add_table_of_themes(self.tree)
111 add_table_of_contents(self.tree)
113 if self.footnote_counter:
114 fnheader = etree.Element("h3")
115 fnheader.text = _("Footnotes")
116 self.footnotes.insert(0, fnheader)
117 self.tree.append(self.footnotes)
119 def start_element(self, tag, attrib=None):
120 self.current_cursors.append(etree.SubElement(
126 def end_element(self):
127 self.current_cursors.pop()
129 def push_text(self, text):
132 cursor[-1].tail = (cursor[-1].tail or '') + text
134 cursor.text = (cursor.text or '') + text
137 class StandaloneHtmlBuilder(HtmlBuilder):
138 css_url = "https://static.wolnelektury.pl/css/compressed/book_text.css"
140 def postprocess(self, document):
141 super(StandaloneHtmlBuilder, self).postprocess(document)
143 tree = etree.Element('html')
144 body = etree.SubElement(tree, 'body')
145 body.append(self.tree)
148 head = etree.Element('head')
152 etree.SubElement(head, 'meta', charset='utf-8')
153 etree.SubElement(head, 'title').text = document.meta.title
159 content="width=device-width, initial-scale=1, maximum-scale=1"
162 if self.no_externalities:
165 ).text = urlopen(self.css_url).read().decode('utf-8')
177 src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"
183 src="http://malsup.github.io/min/jquery.cycle2.min.js"
187 class SnippetHtmlBuilder(HtmlBuilder):
191 with_footnotes = False
192 with_nota_red = False
196 class DaisyHtmlBuilder(StandaloneHtmlBuilder):
197 file_extension = 'xhtml'
201 with_footnotes = False
202 with_nota_red = False
203 with_deep_identifiers = False
204 no_externalities = True
207 tree = etree.ElementTree(self.tree)
208 tree.docinfo.public_id = '-//W3C//DTD XHTML 1.0 Transitional//EN'
209 tree.docinfo.system_url = 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'
210 return OutputFile.from_bytes(