Update python-markdown2 to 1.0.1.16 and enable the cuddled-lists extra which TrentM wrote just for us. Thanks Trent!
authorBenjamin Smedberg <benjamin@smedbergs.us>
Wed, 16 Dec 2009 09:03:04 -0500
changeset 25 4c9db541cce3
parent 24 4cfaabdf6eee
child 26 d910e974e583
push id22
push userbsmedberg@mozilla.com
push dateWed, 16 Dec 2009 14:03:08 +0000
Update python-markdown2 to 1.0.1.16 and enable the cuddled-lists extra which TrentM wrote just for us. Thanks Trent!
weeklyupdates/markdown2.py
weeklyupdates/post.py
--- a/weeklyupdates/markdown2.py
+++ b/weeklyupdates/markdown2.py
@@ -30,27 +30,39 @@ Module usage:
 
 This implementation of Markdown implements the full "core" syntax plus a
 number of extras (e.g., code syntax coloring, footnotes) as described on
 <http://code.google.com/p/python-markdown2/wiki/Extras>.
 """
 
 cmdln_desc = """A fast and complete Python implementation of Markdown, a
 text-to-HTML conversion tool for web writers.
+
+Supported extras (see -x|--extras option below):
+* code-friendly: Disable _ and __ for em and strong.
+* code-color: Pygments-based syntax coloring of <code> sections.
+* cuddled-lists: Allow lists to be cuddled to the preceding paragraph.                           
+* footnotes: Support footnotes as in use on daringfireball.net and
+  implemented in other Markdown processors (tho not in Markdown.pl v1.0.1).
+* pyshell: Treats unindented Python interactive shell sessions as <code>
+  blocks.
+* link-patterns: Auto-link given regex patterns in text (e.g. bug number
+  references, revision number references).
+* xml: Passes one-liner processing instructions and namespaced XML tags.
 """
 
 # Dev Notes:
 # - There is already a Python markdown processor
 #   (http://www.freewisdom.org/projects/python-markdown/).
 # - Python's regex syntax doesn't have '\z', so I'm using '\Z'. I'm
 #   not yet sure if there implications with this. Compare 'pydoc sre'
 #   and 'perldoc perlre'.
 
-__version_info__ = (1, 0, 1, 15) # first three nums match Markdown.pl
-__version__ = '1.0.1.15'
+__version_info__ = (1, 0, 1, 16) # first three nums match Markdown.pl
+__version__ = '1.0.1.16'
 __author__ = "Trent Mick"
 
 import os
 import sys
 from pprint import pprint
 import re
 import logging
 try:
@@ -1124,22 +1136,22 @@ class Markdown(object):
             else:
                 list_re = re.compile(r"(?:(?<=\n\n)|\A\n?)"+whole_list,
                                      re.X | re.M | re.S)
                 text = list_re.sub(self._list_sub, text)
 
         return text
     
     _list_item_re = re.compile(r'''
-        (\n)?               # leading line = \1
-        (^[ \t]*)           # leading whitespace = \2
-        (%s) [ \t]+         # list marker = \3
-        ((?:.+?)            # list item text = \4
-         (\n{1,2}))         # eols = \5
-        (?= \n* (\Z | \2 (%s) [ \t]+))
+        (\n)?                   # leading line = \1
+        (^[ \t]*)               # leading whitespace = \2
+        (?P<marker>%s) [ \t]+   # list marker = \3
+        ((?:.+?)                # list item text = \4
+         (\n{1,2}))             # eols = \5
+        (?= \n* (\Z | \2 (?P<next_marker>%s) [ \t]+))
         ''' % (_marker_any, _marker_any),
         re.M | re.X | re.S)
 
     _last_li_endswith_two_eols = False
     def _list_item_sub(self, match):
         item = match.group(4)
         leading_line = match.group(1)
         leading_space = match.group(2)
@@ -1375,25 +1387,45 @@ class Markdown(object):
             return text
         return self._block_quote_re.sub(self._block_quote_sub, text)
 
     def _form_paragraphs(self, text):
         # Strip leading and trailing lines:
         text = text.strip('\n')
 
         # Wrap <p> tags.
-        grafs = re.split(r"\n{2,}", text)
-        for i, graf in enumerate(grafs):
+        grafs = []
+        for i, graf in enumerate(re.split(r"\n{2,}", text)):
             if graf in self.html_blocks:
                 # Unhashify HTML blocks
-                grafs[i] = self.html_blocks[graf]
+                grafs.append(self.html_blocks[graf])
             else:
+                cuddled_list = None
+                if "cuddled-lists" in self.extras:
+                    # Need to put back trailing '\n' for `_list_item_re`
+                    # match at the end of the paragraph.
+                    li = self._list_item_re.search(graf + '\n')
+                    # Two of the same list marker in this paragraph: a likely
+                    # candidate for a list cuddled to preceding paragraph
+                    # text (issue 33). Note the `[-1]` is a quick way to
+                    # consider numeric bullets (e.g. "1." and "2.") to be
+                    # equal.
+                    if (li and li.group("next_marker")
+                        and li.group("marker")[-1] == li.group("next_marker")[-1]):
+                        start = li.start()
+                        cuddled_list = self._do_lists(graf[start:]).rstrip("\n")
+                        assert cuddled_list.startswith("<ul>") or cuddled_list.startswith("<ol>")
+                        graf = graf[:start]
+                    
                 # Wrap <p> tags.
                 graf = self._run_span_gamut(graf)
-                grafs[i] = "<p>" + graf.lstrip(" \t") + "</p>"
+                grafs.append("<p>" + graf.lstrip(" \t") + "</p>")
+                
+                if cuddled_list:
+                    grafs.append(cuddled_list)
 
         return "\n\n".join(grafs)
 
     def _add_footnotes(self, text):
         if self.footnotes:
             footer = [
                 '<div class="footnotes">',
                 '<hr' + self.empty_element_suffix,
@@ -1784,23 +1816,17 @@ def main(argv=None):
     parser.add_option("--html4tags", action="store_true", default=False, 
                       help="use HTML 4 style for empty element tags")
     parser.add_option("-s", "--safe", metavar="MODE", dest="safe_mode",
                       help="sanitize literal HTML: 'escape' escapes "
                            "HTML meta chars, 'replace' replaces with an "
                            "[HTML_REMOVED] note")
     parser.add_option("-x", "--extras", action="append",
                       help="Turn on specific extra features (not part of "
-                           "the core Markdown spec). Supported values: "
-                           "'code-friendly' disables _/__ for emphasis; "
-                           "'code-color' adds code-block syntax coloring; "
-                           "'link-patterns' adds auto-linking based on patterns; "
-                           "'footnotes' adds the footnotes syntax;"
-                           "'xml' passes one-liner processing instructions and namespaced XML tags;"
-                           "'pyshell' to put unindented Python interactive shell sessions in a <code> block.")
+                           "the core Markdown spec). See above.")
     parser.add_option("--use-file-vars",
                       help="Look for and use Emacs-style 'markdown-extras' "
                            "file var to turn on extras. See "
                            "<http://code.google.com/p/python-markdown2/wiki/Extras>.")
     parser.add_option("--link-patterns-file",
                       help="path to a link pattern file")
     parser.add_option("--self-test", action="store_true",
                       help="run internal self-tests (some doctests)")
--- a/weeklyupdates/post.py
+++ b/weeklyupdates/post.py
@@ -4,17 +4,19 @@ from genshi.input import HTML
 import markdown2
 import re
 
 link_patterns = (
     (re.compile(r'(https?://.*\b)'), r'\1'),
     (re.compile(r'bug[\s:#]+(\d{3,7})\b'), r'https://bugzilla.mozilla.org/show_bug?id=\1'),
 )
 
-md = markdown2.Markdown(html4tags=True, tab_width=2, extras=['link-patterns'],
+md = markdown2.Markdown(html4tags=True, tab_width=2,
+                        extras=['link-patterns',
+                                'cuddled-lists'],
                         link_patterns=link_patterns)
 
 class Post(object):
     username = None
     postdate = None
     posttime = None
     completed = None
     planned = None