Found that django's urlize() does not deal well with adjacent parantheses. Replaced it with a filter based on bleach.linkify, which does better.
- Legacy-Id: 14752
This commit is contained in:
parent
1df3c715d0
commit
2c0348cc7a
|
@ -370,8 +370,9 @@ def format_history_text(text, trunc_words=25):
|
|||
def format_snippet(text, trunc_words=25):
|
||||
# urlize if there aren't already links present
|
||||
if not 'href=' in text:
|
||||
# django's urlize() is buggy in at least Django 1.11; use
|
||||
# bleach.linkify instead
|
||||
# django's urlize() cannot handle adjacent parentheszised
|
||||
# expressions, for instance [REF](http://example.com/foo)
|
||||
# Use bleach.linkify instead
|
||||
text = bleach.linkify(text)
|
||||
full = keep_spacing(collapsebr(linebreaksbr(mark_safe(sanitize_html(text)))))
|
||||
snippet = truncatewords_html(full, trunc_words)
|
||||
|
@ -520,3 +521,9 @@ def zaptmp(s):
|
|||
def rfcbis(s):
|
||||
m = re.search('^.*-rfc(\d+)-?bis(-.*)?$', s)
|
||||
return None if m is None else 'rfc' + m.group(1)
|
||||
|
||||
@register.filter
|
||||
@stringfilter
|
||||
def urlize(value):
|
||||
raise RuntimeError("Use linkify from textfilters instead of urlize")
|
||||
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import calendar
|
||||
import datetime
|
||||
import json
|
||||
import StringIO
|
||||
import bleach
|
||||
import six
|
||||
|
||||
from pyquery import PyQuery
|
||||
from tempfile import NamedTemporaryFile
|
||||
|
@ -17,7 +20,6 @@ from django.urls import NoReverseMatch
|
|||
from django.contrib.auth.models import User
|
||||
|
||||
from django.utils.html import escape
|
||||
from django.template.defaultfilters import urlize
|
||||
|
||||
from ietf.community.models import CommunityList
|
||||
from ietf.community.utils import reset_name_contains_index_for_rule
|
||||
|
@ -1273,7 +1275,7 @@ class StatusUpdateTests(TestCase):
|
|||
response = self.client.get(url)
|
||||
self.assertEqual(response.status_code,200)
|
||||
q=PyQuery(response.content)
|
||||
self.assertTrue(urlize(escape(event.desc) in q('pre')))
|
||||
self.assertTrue(bleach.linkify(escape(event.desc)) in six.text_type(q('pre')))
|
||||
self.assertFalse(q('a#edit_button'))
|
||||
self.client.login(username=chair.person.user.username,password='%s+password'%chair.person.user.username)
|
||||
response = self.client.get(url)
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
{% extends "base.html" %}
|
||||
{# Copyright The IETF Trust 2015, All Rights Reserved #}
|
||||
{% load origin %}
|
||||
|
||||
{% load bootstrap3 %}
|
||||
{% load textfilters %}
|
||||
|
||||
|
||||
{% block title %}
|
||||
Charter submission for {{ group.acronym }} {{ group.type.name }}
|
||||
|
@ -72,10 +73,10 @@
|
|||
<tbody class="meta">
|
||||
<tr>
|
||||
<th>Mailing list</th>
|
||||
<th>Address</th><td>{{ group.list_email|urlize }}</td>
|
||||
<th>Address</th><td>{{ group.list_email|linkify }}</td>
|
||||
</tr>
|
||||
<tr><td></td><th>To subscribe</th><td>{{ group.list_subscribe|urlize }}</td></tr>
|
||||
<tr><td></td><th>Archive</th><td>{{ group.list_archive|urlize }}</td></tr>
|
||||
<tr><td></td><th>To subscribe</th><td>{{ group.list_subscribe|linkify }}</td></tr>
|
||||
<tr><td></td><th>Archive</th><td>{{ group.list_archive|linkify }}</td></tr>
|
||||
</tbody>
|
||||
{% endif %}
|
||||
</table>
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
{# Copyright The IETF Trust 2015, All Rights Reserved #}{% load origin %}{% origin %}
|
||||
{% load ietf_filters %}
|
||||
{% load textfilters %}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-2 hidden-sm hidden-xs">
|
||||
|
||||
|
@ -91,7 +93,7 @@
|
|||
<div class="panel-heading">
|
||||
<h5 class="panel-title"><b>{{ p.pos.name }}</b> ({{ p.discuss_time|date:"Y-m-d" }}{% if not p.for_current_revision %} for -{{ p.get_dochistory.rev}}{% endif %})</h5>
|
||||
</div>
|
||||
<div class="panel-body"><pre class="ballot pasted">{{ p.discuss|escape|urlize }}</pre></div>
|
||||
<div class="panel-body"><pre class="ballot pasted">{{ p.discuss|escape|linkify }}</pre></div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
|
@ -100,7 +102,7 @@
|
|||
<div class="panel-heading">
|
||||
<h5 class="panel-title"><b>Comment</b> ({{ p.comment_time|date:"Y-m-d" }}{% if not p.for_current_revision %} for -{{ p.get_dochistory.rev}}{% endif %})</h5>
|
||||
</div>
|
||||
<div class="panel-body"><pre class="ballot pasted">{{ p.comment|escape|urlize }}</pre></div>
|
||||
<div class="panel-body"><pre class="ballot pasted">{{ p.comment|escape|linkify }}</pre></div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
{% load origin %}
|
||||
{% load staticfiles %}
|
||||
{% load ietf_filters %}
|
||||
{% load textfilters %}
|
||||
|
||||
{% block title %}{{ doc.title }}{% endblock %}
|
||||
|
||||
|
@ -54,6 +55,6 @@
|
|||
<h2>{{ doc.type.name }}<br><small>{{ doc.name }}</small></h2>
|
||||
|
||||
{% if doc.rev and content != None %}
|
||||
<pre class="pasted">{{ content|urlize|safe|sanitize_html|safe }}</pre>
|
||||
<pre class="pasted">{{ content|linkify|safe|sanitize_html|safe }}</pre>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
{% load origin %}
|
||||
|
||||
{% load ietf_filters %}
|
||||
{% load textfilters %}
|
||||
|
||||
{% block title %}Writeups for {{ doc.name }}-{{ doc.rev }}{% endblock %}
|
||||
|
||||
|
@ -20,7 +21,7 @@
|
|||
|
||||
{% for name, text, url in writeups %}
|
||||
{% if text %}
|
||||
<pre>{{ text|urlize }}</pre>
|
||||
<pre>{{ text|linkify }}</pre>
|
||||
{% endif %}
|
||||
|
||||
<p>
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
{% extends "base.html" %}
|
||||
{# Copyright The IETF Trust 2015, All Rights Reserved #}
|
||||
{% load origin %}
|
||||
|
||||
{% load ietf_filters staticfiles %}
|
||||
{% load textfilters %}
|
||||
|
||||
{% block pagehead %}
|
||||
{% if last_call_only %}
|
||||
|
@ -47,7 +47,7 @@
|
|||
<a href="{% url "ietf.doc.views_doc.document_main" doc.name %}">{{ doc.name }}</a>
|
||||
<br><b>{{ doc.title }}</b>
|
||||
{% if doc.note %}
|
||||
<br><i>Note: {{ doc.note|linebreaksbr|urlize }}</i>
|
||||
<br><i>Note: {{ doc.note|linebreaksbr|linkify }}</i>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ doc.intended_std_level.name }}</td>
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
{# Copyright The IETF Trust 2015, All Rights Reserved #}
|
||||
{% load origin %}
|
||||
{% load ietf_filters %}
|
||||
{% load textfilters %}
|
||||
|
||||
{% block title %}
|
||||
Shepherd writeup for {{ doc.canonical_name }}-{{ doc.rev }}
|
||||
|
@ -11,7 +12,7 @@
|
|||
{% origin %}
|
||||
<h1>Shepherd writeup<br><small>{{ doc.canonical_name }}-{{ doc.rev }}</small></h1>
|
||||
|
||||
<pre class="pasted">{{writeup|escape|urlize}}</pre>
|
||||
<pre class="pasted">{{writeup|escape|linkify}}</pre>
|
||||
|
||||
{% if can_edit %}
|
||||
<a class="btn btn-primary" href="{% url 'ietf.doc.views_draft.edit_shepherd_writeup' name=doc.name %}">Edit</a>
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
{% load staticfiles %}
|
||||
{% load bootstrap3 %}
|
||||
{% load ietf_filters %}
|
||||
{% load textfilters %}
|
||||
|
||||
|
||||
{% block title %}
|
||||
Status updates
|
||||
|
@ -27,7 +29,7 @@
|
|||
<span class="label label-success">{{ rpt.group.state.slug|upper }}</span>
|
||||
{% endif %}
|
||||
<br> {{rpt.time|date:"Y-m-d"}}</td>
|
||||
<td><pre class="pasted">{{ rpt.desc|default:"(none)"|escape|urlize }}</pre></td>
|
||||
<td><pre class="pasted">{{ rpt.desc|default:"(none)"|escape|linkify }}</pre></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
|
@ -42,7 +44,7 @@
|
|||
<span class="label label-success">{{ rpt.group.state.slug|upper }}</span>
|
||||
{% endif %}
|
||||
<br> {{rpt.time|date:"Y-m-d"}}</td>
|
||||
<td><pre class="pasted">{{ rpt.desc|default:"(none)"|escape|urlize }}</pre></td>
|
||||
<td><pre class="pasted">{{ rpt.desc|default:"(none)"|escape|linkify }}</pre></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
{% load origin %}
|
||||
{% load ietf_filters %}
|
||||
{% load markup_tags %}
|
||||
{% load textfilters %}
|
||||
|
||||
{% block group_content %}
|
||||
{% origin %}
|
||||
|
@ -176,7 +177,7 @@
|
|||
<a class="btn btn-default btn-xs" href="{% url 'ietf.group.views.edit' acronym=group.acronym field='list_email' %}">Edit</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ group.list_email|urlize }}</td>
|
||||
<td>{{ group.list_email|linkify }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
|
@ -186,7 +187,7 @@
|
|||
<a class="btn btn-default btn-xs" href="{% url 'ietf.group.views.edit' acronym=group.acronym field='list_subscribe' %}">Edit</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ group.list_subscribe|urlize }}</td>
|
||||
<td>{{ group.list_subscribe|linkify }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
|
@ -196,7 +197,7 @@
|
|||
<a class="btn btn-default btn-xs" href="{% url 'ietf.group.views.edit' acronym=group.acronym field='list_archive' %}">Edit</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ group.list_archive|urlize }}</td>
|
||||
<td>{{ group.list_archive|linkify }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
{% endif %}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
{% load staticfiles %}
|
||||
{% load bootstrap3 %}
|
||||
{% load ietf_filters %}
|
||||
{% load textfilters %}
|
||||
|
||||
{% block title %}
|
||||
Status update for {{ group.type.name }} {{ group.acronym }}
|
||||
|
@ -15,7 +16,7 @@
|
|||
Status update for {{ group.type.name }} {{ group.acronym }}
|
||||
</h1>
|
||||
|
||||
<pre class="pasted">{{ status_update.desc|default:"(none)"|escape|urlize }}</pre>
|
||||
<pre class="pasted">{{ status_update.desc|default:"(none)"|escape|linkify }}</pre>
|
||||
|
||||
{% if can_provide_status_update %}
|
||||
<a id="edit_button" class="btn btn-primary" href="{% url "ietf.group.views.group_about_status_edit" acronym=group.acronym %}">Edit</a>
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
{% load staticfiles %}
|
||||
{% load bootstrap3 %}
|
||||
{% load ietf_filters %}
|
||||
{% load textfilters %}
|
||||
|
||||
{% block title %}
|
||||
Status update for {{ group.type.name }} {{ group.acronym }} at {{meeting}}
|
||||
|
@ -15,7 +16,7 @@
|
|||
Status update for {{ group.type.name }} {{ group.acronym }} at {{meeting}}
|
||||
</h1>
|
||||
|
||||
<pre class="pasted">{{ status_update.desc|default:"(none)"|escape|urlize }}</pre>
|
||||
<pre class="pasted">{{ status_update.desc|default:"(none)"|escape|linkify }}</pre>
|
||||
|
||||
<a class="btn btn-default pull-right" href="{% url "ietf.meeting.views.proceedings" num=meeting.number %}">Back</a>
|
||||
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
from __future__ import unicode_literals
|
||||
|
||||
import bleach
|
||||
|
||||
from django import template
|
||||
from django.template.defaultfilters import stringfilter
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
import debug # pyflakes:ignore
|
||||
|
||||
|
@ -65,3 +68,9 @@ def texescape_filter(value):
|
|||
"A TeX escape filter"
|
||||
return texescape(value)
|
||||
|
||||
@register.filter
|
||||
@stringfilter
|
||||
def linkify(value):
|
||||
text = mark_safe(bleach.linkify(value))
|
||||
debug.show('text[:240]')
|
||||
return text
|
||||
|
|
Loading…
Reference in a new issue