board.py
139 lines
| 3.7 KiB
| text/x-python
|
PythonLexer
neko259
|
r1000 | import re | ||
neko259
|
r320 | from django.shortcuts import get_object_or_404 | ||
from django import template | ||||
neko259
|
r1000 | ELLIPSIZER = '...' | ||
REGEX_LINES = re.compile(r'(<div class="br"></div>)', re.U | re.S) | ||||
REGEX_TAG = re.compile(r'<(/)?([^ ]+?)(?:(\s*/)| .*?)?>', re.S) | ||||
neko259
|
r1027 | IMG_ACTION_URL = '[<a href="{}">{}</a>]' | ||
neko259
|
r692 | |||
neko259
|
r320 | register = template.Library() | ||
neko259
|
r460 | actions = [ | ||
{ | ||||
'name': 'google', | ||||
'link': 'http://google.com/searchbyimage?image_url=%s', | ||||
}, | ||||
{ | ||||
'name': 'iqdb', | ||||
'link': 'http://iqdb.org/?url=%s', | ||||
}, | ||||
] | ||||
neko259
|
r320 | |||
@register.simple_tag(name='post_url') | ||||
def post_url(*args, **kwargs): | ||||
post_id = args[0] | ||||
neko259
|
r692 | post = get_object_or_404('Post', id=post_id) | ||
neko259
|
r320 | |||
neko259
|
r621 | return post.get_url() | ||
neko259
|
r614 | |||
neko259
|
r460 | @register.simple_tag(name='image_actions') | ||
def image_actions(*args, **kwargs): | ||||
image_link = args[0] | ||||
if len(args) > 1: | ||||
neko259
|
r1027 | image_link = 'http://' + args[1] + image_link # TODO https? | ||
neko259
|
r460 | |||
neko259
|
r1027 | return ', '.join([IMG_ACTION_URL.format( | ||
action['link'] % image_link, action['name'])for action in actions]) | ||||
neko259
|
r537 | |||
neko259
|
r692 | # TODO Use get_view of a post instead of this | ||
neko259
|
r537 | @register.inclusion_tag('boards/post.html', name='post_view') | ||
neko259
|
r594 | def post_view(post, moderator=False, need_open_link=False, truncated=False, | ||
neko259
|
r1056 | reply_link=False, **kwargs): | ||
neko259
|
r538 | """ | ||
Get post | ||||
""" | ||||
neko259
|
r988 | thread = post.get_thread() | ||
neko259
|
r1032 | is_opening = post.is_opening() | ||
can_bump = thread.can_bump() | ||||
neko259
|
r583 | |||
neko259
|
r1032 | if is_opening: | ||
opening_post_id = post.id | ||||
neko259
|
r949 | else: | ||
neko259
|
r1032 | opening_post_id = thread.get_opening_post_id() | ||
neko259
|
r614 | |||
neko259
|
r537 | return { | ||
'post': post, | ||||
neko259
|
r540 | 'moderator': moderator, | ||
neko259
|
r583 | 'is_opening': is_opening, | ||
'thread': thread, | ||||
'bumpable': can_bump, | ||||
neko259
|
r594 | 'need_open_link': need_open_link, | ||
'truncated': truncated, | ||||
neko259
|
r614 | 'opening_post_id': opening_post_id, | ||
neko259
|
r1056 | 'reply_link': reply_link, | ||
neko259
|
r614 | } | ||
neko259
|
r1000 | |||
neko259
|
r1027 | # TODO Fix or remove this method | ||
neko259
|
r1000 | @register.filter(is_safe=True) | ||
def truncate_lines(text, length): | ||||
if length <= 0: | ||||
return '' | ||||
html4_singlets = ( | ||||
'br', 'col', 'link', 'base', 'img', | ||||
'param', 'area', 'hr', 'input' | ||||
) | ||||
# Count non-HTML chars/words and keep note of open tags | ||||
pos = 0 | ||||
end_text_pos = 0 | ||||
current_len = 0 | ||||
open_tags = [] | ||||
while current_len <= length: | ||||
m = REGEX_LINES.search(text, pos) | ||||
if not m: | ||||
# Checked through whole string | ||||
break | ||||
pos = m.end(0) | ||||
if m.group(1): | ||||
# It's an actual non-HTML word or char | ||||
current_len += 1 | ||||
if current_len == length: | ||||
neko259
|
r1001 | end_text_pos = m.start(0) | ||
neko259
|
r1000 | continue | ||
# Check for tag | ||||
tag = REGEX_TAG.match(m.group(0)) | ||||
if not tag or current_len >= length: | ||||
# Don't worry about non tags or tags after our truncate point | ||||
continue | ||||
closing_tag, tagname, self_closing = tag.groups() | ||||
# Element names are always case-insensitive | ||||
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) | ||||
if current_len <= length: | ||||
return text | ||||
out = text[:end_text_pos] | ||||
if not out.endswith(ELLIPSIZER): | ||||
out += ELLIPSIZER | ||||
# Close any tags still open | ||||
for tag in open_tags: | ||||
out += '</%s>' % tag | ||||
# Return string | ||||
return out | ||||