Eliminated several variations on word wrapping, keeping only what used to be wrap_text(), but renamed as ietf.utils.text.wordwrap(). This performs better than django.utils.text.wrap() when there are indented text parts. Replaced django's default wordwrap filter with one calling ietf.utils.text.wordwrap in templates. Changed to triggered wrapping in some cases, with the maybewordwrap filter, which triggers on lines longer than 100 characters. This fixes the issue with undesired wrapping of reviews.

- Legacy-Id: 13505
This commit is contained in:
Henrik Levkowetz 2017-06-02 23:13:22 +00:00
parent 16d129cacf
commit 5b2087f910
49 changed files with 137 additions and 409 deletions

View file

@ -6,11 +6,6 @@ import os
import types
from email.utils import parseaddr
import debug # pyflakes:ignore
from ietf.doc.models import ConsensusDocEvent
from ietf.doc.utils import get_document_content
from ietf.utils.text import fill
from django import template
from django.conf import settings
from django.utils.html import escape
@ -18,6 +13,13 @@ from django.template.defaultfilters import truncatewords_html, linebreaksbr, str
from django.utils.safestring import mark_safe, SafeData
from django.utils.html import strip_tags
import debug # pyflakes:ignore
from ietf.doc.models import ConsensusDocEvent
from ietf.doc.utils import get_document_content
from ietf.utils.text import wordwrap, fill, wrap_text_if_unwrapped
register = template.Library()
def collapsebr(html):
@ -254,64 +256,9 @@ def truncate_ellipsis(text, arg):
def split(text, splitter=None):
return text.split(splitter)
@register.filter(name="wrap_long_lines")
def wrap_long_lines(text, width=72):
"""Wraps long lines without loosing the formatting and indentation
of short lines"""
if not isinstance(text, (types.StringType,types.UnicodeType)):
return text
text = re.sub(" *\r\n", "\n", text) # get rid of DOS line endings
text = re.sub(" *\r", "\n", text) # get rid of MAC line endings
text = re.sub("( *\n){3,}", "\n\n", text) # get rid of excessive vertical whitespace
lines = text.split("\n")
filled = []
wrapped = False
for line in lines:
if wrapped and line.strip() != "":
line = filled[-1] + " " + line
filled = filled[:-1]
else:
wrapped = False
while (len(line) > 80) and (" " in line[:80]):
wrapped = True
breakpoint = line.rfind(" ",0,80)
filled += [ line[:breakpoint] ]
line = line[breakpoint+1:]
filled += [ line.rstrip() ]
return "\n".join(filled)
register.filter("maybewordwrap", stringfilter(wrap_text_if_unwrapped))
@register.filter(name="wrap_text")
def wrap_text(text, width=72):
"""Wraps long lines without loosing the formatting and indentation
of short lines"""
if not isinstance(text, (types.StringType,types.UnicodeType)):
return text
text = re.sub(" *\r\n", "\n", text) # get rid of DOS line endings
text = re.sub(" *\r", "\n", text) # get rid of MAC line endings
text = re.sub("( *\n){3,}", "\n\n", text) # get rid of excessive vertical whitespace
lines = text.split("\n")
filled = []
wrapped = False
prev_indent = None
for line in lines:
line = line.expandtabs()
indent = " " * (len(line) - len(line.lstrip()))
if wrapped and line.strip() != "" and indent == prev_indent:
line = filled[-1] + " " + line.lstrip()
filled = filled[:-1]
else:
wrapped = False
while (len(line) > width) and (" " in line[:width]):
linelength = len(line)
wrapped = True
breakpoint = line.rfind(" ",0,width)
filled += [ line[:breakpoint] ]
line = indent + line[breakpoint+1:]
if len(line) >= linelength:
break
filled += [ line.rstrip() ]
prev_indent = indent
return "\n".join(filled)
register.filter("wordwrap", stringfilter(wordwrap))
@register.filter(name="compress_empty_lines")
def compress_empty_lines(text):

View file

@ -4,11 +4,11 @@ import re
from django.utils.html import strip_tags
from django.utils.text import wrap
from django.conf import settings
from django.urls import reverse as urlreverse
from ietf.utils.mail import send_mail, send_mail_text
from ietf.utils.text import wordwrap
from ietf.mailtrigger.utils import gather_address_lists
def email_admin_re_charter(request, group, subject, text, mailtrigger):
@ -39,7 +39,7 @@ def email_milestones_changed(request, group, changes, states):
if re.search("Added .* for review, due",text):
subject = u"Review Required - " + subject
text = wrap(strip_tags(text), 70)
text = wordwrap(strip_tags(text), 78)
text += "\n\n"
text += u"URL: %s" % (settings.IDTRACKER_BASE_URL + group.about_url())

View file

@ -8,7 +8,7 @@ from django.utils.safestring import mark_safe
import debug # pyflakes:ignore
from ietf.doc.templatetags.ietf_filters import wrap_text
from ietf.utils.text import wordwrap
from ietf.nomcom.utils import get_nomcom_by_year, retrieve_nomcom_private_key
from ietf.person.models import Person
from ietf.utils.log import log
@ -71,4 +71,4 @@ def decrypt(string, request, year, plain=False):
if not plain:
return force_escape(linebreaksbr(out))
return mark_safe(wrap_text(force_escape(out)))
return mark_safe(wordwrap(force_escape(out)))

View file

@ -1,4 +1,4 @@
{% autoescape off %}{{ ad }} has entered the following ballot position for
{% load ietf_filters %}{% autoescape off %}{{ ad }} has entered the following ballot position for
{{ doc.name }}-{{ doc.rev }}: {{ pos.name }}
When responding, please keep the subject line intact and reply to all
@ -21,13 +21,13 @@ There are no remarks associated with this position.
{{ blocking_name }}:
----------------------------------------------------------------------
{{ discuss|safe|wordwrap:73 }}
{{ discuss|safe|maybewordwrap:80 }}
{% endif %}{% if comment %}----------------------------------------------------------------------
COMMENT:
----------------------------------------------------------------------
{{ comment|safe|wordwrap:73 }}
{{ comment|safe|maybewordwrap:80 }}
{% endif %}
{% endautoescape %}

View file

@ -42,7 +42,7 @@
<div class="form-group">
<label>Body</label>
<pre>{{ body|wrap_text }}</pre>
<pre>{{ body|maybewordwrap }}</pre>
</div>
{% buttons %}

View file

@ -3,6 +3,6 @@ To: {{ to }}{% if cc %}
Cc: {{ cc }} {% endif %}
Subject: {{ group.type.name }} Action: {{ action_type }} {{ group.name }} ({{ group.acronym }})
{% filter wordwrap:73 %}{% if action_type == "Formed" %}A new {% if group.type_id == "rg" %}IRTF{% else %}IETF{% endif %} {{ group.type.name }} has been formed in the {{ group.parent.name }}.{% endif %}{% if action_type == "Rechartered" %}The {{ group.name }} ({{ group.acronym }}) {{ group.type.name }} in the {{ group.parent.name }} of the {% if group.type_id == "rg" %}IRTF{% else %}IETF{% endif %} has been rechartered.{% endif %} For additional information, please contact the {% if group.type_id == "rg" %}IRTF Chair, the Internet Research Steering Group{% else %}Area Directors{% endif %} or the {{ group.type.name }} Chair{{ chairs|pluralize}}.
{% filter wordwrap:78 %}{% if action_type == "Formed" %}A new {% if group.type_id == "rg" %}IRTF{% else %}IETF{% endif %} {{ group.type.name }} has been formed in the {{ group.parent.name }}.{% endif %}{% if action_type == "Rechartered" %}The {{ group.name }} ({{ group.acronym }}) {{ group.type.name }} in the {{ group.parent.name }} of the {% if group.type_id == "rg" %}IRTF{% else %}IETF{% endif %} has been rechartered.{% endif %} For additional information, please contact the {% if group.type_id == "rg" %}IRTF Chair, the Internet Research Steering Group{% else %}Area Directors{% endif %} or the {{ group.type.name }} Chair{{ chairs|pluralize}}.
{% include "doc/charter/group_info.txt" %}{% endfilter %}{% endautoescape %}

View file

@ -1,4 +1,4 @@
{% load ietf_filters %}{% autoescape off %}{% filter wrap_long_lines %}{{ charter_text }}{% endfilter %}
{% load ietf_filters %}{% autoescape off %}{% filter maybewordwrap %}{{ charter_text }}{% endfilter %}
Milestones

View file

@ -1,10 +1,10 @@
{% autoescape off %}To: {{ to }} {% if cc %}
{% load ietf_filters %}{% autoescape off %}To: {{ to }} {% if cc %}
Cc: {{ cc }}
{% endif %}From: IESG Secretary <iesg-secretary@ietf.org>
Reply-To: IESG Secretary <iesg-secretary@ietf.org>
Subject: Evaluation: {{ doc.name }}
{% filter wordwrap:73 %}Evaluation for {{ doc.title }} can be found at {{ doc_url }}
{% filter wordwrap:78 %}Evaluation for {{ doc.title }} can be found at {{ doc_url }}
{% endfilter %}
{% endautoescape%}

View file

@ -3,6 +3,6 @@ To: {{ to }}{% if cc %}
Cc: {{ cc }} {% endif %}
Subject: {{ group.type.name }} Review: {{ group.name }} ({{ group.acronym }})
{% filter wordwrap:73 %}{% if review_type == "new" %}A new {% if group.type_id == "rg" %}IRTF{% else %}IETF{% endif %} {{ group.type.name }} has been proposed in the {{ group.parent.name }}.{% elif review_type == "recharter" %}The {{ group.name }} ({{group.acronym}}) {{ group.type.name }} in the {{ group.parent.name }} of the {% if group.type_id == "rg" %}IRTF{% else %}IETF{% endif %} is undergoing rechartering.{% endif %} The {% if group.type_id == "rg" %}IRSG{% else %}IESG{% endif %} has not made any determination yet. The following draft charter was submitted, and is provided for informational purposes only. Please send your comments to the {% if group.type_id == "rg" %}IRSG{% else %}IESG{% endif %} mailing list ({% if group.type_id == "rg" %}irsg@irtf.org{% else %}iesg@ietf.org{% endif %}) by {{ review_date }}.
{% filter wordwrap:78 %}{% if review_type == "new" %}A new {% if group.type_id == "rg" %}IRTF{% else %}IETF{% endif %} {{ group.type.name }} has been proposed in the {{ group.parent.name }}.{% elif review_type == "recharter" %}The {{ group.name }} ({{group.acronym}}) {{ group.type.name }} in the {{ group.parent.name }} of the {% if group.type_id == "rg" %}IRTF{% else %}IETF{% endif %} is undergoing rechartering.{% endif %} The {% if group.type_id == "rg" %}IRSG{% else %}IESG{% endif %} has not made any determination yet. The following draft charter was submitted, and is provided for informational purposes only. Please send your comments to the {% if group.type_id == "rg" %}IRSG{% else %}IESG{% endif %} mailing list ({% if group.type_id == "rg" %}irsg@irtf.org{% else %}iesg@ietf.org{% endif %}) by {{ review_date }}.
{% include "doc/charter/group_info.txt" %}{% endfilter %}{% endautoescape %}

View file

@ -1,9 +1,9 @@
{% load mail_filters %}{% autoescape off %}From: The IESG <iesg-secretary@ietf.org>
{% load ietf_filters %}{% load mail_filters %}{% autoescape off %}From: The IESG <iesg-secretary@ietf.org>
To: {{ to }}
Cc: {{ cc }}
Subject: Results of IETF-conflict review for {{conflictdoc.canonical_name}}-{{conflictdoc.rev}}
{% filter wordwrap:73 %}The IESG has completed a review of {{conflictdoc.canonical_name}}-{{conflictdoc.rev}} consistent with RFC5742.
{% filter wordwrap:78 %}The IESG has completed a review of {{conflictdoc.canonical_name}}-{{conflictdoc.rev}} consistent with RFC5742.
{% if review.get_state_slug == 'appr-reqnopub-pend' %}
The IESG recommends that '{{ conflictdoc.title }}' {{ conflictdoc.file_tag|safe }} NOT be published as {{ conflictdoc|std_level_prompt_with_article }}.

View file

@ -1,5 +1,5 @@
{% load mail_filters %}{% autoescape off %}
{% filter wordwrap:73 %}Secretary (Bcc'ed):
{% load ietf_filters %}{% load mail_filters %}{% autoescape off %}
{% filter wordwrap:78 %}Secretary (Bcc'ed):
{{ docname }} has been approved.

View file

@ -3,7 +3,7 @@ To: {{ to }}{% if cc %}
Cc: {{ cc }}{% endif %}
Subject: {{ action_type }} Action: '{{ doc.title|clean_whitespace }}' to {{ doc|std_level_prompt }} ({{ doc.filename_with_rev }})
{% filter wordwrap:73 %}The IESG has approved the following document{{ docs|pluralize }}:{% for d in docs %}
{% filter wordwrap:78 %}The IESG has approved the following document{{ docs|pluralize }}:{% for d in docs %}
- '{{ d.filled_title }}'
({{ d.filename_with_rev }}) as {{ d|std_level_prompt }}{% endfor %}

View file

@ -1,8 +1,8 @@
{% load mail_filters %}{% autoescape off %}From: The IESG <iesg-secretary@ietf.org>
{% load ietf_filters %}{% load mail_filters %}{% autoescape off %}From: The IESG <iesg-secretary@ietf.org>
To: {{to}}
Cc: {{cc}}
Subject: Results of IETF-conflict review for {{ doc.file_tag }}
{% filter wordwrap:73 %}
{% filter wordwrap:78 %}
The IESG has completed a review of <{{ doc.name }}> consistent with RFC5742. This review is applied to all non-IETF streams.
{% if disapproved %}
The IESG recommends that '{{ doc.title }}' {{ doc.file_tag|safe }} NOT be published as {{ doc|std_level_prompt_with_article }}.

View file

@ -1,4 +1,4 @@
{% autoescape off %}{% filter wordwrap:73 %}Ballot of {{ doc.file_tag }} has been {{action}} by {{ by }}.{% endfilter %}
{% load ietf_filters %}{% autoescape off %}{% filter wordwrap:78 %}Ballot of {{ doc.file_tag }} has been {{action}} by {{ by }}.{% endfilter %}
This ballot will be on the IESG agenda of {{ telechat_date }}.
{% endautoescape %}

View file

@ -42,7 +42,7 @@ IESG Note
IANA Note
{% if iana %}
{% load ietf_filters %}{% filter wordwrap:"68"|indent:2 %}{{ iana }}{% endfilter %}
{% load ietf_filters %}{% filter wordwrap:"76"|indent:2 %}{{ iana }}{% endfilter %}
{% endif %}
(Insert IANA Note here or remove section)
{% endautoescape%}

View file

@ -1,4 +1,4 @@
{% autoescape off %}{% filter wordwrap:73 %}
{% load ietf_filters %}{% autoescape off %}{% filter wordwrap:78 %}
{% if review_type == "new" %}A new {% if charter.group.type_id == "rg" %}IRTF{% else %}IETF{% endif %} {{ charter.group.type.name }} is being considered in the {% if charter.group.type_id == "rg" %}IRTF{% else %}IETF{% endif %}.{% elif review_type == "recharter" %}A new charter for the {{ charter.group.name }} ({{charter.group.acronym}}) {{ charter.group.type.name }} {% if charter.group.type_id == "rg" %}IRTF{% else %}in the {{ charter.group.parent }} of the IETF{% endif %} is being considered. {% endif %} The draft charter for this {{ charter.group.type.name }} is provided below for your review and comment.
{% if charter.group.type_id != "rg" %}
@ -6,4 +6,4 @@ Review time is one week.
{% endif %}
The IETF Secretariat
{% include "doc/charter/group_info.txt" with group=charter.group%}{% endfilter %}{% endautoescape %}
{% include "doc/charter/group_info.txt" with group=charter.group%}{% endfilter %}{% endautoescape %}

View file

@ -1,4 +1,4 @@
{% autoescape off %}{% filter wordwrap:73 %}
{% load ietf_filters %}{% autoescape off %}{% filter wordwrap:78 %}
The {{ doc.group.acronym|upper }} {{ doc.group.type_id|upper }} has placed {{ doc }} in state
{{ new_state|default:'"None"'}} (entered by {{by}})

View file

@ -1,12 +1,12 @@
{% load mail_filters %}{% autoescape off %}From: IESG Secretary <iesg-secretary@ietf.org>
{% load ietf_filters %}{% load mail_filters %}{% autoescape off %}From: IESG Secretary <iesg-secretary@ietf.org>
Reply-To: IESG Secretary <iesg-secretary@ietf.org>
Subject: Evaluation: {{ doc.file_tag }} to {{ doc|std_level_prompt }}
{% filter wordwrap:73 %}Evaluation for {{ doc.file_tag }} can be found at {{ doc_url }}
{% filter wordwrap:78 %}Evaluation for {{ doc.file_tag }} can be found at {{ doc_url }}
{% if last_call_expires %}Last call to expire on: {{ last_call_expires }}
{% endif %}{% endfilter %}
{% filter wordwrap:73 %}{{ needed_ballot_positions }}{% endfilter %}
{% filter wordwrap:78 %}{{ needed_ballot_positions }}{% endfilter %}
{% endautoescape%}

View file

@ -5,7 +5,7 @@ Reply-To: ietf@ietf.org
Sender: <iesg-secretary@ietf.org>
Subject: Last Call: {{ doc.file_tag }} ({{ doc.title|clean_whitespace }}) to {{ doc|std_level_prompt }}
{% filter wordwrap:73 %}
{% filter wordwrap:78 %}
The IESG has received a request from {{ group }} to consider the following document{{ docs|pluralize }}:{% for d in docs %}
- '{{ d.filled_title }}'
{{ d.file_tag }} as {{ d|std_level_prompt }}{% endfor %}

View file

@ -1,4 +1,4 @@
{% load mail_filters %}{% autoescape off %}{% filter wordwrap:73 %}
{% load ietf_filters %}{% load mail_filters %}{% autoescape off %}{% filter wordwrap:78 %}
The {{ approving_body }} has approved the following document in the {{ doc.stream }} stream:
- "{{ doc.title }}" ({{ doc.name }}) as {{ doc|std_level_prompt }}.{% if group_description %}
@ -7,7 +7,7 @@ This document is the product of the {{ group_description }}.{% endif %}{% endfil
URL: {{ doc_url }}
{% filter wordwrap:73 %} {% if not doc.stream_id == 'ise' %}{% if consensus != None %}The document {% if consensus %}represents{% else %}does not necessarily represent{% endif %} the consensus of the {{ consensus_body }}.
{% filter wordwrap:78 %} {% if not doc.stream_id == 'ise' %}{% if consensus != None %}The document {% if consensus %}represents{% else %}does not necessarily represent{% endif %} the consensus of the {{ consensus_body }}.
{% endif %}{% endif %}No IANA allocation in the document requires IETF Consensus or Standards Action.{% endfilter %}
@ -18,5 +18,5 @@ URL: {{ doc_url }}
[OPTIONAL: Include suggested names and contact information for one or more competent and independent potential reviewers for the document (this can speed the review and approval process).]
{% if doc.has_rfc_editor_note %}{% filter wordwrap:73 %}{{ rfc_editor_note }}{% endfilter %}{% endif %}
{% if doc.has_rfc_editor_note %}{% filter wordwrap:78 %}{{ rfc_editor_note }}{% endfilter %}{% endif %}
{% endautoescape %}

View file

@ -1,4 +1,4 @@
{% autoescape off %}{% filter wordwrap:73 %}
{% load ietf_filters %}{% autoescape off %}{% filter wordwrap:78 %}
The {{ state_type.label }} of {{ doc }} has been changed to "{{ new_state.name }}"{% if prev_state %} from "{{ prev_state.name }}"{% endif %} by {{ by }}:
{{ url }}

View file

@ -1,4 +1,4 @@
{% autoescape off %}{% filter wordwrap:73 %}
{% load ietf_filters %}{% autoescape off %}{% filter wordwrap:78 %}
The tags on {{ doc }} have been changed by {{ by }}:
{{ url }}

View file

@ -1,9 +1,9 @@
{% load mail_filters %}{% autoescape off %}From: The IESG <iesg-secretary@ietf.org>
{% load ietf_filters %}{% load mail_filters %}{% autoescape off %}From: The IESG <iesg-secretary@ietf.org>
To: {{ to }}{% if cc %}
Cc: {{ cc }}{% endif %}
Subject: {{action}}: {{relateddoc.target.document.title}} to {{newstatus}}
{% filter wordwrap:73 %}The IESG has approved changing the status of the following document:
{% filter wordwrap:78 %}The IESG has approved changing the status of the following document:
- {{relateddoc.target.document.title }}
({{relateddoc.target.document.canonical_name }}) to {{ newstatus }}

View file

@ -5,7 +5,7 @@ Reply-To: ietf@ietf.org
Sender: <iesg-secretary@ietf.org>
Subject: Last Call: {{ doc.title|clean_whitespace }}
{% filter wordwrap:73 %}
{% filter wordwrap:78 %}
The IESG has received a request from {{ requester }} to make the following status changes:
{%for change in changes %}
- {{ change }}

View file

@ -11,7 +11,7 @@ post date.{% endif %} Generated {{ time }}.
{% for group in groups %}
{% filter underline %}{{ group.name }} ({{ group.acronym }}){% endfilter %}
{% for d in group.active_drafts %}
{% filter wordwrap:72|indent:2 %}"{{ d.title|clean_whitespace }}", {% for a in d.authors %}{{ a.strip }}, {% endfor %}{{ d.rev_time|date:"Y-m-d"}}, <{{ d.name }}-{{ d.rev }}{{ d.exts }}>
{% filter wordwrap:76|indent:2 %}"{{ d.title|clean_whitespace }}", {% for a in d.authors %}{{ a.strip }}, {% endfor %}{{ d.rev_time|date:"Y-m-d"}}, <{{ d.name }}-{{ d.rev }}{{ d.exts }}>
{% endfilter %}{% if with_abstracts %}
{{ d.abstract.strip|unindent|fill:72|indent:6 }}
{% endif %}{% endfor %}{% endfor %}{% endautoescape %}

View file

@ -117,7 +117,7 @@
{% endif %}
{% if num|startswith:"6." and user|has_role:"Area Director,IAB Chair,Secretariat" %}
<pre>{{ section.text|wordwrap:"76" }}</pre>
<pre>{{ section.text|wordwrap:"80" }}</pre>
{% endif %}
{% endfor %}

View file

@ -71,13 +71,13 @@ Some parts Copyright (c) 2009 The IETF Trust, all rights reserved.
{% if p.pos and p.discuss %}
<li>
<a name="{{ doc.name }}+{{ p.ad.plain_name|slugify }}+discuss">{{ p.ad.plain_name }}: Discuss [{{ p.discuss_time }}]</a>:
<br><pre>{{ p.discuss|wrap_text:80 }}</pre>
<br><pre>{{ p.discuss|wordwrap:80 }}</pre>
</li>
{% endif %}
{% if p.pos and p.comment %}
<li>
<a name="{{ doc.name }}+{{ p.ad.plain_name|slugify }}+comment">{{ p.ad.plain_name }}: Comment [{{ p.comment_time }}]</a>:
<br><pre>{{ p.comment|wrap_text:80 }}</pre>
<br><pre>{{ p.comment|wordwrap:80 }}</pre>
</li>
{% endif %}{% endfor %}
</ul>

View file

@ -24,8 +24,8 @@ specification, is as follows(select one licensing declaration option only):
None selected.
{% endif %}
{% if extra %}{{ extra|safe|wordwrap:80|indent }}
{% if extra %}{{ extra|safe|wordwrap:76|indent }}
{% endif %}Licensing information, comments, notes or URL for further information:
{{ info|safe|wordwrap:80|indent }}
{{ info|safe|wordwrap:76|indent }}

View file

@ -5,7 +5,7 @@ Cc: {{ cc_email }}
Dear {{ to_name }}:
{% filter wordwrap:80 %}
{% filter wordwrap:78 %}
An IPR disclosure that pertains to your {{ doc_info }} was submitted to the IETF Secretariat on {{ ipr.submitted_date|date:"Y-m-d" }} and has been posted on the "IETF Page of Intellectual Property Rights Disclosures" (https://datatracker.ietf.org/ipr/{{ ipr.pk }}/). The title of the IPR disclosure is "{{ ipr.title }}"
{% endfilter %}

View file

@ -180,7 +180,7 @@
<tr>
<th class="text-nowrap">Body</th>
<td>
<pre>{{ liaison.body|wordwrap:"78" }}</pre>
<pre>{{ liaison.body|maybewordwrap:"80" }}</pre>
</td>
</tr>
{% endif %}

View file

@ -1,5 +1,5 @@
{# Copyright The IETF Trust 2015, All Rights Reserved #}{% load origin %}{% origin %}
{{ obj.body|truncatewords:"30"|wordwrap:"71"|linebreaksbr }}
{{ obj.body|truncatewords:"30"|wordwrap:"80"|linebreaksbr }}
<h3>Attached Document{{ attachments|pluralize }}</h3>
{% if attachments %}
<ul>

View file

@ -2,7 +2,7 @@
{% filter center:72 %} Agenda of the {{ schedule.meeting.number|ordinal }} IETF Meeting {% endfilter %}
{% if schedule.meeting.agenda_note %}
{% filter center:72 %}{{ schedule.meeting.agenda_note|striptags|wrap_text:72|safe }}{% endfilter %}
{% filter center:72 %}{{ schedule.meeting.agenda_note|striptags|wordwrap:72|safe }}{% endfilter %}
{% endif %}
{% filter center:72 %}{{ schedule.meeting.date|date:"F j" }}-{% if schedule.meeting.date.month != schedule.meeting.end_date.month %}{{ schedule.meeting.end_date|date:"F " }}{% endif %}{{ schedule.meeting.end_date|date:"j, Y" }}{% endfilter %}
{% filter center:72 %}Updated {{ updated|date:"Y-m-d H:i:s T" }}{% endfilter %}

View file

@ -2,7 +2,7 @@
{% filter center:72 %} Agenda of the {{ meeting.number|ordinal }} IETF Meeting {% endfilter %}
{% if meeting.agenda_note %}
{% filter center:72 %}{{ meeting.agenda_note|striptags|wrap_text:72|safe }}{% endfilter %}
{% filter center:72 %}{{ meeting.agenda_note|striptags|wordwrap:72|safe }}{% endfilter %}
{% endif %}
{% filter center:72 %}{{ meeting.date|date:"F j" }}-{% if meeting.date.month != meeting.end_date.month %}{{ meeting.end_date|date:"F " }}{% endif %}{{ meeting.end_date|date:"j, Y" }}{% endfilter %}

View file

@ -13,7 +13,7 @@
{% if nomcom.group.state_id == 'active' %}
<p>The message that will be sent is as follows:</p>
<pre>{{ mail_template.content|wrap_text:80 }}</pre>
<pre>{{ mail_template.content|wordwrap:80 }}</pre>
{% if mail_template %}
<p>

View file

@ -1,7 +1,7 @@
{% autoescape off %}
{% autoescape off %}{% load ietf_filters %}
Hello,
{% filter wordwrap:73 %}We have received a request to add the email address {{ email }} to the user account '{{ person.user }}' at {{ domain }}. If you requested this change, please confirm that this is your email address by clicking on following link:{% endfilter %}
{% filter wordwrap:78 %}We have received a request to add the email address {{ email }} to the user account '{{ person.user }}' at {{ domain }}. If you requested this change, please confirm that this is your email address by clicking on following link:{% endfilter %}
https://{{ domain }}{% url "ietf.ietfauth.views.confirm_new_email" auth %}

View file

@ -1,7 +1,7 @@
{% autoescape off %}
{% autoescape off %}{% load ietf_filters %}
Hello,
{% filter wordwrap:73 %}We have received an account creation request for {{ username }} at {{ domain }}. In order to set a new password for the {{ username }} account, please go to the following link and follow the instructions there:{% endfilter %}
{% filter wordwrap:78 %}We have received an account creation request for {{ username }} at {{ domain }}. In order to set a new password for the {{ username }} account, please go to the following link and follow the instructions there:{% endfilter %}
https://{{ domain }}{% url "ietf.ietfauth.views.confirm_account" auth %}

View file

@ -1,7 +1,7 @@
{% autoescape off %}
{% autoescape off %}{% load ietf_filters %}
Hello,
{% filter wordwrap:73 %}The password for your datatracker account was just changed using the password change form. If this was not done by you, please contact the secretariat at ietf-action@ietf.org for assistance.{% endfilter %}
{% filter wordwrap:78 %}The password for your datatracker account was just changed using the password change form. If this was not done by you, please contact the secretariat at ietf-action@ietf.org for assistance.{% endfilter %}
Best regards,

View file

@ -1,7 +1,7 @@
{% autoescape off %}
{% autoescape off %}{% load ietf_filters %}
Hello,
{% filter wordwrap:73 %}We have received a password reset request for {{ username }} at {{ domain }}. In order to set a new password for the {{ username }} account, please go to the following link and follow the instructions there:{% endfilter %}
{% filter wordwrap:78 %}We have received a password reset request for {{ username }} at {{ domain }}. In order to set a new password for the {{ username }} account, please go to the following link and follow the instructions there:{% endfilter %}
https://{{ domain }}{% url "ietf.ietfauth.views.confirm_password_reset" auth %}

View file

@ -1,7 +1,7 @@
{% autoescape off %}
{% autoescape off %}{% load ietf_filters %}
Hello,
{% filter wordwrap:73 %}The username (login name) for your datatracker account was just changed using the username change form. If this was not done by you, please contact the secretariat at ietf-action@ietf.org for assistance.{% endfilter %}
{% filter wordwrap:78 %}The username (login name) for your datatracker account was just changed using the username change form. If this was not done by you, please contact the secretariat at ietf-action@ietf.org for assistance.{% endfilter %}
Best regards,

View file

@ -1,4 +1,6 @@
{% autoescape off %}{% filter wordwrap:70 %}{% if review_req.state_id == "part-completed" %}Review is partially done. Another review request has been registered for completing it.
{% load ietf_filters %}{% autoescape off %}{% filter maybewordwrap:80 %}{% if review_req.state_id == "part-completed" %}
Review is partially done. Another review request has been registered for
completing it.
{% endif %}Reviewer: {{ review_req.reviewer.person }}
Review result: {{ review_req.result.name }}

View file

@ -1,10 +1,10 @@
{% autoescape off %}
{% load ietf_filters %}{% autoescape off %}
{{ review_req.type.name }} review of: {{ review_req.doc.name }} ({% if review_req.requested_rev %}rev. {{ review_req.requested_rev }}{% else %}no specific version{% endif %})
Deadline: {{ review_req.deadline|date:"Y-m-d" }}{% if review_req.requested_by %}
Requested by: {{ review_req.requested_by.plain_name }}{% endif %}
{{ review_req_url }}
{{ msg|wordwrap:72 }}
{{ msg|maybewordwrap:78 }}
{% endautoescape %}

View file

@ -1,4 +1,4 @@
{% autoescape off %}{% filter wordwrap:72 %}
{% load ietf_filters %}{% autoescape off %}{% filter wordwrap:78 %}
Reviewer availability of {{ reviewer }} in {{ team.acronym }} changed by {{ by }}.
{{ msg }}

View file

@ -1,4 +1,4 @@
{% autoescape off %}{% filter wordwrap:70 %}This is just a friendly reminder that the deadline for the review of {{ review_request.doc_id }} is in {{ deadline_days }} day{{ deadline_days|pluralize }}:
{% load ietf_filters %}{% autoescape off %}{% filter wordwrap:78 %}This is just a friendly reminder that the deadline for the review of {{ review_request.doc_id }} is in {{ deadline_days }} day{{ deadline_days|pluralize }}:
{{ review_request_url }}

View file

@ -1,4 +1,4 @@
{% autoescape off %}{% filter wordwrap:70 %}This is just a friendly reminder that the deadline for the review of {{ review_request.doc_id }} is in {{ deadline_days }} day{{ deadline_days|pluralize }}:
{% load ietf_filters %}{% autoescape off %}{% filter wordwrap:78 %}This is just a friendly reminder that the deadline for the review of {{ review_request.doc_id }} is in {{ deadline_days }} day{{ deadline_days|pluralize }}:
{{ review_request_url }}

View file

@ -1,11 +1,11 @@
{% autoescape off %}
{% load ietf_filters %}{% autoescape off %}
This is an automated report of current Datatracker sync discrepancies,
also available at:
{{ url }}
{% for title, docs in sections %}
{{ title|wordwrap:73 }}
{{ title|wordwrap:78 }}
{% if docs %}{% for d in docs %}
{{ d.name }}
IESG: {{ d.iesg_state|default:"-" }}

View file

@ -1,4 +1,4 @@
{% filter wordwrap:73 %}
{% load ietf_filters %}{% filter wordwrap:78 %}
We will soon be changing the header fields used in IETF Last Call messages sent to the IETF Announce mailing list.
This message is to to inform you of the change and allow you to test that you are properly receiving messages using the new header fields.

View file

@ -1,4 +1,4 @@
{% filter wordwrap:73 %}
{% load ietf_filters %}{% filter wordwrap:78 %}
Dear {{ person.plain_name }},
We have noticed that there are two records in the IETF Datatracker for a person named "{{ person.plain_name }}". These records have been merged.

View file

@ -34,7 +34,7 @@ from django.utils.html import escape
import string
import re
from ietf.utils.text import fill
from ietf.utils.text import wordwrap
def markup(content, split=True, width=None):
# normalize line endings to LF only
@ -55,9 +55,9 @@ def markup(content, split=True, width=None):
# remove runs of blank lines
content = re.sub("\n\n\n+", "\n\n", content)
# maybe fill. This must be done before the escaping below.
# maybe wordwrap. This must be done before the escaping below.
if width:
content = fill(content, width)
content = wordwrap(content, width)
# expand tabs + escape
content = escape(content.expandtabs())
@ -88,9 +88,9 @@ def markup_unicode(content, split=True, width=None, container_classes=None):
# remove runs of blank lines
content = re.sub("\n\n\n+", "\n\n", content)
# maybe fill. This must be done before the escaping below.
# maybe wordwrap. This must be done before the escaping below.
if width:
content = fill(content, width)
content = wordwrap(content, width)
# expand tabs + escape
content_to_show = escape(content.expandtabs())

View file

@ -1,267 +1,15 @@
"""
We have a plethora of different wrapping functions in use, and probably should
reduce the number. In some cases, we should not wrap at all, instead letting
the browser wrap, using for instance this css:
.pasted {
white-space: pre-wrap;
word-break: keep-all;
}
In order to get a grasp of what we have got, and how the different variations
behave, here are some doctests to verify the output of each function, and
a __main__ which will print all the examples if this file is run as
$ python ietf/utils/text.py
This is the input text, with long lines in all 4 paragraphs. 2 Paragraphs are
indented:
>>> text = '''
... Lorem ipsum dolor sit amet, consectetur adipiscing elit.
... Aliquam euismod semper hendrerit. Morbi fringilla semper
... libero, eu auctor mauris ullamcorper et. Phasellus quis dolor in nibh pretium cursus et molestie lacus. Morbi ut
... magna mauris. Sed feugiat maximus finibus. Nullam dapibus
... aliquam nibh sed varius. Curabitur elit nunc, lacinia
... gravida lectus non, interdum porttitor magna.
...
... Sed suscipit, libero vel ullamcorper malesuada, enim odio vestibulum quam,
... nec luctus ligula diam eget sapien. Proin a lectus at eros ullamcorper
... mollis. Aenean vehicula lacinia arcu, sed auctor mi cursus ut.
...
...
... Pellentesque porta felis nec odio tincidunt pellentesque luctus in massa. Duis lacus augue, facilisis eu congue eu, ultricies eget urna. In id risus
... vestibulum, suscipit lorem sit amet, tempus libero.
...
... Etiam a purus pretium, mollis elit at, iaculis odio. Donec imperdiet lacinia odio at ultrices. Duis hendrerit consequat augue ac efficitur. Etiam vel placerat arcu. Aenean sodales lorem ut auctor rutrum. Vestibulum auctor fringilla felis ac tempor. Nullam tincidunt pellentesque sapien, non facilisis lectus sagittis ac. Vivamus tempus nibh a laoreet hendrerit. Suspendisse tempor neque erat, quis commodo ex aliquam ut. Duis egestas dignissim risus, non semper lectus commodo non.
...
... '''
Some preliminary setup for the tests ...
>>> import os
>>> os.environ["DJANGO_SETTINGS_MODULE"] = "ietf.settings"
>>> import django
>>> django.setup()
>>>
>>> from ietf.doc.templatetags.ietf_filters import wrap_text, wrap_long_lines
>>> from django.utils.text import wrap as django_wrap
>>> from ietf.utils.text import fill, wrap, wrap_text_if_unwrapped
>>>
The first two tests here give reasonable results. The difference lies in
how they deal with remaining lines in a paragraph where there's been a
too long line:
>>> # ----------------------------------------------------------------------
>>> print(wrap_text(text, width=80))
<BLANKLINE>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Aliquam euismod semper hendrerit. Morbi fringilla semper
libero, eu auctor mauris ullamcorper et. Phasellus quis dolor in nibh pretium
cursus et molestie lacus. Morbi ut magna mauris. Sed feugiat maximus finibus.
Nullam dapibus aliquam nibh sed varius. Curabitur elit nunc, lacinia gravida
lectus non, interdum porttitor magna.
<BLANKLINE>
Sed suscipit, libero vel ullamcorper malesuada, enim odio vestibulum quam,
nec luctus ligula diam eget sapien. Proin a lectus at eros ullamcorper
mollis. Aenean vehicula lacinia arcu, sed auctor mi cursus ut.
<BLANKLINE>
Pellentesque porta felis nec odio tincidunt pellentesque luctus in massa.
Duis lacus augue, facilisis eu congue eu, ultricies eget urna. In id risus
vestibulum, suscipit lorem sit amet, tempus libero.
<BLANKLINE>
Etiam a purus pretium, mollis elit at, iaculis odio. Donec imperdiet lacinia
odio at ultrices. Duis hendrerit consequat augue ac efficitur. Etiam vel
placerat arcu. Aenean sodales lorem ut auctor rutrum. Vestibulum auctor
fringilla felis ac tempor. Nullam tincidunt pellentesque sapien, non facilisis
lectus sagittis ac. Vivamus tempus nibh a laoreet hendrerit. Suspendisse tempor
neque erat, quis commodo ex aliquam ut. Duis egestas dignissim risus, non
semper lectus commodo non.
<BLANKLINE>
<BLANKLINE>
>>> # ----------------------------------------------------------------------
>>> # ----------------------------------------------------------------------
>>> print(wrap(text, width=80))
<BLANKLINE>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Aliquam euismod semper hendrerit. Morbi fringilla semper
libero, eu auctor mauris ullamcorper et. Phasellus quis dolor in nibh pretium
cursus et molestie lacus. Morbi ut
magna mauris. Sed feugiat maximus finibus. Nullam dapibus
aliquam nibh sed varius. Curabitur elit nunc, lacinia
gravida lectus non, interdum porttitor magna.
<BLANKLINE>
Sed suscipit, libero vel ullamcorper malesuada, enim odio vestibulum quam,
nec luctus ligula diam eget sapien. Proin a lectus at eros ullamcorper
mollis. Aenean vehicula lacinia arcu, sed auctor mi cursus ut.
<BLANKLINE>
<BLANKLINE>
Pellentesque porta felis nec odio tincidunt pellentesque luctus in massa.
Duis lacus augue, facilisis eu congue eu, ultricies eget urna. In id risus
vestibulum, suscipit lorem sit amet, tempus libero.
<BLANKLINE>
Etiam a purus pretium, mollis elit at, iaculis odio. Donec imperdiet lacinia
odio at ultrices. Duis hendrerit consequat augue ac efficitur. Etiam vel
placerat arcu. Aenean sodales lorem ut auctor rutrum. Vestibulum auctor
fringilla felis ac tempor. Nullam tincidunt pellentesque sapien, non facilisis
lectus sagittis ac. Vivamus tempus nibh a laoreet hendrerit. Suspendisse tempor
neque erat, quis commodo ex aliquam ut. Duis egestas dignissim risus, non semper
lectus commodo non.
<BLANKLINE>
<BLANKLINE>
>>> # ----------------------------------------------------------------------
In the next few functions, things start to go more or less awry:
>>> # ----------------------------------------------------------------------
>>> print(wrap_long_lines(text, width=80))
<BLANKLINE>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Aliquam euismod semper hendrerit. Morbi fringilla semper
libero, eu auctor mauris ullamcorper et. Phasellus quis dolor in nibh pretium
cursus et molestie lacus. Morbi ut magna mauris. Sed feugiat maximus finibus.
Nullam dapibus aliquam nibh sed varius. Curabitur elit nunc, lacinia gravida
lectus non, interdum porttitor magna.
<BLANKLINE>
Sed suscipit, libero vel ullamcorper malesuada, enim odio vestibulum quam,
nec luctus ligula diam eget sapien. Proin a lectus at eros ullamcorper
mollis. Aenean vehicula lacinia arcu, sed auctor mi cursus ut.
<BLANKLINE>
Pellentesque porta felis nec odio tincidunt pellentesque luctus in massa.
Duis lacus augue, facilisis eu congue eu, ultricies eget urna. In id risus
vestibulum, suscipit lorem sit amet, tempus libero.
<BLANKLINE>
Etiam a purus pretium, mollis elit at, iaculis odio. Donec imperdiet lacinia
odio at ultrices. Duis hendrerit consequat augue ac efficitur. Etiam vel
placerat arcu. Aenean sodales lorem ut auctor rutrum. Vestibulum auctor
fringilla felis ac tempor. Nullam tincidunt pellentesque sapien, non facilisis
lectus sagittis ac. Vivamus tempus nibh a laoreet hendrerit. Suspendisse tempor
neque erat, quis commodo ex aliquam ut. Duis egestas dignissim risus, non
semper lectus commodo non.
<BLANKLINE>
<BLANKLINE>
>>> # ----------------------------------------------------------------------
>>> # ----------------------------------------------------------------------
>>> print(fill(text, width=80))
<BLANKLINE>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Aliquam euismod semper
hendrerit. Morbi fringilla semper
libero, eu auctor mauris ullamcorper et.
Phasellus quis dolor in nibh pretium cursus et molestie lacus. Morbi ut
magna
mauris. Sed feugiat maximus finibus. Nullam dapibus
aliquam nibh sed varius.
Curabitur elit nunc, lacinia
gravida lectus non, interdum porttitor magna.
<BLANKLINE>
Sed suscipit, libero vel ullamcorper malesuada, enim odio vestibulum quam,
nec luctus ligula diam eget sapien. Proin a lectus at eros ullamcorper
mollis. Aenean vehicula lacinia arcu, sed auctor mi cursus ut.
<BLANKLINE>
<BLANKLINE>
Pellentesque porta felis nec odio tincidunt pellentesque luctus in
massa. Duis lacus augue, facilisis eu congue eu, ultricies eget urna. In id
risus
vestibulum, suscipit lorem sit amet, tempus libero.
<BLANKLINE>
Etiam a purus pretium, mollis elit at, iaculis odio. Donec imperdiet lacinia
odio at ultrices. Duis hendrerit consequat augue ac efficitur. Etiam vel
placerat arcu. Aenean sodales lorem ut auctor rutrum. Vestibulum auctor
fringilla felis ac tempor. Nullam tincidunt pellentesque sapien, non facilisis
lectus sagittis ac. Vivamus tempus nibh a laoreet hendrerit. Suspendisse tempor
neque erat, quis commodo ex aliquam ut. Duis egestas dignissim risus, non semper
lectus commodo non.
>>> # ----------------------------------------------------------------------
>>> # ----------------------------------------------------------------------
>>> print(django_wrap(text, width=80))
<BLANKLINE>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Aliquam euismod semper hendrerit. Morbi fringilla semper
libero, eu auctor mauris ullamcorper et. Phasellus quis dolor in nibh pretium
cursus et molestie lacus. Morbi ut
magna mauris. Sed feugiat maximus finibus. Nullam dapibus
aliquam nibh sed varius. Curabitur elit nunc, lacinia
gravida lectus non, interdum porttitor magna.
<BLANKLINE>
Sed suscipit, libero vel ullamcorper malesuada, enim odio vestibulum quam,
nec luctus ligula diam eget sapien. Proin a lectus at eros ullamcorper
mollis. Aenean vehicula lacinia arcu, sed auctor mi cursus ut.
<BLANKLINE>
<BLANKLINE>
Pellentesque porta felis nec odio tincidunt pellentesque luctus in massa.
Duis lacus augue, facilisis eu congue eu, ultricies eget urna. In id risus
vestibulum, suscipit lorem sit amet, tempus libero.
<BLANKLINE>
Etiam a purus pretium, mollis elit at, iaculis odio. Donec imperdiet lacinia
odio at ultrices. Duis hendrerit consequat augue ac efficitur. Etiam vel
placerat arcu. Aenean sodales lorem ut auctor rutrum. Vestibulum auctor
fringilla felis ac tempor. Nullam tincidunt pellentesque sapien, non facilisis
lectus sagittis ac. Vivamus tempus nibh a laoreet hendrerit. Suspendisse tempor
neque erat, quis commodo ex aliquam ut. Duis egestas dignissim risus, non semper
lectus commodo non.
<BLANKLINE>
<BLANKLINE>
>>> # ----------------------------------------------------------------------
This last one is just a wrapper around django.utils.text.wrap() above, so
has the same deficiencies as that one. Using one of the two first options
instead of the django.wrap() here might be better:
>>> # ----------------------------------------------------------------------
>>> print(wrap_text_if_unwrapped(text, width=80))
<BLANKLINE>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Aliquam euismod semper hendrerit. Morbi fringilla semper
libero, eu auctor mauris ullamcorper et. Phasellus quis dolor in nibh pretium
cursus et molestie lacus. Morbi ut
magna mauris. Sed feugiat maximus finibus. Nullam dapibus
aliquam nibh sed varius. Curabitur elit nunc, lacinia
gravida lectus non, interdum porttitor magna.
<BLANKLINE>
Sed suscipit, libero vel ullamcorper malesuada, enim odio vestibulum quam,
nec luctus ligula diam eget sapien. Proin a lectus at eros ullamcorper
mollis. Aenean vehicula lacinia arcu, sed auctor mi cursus ut.
<BLANKLINE>
<BLANKLINE>
Pellentesque porta felis nec odio tincidunt pellentesque luctus in massa.
Duis lacus augue, facilisis eu congue eu, ultricies eget urna. In id risus
vestibulum, suscipit lorem sit amet, tempus libero.
<BLANKLINE>
Etiam a purus pretium, mollis elit at, iaculis odio. Donec imperdiet lacinia
odio at ultrices. Duis hendrerit consequat augue ac efficitur. Etiam vel
placerat arcu. Aenean sodales lorem ut auctor rutrum. Vestibulum auctor
fringilla felis ac tempor. Nullam tincidunt pellentesque sapien, non facilisis
lectus sagittis ac. Vivamus tempus nibh a laoreet hendrerit. Suspendisse tempor
neque erat, quis commodo ex aliquam ut. Duis egestas dignissim risus, non semper
lectus commodo non.
<BLANKLINE>
<BLANKLINE>
>>> # ----------------------------------------------------------------------
"""
from __future__ import unicode_literals
import re
import unicodedata
import textwrap
import types
from django.utils.functional import allow_lazy
from django.utils import six
from django.utils.safestring import mark_safe
if __name__ == '__main__':
print __doc__.replace('<BLANKLINE>','')
import debug # pyflakes:ignore
def xslugify(value):
"""
@ -303,24 +51,56 @@ def fill(text, width):
para = textwrap.fill(para, width, replace_whitespace=False)
wrapped.append(para)
return "\n\n".join(wrapped)
def wrap(text, width=80):
textLines = text.split('\n')
wrapped_lines = []
# Preserve any indent (after the general indent)
for line in textLines:
preservedIndent = ''
existIndent = re.search(r'^(\W+)', line)
# Change the existing wrap indent to the original one
if (existIndent):
preservedIndent = existIndent.groups()[0]
wrapped_lines.append(textwrap.fill(line, width=80, subsequent_indent=preservedIndent))
text = '\n'.join(wrapped_lines)
return text
def wordwrap(text, width=80):
"""Wraps long lines without loosing the formatting and indentation
of short lines"""
if not isinstance(text, (types.StringType,types.UnicodeType)):
return text
text = re.sub(" *\r\n", "\n", text) # get rid of DOS line endings
text = re.sub(" *\r", "\n", text) # get rid of MAC line endings
text = re.sub("( *\n){3,}", "\n\n", text) # get rid of excessive vertical whitespace
lines = text.split("\n")
filled = []
wrapped = False
prev_indent = None
for line in lines:
line = line.expandtabs()
indent = " " * (len(line) - len(line.lstrip()))
if wrapped and line.strip() != "" and indent == prev_indent:
line = filled[-1] + " " + line.lstrip()
filled = filled[:-1]
else:
wrapped = False
while (len(line) > width) and (" " in line[:width]):
linelength = len(line)
wrapped = True
breakpoint = line.rfind(" ",0,width)
filled += [ line[:breakpoint] ]
line = indent + line[breakpoint+1:]
if len(line) >= linelength:
break
filled += [ line.rstrip() ]
prev_indent = indent
return "\n".join(filled)
def wrap_text_if_unwrapped(text, width=72, max_tolerated_line_length=100):
from django.utils.text import wrap
# def alternative_wrap(text, width=80):
# # From http://blog.belgoat.com/python-textwrap-wrap-your-text-to-terminal-size/
# textLines = text.split('\n')
# wrapped_lines = []
# # Preserve any indent (after the general indent)
# for line in textLines:
# preservedIndent = ''
# existIndent = re.search(r'^(\W+)', line)
# # Change the existing wrap indent to the original one
# if (existIndent):
# preservedIndent = existIndent.groups()[0]
# wrapped_lines.append(textwrap.fill(line, width=width, subsequent_indent=preservedIndent))
# text = '\n'.join(wrapped_lines)
# return text
def wrap_text_if_unwrapped(text, width=80, max_tolerated_line_length=100):
text = re.sub(" *\r\n", "\n", text) # get rid of DOS line endings
text = re.sub(" *\r", "\n", text) # get rid of MAC line endings
@ -328,9 +108,8 @@ def wrap_text_if_unwrapped(text, width=72, max_tolerated_line_length=100):
for l in text.split("\n"))
if contains_long_lines:
return wrap(text, width)
else:
return text
text = wordwrap(text, width)
return text
def isascii(text):
try: