diff MoinMoin/formatter/text_html.py @ 2572:ce0787373150

introduce ID cache in request, make everybody generate valid IDs even inside includes fixes the TOC macro, top/bottom etc. links inside includes, also [#anchorlinks] etc.
author Johannes Berg <johannes AT sipsolutions DOT net>
date Thu, 26 Jul 2007 16:29:13 +0200
parents 896b81e9764e
children f4c371b00fec
line wrap: on
line diff
--- a/MoinMoin/formatter/text_html.py	Thu Jul 26 16:26:44 2007 +0200
+++ b/MoinMoin/formatter/text_html.py	Thu Jul 26 16:29:13 2007 +0200
@@ -17,6 +17,10 @@
 from MoinMoin.Page import Page
 from MoinMoin.action import AttachFile
 
+# insert IDs into output wherever they occur
+# warning: breaks toggle line numbers javascript
+_id_debug = False
+
 line_anchors = True
 prettyprint = False
 
@@ -184,11 +188,9 @@
         self._in_code = 0 # used by text_gedit
         self._in_code_area = 0
         self._in_code_line = 0
-        self._code_area_num = 0
         self._code_area_js = 0
         self._code_area_state = ['', 0, -1, -1, 0]
         self._show_section_numbers = None
-        self._content_ids = []
         self.pagelink_preclosed = False
         self._is_included = kw.get('is_included', False)
         self.request = request
@@ -316,13 +318,15 @@
             return ' '.join(all)
         return ''
 
-    def _open(self, tag, newline=False, attr=None, allowed_attrs=None, **kw):
+    def _open(self, tag, newline=False, attr=None, allowed_attrs=None,
+              is_unique=False, **kw):
         """ Open a tag with optional attributes (INTERNAL USE BY HTML FORMATTER ONLY!)
 
         @param tag: html tag, string
         @param newline: render tag so following data is on a separate line
         @param attr: dict with tag attributes
         @param allowed_attrs: list of allowed attributes for this element
+        @param is_unique: ID is already unique
         @param kw: arbitrary attributes and values
         @rtype: string ?
         @return: open tag with attributes as a string
@@ -330,6 +334,21 @@
         # If it is self-closing, then don't expect a closing tag later on.
         is_self_closing = (tag in _self_closing_tags) and ' /' or ''
 
+        # make ID unique
+        id = None
+        if not is_unique:
+            if attr and 'id' in attr:
+                attr['id'] = self.make_id_unique(attr['id'])
+                id = attr['id']
+            if 'id' in kw:
+                kw['id'] = self.make_id_unique(kw['id'])
+                id = kw['id']
+        else:
+            if attr and 'id' in attr:
+                id = attr['id']
+            if 'id' in kw:
+                id = kw['id']
+
         if tag in _blocks:
             # Block elements
             result = []
@@ -344,6 +363,8 @@
             result.append('<%s%s%s>' % (tag, attributes, is_self_closing))
             if newline:
                 result.append(self._newline())
+            if _id_debug and id:
+                result.append('(%s) ' % id)
             tagstr = ''.join(result)
         else:
             # Inline elements
@@ -384,23 +405,19 @@
         """ Start page content div.
 
         A link anchor is provided at the beginning of the div, with
-        an id of 'top' or 'top_xxxx' if the content_id argument is
-        set to 'xxxx'.
+        an id of 'top' (modified by the request ID cache).
         """
 
-        # Setup id
-        if content_id != 'content':
-            aid = 'top_%s' % (content_id, )
-        else:
-            aid = 'top'
-        self._content_ids.append(content_id)
+        if hasattr(self, 'page'):
+            self.request.begin_include(self.page.page_name)
+
         result = []
         # Use the content language
         attr = self._langAttr(self.request.content_lang)
         attr['id'] = content_id
         result.append(self._open('div', newline=False, attr=attr,
                                  allowed_attrs=['align'], **kw))
-        result.append(self.anchordef(aid))
+        result.append(self.anchordef('top'))
         if newline:
             result.append('\n')
         return ''.join(result)
@@ -409,23 +426,14 @@
         """ Close page content div.
 
         A link anchor is provided at the end of the div, with
-        an id of 'bottom' or 'bottom_xxxx' if the content_id argument
-        to the previus startContent() call was set to 'xxxx'.
+        an id of 'bottom' (modified by the request ID cache).
         """
 
-        # Setup id
-        try:
-            cid = self._content_ids.pop()
-        except:
-            cid = 'content'
-        if cid != 'content':
-            aid = 'bottom_%s' % (cid, )
-        else:
-            aid = 'bottom'
-
         result = []
-        result.append(self.anchordef(aid))
+        result.append(self.anchordef('bottom'))
         result.append(self._close('div', newline=newline))
+        if hasattr(self, 'page'):
+            self.request.end_include()
         return ''.join(result)
 
     def lang(self, on, lang_name):
@@ -552,6 +560,7 @@
         # Don't add newlines, \n, as it will break pre and
         # line-numbered code sections (from line_achordef() method).
         #return '<a id="%s"></a>' % (id, ) # do not use - this breaks PRE sections for IE
+        id = self.make_id_unique(id)
         return '<span class="anchor" id="%s"></span>' % wikiutil.escape(id, 1)
 
     def line_anchordef(self, lineno):
@@ -574,10 +583,13 @@
         The id argument, if provided, is instead the id of this link
         itself and not of the target element the link references.
         """
-
         attrs = self._langAttr()
         if name:
-            attrs['href'] = '#%s' % name
+            if self.request.include_id:
+                attrs['href'] = '#%s.%s' % (
+                    wikiutil.anchor_name_from_text(self.request.include_id), name)
+            else:
+                attrs['href'] = '#%s' % name
         if 'href' in kw:
             del kw['href']
         if on:
@@ -800,7 +812,6 @@
         non-break spaces.
         """
         tag = 'tt'
-        # Maybe we don't need this, because we have tt will be in inlineStack.
         self._in_code = on
         if on:
             return self._open(tag, allowed_attrs=[], **kw)
@@ -904,7 +915,7 @@
         must be unique within the document.  The show, start, and step are
         used for line numbering.
 
-        Note this is not like most formatter methods, it can not take any
+B        Note this is not like most formatter methods, it can not take any
         extra keyword arguments.
 
         Call once with on=1 to start the region, and a second time
@@ -912,12 +923,13 @@
         """
         _ = self.request.getText
         res = []
-        ci = self.request.make_unique_id('CA-%s_%03d' % (code_id, self._code_area_num))
         if on:
+            ci = self.make_id_unique('CA-%s' % code_id)
             # Open a code area
             self._in_code_area = 1
             self._in_code_line = 0
-            self._code_area_state = [ci, show, start, step, start]
+            # id in here no longer used
+            self._code_area_state = [None, show, start, step, start]
 
             # Open the code div - using left to right always!
             attr = {'class': 'codearea', 'lang': 'en', 'dir': 'ltr'}
@@ -935,13 +947,13 @@
 document.write('<a href="#" onclick="return togglenumber(\'%s\', %d, %d);" \
                 class="codenumbers">%s<\/a>');
 </script>
-''' % (self._code_area_state[0], self._code_area_state[2], self._code_area_state[3],
+''' % (ci, self._code_area_state[2], self._code_area_state[3],
        _("Toggle line numbers"))
                 res.append(toggleLineNumbersLink)
 
             # Open pre - using left to right always!
-            attr = {'id': self._code_area_state[0], 'lang': 'en', 'dir': 'ltr'}
-            res.append(self._open('pre', newline=True, attr=attr))
+            attr = {'id': ci, 'lang': 'en', 'dir': 'ltr'}
+            res.append(self._open('pre', newline=True, attr=attr, is_unique=True))
         else:
             # Close code area
             res = []
@@ -952,7 +964,6 @@
 
             # Update state
             self._in_code_area = 0
-            self._code_area_num += 1
 
         return ''.join(res)
 
@@ -1172,17 +1183,13 @@
             number = '.'.join([str(x) for x in self.request._fmt_hd_counters[self._show_section_numbers-1:]])
             if number: number += ". "
 
-        # make ID unique
-        if 'id' in kw:
-            kw['id'] = self.request.make_unique_id(kw['id'])
-
         # Add space before heading, easier to check source code
         result = '\n' + self._open('h%d' % heading_depth, **kw)
 
         if self.request.user.show_topbottom:
             result += "%s%s%s%s%s%s" % (
-                       self.url(1, "#bottom", do_escape=0), self.icon('bottom'), self.url(0),
-                       self.url(1, "#top", do_escape=0), self.icon('top'), self.url(0))
+                       self.anchorlink(1, "bottom"), self.icon('bottom'), self.anchorlink(0),
+                       self.anchorlink(1, "top"), self.icon('top'), self.anchorlink(0))
 
         return "%s%s" % (result, number)