from django.template import Library from django.utils.encoding import force_unicode import re register = Library() re_widont = re.compile(r'\s+(\S+\s*)$') def widont(value, count=1): """ Adds an HTML non-breaking space between the final two words of the string to avoid "widowed" words. Examples: >>> print widont('Test me out') Test me out >>> widont('It works with trailing spaces too ') u'It works with trailing spaces too ' >>> print widont('NoEffect') NoEffect """ def replace(matchobj): return u' %s' % matchobj.group(1) for i in range(count): value = re_widont.sub(replace, force_unicode(value)) return value re_widont_html = re.compile(r'([^<>\s])\s+([^<>\s]+\s*)(?(?:address|blockquote|br|dd|div|dt|fieldset|form|h[1-6]|li|noscript|p|td|th)[^>]*>|$)', re.IGNORECASE) def widont_html(value): """ Adds an HTML non-breaking space between the final two words at the end of (and in sentences just outside of) block level tags to avoid "widowed" words. Examples: >>> print widont_html('
Single
')Single
>>> print widont_html('test me
out
and this
')test me
out
and this
>>> print widont_html('leading texttest me out
trailing text') leading texttest me out
trailing text """ def replace(matchobj): return u'%s %s%s' % matchobj.groups() return re_widont_html.sub(replace, force_unicode(value)) register.filter(widont) register.filter(widont_html) def _test(): import doctest doctest.testmod() if __name__ == "__main__": _test()