From 175c5cf4f727162fa5bddd2460d37595251bbe8e Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Thu, 7 Oct 2021 12:15:17 +0200 Subject: [PATCH] Support for block annotations. Option to use endnotes in PDF. --- src/librarian/dcparser.py | 7 +++- src/librarian/elements/__init__.py | 1 + src/librarian/elements/base.py | 19 +++++++++- src/librarian/elements/footnotes/__init__.py | 11 +++++- src/librarian/elements/paragraphs/akap.py | 15 +++++++- src/librarian/html.py | 4 +- src/librarian/parser.py | 7 ++++ src/librarian/pdf.py | 9 +++++ src/librarian/pdf/wl.cls | 26 +++++++++++-- src/librarian/pdf/wl2tex.xslt | 39 +++++++++++++++++--- src/librarian/xslt/book2html.xslt | 8 +++- 11 files changed, 130 insertions(+), 16 deletions(-) diff --git a/src/librarian/dcparser.py b/src/librarian/dcparser.py index 16c2397..1976850 100644 --- a/src/librarian/dcparser.py +++ b/src/librarian/dcparser.py @@ -153,6 +153,9 @@ def as_unicode(text): else: return TextPlus(text.decode('utf-8')) +def as_bool(text): + return text == 'true' +as_bool.no_lang = True def as_wluri_strict(text): return WLURI.strict(text) @@ -203,7 +206,7 @@ class Field(object): if validator is None or val[0] is None: return val[0] nv = validator(val[0]) - if hasattr(val[0], 'lang'): + if hasattr(val[0], 'lang') and not hasattr(validator, 'no_lang'): setattr(nv, 'lang', val[0].lang) return nv except ValueError as e: @@ -527,6 +530,8 @@ class BookInfo(WorkInfo): Field(WLNS('coverClass'), 'cover_class', default=['default']), Field(WLNS('coverLogoUrl'), 'cover_logo_urls', multiple=True, required=False), + Field(WLNS('endnotes'), 'endnotes', as_bool, + required=False), Field('pdf-id', 'isbn_pdf', required=False), Field('epub-id', 'isbn_epub', required=False), diff --git a/src/librarian/elements/__init__.py b/src/librarian/elements/__init__.py index 65c82d8..6ec0ba7 100644 --- a/src/librarian/elements/__init__.py +++ b/src/librarian/elements/__init__.py @@ -11,6 +11,7 @@ WL_ELEMENTS = { "coverBoxPosition": etree.ElementBase, "coverLogoUrl": etree.ElementBase, "contentWarning": etree.ElementBase, + "endnotes": etree.ElementBase, "utwor": root.Utwor, "dramat_wierszowany_l": masters.Master, diff --git a/src/librarian/elements/base.py b/src/librarian/elements/base.py index 1d3edd6..3e0f898 100644 --- a/src/librarian/elements/base.py +++ b/src/librarian/elements/base.py @@ -62,6 +62,20 @@ class WLElement(etree.ElementBase): def gettext(self): return get_translation(self.meta.language).gettext + def in_context_of(self, setting): + parent = self.getparent() + if parent is None: + return False + try: + return getattr(parent, setting) + except AttributeError: + return parent.in_context_of(setting) + + def signal(self, signal): + parent = self.getparent() + if parent is not None: + parent.signal(signal) + def raw_printable_text(self): # TODO: podtagi, wyroznienia, etc t = '' @@ -166,7 +180,7 @@ class WLElement(etree.ElementBase): builder.start_chunk() fragment = None - if self.SECTION_PRECEDENCE: + if self.SECTION_PRECEDENCE and not self.in_context_of('NO_TOC'): if not start_chunk: fragment = 'sub%d' % builder.assign_section_number() self.attrib['id'] = fragment @@ -193,9 +207,10 @@ class WLElement(etree.ElementBase): def validate(self): from librarian.elements.masters import Master from librarian.elements.blocks import DlugiCytat, PoezjaCyt + from librarian.elements.footnotes import Footnote if self.SECTION_PRECEDENCE: - assert isinstance(self.getparent(), (Master, DlugiCytat, PoezjaCyt)), \ + assert isinstance(self.getparent(), (Master, DlugiCytat, PoezjaCyt, Footnote)), \ 'Header {} inside a <{}> instead of a master.'.format( etree.tostring(self), self.getparent().tag) diff --git a/src/librarian/elements/footnotes/__init__.py b/src/librarian/elements/footnotes/__init__.py index 433e881..398fdea 100644 --- a/src/librarian/elements/footnotes/__init__.py +++ b/src/librarian/elements/footnotes/__init__.py @@ -5,6 +5,15 @@ from ..base import WLElement class Footnote(WLElement): + NO_TOC = True + START_INLINE = True + + def signal(self, signal): + if signal == 'INLINE': + self.START_INLINE = False + else: + super().signal(signal) + def txt_build(self, builder): pass @@ -72,7 +81,7 @@ class Footnote(WLElement): builder.enter_fragment('footnotes') - builder.start_element('p', { + builder.start_element('div', { 'id': f'annotation-{fn_no}', 'class': "annotation" }) diff --git a/src/librarian/elements/paragraphs/akap.py b/src/librarian/elements/paragraphs/akap.py index b0c0329..18f69d7 100644 --- a/src/librarian/elements/paragraphs/akap.py +++ b/src/librarian/elements/paragraphs/akap.py @@ -9,5 +9,18 @@ class Akap(WLElement): TXT_LEGACY_TOP_MARGIN = 2 TXT_LEGACY_BOTTOM_MARGIN = 0 - EPUB_TAG = HTML_TAG = 'p' + HTML_TAG = 'p' EPUB_CLASS = HTML_CLASS = 'paragraph' + + @property + def EPUB_TAG(self): + try: + return self._set_EPUB_TAG + except AttributeError: + if self.in_context_of('START_INLINE'): + self.signal('INLINE') + self._set_EPUB_TAG = None + else: + self._set_EPUB_TAG = 'p' + return self._set_EPUB_TAG + diff --git a/src/librarian/html.py b/src/librarian/html.py index f0f11db..d4b9795 100644 --- a/src/librarian/html.py +++ b/src/librarian/html.py @@ -114,7 +114,8 @@ def transform(wldoc, stylesheet='legacy', options=None, flags=None, css=None, ga document.clean_ed_note() document.clean_ed_note('abstrakt') - + document.fix_pa_akap() + if not options: options = {} @@ -319,6 +320,7 @@ def add_anchors(root): ) or e.get('id') == 'nota_red' or e.tag == 'blockquote' + or e.get('id') == 'footnotes' ) if any_ancestor(element, f): continue diff --git a/src/librarian/parser.py b/src/librarian/parser.py index 3ae081b..6e21d4d 100644 --- a/src/librarian/parser.py +++ b/src/librarian/parser.py @@ -197,6 +197,13 @@ class WLDocument(object): node.tag = 'span' node.tail = tail + def fix_pa_akap(self): + for pa in ('pa','pe','pr','pt'): + for akap in self.edoc.findall(f'//{pa}/akap'): + akap.getparent().set('blocks', 'true') + if not akap.getparent().index(akap): + akap.set('inline', 'true') + def editors(self): """Returns a set of all editors for book and its children. diff --git a/src/librarian/pdf.py b/src/librarian/pdf.py index a025b9b..31dfe1e 100644 --- a/src/librarian/pdf.py +++ b/src/librarian/pdf.py @@ -284,6 +284,14 @@ def transform(wldoc, verbose=False, save_tex=None, morefloats=None, elif package_available('morefloats', 'maxfloats=19'): root.set('morefloats', 'new') + if customizations is None: + customizations = [] + else: + customizations = list(customizations) + + if book_info.endnotes: + customizations.append('endnotes') + # add customizations if customizations is not None: root.set('customizations', u','.join(customizations)) @@ -306,6 +314,7 @@ def transform(wldoc, verbose=False, save_tex=None, morefloats=None, fix_hanging(document.edoc) fix_tables(document.edoc) mark_subauthors(document.edoc) + document.fix_pa_akap() # wl -> TeXML style_filename = get_stylesheet("wl2tex") diff --git a/src/librarian/pdf/wl.cls b/src/librarian/pdf/wl.cls index c46a0ec..62b23e1 100644 --- a/src/librarian/pdf/wl.cls +++ b/src/librarian/pdf/wl.cls @@ -111,6 +111,9 @@ \newif\ifshowfootnotes \showfootnotestrue \DeclareOption{nofootnotes}{\showfootnotesfalse} +\newif\ifendnotes \endnotesfalse +\DeclareOption{endnotes}{\endnotestrue} + \newif\ifshowthemes \showthemestrue \DeclareOption{nothemes}{\showthemesfalse} @@ -147,6 +150,14 @@ \usepackage{wrapfig} + +\ifendnotes + \usepackage{enotez} + \setenotez{list-name=Przypisy} + \setenotez{backref=true} +\fi + + \usepackage[overload]{textcase} \usepackage{scalefnt} \usepackage[colorlinks=true,linkcolor=black,setpagesize=false,urlcolor=black,xetex]{hyperref} @@ -753,10 +764,17 @@ Letters={Uppercase} } \ifshowfootnotes - \newcommand{\pa}[1]{\NoCaseChange{\footnote{#1 [przypis autorski]}}} - \newcommand{\pe}[1]{\NoCaseChange{\footnote{#1 [przypis edytorski]}}} - \newcommand{\pr}[1]{\NoCaseChange{\footnote{#1 [przypis redakcyjny]}}} - \newcommand{\pt}[1]{\NoCaseChange{\footnote{#1 [przypis tłumacza]}}} + \ifendnotes + \newcommand{\pa}[1]{\NoCaseChange{\endnote{#1 [przypis autorski]}}} + \newcommand{\pe}[1]{\NoCaseChange{\endnote{#1 [przypis edytorski]}}} + \newcommand{\pr}[1]{\NoCaseChange{\endnote{#1 [przypis redakcyjny]}}} + \newcommand{\pt}[1]{\NoCaseChange{\endnote{#1 [przypis tłumacza]}}} + \else + \newcommand{\pa}[1]{\NoCaseChange{\footnote{#1 [przypis autorski]}}} + \newcommand{\pe}[1]{\NoCaseChange{\footnote{#1 [przypis edytorski]}}} + \newcommand{\pr}[1]{\NoCaseChange{\footnote{#1 [przypis redakcyjny]}}} + \newcommand{\pt}[1]{\NoCaseChange{\footnote{#1 [przypis tłumacza]}}} + \fi \else \newcommand{\pa}[1]{} \newcommand{\pe}[1]{} diff --git a/src/librarian/pdf/wl2tex.xslt b/src/librarian/pdf/wl2tex.xslt index 820033d..eb8e370 100644 --- a/src/librarian/pdf/wl2tex.xslt +++ b/src/librarian/pdf/wl2tex.xslt @@ -140,6 +140,18 @@ + + \ifendnotes +\newpage +\begingroup +\parindent 0pt +\parskip 2ex +\def\enotesize{\normalsize} +\printendnotes + \endgroup + \fi + + @@ -342,13 +354,20 @@ - + match="naglowek_osoba|naglowek_podrozdzial|podtytul_podrozdzial|miejsce_czas|didaskalia|lista_osoba|akap|akap_dialog|akap_cd|motto_podpis|naglowek_listy|srodtytul|podtytul_czesc|podtytul_rozdzial|podtytul_akt|podtytul_scena"> + + + + + + - + + + @@ -426,13 +445,23 @@ + - + - + + + + + + + + + + diff --git a/src/librarian/xslt/book2html.xslt b/src/librarian/xslt/book2html.xslt index 54f522e..9b77b5e 100644 --- a/src/librarian/xslt/book2html.xslt +++ b/src/librarian/xslt/book2html.xslt @@ -114,7 +114,13 @@

- + +

+ [przypis autorski] + [przypis tłumacza] + [przypis redakcyjny] + [przypis edytorski] +

-- 2.20.1