From e5803e1b41266b5298e050eebc611c15c267d6c7 Mon Sep 17 00:00:00 2001 From: Yingtong Li Date: Sun, 26 Jan 2020 17:58:47 +1100 Subject: [PATCH] Fork mdx_urlize, also urlize .au domains --- requirements.txt | 1 - selfserv/jinja2.py | 6 ++- selfserv/mdx_urlize.COPYING | 27 ++++++++++ selfserv/mdx_urlize.py | 101 ++++++++++++++++++++++++++++++++++++ 4 files changed, 132 insertions(+), 3 deletions(-) create mode 100644 selfserv/mdx_urlize.COPYING create mode 100644 selfserv/mdx_urlize.py diff --git a/requirements.txt b/requirements.txt index e0720cd..93656bf 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,4 +8,3 @@ google-api-python-client==1.7.7 django-ratelimit==2.0.0 boto3==1.9.86 premailer==3.2.0 -markdown-urlize==0.2.0 diff --git a/selfserv/jinja2.py b/selfserv/jinja2.py index 0567d70..3403b19 100644 --- a/selfserv/jinja2.py +++ b/selfserv/jinja2.py @@ -1,5 +1,5 @@ # Society Self-Service -# Copyright © 2018 Yingtong Li (RunasSudo) +# Copyright © 2018-2020 Yingtong Li (RunasSudo) # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by @@ -26,6 +26,8 @@ from jinja2 import Environment, Markup, select_autoescape import importlib +from .mdx_urlize import UrlizeExtension + def environment(**options): options['autoescape'] = select_autoescape( disabled_extensions=('txt',), @@ -42,6 +44,6 @@ def environment(**options): 'MEDIA_URL': settings.MEDIA_URL, }) env.filters.update({ - 'markdown': lambda x: Markup(markdown.markdown(x, extensions=['nl2br', 'mdx_urlize'])) + 'markdown': lambda x: Markup(markdown.markdown(x, extensions=['nl2br', UrlizeExtension()])) }) return env diff --git a/selfserv/mdx_urlize.COPYING b/selfserv/mdx_urlize.COPYING new file mode 100644 index 0000000..866963a --- /dev/null +++ b/selfserv/mdx_urlize.COPYING @@ -0,0 +1,27 @@ +This is a 2-clause BSD license (http://opensource.org/licenses/BSD-2-Clause) + +Copyright (c) 2014 Rowan Nairn +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/selfserv/mdx_urlize.py b/selfserv/mdx_urlize.py new file mode 100644 index 0000000..8a614df --- /dev/null +++ b/selfserv/mdx_urlize.py @@ -0,0 +1,101 @@ +# Society Self-Service +# Copyright © 2018-2020 Yingtong Li (RunasSudo) +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 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 Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +# Adapted from: +# Copyright (c) 2014 Rowan Nairn. All rights reserved. Licensed under the 2-clause BSD licence +# https://github.com/r0wb0t/markdown-urlize + +"""A more liberal autolinker + +Inspired by Django's urlize function. + +Positive examples: + +>>> import markdown +>>> md = markdown.Markdown(extensions=['urlize']) + +>>> md.convert('http://example.com/') +u'

http://example.com/

' + +>>> md.convert('go to http://example.com') +u'

go to http://example.com

' + +>>> md.convert('example.com') +u'

example.com

' + +>>> md.convert('example.net') +u'

example.net

' + +>>> md.convert('www.example.us') +u'

www.example.us

' + +>>> md.convert('(www.example.us/path/?name=val)') +u'

(www.example.us/path/?name=val)

' + +>>> md.convert('go to now!') +u'

go to http://example.com now!

' + +Negative examples: + +>>> md.convert('del.icio.us') +u'

del.icio.us

' + +""" + +import markdown + +# Global Vars +URLIZE_RE = '(%s)' % '|'.join([ + r'<(?:f|ht)tps?://[^>]*>', + r'\b(?:f|ht)tps?://[^)<>\s]+[^.,)<>\s]', + r'\bwww\.[^)<>\s]+[^.,)<>\s]', + r'[^(<\s]+\.(?:(?:com|net|org)(?:\.au)?)\b', +]) + +class UrlizePattern(markdown.inlinepatterns.Pattern): + """ Return a link Element given an autolink (`http://example/com`). """ + def handleMatch(self, m): + url = m.group(2) + + if url.startswith('<'): + url = url[1:-1] + + text = url + + if not url.split('://')[0] in ('http','https','ftp'): + if '@' in url and not '/' in url: + url = 'mailto:' + url + else: + url = 'http://' + url + + el = markdown.util.etree.Element("a") + el.set('href', url) + el.text = markdown.util.AtomicString(text) + return el + +class UrlizeExtension(markdown.Extension): + """ Urlize Extension for Python-Markdown. """ + + def extendMarkdown(self, md, md_globals): + """ Replace autolink with UrlizePattern """ + md.inlinePatterns['autolink'] = UrlizePattern(URLIZE_RE, md) + +def makeExtension(*args, **kwargs): + return UrlizeExtension(*args, **kwargs) + +if __name__ == "__main__": + import doctest + doctest.testmod()