Commits

Mike Orr committed f95664d

New helpers nl2br() and format_paragraphs in webhelpers.html.converters.

Comments (0)

Files changed (3)

 * Fixed bug in SimplerXMLGenerator that the FeedGenerator uses, so that
   it doesn't use a {} arg.
 * New helpers:
+  - nl2br() and format_paragraphs() in webhelpers.html.converters.
   - ul() and ol() in webhelpers.html.tags.
   - series() in webhelpers.text.
 * Change default form method to "post" (rather than "POST") to conform to XHTML.

tests/test_converters.py

 # -*- coding: utf-8 -*-
-from util import WebHelpersTestCase
-import unittest
+from nose.tools import eq_
 
 from webhelpers.html import HTML, literal
-from webhelpers.html.converters import markdown, textilize
+from webhelpers.html.converters import *
 
-class TestConvertersHelper(WebHelpersTestCase):
-    
-    def test_textilize(self):
-        self.assertEqual('<h1>This is a test of textile</h1>\n\n<p>Paragraph</p>\n\n<p>Another paragraph</p>\n\n<ul>\n<li>Bullets</li>\n</ul>',
-                         textilize("h1. This is a test of textile\n\nParagraph\n\nAnother paragraph\n\n* Bullets"))
+def test_textilize():
+    eq_('<h1>This is a test of textile</h1>\n\n<p>Paragraph</p>\n\n<p>Another paragraph</p>\n\n<ul>\n<li>Bullets</li>\n</ul>',
+        textilize("h1. This is a test of textile\n\nParagraph\n\nAnother paragraph\n\n* Bullets"))
 
-    def test_markdown(self):
-        markdown_text = """
+def test_markdown():
+    markdown_text = """
 Introduction
 ------------
 
 ----------------
 
 [Michel Fortin][] has ported to Markdown to PHP.
-        """
-        self.assertEqual('\n\n<h2>Introduction</h2>\n<p>Markdown is a text-to-HTML conversion tool for web writers.\n</p>\n\n<h2>Acknowledgements <a id="acknowledgements" /></h2>\n<p>[Michel Fortin][] has ported to Markdown to PHP.\n</p>\n\n\n',
-                         markdown(markdown_text))
+    """
+    eq_('\n\n<h2>Introduction</h2>\n<p>Markdown is a text-to-HTML conversion tool for web writers.\n</p>\n\n<h2>Acknowledgements <a id="acknowledgements" /></h2>\n<p>[Michel Fortin][] has ported to Markdown to PHP.\n</p>\n\n\n',
+                markdown(markdown_text))
 
+def test_nl2br():
+    eq_(u'A B<br />\nC D<br />\n<br />\nE F', nl2br("A B\nC D\r\n\r\nE F"))
 
-if __name__ == '__main__':
-    suite = map(unittest.makeSuite, [
-        TestConvertersHelper,
-        ])
-    for testsuite in suite:
-        unittest.TextTestRunner(verbosity=1).run(testsuite)
+def test_format_paragraphs1():
+    eq_(u"<p>crazy\n cross\n platform linebreaks</p>", format_paragraphs("crazy\r\n cross\r platform linebreaks"))
+
+def test_format_paragraphs2():
+    eq_(u"<p>crazy<br />\n cross<br />\n platform linebreaks</p>", format_paragraphs("crazy\r\n cross\r platform linebreaks", True))
+
+def test_format_paragraphs3():
+    eq_(u"<p>A paragraph</p>\n\n<p>and another one!</p>", format_paragraphs("A paragraph\n\nand another one!"))
+
+def test_format_paragraphs4():
+    eq_(u"<p>A paragraph<br />\n With a newline</p>", format_paragraphs("A paragraph\n With a newline", True))
+
+def test_format_paragraphs5():
+    eq_(u"<p>A paragraph\n With a newline</p>", format_paragraphs("A paragraph\n With a newline", False))
+
+def test_format_paragraphs6():
+    eq_(u"<p>A paragraph\n With a newline</p>", format_paragraphs("A paragraph\n With a newline"))
+
+def test_format_paragraphs7():
+    eq_(u"<p></p>", format_paragraphs(None))

webhelpers/html/converters.py

 """Functions that convert from text markup languages to HTML.
 
 """
+import re
 
-from webhelpers.html import literal
+from webhelpers.html import HTML, literal
 import webhelpers.textile as textile
 import webhelpers.markdown as _markdown
 
 __all__ = [
-    'markdown', 
-    'textilize',
+    "markdown", 
+    "textilize",
+    "nl2br",
+    "format_paragraphs",
     ]
 
+_universal_newline_rx = re.compile(R"\r\n|\n|\r")  # All types of newline.
+_paragraph_rx = re.compile(R"\n{2,}")  # Paragraph break: 2 or more newlines.
+br = HTML.br() + "\n"
+
 def markdown(text, **kwargs):
     """Format the text with MarkDown formatting.
     
     """
     texer = textile.Textiler(text)
     return literal(texer.process(sanitize=sanitize))
+
+def nl2br(text):
+    """Insert a <br /> before each newline.
+    """
+    if text is None:
+        return literal("")
+    text = _universal_newline_rx.sub("\n", text)
+    text = text.replace("\n", br)
+    return text
+
+def format_paragraphs(text, preserve_lines=False):
+    """Convert text to HTML paragraphs.
+
+    ``text``:
+        the text to convert.  Split into paragraphs at blank lines (i.e.,
+        wherever two or more consecutive newlines appear), and wrap each
+        paragraph in a <p>.
+
+    ``preserve_lines``:
+        If true, add <br />  before each single line break
+    """
+    if text is None:
+        text = literal("")
+    text = _universal_newline_rx.sub("\n", text)
+    paragraphs = _paragraph_rx.split(text)
+    for i, para in enumerate(paragraphs):
+        if preserve_lines:
+            para = HTML(para)
+            para = para.replace("\n", br)
+        paragraphs[i] = HTML.p(para)
+    return "\n\n".join(paragraphs)
+
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.