Ticket #5025: 5025.diff
File 5025.diff, 6.7 KB (added by , 13 years ago) |
---|
-
django/template/defaultfilters.py
diff --git a/django/template/defaultfilters.py b/django/template/defaultfilters.py index 60fa59e..8f7b1b7 100644
a b def title(value): 239 239 title.is_safe = True 240 240 title = stringfilter(title) 241 241 242 def truncatechars(value, arg): 243 """ 244 Truncates a string after a certain number of characters. 245 246 Argument: Number of characters to truncate after. 247 """ 248 from django.utils.text import truncate_chars 249 try: 250 length = int(arg) 251 except ValueError: # Invalid literal for int(). 252 return value # Fail silently. 253 return truncate_chars(value, length) 254 truncatechars.is_safe = True 255 truncatechars = stringfilter(truncatechars) 256 242 257 def truncatewords(value, arg): 243 258 """ 244 259 Truncates a string after a certain number of words. -
django/utils/text.py
diff --git a/django/utils/text.py b/django/utils/text.py index 00c999c..a618a96 100644
a b 1 1 import re 2 import unicodedata 2 3 from django.utils.encoding import force_unicode 3 4 from django.utils.functional import allow_lazy 4 5 from django.utils.translation import ugettext_lazy, ugettext as _ … … def wrap(text, width): 36 37 return u''.join(_generator()) 37 38 wrap = allow_lazy(wrap, unicode) 38 39 40 def truncate_chars(s, num, end_text=ugettext_lazy('...')): 41 """Truncates a string to be no longer than the specified number of 42 characters. Takes an optional argument of what should be used to notify 43 that the string has been truncated, defaulting to a translatable string of 44 an ellipsis (...) 45 """ 46 s = unicodedata.normalize('NFC', force_unicode(s)) 47 length = int(num) 48 end_text = unicodedata.normalize('NFC', force_unicode(end_text)) 49 50 # Calculate the length to truncate to (max length - end_text length) 51 truncate_len = length 52 for char in end_text: 53 if not unicodedata.combining(char): 54 truncate_len -= 1 55 if truncate_len == 0: 56 break 57 58 s_len = 0 59 end_index = None 60 for i, char in enumerate(s): 61 if unicodedata.combining(char): 62 # Don't consider combining characters as adding to the string 63 # length 64 continue 65 s_len += 1 66 if end_index is None and s_len > truncate_len: 67 end_index = i 68 if s_len > length: 69 # Return the truncated string 70 return u'%s%s' % (s[:end_index or 0], end_text) 71 72 # Return the original string since no truncation was necessary 73 return s 74 truncate_chars = allow_lazy(truncate_chars, unicode) 75 39 76 def truncate_words(s, num, end_text='...'): 40 77 """Truncates a string after a certain number of words. Takes an optional 41 78 argument of what should be used to notify that the string has been -
docs/ref/templates/builtins.txt
diff --git a/docs/ref/templates/builtins.txt b/docs/ref/templates/builtins.txt index 29bed25..efddf02 100644
a b For example:: 2024 2024 2025 2025 If ``value`` is ``"my first post"``, the output will be ``"My First Post"``. 2026 2026 2027 .. templatefilter:: truncatechars 2028 2029 truncatechars 2030 ~~~~~~~~~~~~~ 2031 2032 Truncates a string if it is longer than the specified number of characters. 2033 Truncated strings will end with a translatable ellipsis sequence ("..."). 2034 2035 **Argument:** Number of characters to truncate to 2036 2037 For example:: 2038 2039 {{ value|truncatechars:9 }} 2040 2041 If ``value`` is ``"Joel is a slug"``, the output will be ``"Joel i..."``. 2042 2027 2043 .. templatefilter:: truncatewords 2028 2044 2029 2045 truncatewords -
docs/releases/1.4.txt
diff --git a/docs/releases/1.4.txt b/docs/releases/1.4.txt index 496a4c9..d57cc49 100644
a b A new helper function, 60 60 ``template.Library`` to ease the creation of template tags that store some 61 61 data in a specified context variable. 62 62 63 ``truncatechars`` template filter 64 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 65 66 Added a filter which truncates a string to be no longer than the specified 67 number of characters. Truncated strings end with a translatable ellipsis 68 sequence ("..."). 69 63 70 .. _backwards-incompatible-changes-1.4: 64 71 65 72 Backwards incompatible changes in 1.4 -
tests/regressiontests/utils/text.py
diff --git a/tests/regressiontests/utils/text.py b/tests/regressiontests/utils/text.py index f565d87..3f0a189 100644
a b 1 # -*- coding: utf-8 -*- 1 2 import unittest 2 3 3 4 from django.utils import text 4 5 5 6 class TestUtilsText(unittest.TestCase): 6 7 8 def test_truncate_chars(self): 9 self.assertEqual(u'The quick brown fox jumped over the lazy dog.', 10 text.truncate_chars(u'The quick brown fox jumped over the lazy dog.', 100)) 11 self.assertEqual(u'The quick brown fox ...', 12 text.truncate_chars('The quick brown fox jumped over the lazy dog.', 23)) 13 self.assertEqual(u'The quick brown fo.....', 14 text.truncate_chars('The quick brown fox jumped over the lazy dog.', 23, '.....')) 15 16 # Ensure that we normalize our unicode data first 17 nfc = u'o\xfco\xfco\xfco\xfc' 18 nfd = u'ou\u0308ou\u0308ou\u0308ou\u0308' 19 self.assertEqual(u'oüoüoüoü', text.truncate_chars(nfc, 8)) 20 self.assertEqual(u'oüoüoüoü', text.truncate_chars(nfd, 8)) 21 self.assertEqual(u'oü...', text.truncate_chars(nfc, 5)) 22 self.assertEqual(u'oü...', text.truncate_chars(nfd, 5)) 23 24 # Ensure the final length is calculated correctly when there are 25 # combining characters with no precomposed form, and that combining 26 # characters are not split up. 27 self.assertEqual(u'-B\u030A...', 28 text.truncate_chars(u'-B\u030AB\u030A----8', 5)) 29 self.assertEqual(u'-B\u030AB\u030A-...', 30 text.truncate_chars(u'-B\u030AB\u030A----8', 7)) 31 self.assertEqual(u'-B\u030AB\u030A----8', 32 text.truncate_chars(u'-B\u030AB\u030A----8', 8)) 33 34 # Ensure the length of the end text is correctly calculated when it 35 # contains combining characters with no precomposed form. 36 self.assertEqual(u'---B\u030A', 37 text.truncate_chars(u'-----', 4, end_text=u'B\u030A')) 38 self.assertEqual(u'-----', 39 text.truncate_chars(u'-----', 5, end_text=u'B\u030A')) 40 41 # Make a best effort to shorten to the desired length, but requesting 42 # a length shorter than the ellipsis shouldn't break 43 self.assertEqual(u'...', text.truncate_chars(u'asdf', 1)) 44 7 45 def test_truncate_words(self): 8 46 self.assertEqual(u'The quick brown fox jumped over the lazy dog.', 9 47 text.truncate_words(u'The quick brown fox jumped over the lazy dog.', 10))