mentions: markdown renderer now wraps username in hovercard logic allowing checking the mentioned user.

- ref: #5586
This commit is contained in:
Marcin Kuzminski 2020-01-27 09:24:08 +01:00
parent 8e01135d04
commit e1a5fb601d
7 changed files with 63 additions and 20 deletions

View file

@ -25,6 +25,10 @@ def includeme(config):
name='hovercard_user',
pattern='/_hovercard/user/{user_id}')
config.add_route(
name='hovercard_username',
pattern='/_hovercard/username/{username}')
config.add_route(
name='hovercard_user_group',
pattern='/_hovercard/user_group/{user_group_id}')

View file

@ -63,6 +63,19 @@ class HoverCardsView(BaseAppView):
c.user = User.get_or_404(user_id)
return self._get_template_context(c)
@LoginRequired()
@view_config(
route_name='hovercard_username', request_method='GET', xhr=True,
renderer='rhodecode:templates/hovercards/hovercard_user.mako')
def hovercard_username(self):
c = self.load_default_context()
username = self.request.matchdict['username']
c.user = User.get_by_username(username)
if not c.user:
raise HTTPNotFound()
return self._get_template_context(c)
@LoginRequired()
@view_config(
route_name='hovercard_user_group', request_method='GET', xhr=True,

View file

@ -66,11 +66,12 @@ markdown_tags = [
markdown_attrs = {
"*": ["class", "style", "align"],
"img": ["src", "alt", "title"],
"a": ["href", "alt", "title", "name"],
"a": ["href", "alt", "title", "name", "data-hovercard-alt", "data-hovercard-url"],
"abbr": ["title"],
"acronym": ["title"],
"pre": ["lang"],
"input": ["type", "disabled", "checked"]
"input": ["type", "disabled", "checked"],
"strong": ["title", "data-hovercard-alt", "data-hovercard-url"],
}
standard_styles = [

View file

@ -47,6 +47,14 @@ log = logging.getLogger(__name__)
# default renderer used to generate automated comments
DEFAULT_COMMENTS_RENDERER = 'rst'
try:
from lxml.html import fromstring
from lxml.html import tostring
except ImportError:
log.exception('Failed to import lxml')
fromstring = None
tostring = None
class CustomHTMLTranslator(writers.html4css1.HTMLTranslator):
"""
@ -81,11 +89,7 @@ def relative_links(html_source, server_paths):
if not html_source:
return html_source
try:
from lxml.html import fromstring
from lxml.html import tostring
except ImportError:
log.exception('Failed to import lxml')
if not fromstring and tostring:
return html_source
try:
@ -210,6 +214,8 @@ class MarkupRenderer(object):
URL_PAT = re.compile(r'(http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]'
r'|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+)')
MENTION_PAT = re.compile(MENTIONS_REGEX)
extensions = ['markdown.extensions.codehilite', 'markdown.extensions.extra',
'markdown.extensions.def_list', 'markdown.extensions.sane_lists']
@ -347,6 +353,26 @@ class MarkupRenderer(object):
return cls.URL_PAT.sub(url_func, text)
@classmethod
def convert_mentions(cls, text, mode):
mention_pat = cls.MENTION_PAT
def wrapp(match_obj):
uname = match_obj.groups()[0]
hovercard_url = "pyroutes.url('hovercard_username', {'username': '%s'});" % uname
if mode == 'markdown':
tmpl = '<strong class="tooltip-hovercard" data-hovercard-alt="{uname}" data-hovercard-url="{hovercard_url}">@{uname}</strong>'
elif mode == 'rst':
tmpl = ' **@{uname}** '
else:
raise ValueError('mode must be rst or markdown')
return tmpl.format(**{'uname': uname,
'hovercard_url': hovercard_url})
return mention_pat.sub(wrapp, text).strip()
@classmethod
def plain(cls, source, universal_newline=True, leading_newline=True):
source = safe_unicode(source)
@ -378,12 +404,7 @@ class MarkupRenderer(object):
cls.extensions, cls.output_format)
if mentions:
mention_pat = re.compile(MENTIONS_REGEX)
def wrapp(match_obj):
uname = match_obj.groups()[0]
return ' **@%(uname)s** ' % {'uname': uname}
mention_hl = mention_pat.sub(wrapp, source).strip()
mention_hl = cls.convert_mentions(source, mode='markdown')
# we extracted mentions render with this using Mentions false
return cls.markdown(mention_hl, safe=safe, flavored=flavored,
mentions=False)
@ -409,12 +430,7 @@ class MarkupRenderer(object):
@classmethod
def rst(cls, source, safe=True, mentions=False, clean_html=False):
if mentions:
mention_pat = re.compile(MENTIONS_REGEX)
def wrapp(match_obj):
uname = match_obj.groups()[0]
return ' **@%(uname)s** ' % {'uname': uname}
mention_hl = mention_pat.sub(wrapp, source).strip()
mention_hl = cls.convert_mentions(source, mode='rst')
# we extracted mentions render with this using Mentions false
return cls.rst(mention_hl, safe=safe, mentions=False)
@ -443,7 +459,7 @@ class MarkupRenderer(object):
except Exception:
log.exception('Error when rendering RST')
if safe:
log.debug('Fallbacking to render in plain mode')
log.debug('Fallback to render in plain mode')
return cls.plain(source)
else:
raise

View file

@ -87,6 +87,10 @@ body {
border-left: @border-thickness solid @border-default-color;
}
.cursor-pointer {
cursor: pointer;
}
input + .action-link, .action-link.first{
border-left: none;
}

View file

@ -31,6 +31,7 @@ function registerRCRoutes() {
pyroutes.register('repo_integrations_create', '/%(repo_name)s/settings/integrations/%(integration)s/new', ['repo_name', 'integration']);
pyroutes.register('repo_integrations_edit', '/%(repo_name)s/settings/integrations/%(integration)s/%(integration_id)s', ['repo_name', 'integration', 'integration_id']);
pyroutes.register('hovercard_user', '/_hovercard/user/%(user_id)s', ['user_id']);
pyroutes.register('hovercard_username', '/_hovercard/username/%(username)s', ['username']);
pyroutes.register('hovercard_user_group', '/_hovercard/user_group/%(user_group_id)s', ['user_group_id']);
pyroutes.register('hovercard_pull_request', '/_hovercard/pull_request/%(pull_request_id)s', ['pull_request_id']);
pyroutes.register('hovercard_repo_commit', '/_hovercard/commit/%(repo_name)s/%(commit_id)s', ['repo_name', 'commit_id']);

View file

@ -299,6 +299,10 @@ var tooltipActivate = function () {
var altHovercard =$origin.data('hovercardAlt');
if (hovercardUrl !== undefined && hovercardUrl !== "") {
if (hovercardUrl.substr(0,12) === 'pyroutes.url'){
hovercardUrl = eval(hovercardUrl)
}
var loaded = loadHoverCard(hovercardUrl, altHovercard, function (data) {
instance.content(data);
})