1 | # -*- coding: utf-8 -*-
|
---|
2 |
|
---|
3 | # truncate.py
|
---|
4 | # Copyright © 2009 Paul Schreiber
|
---|
5 | # paulschreiber at gmail dot com
|
---|
6 | # http://paulschreiber.com/
|
---|
7 | # Released under a Creative Commons Attribution-Share Alike 3.0 United States License
|
---|
8 | # http://creativecommons.org/licenses/by-sa/3.0/us/
|
---|
9 | #
|
---|
10 |
|
---|
11 | from django import template
|
---|
12 | from django.template.defaultfilters import stringfilter
|
---|
13 |
|
---|
14 | register = template.Library()
|
---|
15 |
|
---|
16 | @register.filter(name='truncate_head')
|
---|
17 | def truncate_head(value, character_count, ellipsis=True):
|
---|
18 | if value == None:
|
---|
19 | return ""
|
---|
20 |
|
---|
21 | try:
|
---|
22 | length = int(character_count)
|
---|
23 | except ValueError: # Invalid literal for int().
|
---|
24 | return value # Fail silently.
|
---|
25 |
|
---|
26 | if len(value) < length:
|
---|
27 | return value
|
---|
28 |
|
---|
29 | # if we're already on a word boundary, done
|
---|
30 | if value[-(length+1)] == " ":
|
---|
31 | result = value[-length:].strip()
|
---|
32 | else:
|
---|
33 | original_length = len(value)
|
---|
34 | delta = (original_length-length)
|
---|
35 | first_space = value.find(" ", delta, original_length)
|
---|
36 |
|
---|
37 | if first_space == -1:
|
---|
38 | length = delta
|
---|
39 | elif first_space > length:
|
---|
40 | length = first_space
|
---|
41 |
|
---|
42 | result = value[length:].strip()
|
---|
43 |
|
---|
44 | if ellipsis:
|
---|
45 | return u"…" + result
|
---|
46 | else:
|
---|
47 | return result
|
---|
48 |
|
---|
49 | @register.filter(name='truncate_tail')
|
---|
50 | def truncate_tail(value, character_count, ellipsis=True):
|
---|
51 | if value == None:
|
---|
52 | return ""
|
---|
53 |
|
---|
54 | try:
|
---|
55 | length = int(character_count)
|
---|
56 | except ValueError: # Invalid literal for int().
|
---|
57 | return value # Fail silently.
|
---|
58 |
|
---|
59 | if len(value) < length:
|
---|
60 | return value
|
---|
61 |
|
---|
62 | # if we're already on a word boundary, done
|
---|
63 | if value[length] == " ":
|
---|
64 | result = value[:length].strip()
|
---|
65 | else:
|
---|
66 | last_space = value.rfind(" ", 0, length)
|
---|
67 | if last_space != -1 and last_space <= length:
|
---|
68 | length = last_space
|
---|
69 |
|
---|
70 | result = value[:length].strip()
|
---|
71 |
|
---|
72 | if ellipsis:
|
---|
73 | return result + u"…"
|
---|
74 | else:
|
---|
75 | return result
|
---|
76 |
|
---|
77 |
|
---|
78 | @register.filter(name='truncate_middle')
|
---|
79 | def truncate_middle(value, character_count):
|
---|
80 | if value == None:
|
---|
81 | return ""
|
---|
82 |
|
---|
83 | try:
|
---|
84 | length = int(character_count)
|
---|
85 | except ValueError: # Invalid literal for int().
|
---|
86 | return value # Fail silently.
|
---|
87 |
|
---|
88 | if len(value) < length:
|
---|
89 | return value
|
---|
90 |
|
---|
91 | half_size = length / 2
|
---|
92 | first_half = truncate_tail(value, half_size, False)
|
---|
93 | last_half = truncate_head(value, half_size, False)
|
---|
94 |
|
---|
95 | return u"%s…%s" % (first_half, last_half)
|
---|
96 |
|
---|
97 | @register.filter(name='truncatechars')
|
---|
98 | def truncatechars(value, character_count, truncate_type='tail'):
|
---|
99 | """
|
---|
100 | truncatechars(value, character_count, truncate_type='tail')
|
---|
101 |
|
---|
102 | Returns a copy of the string containg only character_counr characters. Try to break on word boundaries.
|
---|
103 |
|
---|
104 | Arguments: Number of characters to truncate after, truncation type (tail/head/middle).
|
---|
105 | """
|
---|
106 |
|
---|
107 | if truncate_type not in ["head", "tail", "middle"]:
|
---|
108 | raise ValueError
|
---|
109 |
|
---|
110 | if value == None:
|
---|
111 | return ""
|
---|
112 |
|
---|
113 | try:
|
---|
114 | length = int(character_count)
|
---|
115 | except ValueError: # Invalid literal for int().
|
---|
116 | return value # Fail silently.
|
---|
117 |
|
---|
118 | if len(value) < length:
|
---|
119 | return value
|
---|
120 |
|
---|
121 | if truncate_type == "tail":
|
---|
122 | return truncate_tail(value, character_count)
|
---|
123 |
|
---|
124 | elif truncate_type == "head":
|
---|
125 | return truncate_head(value, character_count)
|
---|
126 |
|
---|
127 | elif truncate_type == "middle":
|
---|
128 | return truncate_middle(value, character_count)
|
---|
129 |
|
---|
130 |
|
---|
131 | truncatechars.is_safe = True
|
---|
132 | truncate_head.is_safe = True
|
---|
133 | truncate_tail.is_safe = True
|
---|
134 | truncate_middle.is_safe = True
|
---|
135 |
|
---|