import re from django.shortcuts import get_object_or_404 from django import template ELLIPSIZER = '...' REGEX_LINES = re.compile(r'(
)', re.U | re.S) REGEX_TAG = re.compile(r'<(/)?([^ ]+?)(?:(\s*/)| .*?)?>', re.S) IMG_ACTION_URL = '[{}]' register = template.Library() actions = [ { 'name': 'google', 'link': 'http://google.com/searchbyimage?image_url=%s', }, { 'name': 'iqdb', 'link': 'http://iqdb.org/?url=%s', }, ] @register.simple_tag(name='post_url') def post_url(*args, **kwargs): post_id = args[0] post = get_object_or_404('Post', id=post_id) return post.get_url() @register.simple_tag(name='image_actions') def image_actions(*args, **kwargs): image_link = args[0] if len(args) > 1: image_link = 'http://' + args[1] + image_link # TODO https? return ', '.join([IMG_ACTION_URL.format( action['link'] % image_link, action['name'])for action in actions]) # TODO Use get_view of a post instead of this @register.inclusion_tag('boards/post.html', name='post_view') def post_view(post, moderator=False, need_open_link=False, truncated=False, reply_link=False, **kwargs): """ Get post """ thread = post.get_thread() is_opening = post.is_opening() can_bump = thread.can_bump() if is_opening: opening_post_id = post.id else: opening_post_id = thread.get_opening_post_id() return { 'post': post, 'moderator': moderator, 'is_opening': is_opening, 'thread': thread, 'bumpable': can_bump, 'need_open_link': need_open_link, 'truncated': truncated, 'opening_post_id': opening_post_id, 'reply_link': reply_link, } # TODO Fix or remove this method @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: end_text_pos = m.start(0) 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 += '' % tag # Return string return out