''' PClinks Extension for Python-Markdown ====================================== Converts [[type:id]] to relative links. Based on . Original code Copyright [Waylan Limberg](http://achinghead.com/). License: [BSD](https://opensource.org/licenses/bsd-license.php) ''' from markdown.extensions import Extension from markdown.inlinepatterns import InlineProcessor import xml.etree.ElementTree as etree from flask import url_for, render_template from app.utils.unicode_names import normalize from app.models.poll import Poll from app.models.topic import Topic from app.models.user import Member class PCLinkExtension(Extension): def __init__(self, **kwargs): self.config = { # 'base_url': ['/', 'String to append to beginning or URL.'], # 'end_url': ['/', 'String to append to end of URL.'], # 'html_class': ['pclink', 'CSS hook. Leave blank for none.'], } super().__init__(**kwargs) def extendMarkdown(self, md): self.md = md # append to end of inline patterns PCLINK_RE = r'\[\[([a-z]+): ?(\w+)\]\]' pclinkPattern = PCLinksInlineProcessor(PCLINK_RE, self.getConfigs()) pclinkPattern.md = md md.inlinePatterns.register(pclinkPattern, 'pclink', 75) class PCLinksInlineProcessor(InlineProcessor): def __init__(self, pattern, config): super().__init__(pattern) self.config = config self.handles = { 'membre': handleUser, 'user': handleUser, 'u': handleUser, 'sondage': handlePoll, 'poll': handlePoll, 'topic': handleTopic, 't': handleTopic, } def handleMatch(self, m, data): link_type = m.group(1).strip() if link_type in self.handles: content_id = m.group(2).strip() a = self.handles[link_type](content_id, data) else: a = '' return a, m.start(0), m.end(0) # pclinks are links defined as [[type:content_id]] # To add a custom handle, create a function and add it to processor's handles # A custom handle takes two arguments: # - content_id: as defined # - context: the block in which the link has been found # It should return: # - either a string, which will be html-escaped # - either an xml.etree.ElementTree def handlePoll(content_id, context): if not context.startswith("[[") or not context.endswith("]]"): return "[Sondage invalide]" try: id = int(content_id) except ValueError: return "[ID du sondage invalide]" poll = Poll.query.get(content_id) if poll is None: return "[Sondage non trouvé]" html = render_template('widgets/poll.html', poll=poll) html = html.replace('\n', '') # Needed to avoid lots of
due to etree return etree.fromstring(html) def handleTopic(content_id, context): try: id = int(content_id) except ValueError: return "[ID du topic invalide]" topic = Topic.query.get(content_id) if topic is None: return "[Topic non trouvé]" a = etree.Element('a') a.text = topic.title a.set('href', url_for('forum_topic', f=topic.forum, page=(topic,1))) a.set('class', 'topic-link') return a def handleUser(content_id, context): try: norm = normalize(content_id) except ValueError: return "[Nom d'utilisateur invalide]" member = Member.query.filter_by(norm=norm).first() if member is None: return "[Utilisateur non trouvé]" a = etree.Element('a') a.text = member.name a.set('href', url_for('user', username=member.norm)) a.set('class', 'profile-link') return a