Some prelim work on builder api.
[librarian.git] / src / librarian / builders / txt.py
1 # This file is part of Librarian, licensed under GNU Affero GPLv3 or later.
2 # Copyright © Fundacja Wolne Lektury. See NOTICE for more information.
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_margin(self, margin):
19         if margin:
20             if self.pieces:
21                 self.pieces[-1] = self.pieces[-1].rstrip(' ')
22             if margin > self.current_margin:
23                 self.pieces.append('\r\n' * (margin - self.current_margin))
24                 self.current_margin = margin
25                 self.starting_block = True
26
27     def push_text(self, text, prepared=False):
28         if text:
29             if self.starting_block and not prepared:
30                 text = text.lstrip()
31             self.pieces.append(text)
32             self.current_margin = 0
33             if not prepared:
34                 self.starting_block = False
35
36
37 class TxtBuilder:
38     """
39     """
40     build_method_fn = 'txt_build'
41     file_extension = "txt"
42     identifier = "txt"
43     after_child_fn = 'txt_after_child'
44
45     debug = False
46     orphans = False
47     normalize_whitespace = True
48     
49     default_license_description = {
50         "pol": (
51             "Wszystkie zasoby Wolnych Lektur możesz swobodnie wykorzystywać, "
52             "publikować i rozpowszechniać pod warunkiem zachowania warunków "
53             "licencji i zgodnie z Zasadami wykorzystania Wolnych Lektur.\n"
54             "Ten utwór jest w domenie publicznej.\n"
55             "Wszystkie materiały dodatkowe (przypisy, motywy literackie) są "
56             "udostępnione na Licencji Wolnej Sztuki 1.3: "
57             "https://artlibre.org/licence/lal/pl/\n"
58             "Fundacja Wolne Lektury zastrzega sobie prawa do wydania "
59             "krytycznego zgodnie z art. Art.99(2) Ustawy o prawach autorskich "
60             "i prawach pokrewnych.\nWykorzystując zasoby z Wolnych Lektur, "
61             "należy pamiętać o zapisach licencji oraz zasadach, które "
62             "spisaliśmy w Zasadach wykorzystania Wolnych Lektur: "
63             "https://wolnelektury.pl/info/zasady-wykorzystania/\nZapoznaj "
64             "się z nimi, zanim udostępnisz dalej nasze książki."
65         )
66     }
67     license_description = {
68         "pol": (
69             #"Ten utwór jest udostępniony na licencji {meta.license_description}: \n{meta.license}",
70             "Wszystkie zasoby Wolnych Lektur możesz swobodnie wykorzystywać, "
71             "publikować i rozpowszechniać pod warunkiem zachowania warunków "
72             "licencji i zgodnie z Zasadami wykorzystania Wolnych Lektur.\n"
73             "Ten utwór jest jest udostępniony na licencji {meta.license_description} ({meta.license}). "
74             "Wszystkie materiały dodatkowe (przypisy, motywy literackie) są "
75             "udostępnione na Licencji Wolnej Sztuki 1.3: "
76             "https://artlibre.org/licence/lal/pl/\n"
77             "Fundacja Wolne Lektury zastrzega sobie prawa do wydania "
78             "krytycznego zgodnie z art. Art.99(2) Ustawy o prawach autorskich "
79             "i prawach pokrewnych.\nWykorzystując zasoby z Wolnych Lektur, "
80             "należy pamiętać o zapisach licencji oraz zasadach, które "
81             "spisaliśmy w Zasadach wykorzystania Wolnych Lektur: "
82             "https://wolnelektury.pl/info/zasady-wykorzystania/\nZapoznaj "
83             "się z nimi, zanim udostępnisz dalej nasze książki."
84         )
85     }
86
87     def __init__(self, base_url=None):
88         self.fragments = {
89             None: TxtFragment(),
90             'header': TxtFragment()
91         }
92         self.current_fragments = [self.fragments[None]]
93
94     def enter_fragment(self, fragment):
95         self.current_fragments.append(self.fragments[fragment])
96
97     def exit_fragment(self):
98         self.current_fragments.pop()
99         
100     def push_text(self, text, prepared=False):
101         self.current_fragments[-1].push_text(text, prepared=prepared)
102
103     def push_margin(self, margin):
104         self.current_fragments[-1].push_margin(margin)
105         
106     def build(self, document, raw_text=False, **kwargs):
107         document.tree.getroot().txt_build(self)
108         meta = document.meta
109
110         self.enter_fragment('header')
111         if meta.translators:
112             self.push_text("tłum. ")
113             self.push_text(
114                 ", ".join(
115                     translator.readable()
116                     for translator in meta.translators
117                 )
118             )
119             self.push_margin(2)
120
121         if meta.isbn_txt:
122             self.push_margin(2)
123             isbn = meta.isbn_txt
124             if isbn.startswith(('ISBN-' , 'ISBN ')):
125                 isbn = isbn[5:]
126             self.push_text('ISBN {isbn}'.format(isbn=isbn))
127             #builder.push_margin(5)
128
129         self.push_margin(4)
130         self.exit_fragment()
131         
132         text = ''.join(self.fragments[None].pieces).lstrip()
133
134         if raw_text:
135             result = text
136         else:
137             text = ''.join(self.fragments['header'].pieces) +  text
138
139             if meta.license:
140                 license_description = self.license_description['pol'].format(meta=meta)
141             else:
142                 license_description = self.default_license_description['pol']
143
144             if meta.source_name:
145                 source = "\n\nTekst opracowany na podstawie: " + meta.source_name
146             else:
147                 source = ''
148
149             contributors = ', '.join(
150                 person.readable()
151                 for person in sorted(set(
152                     p for p in (
153                         meta.technical_editors + meta.editors
154                     ) if p))
155             )
156             if contributors:
157                 contributors = (
158                     "\n\nOpracowanie redakcyjne i przypisy: %s."
159                     % contributors
160                 )
161
162             funders = ', '.join(meta.funders)
163             if funders:
164                 funders = "\n\nPublikację wsparli i wsparły: %s." % funders
165
166             isbn = getattr(meta, 'isbn_txt', None)
167             if isbn:
168                 isbn = '\n\n' + isbn
169             else:
170                 isbn = ''
171                 
172             result = TEMPLATE % {
173                 "text": text,
174                 "description": meta.description,
175                 "url": meta.url,
176                 "license_description": license_description,
177                 "source": source,
178                 "contributors": contributors,
179                 "funders": funders,
180                 "publisher":  '\n\nWydawca: ' + ', '.join(meta.publisher),
181                 "isbn": isbn,
182             }
183
184         result = '\r\n'.join(result.splitlines()) + '\r\n'
185         return OutputFile.from_bytes(result.encode('utf-8'))