# HG changeset patch # User neko259 # Date 2017-01-02 20:57:45 # Node ID bce744de09c46725718b6ec0e0a2d41f609fb0da # Parent 69d8441fb60122946f66674a66fafa6af2999185 Truncate line breaks diff --git a/boards/templates/boards/post.html b/boards/templates/boards/post.html --- a/boards/templates/boards/post.html +++ b/boards/templates/boards/post.html @@ -83,7 +83,7 @@ {% endcomment %}
{% if truncated %} - {{ post.get_text|truncatewords_html:50|safe }} + {{ post.get_text|truncatewords_html:50|truncatenewlines_html:3|safe }} {% else %} {{ post.get_text|safe }} {% endif %} diff --git a/boards/templatetags/board.py b/boards/templatetags/board.py --- a/boards/templatetags/board.py +++ b/boards/templatetags/board.py @@ -1,9 +1,18 @@ import re + from django.shortcuts import get_object_or_404 from django import template +from django.utils.text import re_tag + +from boards.mdx_neboard import LINE_BREAK_HTML IMG_ACTION_URL = '[{}]' +REGEX_NEWLINE = re.compile(LINE_BREAK_HTML) +TRUNCATOR = '...' +HTML4_SINGLETS =( + 'br', 'col', 'link', 'base', 'img', 'param', 'area', 'hr', 'input' +) register = template.Library() @@ -49,3 +58,59 @@ def post_view(context, post, *args, **kw def page_url(paginator, page_number, *args, **kwargs): if paginator.supports_urls(): return paginator.get_page_url(page_number) + + +@register.filter(name='truncatenewlines_html') +def truncatenewlines_html(value, arg): + current_pos = 0 + match_count = 0 + + # Collect places for truncation + while match_count <= arg: + m = REGEX_NEWLINE.search(value, current_pos) + if m is None: + break + else: + match_count += 1 + current_pos = m.end() + + # Find and close open tags + if match_count > arg: + truncate_pos = current_pos + + open_tags = [] + text = value[:truncate_pos] + current_pos = 0 + while True: + tag = re_tag.search(text, current_pos) + if tag is None: + break + else: + closing_tag, tagname, self_closing = tag.groups() + tagname = tagname.lower() + if self_closing or tagname in HTML4_SINGLETS: + pass + elif closing_tag: + # Check for match in open tags list + try: + i = open_tags.index(tagname) + except ValueError: + pass + else: + # SGML: An end tag closes, back to the matching start tag, + # all unclosed intervening start tags with omitted end tags + open_tags = open_tags[i + 1:] + else: + # Add it to the start of the open tags list + open_tags.insert(0, tagname) + + current_pos = tag.end() + + for tag in open_tags: + text += ''.format(tag) + text += TRUNCATOR + else: + text = value + + return text +