Version 2.2
[librarian.git] / src / librarian / elements / base.py
index fb5e3b1..3e0f898 100644 (file)
@@ -3,9 +3,13 @@
 import re
 from lxml import etree
 from librarian import dcparser, RDFNS
 import re
 from lxml import etree
 from librarian import dcparser, RDFNS
+from librarian.html import raw_printable_text
+from librarian.util import get_translation
 
 
 class WLElement(etree.ElementBase):
 
 
 class WLElement(etree.ElementBase):
+    SECTION_PRECEDENCE = None
+
     TXT_TOP_MARGIN = 0
     TXT_BOTTOM_MARGIN = 0
     TXT_PREFIX = ""
     TXT_TOP_MARGIN = 0
     TXT_BOTTOM_MARGIN = 0
     TXT_PREFIX = ""
@@ -14,18 +18,24 @@ class WLElement(etree.ElementBase):
     HTML_TAG = None
     HTML_ATTR = {}
     HTML_CLASS = None
     HTML_TAG = None
     HTML_ATTR = {}
     HTML_CLASS = None
-    HTML_SECTION = False
-    
+
+    EPUB_TAG = None
+    EPUB_ATTR = {}
+    EPUB_CLASS = None
+    EPUB_START_CHUNK = False
+   
     CAN_HAVE_TEXT = True
     STRIP = False
 
     text_substitutions = [
         (u'---', u'—'),
         (u'--', u'–'),
     CAN_HAVE_TEXT = True
     STRIP = False
 
     text_substitutions = [
         (u'---', u'—'),
         (u'--', u'–'),
-        (u'...', u'…'),
+        #(u'...', u'…'),  # Temporary turnoff for epub
         (u',,', u'„'),
         (u'"', u'”'),
         ('\ufeff', ''),
         (u',,', u'„'),
         (u'"', u'”'),
         ('\ufeff', ''),
+
+        ("'", "\u2019"),    # This was enabled for epub.
     ]
 
     @property
     ]
 
     @property
@@ -37,7 +47,7 @@ class WLElement(etree.ElementBase):
             else:
                 self._meta_object = None
         return self._meta_object
             else:
                 self._meta_object = None
         return self._meta_object
-    
+
     @property
     def meta(self):
         if self.meta_object is not None:
     @property
     def meta(self):
         if self.meta_object is not None:
@@ -47,12 +57,46 @@ class WLElement(etree.ElementBase):
                 return self.getparent().meta
             else:
                 return self.document.base_meta
                 return self.getparent().meta
             else:
                 return self.document.base_meta
+
+    @property
+    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 = ''
+        t += self.normalize_text(self.text)
+        for c in self:
+            if not isinstance(c, WLElement):
+                continue
+            if c.tag not in ('pe', 'pa', 'pt', 'pr', 'motyw'):
+                t += c.raw_printable_text()
+            t += self.normalize_text(c.tail)
+        return t
     
     def normalize_text(self, text):
         text = text or ''
         for e, s in self.text_substitutions:
             text = text.replace(e, s)
     
     def normalize_text(self, text):
         text = text or ''
         for e, s in self.text_substitutions:
             text = text.replace(e, s)
-        text = re.sub(r'\s+', ' ', text)
+            # FIXME: TEmporary turnoff
+#        text = re.sub(r'\s+', ' ', text)
+### TODO: Added now for epub
+        text = re.sub(r'(?<=\s\w)\s+', u'\u00A0', text)
+
         return text
 
     def _build_inner(self, builder, build_method):
         return text
 
     def _build_inner(self, builder, build_method):
@@ -99,39 +143,82 @@ class WLElement(etree.ElementBase):
         # always copy the id attribute (?)
         if self.attrib.get('id'):
             attr['id'] = self.attrib['id']
         # always copy the id attribute (?)
         if self.attrib.get('id'):
             attr['id'] = self.attrib['id']
+        elif '_compat_section_id' in self.attrib:
+            attr['id'] = self.attrib['_compat_section_id']
         return attr
         return attr
-        
-    def html_build(self, builder):
-        if self.HTML_SECTION:
-            builder.start_element(
-                'a', {"name": "f18", "class": "target"}
-            )
-            builder.push_text(" ")
-            builder.end_element()
-
-            builder.start_element(
-                "a", {"href": "#f18", "class": "anchor"}
-            )
-            builder.push_text("18")
-            builder.end_element()
-        
 
 
+    def html_build(self, builder):
         if self.HTML_TAG:
             builder.start_element(
                 self.HTML_TAG,
                 self.get_html_attr(builder),
             )
 
         if self.HTML_TAG:
             builder.start_element(
                 self.HTML_TAG,
                 self.get_html_attr(builder),
             )
 
-        if self.HTML_SECTION:
+        self._html_build_inner(builder)
+        if self.HTML_TAG:
+            builder.end_element()
+
+    def _epub_build_inner(self, builder):
+        self._build_inner(builder, 'epub_build')
+
+    def get_epub_attr(self, builder):
+        attr = self.EPUB_ATTR.copy()
+        if self.EPUB_CLASS:
+            attr['class'] = self.EPUB_CLASS
+        return attr
+
+    def epub_build(self, builder):
+        from librarian.elements.masters import Master
+
+        # TEMPORARY
+        self.CAN_HAVE_TEXT = True
+        self.STRIP = False
+       
+        start_chunk = self.EPUB_START_CHUNK and isinstance(self.getparent(), Master)
+
+        if start_chunk:
+            builder.start_chunk()
+
+        fragment = None
+        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
+
+            builder.add_toc_entry(
+                fragment,
+                self.raw_printable_text(),
+                self.SECTION_PRECEDENCE
+            )
+            
+        if self.EPUB_TAG:
+            attr = self.get_epub_attr(builder)
+            if fragment:
+                attr['id'] = fragment
             builder.start_element(
             builder.start_element(
-                "a", {"name": "sec34"}
+                self.EPUB_TAG,
+                attr
             )
             )
-            builder.end_element()
 
 
-        self._html_build_inner(builder)
-        if self.HTML_TAG:
+        self._epub_build_inner(builder)
+        if self.EPUB_TAG:
             builder.end_element()
 
             builder.end_element()
 
+    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, Footnote)), \
+                    'Header {} inside a <{}> instead of a master.'.format(
+                            etree.tostring(self), self.getparent().tag)
+
+        for c in self:
+            if isinstance(c, WLElement):
+                c.validate()
+
+
     def sanitize(self):
         # TODO: Remove insanity here.
         for e in self:
     def sanitize(self):
         # TODO: Remove insanity here.
         for e in self: