Markdown code blocks expand ticket mentions into full HTML links. I.e. putting #1
into a multi-line code block will result in the following:
<a href="/~sircmpwn/todo.sr.ht/1" title="~sircmpwn/todo.sr.ht#1: Login redirect doesn't return to the previous page">#1</a>
See below for the current live behavior:
<a href="/~sircmpwn/todo.sr.ht/1" title="~sircmpwn/todo.sr.ht#1: Login redirect doesn't return to the previous page">#1</a>
From #236:
We can fix this by detecting that an inner token from a URL (
Link
) is an email (PlainLink
withmailto == True
), then rendering the email as text. Test is in patch, using your example and each part separately renders fine. Adding extraneous HTML to the email text seems to be filtered, but there might be a safer way thanrender_raw_text
.
This is performed by
render_markup
andurlize_ticket
in todosrht/filters.py: https://git.sr.ht/~sircmpwn/todo.sr.ht/tree/master/item/todosrht/filters.pyIt looks like this is actually going to be a bit painful to fix, because the idea of what ticket/user mentions are in a comment is not computed by a real parser at markdown parse time, but with regex prior to it: see
USER_MENTION_PATTERN
andTICKET_MENTION_PATTERN
here: https://git.sr.ht/~sircmpwn/todo.sr.ht/tree/master/item/todosrht/tickets.pyIt seems like it may actually be possible to use these regexes to define new tokens in the actual markdown renderer itself (
SrhtRenderer
, which inherits frommistletoe.HtmlRenderer
): see the docs at https://github.com/miyuchina/mistletoe/blob/master/mistletoe/base_renderer.pyAccording to those docs, it looks like we can "add additional tokens into the parsing process by passing custom tokens to
super().__init__()
" and "add additional render functions by appending toself.render_map
". The latter seems to happen implicitly based on method name.So
SrhtRenderer
would do something like:class TicketMention(SpanToken): """ Ticket mention ("[[~user/]tracker]#123") This is an inline token with a single child of type RawText. """ pattern = re.compile(TICKET_MENTION_PATTERN) parse_inner = False parse_group = 0 def __init__(self, match): content = match.group(self.parse_group) self.delimiter = match.group(1) self.padding = " " if not content.isspace() and content.startswith(" ") and content.endswith(" ") else "" self.children = (RawText(content),) @classmethod def find(cls, string): matches = core_tokens._code_matches core_tokens._code_matches = [] return matchesand
# this is basically just `urlize_ticket` def render_ticket_mention(self, token): text = token.match.group(0) ticket_id = token.match.group('ticket_id') tracker_name = token.match.group('tracker_name') or tracker.name owner = token.match.group('username') or tracker.owner.username ticket_ref = f"~{owner}/{tracker_name}#{ticket_id}" if ticket_ref not in tickets_map: return text ticket = tickets_map[ticket_ref] url = urls.ticket_url(ticket) title = escape(f"{ticket.ref()}: {ticket.title}") return f'<a href="{url}" title="{title}">{text}</a>'I haven't tested this code, but I think it's within debugging distance of something that would work.
This also requires plumbing
tracker
, andtickets_map
down throughsrht.markdown
and intoSrhtRenderer
so that we can use them in therender_ticket_mention
method. The same should be done for user mentions andurlize_users
.