Support for block annotations. Option to use endnotes in PDF.
authorRadek Czajka <rczajka@rczajka.pl>
Thu, 7 Oct 2021 10:15:17 +0000 (12:15 +0200)
committerRadek Czajka <rczajka@rczajka.pl>
Thu, 7 Oct 2021 10:15:17 +0000 (12:15 +0200)
src/librarian/dcparser.py
src/librarian/elements/__init__.py
src/librarian/elements/base.py
src/librarian/elements/footnotes/__init__.py
src/librarian/elements/paragraphs/akap.py
src/librarian/html.py
src/librarian/parser.py
src/librarian/pdf.py
src/librarian/pdf/wl.cls
src/librarian/pdf/wl2tex.xslt
src/librarian/xslt/book2html.xslt

index 16c2397..1976850 100644 (file)
@@ -153,6 +153,9 @@ def as_unicode(text):
     else:
         return TextPlus(text.decode('utf-8'))
 
     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)
 
 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 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:
                     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('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),
 
         Field('pdf-id',  'isbn_pdf',  required=False),
         Field('epub-id', 'isbn_epub', required=False),
index 65c82d8..6ec0ba7 100644 (file)
@@ -11,6 +11,7 @@ WL_ELEMENTS = {
     "coverBoxPosition": etree.ElementBase, 
     "coverLogoUrl": etree.ElementBase,
     "contentWarning": etree.ElementBase,
     "coverBoxPosition": etree.ElementBase, 
     "coverLogoUrl": etree.ElementBase,
     "contentWarning": etree.ElementBase,
+    "endnotes": etree.ElementBase,
 
     "utwor": root.Utwor,
     "dramat_wierszowany_l": masters.Master,
 
     "utwor": root.Utwor,
     "dramat_wierszowany_l": masters.Master,
index 1d3edd6..3e0f898 100644 (file)
@@ -62,6 +62,20 @@ class WLElement(etree.ElementBase):
     def gettext(self):
         return get_translation(self.meta.language).gettext
 
     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 = ''
     def raw_printable_text(self):
         # TODO: podtagi, wyroznienia, etc
         t = ''
@@ -166,7 +180,7 @@ class WLElement(etree.ElementBase):
             builder.start_chunk()
 
         fragment = None
             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
             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
     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:
 
         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)
 
                     'Header {} inside a <{}> instead of a master.'.format(
                             etree.tostring(self), self.getparent().tag)
 
index 433e881..398fdea 100644 (file)
@@ -5,6 +5,15 @@ from ..base import WLElement
 
 
 class Footnote(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
 
     def txt_build(self, builder):
         pass
 
@@ -72,7 +81,7 @@ class Footnote(WLElement):
 
         
         builder.enter_fragment('footnotes')
 
         
         builder.enter_fragment('footnotes')
-        builder.start_element('p', {
+        builder.start_element('div', {
             'id': f'annotation-{fn_no}',
             'class': "annotation"
         })
             'id': f'annotation-{fn_no}',
             'class': "annotation"
         })
index b0c0329..18f69d7 100644 (file)
@@ -9,5 +9,18 @@ class Akap(WLElement):
     TXT_LEGACY_TOP_MARGIN = 2
     TXT_LEGACY_BOTTOM_MARGIN = 0
 
     TXT_LEGACY_TOP_MARGIN = 2
     TXT_LEGACY_BOTTOM_MARGIN = 0
 
-    EPUB_TAG = HTML_TAG = 'p'
+    HTML_TAG = 'p'
     EPUB_CLASS = HTML_CLASS = 'paragraph'
     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
index f0f11db..d4b9795 100644 (file)
@@ -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.clean_ed_note()
         document.clean_ed_note('abstrakt')
-
+        document.fix_pa_akap()
+        
         if not options:
             options = {}
 
         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') == 'nota_red'
                 or e.tag == 'blockquote'
+                or e.get('id') == 'footnotes'
             )
         if any_ancestor(element, f):
             continue
             )
         if any_ancestor(element, f):
             continue
index 3ae081b..6e21d4d 100644 (file)
@@ -197,6 +197,13 @@ class WLDocument(object):
             node.tag = 'span'
             node.tail = tail
 
             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.
 
     def editors(self):
         """Returns a set of all editors for book and its children.
 
index a025b9b..31dfe1e 100644 (file)
@@ -284,6 +284,14 @@ def transform(wldoc, verbose=False, save_tex=None, morefloats=None,
         elif package_available('morefloats', 'maxfloats=19'):
             root.set('morefloats', 'new')
 
         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))
         # 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)
         fix_hanging(document.edoc)
         fix_tables(document.edoc)
         mark_subauthors(document.edoc)
+        document.fix_pa_akap()
 
         # wl -> TeXML
         style_filename = get_stylesheet("wl2tex")
 
         # wl -> TeXML
         style_filename = get_stylesheet("wl2tex")
index c46a0ec..62b23e1 100644 (file)
 \newif\ifshowfootnotes \showfootnotestrue
 \DeclareOption{nofootnotes}{\showfootnotesfalse}
 
 \newif\ifshowfootnotes \showfootnotestrue
 \DeclareOption{nofootnotes}{\showfootnotesfalse}
 
+\newif\ifendnotes \endnotesfalse
+\DeclareOption{endnotes}{\endnotestrue}
+
 \newif\ifshowthemes \showthemestrue
 \DeclareOption{nothemes}{\showthemesfalse}
 
 \newif\ifshowthemes \showthemestrue
 \DeclareOption{nothemes}{\showthemesfalse}
 
 
 \usepackage{wrapfig}
 
 
 \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}
 \usepackage[overload]{textcase}
 \usepackage{scalefnt}
 \usepackage[colorlinks=true,linkcolor=black,setpagesize=false,urlcolor=black,xetex]{hyperref}
@@ -753,10 +764,17 @@ Letters={Uppercase}
 }
 
 \ifshowfootnotes
 }
 
 \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]{}
 \else
   \newcommand{\pa}[1]{}
   \newcommand{\pe}[1]{}
index 820033d..eb8e370 100644 (file)
                 </xsl:if>
             </TeXML>
 
                 </xsl:if>
             </TeXML>
 
+           <TeXML escape="0">
+                   \ifendnotes
+\newpage
+\begingroup
+\parindent 0pt
+\parskip 2ex
+\def\enotesize{\normalsize}
+\printendnotes
+                   \endgroup
+                   \fi
+           </TeXML>
+
             <cmd name="editorialsection" />
 
         </env>
             <cmd name="editorialsection" />
 
         </env>
 
 
 <xsl:template
 
 
 <xsl:template
-       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">
-    <cmd>
+    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">
+  <xsl:choose>
+    <xsl:when test="@inline">
+      <xsl:apply-templates mode="inline"/>
+    </xsl:when>
+    <xsl:otherwise>
+      <cmd>
         <xsl:attribute name="name">
             <xsl:value-of select="wl:texcommand(name())" />
         </xsl:attribute>
         <parm><xsl:apply-templates mode="inline"/></parm>
         <xsl:attribute name="name">
             <xsl:value-of select="wl:texcommand(name())" />
         </xsl:attribute>
         <parm><xsl:apply-templates mode="inline"/></parm>
-    </cmd>
+      </cmd>
+    </xsl:otherwise>
+  </xsl:choose>
 </xsl:template>
 
 <xsl:template match="naglowek_czesc|naglowek_rozdzial|naglowek_akt|naglowek_scena">
 </xsl:template>
 
 <xsl:template match="naglowek_czesc|naglowek_rozdzial|naglowek_akt|naglowek_scena">
 <!-- = (contain other inline tags and special tags) = -->
 <!-- ================================================ -->
 
 <!-- = (contain other inline tags and special tags) = -->
 <!-- ================================================ -->
 
+
 <xsl:template mode="inline"
     match="pa|pe|pr|pt|mat|didask_tekst|slowo_obce|wyroznienie|osoba|indeks_dolny|wieksze_odstepy">
     <cmd>
         <xsl:attribute name="name">
 <xsl:template mode="inline"
     match="pa|pe|pr|pt|mat|didask_tekst|slowo_obce|wyroznienie|osoba|indeks_dolny|wieksze_odstepy">
     <cmd>
         <xsl:attribute name="name">
-            <xsl:value-of select="wl:texcommand(name())" />
+               <xsl:value-of select="wl:texcommand(name())" />
         </xsl:attribute>
         </xsl:attribute>
-        <parm><xsl:apply-templates mode="inline"/></parm>
+       <parm>
+         <xsl:choose>
+           <xsl:when test="@blocks">
+              <xsl:apply-templates/>
+            </xsl:when>
+            <xsl:otherwise>
+              <xsl:apply-templates mode="inline"/>
+            </xsl:otherwise>
+          </xsl:choose>
+        </parm>
     </cmd>
 </xsl:template>
 
     </cmd>
 </xsl:template>
 
index 54f522e..9b77b5e 100644 (file)
                                 </p>
                             </xsl:when>
                             <xsl:otherwise>
                                 </p>
                             </xsl:when>
                             <xsl:otherwise>
-                                <xsl:apply-templates select="text()|*" mode="inline" />
+                              <xsl:apply-templates />
+                              <p>
+                                <xsl:if test="name()='pa'"> [przypis autorski]</xsl:if>
+                                <xsl:if test="name()='pt'"> [przypis tłumacza]</xsl:if>
+                                <xsl:if test="name()='pr'"> [przypis redakcyjny]</xsl:if>
+                                <xsl:if test="name()='pe'"> [przypis edytorski]</xsl:if>
+                              </p>
                             </xsl:otherwise>
                         </xsl:choose>
                     </div>
                             </xsl:otherwise>
                         </xsl:choose>
                     </div>