images in epub
authorJan Szejko <janek37@gmail.com>
Fri, 2 Dec 2016 14:25:27 +0000 (15:25 +0100)
committerJan Szejko <janek37@gmail.com>
Fri, 2 Dec 2016 14:25:27 +0000 (15:25 +0100)
librarian/formats/epub/__init__.py
librarian/utils.py

index b7cf539..b9d1c7a 100644 (file)
@@ -4,11 +4,15 @@
 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
 import os
 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
 import os
+import urllib
 from copy import deepcopy
 from copy import deepcopy
+from mimetypes import guess_type
 from tempfile import NamedTemporaryFile
 import zipfile
 from tempfile import NamedTemporaryFile
 import zipfile
+from urllib2 import urlopen
+
 from lxml import etree
 from lxml import etree
-from librarian import OPFNS, NCXNS, XHTMLNS
+from librarian import OPFNS, NCXNS, XHTMLNS, DCNS
 from librarian import core
 from librarian.formats import Format
 from librarian.formats.cover.wolnelektury import WLCover
 from librarian import core
 from librarian.formats import Format
 from librarian.formats.cover.wolnelektury import WLCover
@@ -30,12 +34,29 @@ class EpubFormat(Format):
         if cover is not None:
             self.cover = cover
 
         if cover is not None:
             self.cover = cover
 
-    def build(self):
+    def build(self, ctx=None):
+
+        def add_file(url, file_id):
+            filename = url.rsplit('/', 1)[1]
+            if url.startswith('file://'):
+                url = ctx.files_path + urllib.quote(url[7:])
+            if url.startswith('/'):
+                url = 'http://milpeer.eu' + url
+            file_content = urlopen(url).read()
+            zip.writestr(os.path.join('OPS', filename), file_content)
+            manifest.append(etree.fromstring(
+                '<item id="%s" href="%s" media-type="%s" />' % (file_id, filename, guess_type(url)[0])))
+
         opf = etree.parse(get_resource('formats/epub/res/content.opf'))
         manifest = opf.find(OPFNS('manifest'))
         guide = opf.find(OPFNS('guide'))
         spine = opf.find(OPFNS('spine'))
 
         opf = etree.parse(get_resource('formats/epub/res/content.opf'))
         manifest = opf.find(OPFNS('manifest'))
         guide = opf.find(OPFNS('guide'))
         spine = opf.find(OPFNS('spine'))
 
+        author = ", ". join(self.doc.meta.get(DCNS('creator')) or '')
+        title = self.doc.meta.title()
+        opf.find('.//' + DCNS('creator')).text = author
+        opf.find('.//' + DCNS('title')).text = title
+
         output_file = NamedTemporaryFile(prefix='librarian', suffix='.epub', delete=False)
         zip = zipfile.ZipFile(output_file, 'w', zipfile.ZIP_DEFLATED)
 
         output_file = NamedTemporaryFile(prefix='librarian', suffix='.epub', delete=False)
         zip = zipfile.ZipFile(output_file, 'w', zipfile.ZIP_DEFLATED)
 
@@ -58,6 +79,7 @@ class EpubFormat(Format):
         # nav_map = toc_file[-1]
 
         if self.cover is not None:
         # nav_map = toc_file[-1]
 
         if self.cover is not None:
+            cover_image = self.doc.meta.get(DCNS('relation.coverimage.url'))[0]
             cover = self.cover(self.doc)
             cover_output = cover.build()
             cover_name = 'cover.%s' % cover.format_ext
             cover = self.cover(self.doc)
             cover_output = cover.build()
             cover_name = 'cover.%s' % cover.format_ext
@@ -83,10 +105,14 @@ class EpubFormat(Format):
             opf.getroot()[0].append(etree.fromstring('<meta name="cover" content="cover-image"/>'))
             guide.append(etree.fromstring('<reference href="cover.html" type="cover" title="Okładka"/>'))
 
             opf.getroot()[0].append(etree.fromstring('<meta name="cover" content="cover-image"/>'))
             guide.append(etree.fromstring('<reference href="cover.html" type="cover" title="Okładka"/>'))
 
-        ctx = Context(format=self)
+        if not ctx:
+            ctx = Context(format=self)
+        else:
+            ctx.format = self
         ctx.toc = TOC()
         ctx.toc_level = 0
         ctx.footnotes = Footnotes()
         ctx.toc = TOC()
         ctx.toc_level = 0
         ctx.footnotes = Footnotes()
+        ctx.images = []
         ctx.part_no = 0
 
         wrap_tmpl = etree.parse(get_resource('formats/epub/res/chapter.html'))
         ctx.part_no = 0
 
         wrap_tmpl = etree.parse(get_resource('formats/epub/res/chapter.html'))
@@ -107,6 +133,9 @@ class EpubFormat(Format):
                     }))
             zip.writestr('OPS/%s.html' % partstr, etree.tostring(wrap, method='html'))
 
                     }))
             zip.writestr('OPS/%s.html' % partstr, etree.tostring(wrap, method='html'))
 
+        for i, url in enumerate(ctx.images):
+            add_file(url, 'image%s' % i)
+
         if len(ctx.footnotes.output):
             ctx.toc.add("Przypisy", "footnotes.html")
             manifest.append(etree.Element(
         if len(ctx.footnotes.output):
             ctx.toc.add("Przypisy", "footnotes.html")
             manifest.append(etree.Element(
@@ -252,6 +281,22 @@ class DivR(EpubRenderer):
 EpubFormat.renderers.register(core.Div, None, DivR('div'))
 
 
 EpubFormat.renderers.register(core.Div, None, DivR('div'))
 
 
+class DivImageR(EpubRenderer):
+    def render(self, element, ctx):
+        src = element.attrib.get('src', '')
+        ctx.images.append(src)
+        src = src.rsplit('/', 1)[1]
+        return super(DivImageR, self).render(element, Context(ctx, src=src))
+
+    def container(self, ctx):
+        root, inner = super(DivImageR, self).container(ctx)
+        src = getattr(ctx, 'src', '')
+        inner.set('src', src)
+        # inner.set('style', 'display: block; width: 60%; margin: 3em auto')
+        return root, inner
+EpubFormat.renderers.register(core.Div, 'img', DivImageR('img'))
+
+
 class HeaderR(EpubRenderer):
     def subcontext(self, element, ctx):
         return Context(ctx, inline=True)
 class HeaderR(EpubRenderer):
     def subcontext(self, element, ctx):
         return Context(ctx, inline=True)
index 25936bf..a2e3522 100755 (executable)
@@ -26,7 +26,7 @@ class Context(object):
         elif self._upctx is not None:
             return getattr(self._upctx, name)
         else:
         elif self._upctx is not None:
             return getattr(self._upctx, name)
         else:
-            raise AttributeError
+            raise AttributeError, "'%s' object has no attribute '%s'" % (type(self), name)
 
     def __setattr__(self, name, value):
         try:
 
     def __setattr__(self, name, value):
         try: