changeset 2601:ff371330b4ec

markdown parser fixes for tables, definition lists, blockquotes, horizontal rule
author RogerHaase <haaserd@gmail.com>
date Tue, 20 May 2014 11:56:38 -0700
parents d62370bd12e1
children cf66bb9ea54e
files MoinMoin/converter/_tests/test_markdown_in.py MoinMoin/converter/html_out.py MoinMoin/converter/markdown_in.py MoinMoin/themes/foobar/static/css/common.css MoinMoin/themes/foobar/static/css/stylus/main.styl MoinMoin/themes/modernized/static/css/common.css MoinMoin/themes/modernized/static/css/stylus/main.styl
diffstat 7 files changed, 76 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/MoinMoin/converter/_tests/test_markdown_in.py	Mon May 19 09:54:26 2014 -0700
+++ b/MoinMoin/converter/_tests/test_markdown_in.py	Tue May 20 11:56:38 2014 -0700
@@ -35,7 +35,7 @@
             (u'Text\nTest',
                 '<p>Text\nTest</p>'),
             (u'Text\n\nTest',
-                '<p>Text</p>\n<p>Test</p>'),
+                '<p>Text</p><p>Test</p>'),
             (u'<http://moinmo.in/>',
                 '<p><a xlink:href="http://moinmo.in/">http://moinmo.in/</a></p>'),
             (u'[yo](javascript:alert("xss"))',
@@ -43,7 +43,7 @@
             (u'[MoinMoin](http://moinmo.in/)',
                 '<p><a xlink:href="http://moinmo.in/">MoinMoin</a></p>'),
             (u'----',
-                '<separator />'),
+                '<separator class="moin-hr3" />'),
         ]
         for i in data:
             yield (self.do, ) + i
@@ -103,11 +103,11 @@
             (u'###### Heading 6 ######',
                 '<h outline-level="6" xml:id="heading-6">Heading 6</h>'),
             (u'Heading 1\n=========\nHeading 2\n---------\n',
-                '<h outline-level="1" xml:id="heading-1">Heading 1</h>\n<h outline-level="2" xml:id="heading-2">Heading 2</h>'),
+                '<h outline-level="1" xml:id="heading-1">Heading 1</h><h outline-level="2" xml:id="heading-2">Heading 2</h>'),
             (u'Heading 2\n---------\n',
                 '<h outline-level="2" xml:id="heading-2">Heading 2</h>'),
             (u'Heading\n=======\n\nxxxx',
-                '<h outline-level="1" xml:id="heading">Heading</h>\n<p>xxxx</p>'),
+                '<h outline-level="1" xml:id="heading">Heading</h><p>xxxx</p>'),
         ]
         for i in data:
             yield (self.do, ) + i
@@ -115,17 +115,17 @@
     def test_list(self):
         data = [
             (u'* Item',
-                '<list item-label-generate="unordered">\n<list-item><list-item-body>Item</list-item-body></list-item>\n</list>'),
+                '<list item-label-generate="unordered"><list-item><list-item-body>Item</list-item-body></list-item></list>'),
             (u'* Item\nItem',
-                '<list item-label-generate="unordered">\n<list-item><list-item-body>Item\nItem</list-item-body></list-item>\n</list>'),
+                '<list item-label-generate="unordered"><list-item><list-item-body>Item\nItem</list-item-body></list-item></list>'),
             (u'* Item 1\n* Item 2',
-                '<list item-label-generate="unordered">\n<list-item><list-item-body>Item 1</list-item-body></list-item>\n<list-item><list-item-body>Item 2</list-item-body></list-item>\n</list>'),
+                '<list item-label-generate="unordered"><list-item><list-item-body>Item 1</list-item-body></list-item><list-item><list-item-body>Item 2</list-item-body></list-item></list>'),
             (u'* Item 1\n    * Item 1.2\n* Item 2',
-                '<list item-label-generate="unordered">\n<list-item><list-item-body>Item 1<list item-label-generate="unordered">\n<list-item><list-item-body>Item 1.2</list-item-body></list-item>\n</list>\n</list-item-body></list-item>\n<list-item><list-item-body>Item 2</list-item-body></list-item>\n</list>'),
+                '<list item-label-generate="unordered"><list-item><list-item-body>Item 1<list item-label-generate="unordered"><list-item><list-item-body>Item 1.2</list-item-body></list-item></list></list-item-body></list-item><list-item><list-item-body>Item 2</list-item-body></list-item></list>'),
             (u'* List 1\n\nyo\n\n\n* List 2',
-                '<list item-label-generate="unordered">\n<list-item><list-item-body>List 1</list-item-body></list-item>\n</list>\n<p>yo</p>\n<list item-label-generate="unordered">\n<list-item><list-item-body>List 2</list-item-body></list-item>\n</list>'),
+                '<list item-label-generate="unordered"><list-item><list-item-body>List 1</list-item-body></list-item></list><p>yo</p><list item-label-generate="unordered"><list-item><list-item-body>List 2</list-item-body></list-item></list>'),
             (u'8. Item',
-                '<list item-label-generate="ordered">\n<list-item><list-item-body>Item</list-item-body></list-item>\n</list>'),
+                '<list item-label-generate="ordered"><list-item><list-item-body>Item</list-item-body></list-item></list>'),
         ]
         for i in data:
             yield (self.do, ) + i
@@ -155,7 +155,7 @@
     def do(self, input, output, args={}):
         out = self.conv(input, 'text/x-markdown;charset=utf-8', **args)
         got_output = self.serialize(out)
-        desired_output = "<page><body>\n%s\n</body></page>" % output
+        desired_output = "<page><body>%s</body></page>" % output
         print '------------------------------------'
         print "WANTED:"
         print desired_output
--- a/MoinMoin/converter/html_out.py	Mon May 19 09:54:26 2014 -0700
+++ b/MoinMoin/converter/html_out.py	Tue May 20 11:56:38 2014 -0700
@@ -316,6 +316,8 @@
         else:
             ret = html.dl(attrib=attrib_new)
 
+        # TODO: ReST parser creates definition list classifiers but they are ignored here.
+        # TODO: An extraneous  "<dd></dd>" is created given " object::\n :: desc 1\n :: desc 2\n" -- moinwiki_in error?
         for item in elem:
             if isinstance(item, ET.Element):
                 if item.tag.uri == moin_page and item.tag.name == 'list-item':
@@ -336,6 +338,25 @@
                                 break
         return ret
 
+    def visit_moinpage_list_item(self, elem):
+        """
+        Used for markdown definition lists.
+
+        Compared to moinwiki and ReST parsers, the markdown parser creates definition lists using only one
+        list-item tag.name for entire list where moinwiki and ReST have one list-item tag.name for
+        each entry in list.
+        """
+        attrib = Attributes(elem)
+        attrib_new = attrib.convert()
+        ret = html.dl(attrib=attrib_new)
+        for item in elem:
+            if isinstance(item, ET.Element) and item.tag.uri == moin_page:
+                if item.tag.name == 'list-item-label':
+                    ret.append(self.new_copy(html.dt, item))
+                elif item.tag.name == 'list-item-body':
+                    ret.append(self.new_copy(html.dd, item))
+        return ret
+
     def eval_object_type(self, mimetype, href):
         """
         Returns the type of an object as a str, one of the following: img, video, audio, object
--- a/MoinMoin/converter/markdown_in.py	Mon May 19 09:54:26 2014 -0700
+++ b/MoinMoin/converter/markdown_in.py	Tue May 20 11:56:38 2014 -0700
@@ -78,19 +78,28 @@
     symmetric_tags = set(['div', 'p', 'strong', 'code', 'quote', 'blockquote'])
 
     # HTML tags to define a list, except dl which is a little bit different
-    list_tags = set(['ul', 'dir', 'ol'])
+    list_tags = set(['ul', 'ol'])
 
     # HTML tags which can be convert without attributes in a different DOM tag
     simple_tags = {  # Emphasis
-        'em': moin_page.emphasis, 'i': moin_page.emphasis,
+        'em': moin_page.emphasis,
+        'i': moin_page.emphasis,
         # Strong
-        'b': moin_page.strong, 'strong': moin_page.strong,
+        'b': moin_page.strong,
+        'strong': moin_page.strong,
         # Code and Blockcode
-        'pre': moin_page.blockcode, 'tt': moin_page.code,
+        'pre': moin_page.blockcode,
+        'tt': moin_page.code,
         'samp': moin_page.code,
         # Lists
-        'dt': moin_page.list_item_label, 'dd': moin_page.list_item_body,
-        # TODO : Some tags related to tables can be also simplify
+        'dl': moin_page.list_item,
+        'dt': moin_page.list_item_label,
+        'dd': moin_page.list_item_body,
+        # Table - th and td require special processing for alignment of cell contents
+        'table': moin_page.table,
+        'thead': moin_page.table_header,
+        'tbody': moin_page.table_body,
+        'tr': moin_page.table_row,
     }
 
     # HTML Tag which does not have equivalence in the DOM Tree
@@ -218,11 +227,8 @@
         attrib[key] = 'line-through'
         return self.new_copy(moin_page.span, element, attrib)
 
-    def visit_hr(self, element, min_class=u'moin-hr1', max_class=u'moin-hr6', default_class=u'moin-hr3'):
-        hr_class = element.attrib.get('class')
-        if not (min_class <= hr_class <= max_class):
-            element.attrib[html('class')] = default_class
-        return self.new_copy(moin_page.separator, element, {})
+    def visit_hr(self, element, default_class=u'moin-hr3'):
+        return self.new_copy(moin_page.separator, element, {moin_page.class_: default_class})
 
     def visit_img(self, element):
         """
@@ -263,7 +269,7 @@
         For some specific inline tags (defined in inline_tags)
         We just return <span element="tag.name">
         """
-        key = html('class')
+        key = html.class_
         attrib = {}
         attrib[key] = ''.join(['html-', element.tag.name])
         return self.new_copy(moin_page.span, element, attrib)
@@ -324,6 +330,21 @@
             return href
         return self.new_copy(moin_page.a, element, attrib)
 
+    def convert_align_to_class(self, attrib):
+        attr = {}
+        alignment = attrib.get('align')
+        if alignment in (u'right', u'center', u'left'):
+            attr[moin_page.class_] = alignment
+        return attr
+
+    def visit_th(self, element):
+        attrib = self.convert_align_to_class(element.attrib)
+        return self.new_copy(html.th, element, attrib=attrib)
+
+    def visit_td(self, element):
+        attrib = self.convert_align_to_class(element.attrib)
+        return self.new_copy(html.td, element, attrib=attrib)
+
     def visit(self, element):
         # Our element can be converted directly, just by changing the namespace
         if element.tag in self.symmetric_tags:
@@ -361,7 +382,8 @@
 
     def do_children(self, element, add_lineno=False):
         new = []
-        if hasattr(element, "text") and element.text is not None:
+        # markdown parser surrounds child nodes with u"\n" children, we ignore them here to avoid the issue in html_out.py
+        if hasattr(element, "text") and element.text is not None and element.text != u'\n':
             new.append(postproc_text(self.markdown, element.text))
 
         for child in element:
@@ -373,7 +395,7 @@
                     r.attrib[html.data_lineno] = self.line_numbers.popleft()
                 r = (r, )
             new.extend(r)
-            if hasattr(child, "tail") and child.tail is not None:
+            if hasattr(child, "tail") and child.tail is not None and child.tail != u'\n':
                 new.append(postproc_text(self.markdown, child.tail))
         return new
 
--- a/MoinMoin/themes/foobar/static/css/common.css	Mon May 19 09:54:26 2014 -0700
+++ b/MoinMoin/themes/foobar/static/css/common.css	Tue May 20 11:56:38 2014 -0700
@@ -373,6 +373,7 @@
 ol.moin-loweralpha-list{list-style-type:lower-alpha}
 ol.moin-upperroman-list{list-style-type:upper-roman}
 ol.moin-lowerroman-list{list-style-type:lower-roman}
+blockquote{margin-left:2em}
 ul.moin-tags{list-style:none;}
 ul.moin-tags li{display:inline;}
 ul.moin-tags li.weight0{font-size:.4822530864197531em}
--- a/MoinMoin/themes/foobar/static/css/stylus/main.styl	Mon May 19 09:54:26 2014 -0700
+++ b/MoinMoin/themes/foobar/static/css/stylus/main.styl	Tue May 20 11:56:38 2014 -0700
@@ -872,6 +872,9 @@
     &.moin-lowerroman-list
         list-style-type lower-roman
 
+blockquote
+    margin-left 2em
+
 // tags list / tag cloud
 tag_scale = 1.2
 tag_font_size = 1em
--- a/MoinMoin/themes/modernized/static/css/common.css	Mon May 19 09:54:26 2014 -0700
+++ b/MoinMoin/themes/modernized/static/css/common.css	Tue May 20 11:56:38 2014 -0700
@@ -228,6 +228,7 @@
 dd{font-size:.92em;margin-left:40px;margin-top:0;margin-bottom:0}
 dd p{margin:.25em 0}
 dd + dd p{margin-top:.67em}
+blockquote{margin-left:2em}
 hr{height:1px;background-color:#4e7da9;border:0;margin:.9em 0}
 .moin-hr1{height:2px}
 .moin-hr2{height:3px}
--- a/MoinMoin/themes/modernized/static/css/stylus/main.styl	Mon May 19 09:54:26 2014 -0700
+++ b/MoinMoin/themes/modernized/static/css/stylus/main.styl	Tue May 20 11:56:38 2014 -0700
@@ -165,6 +165,9 @@
 dd + dd p
     margin-top .67em
 
+blockquote
+    margin-left 2em
+
 hr
     height 1px
     background-color border_color