From 0e685e809181031c29414fb8168a4dd37266f57f Mon Sep 17 00:00:00 2001 From: Ralph Bean Date: Mar 26 2015 14:48:10 +0000 Subject: Merge #73 `Pagure-flavored markdown` --- diff --git a/pagure/__init__.py b/pagure/__init__.py index 1910fd9..090b053 100644 --- a/pagure/__init__.py +++ b/pagure/__init__.py @@ -343,6 +343,10 @@ def get_repo_path(repo): return repopath +# Install our markdown modifications +import pagure.pfmarkdown +pagure.pfmarkdown.inject() + # Import the application import pagure.ui.app import pagure.ui.admin diff --git a/pagure/pfmarkdown.py b/pagure/pfmarkdown.py new file mode 100644 index 0000000..d963835 --- /dev/null +++ b/pagure/pfmarkdown.py @@ -0,0 +1,137 @@ +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +# USA. + +""" Pagure-flavored Markdown + +Author: Ralph Bean +""" + +import flask + +import markdown.inlinepatterns +import markdown.util + +import pagure +import pagure.lib + + +def inject(): + """ Hack out python-markdown to do the autolinking that we want. """ + + # First, make it so that bare links get automatically linkified. + markdown.inlinepatterns.AUTOLINK_RE = '(%s)' % '|'.join([ + r'<(?:f|ht)tps?://[^>]*>', + r'\b(?:f|ht)tps?://[^)<>\s]+[^.,)<>\s]', + r'\bwww\.[^)<>\s]+[^.,)<>\s]', + r'[^(<\s]+\.(?:com|net|org)\b', + ]) + + # Second, build some Pattern objects for @mentions, #bugs, etc... + class MentionPattern(markdown.inlinepatterns.Pattern): + def handleMatch(self, m): + name = markdown.util.AtomicString(m.group(2)) + text = ' @%s' % name + user = pagure.lib.search_user(pagure.SESSION, username=name) + if not user: + return text + + el = markdown.util.etree.Element("a") + url = flask.url_for('view_user', username=name) + el.set('href', url) + el.text = text + return el + + class ExplicitForkIssuePattern(markdown.inlinepatterns.Pattern): + def handleMatch(self, m): + user = markdown.util.AtomicString(m.group(2)) + repo = markdown.util.AtomicString(m.group(3)) + idx = markdown.util.AtomicString(m.group(4)) + text = '%s/%s#%s' % (user, repo, idx) + + if not _issue_exists(user, repo, idx): + return text + + return _issue_anchor_tag(user, repo, idx, text) + + class ExplicitMainIssuePattern(markdown.inlinepatterns.Pattern): + def handleMatch(self, m): + repo = markdown.util.AtomicString(m.group(2)) + idx = markdown.util.AtomicString(m.group(3)) + text = ' %s#%s' % (repo, idx) + + if not _issue_exists(None, repo, idx): + return text + + return _issue_anchor_tag(None, repo, idx, text) + + class ImplicitIssuePattern(markdown.inlinepatterns.Pattern): + def handleMatch(self, m): + idx = markdown.util.AtomicString(m.group(2)) + text = ' #%s' % idx + + root = flask.request.url_root + url = flask.request.url + user = None + if 'fork/' in flask.request.url: + user, repo = url.split('fork/')[1].split('/', 2)[:2] + else: + repo = url.split(root)[1].split('/', 1)[0] + + if not _issue_exists(user, repo, idx): + return text + + return _issue_anchor_tag(user, repo, idx, text) + + MENTION_RE = r'[^|\w]@(\w+)' + EXPLICIT_FORK_ISSUE_RE = r'(\w+)/(\w+)#([0-9]+)' + EXPLICIT_MAIN_ISSUE_RE = r'[^|\w](?
{% autoescape false %} - {{ content | crossref | markdown }} + {{ content | markdown }} {% endautoescape %}
diff --git a/pagure/ui/filters.py b/pagure/ui/filters.py index 2e9d9f6..137c7be 100644 --- a/pagure/ui/filters.py +++ b/pagure/ui/filters.py @@ -189,36 +189,6 @@ def shorted_commit(cid): return cid[:APP.config['SHORT_LENGTH']] -@APP.template_filter('crossref') -def crossref_filter(text): - """ Template filter adding a link when the provided text references - another issue or pull-request. - """ - regex = re.compile('.*\s#(\d+)', re.I) - if text: - if regex.match(text): - - url = flask.request.url - username = None - if 'fork/' in flask.request.url: - username, project = url.split('fork/')[1].split('/', 2)[:2] - else: - project = url.split( - flask.request.url_root)[1].split('/', 1)[0] - - issueid = regex.match(text).group(1) - text = text.replace('#%s' % issueid, '[#%s](%s)' % ( - issueid, flask.url_for( - 'view_issue', username=username, repo=project, - issueid=issueid) - ) - ) - - return text - else: - return '' - - @APP.template_filter('markdown') def markdown_filter(text): """ Template filter converting a string into html content using the @@ -228,21 +198,7 @@ def markdown_filter(text): # Hack to allow blockquotes to be marked by ~~~ ntext = [] indent = False - regexes = [ - re.compile('.*\s(http(s)?:\/\/\S+).*'), - re.compile('^(http(s)?:\/\/\S+).*'), - re.compile('.*\s(ftp(s)?:\/\/\S+).*'), - re.compile('^(ftp(s)?:\/\/\S+).*'), - ] for line in text.split('\n'): - # Automatically link URLs - for regex in regexes: - if regex.match(line): - line = line.replace( - regex.match(line).group(1), - regex.sub(r'<\1>', line) - ) - if line.startswith('~~~'): indent = not indent continue