##// END OF EJS Templates
Reimplemented caret position manipulation. Move caret inside the bbcode tags if inserted
Reimplemented caret position manipulation. Move caret inside the bbcode tags if inserted

File last commit:

r1662:64ac1a71 default
r1783:43080135 default
Show More
mdx_neboard.py
276 lines | 7.2 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
Allow inserting text hints
r1662 class HintPattern(TextFormatter):
name = 'hint'
preview_left = '<span class="hint">'
preview_right = '</span>'
format_left = '[hint]'
format_right = '[/hint]'
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
Allow inserting text hints
r1662 def render_hint(tag_name, value, options, parent, context):
if 'hint' in options:
hint = options['hint']
result = '<span class="hint" title="{}">{}</span>'.format(hint, value)
else:
result = value
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
Allow inserting text hints
r1662 HintPattern,
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)
neko259
Allow inserting text hints
r1662 self.parser.add_formatter('hint', render_hint, strip=True)
neko259
Moved text parser and preparser to a separate module (BB-64)
r1066 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>')
self.parser.add_simple_formatter('code',
'<pre><code>%(value)s</pre></code>',
neko259
Do not modify text inside [code] by parser (BB-54)
r1585 render_embedded=False,
neko259
Escape html inside [code]
r1621 escape_html=True,
neko259
Do not modify text inside [code] by parser (BB-54)
r1585 replace_links=False,
replace_cosmetic=False)
neko259
Moved text parser and preparser to a separate module (BB-64)
r1066
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