Better handling of multipart DAISY.
[librarian.git] / src / librarian / fb2.py
1 # -*- coding: utf-8 -*-
2 #
3 # This file is part of Librarian, licensed under GNU Affero GPLv3 or later.
4 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
5 #
6 from __future__ import unicode_literals
7
8 import os.path
9 from copy import deepcopy
10 from lxml import etree
11 import six
12
13 from librarian import functions, OutputFile
14 from .epub import replace_by_verse
15
16
17 functions.reg_substitute_entities()
18 functions.reg_person_name()
19
20
21 def sectionify(tree):
22     """Finds section headers and adds a tree of _section tags."""
23     sections = [
24         'naglowek_czesc',
25         'naglowek_akt', 'naglowek_rozdzial', 'naglowek_scena',
26         'naglowek_podrozdzial']
27     section_level = dict((v, k) for (k, v) in enumerate(sections))
28
29     # We can assume there are just subelements an no text at section level.
30     for level, section_name in reversed(list(enumerate(sections))):
31         for header in tree.findall('//' + section_name):
32             section = header.makeelement("_section")
33             header.addprevious(section)
34             section.append(header)
35             sibling = section.getnext()
36             while (sibling is not None and
37                     section_level.get(sibling.tag, 1000) > level):
38                 section.append(sibling)
39                 sibling = section.getnext()
40
41
42 def transform(wldoc, verbose=False,
43               cover=None, flags=None):
44     """ produces a FB2 file
45
46     cover: a cover.Cover object or True for default
47     flags: less-advertising, working-copy
48     """
49
50     document = deepcopy(wldoc)
51     del wldoc
52
53     if flags:
54         for flag in flags:
55             document.edoc.getroot().set(flag, 'yes')
56
57     document.clean_ed_note()
58     document.clean_ed_note('abstrakt')
59
60     style_filename = os.path.join(os.path.dirname(__file__), 'fb2/fb2.xslt')
61     style = etree.parse(style_filename)
62
63     replace_by_verse(document.edoc)
64     sectionify(document.edoc)
65
66     result = document.transform(style)
67
68     return OutputFile.from_bytes(six.text_type(result).encode('utf-8'))
69
70 # vim:et