Multi-line markdown code blocks render expand ticket mentions

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&#39;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&#39;t return to the previous page">#1</a>
Assigned to
3 years ago
6 months ago
No labels applied.

~alextee closed duplicate ticket #237 3 years ago

~devdanzin 3 years ago

From #236:

We can fix this by detecting that an inner token from a URL (Link) is an email (PlainLink with mailto == 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 than render_raw_text.

~anteater 6 months ago

This is performed by render_markup and urlize_ticket in todosrht/filters.py: https://git.sr.ht/~sircmpwn/todo.sr.ht/tree/master/item/todosrht/filters.py

It 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 and TICKET_MENTION_PATTERN here: https://git.sr.ht/~sircmpwn/todo.sr.ht/tree/master/item/todosrht/tickets.py

It seems like it may actually be possible to use these regexes to define new tokens in the actual markdown renderer itself (SrhtRenderer, which inherits from mistletoe.HtmlRenderer): see the docs at https://github.com/miyuchina/mistletoe/blob/master/mistletoe/base_renderer.py

According 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 to self.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),)

    def find(cls, string):
        matches = core_tokens._code_matches
        core_tokens._code_matches = []
        return matches


# 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, and tickets_map down through srht.markdown and into SrhtRenderer so that we can use them in the render_ticket_mention method. The same should be done for user mentions and urlize_users.

Register here or Log in to comment, or comment via email.