# coding=utf-8 from xml import etree import re import random import bbcode from urllib.parse import unquote from django.core.exceptions import ObjectDoesNotExist from django.urls import reverse from django.utils.translation import ugettext_lazy as _ import boards from boards import settings from swineboard.settings import ALLOWED_HOSTS __author__ = 'neko259' REFLINK_PATTERN = re.compile(r'^\d+$') GLOBAL_REFLINK_PATTERN = re.compile(r'(\w+)::([^:]+)::(\d+)') MULTI_NEWLINES_PATTERN = re.compile(r'(\r?\n){2,}') ONE_NEWLINE = '\n' REGEX_URL = re.compile(r'https?\://[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(/\S*)?') LINE_BREAK_HTML = '
' SPOILER_SPACE = ' ' REGEX_ANY_LINE_BREAK = re.compile(r'(' + LINE_BREAK_HTML + '|\r|\n)') QUOTE_REPLACEMENT = '\g<1>>' MAX_SPOILER_MULTIPLIER = 2 MAX_SPOILER_SPACE_COUNT = 20 class TextFormatter: """ An interface for formatter that can be used in the text format panel """ def __init__(self): pass name = '' # Left and right tags for the button preview preview_left = '' preview_right = '' # Tag name to enclose the text in the form tag_name = '' has_input = 'false' input_prompt = '' class AutolinkPattern: def handleMatch(self, m): link_element = etree.Element('a') href = m.group(2) link_element.set('href', href) link_element.text = href return link_element class QuotePattern(TextFormatter): name = '>q' preview_left = '' preview_right = '' tag_name = 'quote' class SpoilerPattern(TextFormatter): name = 'spoiler' preview_left = '' preview_right = '' tag_name = 'spoiler' class CommentPattern(TextFormatter): name = '' preview_left = '// ' preview_right = '' tag_name = 'comment' # TODO Use'
preview_right = '
'
tag_name = 'code'
class HintPattern(TextFormatter):
name = 'hint'
preview_left = ''
preview_right = ''
tag_name = 'hint'
class ColorPattern(TextFormatter):
name = 'color'
preview_left = ''
preview_right = ''
tag_name = 'color'
has_input = 'true'
input_prompt = _('Enter color (name or #ccc code)')
def render_reflink(tag_name, value, options, parent, context):
result = '>>%s' % value
post = None
if REFLINK_PATTERN.match(value):
post_id = int(value)
try:
post = boards.models.Post.objects.get(id=post_id)
except ObjectDoesNotExist:
pass
elif GLOBAL_REFLINK_PATTERN.match(value):
match = GLOBAL_REFLINK_PATTERN.search(value)
try:
global_id = boards.models.GlobalId.objects.get(
key_type=match.group(1), key=match.group(2),
local_id=match.group(3))
post = global_id.post
except ObjectDoesNotExist:
pass
if post is not None:
result = post.get_link_view()
return result
def render_quote(tag_name, value, options, parent, context):
source = options.get('quote') or options.get('source')
if source:
result = '%(value)s
',
render_embedded=False,
escape_html=True,
replace_links=False,
replace_cosmetic=False)
def preparse(self, text):
"""
Performs manual parsing before the bbcode parser is used.
Preparsed text is saved as raw and the text before preparsing is lost.
"""
new_text = MULTI_NEWLINES_PATTERN.sub(ONE_NEWLINE, text)
for key, value in PREPARSE_PATTERNS.items():
new_text = re.sub(key, value, new_text, flags=re.MULTILINE)
for link in REGEX_URL.findall(text):
new_text = new_text.replace(link, unquote(link))
return new_text
def parse(self, text):
return self.parser.format(text)
parser = Parser()
def get_parser():
return parser