Commits

pjenvey  committed c6af96a

[svn] Sync'd text helper to 5629. Still needs to get to 6096, which is mostly
auto_link changes
o fixed excerpt to be case insensitive
o excerpt now only uses excerpt_string when it's necessary (this was only broken
in WebHelpers)
o deprecate word_wrap for python's builtin textwrap.fill
o allow simple_format to accept None
o fixed strip_links to be case insensitive
o doc updates
o merged in tests for excerpt, highlighter, strip_links and truncate

  • Participants
  • Parent commits 8f0ebef

Comments (0)

Files changed (3)

 WebHelpers ChangeLog
 
 0.2.3 (**svn**)
+* Sync'd Text helper to 5629.
 * Sync'd Date helper to 6080.
 * Sync'd Tags helper to 5857.
 * Sync'd Asset tag helper to 6057.

File tests/test_text.py

+# -*- coding: utf-8 -*-
 from unittest import TestCase
 import unittest
 from string24 import Template
 class TestTextHelper(TestCase):
     
     def test_simple_format(self):
+        self.assertEqual("<p></p>", simple_format(None))
         self.assertEqual("<p>crazy\n<br /> cross\n<br /> platform linebreaks</p>", simple_format("crazy\r\n cross\r platform linebreaks"))
         self.assertEqual("<p>A paragraph</p>\n\n<p>and another one!</p>", simple_format("A paragraph\n\nand another one!"))
         self.assertEqual("<p>A paragraph\n<br /> With a newline</p>", simple_format("A paragraph\n With a newline"))
         self.assertEqual( '<p>Say hello to %(email_result)s, then go to %(link5_result)s.</p>' %result_values, auto_link('<p>Say hello to %(email_raw)s, then go to %(link5_raw)s.</p>' %raw_values))
         self.assertEqual('%(link6_result)s' % result_values, auto_link('%(link6_raw)s' % raw_values))
 
+    def test_excerpt(self):
+        self.assertEqual("...lo my wo...",
+                         excerpt("hello my world", "my", 3))
+        self.assertEqual("...is a beautiful morn...",
+                         excerpt("This is a beautiful morning", "beautiful", 5))
+        self.assertEqual("This is a...",
+                         excerpt("This is a beautiful morning", "this", 5))
+        self.assertEqual("...iful morning",
+                         excerpt("This is a beautiful morning", "morning", 5))
+        self.assertEqual('',
+                         excerpt("This is a beautiful morning", "day"))
+
+    def test_excerpt_with_regex(self):
+        self.assertEqual('...is a beautiful! mor...',
+                         excerpt('This is a beautiful! morning', 'beautiful', 5))
+        self.assertEqual('...is a beautiful? mor...',
+                         excerpt('This is a beautiful? morning', 'beautiful', 5))
+
+    def test_excerpt_with_utf8(self):
+        self.assertEqual(u"...fficiency could not be ...",
+                         excerpt(u"That's why efficiency could not be helped", 'could', 8))
+
+
+    def test_highlighter(self):
+        self.assertEqual("This is a <strong class=\"hilight\">beautiful</strong> morning",
+                         highlight("This is a beautiful morning", "beautiful"))
+        self.assertEqual(
+            "This is a <strong class=\"hilight\">beautiful</strong> morning, but also a <strong class=\"hilight\">beautiful</strong> day",
+            highlight("This is a beautiful morning, but also a beautiful day", "beautiful"))
+        self.assertEqual("This is a <b>beautiful</b> morning, but also a <b>beautiful</b> day",
+                         highlight("This is a beautiful morning, but also a beautiful day",
+                                   "beautiful", r'<b>\1</b>'))
+        self.assertEqual("This text is not changed because we supplied an empty phrase",
+                         highlight("This text is not changed because we supplied an empty phrase",
+                                   None))
+
+    def test_highlighter_with_regex(self):
+        self.assertEqual("This is a <strong class=\"hilight\">beautiful!</strong> morning",
+                     highlight("This is a beautiful! morning", "beautiful!"))
+
+        self.assertEqual("This is a <strong class=\"hilight\">beautiful! morning</strong>",
+                     highlight("This is a beautiful! morning", "beautiful! morning"))
+
+        self.assertEqual("This is a <strong class=\"hilight\">beautiful? morning</strong>",
+                     highlight("This is a beautiful? morning", "beautiful? morning"))
+
+    def test_strip_links(self):
+        self.assertEqual("on my mind", strip_links("<a href='almost'>on my mind</a>"))
+        self.assertEqual("on my mind", strip_links("<A href='almost'>on my mind</A>"))
+        self.assertEqual("on my mind\nall day long",
+                         strip_links("<a href='almost'>on my mind</a>\n<A href='almost'>all day long</A>"))
+
+    def test_truncate(self):
+        self.assertEqual("Hello World!", truncate("Hello World!", 12))
+        self.assertEqual("Hello Wor...", truncate("Hello World!!", 12))
+
 if __name__ == '__main__':
     suite = [unittest.makeSuite(TestTextHelper)]
     for testsuite in suite:

File webhelpers/rails/text.py

 """
 Text Helpers
+
+Provides a set of methods for filtering, formatting and transforming strings.
 """
-# Last synced with Rails copy at Revision 4994 on Sep 6th, 2006.
+# Last synced with Rails copy at Revision 5629 on Feb 8th, 2007.
 # Purposely left out sanitize and strip_tags, should be included at some point likely using
 # BeautifulSoup.
 
+import itertools
+import re
+import textwrap
+import warnings
+import webhelpers.textile as textile
+import webhelpers.markdown as markdown
 from routes import request_config
 from webhelpers.rails.tags import content_tag, tag_options
-import webhelpers.textile as textile
-import webhelpers.markdown as markdown
-import itertools, re
 
 AUTO_LINK_RE = re.compile(r"""
                         (                        # leading text
-                          <\w+.*?>|              #   leading HTML tag, or
-                          [^=!:'"/]|             #   leading punctuation, or 
-                          ^                      #   beginning of line
+                          <\w+.*?>|              # leading HTML tag, or
+                          [^=!:'"/]|             # leading punctuation, or 
+                          ^                      # beginning of line
                         )
                         (
                           (?:https?://)|         # protocol spec, or
     ``truncate_string``
         If ``text`` exceeds the ``length``, this string will replace
         the end of the string
+
+    Example::
+
+        >>> truncate('Once upon a time in a world far far away', 14)
+        'Once upon a...'
     """
     if not text: return ''
     
         with ``\\1`` where the phrase is supposed to be inserted.
         
     Note: The ``phrase`` is sanitized to include only letters, digits, and spaces before use.
+
+    Example::
+
+        >>> highlight('You searched for: Pylons', 'Pylons')
+        'You searched for: <strong class="hilight">Pylons</strong>'
     """
     if not phrase or not text:
         return text
 
 def excerpt(text, phrase, radius=100, excerpt_string="..."):
     """
-    Extracts an excerpt from the ``text``
-    
+    Extracts an excerpt from the ``text``. Returns an empty string if the phrase
+    isn't found.
+
     ``phrase``
         Phrase to excerpt from ``text``
     ``radius``
     """
     if not text or not phrase:
         return text
-    
-    pat = re.compile('(.{0,%s}%s.{0,%s})' % (radius, re.escape(phrase), radius))
+
+    pat = re.compile('(.{0,%s}%s.{0,%s})' % (radius, re.escape(phrase), radius), re.I)
     match = pat.search(text)
     if not match:
         return ""
-    return excerpt_string + match.expand(r'\1') + excerpt_string
+    excerpt = match.expand(r'\1')
+    if match.start(1) > 0:
+        excerpt = excerpt_string + excerpt
+    if match.end(1) < len(text):
+        excerpt = excerpt + excerpt_string
+    return excerpt
 
 def word_wrap(text, line_width=80):
     """
-    Word wrap long lines to ``line_width``
+    Wraps ``text`` into lines no longer than ``line_width`` width. This function
+    breaks on the first whitespace character that does not exceed ``line_width``.
+
+    Deprecated: Use python's builtin textwrap.fill instead.
     """
-    text = re.sub(r'\n', '\n\n', text)
-    return re.sub(r'(.{1,%s})(\s+|$)' % line_width, r'\1\n', text).strip()
+    warnings.warn("The word_wrap function has been deprecated: Use python's builtin "
+                  "textwrap.fill function instead.", DeprecationWarning, 2)
+    return textwrap.fill(text, line_width)
 
 def simple_format(text):
     """
     Returns ``text`` transformed into HTML using very simple formatting rules
     
-    Surrounds paragraphs with ``<p>`` tags, and converts line breaks into ``<br />``
-    Two consecutive newlines(``\\n\\n``) are considered as a paragraph, one newline (``\\n``) is
-    considered a linebreak, three or more consecutive newlines are turned into two newlines.
+    Two or more consecutive newlines(``\\n\\n``) are considered as a paragraph
+    and wrapped in ``<p>`` tags. One newline (``\\n``) is considered a
+    linebreak and a ``<br />`` tag is appended. This method does not remove the
+    newlines from the text.
     """
+    if text is None:
+        text = ''
     text = re.sub(r'(\r\n|\n|\r)', r'\n', text)
     text = re.sub(r'\n\n+', r'\n\n', text)
     text = re.sub(r'(\n\n)', r'</p>\1<p>', text)
 
 def auto_link(text, link="all", **href_options):
     """
-    Turns all urls and email addresses into clickable links. 
+    Turns all urls and email addresses into clickable links.
     
     ``link``
         Used to determine what to link. Options are "all", "email_addresses", or "urls"
 
 def strip_links(text):
     """
-    Turns all links into words
+    Strips link tags from ``text`` leaving just the link label.
     
     Example::
     
         >>> strip_links("<a href="something">else</a>")
         "else"
     """
-    strip_re = re.compile(r'<a\b.*?>(.*?)<\/a>', re.M)
+    strip_re = re.compile(r'<a\b.*?>(.*?)<\/a>', re.I | re.M)
     return strip_re.sub(r'\1', text)
 
 def textilize(text, sanitize=False):