New Element-based builder API (WiP).
[librarian.git] / src / librarian / builders / txt.py
1 # coding: utf-8
2 from __future__ import unicode_literals
3
4 import io
5 from librarian import OutputFile, get_resource
6
7
8 with io.open(get_resource("res/text/template.txt")) as f:
9     TEMPLATE = f.read()
10
11
12 class TxtFragment:
13     def __init__(self):
14         self.pieces = []
15         self.current_margin = 0
16         self.starting_block = True
17
18     def push_legacy_margin(self, margin):
19         if margin:
20             if self.pieces:
21                 self.pieces[-1] = self.pieces[-1].rstrip(' ')
22             self.pieces.append('\r\n' * margin)
23             self.current_margin += margin
24             self.starting_block = True
25         
26     def push_margin(self, margin):
27         if margin:
28             if self.pieces:
29                 self.pieces[-1] = self.pieces[-1].rstrip(' ')
30             if margin > self.current_margin:
31                 self.pieces.append('\r\n' * (margin - self.current_margin))
32                 self.current_margin = margin
33                 self.starting_block = True
34
35     def push_text(self, text, prepared=False):
36         if text:
37             if self.starting_block and not prepared:
38                 text = text.lstrip()
39             self.pieces.append(text)
40             self.current_margin = 0
41             if not prepared:
42                 self.starting_block = False
43
44
45 class TxtBuilder:
46     """
47     """
48     file_extension = "txt"
49     identifier = "txt"
50
51     default_license_description = {
52         "pol": (
53             "Ten utwór nie jest objęty majątkowym prawem autorskim "
54             "i znajduje się w domenie publicznej, co oznacza że "
55             "możesz go swobodnie wykorzystywać, publikować "
56             "i rozpowszechniać. Jeśli utwór opatrzony jest "
57             "dodatkowymi materiałami (przypisy, motywy literackie "
58             "etc.), które podlegają prawu autorskiemu, to te "
59             "dodatkowe materiały udostępnione są na licencji "
60             "Creative Commons Uznanie Autorstwa – Na Tych Samych "
61             "Warunkach 3.0 PL "
62             "(http://creativecommons.org/licenses/by-sa/3.0/)"
63         )
64     }
65     license_description = {
66         "pol": "Ten utwór jest udostępniony na licencji {meta.license_description}: \n{meta.license}",
67     }
68
69     def __init__(self):
70         self.fragments = {
71             None: TxtFragment(),
72             'header': TxtFragment()
73         }
74         self.current_fragments = [self.fragments[None]]
75
76     def enter_fragment(self, fragment):
77         self.current_fragments.append(self.fragments[fragment])
78
79     def exit_fragment(self):
80         self.current_fragments.pop()
81         
82     def push_text(self, text, prepared=False):
83         self.current_fragments[-1].push_text(text, prepared=prepared)
84
85     def push_margin(self, margin):
86         self.current_fragments[-1].push_margin(margin)
87         
88     def push_legacy_margin(self, margin, where=None):
89         self.current_fragments[-1].push_legacy_margin(margin)
90         
91     def build(self, document, raw_text=False):
92         document.tree.getroot().txt_build(self)
93         meta = document.meta
94
95         self.enter_fragment('header')
96         if meta.translators:
97             self.push_text("tłum. ", 'header')
98             for translator in meta.translators:
99                 self.push_text(translator.readable())
100             #builder.push_margin(2)
101             self.push_legacy_margin(1)
102
103         if meta.isbn_txt:
104             #builder.push_margin(2)
105             self.push_legacy_margin(1)
106             isbn = meta.isbn_txt
107             if isbn.startswith(('ISBN-' , 'ISBN ')):
108                 isbn = isbn[5:]
109             self.push_text('ISBN {isbn}'.format(isbn=isbn))
110             #builder.push_margin(5)
111
112         #builder.push_margin(4)
113         self.push_legacy_margin(1)
114         self.exit_fragment()
115         
116         text = ''.join(self.fragments['header'].pieces) +  ''.join(self.fragments[None].pieces)
117
118         if raw_text:
119             result = text
120         else:
121             if meta.license:
122                 license_description = self.license_description['pol'].format(meta=meta)
123             else:
124                 license_description = self.default_license_description['pol']
125
126             if meta.source_name:
127                 source = "\n\nTekst opracowany na podstawie: " + meta.source_name
128             else:
129                 source = ''
130
131             contributors = ', '.join(
132                 person.readable()
133                 for person in sorted(set(
134                     p for p in (
135                         meta.technical_editors + meta.editors
136                     ) if p))
137             )
138             if contributors:
139                 contributors = (
140                     "\n\nOpracowanie redakcyjne i przypisy: %s."
141                     % contributors
142                 )
143
144             funders = ', '.join(meta.funders)
145             if funders:
146                 funders = u"\n\nPublikację wsparli i wsparły: %s." % funders
147
148             isbn = getattr(meta, 'isbn_txt', None)
149             if isbn:
150                 isbn = '\n\n' + isbn
151             else:
152                 isbn = ''
153                 
154             result = TEMPLATE % {
155                 "text": text,
156                 "description": meta.description,
157                 "url": meta.url,
158                 "license_description": license_description,
159                 "source": source,
160                 "contributors": contributors,
161                 "funders": funders,
162                 "publisher":  '\n\nWydawca: ' + ', '.join(meta.publisher),
163                 "isbn": isbn,
164             }
165
166         result = '\r\n'.join(result.splitlines()) + '\r\n'
167         return OutputFile.from_bytes(result.encode('utf-8'))