add mentions
This commit is contained in:
@@ -6,6 +6,16 @@ from pygments.lexers import get_lexer_by_name
|
||||
from pygments.util import ClassNotFound as PygmentsClassNotFound
|
||||
import re
|
||||
|
||||
class BabycodeParseResult:
|
||||
def __init__(self, result, mentions=[]):
|
||||
self.result = result
|
||||
self.mentions = mentions
|
||||
|
||||
|
||||
def __str__(self):
|
||||
return self.result
|
||||
|
||||
|
||||
BABYCODE_VERSION = 5
|
||||
|
||||
NAMED_COLORS = [
|
||||
@@ -78,6 +88,9 @@ def tag_list(children):
|
||||
return " ".join([f"<li>{x}</li>" for x in list_body.split("\1") if x])
|
||||
|
||||
def tag_color(children, attr, surrounding):
|
||||
if not attr:
|
||||
return f"[color]{children}[/color]"
|
||||
|
||||
hex_re = r"^#?([0-9a-f]{6}|[0-9a-f]{3})$"
|
||||
potential_color = attr.lower().strip()
|
||||
|
||||
@@ -206,6 +219,24 @@ def is_inline(e):
|
||||
|
||||
return e['type'] != 'rule'
|
||||
|
||||
def make_mention(e, mentions):
|
||||
from ..models import Users
|
||||
from flask import url_for
|
||||
target_user = Users.find({'username': e['name'].lower()})
|
||||
if not target_user:
|
||||
return f"@{e['name']}"
|
||||
|
||||
mention_data = {
|
||||
'mention_text': f"@{e['name']}",
|
||||
'mentioned_user_id': int(target_user.id),
|
||||
"start": e['start'],
|
||||
"end": e['end'],
|
||||
}
|
||||
if mention_data not in mentions:
|
||||
mentions.append(mention_data)
|
||||
|
||||
return f"<a class='mention{' display' if target_user.has_display_name() else ''}' href='{url_for('users.page', username=target_user.username)}' title='@{target_user.username}' data-init='highlightMentions' data-username='{target_user.username}'>{'@' if not target_user.has_display_name() else ''}{target_user.get_readable_name()}</a>"
|
||||
|
||||
def should_collapse(text, surrounding):
|
||||
if not isinstance(text, str):
|
||||
return False
|
||||
@@ -218,15 +249,19 @@ def should_collapse(text, surrounding):
|
||||
|
||||
return False
|
||||
|
||||
def babycode_to_html(s, banned_tags=None):
|
||||
allowed_tags = list(TAGS.keys())
|
||||
def sanitize(s):
|
||||
return escape(s.strip().replace('\r\n', '\n').replace('\r', '\n'))
|
||||
|
||||
def babycode_to_html(s, banned_tags={}):
|
||||
allowed_tags = set(TAGS.keys())
|
||||
if banned_tags is not None:
|
||||
for tag in banned_tags:
|
||||
allowed_tags.remove(tag)
|
||||
subj = escape(s.strip().replace('\r\n', '\n').replace('\r', '\n'))
|
||||
allowed_tags.discard(tag)
|
||||
subj = sanitize(s)
|
||||
parser = Parser(subj)
|
||||
parser.valid_bbcode_tags = allowed_tags
|
||||
parser.bbcode_tags_only_text_children = TEXT_ONLY
|
||||
parser.mentions_allowed = '@mention' not in banned_tags
|
||||
parser.valid_emotes = EMOJI.keys()
|
||||
|
||||
uncollapsed = parser.parse()
|
||||
@@ -241,6 +276,7 @@ def babycode_to_html(s, banned_tags=None):
|
||||
elements.append(e)
|
||||
|
||||
out = ""
|
||||
mentions = []
|
||||
def fold(element, nobr, surrounding):
|
||||
if isinstance(element, str):
|
||||
if nobr:
|
||||
@@ -266,6 +302,8 @@ def babycode_to_html(s, banned_tags=None):
|
||||
return EMOJI[element['name']]
|
||||
case "rule":
|
||||
return "<hr>"
|
||||
case "mention":
|
||||
return make_mention(element, mentions)
|
||||
|
||||
for i in range(len(elements)):
|
||||
e = elements[i]
|
||||
@@ -274,4 +312,4 @@ def babycode_to_html(s, banned_tags=None):
|
||||
elements[i + 1] if i+1 < len(elements) else None
|
||||
)
|
||||
out = out + fold(e, False, surrounding)
|
||||
return out
|
||||
return BabycodeParseResult(out, mentions)
|
||||
|
||||
@@ -6,12 +6,14 @@ PAT_EMOTE = r"[^\s:]"
|
||||
PAT_BBCODE_TAG = r"\w"
|
||||
PAT_BBCODE_ATTR = r"[^\]]"
|
||||
PAT_LINK = r"https?:\/\/[\w\-_.?:\/=&~@#%]+[\w\-\/]"
|
||||
PAT_MENTION = r'[a-zA-Z0-9_-]'
|
||||
|
||||
class Parser:
|
||||
def __init__(self, src_str):
|
||||
self.valid_bbcode_tags = []
|
||||
self.valid_bbcode_tags = {}
|
||||
self.valid_emotes = []
|
||||
self.bbcode_tags_only_text_children = [],
|
||||
self.bbcode_tags_only_text_children = []
|
||||
self.mentions_allowed = True
|
||||
self.source = src_str
|
||||
self.position = 0
|
||||
self.position_stack = []
|
||||
@@ -206,6 +208,25 @@ class Parser:
|
||||
"url": word
|
||||
}
|
||||
|
||||
def parse_mention(self):
|
||||
if not self.mentions_allowed:
|
||||
return None
|
||||
|
||||
self.save_position()
|
||||
|
||||
if not self.check_char('@'):
|
||||
self.restore_position()
|
||||
return None
|
||||
|
||||
mention = self.match_pattern(PAT_MENTION)
|
||||
self.forget_position()
|
||||
return {
|
||||
"type": "mention",
|
||||
"name": mention,
|
||||
"start": self.position - len(mention) - 1,
|
||||
"end": self.position,
|
||||
}
|
||||
|
||||
|
||||
def parse_element(self, siblings):
|
||||
if self.is_end_of_source():
|
||||
@@ -214,7 +235,8 @@ class Parser:
|
||||
element = self.parse_emote() \
|
||||
or self.parse_bbcode() \
|
||||
or self.parse_rule() \
|
||||
or self.parse_link()
|
||||
or self.parse_link() \
|
||||
or self.parse_mention()
|
||||
|
||||
if element is None:
|
||||
if len(siblings) > 0:
|
||||
|
||||
Reference in New Issue
Block a user