M src/wiki/plugins/redlinks/mdx/redlinks.py => src/wiki/plugins/redlinks/mdx/redlinks.py +14 -2
@@ 1,6 1,8 @@
+import html
from urllib.parse import urljoin, urlparse
from markdown.extensions import Extension
+from markdown.postprocessors import AndSubstitutePostprocessor
from markdown.treeprocessors import Treeprocessor
from wiki.models import URLPath
@@ 48,11 50,21 @@ class LinkTreeprocessor(Treeprocessor):
return self._my_urlpath
def get_class(self, el):
+ href = el.get("href")
+ if not href:
+ return
+ # The autolinker turns email links into links with many HTML entities.
+ # These entities are further escaped using markdown-specific codes.
+ # First unescape the markdown-specific, then use html.unescape.
+ href = AndSubstitutePostprocessor().run(href)
+ href = html.unescape(href)
try:
- url = urlparse(el.get("href"))
+ url = urlparse(href)
except ValueError:
return
- if url.netloc or url.path.startswith("/"):
+ if url.scheme == "mailto":
+ return
+ if url.scheme or url.netloc or url.path.startswith("/"):
# Contains a hostname or is an absolute link => external
return self.external_class
# Ensure that path ends with a slash
M tests/plugins/redlinks/test_redlinks.py => tests/plugins/redlinks/test_redlinks.py +9 -0
@@ 52,3 52,12 @@ class RedlinksTests(RequireRootArticleMixin, TestBase):
self.assertNotIn("wiki-internal", html)
self.assertNotIn("wiki-external", html)
self.assertIn("wiki-broken", html)
+
+ def test_mailto(self):
+ md = markdown.ArticleMarkdown(article=self.root.article)
+ md_text = "<foo@example.com>"
+ html = md.convert(md_text)
+ self.assertNotIn("wiki-internal", html)
+ self.assertNotIn("wiki-external", html)
+ self.assertNotIn("wiki-broken", html)
+ self.assertIn("<a ", html)