diff --git a/wiki/core/__init__.py b/wiki/core/__init__.py index 35ebe5526..7bc7846a5 100644 --- a/wiki/core/__init__.py +++ b/wiki/core/__init__.py @@ -1,6 +1,7 @@ import markdown import bleach + class ArticleMarkdown(markdown.Markdown): def __init__(self, article, *args, **kwargs): diff --git a/wiki/core/extensions.py b/wiki/core/extensions.py new file mode 100644 index 000000000..f93833506 --- /dev/null +++ b/wiki/core/extensions.py @@ -0,0 +1,12 @@ +from markdown.extensions import Extension + +from .processors import AnchorTagProcessor + + +class AnchorTagExtension(Extension): + """ + Custom extension to register anchor tag processor with Markdown. + """ + + def extendMarkdown(self, md, md_globals): + md.treeprocessors.add('AnchorTagProcessor', AnchorTagProcessor(md), '>inline') diff --git a/wiki/core/processors.py b/wiki/core/processors.py new file mode 100644 index 000000000..d1b00a8e6 --- /dev/null +++ b/wiki/core/processors.py @@ -0,0 +1,19 @@ +from markdown.treeprocessors import Treeprocessor + + +class AnchorTagProcessor(Treeprocessor): + """ + Custom treeprocessor to process the anchor tags in the HTML tree + """ + + def run(self, root): + anchor_tags = root.findall('.//a') + for a_tag in anchor_tags: + if not self.is_href_valid(a_tag.get('href')): + a_tag.set('href', '#') + + def is_href_valid(self, value): + """ + After mark down, validate if the JS is present inside the value of anchor tag. + """ + return not value.lower().startswith('javascript:') diff --git a/wiki/models/article.py b/wiki/models/article.py index 8c9dbdc96..4cb7de5a6 100644 --- a/wiki/models/article.py +++ b/wiki/models/article.py @@ -10,6 +10,7 @@ from wiki.conf import settings from wiki.core import article_markdown, permissions +from wiki.core.extensions import AnchorTagExtension from wiki.core.plugins import registry as plugin_registry from wiki import managers from mptt.models import MPTTModel @@ -188,7 +189,7 @@ def render(self, preview_content=None): else: content = self.current_revision.content extensions = plugin_registry.get_markdown_extensions() - extensions += settings.MARKDOWN_EXTENSIONS + extensions += settings.MARKDOWN_EXTENSIONS + [AnchorTagExtension()] return mark_safe(article_markdown(content, self, extensions=extensions))