mdx_neboard.py
183 lines
| 4.2 KiB
| text/x-python
|
PythonLexer
/ boards / mdx_neboard.py
neko259
|
r699 | # coding=utf-8 | ||
neko259
|
r736 | import re | ||
import bbcode | ||||
neko259
|
r721 | |||
neko259
|
r98 | import boards | ||
neko259
|
r52 | |||
neko259
|
r721 | |||
neko259
|
r89 | __author__ = 'neko259' | ||
neko259
|
r52 | |||
neko259
|
r799 | REFLINK_PATTERN = re.compile(r'^\d+$') | ||
neko259
|
r754 | MULTI_NEWLINES_PATTERN = re.compile(r'(\r?\n){2,}') | ||
ONE_NEWLINE = '\n' | ||||
neko259
|
r302 | |||
neko259
|
r398 | |||
neko259
|
r438 | class TextFormatter(): | ||
""" | ||||
An interface for formatter that can be used in the text format panel | ||||
""" | ||||
neko259
|
r721 | def __init__(self): | ||
pass | ||||
neko259
|
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
|
r736 | class AutolinkPattern(): | ||
neko259
|
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
|
r736 | class QuotePattern(TextFormatter): | ||
name = 'q' | ||||
preview_left = '<span class="multiquote">' | ||||
neko259
|
r438 | preview_right = '</span>' | ||
neko259
|
r736 | format_left = '[quote]' | ||
format_right = '[/quote]' | ||||
neko259
|
r52 | |||
neko259
|
r736 | class SpoilerPattern(TextFormatter): | ||
name = 'spoiler' | ||||
neko259
|
r438 | preview_left = '<span class="spoiler">' | ||
preview_right = '</span>' | ||||
neko259
|
r736 | format_left = '[spoiler]' | ||
format_right = '[/spoiler]' | ||||
neko259
|
r438 | |||
neko259
|
r56 | def handleMatch(self, m): | ||
quote_element = etree.Element('span') | ||||
quote_element.set('class', 'spoiler') | ||||
quote_element.text = m.group(2) | ||||
return quote_element | ||||
neko259
|
r736 | class CommentPattern(TextFormatter): | ||
neko259
|
r438 | name = '' | ||
preview_left = '<span class="comment">// ' | ||||
preview_right = '</span>' | ||||
neko259
|
r736 | format_left = '[comment]' | ||
format_right = '[/comment]' | ||||
neko259
|
r56 | |||
neko259
|
r755 | # TODO Use <s> tag here | ||
neko259
|
r736 | class StrikeThroughPattern(TextFormatter): | ||
neko259
|
r438 | name = 's' | ||
preview_left = '<span class="strikethrough">' | ||||
preview_right = '</span>' | ||||
neko259
|
r736 | format_left = '[s]' | ||
format_right = '[/s]' | ||||
neko259
|
r330 | |||
neko259
|
r438 | class ItalicPattern(TextFormatter): | ||
name = 'i' | ||||
preview_left = '<i>' | ||||
preview_right = '</i>' | ||||
neko259
|
r736 | format_left = '[i]' | ||
format_right = '[/i]' | ||||
neko259
|
r438 | |||
class BoldPattern(TextFormatter): | ||||
name = 'b' | ||||
preview_left = '<b>' | ||||
preview_right = '</b>' | ||||
neko259
|
r736 | format_left = '[b]' | ||
format_right = '[/b]' | ||||
neko259
|
r438 | |||
neko259
|
r440 | class CodePattern(TextFormatter): | ||
name = 'code' | ||||
preview_left = '<code>' | ||||
preview_right = '</code>' | ||||
neko259
|
r736 | format_left = '[code]' | ||
format_right = '[/code]' | ||||
neko259
|
r699 | |||
neko259
|
r736 | def render_reflink(tag_name, value, options, parent, context): | ||
if not REFLINK_PATTERN.match(value): | ||||
neko259
|
r831 | return '>>%s' % value | ||
neko259
|
r100 | |||
neko259
|
r736 | post_id = int(value) | ||
neko259
|
r100 | |||
neko259
|
r736 | posts = boards.models.Post.objects.filter(id=post_id) | ||
if posts.exists(): | ||||
post = posts[0] | ||||
neko259
|
r52 | |||
neko259
|
r831 | return '<a href="%s">>>%s</a>' % (post.get_url(), post_id) | ||
neko259
|
r736 | else: | ||
neko259
|
r831 | return '>>%s' % value | ||
neko259
|
r90 | |||
neko259
|
r52 | |||
neko259
|
r755 | def render_quote(tag_name, value, options, parent, context): | ||
neko259
|
r831 | source = '' | ||
neko259
|
r755 | if 'source' in options: | ||
source = options['source'] | ||||
neko259
|
r831 | result = '' | ||
neko259
|
r755 | if source: | ||
neko259
|
r831 | result = '<div class="multiquote"><div class="quote-header">%s</div><div class="quote-text">%s</div></div>' % (source, value) | ||
neko259
|
r755 | else: | ||
neko259
|
r831 | result = '<div class="multiquote"><div class="quote-text">%s</div></div>' % value | ||
neko259
|
r755 | |||
return result | ||||
neko259
|
r754 | def preparse_text(text): | ||
""" | ||||
Performs manual parsing before the bbcode parser is used. | ||||
""" | ||||
return MULTI_NEWLINES_PATTERN.sub(ONE_NEWLINE, text) | ||||
neko259
|
r736 | def bbcode_extended(markup): | ||
neko259
|
r831 | # The newline hack is added because br's margin does not work in all | ||
# browsers except firefox, when the div's does. | ||||
parser = bbcode.Parser(newline='<div class="br"></div>') | ||||
neko259
|
r736 | parser.add_formatter('post', render_reflink, strip=True) | ||
neko259
|
r755 | parser.add_formatter('quote', render_quote, strip=True) | ||
neko259
|
r736 | parser.add_simple_formatter('comment', | ||
neko259
|
r881 | '<span class="comment">//%(value)s</span>') | ||
neko259
|
r736 | parser.add_simple_formatter('spoiler', | ||
neko259
|
r881 | '<span class="spoiler">%(value)s</span>') | ||
neko259
|
r815 | # TODO Use <s> here | ||
neko259
|
r736 | parser.add_simple_formatter('s', | ||
neko259
|
r881 | '<span class="strikethrough">%(value)s</span>') | ||
neko259
|
r815 | # TODO Why not use built-in tag? | ||
neko259
|
r736 | parser.add_simple_formatter('code', | ||
neko259
|
r881 | '<pre><code>%(value)s</pre></code>', | ||
render_embedded=False) | ||||
neko259
|
r754 | |||
text = preparse_text(markup) | ||||
return parser.format(text) | ||||
neko259
|
r438 | |||
formatters = [ | ||||
QuotePattern, | ||||
SpoilerPattern, | ||||
ItalicPattern, | ||||
BoldPattern, | ||||
CommentPattern, | ||||
StrikeThroughPattern, | ||||
neko259
|
r440 | CodePattern, | ||
neko259
|
r438 | ] | ||