import os
import re
import shutil
+import urllib
+
class UnicodeException(Exception):
def __str__(self):
""" Dirty workaround for Python Unicode handling problems. """
- return self.message
+ return unicode(self).encode('utf-8')
def __unicode__(self):
""" Dirty workaround for Python Unicode handling problems. """
- return self.message
+ args = self.args[0] if len(self.args) == 1 else self.args
+ try:
+ message = unicode(args)
+ except UnicodeDecodeError:
+ message = unicode(args, encoding='utf-8', errors='ignore')
+ return message
class ParseError(UnicodeException):
pass
if not os.path.isdir(dirname):
os.makedirs(dirname)
shutil.copy(self.get_filename(), path)
+
+
+class URLOpener(urllib.FancyURLopener):
+ version = 'FNP Librarian (http://github.com/fnp/librarian)'
+urllib._urlopener = URLOpener()
--- /dev/null
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# This file is part of Librarian, licensed under GNU Affero GPLv3 or later.
+# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
+#
+from collections import namedtuple
+import os.path
+import optparse
+
+from librarian import DirDocProvider, ParseError
+from librarian.parser import WLDocument
+from librarian.cover import WLCover
+
+
+class Option(object):
+ """Option for optparse. Use it like `optparse.OptionParser.add_option`."""
+ def __init__(self, *names, **options):
+ self.names = names
+ self.options = options
+
+ def add(self, parser):
+ parser.add_option(*self.names, **self.options)
+
+ def name(self):
+ return self.options['dest']
+
+ def value(self, options):
+ return getattr(options, self.name())
+
+
+class Book2Anything(object):
+ """A class for creating book2... scripts.
+
+ Subclass it for any format you want to convert to.
+ """
+ format_name = None # Set format name, like "PDF".
+ ext = None # Set file extension, like "pdf".
+ uses_cover = False # Can it add a cover?
+ cover_optional = True # Only relevant if uses_cover
+ uses_provider = False # Does it need a DocProvider?
+ transform = None # Transform method. Uses WLDocument.as_{ext} by default.
+ parser_options = [] # List of Option objects for additional parser args.
+ transform_options = [] # List of Option objects for additional transform args.
+ transform_flags = [] # List of Option objects for supported transform flags.
+
+
+ @classmethod
+ def run(cls):
+ # Parse commandline arguments
+ usage = """Usage: %%prog [options] SOURCE [SOURCE...]
+ Convert SOURCE files to %s format.""" % cls.format_name
+
+ parser = optparse.OptionParser(usage=usage)
+
+ parser.add_option('-v', '--verbose',
+ action='store_true', dest='verbose', default=False,
+ help='print status messages to stdout')
+ parser.add_option('-d', '--make-dir',
+ action='store_true', dest='make_dir', default=False,
+ help='create a directory for author and put the output file in it')
+ 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')
+ if cls.uses_cover:
+ if cls.cover_optional:
+ parser.add_option('-c', '--with-cover',
+ action='store_true', dest='with_cover', default=False,
+ help='create default cover')
+ parser.add_option('-C', '--image-cache',
+ dest='image_cache', metavar='URL',
+ help='prefix for image download cache' +
+ (' (implies --with-cover)' if cls.cover_optional else ''))
+ for option in cls.parser_options + cls.transform_options + cls.transform_flags:
+ option.add(parser)
+
+ options, input_filenames = parser.parse_args()
+
+ if len(input_filenames) < 1:
+ parser.print_help()
+ return(1)
+
+ # Prepare additional args for parser.
+ parser_args = {}
+ for option in cls.parser_options:
+ parser_args[option.name()] = option.value(options)
+ # Prepare additional args for transform method.
+ transform_args = {}
+ for option in cls.transform_options:
+ transform_args[option.name()] = option.value(options)
+ # Add flags to transform_args, if any.
+ transform_flags = [flag.name() for flag in cls.transform_flags
+ if flag.value(options)]
+ if transform_flags:
+ transform_args['flags'] = transform_flags
+ # Add cover support, if any.
+ if cls.uses_cover:
+ if options.image_cache:
+ def cover_class(*args, **kwargs):
+ return WLCover(image_cache=options.image_cache, *args, **kwargs)
+ transform_args['cover'] = cover_class
+ elif not cls.cover_optional or options.with_cover:
+ transform_args['cover'] = WLCover
+
+
+ # Do some real work
+ try:
+ for main_input in input_filenames:
+ if options.verbose:
+ print main_input
+
+ # Where to find input?
+ if cls.uses_provider:
+ path, fname = os.path.realpath(main_input).rsplit('/', 1)
+ provider = DirDocProvider(path)
+ else:
+ provider = None
+
+ # Where to write output?
+ if not (options.output_file or options.output_dir):
+ output_file = os.path.splitext(main_input)[0] + '.' + cls.ext
+ else:
+ output_file = None
+
+ # Do the transformation.
+ doc = WLDocument.from_file(main_input, provider=provider, **parser_args)
+ transform = cls.transform
+ if transform is None:
+ transform = getattr(WLDocument, 'as_%s' % cls.ext)
+ output = transform(doc, **transform_args)
+
+ doc.save_output_file(output,
+ output_file, options.output_dir, options.make_dir, cls.ext)
+
+ except ParseError, e:
+ print '%(file)s:%(name)s:%(message)s' % {
+ 'file': main_input,
+ 'name': e.__class__.__name__,
+ 'message': e
+ }
# 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):
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
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):
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
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'
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
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:
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
import os
import os.path
+import re
import subprocess
from StringIO import StringIO
from copy import deepcopy
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
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'):
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):
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
""" 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
""" 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()
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))
--- /dev/null
+<!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>Wesprzyj Wolne Lektury</title>
+ <link rel="stylesheet" href="style.css" type="text/css" />
+ </head>
+ <body>
+ <div id="book-text" >
+
+ <h2 class="info">Wesprzyj Wolne Lektury!</h2>
+
+ <p class="info">
+ Wolne Lektury to projekt fundacji Nowoczesna Polska – organizacji
+ pożytku publicznego działającej na rzecz wolności korzystania
+ z dóbr kultury.</p>
+
+ <p class="info">
+ Co roku do domeny publicznej przechodzi twórczość kolejnych autorów.
+ Dzięki Twojemu wsparciu będziemy je mogli udostępnić wszystkim bezpłatnie.
+ </p>
+
+ <p class="info">
+ <strong>Jak możesz pomóc?</strong>
+ </p>
+
+ <p class="info">
+ <img src="jedenprocent.png" alt="Logo 1%" /><br/>
+ Przekaż 1% podatku na rozwój Wolnych Lektur:<br/>
+ Fundacja Nowoczesna Polska<br/>
+ KRS 0000070056
+ </p>
+
+ <p class="info">
+ Pomóż uwolnić konkretną książkę, wspierając
+ <a href="http://www.wolnelektury.pl/wesprzyj/">zbiórkę
+ na stronie wolnelektury.pl</a>.
+ </p>
+
+ <p class="info">
+ Przekaż darowiznę na konto:
+ <a href="http://nowoczesnapolska.org.pl/pomoz-nam/wesprzyj-nas/">szczegóły
+ na stronie Fundacji</a>.
+ </p>
+
+ </div>
+ </body>
+</html>
<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"> </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>
--- /dev/null
+# -*- coding: utf-8 -*-
+#
+# This file is part of Librarian, licensed under GNU Affero GPLv3 or later.
+# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
+#
+import os.path
+from copy import deepcopy
+from lxml import etree
+
+from librarian import functions, OutputFile
+from .epub import replace_by_verse
+
+
+functions.reg_substitute_entities()
+functions.reg_person_name()
+
+
+def sectionify(tree):
+ """Finds section headers and adds a tree of _section tags."""
+ sections = ['naglowek_czesc',
+ 'naglowek_akt', 'naglowek_rozdzial', 'naglowek_scena',
+ 'naglowek_podrozdzial']
+ section_level = dict((v,k) for (k,v) in enumerate(sections))
+
+ # We can assume there are just subelements an no text at section level.
+ for level, section_name in reversed(list(enumerate(sections))):
+ for header in tree.findall('//' + section_name):
+ section = header.makeelement("_section")
+ header.addprevious(section)
+ section.append(header)
+ sibling = section.getnext()
+ while (sibling is not None and
+ section_level.get(sibling.tag, 1000) > level):
+ section.append(sibling)
+ sibling = section.getnext()
+
+
+def transform(wldoc, verbose=False,
+ cover=None, flags=None):
+ """ produces a FB2 file
+
+ cover: a cover.Cover object or True for default
+ flags: less-advertising, working-copy
+ """
+
+ document = deepcopy(wldoc)
+ del wldoc
+
+ if flags:
+ for flag in flags:
+ document.edoc.getroot().set(flag, 'yes')
+
+ style_filename = os.path.join(os.path.dirname(__file__), 'fb2/fb2.xslt')
+ style = etree.parse(style_filename)
+
+ replace_by_verse(document.edoc)
+ sectionify(document.edoc)
+
+ result = document.transform(style)
+
+ return OutputFile.from_string(unicode(result).encode('utf-8'))
+
+# vim:et
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+ This file is part of Librarian, licensed under GNU Affero GPLv3 or later.
+ Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
+
+-->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns="http://www.gribuser.ru/xml/fictionbook/2.0">
+
+ <!-- description parsing -->
+ <xsl:template match="rdf:Description" mode="outer">
+ <description>
+ <!-- need to keep ordering here... -->
+
+ <title-info>
+ <!-- obligatory: genre, author, book-title, lang -->
+
+ <!-- XXX -->
+ <genre>literature</genre>
+ <xsl:apply-templates mode="description"
+ select="dc:creator"/>
+ <xsl:apply-templates mode="description"
+ select="dc:title"/>
+ <xsl:apply-templates mode="description"
+ select="dc:date.pd"/>
+ <xsl:apply-templates mode="description"
+ select="dc:language"/>
+ </title-info>
+ <document-info>
+ <!-- obligatory: author, date, id, version -->
+
+ <xsl:apply-templates mode="description"
+ select="dc:contributor.editor"/>
+ <xsl:apply-templates mode="description"
+ select="dc:contributor.technical_editor"/>
+ <program-used>book2fb2</program-used>
+ <!-- maybe today's date instead? -->
+ <xsl:apply-templates mode="description"
+ select="dc:date"/>
+ <xsl:apply-templates mode="description"
+ select="dc:identifier.url"/>
+ <!-- XXX -->
+ <version>0</version>
+ </document-info>
+ <publish-info>
+ <xsl:apply-templates mode="description"
+ select="dc:publisher"/>
+ </publish-info>
+ </description>
+ </xsl:template>
+
+ <xsl:template mode="description"
+ match="dc:creator|dc:contributor.editor|dc:contributor.technical_editor">
+ <!-- last name, first name -->
+ <xsl:variable name="last"
+ select="normalize-space(substring-before(., ','))"/>
+ <xsl:variable name="first"
+ select="normalize-space(substring-after(., ','))"/>
+
+ <author>
+ <first-name><xsl:value-of select="$first"/></first-name>
+ <last-name><xsl:value-of select="$last"/></last-name>
+ </author>
+ </xsl:template>
+ <xsl:template mode="description" match="dc:title">
+ <book-title><xsl:value-of select="."/></book-title>
+ </xsl:template>
+ <xsl:template mode="description" match="dc:language">
+ <lang><xsl:value-of select="."/></lang>
+ </xsl:template>
+ <xsl:template mode="description" match="dc:date.pd|dc:date">
+ <date><xsl:value-of select="."/></date>
+ </xsl:template>
+ <xsl:template mode="description" match="dc:publisher">
+ <publisher><xsl:value-of select="."/></publisher>
+ </xsl:template>
+ <xsl:template mode="description" match="dc:identifier.url">
+ <id><xsl:value-of select="."/></id>
+ </xsl:template>
+</xsl:stylesheet>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+ This file is part of Librarian, licensed under GNU Affero GPLv3 or later.
+ Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
+
+-->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:wl="http://wolnelektury.pl/functions"
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns="http://www.gribuser.ru/xml/fictionbook/2.0"
+ xmlns:l="http://www.w3.org/1999/xlink">
+
+ <xsl:template mode="para" match="lista_osob">
+ <empty-line/>
+ <xsl:apply-templates mode="para"/>
+ <empty-line/>
+ </xsl:template>
+
+ <xsl:template mode="para" match="kwestia">
+ <empty-line/>
+ <xsl:apply-templates mode="para"/>
+ <empty-line/>
+ </xsl:template>
+
+ <xsl:template mode="para" match="lista_osoba">
+ <p><xsl:apply-templates mode="inline"/></p>
+ </xsl:template>
+
+ <xsl:template mode="para" match="naglowek_listy|naglowek_osoba">
+ <p><strong><xsl:apply-templates mode="inline"/></strong></p>
+ </xsl:template>
+
+ <xsl:template mode="para" match="miejsce_czas|didaskalia|didask_tekst">
+ <p><emphasis><xsl:apply-templates mode="inline"/></emphasis></p>
+ </xsl:template>
+
+ <xsl:template mode="inline" match="didaskalia|didask_tekst">
+ <emphasis><xsl:apply-templates mode="inline"/></emphasis>
+ </xsl:template>
+
+</xsl:stylesheet>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+ This file is part of Librarian, licensed under GNU Affero GPLv3 or later.
+ Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
+
+-->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:wl="http://wolnelektury.pl/functions"
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns="http://www.gribuser.ru/xml/fictionbook/2.0"
+ xmlns:l="http://www.w3.org/1999/xlink">
+
+ <xsl:include href="description.xslt"/>
+ <xsl:include href="footnotes.xslt"/>
+ <xsl:include href="inline.xslt"/>
+ <xsl:include href="paragraphs.xslt"/>
+ <xsl:include href="poems.xslt"/>
+ <xsl:include href="sections.xslt"/>
+ <xsl:include href="drama.xslt"/>
+
+ <xsl:strip-space elements="*"/>
+ <xsl:output encoding="utf-8" method="xml" indent="yes"/>
+
+ <xsl:template match="utwor">
+ <FictionBook>
+ <xsl:apply-templates mode="outer"/>
+
+ <body name="footnotes">
+ <xsl:apply-templates mode="footnotes"/>
+ </body>
+ </FictionBook>
+ </xsl:template>
+
+ <!-- we can't handle lyrics nicely yet -->
+ <xsl:template match="powiesc|opowiadanie|liryka_l|liryka_lp|dramat_wierszowany_l|dramat_wierszowany_lp" mode="outer">
+ <body> <!-- main body for main book flow -->
+ <xsl:if test="autor_utworu or nazwa_utworu">
+ <title>
+ <xsl:apply-templates mode="title"
+ select="autor_utworu|dzielo_nadrzedne|nazwa_utworu|podtytul"/>
+ <xsl:call-template name="translators" />
+ </title>
+ </xsl:if>
+
+ <epigraph>
+ <p>
+ Utwór opracowany został w ramach projektu
+ <a l:href="http://www.wolnelektury.pl/">Wolne Lektury</a>
+ przez <a l:href="http://www.nowoczesnapolska.org.pl/">fundację
+ Nowoczesna Polska</a>.
+ </p>
+ </epigraph>
+
+ <xsl:call-template name="section" />
+ </body>
+ </xsl:template>
+
+ <xsl:template match="uwaga" mode="outer"/>
+ <xsl:template match="extra" mode="outer"/>
+
+ <xsl:template mode="title" match="*">
+ <!-- title -->
+
+ <p><xsl:apply-templates mode="inline"/></p>
+ </xsl:template>
+
+ <xsl:template name="translators">
+ <xsl:if test="//dc:contributor.translator">
+ <p>
+ <xsl:text>tłum. </xsl:text>
+ <xsl:for-each select="//dc:contributor.translator">
+ <xsl:if test="position() != 1">, </xsl:if>
+ <xsl:apply-templates mode="person" />
+ </xsl:for-each>
+ </p>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template match="text()" mode="person">
+ <xsl:value-of select="wl:person_name(.)" />
+ </xsl:template>
+
+
+ <xsl:template match="uwaga" mode="title"/>
+ <xsl:template match="extra" mode="title"/>
+</xsl:stylesheet>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+ This file is part of Librarian, licensed under GNU Affero GPLv3 or later.
+ Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
+
+-->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:wl="http://wolnelektury.pl/functions"
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns="http://www.gribuser.ru/xml/fictionbook/2.0"
+ xmlns:l="http://www.w3.org/1999/xlink">
+
+ <!-- footnote body mode -->
+ <xsl:template match="pa|pe|pr|pt" mode="footnotes">
+ <!-- we number them absolutely -->
+ <xsl:variable name="n" select="count(preceding::pa) + count(preceding::pe) + count(preceding::pr) + count(preceding::pt) + 1"/>
+
+ <xsl:element name="section">
+ <xsl:attribute name="id">fn<xsl:value-of select="$n"/></xsl:attribute>
+
+ <p><xsl:apply-templates mode="inline"/>
+ <xsl:if test="local-name() = 'pa'">
+ <xsl:text> [przypis autorski]</xsl:text>
+ </xsl:if></p>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template match="text()" mode="footnotes"/>
+
+ <!-- footnote links -->
+ <xsl:template match="pa|pe|pr|pt" mode="inline">
+ <xsl:variable name="n" select="count(preceding::pa) + count(preceding::pe) + count(preceding::pr) + count(preceding::pt) + 1"/>
+ <xsl:element name="a">
+ <xsl:attribute name="type">note</xsl:attribute>
+ <xsl:attribute name="l:href">#fn<xsl:value-of select="$n"/></xsl:attribute>
+
+ <xsl:text>[</xsl:text>
+ <xsl:value-of select="$n"/>
+ <xsl:text>]</xsl:text>
+ </xsl:element>
+ </xsl:template>
+</xsl:stylesheet>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+ This file is part of Librarian, licensed under GNU Affero GPLv3 or later.
+ Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
+
+-->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:wl="http://wolnelektury.pl/functions"
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns="http://www.gribuser.ru/xml/fictionbook/2.0"
+ xmlns:l="http://www.w3.org/1999/xlink">
+
+ <!-- inline elements -->
+
+ <!-- ignored -->
+ <xsl:template match="motyw" mode="inline"/>
+
+ <!-- formatting -->
+ <xsl:template match="slowo_obce" mode="inline">
+ <emphasis>
+ <xsl:apply-templates mode="inline"/>
+ </emphasis>
+ </xsl:template>
+ <xsl:template match="tytul_dziela" mode="inline">
+ <emphasis>
+ <xsl:if test="@typ">„</xsl:if>
+ <xsl:apply-templates mode="inline"/>
+ <xsl:if test="@typ">”</xsl:if>
+ </emphasis>
+ </xsl:template>
+ <xsl:template match="wyroznienie" mode="inline">
+ <strong>
+ <xsl:apply-templates mode="inline"/>
+ </strong>
+ </xsl:template>
+
+ <!-- text -->
+ <xsl:template match="text()" mode="inline">
+ <xsl:value-of select="wl:substitute_entities(.)"/>
+ </xsl:template>
+
+ <xsl:template match="uwaga" mode="inline"/>
+ <xsl:template match="extra" mode="inline"/>
+</xsl:stylesheet>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+ This file is part of Librarian, licensed under GNU Affero GPLv3 or later.
+ Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
+
+-->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:wl="http://wolnelektury.pl/functions"
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns="http://www.gribuser.ru/xml/fictionbook/2.0"
+ xmlns:l="http://www.w3.org/1999/xlink">
+
+ <!-- in paragraph mode -->
+
+ <xsl:template mode="para" match="akap|akap_dialog|akap_cd|motto_podpis">
+ <!-- paragraphs & similar -->
+
+ <p><xsl:apply-templates mode="inline"/></p>
+ </xsl:template>
+
+ <xsl:template mode="para" match="dlugi_cytat|motto|dedykacja|nota">
+ <cite><xsl:apply-templates mode="para"/></cite>
+ </xsl:template>
+
+ <xsl:template mode="para" match="srodtytul">
+ <p><strong><xsl:apply-templates mode="inline"/></strong></p>
+ </xsl:template>
+
+ <xsl:template mode="para" match="sekcja_swiatlo">
+ <empty-line/><empty-line/><empty-line/>
+ </xsl:template>
+
+ <xsl:template mode="para" match="sekcja_asterysk">
+ <empty-line/><p>*</p><empty-line/>
+ </xsl:template>
+
+ <xsl:template mode="para" match="separator_linia">
+ <empty-line/><p>————————</p><empty-line/>
+ </xsl:template>
+
+
+
+ <xsl:template mode="para" match="*"/>
+ <xsl:template mode="sections" match="*"/>
+</xsl:stylesheet>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+ This file is part of Librarian, licensed under GNU Affero GPLv3 or later.
+ Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
+
+-->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:wl="http://wolnelektury.pl/functions"
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns="http://www.gribuser.ru/xml/fictionbook/2.0"
+ xmlns:l="http://www.w3.org/1999/xlink">
+
+ <!-- poems -->
+
+ <!-- match poem citations -->
+ <xsl:template mode="para" match="poezja_cyt">
+ <cite>
+ <poem>
+ <xsl:apply-templates mode="para"/>
+ </poem>
+ </cite>
+ </xsl:template>
+
+ <!-- regular poem elements -->
+ <xsl:template mode="para" match="strofa">
+ <stanza>
+ <xsl:apply-templates mode="poem"/>
+ </stanza>
+ </xsl:template>
+
+ <!-- XXX: it should be done elsewhere but our cheap verse splitting
+ puts it here -->
+ <xsl:template match="motyw" mode="poem"/>
+
+ <xsl:template mode="poem" match="wers_normalny|wers_cd|wers_wciety|wers_akap">
+ <v><xsl:apply-templates mode="inline"/></v>
+ </xsl:template>
+</xsl:stylesheet>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+ This file is part of Librarian, licensed under GNU Affero GPLv3 or later.
+ Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
+
+-->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:wl="http://wolnelektury.pl/functions"
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns="http://www.gribuser.ru/xml/fictionbook/2.0"
+ xmlns:l="http://www.w3.org/1999/xlink">
+
+ <xsl:template name="section">
+ <!-- All the <_section> are in the end. -->
+ <xsl:if test="count(*) > count(_section)">
+ <section>
+ <xsl:choose>
+ <xsl:when test="(local-name() = 'liryka_l' or local-name() = 'liryka_lp')
+ and count(_section) = 0">
+ <poem>
+ <xsl:apply-templates mode="para" />
+ </poem>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates mode="para" />
+ </xsl:otherwise>
+ </xsl:choose>
+ </section>
+ </xsl:if>
+
+ <!-- Now, recursively, all the _section tags. -->
+ <xsl:apply-templates mode="section" select="_section" />
+ </xsl:template>
+
+ <xsl:template match="_section" mode="para" />
+ <xsl:template match="_section" mode="section" >
+ <section>
+ <xsl:call-template name="section" />
+ </section>
+ </xsl:template>
+
+ <!-- actual headings -->
+ <xsl:template match="naglowek_czesc|naglowek_rozdzial|naglowek_podrozdzial|naglowek_akt|naglowek_scena" mode="para">
+ <title><p><xsl:apply-templates mode="inline"/></p></title>
+ </xsl:template>
+</xsl:stylesheet>
if html_has_content(result):
add_anchors(result.getroot())
+ add_table_of_themes(result.getroot())
add_table_of_contents(result.getroot())
return OutputFile.from_string(etree.tostring(result, method='html',
root.insert(0, toc)
+
+def add_table_of_themes(root):
+ try:
+ from sortify import sortify
+ except ImportError:
+ sortify = lambda x: x
+
+ book_themes = {}
+ for fragment in root.findall('.//a[@class="theme-begin"]'):
+ if not fragment.text:
+ continue
+ theme_names = [s.strip() for s in fragment.text.split(',')]
+ for theme_name in theme_names:
+ book_themes.setdefault(theme_name, []).append(fragment.get('name'))
+ book_themes = book_themes.items()
+ book_themes.sort(key=lambda s: sortify(s[0]))
+ themes_div = etree.Element('div', id="themes")
+ themes_ol = etree.SubElement(themes_div, 'ol')
+ for theme_name, fragments in book_themes:
+ themes_li = etree.SubElement(themes_ol, 'li')
+ themes_li.text = "%s: " % theme_name
+ for i, fragment in enumerate(fragments):
+ item = etree.SubElement(themes_li, 'a', href="#%s" % fragment)
+ item.text = str(i + 1)
+ item.tail = ' '
+ root.insert(0, themes_div)
+
+
def extract_annotations(html_path):
"""For each annotation, yields a tuple: anchor, text, html."""
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
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
+ cover_file = NamedTemporaryFile(suffix='.png', delete=False)
c = cover(book_info)
- import Image
- c.im = Image.open('cover.jpg')
- c.ext = lambda: 'jpg'
- cover_file = NamedTemporaryFile(suffix='.' + c.ext(), delete=False)
c.save(cover_file)
- if cover.uses_dc_cover:
- if document.book_info.cover_by:
+ if bound_cover.uses_dc_cover:
+ 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)
#
from librarian import ValidationError, NoDublinCore, ParseError, NoProvider
from librarian import RDFNS
+from librarian.cover import WLCover
from librarian import dcparser
from xml.parsers.expat import ExpatError
LINE_SWAP_EXPR = re.compile(r'/\s', re.MULTILINE | re.UNICODE)
provider = None
- def __init__(self, edoc, parse_dublincore=True, provider=None, strict=False):
+ def __init__(self, edoc, parse_dublincore=True, provider=None,
+ strict=False, meta_fallbacks=None):
self.edoc = edoc
self.provider = provider
raise NoDublinCore('Document has no DublinCore - which is required.')
self.book_info = dcparser.BookInfo.from_element(
- self.rdf_elem, strict=strict)
+ self.rdf_elem, fallbacks=meta_fallbacks, strict=strict)
else:
self.book_info = None
return cls.from_file(StringIO(xml), *args, **kwargs)
@classmethod
- def from_file(cls, xmlfile, parse_dublincore=True, provider=None):
+ def from_file(cls, xmlfile, *args, **kwargs):
# first, prepare for parsing
if isinstance(xmlfile, basestring):
parser = etree.XMLParser(remove_blank_text=False)
tree = etree.parse(StringIO(data.encode('utf-8')), parser)
- return cls(tree, parse_dublincore=parse_dublincore, provider=provider)
+ return cls(tree, *args, **kwargs)
except (ExpatError, XMLSyntaxError, XSLTApplyError), e:
raise ParseError(e)
xpath = self.path_to_xpath(key)
node = self.edoc.xpath(xpath)[0]
repl = etree.fromstring(u"<%s>%s</%s>" %(node.tag, data, node.tag) )
- node.getparent().replace(node, repl);
+ node.getparent().replace(node, repl)
except Exception, e:
unmerged.append( repr( (key, xpath, e) ) )
node.tag = 'span'
node.tail = tail
+ def editors(self):
+ """Returns a set of all editors for book and its children.
+
+ :returns: set of dcparser.Person objects
+ """
+ if self.book_info is None:
+ raise NoDublinCore('No Dublin Core in document.')
+ persons = set(self.book_info.editors +
+ self.book_info.technical_editors)
+ for child in self.parts():
+ persons.update(child.editors())
+ if None in persons:
+ persons.remove(None)
+ return persons
+
# Converters
def as_html(self, *args, **kwargs):
from librarian import mobi
return mobi.transform(self, *args, **kwargs)
+ def as_fb2(self, *args, **kwargs):
+ from librarian import fb2
+ return fb2.transform(self, *args, **kwargs)
+
+ def as_cover(self, cover_class=None, *args, **kwargs):
+ if cover_class is None:
+ cover_class = WLCover
+ return cover_class(self.book_info, *args, **kwargs).output_file()
+
def save_output_file(self, output_file, output_path=None,
output_dir_path=None, make_author_dir=False, ext=None):
if output_dir_path:
# This file is part of Librarian, licensed under GNU Affero GPLv3 or later.
# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
#
+"""PDF creation library.
+
+Creates one big XML from the book and its children, converts it to LaTeX
+with TeXML, then runs it by XeLaTeX.
+
+"""
from __future__ import with_statement
import os
import os.path
from librarian.parser import WLDocument
from librarian import ParseError, DCNS, get_resource, OutputFile
from librarian import functions
-from librarian.cover import ImageCover as WLCover
+from librarian.cover import WLCover
functions.reg_substitute_entities()
def parse_creator(doc):
- """ find all dc:creator and dc.contributor tags and add *_parsed versions with forenames first """
+ """Generates readable versions of creator and translator tags.
+
+ Finds all dc:creator and dc.contributor.translator tags
+ and adds *_parsed versions with forenames first.
+ """
for person in doc.xpath("|".join('//dc:'+(tag) for tag in (
- 'creator', 'contributor.translator', 'contributor.editor', 'contributor.technical_editor')),
+ 'creator', 'contributor.translator')),
namespaces = {'dc': str(DCNS)})[::-1]:
if not person.text:
continue
def transform(wldoc, verbose=False, save_tex=None, morefloats=None,
- cover=None, flags=None, customizations=None,
- imgdir=""):
+ cover=None, flags=None, customizations=None):
""" produces a PDF file with XeLaTeX
wldoc: a WLDocument
verbose: prints all output from LaTeX
save_tex: path to save the intermediary LaTeX file to
morefloats (old/new/none): force specific morefloats
- cover: a cover.Cover object
+ cover: a cover.Cover factory or True for default
flags: less-advertising,
customizations: user requested customizations regarding various formatting parameters (passed to wl LaTeX class)
"""
# Parse XSLT
try:
+ book_info = wldoc.book_info
document = load_including_children(wldoc)
+ root = document.edoc.getroot()
if cover:
if cover is True:
cover = WLCover
- the_cover = cover(document.book_info)
- document.edoc.getroot().set('data-cover-width', str(the_cover.width))
- document.edoc.getroot().set('data-cover-height', str(the_cover.height))
- if the_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)
+ bound_cover = cover(book_info)
+ root.set('data-cover-width', str(bound_cover.width))
+ root.set('data-cover-height', str(bound_cover.height))
+ if bound_cover.uses_dc_cover:
+ if book_info.cover_by:
+ root.set('data-cover-by', book_info.cover_by)
+ if book_info.cover_source:
+ root.set('data-cover-source',
+ book_info.cover_source)
if flags:
for flag in flags:
- document.edoc.getroot().set('flag-' + flag, 'yes')
+ root.set('flag-' + flag, 'yes')
# check for LaTeX packages
if morefloats:
- document.edoc.getroot().set('morefloats', morefloats.lower())
+ root.set('morefloats', morefloats.lower())
elif package_available('morefloats', 'maxfloats=19'):
- document.edoc.getroot().set('morefloats', 'new')
+ root.set('morefloats', 'new')
# add customizations
if customizations is not None:
- document.edoc.getroot().set('customizations', u','.join(customizations))
+ root.set('customizations', u','.join(customizations))
+
+ # add editors info
+ root.set('editors', u', '.join(sorted(
+ editor.readable() for editor in document.editors())))
# hack the tree
- #move_motifs_inside(document.edoc)
- #hack_motifs(document.edoc)
+ move_motifs_inside(document.edoc)
+ hack_motifs(document.edoc)
parse_creator(document.edoc)
- if document.book_info.language == 'pol':
- substitute_hyphens(document.edoc)
+ substitute_hyphens(document.edoc)
fix_hanging(document.edoc)
# wl -> TeXML
style = etree.parse(style_filename)
texml = document.transform(style)
- # etree.dump(texml.getroot())
+
# TeXML -> LaTeX
temp = mkdtemp('-wl2pdf')
if cover:
- with open(os.path.join(temp, 'cover.jpg'), 'w') as f:
- the_cover.save(f)
-
- shutil.copy("cce_trust.eps", temp)
- shutil.copy("logo.eps", temp)
- for img in document.edoc.findall('//ilustr'):
- # print "--->> %s %s %s" % (imgdir, img, img.get('src'))
- shutil.copy(os.path.join(imgdir, img.get('src')), temp)
-
+ with open(os.path.join(temp, 'cover.png'), 'w') as f:
+ bound_cover.save(f)
del document # no longer needed large object :)
# LaTeX -> PDF
shutil.copy(get_resource('pdf/wl.cls'), temp)
shutil.copy(get_resource('res/wl-logo.png'), temp)
- shutil.copy('logo.eps', temp)
- cwd = os.getcwd()
+ try:
+ cwd = os.getcwd()
+ except OSError:
+ cwd = None
os.chdir(temp)
if verbose:
if p:
raise ParseError("Error parsing .tex file")
- os.chdir(cwd)
+ if cwd is not None:
+ os.chdir(cwd)
output_file = NamedTemporaryFile(prefix='librarian', suffix='.pdf', delete=False)
pdf_path = os.path.join(temp, 'doc.pdf')
return OutputFile.from_filename(output_file.name)
except (XMLSyntaxError, XSLTApplyError), e:
- print e
raise ParseError(e)
text = re.sub(ur"([\u0400-\u04ff]+)", ur"<alien>\1</alien>", text)
- document = WLDocument.from_string(text, parse_dublincore=True)
+ document = WLDocument.from_string(text,
+ parse_dublincore=True, provider=provider)
document.swap_endlines()
for child_uri in document.book_info.parts:
\usepackage{xunicode}
\usepackage{xltxtra}
-
\usepackage[overload]{textcase}
\usepackage{scalefnt}
\usepackage[colorlinks=true,linkcolor=black,setpagesize=false,urlcolor=black,xetex]{hyperref}
\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}{
+
+%% Strona tytułowa %% XXX
+ \hspace{-36mm}\parbox{16cm}{
{\addfontfeature{LetterSpace=-4.0}{\scalefont{4}%
\noindent Philippe Aigrain}}
{\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}{
+%% XXX % sprawdzic czy czegos nie zgubilem z master
+%% szczegolnie jesli chodzi o makra wstawiajace dane z DC, jak np \editors
\clearpage
\thispagestyle{empty}
\includegraphics[scale=.2]{logo.eps}
}
+ Przekaż darowiznę na konto:
+ \href{http://nowoczesnapolska.org.pl/pomoz-nam/wesprzyj-nas/}{szczegóły na stronie Fundacji}.
\clearpage
\thispagestyle{empty}
%{\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{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>
</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() < 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>
# This file is part of Librarian, licensed under GNU Affero GPLv3 or later.
# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
#
-import os
-import optparse
+from StringIO import StringIO
+from librarian import OutputFile
+from librarian.book2anything import Book2Anything, Option
-from librarian import ParseError
-from librarian.parser import WLDocument
-from librarian.cover import WLCover
+class Book2Cover(Book2Anything):
+ format_name = "JPEG"
+ ext = "jpg"
+ uses_cover = True
+ cover_optional = False
-if __name__ == '__main__':
- # Parse commandline arguments
- usage = """Usage: %prog [options] SOURCE [SOURCE...]
- Create cover images for SOURCE files."""
-
- parser = optparse.OptionParser(usage=usage)
-
- parser.add_option('-v', '--verbose', action='store_true', dest='verbose', default=False,
- help='print status messages to stdout')
+ transform_options = [
+ Option('-W', '--width', action='store', type='int', dest='width', default=None,
+ help='Set width.'),
+ Option('-H', '--height', action='store', type='int', dest='height', default=None,
+ help='Set height.'),
+ Option('-l', '--with-logo', dest='with_logo',
+ action='store_true', default=False,
+ help='Add WL logo in white box.'),
+ ]
- options, input_filenames = parser.parse_args()
+ @staticmethod
+ def transform(wldoc, cover, *args, **kwargs):
+ return wldoc.as_cover(cover_class=cover, *args, **kwargs)
- if len(input_filenames) < 1:
- parser.print_help()
- exit(1)
- # Do some real work
- for input_filename in input_filenames:
- if options.verbose:
- print input_filename
-
- output_filename = os.path.splitext(input_filename)[0] + '.jpg'
-
- doc = WLDocument.from_file(input_filename)
- WLCover(doc.book_info).save(output_filename)
+if __name__ == '__main__':
+ Book2Cover.run()
# This file is part of Librarian, licensed under GNU Affero GPLv3 or later.
# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
#
-import os.path
-import optparse
+from librarian.book2anything import Book2Anything, Option
-from librarian import DirDocProvider, ParseError
-from librarian.parser import WLDocument
+class Book2Epub(Book2Anything):
+ format_name = "EPUB"
+ ext = "epub"
+ uses_cover = True
+ uses_provider = True
+ transform_flags = [
+ Option('-w', '--working-copy', dest='working-copy',
+ action='store_true', default=False,
+ help='mark the output as a working copy')
+ ]
-if __name__ == '__main__':
- # Parse commandline arguments
- usage = """Usage: %prog [options] SOURCE [SOURCE...]
- Convert SOURCE files to EPUB format."""
-
- parser = optparse.OptionParser(usage=usage)
-
- parser.add_option('-v', '--verbose', action='store_true', dest='verbose', default=False,
- help='print status messages to stdout')
- parser.add_option('-c', '--with-cover', action='store_true', dest='with_cover', default=False,
- help='create default cover')
- parser.add_option('-w', '--working-copy', action='store_true', dest='working_copy', default=False,
- help='specifies the directory for output')
- 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('-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')
-
- options, input_filenames = parser.parse_args()
-
- if len(input_filenames) < 1:
- parser.print_help()
- exit(1)
-
- flags = []
- if options.working_copy:
- flags.append('working-copy')
- # Do some real work
- 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)
- if not (options.output_file or options.output_dir):
- output_file = os.path.splitext(main_input)[0] + '.epub'
- else:
- output_file = None
-
- doc = WLDocument.from_file(main_input, provider=provider)
- epub = doc.as_epub(cover=options.with_cover, flags=flags)
-
- doc.save_output_file(epub,
- output_file, options.output_dir, options.make_dir, 'epub')
-
- except ParseError, e:
- print '%(file)s:%(name)s:%(message)s' % {
- 'file': main_input,
- 'name': e.__class__.__name__,
- 'message': e
- }
+if __name__ == '__main__':
+ Book2Epub.run()
--- /dev/null
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# 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
+
+
+class Book2Fb2(Book2Anything):
+ format_name = "FB2"
+ ext = "fb2"
+ uses_cover = False
+ uses_provider = True
+
+
+if __name__ == '__main__':
+ Book2Fb2.run()
# This file is part of Librarian, licensed under GNU Affero GPLv3 or later.
# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
#
-import os
-import optparse
-
-from librarian import ParseError
-from librarian.parser import WLDocument
+from librarian.book2anything import Book2Anything, Option
+
+
+class Book2Html(Book2Anything):
+ format_name = "HTML"
+ ext = "html"
+ uses_cover = False
+ uses_provider = False
+ transform_flags = [
+ Option('-r', '--raw', dest='full-page',
+ action='store_false', default=True,
+ help='output raw text for use in templates')
+ ]
+ parser_args = [
+ Option('-i', '--ignore-dublin-core', dest='parse_dublincore',
+ action='store_false', default=True,
+ help='don\'t try to parse dublin core metadata')
+ ]
if __name__ == '__main__':
- # Parse commandline arguments
- usage = """Usage: %prog [options] SOURCE [SOURCE...]
- Convert SOURCE files to HTML format."""
-
- parser = optparse.OptionParser(usage=usage)
-
- parser.add_option('-v', '--verbose', action='store_true', dest='verbose', default=False,
- help='print status messages to stdout')
- parser.add_option('-i', '--ignore-dublin-core', action='store_false', dest='parse_dublincore', default=True,
- help='don\'t try to parse dublin core metadata')
- parser.add_option('-r', '--raw', action='store_false', dest='full_page', default=True,
- help='outpu raw text for use in templates')
-
- options, input_filenames = parser.parse_args()
-
- if len(input_filenames) < 1:
- parser.print_help()
- exit(1)
-
- # Do some real work
- for input_filename in input_filenames:
- if options.verbose:
- print input_filename
-
- output_filename = os.path.splitext(input_filename)[0] + '.html'
- try:
- doc = WLDocument.from_file(input_filename,
- parse_dublincore=options.parse_dublincore)
- flags = ('full-page',) if options.full_page else None
- html = doc.as_html(flags=flags)
- doc.save_output_file(html, output_path=output_filename)
- except ParseError, e:
- print '%(file)s:%(name)s:%(message)s' % {
- 'file': input_filename,
- 'name': e.__class__.__name__,
- 'message': e,
- }
- except IOError, e:
- print '%(file)s:%(name)s:%(message)s' % {
- 'file': input_filename,
- 'name': e.__class__.__name__,
- 'message': e.strerror,
- }
- except BaseException, e:
- print '%(file)s:%(etype)s:%(message)s' % {
- 'file': input_filename,
- 'etype': e.__class__.__name__,
- 'message': e,
- }
- raise
-
+ Book2Html.run()
+++ /dev/null
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-#
-# This file is part of Librarian, licensed under GNU Affero GPLv3 or later.
-# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
-#
-import os
-import optparse
-
-from librarian import ParseError
-from librarian.parser import WLDocument
-
-
-if __name__ == '__main__':
- # Parse commandline arguments
- usage = """Usage: %prog [options] SOURCE [SOURCE...]
- Convert SOURCE files to HTML format."""
-
- parser = optparse.OptionParser(usage=usage)
-
- parser.add_option('-v', '--verbose', action='store_true', dest='verbose', default=False,
- help='print status messages to stdout')
- parser.add_option('-i', '--ignore-dublin-core', action='store_false', dest='parse_dublincore', default=True,
- help='don\'t try to parse dublin core metadata')
-
- options, input_filenames = parser.parse_args()
-
- if len(input_filenames) < 1:
- parser.print_help()
- exit(1)
-
- # Do some real work
- for input_filename in input_filenames:
- if options.verbose:
- print input_filename
-
- output_filename = os.path.splitext(input_filename)[0] + '.html'
- try:
- doc = WLDocument.from_file(input_filename,
- parse_dublincore=options.parse_dublincore)
- html = doc.as_html(flags=('full-page',), stylesheet='partial')
- doc.save_output_file(html, output_path=output_filename)
- except ParseError, e:
- print '%(file)s:%(name)s:%(message)s' % {
- 'file': input_filename,
- 'name': e.__class__.__name__,
- 'message': e.message.encode('utf-8')
- }
- except IOError, e:
- print '%(file)s:%(name)s:%(message)s' % {
- 'file': input_filename,
- 'name': e.__class__.__name__,
- 'message': e.strerror,
- }
- except BaseException, e:
- print '%(file)s:%(etype)s:%(message)s' % {
- 'file': input_filename,
- 'etype': e.__class__.__name__,
- 'message': e.message.encode('utf-8'),
- }
- raise
-
# This file is part of Librarian, licensed under GNU Affero GPLv3 or later.
# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
#
-import os.path
-import optparse
+from librarian.book2anything import Book2Anything
-from librarian import DirDocProvider, ParseError
-from librarian.parser import WLDocument
+class Book2Mobi(Book2Anything):
+ format_name = "MOBI"
+ ext = "mobi"
+ uses_cover = True
+ cover_optional = False
+ uses_provider = True
-if __name__ == '__main__':
- # Parse commandline arguments
- usage = """Usage: %prog [options] SOURCE [SOURCE...]
- Convert SOURCE files to MOBI format."""
-
- parser = optparse.OptionParser(usage=usage)
-
- parser.add_option('-v', '--verbose', action='store_true', dest='verbose', default=False,
- help='print status messages to stdout')
- 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('-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')
-
- options, input_filenames = parser.parse_args()
- if len(input_filenames) < 1:
- parser.print_help()
- exit(1)
-
- # Do some real work
- try:
- for main_input in input_filenames:
- path, fname = os.path.realpath(main_input).rsplit('/', 1)
- provider = DirDocProvider(path)
- if not (options.output_file or options.output_dir):
- output_file = os.path.splitext(main_input)[0] + '.mobi'
- else:
- output_file = None
-
- doc = WLDocument.from_file(main_input, provider=provider)
- mobi = doc.as_mobi()
-
- doc.save_output_file(mobi,
- output_file, options.output_dir, options.make_dir, 'mobi')
- except ParseError, e:
- print '%(file)s:%(name)s:%(message)s' % {
- 'file': main_input,
- 'name': e.__class__.__name__,
- 'message': e
- }
+if __name__ == '__main__':
+ Book2Mobi.run()
# 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()
# This file is part of Librarian, licensed under GNU Affero GPLv3 or later.
# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
#
-import os
-import optparse
-
-from librarian import ParseError
+from librarian.book2anything import Book2Anything, Option
from librarian.parser import WLDocument
-if __name__ == '__main__':
- # Parse commandline arguments
- usage = """Usage: %prog [options] SOURCE [SOURCE...]
- Convert SOURCE files to TXT format."""
-
- parser = optparse.OptionParser(usage=usage)
-
- parser.add_option('-v', '--verbose', action='store_true', dest='verbose', default=False,
- help='print status messages to stdout')
- parser.add_option('-w', '--wrap', action='store', type='int', dest='wrapping', default=0,
- help='set line wrap column')
- parser.add_option('-i', '--ignore-dublin-core', action='store_false', dest='parse_dublincore', default=True,
- help='don\'t try to parse dublin core metadata')
+class Book2Txt(Book2Anything):
+ format_name = "TXT"
+ ext = "txt"
+ uses_cover = False
+ uses_provider = False
+ parser_args = [
+ Option('-i', '--ignore-dublin-core', dest='parse_dublincore',
+ action='store_false', default=True,
+ help='don\'t try to parse dublin core metadata')
+ ]
+ transform_args = [
+ Option('-w', '--wrap', action='store', type='int', dest='wrapping', default=0,
+ help='set line wrap column')
+ ]
+ transform = WLDocument.as_text
- options, input_filenames = parser.parse_args()
- if len(input_filenames) < 1:
- parser.print_help()
- exit(1)
-
- # Do some real work
- for input_filename in input_filenames:
- if options.verbose:
- print input_filename
-
- output_filename = os.path.splitext(input_filename)[0] + '.txt'
- try:
- doc = WLDocument.from_file(input_filename,
- parse_dublincore=options.parse_dublincore)
- html = doc.as_text(wrapping=str(options.wrapping))
- doc.save_output_file(html, output_path=output_filename)
- except ParseError, e:
- print '%(file)s:%(name)s:%(message)s' % {
- 'file': input_filename,
- 'name': e.__class__.__name__,
- 'message': e
- }
- except IOError, e:
- print '%(file)s:%(name)s:%(message)s' % {
- 'file': input_filename,
- 'name': e.__class__.__name__,
- 'message': e.strerror,
- }
- except BaseException, e:
- print '%(file)s:%(etype)s:%(message)s' % {
- 'file': input_filename,
- 'etype': e.__class__.__name__,
- 'message': e,
- }
- raise
+if __name__ == '__main__':
+ Book2Txt.run()
setup(
name='librarian',
- version='1.4.2a',
+ version='1.5.1',
description='Converter from WolneLektury.pl XML-based language to XHTML, TXT and other formats',
author="Marek Stępniowski",
author_email='marek@stepniowski.com',
maintainer='Radek Czajka',
- maintainer_email='radek.czajka@gmail.com',
+ maintainer_email='radoslaw.czajka@nowoczesnapolska.org.pl',
url='http://github.com/fnp/librarian',
packages=['librarian'],
- package_data={'librarian': ['xslt/*.xslt', 'epub/*', 'mobi/*', 'pdf/*', 'fonts/*', 'res/*'] +
+ package_data={'librarian': ['xslt/*.xslt', 'epub/*', 'mobi/*', 'pdf/*', 'fb2/*', 'fonts/*', 'res/*'] +
whole_tree(os.path.join(os.path.dirname(__file__), 'librarian'), 'font-optimizer')},
include_package_data=True,
- install_requires=['lxml>=2.2'],
+ install_requires=[
+ 'lxml>=2.2',
+ 'Pillow',
+ ],
scripts=['scripts/book2html',
'scripts/book2txt',
'scripts/book2epub',
'scripts/book2mobi',
'scripts/book2pdf',
+ 'scripts/book2fb2',
'scripts/book2partner',
'scripts/book2cover',
'scripts/bookfragments',
--- /dev/null
+<?xml version='1.0' encoding='utf-8'?>
+<!--
+ Example file for testing a converter.
+ Just run it through and see if everything looks ok.
+-->
+<utwor>
+<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+xmlns:dc="http://purl.org/dc/elements/1.1/">
+<rdf:Description rdf:about="LINK DO PLATFORMY REDAKCYJNEJ">
+<dc:creator xml:lang="pl">Utworu, Autor</dc:creator>
+<dc:title xml:lang="pl">Tytuł w DC</dc:title>
+<dc:contributor.translator xml:lang="pl">Utworu, Tłumacz</dc:contributor.translator>
+<dc:contributor.editor xml:lang="pl">Literacki, Redaktor</dc:contributor.editor>
+<dc:contributor.technical_editor xml:lang="pl">Techniczny, Redaktor</dc:contributor.technical_editor>
+<dc:publisher xml:lang="pl">Fundacja Nowoczesna Polska</dc:publisher>
+<dc:subject.period xml:lang="pl">period</dc:subject.period>
+<dc:subject.type xml:lang="pl">type</dc:subject.type>
+<dc:subject.genre xml:lang="pl">genre</dc:subject.genre>
+<dc:description xml:lang="pl">Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Reprodukcja cyfrowa wykonana
+ przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN.</dc:description>
+<dc:identifier.url xml:lang="pl">http://wolnelektury.pl/katalog/lektura/test1</dc:identifier.url>
+<dc:source xml:lang="pl">source</dc:source>
+<dc:rights xml:lang="pl">Domena publiczna</dc:rights>
+<dc:date.pd xml:lang="pl">1500</dc:date.pd>
+<dc:format xml:lang="pl">xml</dc:format>
+<dc:type xml:lang="pl">text</dc:type>
+<dc:type xml:lang="en">text</dc:type>
+<dc:date xml:lang="pl">2000</dc:date>
+<dc:language xml:lang="pl">pol</dc:language>
+</rdf:Description>
+</rdf:RDF>
+<liryka_l>
+
+<nota_red><akap>nota_red</akap></nota_red>
+
+<autor_utworu>autor_utworu</autor_utworu>
+<dzielo_nadrzedne>dzielo_nadrzedne</dzielo_nadrzedne>
+<nazwa_utworu>nazwa_utworu</nazwa_utworu>
+<podtytul>podtytul</podtytul>
+
+<akap>[powyżej:
+nota_red (nie pojawia się w tekście, może być podana osobno),
+autor_utworu, dzielo_nadrzedne, nazwa_utworu, podtytul, tłumacz (z DC)]</akap>
+
+<akap>[Noty: nota/akap, dedykacja/akap, motto/akap, motto_podpis]</akap>
+
+
+<nota><akap>nota/akap</akap></nota>
+<dedykacja><akap>dedykacja/akap</akap></dedykacja>
+<motto><akap>motto/akap</akap></motto>
+<motto_podpis>motto_podpis</motto_podpis>
+
+<akap>[Początek dramatu: lista_osob, naglowek_listy, lista_osoba, miejsce_czas]</akap>
+
+<lista_osob>
+ <naglowek_listy>lista_osob/naglowek_listy</naglowek_listy>
+ <lista_osoba>lista_osob/lista_osoba</lista_osoba>
+ <lista_osoba>lista_osob/lista_osoba</lista_osoba>
+</lista_osob>
+<miejsce_czas>miejsce_czas</miejsce_czas>
+
+<akap>[naglowek_czesc, naglowek_rozdzial, naglowek_podrozdzial, srodtytul]</akap>
+
+<naglowek_czesc>naglowek_czesc</naglowek_czesc>
+<naglowek_rozdzial>naglowek_rozdzial</naglowek_rozdzial>
+<naglowek_podrozdzial>naglowek_podrozdzial</naglowek_podrozdzial>
+<srodtytul>srodtytul</srodtytul>
+
+<akap>[akap, akap_cd, akap_dialog, motyw]</akap>
+
+<akap>akap<begin id="a"/><motyw>motyw</motyw></akap>
+<akap_cd>akap_cd</akap_cd>
+<akap_dialog>akap_dialog<end id="a"/></akap_dialog>
+
+<akap>[strofa, wers_akap, wers_wciety,typ=1-6, wers_cd, zastepnik_wersu]</akap>
+
+<strofa>strofa/
+<wers_akap>wers_akap</wers_akap>/
+<wers_wciety typ="1">wers_wciety@typ=1</wers_wciety>/
+<wers_wciety typ="2">wers_wciety@typ=2</wers_wciety>/
+<wers_wciety typ="3">wers_wciety@typ=3</wers_wciety>
+</strofa><strofa>
+<wers_wciety typ="4">wers_wciety@typ=4</wers_wciety>/
+<wers_wciety typ="5">wers_wciety@typ=5</wers_wciety>/
+<wers_wciety typ="6">wers_wciety@typ=6</wers_wciety>/
+<wers_cd>wers_cd</wers_cd>/
+<zastepnik_wersu />. . . . . . . . . . . . . . . .
+</strofa>
+
+<akap>[dlugi_cytat/akap]</akap>
+
+<dlugi_cytat><akap>Cytowany akapit powinien wyglądać jak cytowany akapit.
+Znaczy, może mieć jakieś dodatkowe wcięcie, jakiś rodzaj wyróżnienia czy coś.</akap></dlugi_cytat>
+
+<akap>[poezja_cyt/strofa]</akap>
+
+<poezja_cyt><strofa>To jest poezja/
+cytowana/
+ma być porządnie/
+wyrównana</strofa></poezja_cyt>
+
+<akap>[naglowek_akt, naglowek_scena]</akap>
+
+<naglowek_akt>naglowek_akt</naglowek_akt>
+<naglowek_scena>naglowek_scena</naglowek_scena>
+
+<akap>[Kwestia: naglowek_osoba, kwestia, didask_tekst, didaskalia, strofa, akap]</akap>
+
+<naglowek_osoba>naglowek_osoba</naglowek_osoba>
+
+<kwestia>
+<didask_tekst>didask_tekst</didask_tekst>
+<didaskalia>didaskalia</didaskalia>
+<strofa>Strofa w dramacie/
+jak amen w pacie/
+rzu.</strofa>
+<akap>Powyższy kawałek wiersza jest najzupełniej bez sensu i tak naprawdę wcale nie trzyma rytmu ani rymu. Być może należy skoncentrować się na dramacie prozą, jak ta tutaj niniejsza wypowiedź. </akap></kwestia>
+
+<akap>[didaskalia, osoba]</akap>
+
+<didaskalia>odezwał się <osoba>autor</osoba>.</didaskalia>
+
+<akap>[Wyróżnienia: tytul_dziela, tytul_dziela@typ=1, wyroznienie, slowo_obce]</akap>
+
+<akap>
+<tytul_dziela>tytul_dziela</tytul_dziela>,
+<tytul_dziela typ="1">tytul_dziela@typ=1</tytul_dziela>,
+<wyroznienie>wyroznienie</wyroznienie>,
+<slowo_obce>slowo_obce</slowo_obce>
+</akap>
+
+<akap>[Przypisy: pa, pt, pr, pe]</akap>
+
+<akap>
+<pa>pa - - - przypis <wyroznienie>autorski</wyroznienie></pa>
+<pt>pt - - - przypis tłumacza</pt>
+<pr>pr - - - przypis redakcyjny</pr>
+<pe>pe - - - przypis edytorski</pe>
+</akap>
+
+<akap>[Separatory]</akap>
+
+<akap>[sekcja_swiatlo:]</akap>
+
+<sekcja_swiatlo></sekcja_swiatlo>
+
+<akap>[sekcja_asterysk:]</akap>
+
+<sekcja_asterysk></sekcja_asterysk>
+
+<akap>[separator_linia:]</akap>
+
+<separator_linia></separator_linia>
+
+
+
+<akap>[Komentarze: uwaga, extra]</akap>
+<uwaga>uwaga</uwaga>
+<extra>extra</extra>
+
+<akap>[Nieużywane]</akap>
+
+<wyp_osoba>wyp_osoba</wyp_osoba>
+<wywiad_pyt><akap>wywiad_pyt/akap</akap></wywiad_pyt>
+<wywiad_odp><akap>wywiad_odp/akap</akap></wywiad_odp>
+<mat>mat</mat>
+<www>www</www>
+
+</liryka_l>
+</utwor>
<dc:rights xml:lang="pl">Domena publiczna - Paul Klee zm. 1940</dc:rights>
<dc:date.pd xml:lang="pl">1940</dc:date.pd>
<dc:type>Image</dc:type>
- <dc:format xml:lang="pl">image/png</dc:format>
- <dc:format.dimensions xml:lang="pl">1645 x 2000 px</dc:format.dimensions>
- <dc:format.checksum.sha1 xml:lang="pl">d9ead48f3442ac4e1add602aacdffa4638ae8e21</dc:format.checksum.sha1>
+ <dc:format xml:lang="pl">image/jpeg</dc:format>
+ <dc:format.dimensions xml:lang="pl">329 x 400 px</dc:format.dimensions>
+ <dc:format.checksum.sha1 xml:lang="pl">5ed8e8d24d92017c6341c0b8cfcc414dec55b8bf</dc:format.checksum.sha1>
<dc:date xml:lang="pl">1920</dc:date>
<dc:language xml:lang="pl" xmlns:dc="http://purl.org/dc/elements/1.1/">lat</dc:language>
</rdf:Description>
<div type="whole"/>
</sem>
<sem type="theme" theme="anioł historii">
- <div type="area" x1="462" y1="212" x2="1283" y2="1730"/>
+ <div type="area" x1="92" y1="42" x2="257" y2="346"/>
</sem>
<sem type="theme" theme="spojrzenie">
- <div type="area" x1="688" y1="500" x2="1054" y2="618"/>
+ <div type="area" x1="138" y1="100" x2="211" y2="124"/>
</sem>
<sem type="object" object="skrzydło">
- <div type="area" x1="468" y1="741" x2="694" y2="1027"/>
- <div type="area" x1="1044" y1="762" x2="1260" y2="1041"/>
+ <div type="area" x1="94" y1="148" x2="139" y2="205"/>
+ <div type="area" x1="209" y1="152" x2="252" y2="1041"/>
</sem>
</picture>
<h2>Spis treści</h2>
<ol></ol>
</div>
+<div id="themes"><ol>
+<li>Miłość platoniczna: <a href="#m1189062500041">1</a> <a href="#m1189062500041">2</a> </li>
+<li>Natura: <a href="#m1189062528872">1</a> </li>
+</ol></div>
<h1>
<span class="author">Adam Asnyk</span><span class="title"><a name="m1189062500041" class="theme-begin" fid="1189062500041">Miłość platoniczna</a>Między nami nic nie było</span>
</h1>
<a name="m1189062500041" class="theme-begin" fid="1189062500041">Miłość platoniczna</a><div class="stanza">
-<p class="verse"><a name="f1" class="target"> </a><a href="#f1" class="anchor">1</a>Między nami nic nie było!</p>
+<a name="sec4"></a><p class="verse"><a name="f1" class="target"> </a><a href="#f1" class="anchor">1</a>Między nami nic nie było!</p>
<p class="verse">Żadnych zwierzeń, wyznań żadnych!</p>
<p class="verse">Nic nas z sobą nie łączyło —</p>
<p class="verse">Prócz wiosennych marzeń zdradnych;</p>
</div>
<div class="stanza">
-<p class="verse"><a name="f5" class="target"> </a><a href="#f5" class="anchor">5</a><a name="m1189062528872" class="theme-begin" fid="1189062528872">Natura</a>Prócz tych woni, barw i blasków,</p>
+<a name="sec5"></a><p class="verse"><a name="f5" class="target"> </a><a href="#f5" class="anchor">5</a><a name="m1189062528872" class="theme-begin" fid="1189062528872">Natura</a>Prócz tych woni, barw i blasków,</p>
<p class="verse">Unoszących się w przestrzeni;</p>
<p class="verse">Prócz szumiących śpiewem lasków</p>
<p class="verse">I tej świeżej łąk zieleni;</p>
</div>
<div class="stanza">
-<p class="verse">Prócz tych kaskad i potoków,</p>
+<a name="sec6"></a><p class="verse">Prócz tych kaskad i potoków,</p>
<p class="verse"><a name="f10" class="target"> </a><a href="#f10" class="anchor">10</a>Zraszających każdy parów,</p>
<p class="verse">Prócz girlandy tęcz, obłoków,</p>
<p class="verse">Prócz natury słodkich czarów;</p>
</div>
<div class="stanza">
-<p class="verse">Prócz tych wspólnych, jasnych zdrojów,</p>
+<a name="sec7"></a><p class="verse">Prócz tych wspólnych, jasnych zdrojów,</p>
<p class="verse">Z których serce zachwyt piło;</p>
<p class="verse"><a name="f15" class="target"> </a><a href="#f15" class="anchor">15</a>Prócz pierwiosnków i powojów,—</p>
<p class="verse">Między nami nic nie było!<span class="theme-end" fid="1189062528872"></span><span class="theme-end" fid="1189062500041"></span></p>
Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN.
-Opracowanie redakcyjne i przypisy: Aleksandra Sekuła, Olga Sutkowska
+Opracowanie redakcyjne i przypisy: Adam Fikcyjny, Aleksandra Sekuła, Olga Sutkowska
<dc:subject.period xml:lang="pl">Pozytywizm</dc:subject.period>
<dc:subject.type xml:lang="pl">Liryka</dc:subject.type>
<dc:subject.genre xml:lang="pl">Wiersz</dc:subject.genre>
+<dc:contributor.technical_editor xml:lang="pl">Fikcyjny, Adam</dc:contributor.technical_editor>
<dc:description xml:lang="pl">Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN.</dc:description>
<dc:identifier.url xml:lang="pl">http://wolnelektury.pl/katalog/lektura/poezye</dc:identifier.url>
<dc:relation.hasPart xml:lang="pl">http://wolnelektury.pl/katalog/lektura/miedzy-nami-nic-nie-bylo</dc:relation.hasPart>
+<dc:relation.hasPart xml:lang="pl">http://wolnelektury.pl/katalog/lektura/do-mlodych</dc:relation.hasPart>
<dc:source.URL xml:lang="pl">http://www.polona.pl/Content/5164</dc:source.URL>
<dc:source xml:lang="pl">(Asnyk, Adam) El...y (1838-1897), Poezye, t. 3, Gebethner i Wolff, wyd. nowe poprzedzone słowem wstępnym St. Krzemińskiego, Warszawa, 1898</dc:source>
<dc:rights xml:lang="pl">Domena publiczna - Adam Asnyk zm. 1897</dc:rights>
--- /dev/null
+<utwor><rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+<rdf:Description rdf:about="http://redakcja.wolnelektury.pl/documents/book/do-mlodych/">
+<dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="pl">Asnyk, Adam</dc:creator>
+<dc:title xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="pl">Do młodych</dc:title>
+<dc:contributor.editor xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="pl">Sekuła, Aleksandra</dc:contributor.editor>
+<dc:contributor.technical_editor xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="pl">Sutkowska, Olga</dc:contributor.technical_editor>
+<dc:publisher xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="pl">Fundacja Nowoczesna Polska</dc:publisher>
+<dc:subject.period xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="pl">Pozytywizm</dc:subject.period>
+<dc:subject.type xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="pl">Liryka</dc:subject.type>
+<dc:subject.genre xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="pl">Wiersz</dc:subject.genre>
+<dc:description xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="pl">Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN.</dc:description>
+<dc:identifier.url xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="pl">http://wolnelektury.pl/katalog/lektura/do-mlodych</dc:identifier.url>
+<dc:source.URL xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="pl">http://www.polona.pl/Content/8616</dc:source.URL>
+<dc:source xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="pl">El...y (Adam Asnyk), Poezye, t. 3, Gebethner i Wolff, wyd. nowe poprzedzone słowem wstępnym St. Krzemińskiego, Warszawa 1898</dc:source>
+<dc:rights xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="pl">Domena publiczna - Adam Asnyk zm. 1897</dc:rights>
+<dc:date.pd xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="pl">1897</dc:date.pd>
+<dc:format xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="pl">xml</dc:format>
+<dc:type xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="pl">text</dc:type>
+<dc:type xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="en">text</dc:type>
+<dc:date xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="pl">2009-04-07</dc:date>
+<dc:audience xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="pl">L</dc:audience>
+<dc:language xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="pl">pol</dc:language>
+<dc:relation.coverImage.url xmlns:dc="http://purl.org/dc/elements/1.1/">http://redakcja.wolnelektury.pl/media/dynamic/cover/image/35.jpg</dc:relation.coverImage.url>
+<dc:relation.coverImage.attribution xmlns:dc="http://purl.org/dc/elements/1.1/">leboski@Flickr, CC BY 2.0</dc:relation.coverImage.attribution>
+<dc:relation.coverImage.source xmlns:dc="http://purl.org/dc/elements/1.1/">http://redakcja.wolnelektury.pl/cover/image/35</dc:relation.coverImage.source>
+</rdf:Description>
+</rdf:RDF><liryka_l>
+
+<autor_utworu>Adam Asnyk</autor_utworu>
+
+<nazwa_utworu>Do młodych</nazwa_utworu>
+
+
+
+
+<strofa>Szukajcie prawdy jasnego płomienia,/
+Szukajcie nowych, nieodkrytych dróg!/
+Za każdym krokiem w tajniki stworzenia/
+Coraz się dusza ludzka rozprzestrzenia/
+I większym staje się Bóg!</strofa>
+
+
+<strofa>Choć otrząśniecie kwiaty barwnych mitów,/
+Choć rozproszycie legendowy mrok,/
+Choć mgłę urojeń zedrzecie z błękitów, ---/
+Ludziom niebiańskich nie zbraknie zachwytów,/
+Lecz dalej sięgnie ich wzrok.</strofa>
+
+
+<strofa><begin id="b1238764684390"/><motyw id="m1238764684390">Czas, Kondycja ludzka, Przemijanie</motyw>Każda epoka ma swe własne cele/
+I zapomina o wczorajszych snach:/
+Nieście więc wiedzy pochodnię na czele/
+I nowy udział bierzcie w wieków dziele,---/
+Przyszłości podnoście gmach!</strofa>
+
+
+<strofa>Ale nie depczcie przeszłości ołtarzy,/
+Choć macie sami doskonalsze wznieść:/
+Na nich się jeszcze święty ogień żarzy,/
+I miłość ludzka stoi tam na straży,/
+I wy winniście im cześć!</strofa>
+
+
+<strofa>Ze światem, który w ciemność już zachodzi/
+Wraz z całą tęczą idealnych snów,/
+Prawdziwa mądrość niechaj was pogodzi:/
+I wasze gwiazdy, o zdobywcy młodzi,/
+W ciemnościach pogasną znów!<end id="e1238764684390"/></strofa>
+
+</liryka_l></utwor>
\ No newline at end of file
<dc:contributor.editor xml:lang="pl" />
<dc:contributor.editor xml:lang="pl">Sekuła, Aleksandra</dc:contributor.editor>
<dc:contributor.technical_editor xml:lang="pl">Sutkowska, Olga</dc:contributor.technical_editor>
+<dc:contributor.editor xml:lang="pl">Fikcyjny, Adam</dc:contributor.editor>
+<dc:contributor.technical_editor xml:lang="pl">Fikcyjny, Adam</dc:contributor.technical_editor>
<dc:publisher xml:lang="pl">Fundacja Nowoczesna Polska</dc:publisher>
<dc:subject.period xml:lang="pl">Pozytywizm</dc:subject.period>
<dc:subject.type xml:lang="pl">Liryka</dc:subject.type>
# This file is part of Librarian, licensed under GNU Affero GPLv3 or later.
# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
#
+from zipfile import ZipFile
+from lxml import html
+from nose.tools import *
from librarian import DirDocProvider
from librarian.parser import WLDocument
-from nose.tools import *
-from utils import get_fixture
+from tests.utils import get_fixture
def test_transform():
- WLDocument.from_file(
+ epub = WLDocument.from_file(
get_fixture('text', 'asnyk_zbior.xml'),
provider=DirDocProvider(get_fixture('text', ''))
- ).as_epub(flags=['without_fonts'])
+ ).as_epub(flags=['without_fonts']).get_file()
+ zipf = ZipFile(epub)
+
+ # Check contributor list.
+ last = zipf.open('OPS/last.html')
+ tree = html.parse(last)
+ editors_attribution = False
+ for par in tree.findall("//p"):
+ if par.text.startswith(u'Opracowanie redakcyjne i przypisy:'):
+ editors_attribution = True
+ assert_equal(par.text.rstrip(),
+ u'Opracowanie redakcyjne i przypisy: '
+ u'Adam Fikcyjny, Aleksandra Sekuła, Olga Sutkowska.')
+ assert_true(editors_attribution)
--- /dev/null
+# -*- coding: utf-8 -*-
+#
+# This file is part of Librarian, licensed under GNU Affero GPLv3 or later.
+# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
+#
+import re
+from tempfile import NamedTemporaryFile
+from nose.tools import *
+from librarian import DirDocProvider
+from librarian.parser import WLDocument
+from utils import get_fixture
+
+
+def test_transform():
+ temp = NamedTemporaryFile(delete=False)
+ temp.close()
+ WLDocument.from_file(
+ get_fixture('text', 'asnyk_zbior.xml'),
+ provider=DirDocProvider(get_fixture('text', ''))
+ ).as_pdf(save_tex=temp.name)
+ tex = open(temp.name).read().decode('utf-8')
+ print tex
+
+ # Check contributor list.
+ editors = re.search(ur'\\def\\editors\{'
+ ur'Opracowanie redakcyjne i przypisy: ([^}]*?)\.\s*\}', tex)
+ assert_equal(editors.group(1),
+ u"Adam Fikcyjny, Aleksandra Sekuła, Olga Sutkowska")
# from nose.tools import set_trace; set_trace()
assert pi.type[0] == u"Image"
- assert pi.mime_type == u'image/png' == wlp.mime_type
+ assert pi.mime_type == u'image/jpeg' == wlp.mime_type
assert wlp.slug == 'angelus-novus'
assert path.exists(wlp.image_path)