Merge changes from master to Aigrain publishing code - that will be used for new...
authorMarcin Koziej <marcinkoziej@nowoczesnapolska.org.pl>
Wed, 7 Aug 2013 10:03:14 +0000 (12:03 +0200)
committerMarcin Koziej <marcinkoziej@nowoczesnapolska.org.pl>
Wed, 7 Aug 2013 10:03:14 +0000 (12:03 +0200)
1  2 
librarian/cover.py
librarian/dcparser.py
librarian/epub.py
librarian/epub/xsltLast.xsl
librarian/mobi.py
librarian/pdf/wl.cls
librarian/pdf/wl2tex.xslt
scripts/book2pdf

diff --combined librarian/cover.py
@@@ -4,8 -4,22 +4,22 @@@
  # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
  #
  import re
- import Image, ImageFont, ImageDraw, ImageFilter
- from librarian import get_resource
+ from PIL import Image, ImageFont, ImageDraw, ImageFilter, ImageEnhance
+ from StringIO import StringIO
+ from librarian import get_resource, OutputFile, URLOpener
+ class Metric(object):
+     """Gets metrics from an object, scaling it by a factor."""
+     def __init__(self, obj, scale):
+         self._obj = obj
+         self._scale = float(scale)
+     def __getattr__(self, name):
+         src = getattr(self._obj, name)
+         if src and self._scale:
+             src = type(src)(self._scale * src)
+         return src
  
  
  class TextBox(object):
@@@ -93,7 -107,8 +107,8 @@@ class Cover(object)
      author_lineskip = 40
      author_color = '#000'
      author_shadow = None
-     author_font = None
+     author_font_ttf = get_resource('fonts/DejaVuSerif.ttf')
+     author_font_size = 30
  
      title_top = 100
      title_margin_left = 20
      title_lineskip = 54
      title_color = '#000'
      title_shadow = None
-     title_font = None
+     title_font_ttf = get_resource('fonts/DejaVuSerif.ttf')
+     title_font_size = 40
  
      logo_bottom = None
      logo_width = None
      uses_dc_cover = False
  
      format = 'JPEG'
+     scale = 1
  
      exts = {
          'JPEG': 'jpg',
          'PNG': 'image/png',
          }
  
-     def __init__(self, book_info):
-         #self.author = ", ".join(auth.readable() for auth in book_info.authors)
+     def __init__(self, book_info, format=None, width=None, height=None):
+         self.author = ", ".join(auth.readable() for auth in book_info.authors)
          self.title = book_info.title
+         if format is not None:
+             self.format = format
+         scale = max(float(width or 0) / self.width, float(height or 0) / self.height)
+         if scale:
+             self.scale = scale
  
      def pretty_author(self):
          """Allows for decorating author's name."""
          return self.title
  
      def image(self):
-         img = Image.new('RGB', (self.width, self.height), self.background_color)
+         metr = Metric(self, self.scale)
+         img = Image.new('RGB', (metr.width, metr.height), self.background_color)
  
          if self.background_img:
              background = Image.open(self.background_img)
              del background
  
          # WL logo
-         if self.logo_width:
+         if metr.logo_width:
              logo = Image.open(get_resource('res/wl-logo.png'))
-             logo = logo.resize((self.logo_width, logo.size[1] * self.logo_width / logo.size[0]))
-             img.paste(logo, ((self.width - self.logo_width) / 2, img.size[1] - logo.size[1] - self.logo_bottom))
+             logo = logo.resize((metr.logo_width, logo.size[1] * metr.logo_width / logo.size[0]))
+             img.paste(logo, ((metr.width - metr.logo_width) / 2, img.size[1] - logo.size[1] - metr.logo_bottom))
  
-         top = self.author_top
+         top = metr.author_top
          tbox = TextBox(
-             self.width - self.author_margin_left - self.author_margin_right,
-             self.height - top,
+             metr.width - metr.author_margin_left - metr.author_margin_right,
+             metr.height - top,
              )
-         author_font = self.author_font or ImageFont.truetype(
-             get_resource('fonts/DejaVuSerif.ttf'), 30)
+             
+         author_font = ImageFont.truetype(
+             self.author_font_ttf, metr.author_font_size)
          tbox.text(self.pretty_author(), self.author_color, author_font,
-             self.author_lineskip, self.author_shadow)
+             metr.author_lineskip, self.author_shadow)
          text_img = tbox.image()
-         img.paste(text_img, (self.author_margin_left, top), text_img)
+         img.paste(text_img, (metr.author_margin_left, top), text_img)
  
-         top += text_img.size[1] + self.title_top
+         top += text_img.size[1] + metr.title_top
          tbox = TextBox(
-             self.width - self.title_margin_left - self.title_margin_right,
-             self.height - top,
+             metr.width - metr.title_margin_left - metr.title_margin_right,
+             metr.height - top,
              )
-         title_font = self.author_font or ImageFont.truetype(
-             get_resource('fonts/DejaVuSerif.ttf'), 40)
+         title_font = ImageFont.truetype(
+             self.title_font_ttf, metr.title_font_size)
          tbox.text(self.pretty_title(), self.title_color, title_font,
-             self.title_lineskip, self.title_shadow)
+             metr.title_lineskip, self.title_shadow)
          text_img = tbox.image()
-         img.paste(text_img, (self.title_margin_left, top), text_img)
+         img.paste(text_img, (metr.title_margin_left, top), text_img)
  
          return img
  
          return self.exts[self.format]
  
      def save(self, *args, **kwargs):
-         return self.image().save(format=self.format, *args, **kwargs)
+         return self.image().save(format=self.format, quality=95, *args, **kwargs)
+     def output_file(self, *args, **kwargs):
+         imgstr = StringIO()
+         self.save(imgstr, *args, **kwargs)
+         return OutputFile.from_string(imgstr.getvalue())
  
  
  class WLCover(Cover):
      width = 600
      height = 833
      uses_dc_cover = True
-     author_font = ImageFont.truetype(
-         get_resource('fonts/JunicodeWL-Regular.ttf'), 20)
+     author_font_ttf = get_resource('fonts/JunicodeWL-Regular.ttf')
+     author_font_size = 20
      author_lineskip = 30
-     title_font = ImageFont.truetype(
-         get_resource('fonts/DejaVuSerif-Bold.ttf'), 30)
+     title_font_ttf = get_resource('fonts/DejaVuSerif-Bold.ttf')
+     title_font_size = 30
      title_lineskip = 40
      title_box_width = 350
+     
+     box_top_margin = 100
+     box_bottom_margin = 100
+     box_padding_y = 20
+     box_above_line = 10
+     box_below_line = 15
+     box_line_left = 75
+     box_line_right = 275
+     box_line_width = 2
+     logo_top = 15
+     logo_width = 140
      bar_width = 35
      background_color = '#444'
      author_color = '#444'
          u'Współczesność': '#06393d',
      }
  
-     def __init__(self, book_info):
-         super(WLCover, self).__init__(book_info)
+     def __init__(self, book_info, format=None, width=None, height=None, with_logo=False):
+         super(WLCover, self).__init__(book_info, format=format, width=width, height=height)
          self.kind = book_info.kind
          self.epoch = book_info.epoch
-         print book_info.cover_url
 -        self.with_logo = with_logo
          if book_info.cover_url:
-             from urllib2 import urlopen
-             from StringIO import StringIO
-             bg_src = urlopen(book_info.cover_url)
+             url = book_info.cover_url
+             bg_src = None
+             if bg_src is None:
+                 bg_src = URLOpener().open(url)
              self.background_img = StringIO(bg_src.read())
              bg_src.close()
          else:
          return self.author.upper()
  
      def image(self):
-         img = Image.new('RGB', (self.width, self.height), self.background_color)
+         metr = Metric(self, self.scale)
+         img = Image.new('RGB', (metr.width, metr.height), self.background_color)
          draw = ImageDraw.Draw(img)
  
          if self.epoch in self.epoch_colors:
              epoch_color = self.epoch_colors[self.epoch]
          else:
              epoch_color = '#000'
-         draw.rectangle((0, 0, self.bar_width, self.height), fill=epoch_color)
+         draw.rectangle((0, 0, metr.bar_width, metr.height), fill=epoch_color)
  
          if self.background_img:
              src = Image.open(self.background_img)
-             trg_size = (self.width - self.bar_width, self.height)
+             trg_size = (metr.width - metr.bar_width, metr.height)
              if src.size[0] * trg_size[1] < src.size[1] * trg_size[0]:
                  resized = (
                      trg_size[0],
                      src.size[1] * trg_size[0] / src.size[0]
                  )
                  cut = (resized[1] - trg_size[1]) / 2
-                 src = src.resize(resized)
+                 src = src.resize(resized, Image.ANTIALIAS)
                  src = src.crop((0, cut, src.size[0], src.size[1] - cut))
              else:
                  resized = (
                      trg_size[1],
                  )
                  cut = (resized[0] - trg_size[0]) / 2
-                 src = src.resize(resized)
+                 src = src.resize(resized, Image.ANTIALIAS)
                  src = src.crop((cut, 0, src.size[0] - cut, src.size[1]))
  
-             img.paste(src, (self.bar_width, 0))
+             img.paste(src, (metr.bar_width, 0))
              del src
  
-         box = TextBox(self.title_box_width, self.height, padding_y=20)
+         box = TextBox(metr.title_box_width, metr.height, padding_y=metr.box_padding_y)
+         author_font = ImageFont.truetype(
+             self.author_font_ttf, metr.author_font_size)
          box.text(self.pretty_author(),
-                  font=self.author_font,
-                  line_height=self.author_lineskip,
+                  font=author_font,
+                  line_height=metr.author_lineskip,
                   color=self.author_color,
                   shadow_color=self.author_shadow,
                  )
  
-         box.skip(10)
-         box.draw.line((75, box.height, 275, box.height),
-                 fill=self.author_color, width=2)
-         box.skip(15)
+         box.skip(metr.box_above_line)
+         box.draw.line((metr.box_line_left, box.height, metr.box_line_right, box.height),
+                 fill=self.author_color, width=metr.box_line_width)
+         box.skip(metr.box_below_line)
  
+         title_font = ImageFont.truetype(
+             self.title_font_ttf, metr.title_font_size)
          box.text(self.pretty_title(),
-                  line_height=self.title_lineskip,
-                  font=self.title_font,
+                  line_height=metr.title_lineskip,
+                  font=title_font,
                   color=epoch_color,
                   shadow_color=self.title_shadow,
                  )
+         if self.with_logo:
+             logo = Image.open(get_resource('res/wl-logo-mono.png'))
+             logo = logo.resize((metr.logo_width, logo.size[1] * metr.logo_width / logo.size[0]), Image.ANTIALIAS)
+             alpha = logo.split()[3]
+             alpha = ImageEnhance.Brightness(alpha).enhance(.75)
+             logo.putalpha(alpha)
+             box.skip(metr.logo_top + logo.size[1])
          box_img = box.image()
  
          if self.kind == 'Liryka':
              # top
-             box_top = 100
+             box_top = metr.box_top_margin
          elif self.kind == 'Epika':
              # bottom
-             box_top = self.height - 100 - box_img.size[1]
+             box_top = metr.height - metr.box_bottom_margin - box_img.size[1]
          else:
              # center
-             box_top = (self.height - box_img.size[1]) / 2
+             box_top = (metr.height - box_img.size[1]) / 2
  
-         box_left = self.bar_width + (self.width - self.bar_width -
+         box_left = metr.bar_width + (metr.width - metr.bar_width -
                          box_img.size[0]) / 2
          draw.rectangle((box_left, box_top,
              box_left + box_img.size[0], box_top + box_img.size[1]),
              fill='#fff')
          img.paste(box_img, (box_left, box_top), box_img)
  
-         return img
+         if self.with_logo:
+             img.paste(logo, 
+                 (box_left + (box_img.size[0] - logo.size[0]) / 2,
+                     box_top + box_img.size[1] - metr.box_padding_y - logo.size[1]), mask=logo)
  
+         return img
  
  
  class VirtualoCover(Cover):
@@@ -325,7 -385,8 +384,8 @@@ class PrestigioCover(Cover)
      author_lineskip = 60
      author_color = '#fff'
      author_shadow = '#000'
-     author_font = ImageFont.truetype(get_resource('fonts/JunicodeWL-Italic.ttf'), 50)
+     author_font_ttf = get_resource('fonts/JunicodeWL-Italic.ttf')
+     author_font_size = 50
  
      title_top = 0
      title_margin_left = 118
      title_lineskip = 60
      title_color = '#fff'
      title_shadow = '#000'
-     title_font = ImageFont.truetype(get_resource('fonts/JunicodeWL-Italic.ttf'), 50)
+     title_font_ttf = get_resource('fonts/JunicodeWL-Italic.ttf')
+     title_font_size = 50
  
      def pretty_title(self):
          return u"„%s”" % self.title
@@@ -349,14 -411,16 +410,16 @@@ class BookotekaCover(Cover)
      author_margin_right = 233
      author_lineskip = 156
      author_color = '#d9d919'
-     author_font = ImageFont.truetype(get_resource('fonts/JunicodeWL-Regular.ttf'), 130)
+     author_font_ttf = get_resource('fonts/JunicodeWL-Regular.ttf')
+     author_font_size = 130
  
      title_top = 400
      title_margin_left = 307
      title_margin_right = 233
      title_lineskip = 168
      title_color = '#d9d919'
-     title_font = ImageFont.truetype(get_resource('fonts/JunicodeWL-Regular.ttf'), 140)
+     title_font_ttf = get_resource('fonts/JunicodeWL-Regular.ttf')
+     title_font_size = 140
  
      format = 'PNG'
  
@@@ -365,18 -429,10 +428,10 @@@ class GandalfCover(Cover)
      width = 600
      height = 730
      background_img = get_resource('res/cover-gandalf.png')
-     author_font = ImageFont.truetype(get_resource('fonts/JunicodeWL-Regular.ttf'), 30)
-     title_font = ImageFont.truetype(get_resource('fonts/JunicodeWL-Regular.ttf'), 40)
+     author_font_ttf = get_resource('fonts/JunicodeWL-Regular.ttf')
+     author_font_size = 30
+     title_font_ttf = get_resource('fonts/JunicodeWL-Regular.ttf')
+     title_font_size = 40
      logo_bottom = 25
      logo_width = 250
      format = 'PNG'
- class ImageCover(WLCover):
-     format = 'JPEG'
-     def __init__(self, *args, **kwargs):
-         super(ImageCover, self).__init__(*args, **kwargs)
-         self.im = Image.open(self.background_img)
-         self.width, self.height = self.im.size
-     def image(self):
-         return self.im
diff --combined librarian/dcparser.py
@@@ -115,10 -115,21 +115,21 @@@ class Field(object)
          except ValueError, e:
              raise ValidationError("Field '%s' - invald value: %s" % (self.uri, e.message))
  
-     def validate(self, fdict, strict=False):
+     def validate(self, fdict, fallbacks=None, strict=False):
+         if fallbacks is None:
+             fallbacks = {}
          if not fdict.has_key(self.uri):
              if not self.required:
-                 f = self.default
+                 # Accept single value for single fields and saliases.
+                 if self.name in fallbacks:
+                     if self.multiple:
+                         f = fallbacks[self.name]
+                     else:
+                         f = [fallbacks[self.name]]
+                 elif self.salias and self.salias in fallbacks:
+                     f = [fallbacks[self.salias]]
+                 else:
+                     f = self.default
              else:
                  raise ValidationError("Required field %s not found" % self.uri)
          else:
@@@ -152,7 -163,7 +163,7 @@@ class WorkInfo(object)
      __metaclass__ = DCInfo
  
      FIELDS = (
 -        Field( DCNS('creator'), 'authors', as_person, salias='author', multiple=True),
 +        Field( DCNS('creator'), 'authors', as_person, salias='author', multiple=True, required=False),
          Field( DCNS('title'), 'title'),
          Field( DCNS('type'), 'type', required=False, multiple=True),
  
  
          Field( DCNS('source'), 'source_name', required=False),
          Field( DCNS('source.URL'), 'source_url', required=False),
 -        Field( DCNS('identifier.url'), 'url', WLURI, strict=as_wluri_strict),
 +        Field( DCNS('identifier.url'), 'url', WLURI, strict=as_wluri_strict, required=False),
          Field( DCNS('rights.license'), 'license', required=False),
          Field( DCNS('rights'), 'license_description'),
      )
  
          return cls(desc.attrib, field_dict, *args, **kwargs)
  
-     def __init__(self, rdf_attrs, dc_fields, strict=False):
+     def __init__(self, rdf_attrs, dc_fields, fallbacks=None, strict=False):
          """rdf_attrs should be a dictionary-like object with any attributes of the RDF:Description.
          dc_fields - dictionary mapping DC fields (with namespace) to list of text values for the
          given field. """
          self.fmap = {}
  
          for field in self.FIELDS:
-             value = field.validate(dc_fields, strict=strict)
+             value = field.validate(dc_fields, fallbacks=fallbacks,
+                             strict=strict)
              setattr(self, 'prop_' + field.name, value)
              self.fmap[field.name] = field
              if field.salias: self.fmap[field.salias] = field
diff --combined librarian/epub.py
@@@ -7,6 -7,7 +7,7 @@@ from __future__ import with_statemen
  
  import os
  import os.path
+ import re
  import subprocess
  from StringIO import StringIO
  from copy import deepcopy
@@@ -16,7 -17,7 +17,7 @@@ from tempfile import mkdtemp, NamedTemp
  from shutil import rmtree
  
  from librarian import RDFNS, WLNS, NCXNS, OPFNS, XHTMLNS, OutputFile
- from librarian.cover import ImageCover as WLCover
+ from librarian.cover import WLCover
  
  from librarian import functions, get_resource
  
@@@ -79,7 -80,7 +80,7 @@@ def replace_characters(node)
          return text.replace(u"\ufeff", u"")\
                     .replace("---", u"\u2014")\
                     .replace("--", u"\u2013")\
-                    .replace(",,", u"")\
+                    .replace(",,", u"\u201E")\
                     .replace('"', u"\u201D")\
                     .replace("'", u"\u2019")
      if node.tag in ('uwaga', 'extra'):
@@@ -109,31 -110,74 +110,74 @@@ def find_annotations(annotations, sourc
              find_annotations(annotations, child, part_no)
  
  
+ class Stanza(object):
+     """
+     Converts / verse endings into verse elements in a stanza.
+     Slashes may only occur directly in the stanza. Any slashes in subelements
+     will be ignored, and the subelements will be put inside verse elements.
+     >>> s = etree.fromstring("<strofa>a <b>c</b> <b>c</b>/\\nb<x>x/\\ny</x>c/ \\nd</strofa>")
+     >>> Stanza(s).versify()
+     >>> print etree.tostring(s)
+     <strofa><wers_normalny>a <b>c</b> <b>c</b></wers_normalny><wers_normalny>b<x>x/
+     y</x>c</wers_normalny><wers_normalny>d</wers_normalny></strofa>
+     
+     """
+     def __init__(self, stanza_elem):
+         self.stanza = stanza_elem
+         self.verses = []
+         self.open_verse = None
+     def versify(self):
+         self.push_text(self.stanza.text)
+         for elem in self.stanza:
+             self.push_elem(elem)
+             self.push_text(elem.tail)
+         tail = self.stanza.tail
+         self.stanza.clear()
+         self.stanza.tail = tail
+         self.stanza.extend(self.verses)
+     def open_normal_verse(self):
+         self.open_verse = self.stanza.makeelement("wers_normalny")
+         self.verses.append(self.open_verse)
+     def get_open_verse(self):
+         if self.open_verse is None:
+             self.open_normal_verse()
+         return self.open_verse
+     def push_text(self, text):
+         if not text:
+             return
+         for i, verse_text in enumerate(re.split(r"/\s*\n", text)):
+             if i:
+                 self.open_normal_verse()
+             verse = self.get_open_verse()
+             if len(verse):
+                 verse[-1].tail = (verse[-1].tail or "") + verse_text
+             else:
+                 verse.text = (verse.text or "") + verse_text
+     def push_elem(self, elem):
+         if elem.tag.startswith("wers"):
+             verse = deepcopy(elem)
+             verse.tail = None
+             self.verses.append(verse)
+             self.open_verse = verse
+         else:
+             appended = deepcopy(elem)
+             appended.tail = None
+             self.get_open_verse().append(appended)
  def replace_by_verse(tree):
      """ Find stanzas and create new verses in place of a '/' character """
  
      stanzas = tree.findall('.//' + WLNS('strofa'))
-     for node in stanzas:
-         for child_node in node:
-             if child_node.tag in ('slowo_obce', 'wyroznienie'):
-                 foreign_verses = inner_xml(child_node).split('/\n')
-                 if len(foreign_verses) > 1:
-                     new_foreign = ''
-                     for foreign_verse in foreign_verses:
-                         if foreign_verse.startswith('<wers'):
-                             new_foreign += foreign_verse
-                         else:
-                             new_foreign += ''.join(('<wers_normalny>', foreign_verse, '</wers_normalny>'))
-                     set_inner_xml(child_node, new_foreign)
-         verses = inner_xml(node).split('/\n')
-         if len(verses) > 1:
-             modified_inner_xml = ''
-             for verse in verses:
-                 if verse.startswith('<wers') or verse.startswith('<extra'):
-                     modified_inner_xml += verse
-                 else:
-                     modified_inner_xml += ''.join(('<wers_normalny>', verse, '</wers_normalny>'))
-             set_inner_xml(node, modified_inner_xml)
+     for stanza in stanzas:
+         Stanza(stanza).versify()
  
  
  def add_to_manifest(manifest, partno):
@@@ -248,15 -292,14 +292,14 @@@ def chop(main_text)
      last_node_part = False
      for one_part in main_text:
          name = one_part.tag
-         #if name == 'naglowek_czesc':
-         #    yield part_xml
-         #    last_node_part = True
-         #    main_xml_part[:] = [deepcopy(one_part)]
-         #elif not last_node_part and name in ("naglowek_rozdzial", "naglowek_akt", "srodtytul"):
-         #    yield part_xml
-         #    main_xml_part[:] = [deepcopy(one_part)]
-         #else:
-         if True:
+         if name == 'naglowek_czesc':
+             yield part_xml
+             last_node_part = True
+             main_xml_part[:] = [deepcopy(one_part)]
+         elif not last_node_part and name in ("naglowek_rozdzial", "naglowek_akt", "srodtytul"):
+             yield part_xml
+             main_xml_part[:] = [deepcopy(one_part)]
+         else:
              main_xml_part.append(deepcopy(one_part))
              last_node_part = False
      yield part_xml
@@@ -266,24 -309,21 +309,21 @@@ def transform_chunk(chunk_xml, chunk_no
      """ transforms one chunk, returns a HTML string, a TOC object and a set of used characters """
  
      toc = TOC()
-     #for element in chunk_xml[0]:
-     #    if element.tag in ("naglowek_czesc", "naglowek_rozdzial", "naglowek_akt", "srodtytul"):
-     #        toc.add(node_name(element), "part%d.html" % chunk_no)
-     #    elif element.tag in ('naglowek_podrozdzial', 'naglowek_scena'):
-     #        subnumber = toc.add(node_name(element), "part%d.html" % chunk_no, level=1, is_part=False)
-     #        element.set('sub', str(subnumber))
+     for element in chunk_xml[0]:
+         if element.tag in ("naglowek_czesc", "naglowek_rozdzial", "naglowek_akt", "srodtytul"):
+             toc.add(node_name(element), "part%d.html" % chunk_no)
+         elif element.tag in ('naglowek_podrozdzial', 'naglowek_scena'):
+             subnumber = toc.add(node_name(element), "part%d.html" % chunk_no, level=1, is_part=False)
+             element.set('sub', str(subnumber))
      if empty:
          if not _empty_html_static:
              _empty_html_static.append(open(get_resource('epub/emptyChunk.html')).read())
          chars = set()
          output_html = _empty_html_static[0]
      else:
-         if chunk_no == 1:
-             html_tree = xslt(chunk_xml, get_resource('epub/xsltScheme-FoC.xsl'))
-         else:
-             find_annotations(annotations, chunk_xml, chunk_no)
-             replace_by_verse(chunk_xml)
-             html_tree = xslt(chunk_xml, get_resource('epub/xsltScheme.xsl'))
+         find_annotations(annotations, chunk_xml, chunk_no)
+         replace_by_verse(chunk_xml)
+         html_tree = xslt(chunk_xml, get_resource('epub/xsltScheme.xsl'))
          chars = used_chars(html_tree.getroot())
          output_html = etree.tostring(html_tree, method="html", pretty_print=True)
      return output_html, toc, chars
@@@ -295,7 -335,7 +335,7 @@@ def transform(wldoc, verbose=False
      """ produces a EPUB file
  
      sample=n: generate sample e-book (with at least n paragraphs)
-     cover: a cover.Cover object or True for default
+     cover: a cover.Cover factory or True for default
      flags: less-advertising, without-fonts, working-copy
      """
  
  
          # every input file will have a TOC entry,
          # pointing to starting chunk
-         # hack for FoC:
-         if wldoc.book_info.author is not None:
-             toc_title = "%s, %s" % (wldoc.book_info.author.readable(), wldoc.book_info.title)
-             note = wldoc.edoc.find('//dzielo_nadrzedne')
-             if note is not None:
-                 toc_title += " (%s)" % note.text
-         else:
-             toc_title = wldoc.book_info.title
-         toc = TOC(toc_title, "part%d.html" % chunk_counter)
+         toc = TOC(wldoc.book_info.title, "part%d.html" % chunk_counter)
          chars = set()
          if first:
              # write book title page
              zip.writestr('OPS/title.html',
                   etree.tostring(html_tree, method="html", pretty_print=True))
              # add a title page TOC entry
-             toc.add(u"Title page", "title.html")
-             toc.add(u"Dear readers!", "part1.html")
+             toc.add(u"Strona tytułowa", "title.html")
          elif wldoc.book_info.parts:
              # write title page for every parent
              if sample is not None and sample <= 0:
          for flag in flags:
              document.edoc.getroot().set(flag, 'yes')
  
+     # add editors info
+     document.edoc.getroot().set('editors', u', '.join(sorted(
+         editor.readable() for editor in document.editors())))
      opf = xslt(document.book_info.to_etree(), get_resource('epub/xsltContent.xsl'))
      manifest = opf.find('.//' + OPFNS('manifest'))
      guide = opf.find('.//' + OPFNS('guide'))
                         '<rootfiles><rootfile full-path="OPS/content.opf" ' \
                         'media-type="application/oebps-package+xml" />' \
                         '</rootfiles></container>')
-     #zip.write(get_resource('res/wl-logo-small.png'), os.path.join('OPS', 'logo_wolnelektury.png'))
-     #zip.write(get_resource('res/jedenprocent.png'), os.path.join('OPS', 'jedenprocent.png'))
-     zip.write('logo.png', os.path.join('OPS', 'logo.png'))
+     zip.write(get_resource('res/wl-logo-small.png'), os.path.join('OPS', 'logo_wolnelektury.png'))
+     zip.write(get_resource('res/jedenprocent.png'), os.path.join('OPS', 'jedenprocent.png'))
      if not style:
          style = get_resource('epub/style.css')
      zip.write(style, os.path.join('OPS', 'style.css'))
      if cover:
          if cover is True:
              cover = WLCover
-         if cover.uses_dc_cover:
-             if document.book_info.cover_by:
-                 document.edoc.getroot().set('data-cover-by', document.book_info.cover_by)
-             if document.book_info.cover_source:
-                 document.edoc.getroot().set('data-cover-source', document.book_info.cover_source)
  
          cover_file = StringIO()
 -        bound_cover = cover(document.book_info)
 -        bound_cover.save(cover_file)
 -        cover_name = 'cover.%s' % bound_cover.ext()
 -        zip.writestr(os.path.join('OPS', cover_name), cover_file.getvalue())
 +        c = cover(document.book_info)
-         import Image
-         c.im = Image.open('cover.jpg')
-         c.ext = lambda: 'jpg'
 +        c.save(cover_file)
 +        c_name = 'cover.%s' % c.ext()
 +        zip.writestr(os.path.join('OPS', c_name), cover_file.getvalue())
          del cover_file
  
          cover_tree = etree.parse(get_resource('epub/cover.html'))
-         cover_tree.find('//' + XHTMLNS('img')).set('src', c_name)
+         cover_tree.find('//' + XHTMLNS('img')).set('src', cover_name)
          zip.writestr('OPS/cover.html', etree.tostring(
                          cover_tree, method="html", pretty_print=True))
  
+         if bound_cover.uses_dc_cover:
+             if document.book_info.cover_by:
+                 document.edoc.getroot().set('data-cover-by', document.book_info.cover_by)
+             if document.book_info.cover_source:
+                 document.edoc.getroot().set('data-cover-source', document.book_info.cover_source)
          manifest.append(etree.fromstring(
              '<item id="cover" href="cover.html" media-type="application/xhtml+xml" />'))
          manifest.append(etree.fromstring(
-             '<item id="cover-image" href="%s" media-type="%s" />' % (c_name, c.mime_type())))
+             '<item id="cover-image" href="%s" media-type="%s" />' % (cover_name, bound_cover.mime_type())))
          spine.insert(0, etree.fromstring('<itemref idref="cover" linear="no" />'))
          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"/>'))
              '<item id="html_toc" href="toc.html" media-type="application/xhtml+xml" />'))
          spine.append(etree.fromstring(
              '<itemref idref="html_toc" />'))
-         guide.append(etree.fromstring('<reference href="toc.html" type="toc" title="Table of Contents"/>'))
+         guide.append(etree.fromstring('<reference href="toc.html" type="toc" title="Spis treści"/>'))
  
      toc, chunk_counter, chars, sample = transform_file(document, sample=sample)
  
          zip.writestr('OPS/annotations.html', etree.tostring(
                              html_tree, method="html", pretty_print=True))
  
-     toc.add("Editorial page", "last.html")
+     toc.add("Weprzyj Wolne Lektury", "support.html")
+     manifest.append(etree.fromstring(
+         '<item id="support" href="support.html" media-type="application/xhtml+xml" />'))
+     spine.append(etree.fromstring(
+         '<itemref idref="support" />'))
+     html_string = open(get_resource('epub/support.html')).read()
+     chars.update(used_chars(etree.fromstring(html_string)))
+     zip.writestr('OPS/support.html', html_string)
+     toc.add("Strona redakcyjna", "last.html")
      manifest.append(etree.fromstring(
          '<item id="last" href="last.html" media-type="application/xhtml+xml" />'))
      spine.append(etree.fromstring(
      if not flags or not 'without-fonts' in flags:
          # strip fonts
          tmpdir = mkdtemp('-librarian-epub')
-         cwd = os.getcwd()
+         try:
+             cwd = os.getcwd()
+         except OSError:
+             cwd = None
  
          os.chdir(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'font-optimizer'))
          for fname in 'DejaVuSerif.ttf', 'DejaVuSerif-Bold.ttf', 'DejaVuSerif-Italic.ttf', 'DejaVuSerif-BoldItalic.ttf':
              manifest.append(etree.fromstring(
                  '<item id="%s" href="%s" media-type="font/ttf" />' % (fname, fname)))
          rmtree(tmpdir)
-         os.chdir(cwd)
+         if cwd is not None:
+             os.chdir(cwd)
  
      zip.writestr('OPS/content.opf', etree.tostring(opf, pretty_print=True))
      title = document.book_info.title
  
      # write TOC
      if html_toc:
-         toc.add(u"Table of Contents", "toc.html", index=1)
+         toc.add(u"Spis treści", "toc.html", index=1)
          zip.writestr('OPS/toc.html', toc.html().encode('utf-8'))
      toc.write_to_xml(nav_map)
      zip.writestr('OPS/toc.ncx', etree.tostring(toc_file, pretty_print=True))
@@@ -15,7 -15,7 +15,7 @@@
          <link rel="stylesheet" href="style.css" type="text/css" />
          <meta http-equiv="Content-Type" content="application/xhtml+xml; charset=utf-8" />
          <title>
-           <xsl:text>Editorial page</xsl:text>
+           <xsl:text>Strona redakcyjna</xsl:text>
          </title>
        </head>
        <body>
            <p class="info">
                <xsl:choose>
                    <xsl:when test="//dc:rights.license">
-                       This book is available under the terms of
+                       Ten utwór jest udostepniony na licencji
                        <a>
                            <xsl:attribute name="href">
                                <xsl:value-of select="//dc:rights.license" />
                            </xsl:attribute>
                            <xsl:value-of select="//dc:rights" />
-                       </a>.
+                       </a>
                    </xsl:when>
                    <xsl:otherwise>
                      Ten utwór nie jest chroniony prawem autorskim i znajduje się w domenie
                </xsl:choose>
            </p>
  
-           <p class="info">Published by <a href="http://nowoczesnapolska.org.pl">Modern Poland Foundation</a>, 2012.</p>
+           <p class="info">Źródło: <a>
+               <xsl:attribute name="href">
+                   <xsl:value-of select="//dc:identifier.url" />
+               </xsl:attribute>
+               <xsl:attribute name="title">
+                   <xsl:value-of select="wl:person_name(//dc:creator/text())" />, <xsl:value-of select="//dc:title" />
+               </xsl:attribute>
+               <xsl:value-of select="//dc:identifier.url" />
+           </a></p>
+           <xsl:if test="//dc:source" >
+             <p class="info">Tekst opracowany na podstawie: <xsl:value-of select="//dc:source" /></p>
+           </xsl:if>
+           <xsl:if test="//dc:description" >
+             <p class="info"><xsl:value-of select="//dc:description" /></p>
+           </xsl:if>
  
            <xsl:call-template name="editors" />
  
            <xsl:if test="@data-cover-by">
-             <p class="info">Cover image: 
+             <p class="info">Okładka na podstawie: 
              <xsl:choose>
              <xsl:when test="@data-cover-source">
                  <a>
              </xsl:choose>
              </p>
            </xsl:if>
++          <div class="info">
++          <img src="jedenprocent.png" alt="Logo 1%" />
++          <div>Przekaż 1% podatku na rozwój Wolnych Lektur.</div>
++          <div>Nazwa organizacji: Fundacja Nowoczesna Polska</div>
++          <div>KRS 0000070056</div>
++          </div>
++
+           <p class="info">&#160;</p>
+           <p class="minor info">
+               Plik wygenerowany dnia <span id="file_date"><xsl:value-of select="substring(date:date(), 1, 10)" /></span>.
+           </p>
          </div>
        </body>
      </html>
    </xsl:template>
  
    <xsl:template name="editors">
-     <xsl:if test="//dc:contributor.editor[text()]|//dc:contributor.technical_editor[text()]">
+     <xsl:if test="@editors">
          <p class="info">
-             <xsl:text>Technical editors: </xsl:text>
-             <xsl:for-each select="//dc:contributor.editor[text()]|//dc:contributor.technical_editor[text() and not(//dc:contributor.editor/text()=text())]">
-                 <xsl:sort />
-                 <xsl:if test="position() != 1">, </xsl:if>
-                 <xsl:apply-templates mode="person" />
-             </xsl:for-each>.
-         </p>
+             <xsl:text>Opracowanie redakcyjne i przypisy: </xsl:text>
+             <xsl:value-of select="@editors" />.</p>
      </xsl:if>
    </xsl:template>
  
 +  <xsl:template match="dc:contributor.editor|dc:contributor.technical_editor">
 +      <br /><xsl:apply-templates mode='person' />
 +  </xsl:template>
 +
    <xsl:template match="text()" mode="person">
      <xsl:value-of select="wl:person_name(.)" />
    </xsl:template>
diff --combined librarian/mobi.py
index 6de72b3,d98b838..99b724e
mode 100755,100644..100644
@@@ -9,7 -9,7 +9,7 @@@ import subproces
  from tempfile import NamedTemporaryFile
  
  from librarian import OutputFile
- from librarian.cover import ImageCover as WLCover
+ from librarian.cover import WLCover
  from librarian import get_resource
  
  
@@@ -19,7 -19,7 +19,7 @@@ def transform(wldoc, verbose=False
  
      wldoc: a WLDocument
      sample=n: generate sample e-book (with at least n paragraphs)
-     cover: a cover.Cover object
+     cover: a cover.Cover factory overriding default
      flags: less-advertising,
      """
  
      # provide a cover by default
      if not cover:
          cover = WLCover
 -    bound_cover = cover(book_info)
 -    bound_cover.save(cover_file)
+     cover_file = NamedTemporaryFile(suffix='.png', delete=False)
-     import Image
-     c.im = Image.open('cover.jpg')
-     c.ext = lambda: 'jpg'
-     cover_file = NamedTemporaryFile(suffix='.' + c.ext(), delete=False)
 +    c = cover(book_info)
 +    c.save(cover_file)
  
-     if cover.uses_dc_cover:
-         if document.book_info.cover_by:
+     if bound_cover.uses_dc_cover:
 -        if document.book_info.cover_by:
++        if document.remobook_info.cover_by:
              document.edoc.getroot().set('data-cover-by', document.book_info.cover_by)
          if document.book_info.cover_source:
              document.edoc.getroot().set('data-cover-source', document.book_info.cover_source)
diff --combined librarian/pdf/wl.cls
@@@ -14,9 -14,6 +14,9 @@@
  
  \RequirePackage{setspace}
  \RequirePackage{type1cm}
 +\RequirePackage{amssymb}
 +\RequirePackage{amsmath}
 +
  \DeclareOption{13pt}{%
  \AtEndOfClass{%
  % font size definitions, similar to ones in /usr/share/texmf-texlive/tex/latex/base/
  
  \DeclareOption*{\PassOptionsToClass{\CurrentOption}{book}}
  \ProcessOptions\relax
 -\LoadClass[a4paper,oneside]{book}
 +\LoadClass[a4paper]{book}
  
  
  \usepackage{trace}
 -
 +\usepackage{caption}
 +\usepackage{tabularx}
  \usepackage[MeX]{polski}
 -
 +\usepackage{icomma}
  \usepackage[xetex]{graphicx}
  \usepackage{fontspec}
  \usepackage{xunicode}
  \usepackage{xltxtra}
  
  \usepackage[overload]{textcase}
  \usepackage{scalefnt}
  \usepackage[colorlinks=true,linkcolor=black,setpagesize=false,urlcolor=black,xetex]{hyperref}
@@@ -143,8 -138,7 +142,8 @@@ Letters={SmallCaps,UppercaseSmallCaps
  
  \setlength{\marginparsep}{2em}
  \setlength{\marginparwidth}{8.5em}
 -\setlength{\oddsidemargin}{0pt}
 +\setlength{\oddsidemargin}{36mm}
 +\setlength{\evensidemargin}{0pt}
  \setlength{\voffset}{0pt}
  \setlength{\topmargin}{0pt}
  \setlength{\headheight}{0pt}
  \fancyhf{}
  \renewcommand{\headrulewidth}{0pt}
  \renewcommand{\footrulewidth}{0pt}
 -\lfoot{{\footnotesize \textsc{\@author} \emph{\@title}}}
 +
 +%\lfoot{{\footnotesize \textsc{\@author} \emph{\@title}}}
  \cfoot{}
 -\rfoot{{\footnotesize \thepage}}
 +%\rfoot{{\footnotesize \thepage}}
 +\fancyfoot[LO,RE]{{\footnotesize \textsc{\@author} \emph{\@title}}}
 +\fancyfoot[LE,RO]{{\footnotesize \thepage}}
  
  \clubpenalty=100000
  \widowpenalty=100000
  \raisebox{0pt}[0pt][0pt]{\makebox[0pt][r]{\usebox{\xglyphbox}}}}
  
  \newcommand{\makecover}[2]{
-         %\pdfpagewidth=#1
-         %\pdfpageheight=#2
+         \pdfpagewidth=#1
+         \pdfpageheight=#2
  
          \thispagestyle{empty}
          \newlength{\PictHOffset}
          \addtolength{\PictVOffset}{\headheight}
          \addtolength{\PictVOffset}{\headsep}
          \addtolength{\PictVOffset}{\topskip}
-         \addtolength{\PictVOffset}{-#2}
+         \addtolength{\PictVOffset}{-\pdfpageheight}
  
          \noindent\hspace*{-\PictHOffset}%
          \raisebox{\PictVOffset}[0pt][0pt]{\makebox[0pt][l]{%
-             \includegraphics[height=#2,width=#1]{cover.jpg}}}
-         %\clearpage
-         \vspace{#2}
+             \includegraphics[height=\pdfpageheight,width=\pdfpagewidth]{cover.png}}}
+         \clearpage
  
-         \hspace{-36mm}\parbox{16cm}{
 -        \setlength{\pdfpagewidth}{210mm}
 -        \setlength{\pdfpageheight}{297mm}
++ 
++%% Strona tytułowa %% XXX
++       \hspace{-36mm}\parbox{16cm}{
 +        {\addfontfeature{LetterSpace=-4.0}{\scalefont{4}%
 +            \noindent Philippe Aigrain}}
 +
 +       {\addfontfeature{LetterSpace=-4.0}{\scalefont{2.5}%
 +            przy współpracy Suzanne Aigrain
 +        }}
 +
 +        \vspace{2em}
 +        {\addfontfeature{LetterSpace=-4.0}{\scalefont{6}%
 +            Dzielenie się
 +        }}
 +        
 +        \vspace{2em}
 +        {\addfontfeature{LetterSpace=-4.0}{\scalefont{3}%
 +            Kultura i gospodarka epoki internetu
 +        }}
-         
- %\emph{\thankyou}\\
- %\indent\emph{You made this book possible.}
 +        }
 +
-         %\setlength{\pdfpagewidth}{210mm}
-         %\setlength{\pdfpageheight}{297mm}
++       \setlength{\pdfpagewidth}{210mm}
++       \setlength{\pdfpageheight}{297mm}
  }
  
  
  
      \vspace{.6em}
      \color{black}
-     
      }
  }
  
 +\usepackage{printlen}
 +
  \newcommand{\editorialsection}{
 -  \begin{figure}[b!]
 -  {
 -    \footnotesize
 -    \color{theme}
 -    \noindent \rule{\linewidth}{0.4pt}
++%% XXX % sprawdzic czy czegos nie zgubilem z master
++%% szczegolnie jesli chodzi o makra wstawiajace dane z DC, jak np \editors
 +\clearpage
 +        \thispagestyle{empty}
  
 -    \rightsinfo
 -    \vspace{.6em}
 +% Pusta strona 
 +\clearpage
 +        \thispagestyle{empty}
  
 -    Źródło: \href{\bookurl}{\bookurl}
 +\vspace{2em}
 +      \hspace{0mm}\parbox{16cm}{
 +\centering
 +      {\addfontfeature{LetterSpace=-4.0}{\scalefont{6}%
 +           Dzielenie się
 +      }}
 +
 +  \vspace{2em}
 +         {\addfontfeature{LetterSpace=-4.0}{\scalefont{3}%
 +             Kultura i gospodarka epoki internetu
 +         }}
 +}
  
 -    \vspace{.6em}
 -    \sourceinfo
 +\clearpage
 +        \thispagestyle{empty}
  
 -    \description
 -    \vspace{.6em}
 +\clearpage
 +        \thispagestyle{empty}
  
 -    \editors
 +%\parbox{10cm}{
 +%  \centering
 +
 +  \hspace{-36mm}\parbox{16cm}{
 +\centering
 +
 +  {\addfontfeature{LetterSpace=-4.0}{\scalefont{4}%
 +      \noindent Philippe Aigrain
 +  }}
 +
 +  {\addfontfeature{LetterSpace=-4.0}{\scalefont{2.5}%
 +      przy współpracy Suzanne Aigrain
 +  }}
 +  
 +  \vspace{2em}
 +         {\addfontfeature{LetterSpace=-4.0}{\scalefont{6}%
 +             Dzielenie się
 +         }}
 +         
 +  \vspace{2em}
 +         {\addfontfeature{LetterSpace=-4.0}{\scalefont{4}%
 +             Kultura i gospodarka epoki internetu
 +         }}
 +
 +  \vspace{2em}
 +         {\addfontfeature{LetterSpace=-4.0}{\scalefont{2}%
 +             Z języka angielskiego przełożył \\
 +             \emph{Wojciech Pędzich}
 +         }}
 +
 +\vspace{22em}
 +
 +\includegraphics[scale=.2]{logo.eps}
 +}
  
 -    \ifdefined\coverby
 -        \vspace{.6em}
 -        \coverby
 -    \fi
++    Przekaż darowiznę na konto:
++    \href{http://nowoczesnapolska.org.pl/pomoz-nam/wesprzyj-nas/}{szczegóły na stronie Fundacji}.
  
 -    \vspace{.6em}
 -    \emph{Wesprzyj Wolne Lektury!}
 +\clearpage
 +        \thispagestyle{empty}
  
 -    Wolne Lektury to projekt fundacji Nowoczesna Polska – organizacji
 -    pożytku publicznego działającej na rzecz wolności korzystania
 -    z dóbr kultury.
 +\noindent Tytuł oryginału
  
 -    Co roku do domeny publicznej przechodzi twórczość kolejnych autorów.
 -    Dzięki Twojemu wsparciu będziemy je mogli udostępnić wszystkim bezpłatnie.
 +\noindent \emph{Sharing. Culture and the Economy in the Internet Age}
  
 -    \vspace{.6em}
 -    \emph{Jak możesz pomóc?}
 +\vspace{1em}
  
 -    Przekaż 1\% podatku na rozwój Wolnych Lektur:
 -    Fundacja Nowoczesna Polska, KRS 0000070056.
 +\noindent \editors
  
 -    Pomóż uwolnić konkretną książkę, wspierając
 -    \href{http://www.wolnelektury.pl/wesprzyj/}{zbiórkę na stronie wolnelektury.pl}.
 +\vspace{1em}
  
 -    Przekaż darowiznę na konto:
 -    \href{http://nowoczesnapolska.org.pl/pomoz-nam/wesprzyj-nas/}{szczegóły na stronie Fundacji}.
  
 -    \color{black}
 -  }
 -  \end{figure}
 +\noindent \rightsinfo
 +
 +\vspace{1em}
 +
 +\noindent \coverby
 +
 +
 +%\set\textwidth=450pt
 +%\printlength\textwidth
 +
 +
 +%% {\scalefont{1.5}Drogi czytelniku!}
 +
 +
 +
 +%% \vspace{1em}
 +
 +\vspace{1em}
 +
 +\noindent Tłumaczenie książki powstało w ramach projektu "Przyszłość prawa autorskiego" finansowanego przez {\it Trust for Civil Society in Central and Eastern Europe}.
 +
 +\vspace{1em}
 +
 +\noindent \includegraphics[scale=.4]{cce_trust.eps}
 +
 +\vspace{1em}
 +
 +\noindent Wydawca: Fundacja Nowoczesna Polska, Warszawa 2012
 +
 +\vspace{1em}
 +\includegraphics[scale=.2]{logo.eps}
 +\vspace{1em}
 +
 +\noindent \href{http://nowoczesnapolska.org.pl/}{http://nowoczesnapolska.org.pl/}
 +
 +
 +
 +%\vspace{4em}
 +%\box{\tableofcontents}
 +
 +%%   \begin{figure}[b!]
 +%%   {
 +%%     \footnotesize
 +%%     \color{theme}
 +%%     \noindent \rule{\linewidth}{0.4pt}
 +
 +%%     \rightsinfo
 +%% %    \vspace{.6em}
 +
 +%%     %Źródło: \href{\bookurl}{\bookurl}
 +
 +%%     %\vspace{.6em}
 +%%     %\sourceinfo
 +
 +%%     %\description
 +%%     %\vspace{.6em}
 +
 +%%     Opublikowano przez \href{http://nowoczesnapolska.org.pl}{Fundację Nowoczesna Polska}, 2012.
 +
 +%%     \editors
 +
 +%%     %\vspace{.6em}
 +%%     \coverby
 +    
 +%%     \color{black}
 +%%   }
 +%%   \end{figure}
 +\clearpage
  }
  
  
@@@ -435,13 -300,10 +430,10 @@@ Letters={Uppercase
  %{\addfontfeature{Scale=2.0, FakeStretch=0.98, LetterSpace=-2.0}\emph{#1}}
  }
  
  \newcommand{\tytul}[1]{%
  #1%
- %\vspace{1em}%
- }
- \newcommand{\autorpodutworu}[1]{%
- \section*{\typosection{#1}}%
+ \vspace{1em}%
  }
  
  \newcommand{\nazwapodutworu}[1]{%
  }
  
  \newcommand{\autorutworu}[1]{%
- \addcontentsline{toc}{part}{???}
  \subsection*{\typosubsection{#1}}%
  }
  
  \subsection*{\typosubsubsection{#1}}%
  }
  
 +\newcommand{\podtytulpodutworu}[1]{%
 +\subsection*{\typosubsubsection{#1}}%
 +}
 +
  \newcommand{\translator}[1]{%
  \subsection*{\typosubsubsection{tłum. #1}}%
  }
  
  \newcommand{\powiesc}[1]{#1}
  \newcommand{\opowiadanie}[1]{#1}
  \newcommand{\lirykal}[1]{#1}
  \newcommand{\dramatwspolczesny}[1]{#1}
  
  \newcommand{\nota}[1]{%
- \begin{quotation}%
- #1%
- \end{quotation}%
+ \par{#1}%
  }
  
  \newcommand{\dedykacja}[1]{%
  \subsection*{\typosubsection{#1}}%
  }
  \newcommand{\naglowekczesc}[1]{%
%\pagebreak
+ \pagebreak
  \subsection*{\typosubsection{#1}}%
  }
- \newcommand{\naglowekrozdzial}[1]{%
+ \newcommand{\srodtytul}[1]{%
  \subsection*{\typosubsection{#1}}%
  }
  
  \newcommand{\naglowekscena}[1]{%
  \subsubsection*{\typosubsubsection{#1}}%
  }
- \newcommand{\naglowekpodrozdzial}[1]{%
+ \newcommand{\naglowekrozdzial}[1]{%
  \subsubsection*{\typosubsubsection{#1}}%
  }
  
  \newcommand{\naglowekosoba}[1]{%
  \par{\textsc{#1}}\nopagebreak%
  }
- \newcommand{\srodtytul}[1]{%
- \vskip 1em \par{\large \it \noindent #1}\vskip .5em\nopagebreak%
+ \newcommand{\naglowekpodrozdzial}[1]{%
+ \par{#1}\nopagebreak%
  }
  
  \newcommand{\miejsceczas}[1]{%
  \begin{center}%
  \par{*}%
  \end{center}%
- \noindent%
  }
  
  \newcommand{\separatorlinia}{%
  \fi
  }
  
- \newcommand{\ilustr}[2]{
- \vspace{1em}%
- \begin{center}%
- \par{\includegraphics[width=\textwidth]{#1}\\#2}%
- \end{center}%
- \vspace{1em}%
- }
          <xsl:apply-templates select="powiesc|opowiadanie|liryka_l|liryka_lp|dramat_wierszowany_l|dramat_wierszowany_lp|dramat_wspolczesny" mode='titlepage' />
  
          <env name="document">
-             <TeXML escape="0">
-                 \def\thankyou{%
-                 <xsl:choose>
-                 <xsl:when test="//dc:contributor">Thank you for your contribution, <xsl:value-of select="//dc:contributor"/>!</xsl:when>
-                 <xsl:otherwise>Thank you for all your contributions!</xsl:otherwise>
-                 </xsl:choose>
-                 }
-             </TeXML>
              <xsl:if test="@data-cover-width">
                  <cmd name="makecover">
+                     <parm><xsl:value-of select="210 * @data-cover-width div @data-cover-height" />mm</parm>
                      <parm>210mm</parm>
-                     <parm><xsl:value-of select="210 * @data-cover-height div @data-cover-width" />mm</parm>
                  </cmd>
              </xsl:if>
-             <!--cmd name="maketitle" /-->
+             <cmd name="maketitle" />
  
-             <!--cmd name="tytul"><parm>
+             <cmd name="tytul"><parm>
                <xsl:choose>
                  <xsl:when test="(powiesc|opowiadanie|liryka_l|liryka_lp|dramat_wierszowany_l|dramat_wierszowany_lp|dramat_wspolczesny)/nazwa_utworu">
-                     <!- title in master ->
+                     <!-- title in master -->
                      <xsl:apply-templates select="(powiesc|opowiadanie|liryka_l|liryka_lp|dramat_wierszowany_l|dramat_wierszowany_lp|dramat_wspolczesny)/autor_utworu" mode="title" />
                      <xsl:apply-templates select="(powiesc|opowiadanie|liryka_l|liryka_lp|dramat_wierszowany_l|dramat_wierszowany_lp|dramat_wspolczesny)/dzielo_nadrzedne" mode="title" />
                      <xsl:apply-templates select="(powiesc|opowiadanie|liryka_l|liryka_lp|dramat_wierszowany_l|dramat_wierszowany_lp|dramat_wspolczesny)/nazwa_utworu" mode="title" />
                      <xsl:apply-templates select="(powiesc|opowiadanie|liryka_l|liryka_lp|dramat_wierszowany_l|dramat_wierszowany_lp|dramat_wspolczesny)/podtytul" mode="title" />
-                     <!- dc in master or not ->
+                     <!-- dc in master or not -->
                      <cmd name="translatorsline" />
                  </xsl:when>
                  <xsl:otherwise>
-                     <!- look for author title in dc ->
+                     <!-- look for author title in dc -->
                      <xsl:apply-templates select="rdf:RDF" mode="firstdctitle" />
                      <xsl:apply-templates select="powiesc|opowiadanie|liryka_l|liryka_lp|dramat_wierszowany_l|dramat_wierszowany_lp|dramat_wspolczesny" mode='firstdctitle' />
                  </xsl:otherwise>
                </xsl:choose>
-             </parm></cmd-->
+             </parm></cmd>
+             <xsl:apply-templates select="powiesc|opowiadanie|liryka_l|liryka_lp|dramat_wierszowany_l|dramat_wierszowany_lp|dramat_wspolczesny" />
+             <xsl:apply-templates select="utwor" mode="part" />
  
              <TeXML escape="0">
-                 \def\coverby{
-                 <xsl:if test="@data-cover-by">Obraz na okładce:
+                 <xsl:if test="@data-cover-by">
+                 \def\coverby{Okładka na podstawie:
                      <xsl:choose>
                      <xsl:when test="@data-cover-source">
-                         \href{\datacoversource}{\datacoverby}.
+                         \href{\datacoversource}{\datacoverby}
                      </xsl:when>
                      <xsl:otherwise>
-                         \datacoverby{}.
+                         \datacoverby{}
                      </xsl:otherwise>
                      </xsl:choose>
-                 </xsl:if>
                  }
+                 </xsl:if>
+                 \def\editors{<xsl:call-template name="editors" />}
              </TeXML>
  
              <cmd name="editorialsection" />
  
-             <xsl:apply-templates select="powiesc|opowiadanie|liryka_l|liryka_lp|dramat_wierszowany_l|dramat_wierszowany_lp|dramat_wspolczesny" />
-             <xsl:apply-templates select="utwor" mode="part" />
          </env>
      </TeXML>
  </xsl:template>
  
  <xsl:template match="utwor" mode="part">
-     <cmd name="newpage" />
      <cmd name="tytul"><parm>
-     <!-- Dirty! -->
-     <xsl:apply-templates select="(powiesc|opowiadanie|liryka_l|liryka_lp|dramat_wierszowany_l|dramat_wierszowany_lp|dramat_wspolczesny)/motyw" mode="inline"/>
        <xsl:choose>
          <xsl:when test="(powiesc|opowiadanie|liryka_l|liryka_lp|dramat_wierszowany_l|dramat_wierszowany_lp|dramat_wspolczesny)/nazwa_utworu">
              <!-- title in master -->
-             <xsl:apply-templates select="(powiesc|opowiadanie|liryka_l|liryka_lp|dramat_wierszowany_l|dramat_wierszowany_lp|dramat_wspolczesny)/dzielo_nadrzedne" mode="title" />
-             <xsl:apply-templates select="(powiesc|opowiadanie|liryka_l|liryka_lp|dramat_wierszowany_l|dramat_wierszowany_lp|dramat_wspolczesny)/autor_utworu" mode="title" />
              <xsl:apply-templates select="(powiesc|opowiadanie|liryka_l|liryka_lp|dramat_wierszowany_l|dramat_wierszowany_lp|dramat_wspolczesny)/nazwa_utworu" mode="title" />
              <xsl:apply-templates select="(powiesc|opowiadanie|liryka_l|liryka_lp|dramat_wierszowany_l|dramat_wierszowany_lp|dramat_wspolczesny)/podtytul" mode="title" />
          </xsl:when>
              \href{http://creativecommons.org/licenses/by-sa/3.0/}{Creative Commons
              Uznanie Autorstwa – Na Tych Samych Warunkach 3.0 PL}.}
          <xsl:if test=".//dc:rights.license">
-             \def\rightsinfo{Ta książka jest udostpęniona na licencji
+             \def\rightsinfo{Ten utwór jest udostepniony na licencji
              \href{<xsl:value-of select=".//dc:rights.license" />}{<xsl:value-of select=".//dc:rights" />}.}
          </xsl:if>
  
                  \vspace{.6em}
              </xsl:if>}
          \def\description{<xsl:apply-templates select=".//dc:description" mode="inline" />}
 +        \def\editors{<xsl:call-template name="editors" />}
      </TeXML>
  </xsl:template>
  
      </cmd>
  </xsl:template>
  
- <xsl:template match="ilustr">
-     <cmd>
-         <xsl:attribute name="name">
-             <xsl:value-of select="wl:texcommand(name())" />
-         </xsl:attribute>
-               <parm><xsl:value-of select="@src" /></parm>
-         <parm><xsl:apply-templates mode="inline" /></parm>
-     </cmd>
- </xsl:template>
- <xsl:template match="@*|node()" mode="identity">
-   <xsl:copy>
-     <xsl:apply-templates select="@*|node()" mode="identity"/>
-   </xsl:copy>
- </xsl:template>
- <xsl:template match="dmath">
-   <dmath>
-     <xsl:apply-templates mode="identity"/>
-   </dmath>
- </xsl:template>
- <xsl:template match="math" mode="inline">
-   <math>
-     <xsl:apply-templates mode="identity"/>
-   </math>
- </xsl:template>
- <xsl:template match="tablewrap">
-   <cmd name="begin"><parm>table</parm><opt>h!</opt></cmd>
-   <xsl:apply-templates select="table"/>
-   <cmd name="caption*"><parm>
-     <xsl:apply-templates select="akap"/>
-   </parm></cmd>
-   <cmd name="end"><parm>table</parm></cmd>
- </xsl:template>
- <xsl:template match="table">
-   <xsl:if test="@caption">
-       <cmd name="caption*"><parm>
-       <cmd name="Large"/><xsl:value-of select="@caption"/>
-       </parm></cmd>
-     </xsl:if>
-     <env name="tabularx">
-       <parm><cmd name="textwidth"/></parm>
-         <parm><xsl:value-of select="@spec"/></parm>
-         <xsl:apply-templates />
-     </env>
- </xsl:template>
- <xsl:template match="r">
-     <xsl:apply-templates />
-     <spec cat="esc"/><spec cat="esc"/>
- </xsl:template>
- <xsl:template match="c">
-     <cmd name="footnotesize"/>
-     <xsl:apply-templates mode="inline"/>
-     <xsl:if test="position() &lt; last()-1">
-     <spec cat="align"/>
-     </xsl:if>
- </xsl:template>
- <xsl:template match="hr">
-   <cmd name="hline"/>
- </xsl:template>
  
  <!-- ================ -->
  <!-- = SPECIAL TAGS = -->
  </xsl:template>
  
  <xsl:template name="editors">
-     <xsl:if test=".//dc:contributor.editor_parsed|.//dc:contributor.technical_editor_parsed">
-         <xsl:text>Redakcja techniczna: </xsl:text>
-         <xsl:for-each select=".//dc:contributor.editor_parsed|.//dc:contributor.technical_editor_parsed[not(.//dc:contributor.editor_parsed/text()=text())]">
-             <!--xsl:sort select="@sortkey" /-->
-             <xsl:if test="position() != 1">, </xsl:if>
-             <xsl:apply-templates mode="inline" />
-         </xsl:for-each>.
+     <xsl:if test="@editors">
+         <xsl:text>Opracowanie redakcyjne i przypisy: </xsl:text>
+         <xsl:value-of select="@editors" />
+         <xsl:text>.</xsl:text>
      </xsl:if>
  </xsl:template>
  
diff --combined scripts/book2pdf
@@@ -4,61 -4,21 +4,23 @@@
  # This file is part of Librarian, licensed under GNU Affero GPLv3 or later.
  # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
  #
+ from librarian.book2anything import Book2Anything, Option
 +import os.path
 +from optparse import OptionParser
  
- from librarian import DirDocProvider, ParseError
- from librarian.parser import WLDocument
  
+ class Book2Pdf(Book2Anything):
+     format_name = "PDF"
+     ext = "pdf"
+     uses_cover = True
+     uses_provider = True
+     transform_args = [
+         Option('-t', '--save-tex', dest='save_tex', metavar='FILE',
+                 help='path to save the intermediary LaTeX file to'),
+         Option('-m', '--morefloats', dest='morefloats', metavar='old/new/none',
+                 help='force morefloats in old (<1.0c), new (>=1.0c) or none')
+     ]
  
- if __name__ == '__main__':
-     usage = """Usage: %prog [options] SOURCE [SOURCE...]
-     Convert SOURCE files to PDF format."""
-     parser = OptionParser(usage)
-     parser.add_option('-v', '--verbose', action='store_true', dest='verbose', default=False,
-                       help='make lots of noise and revert to default interaction in LaTeX')
-     parser.add_option('-c', '--with-cover', action='store_true', dest='with_cover', default=False,
-                       help='create default cover')
-     parser.add_option('-d', '--make-dir', action='store_true', dest='make_dir', default=False,
-                       help='create a directory for author and put the PDF in it')
-     parser.add_option('-t', '--save-tex', dest='save_tex', metavar='FILE',
-                       help='path to save the intermediary LaTeX file to')
-     parser.add_option('-o', '--output-file', dest='output_file', metavar='FILE',
-                       help='specifies the output file')
-     parser.add_option('-O', '--output-dir', dest='output_dir', metavar='DIR',
-                       help='specifies the directory for output')
-     parser.add_option('-m', '--morefloats', dest='morefloats', metavar='old/new/none',
-                       help='force morefloats in old (<1.0c), new (>=1.0c) or none')
-     (options, args) = parser.parse_args()
-     if len(args) < 1:
-         parser.print_help()
-         exit(1)
-     if options.output_dir and options.output_file:
-         raise ValueError("Either --output-dir or --output file should be specified")
  
-     try:
-         for main_input in args:
-             path, fname = os.path.realpath(main_input).rsplit('/', 1)
-             provider = DirDocProvider(path)
-             output_file, output_dir = options.output_file, options.output_dir
-             if not (options.output_file or options.output_dir):
-                 output_file = os.path.splitext(main_input)[0] + '.pdf'
-             else:
-                 output_file = None
-             doc = WLDocument.from_file(main_input, provider=provider)
-             pdf = doc.as_pdf(save_tex=options.save_tex,
-                         cover=options.with_cover,
-                         morefloats=options.morefloats, verbose=options.verbose)
-             doc.save_output_file(pdf,
-                 output_file, options.output_dir, options.make_dir, 'pdf')
-     except ParseError, e:
-         print '%(file)s:%(name)s:%(message)s; use -v to see more output' % {
-             'file': main_input,
-             'name': e.__class__.__name__,
-             'message': e
-         }
+ if __name__ == '__main__':
+     Book2Pdf.run()