epub: subtitle fix
authorRadek Czajka <radoslaw.czajka@nowoczesnapolska.org.pl>
Mon, 17 Jan 2011 15:37:06 +0000 (16:37 +0100)
committerRadek Czajka <radoslaw.czajka@nowoczesnapolska.org.pl>
Mon, 17 Jan 2011 15:37:06 +0000 (16:37 +0100)
epub: editorial page, title page update
epubs for asbis
more cover generation

librarian/cover.py
librarian/dcparser.py
librarian/epub.py
librarian/epub/cover.html [new file with mode: 0644]
librarian/epub/style.css
librarian/epub/xsltLast.xsl [new file with mode: 0644]
librarian/epub/xsltScheme.xsl
librarian/epub/xsltTitle.xsl
librarian/functions.py
librarian/res/cover-prestigio.png [new file with mode: 0644]
scripts/book2partner

index c946d43..20cca66 100644 (file)
@@ -43,7 +43,7 @@ def cover(author, title,
 
     if background_img:
         background = Image.open(background_img)
-        img.paste(background)
+        img.paste(background, None, background)
         del background
 
     # WL logo
@@ -72,9 +72,9 @@ def virtualo_cover(author, title):
 
 def asbis_cover(author, title):
     return cover(author, u"„%s”" % title,
-          800, 800, '#000', '',
-          455, 230, 170, 60, '#fff', ImageFont.truetype(get_resource('fonts/JunicodeWL-Italic.ttf'), 50), '#000',
-          0, 230, 170, 60, '#fff', ImageFont.truetype(get_resource('fonts/JunicodeWL-Italic.ttf'), 50), '#000',
+          580, 783, '#fff', get_resource('res/cover-prestigio.png'),
+          446, 118, 62, 60, '#fff', ImageFont.truetype(get_resource('fonts/JunicodeWL-Italic.ttf'), 50), '#000',
+          0, 118, 62, 60, '#fff', ImageFont.truetype(get_resource('fonts/JunicodeWL-Italic.ttf'), 50), '#000',
           None, None
           )
 
index 07a90d7..49a33d4 100644 (file)
@@ -38,6 +38,9 @@ class Person(object):
             names = [ name for name in parts[1].split() if len(name) ] # all non-whitespace tokens
         return cls(surname, *names)
 
+    def readable(self):
+        return u" ".join(self.first_names + (self.last_name,))
+
     def __eq__(self, right):
         return self.last_name == right.last_name and self.first_names == right.first_names
 
index 666bcc9..ad84ab0 100644 (file)
@@ -8,6 +8,7 @@ from __future__ import with_statement
 import os
 import os.path
 import subprocess
+from StringIO import StringIO
 from copy import deepcopy
 from lxml import etree
 import zipfile
@@ -105,7 +106,7 @@ def find_annotations(annotations, source, part_no):
             child.clear()
             child.tail = tail
             child.text = number
-        if child.tag not in ('extra', 'podtytul'):
+        if child.tag not in ('extra',):
             find_annotations(annotations, child, part_no)
 
 
@@ -264,7 +265,7 @@ def transform_chunk(chunk_xml, chunk_no, annotations, empty=False, _empty_html_s
     return output_html, toc, chars
 
 
-def transform(provider, slug=None, file_path=None, output_file=None, output_dir=None, make_dir=False, verbose=False, sample=None):
+def transform(provider, slug=None, file_path=None, output_file=None, output_dir=None, make_dir=False, verbose=False, sample=None, cover_fn=None):
     """ produces a EPUB file
 
     provider: a DocProvider
@@ -273,6 +274,7 @@ def transform(provider, slug=None, file_path=None, output_file=None, output_dir=
     output_dir: path to directory to save output file to; either this or output_file must be present
     make_dir: writes output to <output_dir>/<author>/<slug>.epub instead of <output_dir>/<slug>.epub
     sample=n: generate sample e-book (with at least n paragraphs)
+    cover_fn: function(author, title) -> cover image
     """
 
     def transform_file(input_xml, chunk_counter=1, first=True, sample=None):
@@ -393,6 +395,21 @@ def transform(provider, slug=None, file_path=None, output_file=None, output_dir=
     manifest = opf.find('.//' + OPFNS('manifest'))
     spine = opf.find('.//' + OPFNS('spine'))
 
+    if cover_fn:
+        cover = StringIO()
+        cover_fn(book_info.author.readable(), book_info.title).save(cover, format='JPEG')
+        zip.writestr(os.path.join('OPS', 'cover.jpg'), cover.getvalue())
+        del cover
+        zip.writestr('OPS/cover.html', open(get_resource('epub/cover.html')).read())
+        manifest.append(etree.fromstring(
+            '<item id="cover" href="cover.html" media-type="application/xhtml+xml" />'))
+        manifest.append(etree.fromstring(
+            '<item id="cover-image" href="cover.jpg" media-type="image/jpeg" />'))
+        spine.insert(0, etree.fromstring('<itemref idref="cover" />'))
+        opf.getroot()[0].append(etree.fromstring('<meta name="cover" content="cover-image"/>'))
+        opf.getroot().append(etree.fromstring('<guide><reference href="cover.html" type="cover" title="Okładka"/></guide>'))
+
+
     annotations = etree.Element('annotations')
 
     toc_file = etree.fromstring('<?xml version="1.0" encoding="utf-8"?><!DOCTYPE ncx PUBLIC ' \
@@ -415,6 +432,7 @@ def transform(provider, slug=None, file_path=None, output_file=None, output_dir=
         nav_map.append(etree.fromstring(
             '<navPoint id="NavPoint-%(i)d" playOrder="%(i)d" ><navLabel><text>Przypisy</text>'\
             '</navLabel><content src="annotations.html" /></navPoint>' % {'i': toc_counter}))
+        toc_counter += 1
         manifest.append(etree.fromstring(
             '<item id="annotations" href="annotations.html" media-type="application/xhtml+xml" />'))
         spine.append(etree.fromstring(
@@ -425,6 +443,18 @@ def transform(provider, slug=None, file_path=None, output_file=None, output_dir=
         zip.writestr('OPS/annotations.html', etree.tostring(
                             html_tree, method="html", pretty_print=True))
 
+    nav_map.append(etree.fromstring(
+        '<navPoint id="NavPoint-%(i)d" playOrder="%(i)d" ><navLabel><text>Strona redakcyjna</text>'\
+        '</navLabel><content src="last.html" /></navPoint>' % {'i': toc_counter}))
+    manifest.append(etree.fromstring(
+        '<item id="last" href="last.html" media-type="application/xhtml+xml" />'))
+    spine.append(etree.fromstring(
+        '<itemref idref="last" />'))
+    html_tree = xslt(input_xml, get_resource('epub/xsltLast.xsl'))
+    chars.update(used_chars(html_tree.getroot()))
+    zip.writestr('OPS/last.html', etree.tostring(
+                        html_tree, method="html", pretty_print=True))
+
     # strip fonts
     tmpdir = mkdtemp('-librarian-epub')
     cwd = os.getcwd()
diff --git a/librarian/epub/cover.html b/librarian/epub/cover.html
new file mode 100644 (file)
index 0000000..bbe8508
--- /dev/null
@@ -0,0 +1,13 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <meta http-equiv="Content-Type" content="application/xhtml+xml; charset=utf-8" />
+    <title>Okładka</title>
+    <style type="text/css"> img { max-width: 100%; } </style>
+  </head>
+  <body style="oeb-column-number: 1;">
+    <div id="cover-image">
+      <img src="cover.jpg" alt="Okładka" />
+    </div>
+  </body>
+</html>
\ No newline at end of file
index 21a82a8..55ac117 100644 (file)
@@ -37,6 +37,11 @@ body
 a\r
 {\r
        text-decoration: none;\r
+       color: #00e;\r
+}\r
+\r
+a img {\r
+    border: 0;\r
 }\r
 \r
 #book-text\r
@@ -157,13 +162,11 @@ p
 .title-page\r
 {\r
     margin-top: 1.5em;\r
-    margin-bottom: 1.5em;\r
 }\r
 \r
 .title\r
 {\r
     font-size: 3em;\r
-    margin-bottom: 1.5em;\r
     text-align: center;\r
     line-height: 1.5em;\r
     font-weight: bold;\r
@@ -337,3 +340,10 @@ p.info img
        margin-left: 2em;\r
        margin-right: 2em;\r
 }\r
+\r
+p.minor {\r
+    font-size: 0.75em;\r
+}\r
+p.footer {\r
+    margin-top: 2em;\r
+}\r
diff --git a/librarian/epub/xsltLast.xsl b/librarian/epub/xsltLast.xsl
new file mode 100644 (file)
index 0000000..6cb2748
--- /dev/null
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<xsl:stylesheet version="1.0"\r
+    xmlns="http://www.w3.org/1999/xhtml"\r
+    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"\r
+    xmlns:dc="http://purl.org/dc/elements/1.1/"\r
+    xmlns:wl="http://wolnelektury.pl/functions"\r
+    xmlns:date="http://exslt.org/dates-and-times">\r
+  <xsl:output method="html" version="1.0" encoding="utf-8" />\r
+  <xsl:output doctype-system="http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd" />\r
+  <xsl:output doctype-public="-//W3C//DTD XHTML 1.1//EN" />\r
+\r
+  <xsl:template match="/">\r
+    <html>\r
+      <head>\r
+        <link rel="stylesheet" href="style.css" type="text/css" />\r
+        <meta http-equiv="Content-Type" content="application/xhtml+xml; charset=utf-8" />\r
+        <title>\r
+          <xsl:text>Strona redakcyjna</xsl:text>\r
+        </title>\r
+      </head>\r
+      <body>\r
+        <div id="book-text" >\r
+          <p class="info">\r
+              <xsl:choose>\r
+                  <xsl:when test="//dc:rights.license">\r
+                      Ten utwór jest udostepniony na licencji\r
+                      <a>\r
+                          <xsl:attribute name="href">\r
+                              <xsl:value-of select="//dc:rights.license" />\r
+                          </xsl:attribute>\r
+                          <xsl:value-of select="//dc:rights" />\r
+                      </a>\r
+                  </xsl:when>\r
+                  <xsl:otherwise>\r
+                    Ten utwór nie jest chroniony prawem autorskim i znajduje się w domenie\r
+                    publicznej, co oznacza, że możesz go swobodnie wykorzystywać, publikować\r
+                    i rozpowszechniać. Jeśli utwór opatrzony jest dodatkowymi materiałami\r
+                    (przypisy, motywy literackie etc.) które podlegają prawu autorskiemu, to\r
+                    te dodatkowe materiały udostępnione są na licencji\r
+                    <a href="http://creativecommons.org/licenses/by-sa/3.0/">Creative Commons\r
+                    Uznanie Autorstwa - Na Tych Samych Warunkach 3.0 PL</a>.\r
+                  </xsl:otherwise>\r
+              </xsl:choose>\r
+          </p>\r
+\r
+          <p class="info">Źródło: <a>\r
+              <xsl:attribute name="href">\r
+                  <xsl:value-of select="//dc:identifier.url" />\r
+              </xsl:attribute>\r
+              <xsl:attribute name="title">\r
+                  <xsl:value-of select="wl:person_name(//dc:creator/text())" />, <xsl:value-of select="//dc:title" />\r
+              </xsl:attribute>\r
+              <xsl:value-of select="//dc:identifier.url" />\r
+          </a></p>\r
+\r
+          <xsl:if test="//dc:source" >\r
+            <p class="info">Na podstawie: <xsl:value-of select="//dc:source" /></p>\r
+          </xsl:if>\r
+\r
+          <xsl:if test="//dc:contributor.editor|//dc:contributor.technical_editor">\r
+              <p class="info">\r
+                Opracowanie redakcyjne i przypisy:\r
+                <xsl:apply-templates select="//dc:contributor.editor|//dc:contributor.technical_editor" />\r
+              </p>\r
+          </xsl:if>\r
+\r
+          <p class="info">&#160;</p>\r
+          <p class="minor info">\r
+              Plik wygenerowany dnia <span id="file_date"><xsl:value-of select="substring(date:date(), 1, 10)" /></span>.\r
+          </p>\r
+\r
+        </div>\r
+      </body>\r
+    </html>\r
+  </xsl:template>\r
+\r
+  <xsl:template match="text()" >\r
+    <xsl:value-of select="." disable-output-escaping="yes" />\r
+  </xsl:template>\r
+\r
+  <xsl:template match="dc:contributor.editor|dc:contributor.technical_editor">\r
+      <br /><xsl:apply-templates mode='person' />\r
+  </xsl:template>\r
+\r
+  <xsl:template match="text()" mode="person">\r
+    <xsl:value-of select="wl:person_name(.)" />\r
+  </xsl:template>\r
+</xsl:stylesheet>
\ No newline at end of file
index bb96350..8b384c3 100644 (file)
@@ -19,6 +19,7 @@
           <xsl:if test="//nazwa_utworu">\r
             <!--h1 xmlns="http://www.w3.org/1999/xhtml"-->\r
               <xsl:apply-templates select=" //nazwa_utworu" mode="poczatek"/>\r
+              <xsl:apply-templates select=" //podtytul" mode="poczatek"/>\r
             <!--/h1-->\r
           </xsl:if>\r
           <xsl:apply-templates />\r
   <xsl:template match="nazwa_utworu" />\r
 \r
   <xsl:template match="podtytul" mode="poczatek">\r
-    <h2 class="subtitle" xmlns="http://www.w3.org/1999/xhtml">\r
+    <h2 class="author" xmlns="http://www.w3.org/1999/xhtml">\r
       <xsl:apply-templates />\r
     </h2>\r
   </xsl:template>\r
   <!-- Tagi IGNOROWANE -->\r
   <!--===========================================================-->\r
 \r
-  <xsl:template match="pe|pa|pr|pt" />\r
-\r
   <xsl:template match="extra" />\r
 \r
   <xsl:template match="pe|pa|pr|pt" >\r
index e8afdac..347f038 100644 (file)
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>\r
-<xsl:stylesheet version="1.0" \r
+<xsl:stylesheet version="1.0"\r
+    xmlns="http://www.w3.org/1999/xhtml"\r
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"\r
     xmlns:dc="http://purl.org/dc/elements/1.1/"\r
     xmlns:wl="http://wolnelektury.pl/functions">\r
@@ -8,7 +9,7 @@
   <xsl:output doctype-public="-//W3C//DTD XHTML 1.1//EN" />\r
 \r
   <xsl:template match="/">\r
-    <html xmlns="http://www.w3.org/1999/xhtml">\r
+    <html>\r
       <head>\r
         <link rel="stylesheet" href="style.css" type="text/css" />\r
         <meta http-equiv="Content-Type" content="application/xhtml+xml; charset=utf-8" />\r
@@ -17,7 +18,7 @@
         </title>\r
       </head>\r
       <body>\r
-        <div id="book-text" xmlns="http://www.w3.org/1999/xhtml">\r
+        <div id="book-text" >\r
           <div class='title-page'>\r
             <xsl:choose>\r
               <xsl:when test="//autor_utworu | //nazwa_utworu">\r
               </xsl:otherwise>\r
             </xsl:choose>\r
           </div>\r
-          <p class="info">Publikacja zrealizowana w ramach projektu WolneLektury.pl</p>\r
-          <xsl:if test="//dc:source" >\r
-            <p class="info">Na podstawie: <xsl:value-of select="//dc:source" /></p>\r
-          </xsl:if>\r
-          <p class="info">\r
-              <xsl:choose>\r
-                  <xsl:when test="//dc:rights.license">\r
-                      Ten utwór jest udostepniony na licencji\r
-                      <a>\r
-                          <xsl:attribute name="href">\r
-                              <xsl:value-of select="//dc:rights.license" />\r
-                          </xsl:attribute>\r
-                          <xsl:value-of select="//dc:rights" />\r
-                      </a>\r
-                  </xsl:when>\r
-                  <xsl:otherwise>\r
-                      Ten utwór nie jest chroniony prawem autorskim i znajduje się w domenie publicznej, co oznacza, że możesz go swobodnie wykorzystywać, publikować i rozpowszechniać\r
-                  </xsl:otherwise>\r
-              </xsl:choose>\r
-          </p>\r
 \r
+          <p class="info">&#160;</p>\r
+\r
+          <xsl:apply-templates select="//dc:contributor.translator" />\r
+\r
+          <!--p class="info">\r
+              <a>\r
+                  <xsl:attribute name="href">\r
+                      <xsl:value-of select="//dc:identifier.url" />\r
+                  </xsl:attribute>\r
+                  Ta lektura</a>,\r
+              podobnie jak tysiące innych, jest dostępna on-line na stronie\r
+              <a href="http://www.wolnelektury.pl/">wolnelektury.pl</a>.\r
+          </p-->\r
 \r
           <p class="info">\r
-            <img src="logo_wolnelektury.png" alt="WolneLektury.pl" />\r
+            Utwór opracowany został w&#160;ramach projektu<a href="http://www.wolnelektury.pl/"> Wolne Lektury</a> przez<a href="http://www.nowoczesnapolska.org.pl/"> Fundację Nowoczesna Polska</a>.\r
+          </p>\r
+\r
+          <p class="footer info">\r
+            <a href="http://www.wolnelektury.pl/"><img src="logo_wolnelektury.png" alt="WolneLektury.pl" /></a>\r
           </p>\r
         </div>\r
       </body>\r
   </xsl:template>\r
 \r
   <xsl:template match="dc:creator" mode="poczatek">\r
-    <div class="author" xmlns="http://www.w3.org/1999/xhtml">\r
-      <xsl:apply-templates />\r
-    </div>\r
+    <h2 class="author">\r
+      <xsl:apply-templates mode='person' />\r
+    </h2>\r
   </xsl:template>\r
 \r
   <xsl:template match="dc:creator/text()">\r
-    <div class="author" xmlns="http://www.w3.org/1999/xhtml">\r
-      <xsl:value-of select="wl:person_name(.)" />\r
-    </div>\r
+    <h2 class="author" >\r
+      <xsl:apply-templates mode='person' />\r
+    </h2>\r
+  </xsl:template>\r
+\r
+  <xsl:template match="dc:contributor.translator">\r
+    <p class="info">\r
+      tłum. <xsl:apply-templates mode="person" />\r
+    </p>\r
+  </xsl:template>\r
+\r
+  <xsl:template match="text()" mode="person">\r
+    <xsl:value-of select="wl:person_name(.)" />\r
   </xsl:template>\r
 \r
   <xsl:template match="autor_utworu" mode="poczatek">\r
-    <div class="author" xmlns="http://www.w3.org/1999/xhtml">\r
+    <h2 class="author" >\r
       <xsl:apply-templates />\r
-    </div>\r
+    </h2>\r
   </xsl:template>\r
 \r
   <xsl:template match="dzielo_nadrzedne" mode="poczatek">\r
-    <div class="collection" xmlns="http://www.w3.org/1999/xhtml">\r
+    <h2 class="collection" >\r
       <xsl:apply-templates />\r
-    </div>\r
+    </h2>\r
   </xsl:template>\r
 \r
   <xsl:template match="nazwa_utworu" mode="poczatek" >\r
-    <h1 class="title" xmlns="http://www.w3.org/1999/xhtml">\r
+    <h1 class="title" >\r
       <xsl:apply-templates />\r
     </h1>\r
   </xsl:template>\r
 \r
   <xsl:template match="dc:title" mode="poczatek" >\r
-    <h1 class="title" xmlns="http://www.w3.org/1999/xhtml">\r
+    <h1 class="title" >\r
       <xsl:apply-templates />\r
     </h1>\r
   </xsl:template>\r
 \r
   <xsl:template match="podtytul" mode="poczatek">\r
-    <div class="subtitle" xmlns="http://www.w3.org/1999/xhtml">\r
+    <h2 class="subtitle" >\r
       <xsl:apply-templates />\r
-    </div>\r
+    </h2>\r
   </xsl:template>\r
 \r
   <xsl:template match="pe|pa|pr|pt" />\r
 \r
   <xsl:template match="extra" />\r
 \r
-  <xsl:template match="pe|pa|pr|pt" />\r
-\r
-  <xsl:template match="extra" />\r
-\r
   <xsl:template match="motyw" />\r
 \r
 </xsl:stylesheet>
\ No newline at end of file
index e5023b3..08f920d 100644 (file)
@@ -91,8 +91,7 @@ def reg_person_name():
         """ Converts "Name, Forename" to "Forename Name" """
         if isinstance(text, list):
             text = ''.join(text)
-        p = Person.from_text(text)
-        return ' '.join(p.first_names + (p.last_name,))
+        return Person.from_text(text).readable()
     _register_function(person_name)
 
 
diff --git a/librarian/res/cover-prestigio.png b/librarian/res/cover-prestigio.png
new file mode 100644 (file)
index 0000000..b56843f
Binary files /dev/null and b/librarian/res/cover-prestigio.png differ
index e33ae13..6f2beac 100755 (executable)
@@ -86,6 +86,29 @@ def virtualo(filenames, output_dir, verbose):
     xml_file.close()
 
 
+def asbis(filenames, output_dir, verbose):
+    try:
+        for main_input in input_filenames:
+            if options.verbose:
+                print main_input
+            path, fname = os.path.realpath(main_input).rsplit('/', 1)
+            provider = DirDocProvider(path)
+            slug, ext = os.path.splitext(fname)
+
+            if output_dir != '':
+                try:
+                    os.makedirs(output_dir)
+                except:
+                    pass
+            outfile = os.path.join(output_dir, slug + '.epub')
+            epub.transform(provider, file_path=main_input, output_file=outfile, cover_fn=cover.asbis_cover)
+    except ParseError, e:
+        print '%(file)s:%(name)s:%(message)s' % {
+            'file': main_input,
+            'name': e.__class__.__name__,
+            'message': e.message
+        }
+
 
 
 if __name__ == '__main__':
@@ -101,6 +124,8 @@ if __name__ == '__main__':
                       help='specifies the directory for output')
     parser.add_option('--virtualo', action='store_true', dest='virtualo', default=False,
                       help='prepare files for Virtualo API')
+    parser.add_option('--asbis', action='store_true', dest='asbis', default=False,
+                      help='prepare files for Asbis')
 
     options, input_filenames = parser.parse_args()
 
@@ -110,3 +135,6 @@ if __name__ == '__main__':
 
     if options.virtualo:
         virtualo(input_filenames, options.output_dir, options.verbose)
+    if options.asbis:
+        asbis(input_filenames, options.output_dir, options.verbose)
+        
\ No newline at end of file