From 6d65ed2b0c5f9f6df14de211ea2bf1de0a5dac70 Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Wed, 19 Jan 2011 15:15:48 +0100 Subject: [PATCH 01/16] book2html generates full page --- librarian/html.py | 6 +- librarian/xslt/book2html.xslt | 809 +++++++++++++++++----------------- scripts/book2html | 2 +- 3 files changed, 416 insertions(+), 401 deletions(-) diff --git a/librarian/html.py b/librarian/html.py index 9401a01..4e9abd0 100644 --- a/librarian/html.py +++ b/librarian/html.py @@ -30,7 +30,7 @@ def html_has_content(text): return etree.ETXPath('//p|//{%(ns)s}p|//h1|//{%(ns)s}h1' % {'ns': str(XHTMLNS)})(text) def transform(input, output_filename=None, is_file=True, \ - parse_dublincore=True, stylesheet='legacy', options={}): + parse_dublincore=True, stylesheet='legacy', options={}, flags=None): """Transforms file input_filename in XML to output_filename in XHTML. If output_filename is None, returns an XML, @@ -49,6 +49,10 @@ def transform(input, output_filename=None, is_file=True, \ document = WLDocument.from_string(input, True, \ parse_dublincore=parse_dublincore) + if flags: + for flag in flags: + document.edoc.getroot().set(flag, 'yes') + document.clean_ed_note() result = document.transform(style, **options) diff --git a/librarian/xslt/book2html.xslt b/librarian/xslt/book2html.xslt index 752eade..0f9b665 100755 --- a/librarian/xslt/book2html.xslt +++ b/librarian/xslt/book2html.xslt @@ -1,408 +1,419 @@ - -
- - -
-

Przypisy

- -
- - [] - - -

-
- - - -
-
-
-
-
-
- + + + + + Książka z serwisu WolneLektury.pl + + + + + + + + + + + + +
+ + +
+ + +
+

Przypisy

+ +
+ + [] + + +

+
+ + + +
+
+
+
+
+
@@ -511,16 +522,16 @@
- + - + - @@ -530,7 +541,7 @@ - +
diff --git a/scripts/book2html b/scripts/book2html index f7eaf63..a48aa64 100755 --- a/scripts/book2html +++ b/scripts/book2html @@ -35,7 +35,7 @@ if __name__ == '__main__': output_filename = os.path.splitext(input_filename)[0] + '.html' try: - html.transform(input_filename, output_filename, parse_dublincore=options.parse_dublincore) + html.transform(input_filename, output_filename, parse_dublincore=options.parse_dublincore, flags=('full-page',)) except ParseError, e: print '%(file)s:%(name)s:%(message)s' % { 'file': input_filename, -- 2.20.1 From a2f8ee881d66601e9cb714069dc88d3ed9703db6 Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Wed, 19 Jan 2011 16:47:33 +0100 Subject: [PATCH 02/16] #961: full info in all formats; epub: less-advertising flag some fixes --- librarian/epub.py | 8 ++- librarian/epub/style.css | 22 ++++++++ librarian/epub/xsltLast.xsl | 29 +++++++---- librarian/epub/xsltScheme.xsl | 4 +- librarian/epub/xsltTitle.xsl | 24 ++++++--- librarian/html.py | 1 + librarian/pdf.py | 20 +++---- librarian/pdf/wl.sty | 60 ++++++++++++++------- librarian/pdf/wl2tex.xslt | 98 +++++++++++++++++++++++++++-------- librarian/text.py | 25 ++++++--- librarian/xslt/book2html.xslt | 35 ++++++++++++- librarian/xslt/book2txt.xslt | 36 +++++++++---- scripts/book2partner | 3 +- 13 files changed, 275 insertions(+), 90 deletions(-) diff --git a/librarian/epub.py b/librarian/epub.py index ad84ab0..527d050 100644 --- a/librarian/epub.py +++ b/librarian/epub.py @@ -265,7 +265,8 @@ def transform_chunk(chunk_xml, chunk_no, annotations, empty=False, _empty_html_s return output_html, toc, chars -def transform(provider, slug=None, file_path=None, output_file=None, output_dir=None, make_dir=False, verbose=False, sample=None, cover_fn=None): +def transform(provider, slug=None, file_path=None, output_file=None, output_dir=None, make_dir=False, verbose=False, + sample=None, cover_fn=None, flags=None): """ produces a EPUB file provider: a DocProvider @@ -275,6 +276,7 @@ def transform(provider, slug=None, file_path=None, output_file=None, output_dir= make_dir: writes output to //.epub instead of /.epub sample=n: generate sample e-book (with at least n paragraphs) cover_fn: function(author, title) -> cover image + flags: less-advertising, """ def transform_file(input_xml, chunk_counter=1, first=True, sample=None): @@ -355,6 +357,10 @@ def transform(provider, slug=None, file_path=None, output_file=None, output_dir= raise ValueError('either slug or file_path should be specified') input_xml = etree.parse(provider[slug]) + if flags: + for flag in flags: + input_xml.getroot().set(flag, 'yes') + metadata = input_xml.find('.//'+RDFNS('Description')) if metadata is None: raise NoDublinCore('Document has no DublinCore - which is required.') diff --git a/librarian/epub/style.css b/librarian/epub/style.css index 55ac117..fd98f07 100644 --- a/librarian/epub/style.css +++ b/librarian/epub/style.css @@ -183,6 +183,28 @@ p margin-bottom: 0.25em; } +.intitle +{ + margin: 0; + text-align: center; + font-weight: bold; + + font-size: 1.5em; + line-height: 1.5em; + margin-bottom: 0.25em; +} + +.insubtitle +{ + margin: 0; + text-align: center; + font-weight: bold; + + font-size: 1em; + line-height: 1.5em; + margin-bottom: 0.25em; +} + .collection { margin: 0; diff --git a/librarian/epub/xsltLast.xsl b/librarian/epub/xsltLast.xsl index 6cb2748..3949878 100644 --- a/librarian/epub/xsltLast.xsl +++ b/librarian/epub/xsltLast.xsl @@ -33,12 +33,12 @@ Ten utwór nie jest chroniony prawem autorskim i znajduje się w domenie - publicznej, co oznacza, że możesz go swobodnie wykorzystywać, publikować + publicznej, co oznacza że możesz go swobodnie wykorzystywać, publikować i rozpowszechniać. Jeśli utwór opatrzony jest dodatkowymi materiałami - (przypisy, motywy literackie etc.) które podlegają prawu autorskiemu, to + (przypisy, motywy literackie etc.), które podlegają prawu autorskiemu, to te dodatkowe materiały udostępnione są na licencji Creative Commons - Uznanie Autorstwa - Na Tych Samych Warunkach 3.0 PL. + Uznanie Autorstwa – Na Tych Samych Warunkach 3.0 PL.

@@ -54,16 +54,15 @@

-

Na podstawie:

+

Tekst opracowany na podstawie:

- -

- Opracowanie redakcyjne i przypisy: - -

+ +

+ +

 

Plik wygenerowany dnia . @@ -78,6 +77,18 @@ + + +

+ Opracowanie redakcyjne i przypisy: + + , + + . +

+
+
+
diff --git a/librarian/epub/xsltScheme.xsl b/librarian/epub/xsltScheme.xsl index 8b384c3..1543268 100644 --- a/librarian/epub/xsltScheme.xsl +++ b/librarian/epub/xsltScheme.xsl @@ -94,7 +94,7 @@ -

+

@@ -102,7 +102,7 @@ -

+

diff --git a/librarian/epub/xsltTitle.xsl b/librarian/epub/xsltTitle.xsl index 347f038..53bbb1a 100644 --- a/librarian/epub/xsltTitle.xsl +++ b/librarian/epub/xsltTitle.xsl @@ -34,9 +34,10 @@

 

- + - +

+

- Utwór opracowany został w ramach projektu Wolne Lektury przez Fundację Nowoczesna Polska. + Utwór opracowany został w ramach projektu Wolne Lektury przez fundację Nowoczesna Polska.

- tłum. -

+ + +

+ tłum. + + , + + +

+
diff --git a/librarian/html.py b/librarian/html.py index 4e9abd0..1f0615f 100644 --- a/librarian/html.py +++ b/librarian/html.py @@ -16,6 +16,7 @@ from librarian import functions from lxml.etree import XMLSyntaxError, XSLTApplyError functions.reg_substitute_entities() +functions.reg_person_name() STYLESHEETS = { 'legacy': 'xslt/book2html.xslt', diff --git a/librarian/pdf.py b/librarian/pdf.py index baf7be4..f8a4d73 100644 --- a/librarian/pdf.py +++ b/librarian/pdf.py @@ -128,13 +128,15 @@ def hack_motifs(doc): def parse_creator(doc): - """ find all dc:creator tags and add dc:creator_parsed with forenames first """ - for creator in doc.findall('//'+DCNS('creator')): - p = Person.from_text(creator.text) - creator_parsed = deepcopy(creator) - creator_parsed.tag = DCNS('creator_parsed') - creator_parsed.text = ' '.join(p.first_names + (p.last_name,)) - creator.getparent().insert(0, creator_parsed) + """ find all dc:creator and dc.contributor tags and add *_parsed versions with forenames first """ + for person in doc.xpath("|".join('//dc:'+(tag) for tag in ( + 'creator', 'contributor.translator', 'contributor.editor', 'contributor.technical_editor')), + namespaces = {'dc': str(DCNS)})[::-1]: + p = Person.from_text(person.text) + person_parsed = deepcopy(person) + person_parsed.tag = person.tag + '_parsed' + person_parsed.text = p.readable() + person.getparent().insert(0, person_parsed) def get_stylesheet(name): @@ -286,9 +288,9 @@ def load_including_children(provider, slug=None, uri=None, file_path=None): parse_dublincore=True) f.close() - + print document.book_info for child_uri in document.book_info.parts: + print child_uri child = load_including_children(provider, uri=child_uri) document.edoc.getroot().append(child.edoc.getroot()) - return document diff --git a/librarian/pdf/wl.sty b/librarian/pdf/wl.sty index a7a97ba..3a8016f 100644 --- a/librarian/pdf/wl.sty +++ b/librarian/pdf/wl.sty @@ -111,36 +111,45 @@ Letters={SmallCaps,UppercaseSmallCaps} \href{http://www.wolnelektury.pl}{\xbox{\includegraphics[width=\textwidth]{wl-logo.png}}} \end{minipage} \begin{minipage}[t]{.65\textwidth}\vspace{0pt} - Na podstawie: \sourceinfo + \href{\bookurl}{Ta lektura}, podobnie jak tysiące innych, jest dostępna on-line na stronie + \href{http://www.wolnelektury.pl/}{wolnelektury.pl}. \vspace{.5em} - Wersja lektury on-line dostępna jest \href{\bookurl}{na stronie wolnelektury.pl}. - \vspace{.5em} - - \rightsinfo - - \vspace{.6em} + Utwór opracowany został w ramach projektu \href{http://www.wolnelektury.pl/}{Wolne Lektury} + przez \href{http://nowoczesnapolska.org.pl}{fundację Nowoczesna Polska}. \end{minipage} \noindent \rule{\linewidth}{0.4pt} \vspace{.6em} \color{black} + } +} + +\newcommand{\editorialsection}{ + \begin{figure}[b!] + { + \footnotesize + \color{theme} + \noindent \rule{\linewidth}{0.4pt} -% \begin{figure}[b!] -% \footnotesize -% \color{theme} -% \noindent \rule{\linewidth}{0.4pt} + \rightsinfo + \vspace{.6em} -% Szkolna biblioteka internetowa Wolne Lektury tworzona jest dzięki pracy Wolontariuszy, ale to osoby -% zatrudnione w~FNP będą musiały wymyślić, co powinno zostać napisane w~tym miejscu. Można zupełnie usunąć -% tę sekcję, ale autor konwertera chciał się popisać, że umie coś takiego zrobić. -% \color{black} -% \end{figure} - } + \sourceinfo + + \description + \vspace{.6em} + + Opracowanie redakcyjne i przypisy: \editors. + + \color{black} + } + \end{figure} } + \newcommand{\typosubsubsection}[1]{% {\textsc{#1}} } @@ -162,6 +171,12 @@ Letters={Uppercase} %{\addfontfeature{Scale=2.0, FakeStretch=0.98, LetterSpace=-2.0}\emph{#1}} } + +\newcommand{\tytul}[1]{% +#1% +\vspace{1em}% +} + \newcommand{\nazwapodutworu}[1]{% \section*{\typosection{#1}}% } @@ -170,14 +185,23 @@ Letters={Uppercase} \subsection*{\typosubsection{#1}}% } +\newcommand{\dzielonadrzedne}[1]{% +\subsection*{\typosubsubsection{#1}}% +} + \newcommand{\nazwautworu}[1]{% \section*{\typosection{#1}}% } \newcommand{\podtytul}[1]{% -\subsection*{\typosubsection{#1}}% +\subsection*{\typosubsubsection{#1}}% } +\newcommand{\translator}[1]{% +\subsection*{\typosubsubsection{tłum. #1}}% +} + + \newcommand{\powiesc}[1]{#1} \newcommand{\opowiadanie}[1]{#1} \newcommand{\lirykal}[1]{#1} diff --git a/librarian/pdf/wl2tex.xslt b/librarian/pdf/wl2tex.xslt index c3abdd6..4ca109e 100644 --- a/librarian/pdf/wl2tex.xslt +++ b/librarian/pdf/wl2tex.xslt @@ -46,35 +46,46 @@ - + + - + + + + + + - + + + - - + + + + - + + @@ -90,21 +101,33 @@ - - - - - - - \def\sourceinfo{} + \def\authors{} + \author{\authors} + \title{} + \def\translatorsline{} + \def\bookurl{} - \def\rightsinfo{Ten utwór nie jest chroniony prawem autorskim i~znajduje się w~domenie publicznej, - co oznacza, że możesz go swobodnie wykorzystywać, publikować i~rozpowszechniać.} + + \def\rightsinfo{Ten utwór nie jest chroniony prawem autorskim i~znajduje się w~domenie + publicznej, co oznacza że możesz go swobodnie wykorzystywać, publikować + i~rozpowszechniać. Jeśli utwór opatrzony jest dodatkowymi materiałami + (przypisy, motywy literackie etc.), które podlegają prawu autorskiemu, to + te dodatkowe materiały udostępnione są na licencji + \href{http://creativecommons.org/licenses/by-sa/3.0/}{Creative Commons + Uznanie Autorstwa – Na Tych Samych Warunkach 3.0 PL}.} \def\rightsinfo{Ten utwór jest udostepniony na licencji \href{}{}.} + + \def\sourceinfo{ + + Tekst opracowany na podstawie: + \vspace{.6em} + } + \def\description{} + \def\editors{} @@ -129,12 +152,11 @@
- - - + + @@ -177,15 +199,20 @@ - - - - + + + + + + + + match="naglowek_akt|naglowek_czesc|srodtytul|naglowek_osoba|naglowek_podrozdzial|naglowek_scena|naglowek_rozdzial|miejsce_czas|didaskalia|lista_osoba|akap|akap_dialog|akap_cd|motto_podpis|naglowek_listy"> @@ -305,6 +332,31 @@ + + + , + + + + + + + , + + + + + + + + + , + + + + + + diff --git a/librarian/text.py b/librarian/text.py index e1ca26b..64c956e 100644 --- a/librarian/text.py +++ b/librarian/text.py @@ -11,20 +11,23 @@ import os functions.reg_substitute_entities() functions.reg_wrap_words() functions.reg_strip() +functions.reg_person_name() TEMPLATE = u"""\ -Kodowanie znaków w dokumencie: UTF-8. ------ -%(description)s +%(text)s -%(license_description)s.%(source)s -Wersja lektury w opracowaniu merytorycznym i krytycznym (przypisy i motywy) dostępna jest na stronie %(url)s. ----- +Ta lektura, podobnie jak tysiące innych, dostępna jest na stronie wolnelektury.pl. +Wersja lektury w opracowaniu merytorycznym i krytycznym (przypisy i motywy) dostępna jest na stronie %(url)s. +Utwór opracowany został w ramach projektu Wolne Lektury przez fundację Nowoczesna Polska. +%(license_description)s.%(source)s -%(text)s +%(description)s + +Opracowanie redakcyjne i przypisy: %(contributors)s """ def transform(input_file, output_file, parse_dublincore=True, **options): @@ -40,28 +43,34 @@ def transform(input_file, output_file, parse_dublincore=True, **options): parsed_dc = dcparser.BookInfo.from_element(document.edoc) description = parsed_dc.description url = parsed_dc.url + license_description = parsed_dc.license_description license = parsed_dc.license if license: license_description = u"Ten utwór jest udostepniony na licencji %s: \n%s" % (license_description, license) else: - license_description = u"Ten utwór nie jest chroniony prawem autorskim i znajduje się w domenie publicznej, co oznacza, że możesz go swobodnie wykorzystywać, publikować i rozpowszechniać" + license_description = u"Ten utwór nie jest chroniony prawem autorskim i znajduje się w domenie publicznej, co oznacza że możesz go swobodnie wykorzystywać, publikować i rozpowszechniać. Jeśli utwór opatrzony jest dodatkowymi materiałami (przypisy, motywy literackie etc.), które podlegają prawu autorskiemu, to te dodatkowe materiały udostępnione są na licencji Creative Commons Uznanie Autorstwa – Na Tych Samych Warunkach 3.0 PL (http://creativecommons.org/licenses/by-sa/3.0/)" + source = parsed_dc.source_name if source: - source = "\n\nNa podstawie: " + source + source = "\n\nTekst opracowany na podstawie: " + source else: source = '' + + contributors = ', '.join(person.readable() for person in (parsed_dc.technical_editors + parsed_dc.editors)) else: description = 'Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl).' url = '*' * 10 license = "" license_description = "" source = "" + contributors = "" output_file.write((TEMPLATE % { 'description': description, 'url': url, 'license_description': license_description, 'text': unicode(result), 'source': source, + 'contributors': contributors, }).encode('utf-8')) diff --git a/librarian/xslt/book2html.xslt b/librarian/xslt/book2html.xslt index 0f9b665..682ed9b 100755 --- a/librarian/xslt/book2html.xslt +++ b/librarian/xslt/book2html.xslt @@ -6,7 +6,8 @@ --> + xmlns:wl="http://wolnelektury.pl/functions" + xmlns:dc="http://purl.org/dc/elements/1.1/" > @@ -100,7 +101,7 @@ } - #toc, #themes, #nota_red { + #toc, #themes, #nota_red, #info { position: fixed; left: 0em; top: 1.5em; @@ -148,6 +149,11 @@ position: inherit; } + #info p { + text-align: justify; + margin: 1.5em 0 0; + } + /* =================================================== */ /* = Common elements: headings, paragraphs and lines = */ /* =================================================== */ @@ -285,6 +291,13 @@ margin-top: -0.25em; } + span.translator { + font-size: 0.375em; + display: block; + line-height: 1.5em; + margin-top: 0.25em; + } + div.didaskalia { font-style: italic; margin: 0.5em 0 0 1.5em; @@ -426,6 +439,7 @@

+

@@ -662,6 +676,23 @@
+ + + + tłum. + + , + + + + + + + + + + + diff --git a/librarian/xslt/book2txt.xslt b/librarian/xslt/book2txt.xslt index 15438a5..604b8bd 100755 --- a/librarian/xslt/book2txt.xslt +++ b/librarian/xslt/book2txt.xslt @@ -6,7 +6,8 @@ --> + xmlns:wl="http://wolnelektury.pl/functions" + xmlns:dc="http://purl.org/dc/elements/1.1/" > @@ -17,11 +18,16 @@ - + + + + + + + - @@ -79,30 +85,28 @@ + - + - - + - - + - @@ -298,6 +302,20 @@ + + + tłum. + + + , + + + + + + + + diff --git a/scripts/book2partner b/scripts/book2partner index 6f2beac..786c2c2 100755 --- a/scripts/book2partner +++ b/scripts/book2partner @@ -101,7 +101,8 @@ def asbis(filenames, output_dir, verbose): except: pass outfile = os.path.join(output_dir, slug + '.epub') - epub.transform(provider, file_path=main_input, output_file=outfile, cover_fn=cover.asbis_cover) + epub.transform(provider, file_path=main_input, output_file=outfile, + cover_fn=cover.asbis_cover, flags=('less-advertising',)) except ParseError, e: print '%(file)s:%(name)s:%(message)s' % { 'file': main_input, -- 2.20.1 From 0fd2ed230ea6d53adb5e627731672c996485167b Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Mon, 24 Jan 2011 12:27:35 +0100 Subject: [PATCH 03/16] fixes #1060: sorted and unique editors' names tests fix --- librarian/dcparser.py | 5 +++ librarian/epub/xsltLast.xsl | 3 +- librarian/pdf.py | 2 +- librarian/pdf/wl.sty | 2 +- librarian/pdf/wl2tex.xslt | 12 ++++-- librarian/text.py | 8 ++-- .../text/asnyk_miedzy_nami_expected.html | 38 +++++++------------ .../files/text/asnyk_miedzy_nami_expected.txt | 32 ++++++++-------- tests/files/text/asnyk_miedzy_nami_nodc.txt | 0 tests/test_html.py | 2 +- tests/test_text.py | 12 +++--- 11 files changed, 58 insertions(+), 58 deletions(-) delete mode 100644 tests/files/text/asnyk_miedzy_nami_nodc.txt diff --git a/librarian/dcparser.py b/librarian/dcparser.py index 49a33d4..e2f91a0 100644 --- a/librarian/dcparser.py +++ b/librarian/dcparser.py @@ -44,6 +44,11 @@ class Person(object): def __eq__(self, right): return self.last_name == right.last_name and self.first_names == right.first_names + def __cmp__(self, other): + return cmp((self.last_name, self.first_names), (other.last_name, other.first_names)) + + def __hash__(self): + return hash((self.last_name, self.first_names)) def __unicode__(self): if len(self.first_names) > 0: diff --git a/librarian/epub/xsltLast.xsl b/librarian/epub/xsltLast.xsl index 3949878..0739606 100644 --- a/librarian/epub/xsltLast.xsl +++ b/librarian/epub/xsltLast.xsl @@ -81,7 +81,8 @@

Opracowanie redakcyjne i przypisy: - + + , . diff --git a/librarian/pdf.py b/librarian/pdf.py index f8a4d73..41de1b3 100644 --- a/librarian/pdf.py +++ b/librarian/pdf.py @@ -135,6 +135,7 @@ def parse_creator(doc): p = Person.from_text(person.text) person_parsed = deepcopy(person) person_parsed.tag = person.tag + '_parsed' + person_parsed.set('sortkey', person.text) person_parsed.text = p.readable() person.getparent().insert(0, person_parsed) @@ -288,7 +289,6 @@ def load_including_children(provider, slug=None, uri=None, file_path=None): parse_dublincore=True) f.close() - print document.book_info for child_uri in document.book_info.parts: print child_uri child = load_including_children(provider, uri=child_uri) diff --git a/librarian/pdf/wl.sty b/librarian/pdf/wl.sty index 3a8016f..897535e 100644 --- a/librarian/pdf/wl.sty +++ b/librarian/pdf/wl.sty @@ -142,7 +142,7 @@ Letters={SmallCaps,UppercaseSmallCaps} \description \vspace{.6em} - Opracowanie redakcyjne i przypisy: \editors. + \editors \color{black} } diff --git a/librarian/pdf/wl2tex.xslt b/librarian/pdf/wl2tex.xslt index 4ca109e..c577313 100644 --- a/librarian/pdf/wl2tex.xslt +++ b/librarian/pdf/wl2tex.xslt @@ -340,10 +340,14 @@ - - , - - + + Opracowanie redakcyjne i przypisy: + + + , + + . + diff --git a/librarian/text.py b/librarian/text.py index 64c956e..bcb031d 100644 --- a/librarian/text.py +++ b/librarian/text.py @@ -25,9 +25,7 @@ Utwór opracowany został w ramach projektu Wolne Lektury przez fundację Nowocz %(license_description)s.%(source)s -%(description)s - -Opracowanie redakcyjne i przypisy: %(contributors)s +%(description)s%(contributors)s """ def transform(input_file, output_file, parse_dublincore=True, **options): @@ -57,7 +55,9 @@ def transform(input_file, output_file, parse_dublincore=True, **options): else: source = '' - contributors = ', '.join(person.readable() for person in (parsed_dc.technical_editors + parsed_dc.editors)) + contributors = ', '.join(person.readable() for person in sorted(set(parsed_dc.technical_editors + parsed_dc.editors))) + if contributors: + contributors = "\n\nOpracowanie redakcyjne i przypisy: %s" % contributors else: description = 'Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl).' url = '*' * 10 diff --git a/tests/files/text/asnyk_miedzy_nami_expected.html b/tests/files/text/asnyk_miedzy_nami_expected.html index 456aaf6..6bc7649 100644 --- a/tests/files/text/asnyk_miedzy_nami_expected.html +++ b/tests/files/text/asnyk_miedzy_nami_expected.html @@ -1,4 +1,4 @@ -

+

Spis treści

    @@ -8,38 +8,26 @@ Miłość platoniczna

    1Między nami nic nie było!

    -

    -Żadnych zwierzeń, wyznań żadnych!

    -

    -Nic nas z sobą nie łączyło —

    -

    -Prócz wiosennych marzeń zdradnych;

    +

    Żadnych zwierzeń, wyznań żadnych!

    +

    Nic nas z sobą nie łączyło —

    +

    Prócz wiosennych marzeń zdradnych;

    5NaturaPrócz tych woni, barw i blasków,

    -

    -Unoszących się w przestrzeni;

    -

    -Prócz szumiących śpiewem lasków

    -

    -I tej świeżej łąk zieleni;

    +

    Unoszących się w przestrzeni;

    +

    Prócz szumiących śpiewem lasków

    +

    I tej świeżej łąk zieleni;

    Prócz tych kaskad i potoków,

    -

    10 -Zraszających każdy parów,

    -

    -Prócz girlandy tęcz, obłoków,

    -

    -Prócz natury słodkich czarów;

    +

    10Zraszających każdy parów,

    +

    Prócz girlandy tęcz, obłoków,

    +

    Prócz natury słodkich czarów;

    Prócz tych wspólnych, jasnych zdrojów,

    -

    -Z których serce zachwyt piło;

    -

    15 -Prócz pierwiosnków i powojów,—

    -

    -Między nami nic nie było!

    +

    Z których serce zachwyt piło;

    +

    15Prócz pierwiosnków i powojów,—

    +

    Między nami nic nie było!

    diff --git a/tests/files/text/asnyk_miedzy_nami_expected.txt b/tests/files/text/asnyk_miedzy_nami_expected.txt index 4441c70..70c3185 100644 --- a/tests/files/text/asnyk_miedzy_nami_expected.txt +++ b/tests/files/text/asnyk_miedzy_nami_expected.txt @@ -1,18 +1,3 @@ -Kodowanie znaków w dokumencie: UTF-8. ------ -Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN. - -Ten utwór nie jest chroniony prawem autorskim i znajduje się w domenie publicznej, co oznacza, że możesz go swobodnie wykorzystywać, publikować i rozpowszechniać. - -Na podstawie: (Asnyk, Adam) El...y (1838-1897), Poezye, t. 3, Gebethner i Wolff, wyd. nowe poprzedzone słowem wstępnym St. Krzemińskiego, Warszawa, 1898 - -Wersja lektury w opracowaniu merytorycznym i krytycznym (przypisy i motywy) dostępna jest na stronie http://wolnelektury.pl/katalog/lektura/miedzy-nami-nic-nie-bylo. ------ - - - - - Adam Asnyk Między nami nic nie było @@ -38,3 +23,20 @@ Prócz tych wspólnych, jasnych zdrojów, Z których serce zachwyt piło; Prócz pierwiosnków i powojów,— Między nami nic nie było! + + + + +----- +Ta lektura, podobnie jak tysiące innych, dostępna jest na stronie wolnelektury.pl. +Wersja lektury w opracowaniu merytorycznym i krytycznym (przypisy i motywy) dostępna jest na stronie http://wolnelektury.pl/katalog/lektura/miedzy-nami-nic-nie-bylo. + +Utwór opracowany został w ramach projektu Wolne Lektury przez fundację Nowoczesna Polska. + +Ten utwór nie jest chroniony prawem autorskim i znajduje się w domenie publicznej, co oznacza że możesz go swobodnie wykorzystywać, publikować i rozpowszechniać. Jeśli utwór opatrzony jest dodatkowymi materiałami (przypisy, motywy literackie etc.), które podlegają prawu autorskiemu, to te dodatkowe materiały udostępnione są na licencji Creative Commons Uznanie Autorstwa – Na Tych Samych Warunkach 3.0 PL (http://creativecommons.org/licenses/by-sa/3.0/). + +Tekst opracowany na podstawie: (Asnyk, Adam) El...y (1838-1897), Poezye, t. 3, Gebethner i Wolff, wyd. nowe poprzedzone słowem wstępnym St. Krzemińskiego, Warszawa, 1898 + +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 diff --git a/tests/files/text/asnyk_miedzy_nami_nodc.txt b/tests/files/text/asnyk_miedzy_nami_nodc.txt deleted file mode 100644 index e69de29..0000000 diff --git a/tests/test_html.py b/tests/test_html.py index 4fbbaad..5187e06 100644 --- a/tests/test_html.py +++ b/tests/test_html.py @@ -29,7 +29,7 @@ def test_transform(): def test_no_dublincore(): html.transform( get_fixture('text', 'asnyk_miedzy_nami_nodc.xml'), - get_fixture('text', 'asnyk_miedzy_nami_nodc.html'), + get_fixture('text', 'asnyk_miedzy_nami.html'), ) diff --git a/tests/test_text.py b/tests/test_text.py index 5b01718..7ff94ca 100644 --- a/tests/test_text.py +++ b/tests/test_text.py @@ -18,8 +18,8 @@ def test_transform(): expected_output_file_path = get_fixture('text', 'asnyk_miedzy_nami_expected.txt') text.transform( - get_fixture('text', 'asnyk_miedzy_nami.xml'), - output_file_path, + open(get_fixture('text', 'asnyk_miedzy_nami.xml')), + open(output_file_path, 'w'), ) assert_equal(file(output_file_path).read(), file(expected_output_file_path).read()) @@ -29,8 +29,8 @@ def test_transform(): @raises(NoDublinCore) def test_no_dublincore(): text.transform( - get_fixture('text', 'asnyk_miedzy_nami_nodc.xml'), - get_fixture('text', 'asnyk_miedzy_nami_nodc.txt'), + open(get_fixture('text', 'asnyk_miedzy_nami_nodc.xml')), + open(get_fixture('text', 'asnyk_miedzy_nami.txt'), 'w'), ) @@ -38,7 +38,7 @@ def test_no_dublincore(): def test_passing_parse_dublincore_to_transform(): """Passing parse_dublincore=False to transform omits DublinCore parsing.""" text.transform( - get_fixture('text', 'asnyk_miedzy_nami_nodc.xml'), - get_fixture('text', 'asnyk_miedzy_nami.txt'), + open(get_fixture('text', 'asnyk_miedzy_nami_nodc.xml')), + open(get_fixture('text', 'asnyk_miedzy_nami.txt'), 'w'), parse_dublincore=False, ) -- 2.20.1 From 5c8b83a904d5dd988c0bfd86729b91a1ac763164 Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Mon, 24 Jan 2011 16:25:31 +0100 Subject: [PATCH 04/16] fix for empty editors --- librarian/epub/xsltLast.xsl | 4 ++-- librarian/pdf.py | 2 ++ librarian/text.py | 3 ++- tests/files/text/asnyk_miedzy_nami.xml | 1 + 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/librarian/epub/xsltLast.xsl b/librarian/epub/xsltLast.xsl index 0739606..92f5be6 100644 --- a/librarian/epub/xsltLast.xsl +++ b/librarian/epub/xsltLast.xsl @@ -78,10 +78,10 @@ - +

    Opracowanie redakcyjne i przypisy: - + , diff --git a/librarian/pdf.py b/librarian/pdf.py index 41de1b3..5f28547 100644 --- a/librarian/pdf.py +++ b/librarian/pdf.py @@ -132,6 +132,8 @@ def parse_creator(doc): for person in doc.xpath("|".join('//dc:'+(tag) for tag in ( 'creator', 'contributor.translator', 'contributor.editor', 'contributor.technical_editor')), namespaces = {'dc': str(DCNS)})[::-1]: + if not person.text: + continue p = Person.from_text(person.text) person_parsed = deepcopy(person) person_parsed.tag = person.tag + '_parsed' diff --git a/librarian/text.py b/librarian/text.py index bcb031d..f5aafc1 100644 --- a/librarian/text.py +++ b/librarian/text.py @@ -55,7 +55,8 @@ def transform(input_file, output_file, parse_dublincore=True, **options): else: source = '' - contributors = ', '.join(person.readable() for person in sorted(set(parsed_dc.technical_editors + parsed_dc.editors))) + contributors = ', '.join(person.readable() for person in + sorted(set(p for p in (parsed_dc.technical_editors + parsed_dc.editors) if p))) if contributors: contributors = "\n\nOpracowanie redakcyjne i przypisy: %s" % contributors else: diff --git a/tests/files/text/asnyk_miedzy_nami.xml b/tests/files/text/asnyk_miedzy_nami.xml index d7ab4fc..36d8df6 100644 --- a/tests/files/text/asnyk_miedzy_nami.xml +++ b/tests/files/text/asnyk_miedzy_nami.xml @@ -6,6 +6,7 @@ Asnyk, Adam Między nami nic nie było + Sekuła, Aleksandra Sutkowska, Olga Fundacja Nowoczesna Polska -- 2.20.1 From 53acb1f3e125b31e3c0837a67bf0a4a9a29e4548 Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Mon, 24 Jan 2011 16:40:06 +0100 Subject: [PATCH 05/16] fix for empty dc tags --- librarian/dcparser.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/librarian/dcparser.py b/librarian/dcparser.py index e2f91a0..9faffe8 100644 --- a/librarian/dcparser.py +++ b/librarian/dcparser.py @@ -268,7 +268,8 @@ class BookInfo(object): if len(v) == 0: continue for x in v: e = etree.Element(field.uri) - e.text = unicode(x) + if x is not None: + e.text = unicode(x) description.append(e) else: e = etree.Element(field.uri) @@ -288,7 +289,7 @@ class BookInfo(object): if v is not None: if field.multiple: if len(v) == 0: continue - v = [ unicode(x) for x in v if v is not None ] + v = [ unicode(x) for x in v if x is not None ] else: v = unicode(v) @@ -304,7 +305,7 @@ class BookInfo(object): if v is not None: if field.multiple: if len(v) == 0: continue - v = [ unicode(x) for x in v if v is not None ] + v = [ unicode(x) for x in v if x is not None ] else: v = unicode(v) result[field.name] = v -- 2.20.1 From 6c0f71f581d5b8d9a519a6645f571f54b38afca8 Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Tue, 25 Jan 2011 16:27:59 +0100 Subject: [PATCH 06/16] fix for fragments extraction --- librarian/html.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/librarian/html.py b/librarian/html.py index 1f0615f..5f832e3 100644 --- a/librarian/html.py +++ b/librarian/html.py @@ -127,7 +127,13 @@ def extract_fragments(input_filename): open_fragments = {} closed_fragments = {} - for event, element in etree.iterparse(input_filename, events=('start', 'end')): + # iterparse would die on a HTML document + parser = etree.HTMLParser(encoding='utf-8') + buf = cStringIO.StringIO() + buf.write(etree.tostring(etree.parse(input_filename, parser).getroot()[0][0], encoding='utf-8')) + buf.seek(0) + + for event, element in etree.iterparse(buf, events=('start', 'end')): # Process begin and end elements if element.get('class', '') in ('theme-begin', 'theme-end'): if not event == 'end': continue # Process elements only once, on end event -- 2.20.1 From c69605017947202b0bbd0a2a2335cb37752141b9 Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Tue, 25 Jan 2011 16:37:05 +0100 Subject: [PATCH 07/16] #1038: workaround for ADE problem with small-caps --- librarian/epub/style.css | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/librarian/epub/style.css b/librarian/epub/style.css index fd98f07..70b05ae 100644 --- a/librarian/epub/style.css +++ b/librarian/epub/style.css @@ -344,10 +344,11 @@ em.author-emphasis letter-spacing: 0.1em; } -em.person +.person-list em.person { font-style: normal; - font-variant: small-caps; + /*font-variant: small-caps;*/ + text-transform: uppercase; } p.info -- 2.20.1 From 387bff61a13e750e1ef4e015025415a8b311b25b Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Thu, 27 Jan 2011 11:27:04 +0100 Subject: [PATCH 08/16] whitespace, line breaks etc. --- AUTHORS.md | 2 +- NOTICE | 6 +- README.md | 14 +- librarian/cover.py | 2 +- librarian/epub.py | 6 +- librarian/epub/emptyChunk.html | 14 +- librarian/epub/style.css | 744 ++++++++++++++-------------- librarian/epub/xsltAnnotations.xsl | 152 +++--- librarian/epub/xsltChunkTitle.xsl | 78 +-- librarian/epub/xsltContent.xsl | 98 ++-- librarian/epub/xsltLast.xsl | 198 ++++---- librarian/epub/xsltScheme.xsl | 632 +++++++++++------------ librarian/epub/xsltTitle.xsl | 268 +++++----- librarian/functions.py | 2 +- librarian/pdf.py | 12 +- librarian/pdf/wl2tex.xslt | 10 +- librarian/text.py | 4 +- librarian/xslt/book2txt.xslt | 14 +- librarian/xslt/config.xml | 22 +- librarian/xslt/normalize.xslt | 34 +- librarian/xslt/wl2html_base.xslt | 34 +- librarian/xslt/wl2html_full.xslt | 14 +- librarian/xslt/wl2html_partial.xslt | 18 +- scripts/book2epub | 3 +- scripts/book2html | 6 +- scripts/book2ihtml | 6 +- scripts/book2partner | 17 +- scripts/book2pdf | 8 +- scripts/book2txt | 8 +- scripts/bookfragments | 16 +- scripts/genslugs | 12 +- scripts/master.css | 2 +- scripts/master.plain.css | 2 +- setup.py | 2 +- 34 files changed, 1229 insertions(+), 1231 deletions(-) diff --git a/AUTHORS.md b/AUTHORS.md index 0482d09..70fe140 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -4,6 +4,6 @@ Authors Originally written by Marek Stępniowski Later contributions: - + * Łukasz Rekucki * Radek Czajka diff --git a/NOTICE b/NOTICE index ff69f4a..e4e6ec5 100644 --- a/NOTICE +++ b/NOTICE @@ -1,9 +1,9 @@ - + FNP Librarian Copyright © 2010 Fundacja Nowoczesna Polska - - For full list of contributors see AUTHORS file. + + For full list of contributors see AUTHORS file. This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by diff --git a/README.md b/README.md index 7588245..c0e13e9 100755 --- a/README.md +++ b/README.md @@ -2,10 +2,10 @@ License ------- ![AGPL Logo](http://www.gnu.org/graphics/agplv3-155x51.png) - + Copyright © 2008,2009,2010 Fundacja Nowoczesna Polska - - For full list of contributors see AUTHORS section at the end. + + For full list of contributors see AUTHORS section at the end. This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -21,10 +21,10 @@ License along with this program. If not, see . -About +About ------ -Librarian converts XML-based markup language used by FNP for writing books to +Librarian converts XML-based markup language used by FNP for writing books to other formats, which are more suitable for presentation. Currently we support: @@ -33,8 +33,8 @@ Currently we support: * Plain text * EPUB (XHTML based) * print-ready PDF - -Other features: + +Other features: * extract DublinCore meta-data from documents; * extract marked "themes" from documents. diff --git a/librarian/cover.py b/librarian/cover.py index 20cca66..8aa9abe 100644 --- a/librarian/cover.py +++ b/librarian/cover.py @@ -70,7 +70,7 @@ def virtualo_cover(author, title): 300, 0 ) -def asbis_cover(author, title): +def prestigio_cover(author, title): return cover(author, u"„%s”" % title, 580, 783, '#fff', get_resource('res/cover-prestigio.png'), 446, 118, 62, 60, '#fff', ImageFont.truetype(get_resource('fonts/JunicodeWL-Italic.ttf'), 50), '#000', diff --git a/librarian/epub.py b/librarian/epub.py index 527d050..a87e1d8 100644 --- a/librarian/epub.py +++ b/librarian/epub.py @@ -1,7 +1,7 @@ # -*- 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. +# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. # from __future__ import with_statement @@ -33,7 +33,7 @@ def inner_xml(node): """ nt = node.text if node.text is not None else '' - return ''.join([nt] + [etree.tostring(child) for child in node]) + return ''.join([nt] + [etree.tostring(child) for child in node]) def set_inner_xml(node, text): """ sets node's text and children from a string @@ -467,7 +467,7 @@ def transform(provider, slug=None, file_path=None, output_file=None, output_dir= 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': - optimizer_call = ['perl', 'subset.pl', '--chars', ''.join(chars).encode('utf-8'), + optimizer_call = ['perl', 'subset.pl', '--chars', ''.join(chars).encode('utf-8'), get_resource('fonts/' + fname), os.path.join(tmpdir, fname)] if verbose: print "Running font-optimizer" diff --git a/librarian/epub/emptyChunk.html b/librarian/epub/emptyChunk.html index 14dd415..1452a99 100644 --- a/librarian/epub/emptyChunk.html +++ b/librarian/epub/emptyChunk.html @@ -1,8 +1,8 @@ - - - - - WolneLektury.pl - - + + + + + WolneLektury.pl + + \ No newline at end of file diff --git a/librarian/epub/style.css b/librarian/epub/style.css index 70b05ae..249ae09 100644 --- a/librarian/epub/style.css +++ b/librarian/epub/style.css @@ -1,372 +1,372 @@ -@font-face { - font-family: "DejaVu Serif"; - font-weight: normal; - font-style: normal; - src: url(DejaVuSerif.ttf); -} -@font-face { - font-family: "DejaVu Serif"; - font-weight: bold; - font-style: normal; - src: url(DejaVuSerif-Bold.ttf); -} -@font-face { - font-family: "DejaVu Serif"; - font-weight: normal; - font-style: italic; - src: url(DejaVuSerif-Italic.ttf); -} -@font-face { - font-family: "DejaVu Serif"; - font-weight: bold; - font-style: italic; - src: url(DejaVuSerif-BoldItalic.ttf); -} - -body, p, h1, h2, h3, h4 { - font-family: "DejaVu Serif", serif; -} - - -body -{ - line-height: 1.5em; - margin: 0; -} - -a -{ - text-decoration: none; - color: #00e; -} - -a img { - border: 0; -} - -#book-text -{ - margin: 2em; - /*margin-right: 9em;*/ -} - -/* =================================================== */ -/* = Common elements: headings, paragraphs and lines = */ -/* =================================================== */ - - -.h2 -{ - font-size: 2em; - margin: 0; - margin-top: 1.5em; - font-weight: bold; - line-height: 1.5em; -} - -.h3 -{ - text-align:left; - font-size: 1.5em; - margin-top: 1.5em; - font-weight: normal; - line-height: 1.5em; -} - -.h4 -{ - font-size: 1em; - margin: 0; - margin-top: 1.5em; - line-height: 1.5em; -} - -p -{ - margin: 0; -} - -/* ======================== */ -/* = Footnotes and themes = */ -/* ======================== */ - -.theme-begin -{ - border-left: 0.1em solid #DDDDDD; - color: #777; - padding: 0 0.5em; - width: 7.5em; - font-style: normal; - font-weight: normal; - font-size: 0.875em; - float: right; - margin-right: -9.5em; - clear: both; - left: 40em; - line-height: 1.5em; - text-align: left; -} - -.annotation -{ - font-style: normal; - font-weight: normal; - font-size: 0.875em; -} - -#footnotes .annotation -{ - display: block; - float: left; - width: 2.5em; - clear: both; -} - -#footnotes div -{ - margin: 0; - margin-top: 1.5em; -} - -#footnotes p -{ - margin-left: 2.5em; - font-size: 0.875em; -} - -.block -{ - font-size: 0.875em; - padding: 1em; -} - -/* ============= */ -/* = Numbering = */ -/* ============= */ - -.anchor -{ - margin: -0.25em -0.5em; - color: #777; - font-size: 0.875em; - width: 2em; - text-align: center; - padding: 0.25em 0.5em; - line-height: 1.5em; -} - -/* =================== */ -/* = Custom elements = */ -/* =================== */ - -.title-page -{ - margin-top: 1.5em; -} - -.title -{ - font-size: 3em; - text-align: center; - line-height: 1.5em; - font-weight: bold; -} - -.author -{ - margin: 0; - text-align: center; - font-weight: bold; - - font-size: 1.5em; - line-height: 1.5em; - margin-bottom: 0.25em; -} - -.intitle -{ - margin: 0; - text-align: center; - font-weight: bold; - - font-size: 1.5em; - line-height: 1.5em; - margin-bottom: 0.25em; -} - -.insubtitle -{ - margin: 0; - text-align: center; - font-weight: bold; - - font-size: 1em; - line-height: 1.5em; - margin-bottom: 0.25em; -} - -.collection -{ - margin: 0; - text-align: center; - font-weight: bold; - - font-size: 1.125em; - line-height: 1.5em; - margin-bottom: -0.25em; -} - -.subtitle -{ - margin: 0; - text-align: center; - font-weight: bold; - - font-size: 1.5em; - line-height: 1.5em; - margin-top: -0.25em; -} - -div.didaskalia -{ - font-style: italic; - margin-top: 0.5em; - margin-left: 1.5em; -} - -div.kwestia -{ - margin-top: 0.5em; -} - -.paragraph -{ - text-align: justify; - margin-top: 1.5em; -} - -.motto -{ - text-align: justify; - font-style: italic; - margin-top: 1.5em; -} - -.motto_podpis -{ - font-size: 0.875em; - text-align: right; -} - -div.fragment -{ - border-bottom: 0.1em solid #999; - padding-bottom: 1.5em; -} - -div.note -{ - text-align: right; - font-style: italic; -} -div.note div.paragraph -{ - text-align: right; - font-style: italic; -} -div.dedication -{ - text-align: right; - font-style: italic; -} -div.dedication div.paragaph -{ - text-align: right; - font-style: italic; -} - - -hr.spacer -{ - height: 3em; - visibility: hidden; -} - -hr.spacer-line -{ - margin: 0; - margin-top: 1.5em; - margin-bottom: 1.5em; - border: none; - border-bottom: 0.1em solid #000; -} - -.spacer-asterisk -{ - padding: 0; - margin: 0; - margin-top: 1.5em; - margin-bottom: 1.5em; - text-align: center; -} - -div.person-list ol -{ - list-style: none; - padding: 0; - padding-left: 1.5em; -} - -.place-and-time -{ - font-style: italic; -} - -em.math -{ - font-style: italic; -} -em.foreign-word -{ - font-style: italic; -} -em.book-title -{ - font-style: italic; -} -em.didaskalia -{ - font-style: italic; -} - -em.author-emphasis -{ - letter-spacing: 0.1em; -} - -.person-list em.person -{ - font-style: normal; - /*font-variant: small-caps;*/ - text-transform: uppercase; -} - -p.info -{ - text-align: center; - margin-bottom: 1em; -} - -p.info img -{ - margin: 0; - margin-left: 2em; - margin-right: 2em; -} - -p.minor { - font-size: 0.75em; -} -p.footer { - margin-top: 2em; -} +@font-face { + font-family: "DejaVu Serif"; + font-weight: normal; + font-style: normal; + src: url(DejaVuSerif.ttf); +} +@font-face { + font-family: "DejaVu Serif"; + font-weight: bold; + font-style: normal; + src: url(DejaVuSerif-Bold.ttf); +} +@font-face { + font-family: "DejaVu Serif"; + font-weight: normal; + font-style: italic; + src: url(DejaVuSerif-Italic.ttf); +} +@font-face { + font-family: "DejaVu Serif"; + font-weight: bold; + font-style: italic; + src: url(DejaVuSerif-BoldItalic.ttf); +} + +body, p, h1, h2, h3, h4 { + font-family: "DejaVu Serif", serif; +} + + +body +{ + line-height: 1.5em; + margin: 0; +} + +a +{ + text-decoration: none; + color: #00e; +} + +a img { + border: 0; +} + +#book-text +{ + margin: 2em; + /*margin-right: 9em;*/ +} + +/* =================================================== */ +/* = Common elements: headings, paragraphs and lines = */ +/* =================================================== */ + + +.h2 +{ + font-size: 2em; + margin: 0; + margin-top: 1.5em; + font-weight: bold; + line-height: 1.5em; +} + +.h3 +{ + text-align:left; + font-size: 1.5em; + margin-top: 1.5em; + font-weight: normal; + line-height: 1.5em; +} + +.h4 +{ + font-size: 1em; + margin: 0; + margin-top: 1.5em; + line-height: 1.5em; +} + +p +{ + margin: 0; +} + +/* ======================== */ +/* = Footnotes and themes = */ +/* ======================== */ + +.theme-begin +{ + border-left: 0.1em solid #DDDDDD; + color: #777; + padding: 0 0.5em; + width: 7.5em; + font-style: normal; + font-weight: normal; + font-size: 0.875em; + float: right; + margin-right: -9.5em; + clear: both; + left: 40em; + line-height: 1.5em; + text-align: left; +} + +.annotation +{ + font-style: normal; + font-weight: normal; + font-size: 0.875em; +} + +#footnotes .annotation +{ + display: block; + float: left; + width: 2.5em; + clear: both; +} + +#footnotes div +{ + margin: 0; + margin-top: 1.5em; +} + +#footnotes p +{ + margin-left: 2.5em; + font-size: 0.875em; +} + +.block +{ + font-size: 0.875em; + padding: 1em; +} + +/* ============= */ +/* = Numbering = */ +/* ============= */ + +.anchor +{ + margin: -0.25em -0.5em; + color: #777; + font-size: 0.875em; + width: 2em; + text-align: center; + padding: 0.25em 0.5em; + line-height: 1.5em; +} + +/* =================== */ +/* = Custom elements = */ +/* =================== */ + +.title-page +{ + margin-top: 1.5em; +} + +.title +{ + font-size: 3em; + text-align: center; + line-height: 1.5em; + font-weight: bold; +} + +.author +{ + margin: 0; + text-align: center; + font-weight: bold; + + font-size: 1.5em; + line-height: 1.5em; + margin-bottom: 0.25em; +} + +.intitle +{ + margin: 0; + text-align: center; + font-weight: bold; + + font-size: 1.5em; + line-height: 1.5em; + margin-bottom: 0.25em; +} + +.insubtitle +{ + margin: 0; + text-align: center; + font-weight: bold; + + font-size: 1em; + line-height: 1.5em; + margin-bottom: 0.25em; +} + +.collection +{ + margin: 0; + text-align: center; + font-weight: bold; + + font-size: 1.125em; + line-height: 1.5em; + margin-bottom: -0.25em; +} + +.subtitle +{ + margin: 0; + text-align: center; + font-weight: bold; + + font-size: 1.5em; + line-height: 1.5em; + margin-top: -0.25em; +} + +div.didaskalia +{ + font-style: italic; + margin-top: 0.5em; + margin-left: 1.5em; +} + +div.kwestia +{ + margin-top: 0.5em; +} + +.paragraph +{ + text-align: justify; + margin-top: 1.5em; +} + +.motto +{ + text-align: justify; + font-style: italic; + margin-top: 1.5em; +} + +.motto_podpis +{ + font-size: 0.875em; + text-align: right; +} + +div.fragment +{ + border-bottom: 0.1em solid #999; + padding-bottom: 1.5em; +} + +div.note +{ + text-align: right; + font-style: italic; +} +div.note div.paragraph +{ + text-align: right; + font-style: italic; +} +div.dedication +{ + text-align: right; + font-style: italic; +} +div.dedication div.paragaph +{ + text-align: right; + font-style: italic; +} + + +hr.spacer +{ + height: 3em; + visibility: hidden; +} + +hr.spacer-line +{ + margin: 0; + margin-top: 1.5em; + margin-bottom: 1.5em; + border: none; + border-bottom: 0.1em solid #000; +} + +.spacer-asterisk +{ + padding: 0; + margin: 0; + margin-top: 1.5em; + margin-bottom: 1.5em; + text-align: center; +} + +div.person-list ol +{ + list-style: none; + padding: 0; + padding-left: 1.5em; +} + +.place-and-time +{ + font-style: italic; +} + +em.math +{ + font-style: italic; +} +em.foreign-word +{ + font-style: italic; +} +em.book-title +{ + font-style: italic; +} +em.didaskalia +{ + font-style: italic; +} + +em.author-emphasis +{ + letter-spacing: 0.1em; +} + +.person-list em.person +{ + font-style: normal; + /*font-variant: small-caps;*/ + text-transform: uppercase; +} + +p.info +{ + text-align: center; + margin-bottom: 1em; +} + +p.info img +{ + margin: 0; + margin-left: 2em; + margin-right: 2em; +} + +p.minor { + font-size: 0.75em; +} +p.footer { + margin-top: 2em; +} diff --git a/librarian/epub/xsltAnnotations.xsl b/librarian/epub/xsltAnnotations.xsl index d0af8ab..bc5693e 100644 --- a/librarian/epub/xsltAnnotations.xsl +++ b/librarian/epub/xsltAnnotations.xsl @@ -1,77 +1,77 @@ - - - - - - - - - - - - - <xsl:text>Przypisy</xsl:text> - - - -

    -
    -

    - Przypisy: -

    - -
    -
    - - -
    - - - - - - -
    -

    - - [] - -

    - -

    -
    -
    - - - - - - - - -

    - -

    -
    - - -
    - -
    -
    - - - - „ - - ” - - - - -

    - -

    -
    - + + + + + + + + + + + + + <xsl:text>Przypisy</xsl:text> + + + +
    +
    +

    + Przypisy: +

    + +
    +
    + + +
    + + + + + + +
    +

    + + [] + +

    + +

    +
    +
    + + + + + + + + +

    + +

    +
    + + +
    + +
    +
    + + + + „ + + ” + + + + +

    + +

    +
    +
    \ No newline at end of file diff --git a/librarian/epub/xsltChunkTitle.xsl b/librarian/epub/xsltChunkTitle.xsl index 5827157..caf464d 100644 --- a/librarian/epub/xsltChunkTitle.xsl +++ b/librarian/epub/xsltChunkTitle.xsl @@ -1,40 +1,40 @@ - - - - - - - - - - - - - <xsl:text>Strona tytułowa</xsl:text> - - - -
    -
    - -
    -
    - - -
    - - - - - - - - - - -

    - -

    -
    - + + + + + + + + + + + + + <xsl:text>Strona tytułowa</xsl:text> + + + +
    +
    + +
    +
    + + +
    + + + + + + + + + + +

    + +

    +
    +
    \ No newline at end of file diff --git a/librarian/epub/xsltContent.xsl b/librarian/epub/xsltContent.xsl index 30546a5..27a317f 100644 --- a/librarian/epub/xsltContent.xsl +++ b/librarian/epub/xsltContent.xsl @@ -1,50 +1,50 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/librarian/epub/xsltLast.xsl b/librarian/epub/xsltLast.xsl index 92f5be6..0a4ca5f 100644 --- a/librarian/epub/xsltLast.xsl +++ b/librarian/epub/xsltLast.xsl @@ -1,100 +1,100 @@ - - - - - - - - - - - - - <xsl:text>Strona redakcyjna</xsl:text> - - - -
    -

    - - - Ten utwór jest udostepniony na licencji - - - - - - - - - Ten utwór nie jest chroniony prawem autorskim i znajduje się w domenie - publicznej, co oznacza że możesz go swobodnie wykorzystywać, publikować - i rozpowszechniać. Jeśli utwór opatrzony jest dodatkowymi materiałami - (przypisy, motywy literackie etc.), które podlegają prawu autorskiemu, to - te dodatkowe materiały udostępnione są na licencji - Creative Commons - Uznanie Autorstwa – Na Tych Samych Warunkach 3.0 PL. - - -

    - -

    Źródło: - - - - - , - - -

    - - -

    Tekst opracowany na podstawie:

    -
    - - -

    -
    - - - -

     

    -

    - Plik wygenerowany dnia . -

    - -
    - - -
    - - - - - - - -

    - Opracowanie redakcyjne i przypisy: - - - , - - . -

    -
    -
    - - -
    -
    - - - - + + + + + + + + + + + + + <xsl:text>Strona redakcyjna</xsl:text> + + + +
    +

    + + + Ten utwór jest udostepniony na licencji + + + + + + + + + Ten utwór nie jest chroniony prawem autorskim i znajduje się w domenie + publicznej, co oznacza że możesz go swobodnie wykorzystywać, publikować + i rozpowszechniać. Jeśli utwór opatrzony jest dodatkowymi materiałami + (przypisy, motywy literackie etc.), które podlegają prawu autorskiemu, to + te dodatkowe materiały udostępnione są na licencji + Creative Commons + Uznanie Autorstwa – Na Tych Samych Warunkach 3.0 PL. + + +

    + +

    Źródło: + + + + + , + + +

    + + +

    Tekst opracowany na podstawie:

    +
    + + +

    +
    + + + +

     

    +

    + Plik wygenerowany dnia . +

    + +
    + + +
    + + + + + + + +

    + Opracowanie redakcyjne i przypisy: + + + , + + . +

    +
    +
    + + +
    +
    + + + +
    \ No newline at end of file diff --git a/librarian/epub/xsltScheme.xsl b/librarian/epub/xsltScheme.xsl index 1543268..7e866fd 100644 --- a/librarian/epub/xsltScheme.xsl +++ b/librarian/epub/xsltScheme.xsl @@ -1,317 +1,317 @@ - - - - - - - - - - - - - WolneLektury.pl - - - - - book-text - - - - - - - - - - - - - - - - - -
    - -
    -
    - - -
    -
    - -
    -
      - -
    -
    -
    - - -
    - -
    -
    - - -
    - -
    -
    - - -
    - -
    -
    - - -
    - -
    -
    - - - - - - -

    - -

    -
    - - - - -

    - -

    -
    - - - - -

    - -

    -
    - - - - -

    - -

    -
    - - - - -

    - -

    -
    - - -

    - -

    -
    - - - -

    - -

    -
    - - - -

    - -

    -
    - - -

    - -

    -
    - - -

    - -

    -
    - - -
    - -
    -
    - - -
    - -
    -
    - - -

    - -

    -
    - - -
    - -
     
    -
    - - -
    - -  
    -
    - - -
    - -  
    -
    - - -
    - -  
    -
    - - -
    - - margin-left: em; - - -  
    -
    - - -
    - -  
    -
    - - -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - „ - - ” - - - - - - - - - - - - - - - - - - - - -
  1. - -
  2. -
    - - - - - - -

     

    -
    - - -

    *

    -
    - - -
    -
    - - - - - - - - - - - - - - - [] - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + WolneLektury.pl + + + + + book-text + + + + + + + + + + + + + + + + + +
    + +
    +
    + + +
    +
    + +
    +
      + +
    +
    +
    + + +
    + +
    +
    + + +
    + +
    +
    + + +
    + +
    +
    + + +
    + +
    +
    + + + + + + +

    + +

    +
    + + + + +

    + +

    +
    + + + + +

    + +

    +
    + + + + +

    + +

    +
    + + + + +

    + +

    +
    + + +

    + +

    +
    + + + +

    + +

    +
    + + + +

    + +

    +
    + + +

    + +

    +
    + + +

    + +

    +
    + + +
    + +
    +
    + + +
    + +
    +
    + + +

    + +

    +
    + + +
    + +
     
    +
    + + +
    + +  
    +
    + + +
    + +  
    +
    + + +
    + +  
    +
    + + +
    + + margin-left: em; + + +  
    +
    + + +
    + +  
    +
    + + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + „ + + ” + + + + + + + + + + + + + + + + + + + + +
  3. + +
  4. +
    + + + + + + +

     

    +
    + + +

    *

    +
    + + +
    +
    + + + + + + + + + + + + + + + [] + + + + + + + + + + + + + + + + + + + + +
    \ No newline at end of file diff --git a/librarian/epub/xsltTitle.xsl b/librarian/epub/xsltTitle.xsl index 53bbb1a..544b4b9 100644 --- a/librarian/epub/xsltTitle.xsl +++ b/librarian/epub/xsltTitle.xsl @@ -1,135 +1,135 @@ - - - - - - - - - - - - - <xsl:text>Strona tytułowa</xsl:text> - - - -
    -
    - - - - - - - - - - -
    - -

     

    - - - - -

    - - - - - Ta lektura, - podobnie jak tysiące innych, jest dostępna on-line na stronie - wolnelektury.pl. -

    -
    - -

    - Utwór opracowany został w ramach projektu Wolne Lektury przez fundację Nowoczesna Polska. -

    - - -
    - - -
    - - - - - - - - - - -

    - -

    -
    - - -

    - -

    -
    - - - -

    - tłum. - - , - - -

    -
    -
    - - - - - - -

    - -

    -
    - - -

    - -

    -
    - - -

    - -

    -
    - - -

    - -

    -
    - - -

    - -

    -
    - - - - - - - + + + + + + + + + + + + + <xsl:text>Strona tytułowa</xsl:text> + + + +
    +
    + + + + + + + + + + +
    + +

     

    + + + + +

    + + + + + Ta lektura, + podobnie jak tysiące innych, jest dostępna on-line na stronie + wolnelektury.pl. +

    +
    + +

    + Utwór opracowany został w ramach projektu Wolne Lektury przez fundację Nowoczesna Polska. +

    + + +
    + + +
    + + + + + + + + + + +

    + +

    +
    + + +

    + +

    +
    + + + +

    + tłum. + + , + + +

    +
    +
    + + + + + + +

    + +

    +
    + + +

    + +

    +
    + + +

    + +

    +
    + + +

    + +

    +
    + + +

    + +

    +
    + + + + + + +
    \ No newline at end of file diff --git a/librarian/functions.py b/librarian/functions.py index 08f920d..523b3d5 100644 --- a/librarian/functions.py +++ b/librarian/functions.py @@ -14,7 +14,7 @@ def _register_function(f): ns[f.__name__] = f -def reg_substitute_entities(): +def reg_substitute_entities(): ENTITY_SUBSTITUTIONS = [ (u'---', u'—'), (u'--', u'–'), diff --git a/librarian/pdf.py b/librarian/pdf.py index 5f28547..5f6f0a2 100644 --- a/librarian/pdf.py +++ b/librarian/pdf.py @@ -37,7 +37,7 @@ STYLESHEETS = { def insert_tags(doc, split_re, tagname, exclude=None): - """ inserts for every occurence of `split_re' in text nodes in the `doc' tree + """ inserts for every occurence of `split_re' in text nodes in the `doc' tree >>> t = etree.fromstring('A-B-CX-Y-Z'); >>> insert_tags(t, re.compile('-'), 'd'); @@ -67,7 +67,7 @@ def insert_tags(doc, split_re, tagname, exclude=None): def substitute_hyphens(doc): - insert_tags(doc, + insert_tags(doc, re.compile("(?<=[^-\s])-(?=[^-\s])"), "dywiz", exclude=[DCNS("identifier.url"), DCNS("rights.license")] @@ -75,7 +75,7 @@ def substitute_hyphens(doc): def fix_hanging(doc): - insert_tags(doc, + insert_tags(doc, re.compile("(?<=\s\w)\s+"), "nbsp", exclude=[DCNS("identifier.url"), DCNS("rights.license")] @@ -147,7 +147,7 @@ def get_stylesheet(name): def package_available(package, args='', verbose=False): - """ check if a verion of a latex package accepting given args is available """ + """ check if a verion of a latex package accepting given args is available """ tempdir = mkdtemp('-wl2pdf-test') fpath = os.path.join(tempdir, 'test.tex') f = open(fpath, 'w') @@ -166,7 +166,7 @@ def package_available(package, args='', verbose=False): return p == 0 -def transform(provider, slug=None, file_path=None, +def transform(provider, slug=None, file_path=None, output_file=None, output_dir=None, make_dir=False, verbose=False, save_tex=None, morefloats=None): """ produces a PDF file with XeLaTeX @@ -271,7 +271,7 @@ def transform(provider, slug=None, file_path=None, def load_including_children(provider, slug=None, uri=None, file_path=None): - """ makes one big xml file with children inserted at end + """ makes one big xml file with children inserted at end either slug or uri must be provided """ diff --git a/librarian/pdf/wl2tex.xslt b/librarian/pdf/wl2tex.xslt index c577313..5a49a01 100644 --- a/librarian/pdf/wl2tex.xslt +++ b/librarian/pdf/wl2tex.xslt @@ -1,9 +1,9 @@ - @@ -199,7 +199,7 @@ - @@ -211,7 +211,7 @@ - diff --git a/librarian/text.py b/librarian/text.py index f5aafc1..c0591e0 100644 --- a/librarian/text.py +++ b/librarian/text.py @@ -45,7 +45,7 @@ def transform(input_file, output_file, parse_dublincore=True, **options): license_description = parsed_dc.license_description license = parsed_dc.license if license: - license_description = u"Ten utwór jest udostepniony na licencji %s: \n%s" % (license_description, license) + license_description = u"Ten utwór jest udostepniony na licencji %s: \n%s" % (license_description, license) else: license_description = u"Ten utwór nie jest chroniony prawem autorskim i znajduje się w domenie publicznej, co oznacza że możesz go swobodnie wykorzystywać, publikować i rozpowszechniać. Jeśli utwór opatrzony jest dodatkowymi materiałami (przypisy, motywy literackie etc.), które podlegają prawu autorskiemu, to te dodatkowe materiały udostępnione są na licencji Creative Commons Uznanie Autorstwa – Na Tych Samych Warunkach 3.0 PL (http://creativecommons.org/licenses/by-sa/3.0/)" @@ -55,7 +55,7 @@ def transform(input_file, output_file, parse_dublincore=True, **options): else: source = '' - contributors = ', '.join(person.readable() for person in + contributors = ', '.join(person.readable() for person in sorted(set(p for p in (parsed_dc.technical_editors + parsed_dc.editors) if p))) if contributors: contributors = "\n\nOpracowanie redakcyjne i przypisy: %s" % contributors diff --git a/librarian/xslt/book2txt.xslt b/librarian/xslt/book2txt.xslt index 604b8bd..bf78d41 100755 --- a/librarian/xslt/book2txt.xslt +++ b/librarian/xslt/book2txt.xslt @@ -1,9 +1,9 @@ - + / / @@ -176,16 +176,16 @@ - + - + - @@ -195,7 +195,7 @@ - + diff --git a/librarian/xslt/config.xml b/librarian/xslt/config.xml index ad09e36..e9e999c 100755 --- a/librarian/xslt/config.xml +++ b/librarian/xslt/config.xml @@ -1,9 +1,9 @@ @@ -48,27 +48,27 @@ - - + + - + - + - + - + - + @@ -91,13 +91,13 @@ - + - +
    diff --git a/librarian/xslt/normalize.xslt b/librarian/xslt/normalize.xslt index 400c927..494d028 100755 --- a/librarian/xslt/normalize.xslt +++ b/librarian/xslt/normalize.xslt @@ -1,17 +1,17 @@ - + @@ -38,10 +38,10 @@ - + -
    +
    @@ -111,7 +111,7 @@ - + @@ -146,7 +146,7 @@ dot - + @@ -244,7 +244,7 @@ - + @@ -253,7 +253,7 @@ - + @@ -276,7 +276,7 @@ - + @@ -309,7 +309,7 @@ - + @@ -357,7 +357,7 @@ - + @@ -378,7 +378,7 @@ - + @@ -389,11 +389,11 @@ Nieprzetworzony węzeł: - + - +
    \ No newline at end of file diff --git a/librarian/xslt/wl2html_base.xslt b/librarian/xslt/wl2html_base.xslt index 7a2b3ae..3341658 100755 --- a/librarian/xslt/wl2html_base.xslt +++ b/librarian/xslt/wl2html_base.xslt @@ -1,15 +1,15 @@ @@ -21,7 +21,7 @@ indent="yes" omit-xml-declaration = "yes" /> - @@ -89,12 +89,12 @@ - + - + @@ -113,7 +113,7 @@ - + @@ -228,7 +228,7 @@ - + @@ -326,12 +326,12 @@ - + - + @@ -345,7 +345,7 @@ - + @@ -355,9 +355,9 @@ - + - + diff --git a/librarian/xslt/wl2html_full.xslt b/librarian/xslt/wl2html_full.xslt index 050f1e8..30381c3 100755 --- a/librarian/xslt/wl2html_full.xslt +++ b/librarian/xslt/wl2html_full.xslt @@ -1,17 +1,17 @@ - - + - + @@ -20,7 +20,7 @@ - + diff --git a/librarian/xslt/wl2html_partial.xslt b/librarian/xslt/wl2html_partial.xslt index 22ee122..0e5e27b 100755 --- a/librarian/xslt/wl2html_partial.xslt +++ b/librarian/xslt/wl2html_partial.xslt @@ -1,20 +1,20 @@ - - - - + + + -
    - +
    +
    \ No newline at end of file diff --git a/scripts/book2epub b/scripts/book2epub index ea87483..502d965 100755 --- a/scripts/book2epub +++ b/scripts/book2epub @@ -2,7 +2,7 @@ # -*- 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. +# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. # import os.path import optparse @@ -55,4 +55,3 @@ if __name__ == '__main__': 'name': e.__class__.__name__, 'message': e.message } - \ No newline at end of file diff --git a/scripts/book2html b/scripts/book2html index a48aa64..f42c0ff 100755 --- a/scripts/book2html +++ b/scripts/book2html @@ -2,7 +2,7 @@ # -*- 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. +# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. # import os import optparse @@ -21,7 +21,7 @@ if __name__ == '__main__': 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: @@ -32,7 +32,7 @@ if __name__ == '__main__': for input_filename in input_filenames: if options.verbose: print input_filename - + output_filename = os.path.splitext(input_filename)[0] + '.html' try: html.transform(input_filename, output_filename, parse_dublincore=options.parse_dublincore, flags=('full-page',)) diff --git a/scripts/book2ihtml b/scripts/book2ihtml index 101b4cf..97d8ebd 100755 --- a/scripts/book2ihtml +++ b/scripts/book2ihtml @@ -2,7 +2,7 @@ # -*- 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. +# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. # import os import optparse @@ -21,7 +21,7 @@ if __name__ == '__main__': 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: @@ -32,7 +32,7 @@ if __name__ == '__main__': for input_filename in input_filenames: if options.verbose: print input_filename - + output_filename = os.path.splitext(input_filename)[0] + '.html' try: html.transform(input_filename, output_filename, parse_dublincore=options.parse_dublincore,\ diff --git a/scripts/book2partner b/scripts/book2partner index 786c2c2..d2a47b3 100755 --- a/scripts/book2partner +++ b/scripts/book2partner @@ -2,7 +2,7 @@ # -*- 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. +# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. # import os.path import optparse @@ -67,7 +67,7 @@ def virtualo(filenames, output_dir, verbose): xml.append(product_elem) cover.virtualo_cover( - u' '.join(info.author.first_names + (info.author.last_name,)), + u' '.join(info.author.first_names + (info.author.last_name,)), info.title ).save(os.path.join(outfile_dir, slug+'.jpg')) outfile = os.path.join(outfile_dir, '1.epub') @@ -86,7 +86,7 @@ def virtualo(filenames, output_dir, verbose): xml_file.close() -def asbis(filenames, output_dir, verbose): +def prestigio(filenames, output_dir, verbose): try: for main_input in input_filenames: if options.verbose: @@ -102,7 +102,7 @@ def asbis(filenames, output_dir, verbose): pass outfile = os.path.join(output_dir, slug + '.epub') epub.transform(provider, file_path=main_input, output_file=outfile, - cover_fn=cover.asbis_cover, flags=('less-advertising',)) + cover_fn=cover.prestigio_cover, flags=('less-advertising',)) except ParseError, e: print '%(file)s:%(name)s:%(message)s' % { 'file': main_input, @@ -125,8 +125,8 @@ if __name__ == '__main__': help='specifies the directory for output') parser.add_option('--virtualo', action='store_true', dest='virtualo', default=False, help='prepare files for Virtualo API') - parser.add_option('--asbis', action='store_true', dest='asbis', default=False, - help='prepare files for Asbis') + parser.add_option('--prestigio', action='store_true', dest='prestigio', default=False, + help='prepare files for prestigio') options, input_filenames = parser.parse_args() @@ -136,6 +136,5 @@ if __name__ == '__main__': if options.virtualo: virtualo(input_filenames, options.output_dir, options.verbose) - if options.asbis: - asbis(input_filenames, options.output_dir, options.verbose) - \ No newline at end of file + if options.prestigio: + prestigio(input_filenames, options.output_dir, options.verbose) diff --git a/scripts/book2pdf b/scripts/book2pdf index fd69970..532577c 100755 --- a/scripts/book2pdf +++ b/scripts/book2pdf @@ -2,7 +2,7 @@ # -*- 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. +# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. # import os.path from optparse import OptionParser @@ -49,9 +49,9 @@ if __name__ == '__main__': else: output_dir = path - pdf.transform(provider, - file_path=main_input, - output_file=output_file, + pdf.transform(provider, + file_path=main_input, + output_file=output_file, output_dir=output_dir, verbose=options.verbose, make_dir=options.make_dir, diff --git a/scripts/book2txt b/scripts/book2txt index d5e18c6..f77e512 100755 --- a/scripts/book2txt +++ b/scripts/book2txt @@ -2,7 +2,7 @@ # -*- 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. +# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. # import os import optparse @@ -24,9 +24,9 @@ if __name__ == '__main__': 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') - + options, input_filenames = parser.parse_args() - + if len(input_filenames) < 1: parser.print_help() exit(1) @@ -35,7 +35,7 @@ if __name__ == '__main__': for input_filename in input_filenames: if options.verbose: print input_filename - + output_filename = os.path.splitext(input_filename)[0] + '.txt' try: output_file = open(output_filename, 'w') diff --git a/scripts/bookfragments b/scripts/bookfragments index 124c1c5..0d94497 100755 --- a/scripts/bookfragments +++ b/scripts/bookfragments @@ -2,7 +2,7 @@ # -*- 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. +# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. # import os import optparse @@ -14,25 +14,25 @@ if __name__ == '__main__': # Parse commandline arguments usage = """Usage: %prog [options] SOURCE [SOURCE...] Extract theme fragments from SOURCE.""" - + parser = optparse.OptionParser(usage=usage) - + parser.add_option('-v', '--verbose', action='store_true', dest='verbose', default=False, help='print status messages to stdout') - + 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] + '.fragments.html' - + closed_fragments, open_fragments = html.extract_fragments(input_filename) for fragment_id in open_fragments: diff --git a/scripts/genslugs b/scripts/genslugs index 0957da7..a234096 100755 --- a/scripts/genslugs +++ b/scripts/genslugs @@ -2,7 +2,7 @@ # -*- 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. +# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. # import os import optparse @@ -26,7 +26,7 @@ if __name__ == '__main__': help='print status messages to stdout') parser.add_option('-f', '--force', action='store_true', dest='force', default=False, help='overwrite current identifiers') - + options, input_filenames = parser.parse_args() if len(input_filenames) < 1: @@ -37,14 +37,14 @@ if __name__ == '__main__': for input_filename in input_filenames: if options.verbose: print input_filename - + doc = etree.parse(input_filename) try: title = doc.find('//{http://purl.org/dc/elements/1.1/}title').text except AttributeError: print '%s:error:Book title not found. Skipping.' % input_filename continue - + parent = '' try: parent_url = doc.find('//{http://purl.org/dc/elements/1.1/}relation.isPartOf').text @@ -53,7 +53,7 @@ if __name__ == '__main__': pass except IndexError: print '%s:error:Invalid parent URL "%s". Skipping.' % (input_filename, parent_url) - + book_url = doc.find('//{http://purl.org/dc/elements/1.1/}identifier.url') if book_url is None: book_description = doc.find('//{http://www.w3.org/1999/02/22-rdf-syntax-ns#}Description') @@ -61,7 +61,7 @@ if __name__ == '__main__': if not options.force and book_url.text.startswith('http://'): print '%s:Notice:Book already has identifier URL "%s". Skipping.' % (input_filename, book_url.text) continue - + book_url.text = BOOK_URL + slughifi(parent + title)[:60] doc.write(input_filename, xml_declaration=True, pretty_print=True, encoding='utf-8') diff --git a/scripts/master.css b/scripts/master.css index 264dc07..44fe927 100755 --- a/scripts/master.css +++ b/scripts/master.css @@ -1,7 +1,7 @@ /* * This file is part of Librarian, licensed under GNU Affero GPLv3 or later. * Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. - * + * */ body { font-size: 16px; diff --git a/scripts/master.plain.css b/scripts/master.plain.css index b580c19..68fd9c5 100755 --- a/scripts/master.plain.css +++ b/scripts/master.plain.css @@ -1,7 +1,7 @@ /* * This file is part of Librarian, licensed under GNU Affero GPLv3 or later. * Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. - * + * */ body { font-size: 16px; diff --git a/setup.py b/setup.py index 017cc57..d1db01b 100644 --- a/setup.py +++ b/setup.py @@ -29,7 +29,7 @@ setup( maintainer_email='radek.czajka@gmail.com', url='http://github.com/fnp/librarian', packages=['librarian'], - package_data={'librarian': ['xslt/*.xslt', 'epub/*', 'pdf/*', 'fonts/*', 'res/*'] + + package_data={'librarian': ['xslt/*.xslt', 'epub/*', 'pdf/*', 'fonts/*', 'res/*'] + whole_tree(os.path.join(os.path.dirname(__file__), 'librarian'), 'font-optimizer')}, include_package_data=True, install_requires=['lxml>=2.2'], -- 2.20.1 From 51b9dc0babf62ea90091eeb5bafec66e39aab910 Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Wed, 2 Feb 2011 13:11:51 +0100 Subject: [PATCH 09/16] Booktoteka packager and some cover refactoring --- librarian/cover.py | 169 +++++++++++++++++++++++------- librarian/epub.py | 27 +++-- librarian/epub/cover.html | 2 +- librarian/res/cover-bookoteka.png | Bin 0 -> 56260 bytes scripts/book2partner | 35 ++++++- 5 files changed, 182 insertions(+), 51 deletions(-) create mode 100644 librarian/res/cover-bookoteka.png diff --git a/librarian/cover.py b/librarian/cover.py index 8aa9abe..e34ce62 100644 --- a/librarian/cover.py +++ b/librarian/cover.py @@ -7,12 +7,46 @@ import Image, ImageFont, ImageDraw, ImageFilter from librarian import get_resource -def cover(author, title, - width, height, background_color, background_img, - author_top, author_margin_left, author_margin_right, author_lineskip, author_color, author_font, author_shadow, - title_top, title_margin_left, title_margin_right, title_lineskip, title_color, title_font, title_shadow, - logo_width, logo_bottom - ): +class Cover(object): + width = 600 + height = 800 + background_color = '#fff' + background_img = None + + author_top = 100 + author_margin_left = 20 + author_margin_right = 20 + author_lineskip = 40 + author_color = '#000' + author_shadow = None + author_font = None + + title_top = 100 + title_margin_left = 20 + title_margin_right = 20 + title_lineskip = 54 + title_color = '#000' + title_shadow = None + title_font = None + + logo_bottom = None + logo_width = None + + format = 'JPEG' + + + exts = { + 'JPEG': 'jpg', + 'PNG': 'png', + } + + mime_types = { + 'JPEG': 'image/jpeg', + 'PNG': 'image/png', + } + + + @staticmethod def draw_centered_text(text, img, font, margin_left, width, pos_y, lineskip, color, shadow_color): if shadow_color: shadow_img = Image.new('RGBA', img.size) @@ -39,42 +73,103 @@ def cover(author, title, return pos_y - img = Image.new('RGB', (width, height), background_color) + def __init__(self, author='', title=''): + self.author = author + self.title = title + + def pretty_author(self): + return self.author + + def pretty_title(self): + return self.title + + def image(self): + img = Image.new('RGB', (self.width, self.height), self.background_color) + + if self.background_img: + background = Image.open(self.background_img) + img.paste(background, None, background) + del background + + # WL logo + if self.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)) + + author_font = self.author_font or ImageFont.truetype(get_resource('fonts/DejaVuSerif.ttf'), 30) + title_y = self.draw_centered_text(self.pretty_author(), img, author_font, + self.author_margin_left, self.width - self.author_margin_left - self.author_margin_right, self.author_top, + self.author_lineskip, self.author_color, self.author_shadow) + self.title_top + title_font = self.title_font or ImageFont.truetype(get_resource('fonts/DejaVuSerif.ttf'), 40) + self.draw_centered_text(self.pretty_title(), img, title_font, + self.title_margin_left, self.width - self.title_margin_left - self.title_margin_right, title_y, + self.title_lineskip, self.title_color, self.title_shadow) + + return img + + def mime_type(self): + return self.mime_types[self.format] + + def ext(self): + return self.exts[self.format] + + def save(self, *args, **kwargs): + return self.image().save(*args, format=self.format, **kwargs) + + + +class VirtualoCover(Cover): + width = 600 + height = 730 + author_top = 73 + title_top = 73 + logo_bottom = 0 + logo_width = 300 + + +class PrestigioCover(Cover): + width = 580 + height = 783 + background_img = get_resource('res/cover-prestigio.png') - if background_img: - background = Image.open(background_img) - img.paste(background, None, background) - del background + author_top = 446 + author_margin_left = 118 + author_margin_right = 62 + author_lineskip = 60 + author_color = '#fff' + author_shadow = '#000' + author_font = ImageFont.truetype(get_resource('fonts/JunicodeWL-Italic.ttf'), 50) - # WL logo - if logo_width: - logo = Image.open(get_resource('res/wl-logo.png')) - logo = logo.resize((logo_width, logo.size[1] * logo_width / logo.size[0])) - img.paste(logo, ((width - logo_width) / 2, img.size[1] - logo.size[1] - logo_bottom)) + title_top = 0 + title_margin_left = 118 + title_margin_right = 62 + title_lineskip = 60 + title_color = '#fff' + title_shadow = '#000' + title_font = ImageFont.truetype(get_resource('fonts/JunicodeWL-Italic.ttf'), 50) - title_y = draw_centered_text(author, img, author_font, - author_margin_left, width - author_margin_left - author_margin_right, author_top, - author_lineskip, author_color, author_shadow) + title_top - draw_centered_text(title, img, title_font, - title_margin_left, width - title_margin_left - title_margin_right, title_y, - title_lineskip, title_color, title_shadow) + def pretty_title(self): + return u"„%s”" % self.title - return img +class BookotekaCover(Cover): + width = 2140 + height = 2733 + background_img = get_resource('res/cover-bookoteka.png') -def virtualo_cover(author, title): - return cover(author, title, - 600, 730, '#fff', None, - 73, 20, 20, 40, '#000', ImageFont.truetype(get_resource('fonts/DejaVuSerif.ttf'), 30), None, - 73, 20, 20, 54, '#000', ImageFont.truetype(get_resource('fonts/DejaVuSerif.ttf'), 40), None, - 300, 0 - ) + author_top = 480 + author_margin_left = 307 + author_margin_right = 233 + author_lineskip = 156 + author_color = '#d9d919' + author_font = ImageFont.truetype(get_resource('fonts/JunicodeWL-Regular.ttf'), 130) -def prestigio_cover(author, title): - return cover(author, u"„%s”" % title, - 580, 783, '#fff', get_resource('res/cover-prestigio.png'), - 446, 118, 62, 60, '#fff', ImageFont.truetype(get_resource('fonts/JunicodeWL-Italic.ttf'), 50), '#000', - 0, 118, 62, 60, '#fff', ImageFont.truetype(get_resource('fonts/JunicodeWL-Italic.ttf'), 50), '#000', - None, None - ) + 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) + format = 'PNG' diff --git a/librarian/epub.py b/librarian/epub.py index a87e1d8..f2987b5 100644 --- a/librarian/epub.py +++ b/librarian/epub.py @@ -17,7 +17,7 @@ from shutil import rmtree import sys -from librarian import XMLNamespace, RDFNS, DCNS, WLNS, NCXNS, OPFNS, NoDublinCore +from librarian import XMLNamespace, RDFNS, DCNS, WLNS, NCXNS, OPFNS, XHTMLNS, NoDublinCore from librarian.dcparser import BookInfo from librarian import functions, get_resource @@ -266,7 +266,7 @@ def transform_chunk(chunk_xml, chunk_no, annotations, empty=False, _empty_html_s def transform(provider, slug=None, file_path=None, output_file=None, output_dir=None, make_dir=False, verbose=False, - sample=None, cover_fn=None, flags=None): + sample=None, cover=None, flags=None): """ produces a EPUB file provider: a DocProvider @@ -275,7 +275,7 @@ def transform(provider, slug=None, file_path=None, output_file=None, output_dir= output_dir: path to directory to save output file to; either this or output_file must be present make_dir: writes output to //.epub instead of /.epub sample=n: generate sample e-book (with at least n paragraphs) - cover_fn: function(author, title) -> cover image + cover: a cover.Cover object flags: less-advertising, """ @@ -401,16 +401,23 @@ def transform(provider, slug=None, file_path=None, output_file=None, output_dir= manifest = opf.find('.//' + OPFNS('manifest')) spine = opf.find('.//' + OPFNS('spine')) - if cover_fn: - cover = StringIO() - cover_fn(book_info.author.readable(), book_info.title).save(cover, format='JPEG') - zip.writestr(os.path.join('OPS', 'cover.jpg'), cover.getvalue()) - del cover - zip.writestr('OPS/cover.html', open(get_resource('epub/cover.html')).read()) + if cover: + cover_file = StringIO() + c = cover(book_info.author.readable(), book_info.title) + 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) + zip.writestr('OPS/cover.html', etree.tostring( + cover_tree, method="html", pretty_print=True)) + manifest.append(etree.fromstring( '')) manifest.append(etree.fromstring( - '')) + '' % (c_name, c.mime_type()))) spine.insert(0, etree.fromstring('')) opf.getroot()[0].append(etree.fromstring('')) opf.getroot().append(etree.fromstring('')) diff --git a/librarian/epub/cover.html b/librarian/epub/cover.html index bbe8508..784067c 100644 --- a/librarian/epub/cover.html +++ b/librarian/epub/cover.html @@ -7,7 +7,7 @@
    - Okładka + Okładka
    \ No newline at end of file diff --git a/librarian/res/cover-bookoteka.png b/librarian/res/cover-bookoteka.png new file mode 100644 index 0000000000000000000000000000000000000000..7196bcfab6525885ff08da54d3ad8c39a4103923 GIT binary patch literal 56260 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 R(xO|G5Rnlse53Q>zW{nh8Ib@0 literal 0 HcmV?d00001 diff --git a/scripts/book2partner b/scripts/book2partner index d2a47b3..6955899 100755 --- a/scripts/book2partner +++ b/scripts/book2partner @@ -66,7 +66,7 @@ def virtualo(filenames, output_dir, verbose): product_elem[4][0][1].text = utf_trunc(info.author.last_name, 100) xml.append(product_elem) - cover.virtualo_cover( + cover.VirtualoCover( u' '.join(info.author.first_names + (info.author.last_name,)), info.title ).save(os.path.join(outfile_dir, slug+'.jpg')) @@ -102,7 +102,32 @@ def prestigio(filenames, output_dir, verbose): pass outfile = os.path.join(output_dir, slug + '.epub') epub.transform(provider, file_path=main_input, output_file=outfile, - cover_fn=cover.prestigio_cover, flags=('less-advertising',)) + cover=cover.PrestigioCover, flags=('less-advertising',)) + except ParseError, e: + print '%(file)s:%(name)s:%(message)s' % { + 'file': main_input, + 'name': e.__class__.__name__, + 'message': e.message + } + + +def bookoteka(filenames, output_dir, verbose): + 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) + slug, ext = os.path.splitext(fname) + + if output_dir != '': + try: + os.makedirs(output_dir) + except: + pass + outfile = os.path.join(output_dir, slug + '.epub') + epub.transform(provider, file_path=main_input, output_file=outfile, + cover=cover.BookotekaCover) except ParseError, e: print '%(file)s:%(name)s:%(message)s' % { 'file': main_input, @@ -123,10 +148,12 @@ if __name__ == '__main__': help='print status messages to stdout') parser.add_option('-O', '--output-dir', dest='output_dir', metavar='DIR', default='', help='specifies the directory for output') + parser.add_option('--bookoteka', action='store_true', dest='bookoteka', default=False, + help='prepare files for Bookoteka') parser.add_option('--virtualo', action='store_true', dest='virtualo', default=False, help='prepare files for Virtualo API') parser.add_option('--prestigio', action='store_true', dest='prestigio', default=False, - help='prepare files for prestigio') + help='prepare files for Prestigio') options, input_filenames = parser.parse_args() @@ -134,6 +161,8 @@ if __name__ == '__main__': parser.print_help() exit(1) + if options.bookoteka: + bookoteka(input_filenames, options.output_dir, options.verbose) if options.virtualo: virtualo(input_filenames, options.output_dir, options.verbose) if options.prestigio: -- 2.20.1 From c461850146a3c49dd5bec6c845c1b0ce52a34896 Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Thu, 3 Feb 2011 15:47:14 +0100 Subject: [PATCH 10/16] python 2.5 compatibility fix --- librarian/cover.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/librarian/cover.py b/librarian/cover.py index e34ce62..27f7a70 100644 --- a/librarian/cover.py +++ b/librarian/cover.py @@ -115,7 +115,7 @@ class Cover(object): return self.exts[self.format] def save(self, *args, **kwargs): - return self.image().save(*args, format=self.format, **kwargs) + return self.image().save(format=self.format, *args, **kwargs) -- 2.20.1 From f492e325efb42a3348b2479a0fd0ffc3c484657b Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Mon, 14 Feb 2011 08:50:40 +0100 Subject: [PATCH 11/16] Add raw text option to text conversion (lesmianator will need it). --- librarian/text.py | 83 ++++++++++++++++++++---------------- librarian/xslt/book2txt.xslt | 2 +- 2 files changed, 48 insertions(+), 37 deletions(-) diff --git a/librarian/text.py b/librarian/text.py index c0591e0..c23bcd6 100644 --- a/librarian/text.py +++ b/librarian/text.py @@ -28,50 +28,61 @@ Utwór opracowany został w ramach projektu Wolne Lektury przez fundację Nowocz %(description)s%(contributors)s """ -def transform(input_file, output_file, parse_dublincore=True, **options): - """Transforms input_file in XML to output_file in TXT.""" +def transform(input_file, output_file, parse_dublincore=True, flags=None, **options): + """ + Transforms input_file in XML to output_file in TXT. + possible flags: raw-text, + """ # Parse XSLT style_filename = os.path.join(os.path.dirname(__file__), 'xslt/book2txt.xslt') style = etree.parse(style_filename) document = parser.WLDocument.from_file(input_file, True, parse_dublincore=parse_dublincore) - result = document.transform(style, **options) - if parse_dublincore: - parsed_dc = dcparser.BookInfo.from_element(document.edoc) - description = parsed_dc.description - url = parsed_dc.url + if flags: + for flag in flags: + document.edoc.getroot().set(flag, 'yes') - license_description = parsed_dc.license_description - license = parsed_dc.license - if license: - license_description = u"Ten utwór jest udostepniony na licencji %s: \n%s" % (license_description, license) - else: - license_description = u"Ten utwór nie jest chroniony prawem autorskim i znajduje się w domenie publicznej, co oznacza że możesz go swobodnie wykorzystywać, publikować i rozpowszechniać. Jeśli utwór opatrzony jest dodatkowymi materiałami (przypisy, motywy literackie etc.), które podlegają prawu autorskiemu, to te dodatkowe materiały udostępnione są na licencji Creative Commons Uznanie Autorstwa – Na Tych Samych Warunkach 3.0 PL (http://creativecommons.org/licenses/by-sa/3.0/)" + result = document.transform(style, **options) - source = parsed_dc.source_name - if source: - source = "\n\nTekst opracowany na podstawie: " + source + if not flags or 'raw-text' not in flags: + if parse_dublincore: + parsed_dc = dcparser.BookInfo.from_element(document.edoc) + description = parsed_dc.description + url = parsed_dc.url + + license_description = parsed_dc.license_description + license = parsed_dc.license + if license: + license_description = u"Ten utwór jest udostepniony na licencji %s: \n%s" % (license_description, license) + else: + license_description = u"Ten utwór nie jest chroniony prawem autorskim i znajduje się w domenie publicznej, co oznacza że możesz go swobodnie wykorzystywać, publikować i rozpowszechniać. Jeśli utwór opatrzony jest dodatkowymi materiałami (przypisy, motywy literackie etc.), które podlegają prawu autorskiemu, to te dodatkowe materiały udostępnione są na licencji Creative Commons Uznanie Autorstwa – Na Tych Samych Warunkach 3.0 PL (http://creativecommons.org/licenses/by-sa/3.0/)" + + source = parsed_dc.source_name + if source: + source = "\n\nTekst opracowany na podstawie: " + source + else: + source = '' + + contributors = ', '.join(person.readable() for person in + sorted(set(p for p in (parsed_dc.technical_editors + parsed_dc.editors) if p))) + if contributors: + contributors = "\n\nOpracowanie redakcyjne i przypisy: %s" % contributors else: - source = '' - - contributors = ', '.join(person.readable() for person in - sorted(set(p for p in (parsed_dc.technical_editors + parsed_dc.editors) if p))) - if contributors: - contributors = "\n\nOpracowanie redakcyjne i przypisy: %s" % contributors + description = 'Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl).' + url = '*' * 10 + license = "" + license_description = "" + source = "" + contributors = "" + output_file.write((TEMPLATE % { + 'description': description, + 'url': url, + 'license_description': license_description, + 'text': unicode(result), + 'source': source, + 'contributors': contributors, + }).encode('utf-8')) else: - description = 'Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl).' - url = '*' * 10 - license = "" - license_description = "" - source = "" - contributors = "" - output_file.write((TEMPLATE % { - 'description': description, - 'url': url, - 'license_description': license_description, - 'text': unicode(result), - 'source': source, - 'contributors': contributors, - }).encode('utf-8')) + output_file.write(unicode(result).encode('utf-8')) diff --git a/librarian/xslt/book2txt.xslt b/librarian/xslt/book2txt.xslt index bf78d41..317e581 100755 --- a/librarian/xslt/book2txt.xslt +++ b/librarian/xslt/book2txt.xslt @@ -18,7 +18,7 @@ - + -- 2.20.1 From e2bc69b731434e6929686637ba4cf296632138e2 Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Mon, 21 Feb 2011 13:08:51 +0100 Subject: [PATCH 12/16] bugfix for with tail --- librarian/epub.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/librarian/epub.py b/librarian/epub.py index f2987b5..a615b7e 100644 --- a/librarian/epub.py +++ b/librarian/epub.py @@ -84,13 +84,10 @@ def replace_characters(node): .replace(",,", u"\u201E")\ .replace('"', u"\u201D")\ .replace("'", u"\u2019") - if node.tag == 'extra': - node.clear() - else: - node.text = replace_chars(node.text) - node.tail = replace_chars(node.tail) - for child in node: - replace_characters(child) + node.text = replace_chars(node.text) + node.tail = replace_chars(node.tail) + for child in node: + replace_characters(child) def find_annotations(annotations, source, part_no): @@ -106,7 +103,7 @@ def find_annotations(annotations, source, part_no): child.clear() child.tail = tail child.text = number - if child.tag not in ('extra',): + if child.tag not in ('extra', 'uwaga'): find_annotations(annotations, child, part_no) -- 2.20.1 From b92b58ba86f08f04b4f0436479d3d73ce0c03f00 Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Tue, 22 Feb 2011 11:43:04 +0100 Subject: [PATCH 13/16] #950: visibly mark author's annotations, add pdf cover option, add prestigio-pdf packager epub: minor fix --- librarian/epub.py | 4 +++ librarian/epub/xsltAnnotations.xsl | 1 + librarian/pdf.py | 21 +++++++++++++-- librarian/pdf/wl.sty | 42 +++++++++++++++++++++++++++--- librarian/pdf/wl2tex.xslt | 22 ++++++++++++++++ librarian/xslt/book2html.xslt | 4 ++- scripts/book2partner | 31 +++++++++++++++++++++- 7 files changed, 117 insertions(+), 8 deletions(-) diff --git a/librarian/epub.py b/librarian/epub.py index a615b7e..0f23923 100644 --- a/librarian/epub.py +++ b/librarian/epub.py @@ -84,6 +84,10 @@ def replace_characters(node): .replace(",,", u"\u201E")\ .replace('"', u"\u201D")\ .replace("'", u"\u2019") + if node.tag in ('uwaga', 'extra'): + t = node.tail + node.clear() + node.tail = t node.text = replace_chars(node.text) node.tail = replace_chars(node.tail) for child in node: diff --git a/librarian/epub/xsltAnnotations.xsl b/librarian/epub/xsltAnnotations.xsl index bc5693e..2d05f1c 100644 --- a/librarian/epub/xsltAnnotations.xsl +++ b/librarian/epub/xsltAnnotations.xsl @@ -38,6 +38,7 @@

    + [przypis autorski]

    diff --git a/librarian/pdf.py b/librarian/pdf.py index 5f6f0a2..476fbee 100644 --- a/librarian/pdf.py +++ b/librarian/pdf.py @@ -167,7 +167,8 @@ def package_available(package, args='', verbose=False): def transform(provider, slug=None, file_path=None, - output_file=None, output_dir=None, make_dir=False, verbose=False, save_tex=None, morefloats=None): + output_file=None, output_dir=None, make_dir=False, verbose=False, save_tex=None, morefloats=None, + cover=None, flags=None): """ produces a PDF file with XeLaTeX provider: a DocProvider @@ -179,6 +180,8 @@ def transform(provider, slug=None, file_path=None, 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 + flags: less-advertising, """ # Parse XSLT @@ -192,6 +195,13 @@ def transform(provider, slug=None, file_path=None, raise ValueError('either slug or file_path should be specified') document = load_including_children(provider, slug=slug) + if cover: + document.edoc.getroot().set('data-cover-width', str(cover.width)) + document.edoc.getroot().set('data-cover-height', str(cover.height)) + if flags: + for flag in flags: + document.edoc.getroot().set('flag-' + flag, 'yes') + # check for LaTeX packages if morefloats: document.edoc.getroot().set('morefloats', morefloats.lower()) @@ -214,10 +224,17 @@ def transform(provider, slug=None, file_path=None, style_filename = get_stylesheet("wl2tex") style = etree.parse(style_filename) texml = document.transform(style) - del document # no longer needed large object :) # TeXML -> LaTeX temp = mkdtemp('-wl2pdf') + + if cover: + c = cover(document.book_info.author.readable(), document.book_info.title) + with open(os.path.join(temp, 'cover.png'), 'w') as f: + c.save(f) + + del document # no longer needed large object :) + tex_path = os.path.join(temp, 'doc.tex') fout = open(tex_path, 'w') process(StringIO(texml), fout, 'utf-8') diff --git a/librarian/pdf/wl.sty b/librarian/pdf/wl.sty index 897535e..28a23a5 100644 --- a/librarian/pdf/wl.sty +++ b/librarian/pdf/wl.sty @@ -9,7 +9,7 @@ \usepackage[overload]{textcase} \usepackage{scalefnt} -\usepackage[colorlinks=true,linkcolor=black,urlcolor=black]{hyperref} +\usepackage[colorlinks=true,linkcolor=black,setpagesize=false,urlcolor=black,xetex]{hyperref} \setmainfont [ %ExternalLocation, @@ -100,6 +100,34 @@ Letters={SmallCaps,UppercaseSmallCaps} \usebox{\ximagebox}% \raisebox{0pt}[0pt][0pt]{\makebox[0pt][r]{\usebox{\xglyphbox}}}} +\newcommand{\makecover}[2]{ + \pdfpagewidth=#1 + \pdfpageheight=#2 + + \thispagestyle{empty} + \newlength{\PictHOffset} + \newlength{\PictVOffset} + \setlength{\PictHOffset}{1in} + \addtolength{\PictHOffset}{\hoffset} + \addtolength{\PictHOffset}{\oddsidemargin} + + \setlength{\PictVOffset}{1in} + \addtolength{\PictVOffset}{\voffset} + \addtolength{\PictVOffset}{\topmargin} + \addtolength{\PictVOffset}{\headheight} + \addtolength{\PictVOffset}{\headsep} + \addtolength{\PictVOffset}{\topskip} + \addtolength{\PictVOffset}{-\pdfpageheight} + + \noindent\hspace*{-\PictHOffset}% + \raisebox{\PictVOffset}[0pt][0pt]{\makebox[0pt][l]{% + \includegraphics[height=\pdfpageheight,width=\pdfpagewidth]{cover.png}}} + \clearpage + + \setlength{\pdfpagewidth}{210mm} + \setlength{\pdfpageheight}{297mm} +} + \renewcommand{\maketitle}{ { @@ -112,12 +140,15 @@ Letters={SmallCaps,UppercaseSmallCaps} \end{minipage} \begin{minipage}[t]{.65\textwidth}\vspace{0pt} + \ifflaglessadvertising + \else \href{\bookurl}{Ta lektura}, podobnie jak tysiące innych, jest dostępna on-line na stronie \href{http://www.wolnelektury.pl/}{wolnelektury.pl}. \vspace{.5em} + \fi - Utwór opracowany został w ramach projektu \href{http://www.wolnelektury.pl/}{Wolne Lektury} - przez \href{http://nowoczesnapolska.org.pl}{fundację Nowoczesna Polska}. + Utwór opracowany został w ramach projektu \href{http://www.wolnelektury.pl/}{Wolne Lektury} + przez \href{http://nowoczesnapolska.org.pl}{fundację Nowoczesna Polska}. \end{minipage} \noindent \rule{\linewidth}{0.4pt} @@ -137,6 +168,9 @@ Letters={SmallCaps,UppercaseSmallCaps} \rightsinfo \vspace{.6em} + Źródło: \href{\bookurl}{\bookurl} + + \vspace{.6em} \sourceinfo \description @@ -325,7 +359,7 @@ Letters={Uppercase} } -\newcommand{\pa}[1]{\NoCaseChange{\footnote{#1}}} +\newcommand{\pa}[1]{\NoCaseChange{\footnote{#1 [przypis autorski]}}} \newcommand{\pe}[1]{\NoCaseChange{\footnote{#1}}} \newcommand{\pr}[1]{\NoCaseChange{\footnote{#1}}} \newcommand{\pt}[1]{\NoCaseChange{\footnote{#1}}} diff --git a/librarian/pdf/wl2tex.xslt b/librarian/pdf/wl2tex.xslt index 5a49a01..58be05f 100644 --- a/librarian/pdf/wl2tex.xslt +++ b/librarian/pdf/wl2tex.xslt @@ -16,6 +16,22 @@ \documentclass[a4paper, oneside, 11pt]{book} + + + + \newif\ifflaglessadvertising + + + true + + + + + + \def\{} + + + \usepackage{wl} @@ -44,6 +60,12 @@ + + + mm + 210mm + + diff --git a/librarian/xslt/book2html.xslt b/librarian/xslt/book2html.xslt index 682ed9b..8e1a574 100755 --- a/librarian/xslt/book2html.xslt +++ b/librarian/xslt/book2html.xslt @@ -416,7 +416,9 @@ [] -

    +

    + [przypis autorski] +

    diff --git a/scripts/book2partner b/scripts/book2partner index 6955899..136fffc 100755 --- a/scripts/book2partner +++ b/scripts/book2partner @@ -9,7 +9,7 @@ import optparse from copy import deepcopy from lxml import etree -from librarian import epub, DirDocProvider, ParseError, cover +from librarian import epub, pdf, DirDocProvider, ParseError, cover from librarian.dcparser import BookInfo @@ -111,6 +111,31 @@ def prestigio(filenames, output_dir, verbose): } +def prestigio_pdf(filenames, output_dir, verbose): + 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) + slug, ext = os.path.splitext(fname) + + if output_dir != '': + try: + os.makedirs(output_dir) + except: + pass + outfile = os.path.join(output_dir, slug + '.pdf') + pdf.transform(provider, file_path=main_input, output_file=outfile, + cover=cover.PrestigioCover, verbose=options.verbose, flags=('less-advertising',)) + except ParseError, e: + print '%(file)s:%(name)s:%(message)s' % { + 'file': main_input, + 'name': e.__class__.__name__, + 'message': e.message + } + + def bookoteka(filenames, output_dir, verbose): try: for main_input in input_filenames: @@ -154,6 +179,8 @@ if __name__ == '__main__': help='prepare files for Virtualo API') parser.add_option('--prestigio', action='store_true', dest='prestigio', default=False, help='prepare files for Prestigio') + parser.add_option('--prestigio-pdf', action='store_true', dest='prestigio_pdf', default=False, + help='prepare PDF files for Prestigio') options, input_filenames = parser.parse_args() @@ -167,3 +194,5 @@ if __name__ == '__main__': virtualo(input_filenames, options.output_dir, options.verbose) if options.prestigio: prestigio(input_filenames, options.output_dir, options.verbose) + if options.prestigio_pdf: + prestigio_pdf(input_filenames, options.output_dir, options.verbose) -- 2.20.1 From 12266a4397d9e344b7f95a19edc4a8df7cd5f9f0 Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Fri, 4 Mar 2011 09:50:19 +0100 Subject: [PATCH 14/16] vendor packagers rewrite --- librarian/cover.py | 15 ++- librarian/packagers.py | 144 +++++++++++++++++++++++++++ librarian/res/cover-gandalf.png | Bin 0 -> 13175 bytes librarian/res/wl-logo.png | Bin 33773 -> 34275 bytes scripts/book2partner | 167 ++------------------------------ 5 files changed, 166 insertions(+), 160 deletions(-) create mode 100644 librarian/packagers.py create mode 100644 librarian/res/cover-gandalf.png diff --git a/librarian/cover.py b/librarian/cover.py index 27f7a70..9070344 100644 --- a/librarian/cover.py +++ b/librarian/cover.py @@ -124,8 +124,8 @@ class VirtualoCover(Cover): height = 730 author_top = 73 title_top = 73 - logo_bottom = 0 - logo_width = 300 + logo_bottom = 25 + logo_width = 250 class PrestigioCover(Cover): @@ -173,3 +173,14 @@ class BookotekaCover(Cover): title_font = ImageFont.truetype(get_resource('fonts/JunicodeWL-Regular.ttf'), 140) format = 'PNG' + + +class GandalfCover(Cover): + width = 600 + height = 730 + background_img = get_resource('res/cover-gandalf.png') + author_font = ImageFont.truetype(get_resource('fonts/JunicodeWL-Regular.ttf'), 30) + title_font = ImageFont.truetype(get_resource('fonts/JunicodeWL-Regular.ttf'), 40) + logo_bottom = 25 + logo_width = 250 + format = 'PNG' diff --git a/librarian/packagers.py b/librarian/packagers.py new file mode 100644 index 0000000..285a15f --- /dev/null +++ b/librarian/packagers.py @@ -0,0 +1,144 @@ +# -*- 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 +from copy import deepcopy +from lxml import etree +from librarian import epub, pdf, DirDocProvider, ParseError, cover +from librarian.dcparser import BookInfo + + +class Packager(object): + cover = None + flags = None + + @classmethod + def prepare_file(cls, main_input, output_dir, verbose=False): + path, fname = os.path.realpath(main_input).rsplit('/', 1) + provider = DirDocProvider(path) + slug, ext = os.path.splitext(fname) + + if output_dir != '': + try: + os.makedirs(output_dir) + except: + pass + outfile = os.path.join(output_dir, slug + '.' + cls.ext) + cls.converter.transform(provider, file_path=main_input, output_file=outfile, + cover=cls.cover, flags=cls.flags) + + + @classmethod + def prepare(cls, input_filenames, output_dir='', verbose=False): + try: + for main_input in input_filenames: + if verbose: + print main_input + cls.prepare_file(main_input, output_dir, verbose) + except ParseError, e: + print '%(file)s:%(name)s:%(message)s' % { + 'file': main_input, + 'name': e.__class__.__name__, + 'message': e.message + } + + +class EpubPackager(Packager): + converter = epub + ext = 'epub' + +class PdfPackager(Packager): + converter = pdf + ext = 'pdf' + + +class GandalfEpubPackager(EpubPackager): + cover = cover.GandalfCover + +class BookotekaEpubPackager(EpubPackager): + cover = cover.BookotekaCover + +class PrestigioEpubPackager(EpubPackager): + cover = cover.PrestigioCover + flags = ('less-advertising',) + +class PrestigioPdfPackager(PdfPackager): + cover = cover.PrestigioCover + flags = ('less-advertising',) + + +class VirtualoEpubPackager(Packager): + @staticmethod + def utf_trunc(text, limit): + """ truncates text to at most `limit' bytes in utf-8 """ + if text is None: + return text + orig_text = text + if len(text.encode('utf-8')) > limit: + newlimit = limit - 3 + while len(text.encode('utf-8')) > newlimit: + text = text[:(newlimit - len(text.encode('utf-8'))) / 4] + text += '...' + return text + + @classmethod + def prepare(cls, input_filenames, output_dir='', verbose=False): + xml = etree.fromstring(""" + """) + product = etree.fromstring(""" + + + + + + + Jan + Kowalski + + + 0.0 + PL + """) + + try: + for main_input in input_filenames: + if verbose: + print main_input + path, fname = os.path.realpath(main_input).rsplit('/', 1) + provider = DirDocProvider(path) + slug, ext = os.path.splitext(fname) + + outfile_dir = os.path.join(output_dir, slug) + os.makedirs(os.path.join(output_dir, slug)) + + info = BookInfo.from_file(main_input) + + product_elem = deepcopy(product) + product_elem[0].text = cls.utf_trunc(slug, 100) + product_elem[1].text = cls.utf_trunc(info.title, 255) + product_elem[2].text = cls.utf_trunc(info.description, 255) + product_elem[3].text = cls.utf_trunc(info.source_name, 3000) + product_elem[4][0][0].text = cls.utf_trunc(u' '.join(info.author.first_names), 100) + product_elem[4][0][1].text = cls.utf_trunc(info.author.last_name, 100) + xml.append(product_elem) + + cover.VirtualoCover( + u' '.join(info.author.first_names + (info.author.last_name,)), + info.title + ).save(os.path.join(outfile_dir, slug+'.jpg')) + outfile = os.path.join(outfile_dir, '1.epub') + outfile_sample = os.path.join(outfile_dir, '1.sample.epub') + epub.transform(provider, file_path=main_input, output_file=outfile) + epub.transform(provider, file_path=main_input, output_file=outfile_sample, sample=25) + except ParseError, e: + print '%(file)s:%(name)s:%(message)s' % { + 'file': main_input, + 'name': e.__class__.__name__, + 'message': e.message + } + + xml_file = open(os.path.join(output_dir, 'import_products.xml'), 'w') + xml_file.write(etree.tostring(xml, pretty_print=True, encoding=unicode).encode('utf-8')) + xml_file.close() diff --git a/librarian/res/cover-gandalf.png b/librarian/res/cover-gandalf.png new file mode 100644 index 0000000000000000000000000000000000000000..3c1513296a97a1045821d42831219fa8ff16f990 GIT binary patch literal 13175 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 literal 0 HcmV?d00001 diff --git a/librarian/res/wl-logo.png b/librarian/res/wl-logo.png index 03b46b5fd6ab6ddd869a20b7c7005f8f342c2b88..1194a1c2809fc85ae623674cc4fd81f48589411d 100644 GIT binary patch literal 34275 zcmd43Ran*S6E=zhQi61c(v7sVG?G$+bO}gEcPSkLf^nC^x!BXO*4HOg-2ITt*R9pfscoEL_os1~l%u_-X zWH!l6wJRv7mr(CS1eF}8cjsI*BJAb`?k8ThK#>{!P<;0i-j@pV#gD)^wIo_oQ}u#^ zxmgtVs>&OegS}dpstXH;gUT6~gUW)t+A({^2KAn7wh=Zgc6iYzkx+uD<~m|{{m{?h zdk_^s(Ex85VxjI=OP4CkY-isqplF{OW#JKM5=H_|^VW z^6xLtQ~&-H`R|wi{pEkZ{Qv*u|E7okTkZeBn*P6UN$QH%T>O~(o#(yorOsiK1&X%s zr9bT8=d>xV$75Q>#LpWu`NZky>xD(|-f))9K>e2mB0AZ=pzWcw2%MZ>XjKT2*yCHD zry4ZTuAsOom#7^dh1E*W61r2h+U7jZeEe%VwQS!R>KVgTX-JcCf0wAuy>bg1ha-Qh zEe0wPZ=#~pJ0fn`wrTlis*TX~UcV4DVT|=BnIMloPhEXJ*HF;rd|S~n>Y((7)V2(j zfCX--g%vGRYCW4KIKR>U*BW(xfzw-Yv}<*Ny89UXW;!moxbC_sZO8y*{)#qyBJz85 zZxrh0QwGpB<30U{M$j-Ke2Ry1{840$x_;{0CHPhxN&T{W7;G7NRumwfg78P@0S$Zw zqlWl9`@h!AZA(rosC#NYhn3A?PJGKLyG0@Taa-4%=V?r3TGO8Jud0#86OCIa9aIWZ zQc^us3URohBeLWA3E3^=QyD>xZlQJrJNf=_H?Pd&RdMG*2F0(Yvqi)1SQ+=K{x4T)FpcEMcQO%diD3jg<76 zymk2SLFJ<583xA;nO&@E_&LXOhOYMu;V*vHT;_hR=*Q0KX}@HCLCUZ9Bs;Pn#n?_=DC(X+(5Na49&PoP1^#) zpEZcV>xf{m_Y>C5TWOilu%XLs(UzJyblY!`cYF%SShu(Km}(10cQT`Y)ojr;%KeiT zdN?|c=h%q&e@3epbjIIY-2~&S1rAPXg>;4}WXWyGfK!V3Mc?k-YuRo58O)M(YLQZ~ zLkQJ;;j1J4-6i5CU2E$mOwM$UB$0r>;cf}bkpwjXS!R$P>aDg_pe5=W@uLX=a;c%* zNpzX3SJ8Jap-H(P+o&G4!BURdGH4A$c|x-p@4%CxS9FkV+3qtNVmT)w0yjWtuWH7k zvNW4RAqfq&h#>8jCJ?45^x8Vo$PRB%|x-s>p?91K#o)*@{ZS#QqvxC&8b={V( z(Ar3Cr$=E9o~d$-*<9T6+{5X++T3ENQz+r!esh=m(zp`${Y){*S%DJ@Qs$f+rBXac z+O(}*brNP(f8k*D&ZtRz(Mew57%qX?eXqUw=(4 zlf^RBw7%jv)pbWe1ro;WA6~XqKIA|82~jqYy`0ddds-@y1OGE;q1beAw75ZhuW~lK zn@?Hh03mneMJgAGw(@FP<0qo^3|^)yE4~K9ayu1xBNm$sBk7?#_c^17j^L1)8H{Ko zgwIb6p#*JyA;ehD`Dfvp`gLzea7JoB{d&74y)RA(E?Jt2 zi9Y6i&LH~6XgX-yH&it1PvGZW>NU9L4?pTI5%SNNsCllp_FfbfcQMLUAlI2Yk|pW& zX2HZac+NtoDMJ2L z;M07yF}QFYo4TZkQTrTTeY1YYc!tdN?cmeKsefw=*Arg%2PeshAyQ;(*OJzw=!nc9 z4wUMxLJJvJT7yC$YAk~tl#*J0wiQYKnTImv*O2#@^|bzh-&akZepw2J=+)zjxE(Wf zZY1(CD!Q66wRHHLo%>#w6Sm=G(7}?}^xM8Ixf7USaJFkWigH$sKW|mL5I<_=M|bq$ zf9_r6O?kYJ)CcgPfv=xWZClv_%XY1|d2wc5NSiZv^71Veo6;syO0(%qC`2#P0^F*%iZzN@-}YC^ zrK-2hj?u0I1w^D|mrs5=wf#MZa5{J-2@JC$i$29QJD=_FMIKs>!#}4i!@!!Idz^|IQ}!Bu*|PoJJj)~Lvzljfse*9 zE8;L0lPmgo%F92`EwatxGca~oBBfc^plr!ro1Z5xP{Ew*SX5wm)bNR25U+kI0H7vZ zk>6O}+u<-XGqrR&mAFby=0{6XBB5MH+%LB@R=Rkpr{x$~`KqjvZ<)R^4>X%D5A~P| zXu6%+P!}xtKQn`@1e_2KI!?Jp@!Vi)zx)tTh}01qxoysONEK*EV5kg_9*V*lS}X2~ zPEI^6gaeHv_xMvIyHMP?AfF<3OJ)n(fBT`(!!q1aKUQ`z*Bh~6iaVhQzT7S!O8wSQ ztDBde(}?mSHCWvYjztr@o|3pDd&}k@?NPTCghFp4++| ze*q3AU3!3Ftchw%gJ$Rje5H0_yNiwiQ}s%@&JeN8>U0lT@)uNoxR2YSNLZg$vmark zV1x#PeSuHjBi zFg+V9RWztS&YtV+Iv+>ii8GHmoIGb@l&Lubs@cS5DKNlJHvi`9@nsJyknNA-SKO-r zz61!vj`|6CvW3v8zUSUpW?z3|lIb)fVfU=98Y8{{TH}6mM}5gZS&R%u9>6Btsx$6a z+2dgRdU>kBwZzP@|7u7-frD>CA@n}e!OV|YGiv6GHfb$C8+8yT$G?-|9@?rw&nl`V zr5Ulw_@bCLA{K{d=aOE#a746SuGixY*_r~A1c7s3eLs-tJ1_>mZ07j8^>1f2}lXq9i(h2MglgdD! z-7YNqKE^E1DBY>h880F1_Y340dssU^w%9LI{Ow4`*Tc?@^?Zts1IRCLqG#qTx?v(0JDqJ{Re^ zWmwE_R0pBaD8N{FyfjNucNZ&=Aw3AI5?}*59sBnj-!ZgjZdBT-{Q9ktF}))N1hTlH zc1d6PG*UH;w5a=R|K=6eRAmRX54xl#d%$l!wNltIbHr)`Z zD067-hF=-5J~L5+pXvktO<^9M_5qA(Hhz+swgMR8<_j&upjg z2UfW#9ddl5!hS~(Ce83AWu18#Db%LL&HKx*hmrM8|JG5V%b@p7#|6Lx;GuHsIl%p| z!I+omxQw61>J@3`ON1Hra$nrN=h%mK=J6>Ku%xum`gg>10NMmBwJP$`At&dYU$-N& zD07-A(@$!#ZM2y&Q)7s91Y&mZFIOhNGaZp#GM)HTvp22!_t|4yPQQg$lkV58H$YEH zJf$HJ49`J=KY8+@5=ZNSpfs7Ae%LVh1$P)>mcex=4LXd$fgwS zEuopY$P7RZc`_5F>aGTl-$N>s`^#D4tFJfixID5*zLrpf-i*sKQh#M||E(F~4$Yl< zZbRjfJ~1Z5=tuEp*qdFtw%EJvY_zE>&Hz`3#59efTT5^3$ufIxV{DG8RhD-ovtF+8 zcLmlsdWxzLD^h7JZ+)7W+9i>wu(MJitTAZaq7Q-tU$k~_x&srv`yzD@lmeO7F>7|+ zJf|}BM>if`hZ^7N>?Ah?4NjZHf{0QCK_!+i#pB)a)fW_PN)Fi zDLQq0J0dp(z`7L;`pq>;gicm6z-#{|`0qJ+wOKFEG`CNkGWNmeHBV_ogVGDVux2_l z8Y#53-~rwnocUa)$qIDZW{}MK<6l(ailn=6|Xu(nzN&m z=9Pt1*`r0}yrenvq?Z#9z`F5d9@81LCDcFW>X7vU*U~^CT7XK3#c;JR2a&f_Q4kIo zv#10liDw0W_>!2NL3~$`JcXiL(qupILQR_o80l{n+uAyO7j#Q6@$0{HQvS1(JSk@p ze`PiMxHi>m1hy*Y$yZ7JkaU}X0t|DuAc zr;-Aoaq5UQ8k-*{#lHdTRyTQI={A$t_Y{C3FjrJGbd(u(Y99~4R|}CqO11MScUuW@ zdWOqB?bfPOW&xyS)t1dkc{L%adZHHg zF@Ks61<}Nukr1$Xf4;{9_(+J6N+N7MN(+#j#`$!o_#9RBct!6a{_x5~OP9LQNeo~# z7HwjBv&%$hzZ(Igm)vtN7MJpPC>J;-+7 z+*q4lB##Fb(Up#mtXFK8{z7PY0UuY;$X)_D9`f6&BtYDi5=a!LPODg^+c%JI1R|-0 zL~O#rcqNuax>v#aqeWKE7_RwB~X?f8n{8R)Js-(Z-1WGUuwQK=GtSjGYXUL#XD1+H(GNl}ZGh`JzR_XS9 z=xq}^db4TZ9S(oaHp_=%P%BV?-Qx&_Y|6gKd~d7HIXJtbVsO0#Wrk-|;RQfi#aff( z)t|mMur>Z3^e*tFq(*{Q?~eC|Ov(6=*o`J{UHuxvpIEW3aFX)fC&Py2Z)l4>TxI$3+K--ci%!U>JqGF; z^Ban~T7nKwbsfqUAz%Y-svS&G{azCt1ka%#SH@QoXmGNENf7r(Xfgqxr>&e%JR8jh z0HvSIOe71fbM-ZXcd%^3m-O*2p7(~^48+ID?6vfto@xRM8m!&oysr`%>Tdn#k+%EY zf+mlT22Q>L`Nm4c?LomBEPHxQY9$6y|7?Dn+whTIiXI z6cM5AF%b$Fygd!Pnp@N3KQA3^Q+s%J&GZGvnFo*m@j3(}y1`XTu84c4g($#YXTD^= zMoaJD%ib*4q`Aqw4ngc{9j$uSR-CT~jKk)Q;U?OsydvFh9`#K1i}C9wS~b^hx=mS~ z-q8PzH!CbxgqLxBA^*iuJxqQWfX*Ml%XS13m|q$CrcbcHG9l9QWVNc^{@fxzT9>(s z(#T^^c@_`b*7H>?1+D;>g)W9bl)ga zSGDkhN%s5G@#{P>^Bcsch4I`w?CW^O;rH|mU&kAQ@2`>nNH?9G`>9Oo54Q8J-`?@@ z0P0r_$~FOto_+IR(&dgFxxUeR!O9>CA}4|o5+4DPq=e6}XvXka?-KueXzjp$MLMhz zN2=<>Y_Ya@IwQt~^n#lv)DDw6*PHO1p-(NQ%Zy9EGAyCSHcNj6Ts8G4J3~$;GjY?x zRc72yVw()&Xh5J^I?=2)3@D$r`DdMgTn15dS9^7`hO&-CU})%ENYMJNF5iPWjk?)^ z!1U3bl15mV#7>7?M6BlyAaJ_R!1}jGbE>@5yStw!PaI1+!o|gqoIHE=cW~>3BrVqd zSd_(d_mN`gSC&rOU-a7fBtq0EXd=!}<4V$2wd#_2fXwF^kyJduIsg*d@UA!r)d_GW zeKG8BCxtc|oZR+`wYtAm?1u&x=$;|gV#Ea`A9ud|Hvvjn$5(|r7i!jej$Qd-I^nI! zLs3uBkhosu%W}tn-3>yMcpR>OEaHuYq+)~$VMMgN;D;!z7j>8^z%ePqF^Ha9F2-xL#w{(&JnF_xb7VzV*05L`? zCKpwIu2h1$4Q?T3BPGDC-D%7KVn&;un66-VjJr!Brf@dE^vTE_dCC6u=Bw^0O7#BR zk{-VchJ~}spaDV}&ul2xa-Dmn_$b;i22X2qgsc1*tnP`kAU+AicLqh@(0Z@Oc>$S= zgiRC&4Bm-ClEbxWd6Ea--3Gu$`6|5!zwmCpuRv#ewPmSnw!OWSG=6Ht?ZC|p*$uNl zI+r@&n9usehbH9_f7Uo!ntukMnm+dO;#Ck97x&>AQBWlIe7Ftp=`&VE87pkS%(PCQ zrs%gBO`7+|OG5ZS5wbt=nr~r%GvC$j+JYLt<|HTLG%@ix9#OoR{uY&1%(3TP@hMAq z+%;sBgXQ1SMJhdwXNZUN>%(m#kWz@Ubj=x{@C5_`(S=f1h&CnW3(+lHkpKxHRIJ#i zJ6P9;#hEJ*GaAD3ivs7)oP^sp9xKEh0sz3Jpna8!9NXlqO1tT{itoBi59vZ)>C#oQ zjo8tAyZduEbngwasW_evKddb#muD50Nv{GI`w@g98pKhwZ2OMs+#Yii75w^0)b&Bj9LL}^QA}ZRy0|tJ@bjSHcLe}<@ zUA2c;&|`#$abY6g5fU{)l1f(jdqkW3THp6Qg*3R280cM^EX@uP14P>ULy3sR3UI(t zt$25Szla-pg5s8R-+F{H#VvXs z?QOxrrke+{NO~3O|18ab?(aMND5i_HQYM@Rb}X`cXR(JJCbZK$Bf@LK@o}Nk_Hz59KRO z@U|ZZVHg{Ew|~=ALH4(*Gu!B+!RTtgHyu>?;$i8ysLJL>7AC)OpybI>X4Yax1KJ(C zDdybH2yhcGjh~>h5ybs^?tb|=rCf`xEdVP%@1ztmyLn*Jw3 zPMHu9>YWPN_tNf}9~qe++~PU-Fl#A=DApm?#_1NgsqZ?H^{c3W$b5j`^dx3}`lNq{ z&HOprJCDxnbOGQY;LF_?EDCNOoO-iS-*TQ=Up}vf{c!L$#Qwh-3i-Xz)*S@is`R7y zVG|r926!K&!dB}pGaM#z$tY}=XPoRYFiu5-t?Ini;s12=#(np{9m{WoXl~vvgc8;E z1=i8K#B!vv6wOko z#*s`~t(r=kF2?eQfn<@;lf;hCMUdM7;>M=;jCMZm;oMhv+zoP`_G=2F;(UI?=YQfo zcZ7-%+or0x8ug5 z@$sXSDTKc^I%bH8z#Vu&^G|`CHFERC!8i5r6T2Qk!s}l#pN80Zs6byt*QMd-r-H%Ahwn+&8~mDI^Nrr6XA6 zzghq=O<2$3s79@9kMBa;?R8%N4Ju`N^F!Dee6?w;Vry2z6HF*uQxcL7@C7-ndJ|zQ z)I8dpmljq_DKVUD*an#yw9dhOiJFsIj!$QhYfSuH<3iiB=7z>d^8fk{+Hqz(OYivCr^t?Ej^^UEH*8pWNA%U zR)yj9+s^X&bU3ctZMlT=JKebEt5=wHSKba=*O%T&VUBHMZAE+gzn@f`K<#_(TNNKd2@Je zQSk18*}(A3mg_XzOmf9^pR&PP*ir1Z6c>QIoVyVA{&MRzS9B+&h_ruohh#68frXR? z&0S01O~=snEnGoVXsda2?q*{l(0h`49uu-`TI8hXspmh1ZCiohgaYGFcXpCU&pm^#WE+KheWck$teVma$1o zw0O|r&=Q%aOQ>Xp;XXa~8;Hm#$R8S@QjGZwjW67`7*>xksv#a+##;)jA-b|;a@nog zES}l9m1~wT7^XiPd?JixTU(j>#r-qac;js*X%W*a(&rDC7e>D9q)w%^*gQ>K9J^@K z-zHAHxL8a6x2qb<$2s5>lhetw3Qy{z(0%-T3EqC|NlU?D+0eK+;KwUNtJzs;d2qM5 za5w8MX%J%v${93F^^UjzGdG=19EhbhF+=N&3kofZWG#z6%ZJ{iet8AR25^uP0pdEJ zPe+t%AX;=-c#-0A`l@dHtG(G3YMHr5!60#GT3(n&m#r!vohr|inTABTdhd@Z z&p9{*0I8fbg{&am{ASFI4=WP$F$EDcJ7ZITI5C5cldzT z>a-NyD<0ap7T-Tm^V6CH4R-`X{gugQgJ?(|8f22hRyN$m4I34=fRBH=uf8_OCw=o= zEdG^JopH|YNi0Lus|Pn}IU6=wL5DmzZc#e(38F0WxauY9n0?{}U5h z(E(0q>z3v-Ar0h;pS^$4_EIviY}GwD~*=Qc@9!j(GFmKNm&`NnyQUpE7#VSyo6zm_jeWOBQm?XbU#R< zuS+*}Y)wE)fZCz{fP{!`PANW-g@xcoCE+Qjw(aD}<~TpfUN|fY(H&u6fk_S2V%2Lf z6~W#Cl_S5tepw#}2=YmG1$gyz%^_PWQ1i9Ri=t7OHGV6r|7vZ<(h$(Qhsz-GXXs((!4?7E*nfQA?nb>AMeQop(YQKvhKpB^i=+M#j}&uS!bKcP|x zCi2)X4Od}R+b*lecQ{8ZLv*??ZVi3uL{gKB$E@;mG<`81xsL=MyN25gVavV!HEgU9t z*okD$1(vM3o7+s6s7RzQswtPC$&`2s$9~R{@P{wMQ;X-R`=O#10#ritm=$v|i)c3b z6u63G*~q1z^=Y0r>5rVCtMfA^`zOd5XQ51Q$i1C?M1-o&t-LL6P??n}Antb1aA7=YqGp=T{t|Jn}b079v0!^q|0*%MEENrFJ`& z2St&d?s1~IR7$dg(UiQ`U@ZzM2GQQUVP#OZblyk7@`I$&@vjblKWdcT zZ@OY0SF!zT+$VVlHaWRf_GjPTg2WfRqd`UaugEy^N%z$2{7o)kagm;>L0ujjhnd_s zPo4hen5o1`dT-uMNlKa;hV%=PuC(1!4KO|&EpT(SoGz&I9-u?OqB)k8XhHrR5Z=#f zUVmuS5y>9j5AkNOGXmVMA`OB{2JIIGOpVKr?E3RxAad#l*s3M$EtLP|As>vugSxU@ z9o7zX3aRKly14KYorG@gAGKzJpKB$F6te>ijY~vB7S$OT0^>BDnvL~^h+0+lh?3vD+fH>C-yw| z2(f^ir83${cA*i&7`XO;yR4shYmGxZ;)hxO+c@wIn_#CM6*!f+<)W?7OI_^cy zC8rVmnFfYgHPF1VhMjR^F|0eg9)v_sG`F3GF3oZtW)n^w;{oGrY?3Iddb$NQWl|L& z@s#hSe8RyFEEikpEE1w~COdkmg?wIl*M7d1ZTe_+1WD}D-Z zQ*(ArSY$R~R4W%Upu=IeP!t9O^dp3ZI1@e303$%TJxg0OehFoaGvF|@Q&s8E3=ljA zWKl0nla)&DL@uzRCHW`3g4Pi#^JTANjTuhTExa-O(AxPlA;;$-MT zeu(Li#jrgG-~_SqW})s6*p8x(TA_->YH<)7@Pc7{f{p~y^~2V`H`K@!$|d>~Rik?) zaLg85v)@`9Lkf3%-y8A0fTr=H{%v4>@OHwlmCSR$-aLrn!t``p3EtO|B9M(Cfwum| z=F!Ml_yD`bA8=SENv+(JY^o)L5E5y1cd_R^@NwvNYsBb$orzWE%uVMZhZPSx8KeV0 z*{wWvZu<49$djea7$|=2)8soCB0L-(0pMG21y~RXHq2TfY5-13Q>e77|Ku*X3E0k< zs{>t9J)bVb-c9_GIytRc5?BQyo$hGnVTYUYcY(0#DrIlI{)Jrmpu^nqMDK1ovsA(F93uMGxH+KmF`Nzp*MkYl96+=7QckS0{HKv zb%>9MMoFm@qG9%T=7oS6i$-cf5uECS^4Sp11uU}*?HcK!jd&JD!D7vRYD1uoo1p5V zWqi#uyE`ehE;M-+8A3|sBBThzD#)RLYe^y&X_{r4T5!z}Y7xo8TwN1A~ z0~YhX30_y>l~`y+)~!`s;C+8o zj=J|@sUeI=<9BNZsyD~+lQAc-);+W(SMQ%B&4qhW5F`o9BwDF1S#6YHgkSuQVBxE( zE)}ad7y$~H>INz2TP*~mN6acjcN=Gepa#Mp^_Y^#hNXJA?D4HeDWgn{&rbRH-Iu>B zPR)zhs&PV;9Z)_|lgyw)2IVec+`_S0a0(8)(9h&w7*5^$=+uqN0Hb&lggG{fXYMeek(nYtrk?1pj6dJ9RRft{5Hi0~-}L;eH|$tYqUS>xhDA+X{$|$OV!olj4(CiIn$lC^-0VzUJrj zvXukU8dNX7R)4PI*Aw zS~NtHva&xg5f=_Ch=zvM${Bu5#-?NCb#Z3Q+xTPiYk6Y=cF@%BBKGj}5&G$A+>|c3 z5nAN*LVQU)5xyUj*Y80{R5e>EYIg9x>Bik(en?){h3|>GT7E2#)L~4YA0j!<@^4h9 zfl+=w2l-mdj3qCMh2!<8>_64eAU{9c$aF1Dojcbq3(^nPUJzSCMj(QO2uysYoI}q} z<*oqvtN`?wGr8x;s(M~i+sHiM*pFgo7^fVs*y z_mI>)aL;kvWEPePwM@SW@GN!;b(SD9RMdo2N8imA6AI$T$8X@ncQJv_X6u<}f|+qM zlC`Nb#g32K@i@pub1@f)VO1<{0Fr!s-8GXXgU%N{`c$IOxS!#-=N^TTiK7>fMA{V_ z&o^KIS^?7Ly}Mi~Q9_0_l}Mex%PEB4_*jH}t^rhl z*lqHBytuLE9@N zseAK_C)ffY)ED1kD8fWZ!7H1yei$qqxR`825F$T_cK8Ln$nUhVsFzIb@kcSNtgSy`>=; zP?cR=QqHu|=}s9go-lR8n**N>fy;=*KCm6j93{uPXUQ}_=eC_eBxk!nN%4kgN`Az; z4?S=0X>;JzGHfci7H5Ma-j?(Ae#Wu;X-?p8UK?{d*jpuLr@xFNysLLQ=0d>L}qJFiGQO(z2+UEp)oPtOIbV>(-UFN}pnF??B>7~DyVE+Ip46J! zr|>CeVB$}!XwYtH1hHl!?$;n>J2-yXpZO}pq-F4dAJ zpE^AXEfW4F+>E*=Q$TMCC@tgh^d}!-^#@>*g)xzz%=tT+I9x_?rNb|}3)EWsy+}=4 zV`>PuR=nw^&Wc0j0?+Mu%XbL zGAsLKAMZA$?$`Tb%{t>P{{{{Kr;1%`NY*Dn8-yz$jhU~bAH?mjzQVPOdLuj=szli$ zD;VjdLVPv^c<9ypZ2@p1eq2@L`oNq?%hpe=d3^>R2?0$v`?GPmleA2td}LZfKW1UP zzsb*faQ|U8qwFNa#|xoJchDdy7lwgZf+zr_U}YF#Nl27aLN$KV|8S~?!DtfJPlM}g zQhs41TkyGL4reFgzBYx?Ue09q(pO+-0A0p>Sr6u^cAF*#@$*}N+NInxSrvc6fJ&w; zA|AyU*?X569Y&q5;9sD44pcI}{*E3dK5Wbuh(!izA^LELL36mm(^KLTSeRfx)8Npg zw=|**olW-pqYDHw+a_+lH^Ik0s+xoQItK>@MaN1B*`z^625Gb04*K0oj%jt(kHN|( zEKVm#xCOzHcQO0?7`@ogpc2Y{5uOXEC}`PRg#pBF^i>_uQ>C1`Y?0F#g3eHz?h|_w zE|i{gra{Ha;M9%tzXbZ?g;yjo#@ju1uKP~iqS$)tayG!JIvDlg9#v%Mr8W39t#QjU zpJNl57@^u#`w#sz{}OF8ln@Gv^~G_5LF3Mmu#gCfil#*bUs*7&$kv~?j;qy&elK5% zhUxJ`x0G!Rat4~0STiJlpBm)5qP{KN5Mt$SUb~r}9OYfs)gQZc${$vSw2Ko%F6eRV5C4@_6`c4Ml6LPW|Kyf^aGEo5 zHv{qvr><0Vq1U1tBN!NdxLz&f1YznfIIMF+teNHM))Wk&#ObDd0~eZ_%@P$I9IV08uO55f~! zrR0v5aEmZ)Es8f|c5gt0!c?Su*NA@5Jf8t{RZmjkDY|~Df%Xi5Ch1*W2)M*^t+MJ;Qmpn$iF#o^;50_eYF>akxM>b+m59Ho-6GC8!pICP?D zNEF0`BCd7&rkEM|41~$CQQXzq#xjX$0GJgQRVxjVici$qA1Evy-)DS2vhrF|`cw1+ zWC>xsAaU^X)Tg^e3F=)hxm#;*q+gd~mRMpwHiem%R66)$qgfk5je!J8(^}9RziaMX zv;S7EQ!L=NUKW)T!bwV6UCv1Q6)+LKhu}=#&b-#o&aQ;u68t`|U@$XM;v7l@85 zz11fn+a6(skh&vcijQxVlJiOAg4fOt6y%k9QPXX3zw$Tf3V1dI`q_REKfv$=`FB6r z_GO0H13oo5_Y}qC0V;hC*NwSAf-mpB0SW!WwViWv^3(3t39g`ukOo@O5iXE;kK39M z#L2dkwZkbIJQp!f6PJIUio+A1NFS$cmh8X!Ywo%Qoa z9zMK!CLfx%dOh&%b0vQ)-WQ(fcjp8k!2%32gpN(pzIh2aPI--wUVzK zK>mc=JYO?Ze@&z77!QjYFbMP9L!IZ=AG>U5xgchQD-3YTbGoB+3m3%ByH6=?n9 z`;urZryXBEu$_VJ{>xvY^5hF|S+HOPq2vXVfcQ+=fF!?GoiPpMa28t4W`87fqbR{6 ztwH@nUjf-7cT1i)5ZLsO61+dt4Mr=$-mCB33p6SP#%aBYX*G(Hwrm z?)*ni+r4c??=>w4e&d$nB-g6KGcg%BkeGX~X+bzd(~#7D@$5<9kMWr(b2AMkVA3>V9HJ@ldCsiwQwk$}UHBskB^*c;6K?`bjeP zeedUC5s?siMI#X*dee;8{^&VBN^)XNF|b%(XE==2_wIP+yr((GnJ8R8HAXu(TN<7- z((B@i8OVPBuFEQp4J}MRh5;J_Z^9(KjP+T0S`b=nb!K8fIEzxq+?Vv@`&d<A*0;KXllCICgq<8vUZL%*(q24N~!t;C+#Bqo+`mYus!e8Pe^i1au z*Yht+!y_}D{WiabrsK(psHz4dx?qR)5$&I%X`-a2JWnlb4bpr|PBeiRURUaX6b%eA z&p?Wx(sjfZ;3s&#`%CCjD6{XvfD^)jPqoiyH8aXkQ3wF$<92{^f|5HTfo3FlUD6&G z%?T!0tW6fun9clYV`mZ}9Z>;kMI*ozL(^}n^#Gq#50^-%LT&0DBrTKv3@weS$NhPg zr4>Dw&#!3)XD|TsciQ~^(e{wXVma~SBb10c+%HSZ+|uicyD+4rXaUT}=P+Ze{@l;= z)`2gDdMRzB-Jz>8-J0=R!$-^p7QgQkD1`o&)JO@czh5|+fnw>W6)ULB&Mc7b_e?3l zY{uVf^U+}GeWumh;@_kgZc&jyYp=F)M9-iCTRXFP8*TF%D=q2~8WKdN+5!?p(uTU@ zdpO>1Mmh~a5XB<-hpW$jr*X4 zoe_gFy>M=g?X&K|np|^+dzar?+gNk&Ww1o3hi9VfYO1bM$O&@rt`0=}tjS$2&_U;~ z)wO^2lwR}Ebo3`bIhv(%P{j@cLr67VX}CM*a$0&Lr$pZP9?eKP=n1x$5w;hDCjxcc zd}5|6KQJpiwdqA@U!*;18lWsx&-W>~(Vvv}R{vfa$gsF0R1b9v$+2o`0j0;{yK!xH z81f9v`W&%&8rIH7mR?2$TXX>UHkzDHj}a9*$AR)#Q3?@nW*rE438M?EB|ee_HY1S* zxg`4>i!jH|{U!alfM0DCv?}wb_#VHr{dxN;gk;d^O~b#uH+qpeu&S_=6~Oy#RDLMl z;Mow841@h1gdaK`^jRehWkXPcNoUBc)F`M#R=no?WicNN5c*R$MO2(p)RE=n(mW;r*Bj~G+6%496PcaHY(O48v z@k2`WCXMqYYp`OuhCC>gpvoOs{yzVe3=3EpDw8H*n+*XEUWw39;a^Px5X6^Gp#Pfd z$ne8JotVB$4QZNy3499F`?+E)P|JDYfAQgui$cB!3i2LRvEKHBB=<&imizknP0}+^ zcFpHb)P(D=F=Sd&X3UH^+eF~K%Y5Dy zjfZkaW4%a{?{;@V3_AL#l|pLj3h+t^^9B;6lmaBgTS0z)eJCw` zFY2TXg*RkAi2~FSf19@2+%i=#kjze5^B?idPB6D~c8<&$ogOjmY&=fxc9sT|5vU_4 zuQn{7)58rL*lfNL(5Mu$1tqDogpJQZTmO1ALs)#+aT+_YD`?1gZy&C=zI=>V>48w_ z0N*!XD@z>>?jb2HXajs!N*7aUmuO?M7)GiP9RNOiLd5p4_Z750;14P?i{2m4CGW;j z<|-{Js-@Ks>bI3)UAFZ!y75Y#9R!2~hIqI8yJ#HSp@p5uNPdsLivhqG1QxrzuqCP> zvVES+OU~H5_xT?Eg_q~6E`-jWNR?BQzXVb4PVg>_kCn)%%xZMh3J|X2gKa1%2sGEwU_)B{A-=s? zx|pbWa|puQg!@^5_a8}35ECii^yC~MA7|mt@Qj@$(5RH0c>;XEEN})pr5)6}W{N zq7DI}pfyZ?|J_JbG|C-ull`yFFC`~HiY;iN{;b80bNIZq$HO1QeM?4F16_P4ESmSB z%ODH>CauV?riWz}ez`ZoYVhhaGb3YXAr00l9*B`3rH0I@J6xm0Vi1G7=gm6~7A|~ zWGTuSwUCfn#{h#W|F}Gr?!R>xn7o-aWk{g>rx`?omvf^@M!p!_{H2G)p_|GjL&O09@`5QqQ0Z8*89Nbwa_IMA0 z#S(iQDc6Y=#_`k@HypwM_WEsi6k#;U8If${ILK8w{y)vVRa9I{)HO=5mb z{&O8YJR?TS!tQl8)DTaj89{b-m(~qK(7R!hle2`w!|5j;2K}3B_1qmIVeW&#=gpK^@@z0w}7$zfa-vJpxl{p|o9J*;Mln@aU4?6E)p@Tv% z+ndfhQ2d$S>lJSIa`#i2wV;!3rdAlv5j9;cZYk9NC|%QS7ZijBjra_2@-$uPFG7s0 zo^`9Wa-Pds7k1MTl$I4){gde5%aoWfkW$??wd^XvLYP2U7!#s`BRvrFy!$ zdfh?k9b#6k?{KWQ=Q#xB7!+kLICU1}4RIDHuV#0MW1wW&wTckXgR(VHRl2P>9(8D& zk)vGBS601XIMoAT^GCi}k$*wdYM5!}#rbxeg6HBvW(%S(^PGZrjW2rD*R1%2>-vXt zgrh509Kg?QBRG7DJgH%#Yy2mpO(-9^B5^o!p9xyI!5?mM9@qJ3skKK`pg#tX=xxt~ zQ%FxYnBYi?d7UCksCSrlI;e0TG5Csd4C0f8%L>D6fWL$0?Q^=elCi`6ABHyyzjfy; zwi{2XfPXjW5MDH}zcr6fDa6$^u`uZbVolgPB%)JBG;!0TgZ7Z+M-*M{ra7bbIgrX} zw9OGd)hey*&~F>{AFTie+ARsB`UnVy{$MIvOM3She_(Na$b-}jC?>S zS!m85c5y=~5?RE$g-Cml(^IB&;U?WSPu8Rf?TwN3l=Em2AK-2+*-t56kDPAhJs2IK z=6H(9wn26(H+TiQ8$}}bk3K<<(5Yu6m#a~70%#NP#u=m9fq_@(zT|V_W{lW5 zl0Fj_%uv)(U^T;i(+~;zP$W5?zMK*_fPREePXNbj?0@QdD%AlxaWBYdmiZmhH`=TZ z-^G0o4X`Hh+nKZo$Y>FzTx1ExQdLEHmd5v4m8VHsaS@VO3l zDkYNA&K~CAFmDC?0W_d0F795nrWH+hHtOC$D^pDY%62%H9_NGW*!nug{F|+tU9(8y zKSc72Cl!m4sj(L^S^D{)#}u?z#y)Zym-)r<%#j=8L1qo2FswSgNT9Y!Yz0U2Xcby~ zT?jhz)@v9Ib^FgD_54*`FyPFk6t+X(R@b@%Vle`Z=!c?L8wK3DL6!264eU#-2aCYWpm{7l!e+4EOny@C4e@TSgES3J(qX&BPofbod1FSQnzgBfIeS6!Y z_%9ynT$4k-c|Lkxc!)O0&ZuQ|cG5o_ur_#v z)%^p2!T49ie}F2Zj3(HDCSUo~t6KVPmQ+|E6sm%wq?F2Jj?&81-q5ni5|^@i ze7~MB1-8+&M65*~1Ue_Bl6)CA{_TJ4PkYbE7Dhz%{5;=uU0<;8;k{B;<+8E%L;DRZ zuKi195@iyFPUZ3l1Ic|eE8HEcv`Lv+OZ&Prm*T6@g#BR#^F)>TgNaf}tK6-3=c?4j zw7FC+q@)d;G`%=)gR?Vwh#sF#5XCoGmItNSeKhFm4eb5GcQC0=>dNvIFz&VF37Eh`eWxyjh4nwAM?oQt#Bkv zITfD>Svqg5L(-;AiazhoYHxV4;b}$Y6vFEo4$|sODH-eu$b5(4S~+1Ra}yR{ekz{V z_P!G0Fk_vgk)PHM6H7i9<4S3&*X!a>mq*nNJr#9TP0T#}Ve}5ZKas|b5p#+c`i=9_ z#3LX4Yl8wp=jHYP?t9QNB%Vpnz>+!~4HW6vJ=d=i>lsQ54kP6}fuYvAPS_<-s*pq; zqw&e>?kb#%2r%;Jx#6!L$2p_70PQt&db9Dd;=X!^ilryQP6MT3!sZ=}k#R14lD3Yw zpdu_sNsyA-wBA1piE8GWg*SHQ_^K8QG~cvPK16nYnytdPUW@pN3%S1?H4}Xuu2#Je zkiD8=H@(-a;gYe=CWUW_S?~7velH0n66*HtUr7JAuF80Im6E>>tfskv-;1yQj-?>S`U!+w6Vm zL1R@7oF=ZSGsX%bXN}>hr80%0%>Np%C+u8QT>m*_7QGKSwzO-fpBwbhpeSMtbzh)M$k|>7}{`#xkt4r07i2 zo68Htu+T_L0qnxl3LJqmS&M}#x%0mL!+T}#7fqp3%CONNQv;&1VpV=IGuMnSJJ+<9 zUJ2x}x!88}2tjU__AKMWvB0)dKi~JpRy?%YUNs~M2&bd5mZ(8aSqvE2{n@1Lg-+$H z`%UgePHBVsWd-YH`p3e=xy9MJy+*`L4&rSwt$@51)yzN)mF*&MMXY^I{sHs1aK4#M zX4+y8!SU6)w3RtW{Idw&o$`u|tu=NJ<%=5W#C0xJBhzPV@wRL?d`aW-z{_+jLeaBwD*fpePwxrc(5yhDV+I<9iBJ1h=TgFm{bI=4^~zfctDQtbi;gDR z&M!7b3e}XY-6sy^u0rs0b#f!Q2^8Hf?Jq4*#7Tc!6dsP|w6mHSz+SAaRXy!J^SXb+K z!%u*NQLu-1JWu&~^t{w_d5u{h>J?()ulLVsR)HO$Jz)o;pTTh**l$TySibd6L$!0# zEcvQ0X_=0)laTjP$Q_lQN)O_;R6$jTpYL?~n3EooKV3TitxR9r-Zpu|=(h;4i(QPd z5PG&>_h)9jiEP=z9bS$lDwAhsSG!uyi)aDmD;Za9bv3nFE4>^uCy`|;hXZ#q#@ZX==0V2 zrJ$Jyo#MJ-1?#=w0a*PSFGIB}Vgb_Xo}tNubCF9Hf;`|t*s(F-sWF^dD>PKHd%-m8 z^Q~B0EakbR?Zu7GEmW&bYgSm@Z|g*S2u4KuQ+#U3WN!fJDakLc5gBLs@Y~*@W+Eu2 z+ou%bf3>wF-+)BXW0n&DF`urn{Gsqke1hofM${+7=1ns$so^bnEd=G)O3$V`Sfep_ zPbp~XavW4m!<7@qf)6WnIuApPx{0Bp#>1q>-H)8hGjxTqd9)E?!!J1U?D^un>L5m6 z&*V}%D`=$i@5kT%7L0=p?Yvd6o{@~^Q_zBk$Ml48BBWEjY;@HlRD4{@MIP|9v`>Se zHa-;+Wb%!~#-dl;{e+#V-%x80jUC!t?cE`$HyH8c(djJddqpNN)TG+(4=es~M$Dt! zAUE21zgWVtTb6;H^G9`Tbr^)(^>#bAu7wfcNj6sO{;1~dx}z}Ng z$a9c_V1%g@*j8eOKQxo5gv5ivC-+y8Uus6v9XY|=>8Pul@yUmB`L5^y)l5%}-uhNi z5~({HP2a`*)KG#Y8RK}^SZ6_Qpd}Bu*%P41mD`_Oub2(*VF$K}RtROh5WMXV~JmBIr zD4PXU;e&li{_=&}&A?c`mpy!fH^Sgm!eh;0h|K7LakKuyP}xm1VcDz5LU7EZMOvy; zSM%IZekP#O7TGiyc^!hEV=n{ec*<|Z?`@`z=hXK$%ej7&>k|mKgZ?s$>}0O)xZqt& zOUDodF0LjRWh0r?j-KY5(fmptQ}Aqt(;-Hc;&hkimw$jq!4YJcezri#3gTW~7ek8i zUUs{gr$O~A_%>OiIypb1Ex!{JQfTI`beMxUuozd?oGUYc>QqQNgznw)$LFHU9n(5}NF7$$`vl_N*;eOI~PZ=syU9xC8Y7m7b2E%9{x8(_^K@5xWKC5*Llyha=-|H z8Kl#DCCj2xw3-|`rkGRZlZQwRehn&5{Lu_;3~)G#(I%RKL1Kj6g9<#0WIt-*6o_v{ z%l4A2S>FOr=esxUe7z*kCET-FOrhZ|*_1psj+BltJ2ZKW{|y$0EA#K~=9VxhpaL#p z0Y5gBi+Y*t)9I^Ka$E*e3=y!@5Cra7f$^b?Z!>0c*I7-fbm(K8JixE4>5h7ex9wgy z7gn6nWX~gr#&CPO4MeD>@a03k{+wHq&u!7~fzS!P42#om088E#J1B~g8=akA7I|Pd zzk$btOdvKCcAvVW&Lk^py_4W8^Z@)n#68LTKDMwu^mR*xYcga_MlT^wieX~&&?t_N z%hSBZc&xep9AD$;w4=T|Ib6H&hM&(Uw0J4tzM;>`mLW*uL`UE%CiC*+3*rR3a$=V5{m{Tcu57rj`z=iK+9~$K47v!F8QVtFqL> zXV%v@$UbeumTyrAUctx`vX@ONDhI^x;rmxx+|Vt5zS1Q_4B?aS@__iW5{8 z28c%}@WD$**M}frxTIJ?^_08MLJv93wY5+oG=>B$n9O8ovOb?)$NuYU= zb5ogAL$>uS_-6Gb}aXiI(lIL@$I7P4UQibNaDrmjWGqLRqTbEG@B%Mkt*Vn?Q#be zsBTX}Y$Wr~$rkxM_!HS)t*;r54o}1FJ0Jb&r=M4`teR2u0|7n6H&bTSqdN}ARoG&P zgMEDwG?O5>N`6OA>r11!Sb#=APlgMU8Pt-3{L3vHoAazA&wCsa zn+4_!SZ?&XO;+eEDUJ3xbF{k)0dNs^{kBkh&_7Ya!D81r@6HBh5hJW^d9Dj1?VmQx zIIy*Q<+fkpv%j z{W0%mDmwo+x3_Dz>3nn!5~X8nB09_RA|_rBgqXL%2+z5Y!)fh>K#-)goZ0Ukqi2R* zgLDpyrr0$j+0SRj)%|u;&U|c~#?f-3)e|uZ8#@$X;E!DFHF;n22sJs*Mse4DYKgqb zpR8tb6nIP2Mw`Mx)9EW6XA$Z<`Uw{QmmGoHG^vzk=KCIU{7N=oadC2%1A^ndDrhc+rVxvN3FIre z>}~J+!NrI}mRjS^j>(YN9KD6@8^9^Up;AoSk!7Ukw`%^#j*|xOviCHL)|6bq~?x}*X$O3wRt%RXzZ#=KB^R=jfr5B7{8(z5YS#E*3lePp6Sny;| z+a4wwV}|?%R42%4TR_V&csGfD{1gm!tmX|2n$K=hGu*vf3%a2yr{mj}1vJ=%JHB>K z!XCH(tpym$->H$T!QoywwB93e-QJ0Jt-_@Lo7E|C{x#s5B31lF9%bji(vWdbL}N1^ zpI<>Try{8}@&*9;qK3mwk7FkBUgQl2i{V1L&#n*tpe|!{=he+`#~ay%8>m##j$N)lv@Ki ze8f~U!v}veTmDpya*3m3P0w@D)qp#ZeY3sc-hz1}>wEwYt`ZY`a6|}ccxbJuwwvbL zQ19*(-2zu@T3SF>tK|nTJ)q2in$v}}o=-fsWpy#pM0MMv-9=zY z!9VMb3et#hE^iMcX9kz|RccSTv~?EK#r5$#{?OPp*mSI`F&zCVOr}(!PGHvDccf;Y z{eVHo|1cMYlORdW-WHmY%^2cLcD(02A`q*w2jz^ z9xpnX@C<^LFitj#C*LhlamT8iy=|o$e$O2=65Wx&LBKDz!8;0;_G5Rk&8=(veT)6b zS@A)dm6jGEJ8}O=wekG#X?PpM+?QN!e}?ulP#<|1jT$;++h#AZ%bN=P3oAL^C~yf% z53N-(de^JmxI0eJI)F{vrg5HDJ{>!MpZN_bH@WR?HF7rC$Nq~ca)kDYrDf*1;V%_i zqS%Db7LXLogZqAyTV5MU7M2c=gPf!JIbH58P=!c z8mu*o%C|_bi$*!WYGmyMR&1@+T3w5VuEwN3N|&KzOS!*lqf4fw4pUV>FTa(4Q%fXi z-{+P}SzJVM8G?tjw|xui(nCVOMWK^29h`Am`Dz)E95MJfAR$@H&a!Ra_IH{NUZt}W z7w5{B$i!lk0;Gh}MKed;(T4Wu5{}3rhlb)Ir_Ic&VJ!xR*;wqDLoQ|jUl_Uf9piog zVjt|rFzl-d#tub`!ap61r7^rHiV%Rg)EkdH>2womH@0|LSVgXLYspy=vp|gZFSDi& zsHu>A`YSDvZGY zkk4l3MZy(E^h=A_KNY&QI6 z{k(ULG^2Y518io^LDTt)~Kovurw$Ecn`tiZmAo?ZTI#4#@D*>t!C?3vY)R-`<34-Oqpd! zY1@y#umL2lyat4$^FqQO;5fxYhtsSry3_e*GiTlDInQJgRV>sjW-0EfjbtfnM<;Fs0x~bV|F>oBo-4>!BbV8GVnTYIodkx?K>Iz|Y-x$$9;RX`1 zYq~zukxwe4Bkds0*sj_YG6d>7;nI}q#XQUujQpl5)F|C?lvP(V*L9F6f!v`mJMB~w z31`i@X5~GNJJd{Bmy>FqZs!ADDDgtqdAmKAC7)2M0qI6BQH?~r<623_yh{vIX~!+; z?tI<0FXX6C&1yEHDX52f?*OE~VdpY`8=qRHe8n$<`+pyAn-E;bT0g3|Sa<$yq&aUk z==hj~A7BK_Xw?kPGZ7!A1>jag&*)?l=5}_) zW-%NhzfZfl4JIFkzn0pDODiuG6TDTdYikSU_W$?N4;XT&uFi3a;4OOrRiYiw;vYU;NHXn%0x#TX?<3%qq5;F4y`Ig*!aV=e| zmY)xgW3KK&(hCAhIhdSp3|c;t&!=S2X*tq9`JifjTRe?;ei=+OdV=cO0lT!&hz@`x z&tg>BOu6Lw+Q%!F;j3HMEa8Hf{$Cu)EZpzB@4f|8U=aWi&_9kIBNBHnnQg#k!^W#Hcp`YC;7sCd zW$5?_+g!i8j!fwSQjqqd4X5q4YixaO4?0~Sh@9vLnb8^o?&=TN(faZ3JOPT*;RB`U z&bvskKYRoYijwoXkn90kO{Ugq7wwF)Z6J~$`Z-vU-AEu-wu$5;Vea*K%up0l^i9L( z!?_UaOoaJZ)l7U+==_h+yC)(hSR;pfYd>Ex1n(A@W1J7ad64rE*hLIIF7|J-c%^N7 zP0Qm+KIz9=weQsIpSeXJu?QTEf|_(G^C>91vx-Elkcm>^BM9eab}Nux###TShs8H*xu%v z%mIJzz!aH&*0=YS&U}w=0KL!!1TEyEk-$CzpBTd z?C|jkq;eJCw{=DBWd-i{qI#Z(9($FX0FXMvPGhK@_-UA-J5+h)j4AFbiG|X4M`3Xk^SNw2K1puS>xJabq8QlOWql0C zyn^92+O;cQsMHyE-I4yjKSJ)gzu}^(oKT7^)CK~YJDnQ~ z^Y;MA`53^4Q}1!yV!sV3u*oS(leJF(!o%%ha4yJv!02T3IB5}l1=HMvZ;y9k^WABF zjJLh+PlUn@ta}u4h%f|1VrQ8-4!X(>|y5d0h)HhT|Y(+*Ixf&{R z9TOCZZz4Ep14*lBJz}Q0>S|3gBZ=w3x^`T!f83BM`#&zDAR>!g`D5t!Tzz?jU2qhi z2={%BHaqbNjLxxCAyw zP~^aunVh}mnZ$o?8trnWBg+;5eYJ15ccQJMllWqZ*~Mf+KP=K~kve^r%CPoeUtMm} zuIar1r}WNyMJWMq&BD@}{yhuZ3w7~x8tX~GxesLV0D2|~V<(oZcUVoerxVbKf{0nj zx!pZ($|z~YBRF`z>2jEQg0^;cWU7CM?e+}~8E4iaU_(Uw+Ya7Q3tcVhjTlS!X=XW{ zA2q4X7&kXQy~HXT=vtKH4FzLEZ=|{c(aD0Esxw8PHBWMLJ8kH4>;R5$jfZ{)H5^Df zZbrieb%|)>=+2URK8j7nfsdDYoo$p{VKQRW(kJpnPIZ#%-qtCx!ECQ(j_#! z1DHmG-NhSxZ`no2x#`gJp7!vy2utK>>sHA@%5Qc0TS{9b8G9vs%m1Ybwh`x(z@a4=QD}K=4obTVO){LpK}!pM|+o|k!D!c3tV9!WjAL|2c<*h>Y=sYuz{&0)jLd$aih7(T5EH_dKI09}MDN-{v$( zEy{B<%7x!u8Qa%!)-WYf28<+I-?`5-Exrg;?jyyhXLeRNJZ+%7S|lpUb#l}_3hz^C zDFaDCwDX2wVt_(!`>WWKk%A6}eO#oIh(8zp9$zB##`XEF-42Q%OG-bS!#WHUNA-Wl zl+}SR>`Y$BUd#8C`msQy#|CJ;dd8=5*=+^Z=y=RUK_um2SQ5ONRB=*zK-a#VPUCRVma%E;hn|fMk>Z!ytz}X|1+%oF7fC3%~zSo%a z`(1LB^Tr>dYj;4+LwC<)3?FoFb9o_!(08!uOm)o<1pEJyBVA$@PwWwwGCVG63qtlr zurmF@zdUhJ`FMXQmq)W#zYF+{X>2}-+o2-Yh4QknG|?nEO;&q+3c@$wjYeF}?Tq9k zY&8{P`ucuCl?f~62QDC;m0}JoaQnaftS%n~*_JMZ-?kw8xWv;Gr3%8wEv2l}O}eho z4)E(hrOdKM{e&)HbIZ#>A0DY$RBzmApf{D!{hF_S zNTa{F%qY8mshQ33nC%H5U3YJgnI8xSbrr>_awLqqn_3g#8S2g!x&X641ecM4Sh%(( zR@&yR9t>Dq_~+KsD;9$=SBlCWBHtHmC^ZjKWJCZw{c0Z{aBe<$YE#*{9?Cf}=;%CRttT+J8?y)p&kdM`7;M7gQ; z?W5NU(~l)L*$w{!fCXk-5}^^`n{IG%1zZJF2`oxDcUXWaeJ`GSxl*s4_?vW_FJT%! zP%eA4`ipJNH)}@ntgzX7j*r;q-D=M678Bafp7*aoFa!w^g-jXz*?BzgU+JTkE?h#^ z1t@2it2d<5LTLO&O`0Xyzgf+Bvou zWeV_|Md|847DXv;gpaWDkrbjXD9%I09oj?&{vmPgpd%9&#<*?;#Rc&0%fd2#{+30J zQxNWNaj^Ei&TLC2Sy!xF!%P9ADO<1oY7Fi}+ttKsLwmb#TxL?l%$(VaUi@y)!ox7gwa&CQU2#?s z-!F>a*dVdwhZb7Yx|VGizF#5qlYdsgneZkU%#8i^clMAW%f$u=A#Hm1Od7(|DN4zO z1`g_S+k5PsoqeF9-i+(bFQvf!-CU|Z;Eh0OLD!bAQ2x-sVLxCXpclyAuYCM16S7U! zPk2mh%}(7~x)G>r%%!M7zX8VxG)a@)@4ET!`9;j$`3tIi1pVol@WvZ6)KejJutL%|>nMn+`KYBSw|_=}!kqVb+&oWl z=yTouOuRE8KVByXBZSz&x-0kvxAC=b*mGd)RHVZAh0*=?hktn9>@rXxQ71yL`KoWVYjX z?}GVi6fXc0KXa{OcHc~ATcm8kq=34#2HaRCBZv1uZgp}a0iu~NbU$D8E!a`+6-B3^ zmhB91(_8%-Stnze@N&OODYu-(H{#_B6AKJn0TGegbIIOi1!ps}D6*~lnEsuHAxc(z zQjlN1?ua7^G(t&?TQku;^duo^Rl`NDvmHC^&|d-io#uj6#xH1&Y0qR9DD4{3%Dawk z=g&OX=gFPryKg2gj)HCm@Lk{IqUGH=cdpR3iFK5i2OCEa=DMOzHkxeyv+~asny!cPp*xz*1M31iyBt|wYqZpd))2779Y)MsyM{z zo5|aR;pCF}P=~KJBwOFVv=9C)oYB(^1T_UC#jMWY?eF2le$?5q+Nv@KX`L>j^k1dm z55CCCisbk**6V$j#qx>}rKT%Fy<1B7E)e|IkV(~Q_9%MU5FpT?-{?v@EXv|CpKYdW zT6W660L%^DRIN2$IYp#R3f&e9Xje+2@uu-`k!&zioSu63SIi`QTQU~(zsZVl&c`0PmDoo(m7pFqFv)5Q0hx42g^P_W%_Y|6=sk zsR0~*vHlhm4=8qS9Z{xXPOZ0WKl70{lV+Aze~IP7FO9+CKpg)2SU50HXU!i++LSl| zHV_L4Z+-VQHIsi7+u)Ydyq8U-&4G}Cs}JA*&tZ2Vj=>k_`z(4XP|Ws$(VXR74V}9LK@RtEu1MTW(m9)QCJb)9eGqHN3TZ^qGX%fE;mQ zFb^C+xK)|f)HgTphz{99_D)A7{OKd;(_)~3^=6caA%YMN`IRW%c!qvNIa7?^(v`VYZ9Vt{XHZNxRcpfhi%DK-I2DlJER7vDjwr*`|XVie(nA`ouG!|bm{12pAVpY z+U2^#yX#kNE$D4u71eosY%nV-AX5T-E+{#omZE1X0Bj#v@Xllz3Atdk1sk%-5Ts=P zzg^06JapSt*ZFcz^(x0Ez-YYq_=KIME47=fIs(hYB#5kb4~?LaxbYCF*qkA-qy#H* z&djFp@XLL9z4yE9M#()bk}oN4%y0?E^#!RIA})QpvrMhd_)JN2I$6S^Tg=RTCX1-J1Vtb=JM=S| z(Q|61ku%W283r+|C%)hcNXiWezE}ZeFvalWseUG5155WnNSm#}VW_LM-2mqszK^ye z8z@mr;oF`#Spv5lx4DJp2Y6D46mygx7j~~Yj)52ax>b-`P`W2=l6rCGl`^!59iv9-_m?vZo^WCKC?{fo>(P!Tz=?3`SLMPa!O;rQ zjsRd1QoBkm8Ui*%1zHmK%7`}EdonhDtmO22Lcn@C+#Z7(S!m7(`1@Wza2O!bG1yLf zFGXRPKsL*_=AxWhb(WQZJVP!e(vFCT+zDtB=Hpg(1;;f9vbX&mrh{4Q3(?Yi#!cswV^Al12^XL$A`cdoNd`M1l3t-JTcVTtmRwi`K|&h zUo!k`&xD=?C?ev!kth&;Y!Lvd%kEi{XR|0NY32l{2|#~@K%yEd#skUqn^vsB@>zkQ zl7>Nd&JLNNEF3K>YJhFh%WkgkY#Ku9-c=9eK1Vy6i?_AI(x%n^9bPNn?Fmuz4~|J z1n-IDdB9-C441yyLXTvCKEPf$D9u}S=+KRuw!~;8kd`BLa9d+|ji0r6=7Q_t=`xB6 zwkLQ+kDa(e^x+_Q?3{;=i+uhs|B)Xj5gkT2TVGK8@2jxQt5sI^E~O8>udd$({h`#3 zovy5zT=hNF0)6kFL0OCpWSM)d)Luvw*OX{5H0|H%>~-Bs3bk$CBAj47>;%l|2Z7-U zZ_Rt}pu0#B;JY|r)zA_72@$rno0fbLYFS|Z$*uilV#*f|wpXQYENQhd2#n1cKmRqU zi;@hF!nHL4j^SB{?gttA&VbFY2O~x;txO6Fmc_NwgtoU>&{2w`dF`)_a z_f=a`R*;(S`}b)vlf*V3YEK^_VgZ;bYO5fD3|VlS9DWi$Hz8pv{$M8p6+0Ic^Q z|K9|e4k)(es~yz=NBu35FA!)rk&8WmzybBK(GNGUxVt+&MnIPR9|Nm)I=oNNt!V@H z8y2YXw%-~Du{EN@wh~7X4_`Yzaa%z1$*v%c6ng7la;ylc8g;Co55<1@?=82ny2uxxV1lSBg6b7jv^ua{=qHluftDH>`Z06UtU;^w z`CnkxPg*bX-?(G}7@e`@9k6VNQnNrn`D2mdOWMtv_8FYb1s#K(IMk*!&-o)#JaK_@ z8CkqXIEnB9YE_`zf0vwz0NFalY{mzW6%6hu|EXktFO|@UI780)fBtJ?1$Cf+OHAkd z#RU7IFp$eKTXMn7`{OD8C#jKkq9S;wzXe9`y7J#gg1G~gVCroO5vNid5HS$Fs~ literal 33773 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 J5P$mW{{R6qS7`tM diff --git a/scripts/book2partner b/scripts/book2partner index 136fffc..b121333 100755 --- a/scripts/book2partner +++ b/scripts/book2partner @@ -4,162 +4,9 @@ # 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 copy import deepcopy -from lxml import etree - -from librarian import epub, pdf, DirDocProvider, ParseError, cover -from librarian.dcparser import BookInfo - - -def utf_trunc(text, limit): - """ truncates text to at most `limit' bytes in utf-8 """ - if text is None: - return text - orig_text = text - if len(text.encode('utf-8')) > limit: - newlimit = limit - 3 - while len(text.encode('utf-8')) > newlimit: - text = text[:(newlimit - len(text.encode('utf-8'))) / 4] - text += '...' - return text - - -def virtualo(filenames, output_dir, verbose): - xml = etree.fromstring(""" - """) - product = etree.fromstring(""" - - - - - - - Jan - Kowalski - - - 0.0 - PL - """) - - 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) - slug, ext = os.path.splitext(fname) - - outfile_dir = os.path.join(output_dir, slug) - os.makedirs(os.path.join(output_dir, slug)) - - info = BookInfo.from_file(main_input) - - product_elem = deepcopy(product) - product_elem[0].text = utf_trunc(slug, 100) - product_elem[1].text = utf_trunc(info.title, 255) - product_elem[2].text = utf_trunc(info.description, 255) - product_elem[3].text = utf_trunc(info.source_name, 3000) - product_elem[4][0][0].text = utf_trunc(u' '.join(info.author.first_names), 100) - product_elem[4][0][1].text = utf_trunc(info.author.last_name, 100) - xml.append(product_elem) - - cover.VirtualoCover( - u' '.join(info.author.first_names + (info.author.last_name,)), - info.title - ).save(os.path.join(outfile_dir, slug+'.jpg')) - outfile = os.path.join(outfile_dir, '1.epub') - outfile_sample = os.path.join(outfile_dir, '1.sample.epub') - epub.transform(provider, file_path=main_input, output_file=outfile) - epub.transform(provider, file_path=main_input, output_file=outfile_sample, sample=25) - except ParseError, e: - print '%(file)s:%(name)s:%(message)s' % { - 'file': main_input, - 'name': e.__class__.__name__, - 'message': e.message - } - - xml_file = open(os.path.join(output_dir, 'import_products.xml'), 'w') - xml_file.write(etree.tostring(xml, pretty_print=True, encoding=unicode).encode('utf-8')) - xml_file.close() - - -def prestigio(filenames, output_dir, verbose): - 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) - slug, ext = os.path.splitext(fname) - - if output_dir != '': - try: - os.makedirs(output_dir) - except: - pass - outfile = os.path.join(output_dir, slug + '.epub') - epub.transform(provider, file_path=main_input, output_file=outfile, - cover=cover.PrestigioCover, flags=('less-advertising',)) - except ParseError, e: - print '%(file)s:%(name)s:%(message)s' % { - 'file': main_input, - 'name': e.__class__.__name__, - 'message': e.message - } - - -def prestigio_pdf(filenames, output_dir, verbose): - 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) - slug, ext = os.path.splitext(fname) - - if output_dir != '': - try: - os.makedirs(output_dir) - except: - pass - outfile = os.path.join(output_dir, slug + '.pdf') - pdf.transform(provider, file_path=main_input, output_file=outfile, - cover=cover.PrestigioCover, verbose=options.verbose, flags=('less-advertising',)) - except ParseError, e: - print '%(file)s:%(name)s:%(message)s' % { - 'file': main_input, - 'name': e.__class__.__name__, - 'message': e.message - } - - -def bookoteka(filenames, output_dir, verbose): - 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) - slug, ext = os.path.splitext(fname) - - if output_dir != '': - try: - os.makedirs(output_dir) - except: - pass - outfile = os.path.join(output_dir, slug + '.epub') - epub.transform(provider, file_path=main_input, output_file=outfile, - cover=cover.BookotekaCover) - except ParseError, e: - print '%(file)s:%(name)s:%(message)s' % { - 'file': main_input, - 'name': e.__class__.__name__, - 'message': e.message - } +from librarian import packagers if __name__ == '__main__': @@ -175,6 +22,8 @@ if __name__ == '__main__': help='specifies the directory for output') parser.add_option('--bookoteka', action='store_true', dest='bookoteka', default=False, help='prepare files for Bookoteka') + parser.add_option('--gandalf', action='store_true', dest='gandalf', default=False, + help='prepare files for Gandalf') parser.add_option('--virtualo', action='store_true', dest='virtualo', default=False, help='prepare files for Virtualo API') parser.add_option('--prestigio', action='store_true', dest='prestigio', default=False, @@ -189,10 +38,12 @@ if __name__ == '__main__': exit(1) if options.bookoteka: - bookoteka(input_filenames, options.output_dir, options.verbose) + packagers.BookotekaEpubPackager.prepare(input_filenames, options.output_dir, options.verbose) + if options.gandalf: + packagers.GandalfEpubPackager.prepare(input_filenames, options.output_dir, options.verbose) if options.virtualo: - virtualo(input_filenames, options.output_dir, options.verbose) + packagers.VirtualoEpubPackager.prepare(input_filenames, options.output_dir, options.verbose) if options.prestigio: - prestigio(input_filenames, options.output_dir, options.verbose) + packagers.PrestigioEpubPackager.prepare(input_filenames, options.output_dir, options.verbose) if options.prestigio_pdf: - prestigio_pdf(input_filenames, options.output_dir, options.verbose) + packagers.PrestigioPdfPackager.prepare(input_filenames, options.output_dir, options.verbose) -- 2.20.1 From e868b7e6511dfbb89e5a9dd69bbb7ef13c42620a Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Mon, 7 Mar 2011 10:43:58 +0100 Subject: [PATCH 15/16] vendor cover change --- librarian/packagers.py | 3 +++ librarian/res/cover-gandalf.png | Bin 13175 -> 29218 bytes scripts/book2partner | 6 +++++- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/librarian/packagers.py b/librarian/packagers.py index 285a15f..054f068 100644 --- a/librarian/packagers.py +++ b/librarian/packagers.py @@ -57,6 +57,9 @@ class PdfPackager(Packager): class GandalfEpubPackager(EpubPackager): cover = cover.GandalfCover +class GandalfPdfPackager(PdfPackager): + cover = cover.GandalfCover + class BookotekaEpubPackager(EpubPackager): cover = cover.BookotekaCover diff --git a/librarian/res/cover-gandalf.png b/librarian/res/cover-gandalf.png index 3c1513296a97a1045821d42831219fa8ff16f990..a5c8f508fb353e1205d99ad0fd819d6dcc193a29 100644 GIT binary patch literal 29218 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 ZygAparc8c-?+3$BQc#mGe`*%?e*lmhl(PT; literal 13175 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 diff --git a/scripts/book2partner b/scripts/book2partner index b121333..0488273 100755 --- a/scripts/book2partner +++ b/scripts/book2partner @@ -23,7 +23,9 @@ if __name__ == '__main__': parser.add_option('--bookoteka', action='store_true', dest='bookoteka', default=False, help='prepare files for Bookoteka') parser.add_option('--gandalf', action='store_true', dest='gandalf', default=False, - help='prepare files for Gandalf') + help='prepare EPUB files for Gandalf') + parser.add_option('--gandalf-pdf', action='store_true', dest='gandalf_pdf', default=False, + help='prepare PDF files for Gandalf') parser.add_option('--virtualo', action='store_true', dest='virtualo', default=False, help='prepare files for Virtualo API') parser.add_option('--prestigio', action='store_true', dest='prestigio', default=False, @@ -41,6 +43,8 @@ if __name__ == '__main__': packagers.BookotekaEpubPackager.prepare(input_filenames, options.output_dir, options.verbose) if options.gandalf: packagers.GandalfEpubPackager.prepare(input_filenames, options.output_dir, options.verbose) + if options.gandalf_pdf: + packagers.GandalfPdfPackager.prepare(input_filenames, options.output_dir, options.verbose) if options.virtualo: packagers.VirtualoEpubPackager.prepare(input_filenames, options.output_dir, options.verbose) if options.prestigio: -- 2.20.1 From fec62da2886e29aa0a9233e13fd9cae0ca6076bf Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Tue, 8 Mar 2011 13:07:08 +0100 Subject: [PATCH 16/16] encode unicode for lxml --- librarian/parser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/librarian/parser.py b/librarian/parser.py index 4cdaa79..afc4f1a 100644 --- a/librarian/parser.py +++ b/librarian/parser.py @@ -61,7 +61,7 @@ class WLDocument(object): try: parser = etree.XMLParser(remove_blank_text=False) - tree = etree.parse(StringIO(data), parser) + tree = etree.parse(StringIO(data.encode('utf-8')), parser) if swap_endlines: cls.swap_endlines(tree) -- 2.20.1