Show More
@@ -26,6 +26,10 b' def includeme(config):' | |||
|
26 | 26 | pattern='/_hovercard/user/{user_id}') |
|
27 | 27 | |
|
28 | 28 | config.add_route( |
|
29 | name='hovercard_username', | |
|
30 | pattern='/_hovercard/username/{username}') | |
|
31 | ||
|
32 | config.add_route( | |
|
29 | 33 | name='hovercard_user_group', |
|
30 | 34 | pattern='/_hovercard/user_group/{user_group_id}') |
|
31 | 35 |
@@ -65,6 +65,19 b' class HoverCardsView(BaseAppView):' | |||
|
65 | 65 | |
|
66 | 66 | @LoginRequired() |
|
67 | 67 | @view_config( |
|
68 | route_name='hovercard_username', request_method='GET', xhr=True, | |
|
69 | renderer='rhodecode:templates/hovercards/hovercard_user.mako') | |
|
70 | def hovercard_username(self): | |
|
71 | c = self.load_default_context() | |
|
72 | username = self.request.matchdict['username'] | |
|
73 | c.user = User.get_by_username(username) | |
|
74 | if not c.user: | |
|
75 | raise HTTPNotFound() | |
|
76 | ||
|
77 | return self._get_template_context(c) | |
|
78 | ||
|
79 | @LoginRequired() | |
|
80 | @view_config( | |
|
68 | 81 | route_name='hovercard_user_group', request_method='GET', xhr=True, |
|
69 | 82 | renderer='rhodecode:templates/hovercards/hovercard_user_group.mako') |
|
70 | 83 | def hovercard_user_group(self): |
@@ -66,11 +66,12 b' markdown_tags = [' | |||
|
66 | 66 | markdown_attrs = { |
|
67 | 67 | "*": ["class", "style", "align"], |
|
68 | 68 | "img": ["src", "alt", "title"], |
|
69 | "a": ["href", "alt", "title", "name"], | |
|
69 | "a": ["href", "alt", "title", "name", "data-hovercard-alt", "data-hovercard-url"], | |
|
70 | 70 | "abbr": ["title"], |
|
71 | 71 | "acronym": ["title"], |
|
72 | 72 | "pre": ["lang"], |
|
73 | "input": ["type", "disabled", "checked"] | |
|
73 | "input": ["type", "disabled", "checked"], | |
|
74 | "strong": ["title", "data-hovercard-alt", "data-hovercard-url"], | |
|
74 | 75 | } |
|
75 | 76 | |
|
76 | 77 | standard_styles = [ |
@@ -47,6 +47,14 b' log = logging.getLogger(__name__)' | |||
|
47 | 47 | # default renderer used to generate automated comments |
|
48 | 48 | DEFAULT_COMMENTS_RENDERER = 'rst' |
|
49 | 49 | |
|
50 | try: | |
|
51 | from lxml.html import fromstring | |
|
52 | from lxml.html import tostring | |
|
53 | except ImportError: | |
|
54 | log.exception('Failed to import lxml') | |
|
55 | fromstring = None | |
|
56 | tostring = None | |
|
57 | ||
|
50 | 58 | |
|
51 | 59 | class CustomHTMLTranslator(writers.html4css1.HTMLTranslator): |
|
52 | 60 | """ |
@@ -81,11 +89,7 b' def relative_links(html_source, server_p' | |||
|
81 | 89 | if not html_source: |
|
82 | 90 | return html_source |
|
83 | 91 | |
|
84 | try: | |
|
85 | from lxml.html import fromstring | |
|
86 | from lxml.html import tostring | |
|
87 | except ImportError: | |
|
88 | log.exception('Failed to import lxml') | |
|
92 | if not fromstring and tostring: | |
|
89 | 93 | return html_source |
|
90 | 94 | |
|
91 | 95 | try: |
@@ -210,6 +214,8 b' class MarkupRenderer(object):' | |||
|
210 | 214 | URL_PAT = re.compile(r'(http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]' |
|
211 | 215 | r'|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+)') |
|
212 | 216 | |
|
217 | MENTION_PAT = re.compile(MENTIONS_REGEX) | |
|
218 | ||
|
213 | 219 | extensions = ['markdown.extensions.codehilite', 'markdown.extensions.extra', |
|
214 | 220 | 'markdown.extensions.def_list', 'markdown.extensions.sane_lists'] |
|
215 | 221 | |
@@ -348,6 +354,26 b' class MarkupRenderer(object):' | |||
|
348 | 354 | return cls.URL_PAT.sub(url_func, text) |
|
349 | 355 | |
|
350 | 356 | @classmethod |
|
357 | def convert_mentions(cls, text, mode): | |
|
358 | mention_pat = cls.MENTION_PAT | |
|
359 | ||
|
360 | def wrapp(match_obj): | |
|
361 | uname = match_obj.groups()[0] | |
|
362 | hovercard_url = "pyroutes.url('hovercard_username', {'username': '%s'});" % uname | |
|
363 | ||
|
364 | if mode == 'markdown': | |
|
365 | tmpl = '<strong class="tooltip-hovercard" data-hovercard-alt="{uname}" data-hovercard-url="{hovercard_url}">@{uname}</strong>' | |
|
366 | elif mode == 'rst': | |
|
367 | tmpl = ' **@{uname}** ' | |
|
368 | else: | |
|
369 | raise ValueError('mode must be rst or markdown') | |
|
370 | ||
|
371 | return tmpl.format(**{'uname': uname, | |
|
372 | 'hovercard_url': hovercard_url}) | |
|
373 | ||
|
374 | return mention_pat.sub(wrapp, text).strip() | |
|
375 | ||
|
376 | @classmethod | |
|
351 | 377 | def plain(cls, source, universal_newline=True, leading_newline=True): |
|
352 | 378 | source = safe_unicode(source) |
|
353 | 379 | if universal_newline: |
@@ -378,12 +404,7 b' class MarkupRenderer(object):' | |||
|
378 | 404 | cls.extensions, cls.output_format) |
|
379 | 405 | |
|
380 | 406 | if mentions: |
|
381 | mention_pat = re.compile(MENTIONS_REGEX) | |
|
382 | ||
|
383 | def wrapp(match_obj): | |
|
384 | uname = match_obj.groups()[0] | |
|
385 | return ' **@%(uname)s** ' % {'uname': uname} | |
|
386 | mention_hl = mention_pat.sub(wrapp, source).strip() | |
|
407 | mention_hl = cls.convert_mentions(source, mode='markdown') | |
|
387 | 408 | # we extracted mentions render with this using Mentions false |
|
388 | 409 | return cls.markdown(mention_hl, safe=safe, flavored=flavored, |
|
389 | 410 | mentions=False) |
@@ -409,12 +430,7 b' class MarkupRenderer(object):' | |||
|
409 | 430 | @classmethod |
|
410 | 431 | def rst(cls, source, safe=True, mentions=False, clean_html=False): |
|
411 | 432 | if mentions: |
|
412 | mention_pat = re.compile(MENTIONS_REGEX) | |
|
413 | ||
|
414 | def wrapp(match_obj): | |
|
415 | uname = match_obj.groups()[0] | |
|
416 | return ' **@%(uname)s** ' % {'uname': uname} | |
|
417 | mention_hl = mention_pat.sub(wrapp, source).strip() | |
|
433 | mention_hl = cls.convert_mentions(source, mode='rst') | |
|
418 | 434 | # we extracted mentions render with this using Mentions false |
|
419 | 435 | return cls.rst(mention_hl, safe=safe, mentions=False) |
|
420 | 436 | |
@@ -443,7 +459,7 b' class MarkupRenderer(object):' | |||
|
443 | 459 | except Exception: |
|
444 | 460 | log.exception('Error when rendering RST') |
|
445 | 461 | if safe: |
|
446 |
log.debug('Fallback |
|
|
462 | log.debug('Fallback to render in plain mode') | |
|
447 | 463 | return cls.plain(source) |
|
448 | 464 | else: |
|
449 | 465 | raise |
@@ -87,6 +87,10 b' body {' | |||
|
87 | 87 | border-left: @border-thickness solid @border-default-color; |
|
88 | 88 | } |
|
89 | 89 | |
|
90 | .cursor-pointer { | |
|
91 | cursor: pointer; | |
|
92 | } | |
|
93 | ||
|
90 | 94 | input + .action-link, .action-link.first{ |
|
91 | 95 | border-left: none; |
|
92 | 96 | } |
@@ -31,6 +31,7 b' function registerRCRoutes() {' | |||
|
31 | 31 | pyroutes.register('repo_integrations_create', '/%(repo_name)s/settings/integrations/%(integration)s/new', ['repo_name', 'integration']); |
|
32 | 32 | pyroutes.register('repo_integrations_edit', '/%(repo_name)s/settings/integrations/%(integration)s/%(integration_id)s', ['repo_name', 'integration', 'integration_id']); |
|
33 | 33 | pyroutes.register('hovercard_user', '/_hovercard/user/%(user_id)s', ['user_id']); |
|
34 | pyroutes.register('hovercard_username', '/_hovercard/username/%(username)s', ['username']); | |
|
34 | 35 | pyroutes.register('hovercard_user_group', '/_hovercard/user_group/%(user_group_id)s', ['user_group_id']); |
|
35 | 36 | pyroutes.register('hovercard_pull_request', '/_hovercard/pull_request/%(pull_request_id)s', ['pull_request_id']); |
|
36 | 37 | pyroutes.register('hovercard_repo_commit', '/_hovercard/commit/%(repo_name)s/%(commit_id)s', ['repo_name', 'commit_id']); |
@@ -299,6 +299,10 b' var tooltipActivate = function () {' | |||
|
299 | 299 | var altHovercard =$origin.data('hovercardAlt'); |
|
300 | 300 | |
|
301 | 301 | if (hovercardUrl !== undefined && hovercardUrl !== "") { |
|
302 | if (hovercardUrl.substr(0,12) === 'pyroutes.url'){ | |
|
303 | hovercardUrl = eval(hovercardUrl) | |
|
304 | } | |
|
305 | ||
|
302 | 306 | var loaded = loadHoverCard(hovercardUrl, altHovercard, function (data) { |
|
303 | 307 | instance.content(data); |
|
304 | 308 | }) |
General Comments 0
You need to be logged in to leave comments.
Login now