99from ietf .doc .models import ConsensusDocEvent
1010from django import template
1111from django .utils .html import escape , fix_ampersands
12- from django .template .defaultfilters import truncatewords_html , linebreaksbr , stringfilter , urlize
12+ from django .template .defaultfilters import truncatewords_html , linebreaksbr , stringfilter , urlize , striptags
1313from django .template import resolve_variable
1414from django .utils .safestring import mark_safe , SafeData
1515from django .utils .html import strip_tags
@@ -48,12 +48,12 @@ def parse_email_list(value):
4848 u'<a href="mailto:joe@example.org">joe@example.org</a>, <a href="mailto:fred@example.com">fred@example.com</a>'
4949
5050 Parsing a non-string should return the input value, rather than fail:
51-
51+
5252 >>> parse_email_list(['joe@example.org', 'fred@example.com'])
5353 ['joe@example.org', 'fred@example.com']
54-
54+
5555 Null input values should pass through silently:
56-
56+
5757 >>> parse_email_list('')
5858 ''
5959
@@ -87,7 +87,7 @@ def fix_angle_quotes(value):
8787 if "<" in value :
8888 value = re .sub ("<([\w\-\.]+@[\w\-\.]+)>" , "<\1 >" , value )
8989 return value
90-
90+
9191# there's an "ahref -> a href" in GEN_UTIL
9292# but let's wait until we understand what that's for.
9393@register .filter (name = 'make_one_per_line' )
@@ -99,7 +99,7 @@ def make_one_per_line(value):
9999 'a\\ nb\\ nc'
100100
101101 Pass through non-strings:
102-
102+
103103 >>> make_one_per_line([1, 2])
104104 [1, 2]
105105
@@ -110,7 +110,7 @@ def make_one_per_line(value):
110110 return re .sub (", ?" , "\n " , value )
111111 else :
112112 return value
113-
113+
114114@register .filter (name = 'timesum' )
115115def timesum (value ):
116116 """
@@ -222,7 +222,7 @@ def rfclink(string):
222222 URL for that RFC.
223223 """
224224 string = str (string );
225- return "http: //tools.ietf.org/html/rfc" + string ;
225+ return "//tools.ietf.org/html/rfc" + string ;
226226
227227@register .filter (name = 'urlize_ietf_docs' , is_safe = True , needs_autoescape = True )
228228def urlize_ietf_docs (string , autoescape = None ):
@@ -274,7 +274,7 @@ def truncate_ellipsis(text, arg):
274274 return escape (text [:num - 1 ])+ "…"
275275 else :
276276 return escape (text )
277-
277+
278278@register .filter
279279def split (text , splitter = None ):
280280 return text .split (splitter )
@@ -375,7 +375,7 @@ def linebreaks_lf(text):
375375@register .filter (name = 'clean_whitespace' )
376376def clean_whitespace (text ):
377377 """
378- Map all ASCII control characters (0x00-0x1F) to spaces, and
378+ Map all ASCII control characters (0x00-0x1F) to spaces, and
379379 remove unnecessary spaces.
380380 """
381381 text = re .sub ("[\000 -\040 ]+" , " " , text )
@@ -384,7 +384,7 @@ def clean_whitespace(text):
384384@register .filter (name = 'unescape' )
385385def unescape (text ):
386386 """
387- Unescape />/<
387+ Unescape />/<
388388 """
389389 text = text .replace (">" , ">" )
390390 text = text .replace ("<" , "<" )
@@ -423,7 +423,7 @@ def has_role(user, role_names):
423423@register .filter
424424def stable_dictsort (value , arg ):
425425 """
426- Like dictsort, except it's stable (preserves the order of items
426+ Like dictsort, except it's stable (preserves the order of items
427427 whose sort key is the same). See also bug report
428428 http://code.djangoproject.com/ticket/12110
429429 """
@@ -448,10 +448,10 @@ def format_history_text(text):
448448 if text .startswith ("This was part of a ballot set with:" ):
449449 full = urlize_ietf_docs (full )
450450
451- full = mark_safe (keep_spacing (linebreaksbr (urlize (sanitize_html (full )))))
451+ full = mark_safe (keep_spacing (linebreaksbr (urlize_html (sanitize_html (full )))))
452452 snippet = truncatewords_html (full , 25 )
453453 if snippet != full :
454- return mark_safe (u'<div class="snippet">%s<span class="show-all">[show all] </span></div><div style="display:none" class="full">%s</div>' % (snippet , full ))
454+ return mark_safe (u'<div class="snippet">%s<button class="btn btn-xs btn-default show-all"><span class="fa fa-caret-down"> </span></button></ div><div class="hidden full">%s</div>' % (snippet , full ))
455455 return full
456456
457457@register .filter
@@ -512,3 +512,66 @@ def consensus(doc):
512512 else :
513513 return "Unknown"
514514
515+ # FACELIFT: The following filters are only used by the facelift UI:
516+
517+ @register .filter
518+ def pos_to_label (text ):
519+ """Return a valid Bootstrap3 label type for a ballot position."""
520+ return {
521+ 'Yes' : 'success' ,
522+ 'No Objection' : 'info' ,
523+ 'Abstain' : 'warning' ,
524+ 'Discuss' : 'danger' ,
525+ 'Block' : 'danger' ,
526+ 'Recuse' : 'default' ,
527+ }.get (str (text ), 'blank' )
528+
529+ @register .filter
530+ def capfirst_allcaps (text ):
531+ from django .template import defaultfilters
532+ """Like capfirst, except it doesn't lowercase words in ALL CAPS."""
533+ result = text
534+ i = False
535+ for token in re .split ("(\W+)" , striptags (text )):
536+ if not re .match ("^[A-Z]+$" , token ):
537+ if not i :
538+ result = result .replace (token , token .capitalize ())
539+ i = True
540+ else :
541+ result = result .replace (token , token .lower ())
542+ return result
543+
544+ @register .filter
545+ def lower_allcaps (text ):
546+ from django .template import defaultfilters
547+ """Like lower, except it doesn't lowercase words in ALL CAPS."""
548+ result = text
549+ i = False
550+ for token in re .split ("(\W+)" , striptags (text )):
551+ if not re .match ("^[A-Z]+$" , token ):
552+ result = result .replace (token , token .lower ())
553+ return result
554+
555+ # See https://djangosnippets.org/snippets/2072/ and
556+ # https://stackoverflow.com/questions/9939248/how-to-prevent-django-basic-inlines-from-autoescaping
557+ @register .filter
558+ def urlize_html (html , autoescape = False ):
559+ """
560+ Returns urls found in an (X)HTML text node element as urls via Django urlize filter.
561+ """
562+ try :
563+ from BeautifulSoup import BeautifulSoup
564+ from django .utils .html import urlize
565+ except ImportError :
566+ if settings .DEBUG :
567+ raise template .TemplateSyntaxError , "Error in urlize_html The Python BeautifulSoup libraries aren't installed."
568+ return html
569+ else :
570+ soup = BeautifulSoup (html )
571+
572+ textNodes = soup .findAll (text = True )
573+ for textNode in textNodes :
574+ urlizedText = urlize (textNode , autoescape = autoescape )
575+ textNode .replaceWith (BeautifulSoup (urlizedText ))
576+
577+ return str (soup )
0 commit comments