##// END OF EJS Templates
Rename "pull" request to "list"
Rename "pull" request to "list"

File last commit:

r1528:4c509fcc decentral
r1566:a1b54223 default
Show More
mdx_neboard.py
254 lines | 6.5 KiB | text/x-python | PythonLexer
neko259
Replace '--' with '—' character
r699 # coding=utf-8
neko259
Very alpha bbcode support (markdown removed)
r736 import re
neko259
Add a random number of spaces to spoiler (BB-71)
r1458 import random
neko259
Very alpha bbcode support (markdown removed)
r736 import bbcode
neko259
Moved text parser and preparser to a separate module (BB-64)
r1066
from urllib.parse import unquote
neko259
Refactoring
r1061 from django.core.exceptions import ObjectDoesNotExist
neko259
User notifications (BB-59)
r990 from django.core.urlresolvers import reverse
neko259
Small code cleanups
r721
neko259
Added jump view to open message of any thread by id. This fixes #49
r98 import boards
neko259
#12 Added markdown extension for reflinks, quotes and autolinks.
r52
neko259
Small code cleanups
r721
neko259
Implemented RSS support. This fixes #11
r89 __author__ = 'neko259'
neko259
#12 Added markdown extension for reflinks, quotes and autolinks.
r52
neko259
Fixed parsing an invalid reflink and reflink href attributes
r799 REFLINK_PATTERN = re.compile(r'^\d+$')
neko259
Parse global reflinks
r1528 GLOBAL_REFLINK_PATTERN = re.compile(r'(\w+)::([^:]+)::(\d+)')
neko259
Strip multiple newlines to one in the post before parsing with bbcode
r754 MULTI_NEWLINES_PATTERN = re.compile(r'(\r?\n){2,}')
ONE_NEWLINE = '\n'
neko259
Moved text parser and preparser to a separate module (BB-64)
r1066 REGEX_URL = re.compile(r'https?\://[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(/\S*)?')
neko259
Add ">" char at every line inside quote
r1068 LINE_BREAK_HTML = '<div class="br"></div>'
neko259
Moved spoiler multiplier and space to module constants
r1460 SPOILER_SPACE = '&nbsp;'
MAX_SPOILER_MULTIPLIER = 2
neko259
Speed up parsing by moving constants to module scape
r302
neko259
Split up post model into post and thread to normalise models. Still need some refactoring
r398
neko259
Added a new format panel to the text form
r438 class TextFormatter():
"""
An interface for formatter that can be used in the text format panel
"""
neko259
Small code cleanups
r721 def __init__(self):
pass
neko259
Added a new format panel to the text form
r438 name = ''
# Left and right tags for the button preview
preview_left = ''
preview_right = ''
# Left and right characters for the textarea input
format_left = ''
format_right = ''
neko259
Very alpha bbcode support (markdown removed)
r736 class AutolinkPattern():
neko259
#12 Added markdown extension for reflinks, quotes and autolinks.
r52 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
neko259
Very alpha bbcode support (markdown removed)
r736 class QuotePattern(TextFormatter):
neko259
Add ">" char at every line inside quote
r1068 name = '>q'
preview_left = '<span class="quote">'
neko259
Added a new format panel to the text form
r438 preview_right = '</span>'
neko259
Very alpha bbcode support (markdown removed)
r736 format_left = '[quote]'
format_right = '[/quote]'
neko259
#12 Added markdown extension for reflinks, quotes and autolinks.
r52
neko259
Very alpha bbcode support (markdown removed)
r736 class SpoilerPattern(TextFormatter):
name = 'spoiler'
neko259
Added a new format panel to the text form
r438 preview_left = '<span class="spoiler">'
preview_right = '</span>'
neko259
Very alpha bbcode support (markdown removed)
r736 format_left = '[spoiler]'
format_right = '[/spoiler]'
neko259
Added a new format panel to the text form
r438
neko259
#12 Added spoilers and comments.
r56
neko259
Very alpha bbcode support (markdown removed)
r736 class CommentPattern(TextFormatter):
neko259
Added a new format panel to the text form
r438 name = ''
preview_left = '<span class="comment">// '
preview_right = '</span>'
neko259
Very alpha bbcode support (markdown removed)
r736 format_left = '[comment]'
format_right = '[/comment]'
neko259
#12 Added spoilers and comments.
r56
neko259
Added source parameter to quotes
r755 # TODO Use <s> tag here
neko259
Very alpha bbcode support (markdown removed)
r736 class StrikeThroughPattern(TextFormatter):
neko259
Added a new format panel to the text form
r438 name = 's'
preview_left = '<span class="strikethrough">'
preview_right = '</span>'
neko259
Very alpha bbcode support (markdown removed)
r736 format_left = '[s]'
format_right = '[/s]'
neko259
Added strikethrough text to the text parser
r330
neko259
Added a new format panel to the text form
r438 class ItalicPattern(TextFormatter):
name = 'i'
preview_left = '<i>'
preview_right = '</i>'
neko259
Very alpha bbcode support (markdown removed)
r736 format_left = '[i]'
format_right = '[/i]'
neko259
Added a new format panel to the text form
r438
class BoldPattern(TextFormatter):
name = 'b'
preview_left = '<b>'
preview_right = '</b>'
neko259
Very alpha bbcode support (markdown removed)
r736 format_left = '[b]'
format_right = '[/b]'
neko259
Added a new format panel to the text form
r438
neko259
Added proper formatting when several lines are selected
r440 class CodePattern(TextFormatter):
name = 'code'
preview_left = '<code>'
preview_right = '</code>'
neko259
Very alpha bbcode support (markdown removed)
r736 format_left = '[code]'
format_right = '[/code]'
neko259
Replace '--' with '—' character
r699
neko259
Very alpha bbcode support (markdown removed)
r736 def render_reflink(tag_name, value, options, parent, context):
neko259
Refactoring
r1061 result = '>>%s' % value
neko259
Removed image tag from markdown. Refactored markdown extension code. This fixes #21
r100
neko259
Parse global reflinks
r1528 post = None
neko259
Refactoring
r1061 if REFLINK_PATTERN.match(value):
post_id = int(value)
neko259
Removed image tag from markdown. Refactored markdown extension code. This fixes #21
r100
neko259
Refactoring
r1061 try:
post = boards.models.Post.objects.get(id=post_id)
neko259
#12 Added markdown extension for reflinks, quotes and autolinks.
r52
neko259
Refactoring
r1061 except ObjectDoesNotExist:
pass
neko259
Parse global reflinks
r1528 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()
neko259
Refactoring
r1061
return result
neko259
Changed parser to show quotes and reflinks as they are posted, not with borders and '#' character.
r90
neko259
#12 Added markdown extension for reflinks, quotes and autolinks.
r52
neko259
Added source parameter to quotes
r755 def render_quote(tag_name, value, options, parent, context):
neko259
Use <div> as a line break. Hell yeah!
r831 source = ''
neko259
Added source parameter to quotes
r755 if 'source' in options:
source = options['source']
neko259
Parse direct option of the quote tag in addition to the source option
r1398 elif 'quote' in options:
source = options['quote']
neko259
Added source parameter to quotes
r755
if source:
neko259
Use <div> as a line break. Hell yeah!
r831 result = '<div class="multiquote"><div class="quote-header">%s</div><div class="quote-text">%s</div></div>' % (source, value)
neko259
Added source parameter to quotes
r755 else:
neko259
Add ">" char at every line inside quote
r1068 # Insert a ">" at the start of every line
result = '<span class="quote">&gt;{}</span>'.format(
value.replace(LINE_BREAK_HTML,
'{}&gt;'.format(LINE_BREAK_HTML)))
neko259
Added source parameter to quotes
r755
return result
neko259
User notifications (BB-59)
r990 def render_notification(tag_name, value, options, parent, content):
neko259
Use only lowercase name in notifications. Refactored post manager and refmap...
r1008 username = value.lower()
neko259
User notifications (BB-59)
r990 return '<a href="{}" class="user-cast">@{}</a>'.format(
neko259
Use only lowercase name in notifications. Refactored post manager and refmap...
r1008 reverse('notifications', kwargs={'username': username}), username)
neko259
User notifications (BB-59)
r990
neko259
Add a bbcode tag to render tag link
r1202 def render_tag(tag_name, value, options, parent, context):
tag_name = value.lower()
try:
url = boards.models.Tag.objects.get(name=tag_name).get_view()
except ObjectDoesNotExist:
url = tag_name
return url
neko259
Add a random number of spaces to spoiler (BB-71)
r1458 def render_spoiler(tag_name, value, options, parent, context):
text_len = len(value)
neko259
Moved spoiler multiplier and space to module constants
r1460 space_count = random.randint(0, text_len * MAX_SPOILER_MULTIPLIER)
side_spaces = SPOILER_SPACE * (space_count // 2)
neko259
Show even number of spaces before and after spoiler
r1459 return '<span class="spoiler">{}{}{}</span>'.format(side_spaces, value,
side_spaces)
neko259
Add a random number of spaces to spoiler (BB-71)
r1458
neko259
Added a new format panel to the text form
r438 formatters = [
QuotePattern,
SpoilerPattern,
ItalicPattern,
BoldPattern,
CommentPattern,
StrikeThroughPattern,
neko259
Added proper formatting when several lines are selected
r440 CodePattern,
neko259
Added a new format panel to the text form
r438 ]
neko259
Moved text parser and preparser to a separate module (BB-64)
r1066
PREPARSE_PATTERNS = {
r'(?<!>)>>(\d+)': r'[post]\1[/post]', # Reflink ">>123"
r'^>([^>].+)': r'[quote]\1[/quote]', # Quote ">text"
r'^//(.+)': r'[comment]\1[/comment]', # Comment "//text"
r'\B@(\w+)': r'[user]\1[/user]', # User notification "@user"
}
class Parser:
def __init__(self):
# The newline hack is added because br's margin does not work in all
# browsers except firefox, when the div's does.
neko259
Add ">" char at every line inside quote
r1068 self.parser = bbcode.Parser(newline=LINE_BREAK_HTML)
neko259
Moved text parser and preparser to a separate module (BB-64)
r1066
self.parser.add_formatter('post', render_reflink, strip=True)
self.parser.add_formatter('quote', render_quote, strip=True)
self.parser.add_formatter('user', render_notification, strip=True)
neko259
Add a bbcode tag to render tag link
r1202 self.parser.add_formatter('tag', render_tag, strip=True)
neko259
Add a random number of spaces to spoiler (BB-71)
r1458 self.parser.add_formatter('spoiler', render_spoiler, strip=True)
neko259
Moved text parser and preparser to a separate module (BB-64)
r1066 self.parser.add_simple_formatter(
'comment', '<span class="comment">//%(value)s</span>')
self.parser.add_simple_formatter(
's', '<span class="strikethrough">%(value)s</span>')
# TODO Why not use built-in tag?
self.parser.add_simple_formatter('code',
'<pre><code>%(value)s</pre></code>',
render_embedded=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):
neko259
Use old-style quotes when no source is specified
r1067 return self.parser.format(text)
neko259
Use singleton parser
r1499
parser = Parser()
def get_parser():
return parser