From: Radek Czajka
Date: Mon, 5 Jul 2021 09:47:09 +0000 (+0200)
Subject: New EPUB builder, other minor changes.
X-Git-Tag: 2.0~2
X-Git-Url: https://git.mdrn.pl/librarian.git/commitdiff_plain/db91f942ce46e3af1420f3469a83257ef5aca4c2?ds=inline;hp=8df0bad21a18b56933084288320fa35e2a3fce6f
New EPUB builder, other minor changes.
---
diff --git a/src/librarian/builders/__init__.py b/src/librarian/builders/__init__.py
index dc5bdee..e359cd6 100644
--- a/src/librarian/builders/__init__.py
+++ b/src/librarian/builders/__init__.py
@@ -3,6 +3,8 @@ from .txt import TxtBuilder
from .html import HtmlBuilder, StandaloneHtmlBuilder, DaisyHtmlBuilder
from .sanitize import Sanitizer
from .daisy import DaisyBuilder
+from .epub import EpubBuilder
+from .pdf import PdfBuilder
builders = OrderedDict([
@@ -12,4 +14,7 @@ builders = OrderedDict([
("html-daisy", DaisyHtmlBuilder),
("daisy", DaisyBuilder),
("sanitizer", Sanitizer),
+
+ ("epub", EpubBuilder),
+ ("pdf", PdfBuilder),
])
diff --git a/src/librarian/builders/epub.py b/src/librarian/builders/epub.py
new file mode 100644
index 0000000..91405c3
--- /dev/null
+++ b/src/librarian/builders/epub.py
@@ -0,0 +1,690 @@
+from datetime import date
+import os
+import tempfile
+from ebooklib import epub
+from lxml import etree
+import six
+from librarian import functions, OutputFile, get_resource, XHTMLNS
+from librarian.cover import make_cover
+from librarian.embeds.mathml import MathML
+import librarian.epub
+from librarian.fonts import strip_font
+from librarian.fundraising import FUNDRAISING
+
+
+
+
+class Xhtml:
+ def __init__(self):
+ self.element = etree.XML('''WolneLektury.pl''')
+
+ @property
+ def title(self):
+ return self.element.find('.//' + XHTMLNS('title'))
+
+ @property
+ def body(self):
+ return self.element.find('.//' + XHTMLNS('body'))
+
+
+class Builder:
+ file_extension = None
+
+ def __init__(self, base_url=None):
+ self._base_url = base_url or 'file:///home/rczajka/for/fnp/librarian/temp~/maly/img/'
+ self.footnotes = etree.Element('div', id='footnotes')
+
+ self.cursors = {
+# None: None,
+# 'header': self.header,
+ 'footnotes': self.footnotes,
+ }
+ self.current_cursors = []
+
+ self.toc_base = 0
+
+ @property
+ def cursor(self):
+ return self.current_cursors[-1]
+
+ def enter_fragment(self, fragment):
+ self.current_cursors.append(self.cursors[fragment])
+
+ 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]
+
+
+
+ @property
+ def base_url(self):
+ if self._base_url is not None:
+ return self._base_url
+ else:
+ return 'https://wolnelektury.pl/media/book/pictures/{}/'.format(self.document.meta.url.slug)
+
+
+ # Base URL should be on Document level, not builder.
+ def build(self, document, **kwargs):
+ """Should return an OutputFile with the output."""
+ raise NotImplementedError()
+
+
+class EpubBuilder(Builder):
+ file_extension = 'epub'
+
+ def __init__(self, *args, **kwargs):
+ self.chars = set()
+ self.fundr = 0
+ super().__init__(*args, **kwargs)
+
+ def build(self, document, **kwargs):
+ # replace_characters -- nie, robimy to na poziomie elementów
+
+ # hyphenator (\00ad w odp. miejscach) -- jeÅli już, to też powinno to siÄ dziaÄ na poziomie elementów
+ # spójniki (\u00a0 po)-- jeÅli już, to na poziomie elementów
+ # trick na dywizy: -
+
+ # do toc trafia:
+ # poczÄ
tek z KAŻDEGO PLIKU xml
+
+ # zliczamy zbiór użytych znaków
+
+ # flagi:
+ # mieliÅmy takÄ
flagÄ less-advertising, używanÄ
tylko dla Prestigio; już nie używamy.
+
+ # @editors = document.editors() (jako str)
+ # @funders = join(meta.funders)
+ # @thanks = meta.thanks
+
+
+ self.output = output = epub.EpubBook()
+ self.document = document
+
+ self.set_metadata()
+
+
+ self.add_cover()
+
+ self.add_title_page()
+ self.add_toc()
+
+
+
+ self.start_chunk()
+
+ self.add_toc_entry(
+ None,
+ 'PoczÄ
tek utworu', # i18n
+ 0
+ )
+ self.output.guide.append({
+ "type": "text",
+ "title": "PoczÄ
tek",
+ "href": "part1.xhtml"
+ })
+
+
+ self.build_document(self.document)
+
+
+ self.close_chunk()
+
+ self.add_annotations()
+ self.add_support_page()
+ self.add_last_page()
+
+
+ e = len(self.output.spine) - 3 - 3
+ nfunds = len(FUNDRAISING)
+ if e > 16:
+ nfunds *= 2
+
+ # COUNTING CHARACTERS?
+ for f in range(nfunds):
+ spine_index = int(4 + (f / nfunds * e) + f)
+
+ h = Xhtml()
+ h.body.append(
+ etree.XML('
' + FUNDRAISING[f % len(FUNDRAISING)] + '
')
+ )
+ self.add_html(h.element, file_name='fund%d.xhtml' % f, spine=spine_index)
+
+ self.add_fonts()
+
+ output_file = tempfile.NamedTemporaryFile(
+ prefix='librarian', suffix='.epub',
+ delete=False)
+ output_file.close()
+ epub.write_epub(output_file.name, output, {'epub3_landmark': False})
+ return OutputFile.from_filename(output_file.name)
+
+ def build_document(self, document):
+ self.toc_precedences = []
+
+ self.start_chunk()
+
+
+ document.tree.getroot().epub_build(self)
+ if document.meta.parts:
+ self.start_chunk()
+
+ self.start_element('div', {'class': 'title-page'})
+ self.start_element('h1', {'class': 'title'})
+ self.push_text(document.meta.title)
+ self.end_element()
+ self.end_element()
+
+ ######
+ # 160
+ # translators
+ # working copy?
+ # ta lektura
+ # tanks
+ # utwor opracowany
+ # isbn
+ # logo
+
+ for child in document.children:
+ self.start_chunk()
+ self.add_toc_entry(None, child.meta.title, 0)
+ self.build_document(child)
+
+ self.shift_toc_base()
+
+
+ def add_title_page(self):
+ html = Xhtml()
+ html.title.text = "Strona tytuÅowa"
+ bt = etree.SubElement(html.body, 'div', **{'class': 'book-text'})
+ tp = etree.SubElement(bt, 'div', **{'class': 'title-page'})
+
+ # Tak jak jest teraz â czy może byÄ jednoczeÅnie
+ # no âautor_utworuâ
+ # i âdzieÅo nadrzÄdneâ
+ # wczeÅniej mogÅo byÄ dzieÅo nadrzÄdne,
+
+ e = self.document.tree.find('//autor_utworu')
+ if e is not None:
+ etree.SubElement(tp, 'h2', **{'class': 'author'}).text = e.raw_printable_text()
+ e = self.document.tree.find('//nazwa_utworu')
+ if e is not None:
+ etree.SubElement(tp, 'h1', **{'class': 'title'}).text = e.raw_printable_text()
+
+ if not len(tp):
+ for author in self.document.meta.authors:
+ etree.SubElement(tp, 'h2', **{'class': 'author'}).text = author.readable()
+ etree.SubElement(tp, 'h1', **{'class': 'title'}).text = self.document.meta.title
+
+#
+# else:
+#
+#
+
+ etree.SubElement(tp, 'p', **{"class": "info"}).text = '\u00a0'
+
+ if self.document.meta.translators:
+ p = etree.SubElement(tp, 'p', **{'class': 'info'})
+ p.text = 'tÅum. ' + ', '.join(t.readable() for t in self.document.meta.translators)
+
+ #[Kopia robocza]
+
+ p = etree.XML("""
+ Ta lektura, podobnie jak tysiÄ
ce innych, jest dostÄpna on-line na stronie
+ wolnelektury.pl.
+
""")
+ p[0].attrib['href'] = str(self.document.meta.url)
+ tp.append(p)
+
+ if self.document.meta.thanks:
+ etree.SubElement(tp, 'p', **{'class': 'info'}).text = self.document.meta.thanks
+
+ tp.append(etree.XML("""
+
+ Utwór opracowany zostaÅ w ramach projektu Wolne Lektury przez fundacjÄ Nowoczesna Polska.
+
+ """))
+
+ if self.document.meta.isbn_epub:
+ etree.SubElement(tp, 'p', **{"class": "info"}).text = self.document.meta.isbn_epub
+
+ tp.append(etree.XML(""""""))
+
+ self.add_html(
+ html.element,
+ file_name='title.xhtml',
+ spine=True,
+ toc='Strona tytuÅowa' # TODO: i18n
+ )
+
+ self.add_file(
+ get_resource('res/wl-logo-small.png'),
+ file_name='logo_wolnelektury.png',
+ media_type='image/png'
+ )
+
+ def set_metadata(self):
+ self.output.set_identifier(
+ str(self.document.meta.url))
+ self.output.set_language(
+ functions.lang_code_3to2(self.document.meta.language)
+ )
+ self.output.set_title(self.document.meta.title)
+
+ for i, author in enumerate(self.document.meta.authors):
+ self.output.add_author(
+ author.readable(),
+ file_as=six.text_type(author),
+ uid='creator{}'.format(i)
+ )
+ for translator in self.document.meta.translators:
+ self.output.add_author(
+ translator.readable(),
+ file_as=six.text_type(translator),
+ role='trl',
+ uid='translator{}'.format(i)
+ )
+ for publisher in self.document.meta.publisher:
+ self.output.add_metadata("DC", "publisher", publisher)
+
+ self.output.add_metadata("DC", "date", self.document.meta.created_at)
+
+
+
+
+ def add_toc(self):
+ item = epub.EpubNav()
+ self.output.add_item(item)
+ self.output.spine.append(item)
+ self.output.add_item(epub.EpubNcx())
+
+ self.output.toc.append(
+ epub.Link(
+ "nav.xhtml",
+ "Spis treÅci",
+ "nav"
+ )
+ )
+
+
+
+ def add_support_page(self):
+ self.add_file(
+ get_resource('epub/support.xhtml'),
+ spine=True,
+ toc='Wesprzyj Wolne Lektury'
+ )
+
+ self.add_file(
+ get_resource('res/jedenprocent.png'),
+ media_type='image/png'
+ )
+ self.add_file(
+ get_resource('epub/style.css'),
+ media_type='text/css'
+ )
+
+
+ def add_file(self, path=None, content=None,
+ media_type='application/xhtml+xml',
+ file_name=None, uid=None,
+ spine=False, toc=None):
+
+ # update chars?
+ # jakieÅ tam ÅcieÅnianie biaÅych znaków?
+
+ if content is None:
+ with open(path, 'rb') as f:
+ content = f.read()
+ if file_name is None:
+ file_name = path.rsplit('/', 1)[-1]
+
+ if uid is None:
+ uid = file_name.split('.', 1)[0]
+
+ item = epub.EpubItem(
+ uid=uid,
+ file_name=file_name,
+ media_type=media_type,
+ content=content
+ )
+
+ self.output.add_item(item)
+ if spine:
+ if spine is True:
+ self.output.spine.append(item)
+ else:
+ self.output.spine.insert(spine, item)
+
+ if toc:
+ self.output.toc.append(
+ epub.Link(
+ file_name,
+ toc,
+ uid
+ )
+ )
+
+ def add_html(self, html_tree, **kwargs):
+ html = etree.tostring(
+ html_tree, pretty_print=True, xml_declaration=True,
+ encoding="utf-8",
+ doctype=''
+ )
+
+ html = librarian.epub.squeeze_whitespace(html)
+
+ self.add_file(
+ content=html,
+ **kwargs
+ )
+
+
+ def add_fonts(self):
+ print("".join(sorted(self.chars)))
+ # TODO: optimizer
+ for fname in ('DejaVuSerif.ttf', 'DejaVuSerif-Bold.ttf',
+ 'DejaVuSerif-Italic.ttf', 'DejaVuSerif-BoldItalic.ttf'):
+ self.add_file(
+ content=strip_font(
+ get_resource('fonts/' + fname),
+ self.chars
+ ),
+ file_name=fname,
+ media_type='font/ttf'
+ )
+
+ def start_chunk(self):
+ if getattr(self, 'current_chunk', None) is not None:
+ if not len(self.current_chunk):
+ return
+ self.close_chunk()
+ self.current_chunk = etree.Element(
+ 'div',
+ id="book-text"
+ )
+ self.cursors[None] = self.current_chunk
+ self.current_cursors.append(self.current_chunk)
+
+ self.section_number = 0
+
+
+ def close_chunk(self):
+ assert self.cursor is self.current_chunk
+ ###### -- what if we're inside?
+
+ chunk_no = getattr(
+ self,
+ 'chunk_counter',
+ 1
+ )
+ self.chunk_counter = chunk_no + 1
+
+ html = Xhtml()
+ html.body.append(self.current_chunk)
+
+ self.add_html(
+ ## html container from template.
+ #self.current_chunk,
+ html.element,
+ file_name='part%d.xhtml' % chunk_no,
+ spine=True,
+
+ )
+ self.current_chunk = None
+ self.current_cursors.pop()
+
+ def start_element(self, tag, attr):
+ self.current_cursors.append(
+ etree.SubElement(self.cursor, tag, **attr)
+ )
+
+ def end_element(self):
+ self.current_cursors.pop()
+
+ def push_text(self, text):
+ self.chars.update(text)
+ if len(self.cursor):
+ self.cursor[-1].tail = (self.cursor[-1].tail or '') + text
+ else:
+ self.cursor.text = (self.cursor.text or '') + text
+
+
+ def assign_image_number(self):
+ image_number = getattr(self, 'image_number', 0)
+ self.image_number = image_number + 1
+ return image_number
+
+ def assign_footnote_number(self):
+ number = getattr(self, 'footnote_number', 1)
+ self.footnote_number = number + 1
+ return number
+
+ def assign_section_number(self):
+ number = getattr(self, 'section_number', 1)
+ self.section_number = number + 1
+ return number
+
+ def assign_mathml_number(self):
+ number = getattr(self, 'mathml_number', 0)
+ self.mathml_number = number + 1
+ return number
+
+
+ def add_toc_entry(self, fragment, name, precedence):
+ if precedence:
+ while self.toc_precedences and self.toc_precedences[-1] >= precedence:
+ self.toc_precedences.pop()
+ else:
+ self.toc_precedences = []
+
+ real_level = self.toc_base + len(self.toc_precedences)
+ if precedence:
+ self.toc_precedences.append(precedence)
+ else:
+ self.toc_base += 1
+
+ part_number = getattr(
+ self,
+ 'chunk_counter',
+ 1
+ )
+ filename = 'part%d.xhtml' % part_number
+ uid = filename.split('.')[0]
+ if fragment:
+ filename += '#' + fragment
+ uid += '-' + fragment
+
+ toc = self.output.toc
+ for l in range(1, real_level):
+ if isinstance(toc[-1], epub.Link):
+ toc[-1] = [toc[-1], []]
+ toc = toc[-1][1]
+
+ toc.append(
+ epub.Link(
+ filename,
+ name,
+ uid
+ )
+ )
+
+ def shift_toc_base(self):
+ self.toc_base -= 1
+
+
+ def add_last_page(self):
+ html = Xhtml()
+ m = self.document.meta
+
+ html.title.text = 'Strona redakcyjna'
+ d = etree.SubElement(html.body, 'div', id='book-text')
+
+ newp = lambda: etree.SubElement(d, 'p', {'class': 'info'})
+
+ p = newp()
+ if m.license:
+ p.text = """
+ Ten utwór jest udostÄpniony na licencji
+ """
+ etree.SubElement(p, 'a', href=m.license).text = m.license_description
+ else:
+ p.text = """
+ Ten utwór nie jest objÄty majÄ
tkowym prawem autorskim i znajduje siÄ w domenie
+ publicznej, co oznacza że możesz go swobodnie wykorzystywaÄ, publikowaÄ
+ i rozpowszechniaÄ. JeÅli utwór opatrzony jest dodatkowymi materiaÅami
+ (przypisy, motywy literackie etc.), które podlegajÄ
prawu autorskiemu, to
+ te dodatkowe materiaÅy udostÄpnione sÄ
na licencji
+ """
+ a = etree.SubElement(p, "a", href="http://creativecommons.org/licenses/by-sa/3.0/")
+ a.text = """Creative Commons
+ Uznanie Autorstwa â Na Tych Samych Warunkach 3.0 PL"""
+ a.tail = "."
+
+
+ p = newp()
+ p.text = 'ŹródÅo: '
+ etree.SubElement(
+ p, 'a', href=str(m.url),
+ title=', '.join((
+ ', '.join(p.readable() for p in m.authors),
+ m.title
+ ))
+ ).text = str(m.url)
+
+ newp().text = 'Tekst opracowany na podstawie: ' + m.source_name
+
+ newp().text = """
+ Wydawca:
+ """ + ", ".join(p for p in m.publisher)
+
+ if m.description:
+ newp().text = m.description
+
+
+ if m.editors:
+ newp().text = 'Opracowanie redakcyjne i przypisy: %s.' % (
+ ', '.join(e.readable() for e in sorted(self.document.editors())))
+
+ if m.funders:
+ etree.SubElement(d, 'p', {'class': 'minor-info'}).text = '''PublikacjÄ wsparli i wsparÅy:
+ %s.''' % (', '.join(m.funders))
+
+ if m.cover_by:
+ p = newp()
+ p.text = 'OkÅadka na podstawie: '
+ if m.cover_source:
+ etree.SubElement(
+ p,
+ 'a',
+ href=m.cover_source
+ ).text = m.cover_by
+ else:
+ p.text += m.cover_by
+
+ if m.isbn_epub:
+ newp().text = m.isbn_epub
+
+ newp().text = '\u00a0'
+
+ p = newp()
+ p.attrib['class'] = 'minor-info'
+ p.text = '''
+ Plik wygenerowany dnia '''
+ span = etree.SubElement(p, 'span', id='file_date')
+ span.text = str(date.today())
+ span.tail = '''.
+ '''
+
+ self.add_html(
+ html.element,
+ file_name='last.xhtml',
+ toc='Strona redakcyjna',
+ spine=True
+ )
+
+
+ def add_annotations(self):
+ if not len(self.footnotes):
+ return
+
+ html = Xhtml()
+ html.title.text = 'Przypisy'
+ d = etree.SubElement(
+ etree.SubElement(
+ html.body,
+ 'div',
+ id='book-text'
+ ),
+ 'div',
+ id='footnotes'
+ )
+
+ etree.SubElement(
+ d,
+ 'h2',
+ ).text = 'Przypisy:'
+
+ d.extend(self.footnotes)
+
+ self.add_html(
+ html.element,
+ file_name='annotations.xhtml',
+ spine=True,
+ toc='Przypisy'
+ )
+
+ def add_cover(self):
+ # TODO: allow other covers
+
+ cover_maker = make_cover
+
+ cover_file = six.BytesIO()
+ cover = cover_maker(self.document.meta)
+ cover.save(cover_file)
+ cover_name = 'cover.%s' % cover.ext()
+
+ self.output.set_cover(
+ file_name=cover_name,
+ content=cover_file.getvalue(),
+ create_page = False
+ )
+ ci = ('''
+
+
+
+ OkÅadka
+
+
+
+
+
+''' % cover.ext()).encode('utf-8')
+ self.add_file(file_name='cover.xhtml', content=ci)
+
+ self.output.spine.append('cover')
+ self.output.guide.append({
+ 'type': 'cover',
+ 'href': 'cover.xhtml',
+ 'title': 'OkÅadka'
+ })
+
+ def mathml(self, element):
+ name = "math%d.png" % self.assign_mathml_number()
+ self.add_file(
+ content=MathML(element).to_latex().to_png().data,
+ media_type='image/png',
+ file_name=name
+ )
+ return name
diff --git a/src/librarian/builders/pdf.py b/src/librarian/builders/pdf.py
new file mode 100644
index 0000000..6b2501e
--- /dev/null
+++ b/src/librarian/builders/pdf.py
@@ -0,0 +1,12 @@
+from librarian import OutputFile
+
+
+class PdfBuilder:
+ # ObowiÄ
zkowe
+ file_extension = 'pdf'
+ def build(self, document, mp3):
+ # stub
+ return OutputFile.from_bytes(b'')
+
+
+
diff --git a/src/librarian/builders/txt.py b/src/librarian/builders/txt.py
index 3f19346..8dba4ae 100644
--- a/src/librarian/builders/txt.py
+++ b/src/librarian/builders/txt.py
@@ -50,20 +50,40 @@ class TxtBuilder:
default_license_description = {
"pol": (
- "Ten utwór nie jest objÄty majÄ
tkowym prawem autorskim "
- "i znajduje siÄ w domenie publicznej, co oznacza że "
- "możesz go swobodnie wykorzystywaÄ, publikowaÄ "
- "i rozpowszechniaÄ. JeÅli utwór opatrzony jest "
- "dodatkowymi materiaÅami (przypisy, motywy literackie "
- "etc.), które podlegajÄ
prawu autorskiemu, to te "
- "dodatkowe materiaÅy udostÄpnione sÄ
na licencji "
- "Creative Commons Uznanie Autorstwa â Na Tych Samych "
- "Warunkach 3.0 PL "
- "(http://creativecommons.org/licenses/by-sa/3.0/)"
+ "Wszystkie zasoby Wolnych Lektur możesz swobodnie wykorzystywaÄ, "
+ "publikowaÄ i rozpowszechniaÄ pod warunkiem zachowania warunków "
+ "licencji i zgodnie z Zasadami wykorzystania Wolnych Lektur.\n"
+ "Ten utwór jest w domenie publicznej. "
+ "Wszystkie materiaÅy dodatkowe (przypisy, motywy literackie) sÄ
"
+ "udostÄpnione na Licencji Wolnej Sztuki 1.3 "
+ "(https://artlibre.org/licence/lal/pl/).\n"
+ "Fundacja Nowoczesna Polska zastrzega sobie prawa do wydania "
+ "krytycznego zgodnie z art. Art.99(2) Ustawy o prawach autorskich "
+ "i prawach pokrewnych. WykorzystujÄ
c zasoby z Wolnych Lektur, "
+ "należy pamiÄtaÄ o zapisach licencji oraz zasadach, które "
+ "spisaliÅmy w Zasadach wykorzystania Wolnych Lektur "
+ "(https://wolnelektury.pl/info/zasady-wykorzystania/). Zapoznaj "
+ "siÄ z nimi, zanim udostÄpnisz dalej nasze ksiÄ
żki."
)
}
license_description = {
- "pol": "Ten utwór jest udostÄpniony na licencji {meta.license_description}: \n{meta.license}",
+ "pol": (
+ #"Ten utwór jest udostÄpniony na licencji {meta.license_description}: \n{meta.license}",
+ "Wszystkie zasoby Wolnych Lektur możesz swobodnie wykorzystywaÄ, "
+ "publikowaÄ i rozpowszechniaÄ pod warunkiem zachowania warunków "
+ "licencji i zgodnie z Zasadami wykorzystania Wolnych Lektur.\n"
+ "Ten utwór jest jest udostÄpniony na licencji {meta.license_description} ({meta.license}). "
+ "Wszystkie materiaÅy dodatkowe (przypisy, motywy literackie) sÄ
"
+ "udostÄpnione na Licencji Wolnej Sztuki 1.3 "
+ "(https://artlibre.org/licence/lal/pl/).\n"
+ "Fundacja Nowoczesna Polska zastrzega sobie prawa do wydania "
+ "krytycznego zgodnie z art. Art.99(2) Ustawy o prawach autorskich "
+ "i prawach pokrewnych. WykorzystujÄ
c zasoby z Wolnych Lektur, "
+ "należy pamiÄtaÄ o zapisach licencji oraz zasadach, które "
+ "spisaliÅmy w Zasadach wykorzystania Wolnych Lektur "
+ "(https://wolnelektury.pl/info/zasady-wykorzystania/). Zapoznaj "
+ "siÄ z nimi, zanim udostÄpnisz dalej nasze ksiÄ
żki."
+ )
}
def __init__(self):
diff --git a/src/librarian/cover.py b/src/librarian/cover.py
index 1873be9..7d7964d 100644
--- a/src/librarian/cover.py
+++ b/src/librarian/cover.py
@@ -363,10 +363,10 @@ class WLCover(Cover):
box_img = box.image()
# Find box position.
- if self.box_position == 'top':
- box_top = metr.box_top_margin
- elif self.box_position == 'bottom':
+ if self.box_position == 'bottom' or box_img.size[1] + metr.box_top_margin + metr.box_bottom_margin > metr.height:
box_top = metr.height - metr.box_bottom_margin - box_img.size[1]
+ elif self.box_position == 'top':
+ box_top = metr.box_top_margin
else: # Middle.
box_top = (metr.height - box_img.size[1]) // 2
@@ -470,6 +470,7 @@ class WLNoBoxCover(WLCover):
class LogoWLCover(WLCover):
gradient_height = 90
gradient_logo_height = 60
+ gradient_logo_max_width = 1000
gradient_logo_margin_right = 30
gradient_logo_spacing = 40
gradient_color = '#000'
@@ -478,6 +479,8 @@ class LogoWLCover(WLCover):
'res/wl-logo-white.png',
'res/fnp-logo-white.png',
]
+ annotation = None
+ annotation_height = 10
def __init__(self, book_info, *args, **kwargs):
super(LogoWLCover, self).__init__(book_info, *args, **kwargs)
@@ -537,7 +540,10 @@ class LogoWLCover(WLCover):
- 2 * metr.gradient_logo_margin_right
)
widths = [
- logo.size[0] * metr.gradient_logo_height / logo.size[1]
+ min(
+ metr.gradient_logo_max_width,
+ logo.size[0] * metr.gradient_logo_height / logo.size[1]
+ )
for logo in logos]
taken_space = (
sum(widths)
@@ -553,13 +559,36 @@ class LogoWLCover(WLCover):
logo = logo.resize(
(
int(round(widths[i] * logo_scale)),
- int(round(metr.gradient_logo_height * logo_scale))
+ int(round(
+ logo.size[1] * widths[i] / logo.size[0] * logo_scale
+ ))
),
Image.ANTIALIAS)
cursor -= logo.size[0]
- img.paste(logo, (cursor, logo_top), mask=logo)
+ img.paste(
+ logo,
+ (
+ cursor,
+ int(round(logo_top + (metr.gradient_logo_height - logo.size[1]) * logo_scale / 2))
+ ),
+ mask=logo
+ )
cursor -= int(round(metr.gradient_logo_spacing * logo_scale))
+ if self.annotation:
+ img2 = Image.new('RGBA', (metr.height, metr.height), color=None)
+ draw = ImageDraw.Draw(img2)
+ author_font = ImageFont.truetype(
+ self.author_font_ttf, metr.annotation_height,
+ layout_engine=ImageFont.LAYOUT_BASIC)
+ draw.text((self.annotation_height, self.annotation_height), self.annotation, font=author_font, fill='#FFFFFF')
+ img2.show()
+ img2 = img2.rotate(90)
+ img2.show()
+ img.putalpha(0)
+ img.alpha_composite(img2, (0, 0))
+ img = img.convert('RGB')
+
return img
@@ -676,11 +705,22 @@ class AtriumCover(LogoWLCover):
]
+class BNCover(LogoWLCover):
+ gradient_logos = [
+ 'res/dofinansowano.png',
+ 'res/MKIDN.jpg',
+ 'res/BN.png',
+ 'res/wl-logo-white.png',
+ ]
+# annotation = 'Zadanie âUdostÄpnienie publikacji w formatach cyfrowychâ w ramach Narodowego Programu Rozwoju Czytelnictwa. Dofinansowano ze Årodków Ministra Kultury, Dziedzictwa Narodowego i Sportu.'
+
+
COVER_CLASSES = {
'default': LogoWLCover,
'kmlu': KMLUCover,
'mpw': MPWCover,
'atrium': AtriumCover,
+ 'bn': BNCover,
}
diff --git a/src/librarian/document.py b/src/librarian/document.py
index 6e94ff2..0dbb14f 100644
--- a/src/librarian/document.py
+++ b/src/librarian/document.py
@@ -4,12 +4,12 @@ import re
from lxml import etree
import six
from .parser import parser
-from . import dcparser, DCNS
+from . import dcparser, DCNS, DirDocProvider
from .functions import lang_code_3to2
class WLDocument:
- def __init__(self, filename=None, url=None):
+ def __init__(self, filename=None, url=None, provider=None):
source = filename or six.moves.urllib.request.urlopen(url)
tree = etree.parse(source, parser=parser)
self.tree = tree
@@ -18,6 +18,8 @@ class WLDocument:
DCNS('language'): ["pol"],
}, validate_required=False)
+ self.provider = provider if provider is not None else DirDocProvider('.')
+
@property
def meta(self):
# Allow metadata of the master element as document meta.
@@ -25,6 +27,15 @@ class WLDocument:
return self.tree.getroot().meta
return master.meta
+ @property
+ def children(self):
+ for part_uri in self.meta.parts or []:
+ yield type(self)(
+ filename=self.provider.by_uri(part_uri),
+ provider=self.provider
+ )
+
+
def build(self, builder, **kwargs):
return builder().build(self, **kwargs)
@@ -66,3 +77,13 @@ class WLDocument:
_compat_assigns_section_ids_in_elem(child, idfier + '-')
_compat_assigns_section_ids_in_elem(self.tree.getroot().master)
+
+ def editors(self):
+ persons = set(self.meta.editors
+ + self.meta.technical_editors)
+ #for child in self.parts():
+ # persons.update(child.editors())
+ #if None in persons:
+ # persons.remove(None)
+ return persons
+
diff --git a/src/librarian/elements/__init__.py b/src/librarian/elements/__init__.py
index f3a8521..c3a55fb 100644
--- a/src/librarian/elements/__init__.py
+++ b/src/librarian/elements/__init__.py
@@ -82,7 +82,7 @@ WL_ELEMENTS = {
"naglowek_czesc": headers.NaglowekCzesc,
"naglowek_akt": headers.NaglowekCzesc,
- "naglowek_scena": headers.NaglowekRozdzial,
+ "naglowek_scena": headers.NaglowekScena,
"naglowek_rozdzial": headers.NaglowekRozdzial,
"naglowek_podrozdzial": headers.NaglowekPodrozdzial,
"srodtytul": headers.NaglowekCzesc,
diff --git a/src/librarian/elements/base.py b/src/librarian/elements/base.py
index b9df185..5317268 100644
--- a/src/librarian/elements/base.py
+++ b/src/librarian/elements/base.py
@@ -3,10 +3,13 @@
import re
from lxml import etree
from librarian import dcparser, RDFNS
+from librarian.html import raw_printable_text
from librarian.util import get_translation
class WLElement(etree.ElementBase):
+ SECTION_PRECEDENCE = None
+
TXT_TOP_MARGIN = 0
TXT_BOTTOM_MARGIN = 0
TXT_PREFIX = ""
@@ -15,17 +18,24 @@ class WLElement(etree.ElementBase):
HTML_TAG = None
HTML_ATTR = {}
HTML_CLASS = None
-
+
+ EPUB_TAG = None
+ EPUB_ATTR = {}
+ EPUB_CLASS = None
+ EPUB_START_CHUNK = False
+
CAN_HAVE_TEXT = True
STRIP = False
text_substitutions = [
(u'---', u'â'),
(u'--', u'â'),
- (u'...', u'â¦'),
+ #(u'...', u'â¦'), # Temporary turnoff for epub
(u',,', u'â'),
(u'"', u'â'),
('\ufeff', ''),
+
+ ("'", "\u2019"), # This was enabled for epub.
]
@property
@@ -52,11 +62,25 @@ class WLElement(etree.ElementBase):
def gettext(self):
return get_translation(self.meta.language).gettext
+ def raw_printable_text(self):
+ # TODO: podtagi, wyroznienia, etc
+ t = ''
+ t += self.normalize_text(self.text)
+ for c in self:
+ if c.tag not in ('pe', 'pa', 'pt', 'pr', 'motyw'):
+ t += c.raw_printable_text()
+ t += self.normalize_text(c.tail)
+ return t
+
def normalize_text(self, text):
text = text or ''
for e, s in self.text_substitutions:
text = text.replace(e, s)
- text = re.sub(r'\s+', ' ', text)
+ # FIXME: TEmporary turnoff
+# text = re.sub(r'\s+', ' ', text)
+### TODO: Added now for epub
+ text = re.sub(r'(?<=\s\w)\s+', u'\u00A0', text)
+
return text
def _build_inner(self, builder, build_method):
@@ -118,6 +142,48 @@ class WLElement(etree.ElementBase):
if self.HTML_TAG:
builder.end_element()
+ def _epub_build_inner(self, builder):
+ self._build_inner(builder, 'epub_build')
+
+ def get_epub_attr(self, builder):
+ attr = self.EPUB_ATTR.copy()
+ if self.EPUB_CLASS:
+ attr['class'] = self.EPUB_CLASS
+ return attr
+
+ def epub_build(self, builder):
+ # TEMPORARY
+ self.CAN_HAVE_TEXT = True
+ self.STRIP = False
+
+ if self.EPUB_START_CHUNK:
+ builder.start_chunk()
+
+ fragment = None
+ if self.SECTION_PRECEDENCE:
+ if not self.EPUB_START_CHUNK:
+ fragment = 'sub%d' % builder.assign_section_number()
+ self.attrib['id'] = fragment
+
+ builder.add_toc_entry(
+ fragment,
+ self.raw_printable_text(),
+ self.SECTION_PRECEDENCE
+ )
+
+ if self.EPUB_TAG:
+ attr = self.get_epub_attr(builder)
+ if fragment:
+ attr['id'] = fragment
+ builder.start_element(
+ self.EPUB_TAG,
+ attr
+ )
+
+ self._epub_build_inner(builder)
+ if self.EPUB_TAG:
+ builder.end_element()
+
def sanitize(self):
# TODO: Remove insanity here.
for e in self:
diff --git a/src/librarian/elements/blocks/dedykacja.py b/src/librarian/elements/blocks/dedykacja.py
index 5436271..7ac809d 100644
--- a/src/librarian/elements/blocks/dedykacja.py
+++ b/src/librarian/elements/blocks/dedykacja.py
@@ -4,5 +4,5 @@ from ..base import WLElement
class Dedykacja(WLElement):
TXT_LEGACY_TOP_MARGIN = 2
- HTML_TAG = "div"
- HTML_CLASS = "dedication"
+ EPUB_TAG = HTML_TAG = "div"
+ EPUB_CLASS = HTML_CLASS = "dedication"
diff --git a/src/librarian/elements/blocks/dlugi_cytat.py b/src/librarian/elements/blocks/dlugi_cytat.py
index c660583..22e98dd 100644
--- a/src/librarian/elements/blocks/dlugi_cytat.py
+++ b/src/librarian/elements/blocks/dlugi_cytat.py
@@ -10,3 +10,6 @@ class DlugiCytat(WLElement):
TXT_LEGACY_BOTTOM_MARGIN = 0
HTML_TAG = 'blockquote'
+
+ EPUB_TAG = 'div'
+ EPUB_CLASS = 'block'
diff --git a/src/librarian/elements/blocks/nota.py b/src/librarian/elements/blocks/nota.py
index a01bf29..0e3f61f 100644
--- a/src/librarian/elements/blocks/nota.py
+++ b/src/librarian/elements/blocks/nota.py
@@ -4,5 +4,5 @@ from ..base import WLElement
class Nota(WLElement):
CAN_HAVE_TEXT = False
- HTML_TAG = "div"
- HTML_CLASS = "note"
+ EPUB_TAG = HTML_TAG = "div"
+ EPUB_CLASS = HTML_CLASS = "note"
diff --git a/src/librarian/elements/blocks/poezja_cyt.py b/src/librarian/elements/blocks/poezja_cyt.py
index 0c103b1..14cd539 100644
--- a/src/librarian/elements/blocks/poezja_cyt.py
+++ b/src/librarian/elements/blocks/poezja_cyt.py
@@ -10,3 +10,6 @@ class PoezjaCyt(WLElement):
TXT_LEGACY_BOTTOM_MARGIN = 0
HTML_TAG = 'blockquote'
+
+ EPUB_TAG = 'div'
+ EPUB_CLASS = 'block'
diff --git a/src/librarian/elements/blocks/ramka.py b/src/librarian/elements/blocks/ramka.py
index d8dd5f0..b85f83f 100644
--- a/src/librarian/elements/blocks/ramka.py
+++ b/src/librarian/elements/blocks/ramka.py
@@ -5,3 +5,5 @@ class Ramka(WLElement):
HTML_TAG = "div"
HTML_CLASS = "ramka"
+ EPUB_TAG = "div"
+ EPUB_CLASS = "frame"
diff --git a/src/librarian/elements/comments/abstrakt.py b/src/librarian/elements/comments/abstrakt.py
index 9b43dc3..887712b 100644
--- a/src/librarian/elements/comments/abstrakt.py
+++ b/src/librarian/elements/comments/abstrakt.py
@@ -7,3 +7,6 @@ class Abstrakt(WLElement):
def html_build(self, builder):
pass
+
+ def epub_build(self, builder):
+ pass
diff --git a/src/librarian/elements/comments/nota_red.py b/src/librarian/elements/comments/nota_red.py
index faa5dd1..0ce970e 100644
--- a/src/librarian/elements/comments/nota_red.py
+++ b/src/librarian/elements/comments/nota_red.py
@@ -9,3 +9,6 @@ class NotaRed(WLElement):
builder.enter_fragment('nota_red')
super(NotaRed, self).html_build(builder)
builder.exit_fragment()
+
+ def epub_build(self, builder):
+ pass
diff --git a/src/librarian/elements/comments/uwaga.py b/src/librarian/elements/comments/uwaga.py
index adf908b..1bdeb39 100644
--- a/src/librarian/elements/comments/uwaga.py
+++ b/src/librarian/elements/comments/uwaga.py
@@ -7,3 +7,6 @@ class Uwaga(WLElement):
def html_build(self, builder):
pass
+
+ def epub_build(self, builder):
+ pass
diff --git a/src/librarian/elements/drama/didask_tekst.py b/src/librarian/elements/drama/didask_tekst.py
index 7227c17..088e373 100644
--- a/src/librarian/elements/drama/didask_tekst.py
+++ b/src/librarian/elements/drama/didask_tekst.py
@@ -5,5 +5,5 @@ class DidaskTekst(WLElement):
TXT_PREFIX = "/ "
TXT_SUFFIX = " /"
- HTML_TAG = "em"
- HTML_CLASS = "didaskalia"
+ EPUB_TAG = HTML_TAG = "em"
+ EPUB_CLASS = HTML_CLASS = "didaskalia"
diff --git a/src/librarian/elements/drama/didaskalia.py b/src/librarian/elements/drama/didaskalia.py
index af0520f..bf81b69 100644
--- a/src/librarian/elements/drama/didaskalia.py
+++ b/src/librarian/elements/drama/didaskalia.py
@@ -9,5 +9,5 @@ class Didaskalia(WLElement):
TXT_PREFIX = "/ "
TXT_SUFFIX = " /"
- HTML_TAG = "div"
- HTML_CLASS = "didaskalia"
+ EPUB_TAG =_HTML_TAG = "div"
+ EPUB_CLASS = HTML_CLASS = "didaskalia"
diff --git a/src/librarian/elements/drama/kwestia.py b/src/librarian/elements/drama/kwestia.py
index 27dca30..56463d6 100644
--- a/src/librarian/elements/drama/kwestia.py
+++ b/src/librarian/elements/drama/kwestia.py
@@ -4,5 +4,5 @@ from ..base import WLElement
class Kwestia(WLElement):
CAN_HAVE_TEXT = False
- HTML_TAG = "div"
- HTML_CLASS = "kwestia"
+ EPUB_TAG = HTML_TAG = "div"
+ EPUB_CLASS = HTML_CLASS = "kwestia"
diff --git a/src/librarian/elements/drama/lista_osob.py b/src/librarian/elements/drama/lista_osob.py
index 5beca64..269b05c 100644
--- a/src/librarian/elements/drama/lista_osob.py
+++ b/src/librarian/elements/drama/lista_osob.py
@@ -19,3 +19,10 @@ class ListaOsob(WLElement):
super(ListaOsob, self)._html_build_inner(builder)
builder.cursor.append(ol)
builder.forget_fragment('list')
+
+ def _epub_build_inner(self, builder):
+ ol = etree.Element('ol')
+ builder.create_fragment('list', ol)
+ super(ListaOsob, self)._epub_build_inner(builder)
+ builder.cursor.append(ol)
+ builder.forget_fragment('list')
diff --git a/src/librarian/elements/drama/lista_osoba.py b/src/librarian/elements/drama/lista_osoba.py
index fe55838..c5770ee 100644
--- a/src/librarian/elements/drama/lista_osoba.py
+++ b/src/librarian/elements/drama/lista_osoba.py
@@ -8,10 +8,14 @@ class ListaOsoba(WLElement):
TXT_LEGACY_BOTTOM_MARGIN = 0
TXT_PREFIX = " * "
- HTML_TAG = "li"
+ EPUB_TAG = HTML_TAG = "li"
def html_build(self, builder):
builder.enter_fragment('list')
super(ListaOsoba, self).html_build(builder)
builder.exit_fragment()
+ def epub_build(self, builder):
+ builder.enter_fragment('list')
+ super(ListaOsoba, self).epub_build(builder)
+ builder.exit_fragment()
diff --git a/src/librarian/elements/drama/miejsce_czas.py b/src/librarian/elements/drama/miejsce_czas.py
index a4e9453..cf47ed2 100644
--- a/src/librarian/elements/drama/miejsce_czas.py
+++ b/src/librarian/elements/drama/miejsce_czas.py
@@ -2,4 +2,7 @@ from ..paragraphs import Akap
class MiejsceCzas(Akap):
- HTML_CLASS = 'place-and-time'
+ EPUB_CLASS = HTML_CLASS = 'place-and-time'
+
+ EPUB_TAG = "div"
+
diff --git a/src/librarian/elements/drama/naglowek_listy.py b/src/librarian/elements/drama/naglowek_listy.py
index 4db9111..1f164a4 100644
--- a/src/librarian/elements/drama/naglowek_listy.py
+++ b/src/librarian/elements/drama/naglowek_listy.py
@@ -3,3 +3,6 @@ from ..base import WLElement
class NaglowekListy(WLElement):
HTML_TAG = "h3"
+
+ EPUB_TAG = "div"
+ EPUB_CLASS = "h3"
diff --git a/src/librarian/elements/drama/naglowek_osoba.py b/src/librarian/elements/drama/naglowek_osoba.py
index 5ab78fd..afa16ce 100644
--- a/src/librarian/elements/drama/naglowek_osoba.py
+++ b/src/librarian/elements/drama/naglowek_osoba.py
@@ -8,3 +8,6 @@ class NaglowekOsoba(WLElement):
TXT_LEGACY_BOTTOM_MARGIN = 0
HTML_TAG = "h4"
+
+ EPUB_TAG = "h2"
+ EPUB_CLASS = "h4"
diff --git a/src/librarian/elements/drama/osoba.py b/src/librarian/elements/drama/osoba.py
index b0fb793..ffd9494 100644
--- a/src/librarian/elements/drama/osoba.py
+++ b/src/librarian/elements/drama/osoba.py
@@ -2,6 +2,6 @@ from ..base import WLElement
class Osoba(WLElement):
- HTML_TAG = "em"
- HTML_CLASS = "person"
+ EPUB_TAG = HTML_TAG = "em"
+ EPUB_CLASS = HTML_CLASS = "person"
diff --git a/src/librarian/elements/figures/ilustr.py b/src/librarian/elements/figures/ilustr.py
index 3c3026c..ab7c2b7 100644
--- a/src/librarian/elements/figures/ilustr.py
+++ b/src/librarian/elements/figures/ilustr.py
@@ -1,12 +1,51 @@
+import six.moves
+from PIL import Image
from ..base import WLElement
class Ilustr(WLElement):
- HTML_TAG = 'img'
+ EPUB_TAG = HTML_TAG = 'img'
def get_html_attr(self, builder):
+ ## TODO: thumbnail.
+
+ url = six.moves.urllib.parse.urljoin(
+ builder.base_url,
+ self.get('src')
+ )
+
+ imgfile = six.moves.urllib.request.urlopen(url)
+ img = Image.open(imgfile)
+ th_format, ext, media_type = {
+ 'GIF': ('GIF', 'gif', 'image/gif'),
+ 'PNG': ('PNG', 'png', 'image/png'),
+ }.get(img.format, ('JPEG', 'jpg', 'image/jpeg'))
+
+ width = 1200
+ if img.size[0] < width:
+ th = img
+ else:
+ th = img.resize((width, round(width * img.size[1] / img.size[0])))
+
+ imgfile.close()
+ buffer = six.BytesIO()
+ th.save(buffer, format=th_format)
+ ## TODO: Counter
+ file_name = 'image%d.%s' % (
+ builder.assign_image_number(),
+ ext
+ )
+
+ builder.add_file(
+ content=buffer.getvalue(),
+ file_name=file_name,
+ media_type=media_type,
+ )
+
return {
- 'src': builder.base_url + self.attrib['src'],
+ 'src': file_name,
'alt': self.attrib['alt'],
'title': self.attrib['alt'],
}
+
+ get_epub_attr = get_html_attr
diff --git a/src/librarian/elements/figures/kol.py b/src/librarian/elements/figures/kol.py
index e0dae02..c94f20d 100644
--- a/src/librarian/elements/figures/kol.py
+++ b/src/librarian/elements/figures/kol.py
@@ -2,4 +2,4 @@ from ..base import WLElement
class Kol(WLElement):
- HTML_TAG = 'td'
+ EPUB_TAG = HTML_TAG = 'td'
diff --git a/src/librarian/elements/figures/tabela.py b/src/librarian/elements/figures/tabela.py
index af4a436..7da7877 100644
--- a/src/librarian/elements/figures/tabela.py
+++ b/src/librarian/elements/figures/tabela.py
@@ -2,7 +2,7 @@ from ..base import WLElement
class Tabela(WLElement):
- HTML_TAG = 'table'
+ EPUB_TAG = HTML_TAG = 'table'
def get_html_attr(self, builder):
if self.attrib.get('ramka', '') == '1':
@@ -10,3 +10,7 @@ class Tabela(WLElement):
'class': 'border'
}
return {}
+
+ get_epub_attr = get_html_attr
+
+
diff --git a/src/librarian/elements/figures/wiersz.py b/src/librarian/elements/figures/wiersz.py
index bc61f9d..2c7d91a 100644
--- a/src/librarian/elements/figures/wiersz.py
+++ b/src/librarian/elements/figures/wiersz.py
@@ -2,4 +2,4 @@ from ..base import WLElement
class Wiersz(WLElement):
- HTML_TAG = 'tr'
+ EPUB_TAG = HTML_TAG = 'tr'
diff --git a/src/librarian/elements/footnotes/__init__.py b/src/librarian/elements/footnotes/__init__.py
index 0f30747..433e881 100644
--- a/src/librarian/elements/footnotes/__init__.py
+++ b/src/librarian/elements/footnotes/__init__.py
@@ -49,6 +49,49 @@ class Footnote(WLElement):
builder.end_element()
builder.exit_fragment()
+ def epub_build(self, builder):
+ fn_no = builder.assign_footnote_number()
+ part_number = getattr(
+ builder,
+ 'chunk_counter',
+ 1
+ )
+
+ builder.start_element(
+ 'a',
+ {
+ 'class': 'anchor',
+ 'id': f'anchor-{fn_no}',
+ 'href': f'annotations.xhtml#annotation-{fn_no}',
+ }
+ )
+ builder.start_element('sup', {})
+ builder.push_text(str(fn_no))
+ builder.end_element()
+ builder.end_element()
+
+
+ builder.enter_fragment('footnotes')
+ builder.start_element('p', {
+ 'id': f'annotation-{fn_no}',
+ 'class': "annotation"
+ })
+ builder.start_element('a', {
+ 'href': f"part{part_number}.xhtml#anchor-{fn_no}"
+ })
+ builder.push_text(str(fn_no))
+ builder.end_element()
+ builder.push_text('. ')
+
+ super().epub_build(builder)
+ builder.push_text(' [' + self.qualifier + ']')
+ builder.end_element()
+
+ builder.push_text('\n')
+
+ builder.exit_fragment()
+
+
class PA(Footnote):
"""Przypis autorski."""
diff --git a/src/librarian/elements/front/autor_utworu.py b/src/librarian/elements/front/autor_utworu.py
index fd6b2e8..736a24c 100644
--- a/src/librarian/elements/front/autor_utworu.py
+++ b/src/librarian/elements/front/autor_utworu.py
@@ -6,3 +6,6 @@ class AutorUtworu(HeaderElement):
TXT_LEGACY_BOTTOM_MARGIN = 2
HTML_CLASS = 'author'
+
+ def epub_build(self, builder):
+ return
diff --git a/src/librarian/elements/front/dzielo_nadrzedne.py b/src/librarian/elements/front/dzielo_nadrzedne.py
index a034ae7..5f114bc 100644
--- a/src/librarian/elements/front/dzielo_nadrzedne.py
+++ b/src/librarian/elements/front/dzielo_nadrzedne.py
@@ -6,3 +6,6 @@ class DzieloNadrzedne(HeaderElement):
TXT_LEGACY_BOTTOM_MARGIN = 1
HTML_CLASS = "collection"
+
+ def epub_build(self, builder):
+ return
diff --git a/src/librarian/elements/front/motto.py b/src/librarian/elements/front/motto.py
index 98c7334..7f23ea6 100644
--- a/src/librarian/elements/front/motto.py
+++ b/src/librarian/elements/front/motto.py
@@ -5,5 +5,5 @@ class Motto(WLElement):
TXT_LEGACY_TOP_MARGIN = 4
TXT_LEGACY_BOTTOM_MARGIN = 2
- HTML_TAG = "div"
- HTML_CLASS = "motto"
+ EPUB_TAG = HTML_TAG = "div"
+ EPUB_CLASS = HTML_CLASS = "motto"
diff --git a/src/librarian/elements/front/motto_podpis.py b/src/librarian/elements/front/motto_podpis.py
index 58fc9db..8fee127 100644
--- a/src/librarian/elements/front/motto_podpis.py
+++ b/src/librarian/elements/front/motto_podpis.py
@@ -3,5 +3,7 @@ from ..base import WLElement
class MottoPodpis(WLElement):
HTML_TAG = "p"
- HTML_CLASS = "motto_podpis"
+ EPUB_CLASS = HTML_CLASS = "motto_podpis"
+ EPUB_TAG = "div"
+
diff --git a/src/librarian/elements/front/nazwa_utworu.py b/src/librarian/elements/front/nazwa_utworu.py
index aa68082..4d06b47 100644
--- a/src/librarian/elements/front/nazwa_utworu.py
+++ b/src/librarian/elements/front/nazwa_utworu.py
@@ -6,3 +6,6 @@ class NazwaUtworu(HeaderElement):
TXT_LEGACY_BOTTOM_MARGIN = 1
HTML_CLASS = 'title'
+
+ EPUB_TAG = 'h2'
+ EPUB_CLASS = 'intitle'
diff --git a/src/librarian/elements/front/podtytul.py b/src/librarian/elements/front/podtytul.py
index 4431bc2..71e28a8 100644
--- a/src/librarian/elements/front/podtytul.py
+++ b/src/librarian/elements/front/podtytul.py
@@ -6,3 +6,7 @@ class Podtytul(HeaderElement):
TXT_LEGACY_BOTTOM_MARGIN = 1
HTML_CLASS = 'subtitle'
+
+ EPUB_TAG = 'h2'
+ EPUB_CLASS = 'insubtitle'
+
diff --git a/src/librarian/elements/headers/__init__.py b/src/librarian/elements/headers/__init__.py
index 3389eec..f3bda2b 100644
--- a/src/librarian/elements/headers/__init__.py
+++ b/src/librarian/elements/headers/__init__.py
@@ -1,6 +1,9 @@
from .naglowek_czesc import NaglowekCzesc
from .naglowek_podrozdzial import NaglowekPodrozdzial
from .naglowek_rozdzial import NaglowekRozdzial
+from .naglowek_scena import NaglowekScena
from .podtytul_czesc import PodtytulCzesc
from .podtytul_rozdzial import PodtytulRozdzial
from .podtytul_podrozdzial import PodtytulPodrozdzial
+
+
diff --git a/src/librarian/elements/headers/naglowek_czesc.py b/src/librarian/elements/headers/naglowek_czesc.py
index c7b2d9e..829e4f4 100644
--- a/src/librarian/elements/headers/naglowek_czesc.py
+++ b/src/librarian/elements/headers/naglowek_czesc.py
@@ -2,9 +2,14 @@ from ..base import WLElement
class NaglowekCzesc(WLElement):
+ SECTION_PRECEDENCE = 1
+
TXT_TOP_MARGIN = 5
TXT_BOTTOM_MARGIN = 2
TXT_LEGACY_TOP_MARGIN = 5
TXT_LEGACY_BOTTOM_MARGIN = 0
- HTML_TAG = "h2"
+ EPUB_TAG = HTML_TAG = "h2"
+
+ EPUB_CLASS = "h2"
+ EPUB_START_CHUNK = True
diff --git a/src/librarian/elements/headers/naglowek_rozdzial.py b/src/librarian/elements/headers/naglowek_rozdzial.py
index ded615f..33ff355 100644
--- a/src/librarian/elements/headers/naglowek_rozdzial.py
+++ b/src/librarian/elements/headers/naglowek_rozdzial.py
@@ -2,9 +2,15 @@ from ..base import WLElement
class NaglowekRozdzial(WLElement):
+ SECTION_PRECEDENCE = 2
+
TXT_TOP_MARGIN = 4
TXT_BOTTOM_MARGIN = 2
TXT_LEGACY_TOP_MARGIN = 4
TXT_LEGACY_BOTTOM_MARGIN = 0
HTML_TAG = 'h3'
+
+ EPUB_TAG = 'h2'
+ EPUB_CLASS = 'h3'
+ EPUB_START_CHUNK = True
diff --git a/src/librarian/elements/headers/naglowek_scena.py b/src/librarian/elements/headers/naglowek_scena.py
new file mode 100644
index 0000000..8a52ca2
--- /dev/null
+++ b/src/librarian/elements/headers/naglowek_scena.py
@@ -0,0 +1,17 @@
+from ..base import WLElement
+
+
+class NaglowekScena(WLElement):
+ SECTION_PRECEDENCE = 2
+
+ TXT_TOP_MARGIN = 4
+ TXT_BOTTOM_MARGIN = 2
+ TXT_LEGACY_TOP_MARGIN = 4
+ TXT_LEGACY_BOTTOM_MARGIN = 0
+
+ HTML_TAG = 'h3'
+
+ EPUB_TAG = 'h2'
+ EPUB_CLASS = 'h3'
+ EPUB_START_CHUNK = False
+
diff --git a/src/librarian/elements/headers/podtytul_czesc.py b/src/librarian/elements/headers/podtytul_czesc.py
index 9825211..df8fd5c 100644
--- a/src/librarian/elements/headers/podtytul_czesc.py
+++ b/src/librarian/elements/headers/podtytul_czesc.py
@@ -7,3 +7,11 @@ class PodtytulCzesc(WLElement):
HTML_TAG = "div"
HTML_CLASS = "subtitle2"
+
+ EPUB_TAG = "h2"
+ EPUB_CLASS = "h2"
+
+ def _epub_build_inner(self, builder):
+ builder.start_element('small', {})
+ super()._epub_build_inner(builder)
+ builder.end_element()
diff --git a/src/librarian/elements/headers/podtytul_podrozdzial.py b/src/librarian/elements/headers/podtytul_podrozdzial.py
index 74aef13..cc00207 100644
--- a/src/librarian/elements/headers/podtytul_podrozdzial.py
+++ b/src/librarian/elements/headers/podtytul_podrozdzial.py
@@ -7,3 +7,11 @@ class PodtytulPodrozdzial(WLElement):
HTML_TAG = "div"
HTML_CLASS = "subtitle4"
+
+ EPUB_TAG = "h2"
+ EPUB_CLASS = "h4"
+
+ def _epub_build_inner(self, builder):
+ builder.start_element('small', {})
+ super()._epub_build_inner(builder)
+ builder.end_element()
diff --git a/src/librarian/elements/headers/podtytul_rozdzial.py b/src/librarian/elements/headers/podtytul_rozdzial.py
index 675e19b..f8db548 100644
--- a/src/librarian/elements/headers/podtytul_rozdzial.py
+++ b/src/librarian/elements/headers/podtytul_rozdzial.py
@@ -7,3 +7,11 @@ class PodtytulRozdzial(WLElement):
HTML_TAG = "div"
HTML_CLASS = "subtitle3"
+
+ EPUB_TAG = "h2"
+ EPUB_CLASS = "h3"
+
+ def _epub_build_inner(self, builder):
+ builder.start_element('small', {})
+ super()._epub_build_inner(builder)
+ builder.end_element()
diff --git a/src/librarian/elements/paragraphs/akap.py b/src/librarian/elements/paragraphs/akap.py
index 0a76c52..b0c0329 100644
--- a/src/librarian/elements/paragraphs/akap.py
+++ b/src/librarian/elements/paragraphs/akap.py
@@ -9,5 +9,5 @@ class Akap(WLElement):
TXT_LEGACY_TOP_MARGIN = 2
TXT_LEGACY_BOTTOM_MARGIN = 0
- HTML_TAG = 'p'
- HTML_CLASS = 'paragraph'
+ EPUB_TAG = HTML_TAG = 'p'
+ EPUB_CLASS = HTML_CLASS = 'paragraph'
diff --git a/src/librarian/elements/poetry/strofa.py b/src/librarian/elements/poetry/strofa.py
index 7df549f..a843d20 100644
--- a/src/librarian/elements/poetry/strofa.py
+++ b/src/librarian/elements/poetry/strofa.py
@@ -1,4 +1,5 @@
from copy import copy
+import re
from ..base import WLElement
from .wers import Wers
@@ -9,8 +10,19 @@ class Strofa(WLElement):
TXT_LEGACY_TOP_MARGIN = 1
TXT_LEGACY_BOTTOM_MARGIN = 0
- HTML_TAG = 'div'
- HTML_CLASS = 'stanza'
+ EPUB_TAG = HTML_TAG = 'div'
+ EPUB_CLASS = HTML_CLASS = 'stanza'
+
+ def epub_build(self, builder):
+ super().epub_build(builder)
+ builder.start_element(
+ 'div',
+ {
+ 'class': 'stanza-spacer'
+ }
+ )
+ builder.push_text('\u00a0');
+ builder.end_element()
def get_verses(self):
from librarian.parser import parser
@@ -20,7 +32,7 @@ class Strofa(WLElement):
]
if self.text:
# Before any tags. These are text-only verses.
- pieces = self.text.split('/')
+ pieces = re.split(r"/\s+", self.text)
for piece in pieces[:-1]:
verses[-1].text = piece
verses.append(parser.makeelement('wers'))
@@ -28,7 +40,7 @@ class Strofa(WLElement):
for child in self:
if child.tail:
- pieces = child.tail.split('/')
+ pieces = re.split(r"/\s+", child.tail)
child_copy = copy(child)
child_copy.tail = pieces[0]
verses[-1].append(child_copy)
diff --git a/src/librarian/elements/poetry/wers.py b/src/librarian/elements/poetry/wers.py
index 5c28058..55cf537 100644
--- a/src/librarian/elements/poetry/wers.py
+++ b/src/librarian/elements/poetry/wers.py
@@ -9,11 +9,16 @@ class Wers(WLElement):
TXT_LEGACY_TOP_MARGIN = 1
TXT_LEGACY_BOTTOM_MARGIN = 0
- HTML_TAG = 'div'
- HTML_CLASS = 'verse'
+ EPUB_TAG = HTML_TAG = 'div'
+ EPUB_CLASS = HTML_CLASS = 'verse'
@property
def meta(self):
if hasattr(self, 'stanza'):
return self.stanza.meta
return super(Wers, self).meta
+
+ def _epub_build_inner(self, builder):
+ super()._epub_build_inner(builder)
+ builder.push_text('''\u00a0''')
+
diff --git a/src/librarian/elements/poetry/wers_akap.py b/src/librarian/elements/poetry/wers_akap.py
index 03b8187..c0d70f4 100644
--- a/src/librarian/elements/poetry/wers_akap.py
+++ b/src/librarian/elements/poetry/wers_akap.py
@@ -7,3 +7,7 @@ class WersAkap(Wers):
HTML_ATTR = {
"style": "padding-left: 1em"
}
+
+ EPUB_ATTR = {
+ "style": "margin-left: 1em"
+ }
diff --git a/src/librarian/elements/poetry/wers_cd.py b/src/librarian/elements/poetry/wers_cd.py
index a61d5bc..df1f563 100644
--- a/src/librarian/elements/poetry/wers_cd.py
+++ b/src/librarian/elements/poetry/wers_cd.py
@@ -8,3 +8,7 @@ class WersCd(Wers):
HTML_ATTR = {
"style": "padding-left: 12em",
}
+
+ EPUB_ATTR = {
+ "style": "margin-left: 12em",
+ }
diff --git a/src/librarian/elements/poetry/wers_do_prawej.py b/src/librarian/elements/poetry/wers_do_prawej.py
index 9ab5ff0..81af0d6 100644
--- a/src/librarian/elements/poetry/wers_do_prawej.py
+++ b/src/librarian/elements/poetry/wers_do_prawej.py
@@ -4,6 +4,6 @@ from .wers import Wers
class WersDoPrawej(Wers):
TXT_PREFIX = ' '
- HTML_ATTR = {
+ EPUB_ATTR = HTML_ATTR = {
"style": "text-align: right",
}
diff --git a/src/librarian/elements/poetry/wers_wciety.py b/src/librarian/elements/poetry/wers_wciety.py
index 8ac2bb3..662e57a 100644
--- a/src/librarian/elements/poetry/wers_wciety.py
+++ b/src/librarian/elements/poetry/wers_wciety.py
@@ -18,3 +18,8 @@ class WersWciety(Wers):
attr = super(WersWciety, self).get_html_attr(builder)
attr['style'] = "padding-left: {}em".format(self.typ)
return attr
+
+ def get_epub_attr(self, builder):
+ attr = super(WersWciety, self).get_html_attr(builder)
+ attr['style'] = "margin-left: {}em".format(self.typ)
+ return attr
diff --git a/src/librarian/elements/separators/sekcja_asterysk.py b/src/librarian/elements/separators/sekcja_asterysk.py
index e68430d..46be85b 100644
--- a/src/librarian/elements/separators/sekcja_asterysk.py
+++ b/src/librarian/elements/separators/sekcja_asterysk.py
@@ -7,8 +7,8 @@ class SekcjaAsterysk(WLElement):
TXT_LEGACY_TOP_MARGIN = 2
TXT_LEGACY_BOTTOM_MARGIN = 2
- HTML_TAG = "p"
- HTML_CLASS = "spacer-asterisk"
+ EPUB_TAG = HTML_TAG = "p"
+ HTML_CLASS = HTML_CLASS = "spacer-asterisk"
def _txt_build_inner(self, builder):
builder.push_text('*')
@@ -16,3 +16,5 @@ class SekcjaAsterysk(WLElement):
def _html_build_inner(self, builder):
builder.push_text("*")
+ _epub_build_inner = _html_build_inner
+
diff --git a/src/librarian/elements/separators/sekcja_swiatlo.py b/src/librarian/elements/separators/sekcja_swiatlo.py
index 7d950da..28ba6e5 100644
--- a/src/librarian/elements/separators/sekcja_swiatlo.py
+++ b/src/librarian/elements/separators/sekcja_swiatlo.py
@@ -7,3 +7,9 @@ class SekcjaSwiatlo(WLElement):
HTML_TAG = "hr"
HTML_CLASS = "spacer"
+
+ EPUB_TAG = 'p'
+ EPUB_CLASS = 'spacer'
+
+ def _epub_build_inner(self, builder):
+ builder.push_text("\u00a0")
diff --git a/src/librarian/elements/separators/separator_linia.py b/src/librarian/elements/separators/separator_linia.py
index 5249691..49ea17f 100644
--- a/src/librarian/elements/separators/separator_linia.py
+++ b/src/librarian/elements/separators/separator_linia.py
@@ -7,8 +7,8 @@ class SeparatorLinia(WLElement):
TXT_LEGACY_TOP_MARGIN = 2
TXT_LEGACY_BOTTOM_MARGIN = 2
- HTML_TAG = "hr"
- HTML_CLASS = "spacer-line"
+ EPUB_TAG = HTML_TAG = "hr"
+ EPUB_CLASS = HTML_CLASS = "spacer-line"
def _txt_build_inner(self, builder):
builder.push_text('-' * 48)
diff --git a/src/librarian/elements/styles/indeks_dolny.py b/src/librarian/elements/styles/indeks_dolny.py
index 5d19a44..bac93c0 100644
--- a/src/librarian/elements/styles/indeks_dolny.py
+++ b/src/librarian/elements/styles/indeks_dolny.py
@@ -4,4 +4,4 @@ from ..base import WLElement
class IndeksDolny(WLElement):
TXT_PREFIX = "_"
- HTML_TAG = "sub"
+ EPUB_TAG = HTML_TAG = "sub"
diff --git a/src/librarian/elements/styles/mat.py b/src/librarian/elements/styles/mat.py
index f284695..fa353f9 100644
--- a/src/librarian/elements/styles/mat.py
+++ b/src/librarian/elements/styles/mat.py
@@ -8,3 +8,7 @@ class Mat(WLElement):
e.tag = 'math'
e.attrib['xmlns'] = 'http://www.w3.org/1998/Math/MathML'
builder.cursor.append(e)
+
+ def epub_build(self, builder):
+ builder.start_element('img', {"src": builder.mathml(self)})
+ builder.end_element()
diff --git a/src/librarian/elements/styles/slowo_obce.py b/src/librarian/elements/styles/slowo_obce.py
index 3592a1e..5848aa6 100644
--- a/src/librarian/elements/styles/slowo_obce.py
+++ b/src/librarian/elements/styles/slowo_obce.py
@@ -2,5 +2,5 @@ from ..base import WLElement
class SlowoObce(WLElement):
- HTML_TAG = 'em'
- HTML_CLASS = 'foreign-word'
+ EPUB_TAG = HTML_TAG = 'em'
+ EPUB_CLASS = HTML_CLASS = 'foreign-word'
diff --git a/src/librarian/elements/styles/tytul_dziela.py b/src/librarian/elements/styles/tytul_dziela.py
index ef3618c..906d98c 100644
--- a/src/librarian/elements/styles/tytul_dziela.py
+++ b/src/librarian/elements/styles/tytul_dziela.py
@@ -3,8 +3,8 @@ from ..base import WLElement
class TytulDziela(WLElement):
- HTML_TAG = 'em'
- HTML_CLASS = 'book-title'
+ EPUB_TAG = HTML_TAG = 'em'
+ EPUB_CLASS = HTML_CLASS = 'book-title'
def normalize_text(self, text):
txt = super(TytulDziela, self).normalize_text(text)
diff --git a/src/librarian/elements/styles/wieksze_odstepy.py b/src/librarian/elements/styles/wieksze_odstepy.py
index 3229402..953e797 100644
--- a/src/librarian/elements/styles/wieksze_odstepy.py
+++ b/src/librarian/elements/styles/wieksze_odstepy.py
@@ -5,5 +5,5 @@ class WiekszeOdstepy(WLElement):
TXT_PREFIX = "*"
TXT_SUFFIX = "*"
- HTML_TAG = "em"
- HTML_CLASS = "wieksze-odstepy"
+ EPUB_TAG = HTML_TAG = "em"
+ EPUB_CLASS = HTML_CLASS = "wieksze-odstepy"
diff --git a/src/librarian/elements/styles/wyroznienie.py b/src/librarian/elements/styles/wyroznienie.py
index c76b4cf..2a71a29 100644
--- a/src/librarian/elements/styles/wyroznienie.py
+++ b/src/librarian/elements/styles/wyroznienie.py
@@ -5,5 +5,5 @@ class Wyroznienie(WLElement):
TXT_PREFIX = "*"
TXT_SUFFIX = "*"
- HTML_TAG = "em"
- HTML_CLASS = "author-emphasis"
+ EPUB_TAG = HTML_TAG = "em"
+ EPUB_CLASS = HTML_CLASS = "author-emphasis"
diff --git a/src/librarian/elements/themes/motyw.py b/src/librarian/elements/themes/motyw.py
index f9ab197..25369a7 100644
--- a/src/librarian/elements/themes/motyw.py
+++ b/src/librarian/elements/themes/motyw.py
@@ -18,3 +18,6 @@ class Motyw(WLElement):
"fid": fid,
"name": "m" + fid,
}
+
+ def epub_build(self, builder):
+ pass
diff --git a/src/librarian/epub.py b/src/librarian/epub.py
index e2cdae7..0fb91e5 100644
--- a/src/librarian/epub.py
+++ b/src/librarian/epub.py
@@ -30,6 +30,7 @@ functions.reg_person_name()
def squeeze_whitespace(s):
+ return s
return re.sub(b'\\s+', b' ', s)
@@ -62,33 +63,6 @@ def hyphenate_and_fix_conjunctions(source_tree, hyph):
parent.tail = newt
-def inner_xml(node):
- """ returns node's text and children as a string
-
- >>> print(inner_xml(etree.fromstring('xyz')))
- xyz
- """
-
- nt = node.text if node.text is not None else ''
- return ''.join(
- [nt] + [etree.tostring(child, encoding='unicode') for child in node]
- )
-
-
-def set_inner_xml(node, text):
- """ sets node's text and children from a string
-
- >>> e = etree.fromstring('bxx')
- >>> set_inner_xml(e, 'xyz')
- >>> print(etree.tostring(e, encoding='unicode'))
- xyz
- """
-
- p = etree.fromstring('%s' % text)
- node.text = p.text
- node[:] = p[:]
-
-
def node_name(node):
""" Find out a node's name
@@ -377,17 +351,8 @@ def remove_empty_lists_from_toc(toc):
toc[i] = e[0]
-def transform(wldoc, verbose=False, style=None,
- sample=None, cover=None, flags=None, hyphenate=False,
- base_url='file://./', output_type='epub'):
- """ produces a EPUB file
-
- sample=n: generate sample e-book (with at least n paragraphs)
- cover: a cover.Cover factory or True for default
- flags: less-advertising, without-fonts, working-copy
- """
- def transform_file(wldoc, chunk_counter=1, first=True, sample=None):
+def transform_file(wldoc, chunk_counter=1, first=True, sample=None, hyphenate=False, output_type='epub', spine=None, output=None, annotations=None):
""" processes one input file and proceeds to its children """
replace_characters(wldoc.edoc.getroot())
@@ -518,12 +483,27 @@ def transform(wldoc, verbose=False, style=None,
for child in wldoc.parts():
child_toc, chunk_counter, chunk_chars, sample = transform_file(
- child, chunk_counter, first=False, sample=sample)
+ child, chunk_counter, first=False, sample=sample,
+ hyphenate=hyphenate, output_type=output_type,
+ spine=spine, output=output, annotations=annotations,
+ )
toc[-1][1].extend(child_toc)
chars = chars.union(chunk_chars)
return toc, chunk_counter, chars, sample
+
+def transform(wldoc, verbose=False, style=None,
+ sample=None, cover=None, flags=None, hyphenate=False,
+ base_url='file://./', output_type='epub'):
+ """ produces a EPUB file
+
+ sample=n: generate sample e-book (with at least n paragraphs)
+ cover: a cover.Cover factory or True for default
+ flags: less-advertising, without-fonts, working-copy
+ """
+
+
document = deepcopy(wldoc)
del wldoc
@@ -584,8 +564,8 @@ def transform(wldoc, verbose=False, style=None,
base_url,
ilustr.get('src')
)
- with six.moves.urllib.request.urlopen(url) as imgfile:
- img = Image.open(imgfile)
+ imgfile = six.moves.urllib.request.urlopen(url)
+ img = Image.open(imgfile)
th_format, ext, media_type = {
'GIF': ('GIF', 'gif', 'image/gif'),
@@ -598,6 +578,8 @@ def transform(wldoc, verbose=False, style=None,
else:
th = img.resize((width, round(width * img.size[1] / img.size[0])))
+ imgfile.close()
+
buffer = six.BytesIO()
th.save(buffer, format=th_format)
@@ -677,7 +659,11 @@ def transform(wldoc, verbose=False, style=None,
annotations = etree.Element('annotations')
- toc, chunk_counter, chars, sample = transform_file(document, sample=sample)
+ toc, chunk_counter, chars, sample = transform_file(
+ document, sample=sample,
+ hyphenate=hyphenate, output_type=output_type,
+ spine=spine, output=output, annotations=annotations
+ )
output.toc = toc[0][1]
# Last modifications in container files and EPUB creation
@@ -786,6 +772,7 @@ def transform(wldoc, verbose=False, style=None,
os.chdir(cwd)
remove_empty_lists_from_toc(output.toc)
+ print(output.toc)
output_file = NamedTemporaryFile(prefix='librarian', suffix='.epub',
delete=False)
diff --git a/src/librarian/epub/style.css b/src/librarian/epub/style.css
index 82ad4b9..a740f85 100644
--- a/src/librarian/epub/style.css
+++ b/src/librarian/epub/style.css
@@ -387,4 +387,13 @@ table.border th, table.border td {
th, td {
vertical-align: top;
-}
\ No newline at end of file
+}
+
+.fundraising {
+ margin: 2em 1em 0;
+ border: 2px solid black;
+ padding: 2em 2em;
+ text-align: center;
+ font-size: 1.3em;
+ line-height: 1.4em;
+}
diff --git a/src/librarian/epub/xsltAnnotations.xsl b/src/librarian/epub/xsltAnnotations.xsl
index cd22462..90f038e 100644
--- a/src/librarian/epub/xsltAnnotations.xsl
+++ b/src/librarian/epub/xsltAnnotations.xsl
@@ -15,7 +15,7 @@
@@ -29,7 +29,7 @@
- . [przypis autorski] [przypis tÅumacza] [przypis redakcyjny] [przypis edytorski]
+ . [przypis autorski] [przypis tÅumacza] [przypis redakcyjny] [przypis edytorski]
diff --git a/src/librarian/epub/xsltScheme.xsl b/src/librarian/epub/xsltScheme.xsl
index 93767cf..0fae871 100644
--- a/src/librarian/epub/xsltScheme.xsl
+++ b/src/librarian/epub/xsltScheme.xsl
@@ -7,9 +7,7 @@
-
- WolneLektury.pl
-
+ WolneLektury.pl
@@ -79,12 +77,12 @@
-
-
-
+
+
+
@@ -376,7 +374,7 @@
-
diff --git a/src/librarian/fonts.py b/src/librarian/fonts.py
new file mode 100644
index 0000000..adaeae4
--- /dev/null
+++ b/src/librarian/fonts.py
@@ -0,0 +1,38 @@
+import os
+from shutil import rmtree
+import subprocess
+from tempfile import mkdtemp
+
+
+def strip_font(path, chars, verbose=False):
+ tmpdir = mkdtemp('-librarian-epub')
+ try:
+ cwd = os.getcwd()
+ except OSError:
+ cwd = None
+
+ os.chdir(os.path.join(os.path.dirname(os.path.realpath(__file__)),
+ 'font-optimizer'))
+ optimizer_call = [
+ 'perl', 'subset.pl', '--chars',
+ ''.join(chars).encode('utf-8'),
+ path,
+ os.path.join(tmpdir, 'font.ttf')
+ ]
+ env = {"PERL_USE_UNSAFE_INC": "1"}
+ if verbose:
+ print("Running font-optimizer")
+ subprocess.check_call(optimizer_call, env=env)
+ else:
+ dev_null = open(os.devnull, 'w')
+ subprocess.check_call(optimizer_call, stdout=dev_null,
+ stderr=dev_null, env=env)
+ with open(os.path.join(tmpdir, 'font.ttf'), 'rb') as f:
+ content = f.read()
+
+ rmtree(tmpdir)
+
+ if cwd is not None:
+ os.chdir(cwd)
+
+ return content
diff --git a/src/librarian/fundraising.py b/src/librarian/fundraising.py
new file mode 100644
index 0000000..18d7774
--- /dev/null
+++ b/src/librarian/fundraising.py
@@ -0,0 +1,13 @@
+FUNDRAISING = [
+ 'Przyjaciele Wolnych Lektur otrzymujÄ
dostÄp do nowych tekstów wspóÅczesnych autorek i autorów wczeÅniej niż inni. Kliknij, by przejÅÄ do strony pÅatnoÅci. Zadeklaruj staÅÄ
wpÅatÄ i doÅÄ
cz do Towarzystwa PrzyjacióŠWolnych Lektur.',
+ 'Czytaj teksty wspóÅczesnych autorek i autorów wczeÅniej niż inni. Ty decydujesz, ile pÅacisz! Zadeklaruj staÅÄ
wpÅatÄ i doÅÄ
cz do Towarzystwa PrzyjacióŠWolnych Lektur.',
+ 'Informacje o nowoÅciach w naszej bibliotece w Twojej skrzynce mailowej? Nic prostszego, zapisz siÄ do newslettera.
Kliknij, by pozostawiÄ swój adres e-mail.',
+ '''Przekaż 1% podatku na Wolne Lektury.
+KRS: 0000070056
+Nazwa organizacji: Fundacja Nowoczesna Polska
+
+Możesz to zrobiÄ w swoim formularzu PIT dostÄpnym od 15 lutego na stronie: www.podatki.gov.pl/pit.
+
+Każda wpÅacona kwota zostanie przeznaczona na rozwój Wolnych Lektur.
+DziÄkujemy, że jesteÅcie z nami!''',
+]
diff --git a/src/librarian/html.py b/src/librarian/html.py
index 363286c..f0f11db 100644
--- a/src/librarian/html.py
+++ b/src/librarian/html.py
@@ -58,9 +58,8 @@ def add_image_sizes(tree, gallery_path, gallery_url, base_url):
rel_path = ilustr.attrib['src']
img_url = six.moves.urllib.parse.urljoin(base_url, rel_path)
- with six.moves.urllib.request.urlopen(img_url) as f:
- img = Image.open(f)
-
+ f = six.moves.urllib.request.urlopen(img_url)
+ img = Image.open(f)
ext = {'GIF': 'gif', 'PNG': 'png'}.get(img.format, 'jpg')
srcset = []
@@ -75,10 +74,12 @@ def add_image_sizes(tree, gallery_path, gallery_url, base_url):
]
largest = None
for w in widths:
- height = round(img.size[1] * w / img.size[0])
- th = img.resize((w, height))
fname = '%d.W%d.%s' % (i, w, ext)
- th.save(gallery_path + fname)
+ fpath = gallery_path + fname
+ if not os.path.exists(fpath):
+ height = round(img.size[1] * w / img.size[0])
+ th = img.resize((w, height))
+ th.save(fpath)
th_url = gallery_url + fname
srcset.append(" ".join((
th_url,
@@ -88,6 +89,8 @@ def add_image_sizes(tree, gallery_path, gallery_url, base_url):
ilustr.attrib['srcset'] = ", ".join(srcset)
ilustr.attrib['src'] = largest_url
+ f.close()
+
def transform(wldoc, stylesheet='legacy', options=None, flags=None, css=None, gallery_path='img/', gallery_url='img/', base_url='file://./'):
"""Transforms the WL document to XHTML.
diff --git a/src/librarian/pdf.py b/src/librarian/pdf.py
index cad66a4..a025b9b 100644
--- a/src/librarian/pdf.py
+++ b/src/librarian/pdf.py
@@ -320,8 +320,8 @@ def transform(wldoc, verbose=False, save_tex=None, morefloats=None,
base_url,
ilustr.get('src')
)
- with six.moves.urllib.request.urlopen(url) as imgfile:
- img = Image.open(imgfile)
+ imgfile = six.moves.urllib.request.urlopen(url)
+ img = Image.open(imgfile)
th_format, ext, media_type = {
'GIF': ('GIF', 'gif', 'image/gif'),
@@ -338,6 +338,8 @@ def transform(wldoc, verbose=False, save_tex=None, morefloats=None,
th.save(os.path.join(temp, file_name))
ilustr.set('src', file_name)
+ imgfile.close()
+
for sponsor in book_info.sponsors:
ins = etree.Element("data-sponsor", name=sponsor)
logo = sponsor_logo(sponsor)
diff --git a/src/librarian/pdf/wl.cls b/src/librarian/pdf/wl.cls
index f8b7731..c46a0ec 100644
--- a/src/librarian/pdf/wl.cls
+++ b/src/librarian/pdf/wl.cls
@@ -145,6 +145,8 @@
\usepackage{unicode-math}
\setmathfont{Latin Modern Math}
+\usepackage{wrapfig}
+
\usepackage[overload]{textcase}
\usepackage{scalefnt}
\usepackage[colorlinks=true,linkcolor=black,setpagesize=false,urlcolor=black,xetex]{hyperref}
diff --git a/src/librarian/pdf/wl2tex.xslt b/src/librarian/pdf/wl2tex.xslt
index 43a3274..820033d 100644
--- a/src/librarian/pdf/wl2tex.xslt
+++ b/src/librarian/pdf/wl2tex.xslt
@@ -290,10 +290,25 @@
-
+
+
+
+
+ R
+ 5cm
+
+ width=
+
+
+
+
+
+
-
+
+
+
diff --git a/src/librarian/res/BN.png b/src/librarian/res/BN.png
new file mode 100644
index 0000000..2e6df23
Binary files /dev/null and b/src/librarian/res/BN.png differ
diff --git a/src/librarian/res/MKIDN.jpg b/src/librarian/res/MKIDN.jpg
new file mode 100644
index 0000000..373062c
Binary files /dev/null and b/src/librarian/res/MKIDN.jpg differ
diff --git a/src/librarian/res/atrium-logo.png b/src/librarian/res/atrium-logo.png
index 35af904..4555c55 100644
Binary files a/src/librarian/res/atrium-logo.png and b/src/librarian/res/atrium-logo.png differ
diff --git a/src/librarian/res/dofinansowano.png b/src/librarian/res/dofinansowano.png
new file mode 100644
index 0000000..80c531b
Binary files /dev/null and b/src/librarian/res/dofinansowano.png differ
diff --git a/src/librarian/text.py b/src/librarian/text.py
index e425552..5b03525 100644
--- a/src/librarian/text.py
+++ b/src/librarian/text.py
@@ -51,27 +51,39 @@ def transform(wldoc, flags=None, **options):
description = parsed_dc.description
url = document.book_info.url
- license_description = parsed_dc.license_description
+ license_name = parsed_dc.license_description
license = parsed_dc.license
+ license_description = [
+ (
+ "Wszystkie zasoby Wolnych Lektur możesz swobodnie wykorzystywaÄ, "
+ "publikowaÄ i rozpowszechniaÄ pod warunkiem zachowania warunków "
+ "licencji i zgodnie z Zasadami wykorzystania Wolnych Lektur."
+ )
+ ]
+
if license:
- license_description = (
- u"Ten utwór jest udostÄpniony na licencji %s: \n%s" % (
- license_description, license
+ license_description.append(
+ "Ten utwór jest udostÄpniony na licencji %s: %s" % (
+ license_name, license
)
)
else:
- license_description = (
- "Ten utwór nie jest objÄty majÄ
tkowym prawem autorskim "
- "i znajduje siÄ w domenie publicznej, co oznacza że "
- "możesz go swobodnie wykorzystywaÄ, publikowaÄ "
- "i rozpowszechniaÄ. JeÅli utwór opatrzony jest "
- "dodatkowymi materiaÅami (przypisy, motywy literackie "
- "etc.), które podlegajÄ
prawu autorskiemu, to te "
- "dodatkowe materiaÅy udostÄpnione sÄ
na licencji "
- "Creative Commons Uznanie Autorstwa â Na Tych Samych "
- "Warunkach 3.0 PL "
- "(http://creativecommons.org/licenses/by-sa/3.0/)"
+ license_description.append(
+ "Ten utwór jest w domenie publicznej."
)
+ license_description.append(
+ "Wszystkie materiaÅy dodatkowe (przypisy, motywy literackie) sÄ
"
+ "udostÄpnione na Licencji Wolnej Sztuki 1.3: "
+ "https://artlibre.org/licence/lal/pl/\n"
+ "Fundacja Nowoczesna Polska zastrzega sobie prawa do wydania "
+ "krytycznego zgodnie z art. Art.99(2) Ustawy o prawach autorskich "
+ "i prawach pokrewnych.\nWykorzystujÄ
c zasoby z Wolnych Lektur, "
+ "należy pamiÄtaÄ o zapisach licencji oraz zasadach, które "
+ "spisaliÅmy w Zasadach wykorzystania Wolnych Lektur: "
+ "https://wolnelektury.pl/info/zasady-wykorzystania/\nZapoznaj "
+ "siÄ z nimi, zanim udostÄpnisz dalej nasze ksiÄ
żki"
+ )
+ license_description = "\n".join(license_description)
source = parsed_dc.source_name
if source:
diff --git a/src/librarian/xslt/book2html.xslt b/src/librarian/xslt/book2html.xslt
index 04e2658..54f522e 100644
--- a/src/librarian/xslt/book2html.xslt
+++ b/src/librarian/xslt/book2html.xslt
@@ -24,6 +24,60 @@
+
@@ -133,27 +187,47 @@
+
+
+
+ ilustr
+
+
+ oblew
+
+
+
-
-
-
-
-
-
-
- (min-width: 718px) 600px,
- (min-width: 600px) calc(100vw - 118px),
- (min-width: 320px) calc(100vw - 75px),
- (min-width: 15em) calc(100wv - 60px),
- calc(100wv - 40px)
-
-
-
-
-
-
+
+
+
+
+
+
+
+ (min-width: 718px) 600px,
+ (min-width: 600px) calc(100vw - 118px),
+ (min-width: 320px) calc(100vw - 75px),
+ (min-width: 15em) calc(100wv - 60px),
+ calc(100wv - 40px)
+
+
+
+
+
+
+
+
+
+
+ width:
+
+
+
+
+
diff --git a/tests/uat/main.xml b/tests/uat/main.xml
index 4b77300..ceae2e7 100644
--- a/tests/uat/main.xml
+++ b/tests/uat/main.xml
@@ -6,28 +6,29 @@
2020-01-08
Fundacja Nowoczesna Polska
pol
- wl-test
+ main
gnu gpl
-Wolne Lektury
-Testy
-PodtytuÅ
-
+ DzieÅo nadrzÄdnePrzypis w dziele nadrzÄdnym
+ WolnePrzypis w nazwie utworu Lektury
+ TestyPrzypis w tytule utworu
+ PodtytuÅPrzypis w podtytule
+
Testy struktury
-
+
NagÅówek czÄÅci
PodtytuÅ czÄÅci
-
+
NagÅówek rozdziaÅu
PodtytuÅ rozdziaÅu
-
+
NagÅówek podrozdziaÅu
PodtytuÅ podrozdziaÅu
-
+
NagÅówek aktu
PodtytuÅ aktu
@@ -37,6 +38,210 @@
ÅródtytuÅ
NagÅówki powinny tworzyÄ prawidÅowÄ
strukturÄ. Użyte elementy: tytuÅy i podtytuÅy czÄÅci, rozdziaÅu, podrozdziaÅu, aktu i sceny, oraz ÅródtytuÅ.
+
+
+
+ Akapity
+
+ ZwykÅy akapit.
+
+ Kontynuacja akapitu.
+
+ --- Akapit dialogowy.
+
+ ZastÄpnik wersu w akapicie:
+ . . . . . . . .
+
+ Poezja cytowana w akapicie dialogowym (?):
+ --- Cytat
+
+
+
+
+
+
+ Dramat
+
+
+
+ Lista osób
+
+
+ Pustelnik --- pustelnik
+
+
+ Hesia --- Hesia
+
+
+
+
+
+
+
+ PUSTELNIK
+
+
+
+ WiÄc jako dawniej czynili mocarze,/
+ Z Lechem siÄ mieniaÅ Scyta na obrÄ
czki;/
+ A pokochawszy mocniej sercem, w darze/
+ DaÅ mu koronÄ... stÄ
d nasza korona./
+ Zbawiciel niegdyÅ wyciÄ
gajÄ
c rÄ
czki/
+ SzedÅ do niej z matki zadumanej Åona/
+ I ku rubinom podawaÅ siÄ caÅy/
+ Jako różyczka z liÅci wychylona,/
+ I woÅaÅ: caca! i na brylant biaÅy/
+ Różanych ustek pereÅkami ÅwieciÅ.
+
+
+
+ SÅychaÄ gÅos Hesi.
+
+ GÅOS HESI
+
+
+
+ MamuÅciu, tak zimno! troszkÄ ciepÅej wody...
+
+
+
+ DULSKA
+
+
+
+ Jeszcze czego? Hartujcie siÄ... Felicjan! wstajesz? Wiesz? ten bÅazen, twój syn, nie wróciÅ jeszcze do domu! Co? nic nie mówisz? naturalnie.
+ Ojciec toleruje. Niedaleko padÅo jabÅko od jabÅoni. Ale jak bÄdÄ
dÅużki maÅe --- nie zapÅacÄ.
+
+
+
+
+
+
+ Wyróżnienia
+
+ Wyróżnienia:
+ didaskalia tekstowe,
+ didaskalia,
+ indeks dolny,
+ osoba,
+ sÅowo obce,
+ tytuÅ dzieÅa,
+ wiÄksze odstÄpny,
+ wyróżnienie,
+ https://wolnelektury.pl/.
+
+
+
+
+
+ Grupy
+
+ DÅugi cytat:
+
+
+ DÅugi cytat, akapit.
+ Kontynuacja akapitu.
+ --- Akapit dialogowy
+
+ Strofa/ w/ cytacie
+
+ Didaskalia (czy tak?)
+
+
+ Cytat w cytacie!
+ Kontynuacja akapitu w cytacie
+ --- Akapit dialogowy w cytacie
+
+
+
+
+ Poezja/ cytowana/ w cytacie
+
+
+
+
+
+
+ ...
+
+
+
+ RozdziaÅ w cytacie
+ PodrozdziaÅ w cytacie
+ ÅródtytuÅ w cytacie
+
+
+
+
+
+ Nota w cytacie
+
+
+ Asterysk:
+
+
+ ÅwiatÅo:
+
+
+ Separator linia:
+
+
+ Koniec cytatu.
+
+
+
+ Tekst za cytatem.
+
+
+ Cytat poetycki:
+
+
+ NagÅówek rozdziaÅu
+ NagÅówek podrozdziaÅu
+ ÅródtytuÅ
+ NagÅówek: osoba
+
+
+
+ Nota
+
+
+
+ Akapit
+
+ Strofa/ w/ cytacie
+
+ didaskalia?
+
+
+
+ Strofa/ w/ kwestii/ w cytacie.
+
+
+
+
+ Motto-podpis
+
+
+
+
+ Poezja/
+ cytowana/
+ w cytacie/
+ poetyckim
+
+
+
+ Asterysk:
+
+
+
+
+
+
+
+
+
Strofa w przypisie
@@ -95,6 +300,114 @@
+
+
+
+
+ Wzory
+
+
+ Wzór:
+
+ δ
+ =
+
+
+ e
+ â¢
+ F
+ â¢
+ l
+ Ã
+
+
+ l
+ 2
+
+ +
+ h
+
+
+
+
+ m
+ â¢
+
+ v
+ 2
+
+
+
+
+
+
+
+
+
+
+ Separatory
+
+
+ Asterysk:
+
+
+ ÅwiatÅo:
+
+
+ Separator linia:
+
+
+
+
+
+ Tabele
+
+ Tabela bez ramek:
+
+
+
+
+ Komórka 1
+
+
+ Komórka 2
+
+
+
+
+ Komórka 3
+
+
+ Komórka 4
+
+
+
+
+ Tabela z ramkami:
+
+
+
+
+
+ Komórka 1
+
+
+ Komórka 2
+
+
+
+
+ Komórka 3
+
+
+ Komórka 4
+
+
+
+
+ Ilustracje
+
+
diff --git a/tests/uat/parent.xml b/tests/uat/parent.xml
new file mode 100644
index 0000000..544032a
--- /dev/null
+++ b/tests/uat/parent.xml
@@ -0,0 +1,15 @@
+
+
+
+ Radek Czajka
+ Test Parent Document
+ 2020-01-08
+ Fundacja Nowoczesna Polska
+ pol
+ wl-test-parent
+ gnu agpl
+ main
+ part2
+
+
+
diff --git a/tests/uat/part2.xml b/tests/uat/part2.xml
new file mode 100644
index 0000000..2459748
--- /dev/null
+++ b/tests/uat/part2.xml
@@ -0,0 +1,25 @@
+
+
+
+ Radek Czajka
+ Test Document, Part 2
+ 2020-01-08
+ Fundacja Nowoczesna Polska
+ pol
+ part2
+ gnu gpl
+
+
+
+
+
+Wolne Lektury
+Testy
+PodtytuÅ
+
+
+ Druga czÄÅÄ. Powinna byÄ widoczna
+
+
+
+