diff --git a/taiga/mdrender/extensions/autolink.py b/taiga/mdrender/extensions/autolink.py index 1dbf2b98..7faeb930 100644 --- a/taiga/mdrender/extensions/autolink.py +++ b/taiga/mdrender/extensions/autolink.py @@ -6,6 +6,7 @@ import re import markdown + # We can't re-use the built-in AutolinkPattern because we need to add protocols # to links without them. class AutolinkPattern(markdown.inlinepatterns.Pattern): @@ -20,6 +21,7 @@ class AutolinkPattern(markdown.inlinepatterns.Pattern): el.text = markdown.util.AtomicString(m.group(2)) return el + class AutolinkExtension(markdown.Extension): """An extension that turns all URLs into links. diff --git a/taiga/mdrender/extensions/automail.py b/taiga/mdrender/extensions/automail.py index f8c65f77..7c98520c 100644 --- a/taiga/mdrender/extensions/automail.py +++ b/taiga/mdrender/extensions/automail.py @@ -3,9 +3,9 @@ # for details. All rights reserved. Use of this source code is governed by a # BSD-style license that can be found in the LICENSE file. -import re import markdown + # We can't re-use the built-in AutomailPattern because we need to add mailto:. # We also don't care about HTML-encoding the email. class AutomailPattern(markdown.inlinepatterns.Pattern): @@ -15,6 +15,7 @@ class AutomailPattern(markdown.inlinepatterns.Pattern): el.text = markdown.util.AtomicString(m.group(2)) return el + class AutomailExtension(markdown.Extension): """An extension that turns all email addresses into links.""" diff --git a/taiga/mdrender/extensions/emojify.py b/taiga/mdrender/extensions/emojify.py index c7b4a19c..502b0495 100644 --- a/taiga/mdrender/extensions/emojify.py +++ b/taiga/mdrender/extensions/emojify.py @@ -1,4 +1,4 @@ -#-*- coding: utf-8 -*- +# -*- coding: utf-8 -*- # Tested on Markdown 2.3.1 # @@ -26,7 +26,6 @@ import re -import os from markdown.extensions import Extension from markdown.preprocessors import Preprocessor @@ -167,7 +166,7 @@ class EmojifyPreprocessor(Preprocessor): def emojify(match): emoji = match.group(1) - if not emoji in emojis_set: + if emoji not in emojis_set: return match.group(0) url = emojis_path + emoji + u'.png' diff --git a/taiga/mdrender/extensions/mentions.py b/taiga/mdrender/extensions/mentions.py index f826b577..37468f66 100644 --- a/taiga/mdrender/extensions/mentions.py +++ b/taiga/mdrender/extensions/mentions.py @@ -1,4 +1,4 @@ -#-*- coding: utf-8 -*- +# -*- coding: utf-8 -*- # Tested on Markdown 2.3.1 # @@ -23,10 +23,6 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. - -import re -import os - from markdown.extensions import Extension from markdown.inlinepatterns import Pattern from markdown.util import etree @@ -39,9 +35,7 @@ class MentionsExtension(Extension): MENTION_RE = r'(?<=^|(?<=[^a-zA-Z0-9-_\.]))@([A-Za-z]+[A-Za-z0-9-]+)' mentionsPattern = MentionsPattern(MENTION_RE) mentionsPattern.md = md - md.inlinePatterns.add('mentions', - mentionsPattern, - '_begin') + md.inlinePatterns.add('mentions', mentionsPattern, '_begin') class MentionsPattern(Pattern): diff --git a/taiga/mdrender/extensions/references.py b/taiga/mdrender/extensions/references.py index eed3db3e..4861270a 100644 --- a/taiga/mdrender/extensions/references.py +++ b/taiga/mdrender/extensions/references.py @@ -1,4 +1,4 @@ -#-*- coding: utf-8 -*- +# -*- coding: utf-8 -*- # Tested on Markdown 2.3.1 # @@ -23,10 +23,6 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. - -import re -import os - from markdown.extensions import Extension from markdown.inlinepatterns import Pattern from markdown.util import etree @@ -43,9 +39,8 @@ class TaigaReferencesExtension(Extension): TAIGA_REFERENCE_RE = r'(?<=^|(?<=[^a-zA-Z0-9-\[]))#(\d+)' referencesPattern = TaigaReferencesPattern(TAIGA_REFERENCE_RE, self.project) referencesPattern.md = md - md.inlinePatterns.add('taiga-references', - referencesPattern, - '_begin') + md.inlinePatterns.add('taiga-references', referencesPattern, '_begin') + class TaigaReferencesPattern(Pattern): def __init__(self, pattern, project): @@ -73,7 +68,6 @@ class TaigaReferencesPattern(Pattern): else: return "#{}".format(obj_ref) - url = "/#/project/{}/{}/{}".format( self.project.slug, obj_section, diff --git a/taiga/mdrender/extensions/semi_sane_lists.py b/taiga/mdrender/extensions/semi_sane_lists.py index 477b8ef7..7eba07e7 100644 --- a/taiga/mdrender/extensions/semi_sane_lists.py +++ b/taiga/mdrender/extensions/semi_sane_lists.py @@ -2,15 +2,17 @@ # for details. All rights reserved. Use of this source code is governed by a # BSD-style license that can be found in the LICENSE file. -import re import markdown + class SemiSaneOListProcessor(markdown.blockprocessors.OListProcessor): SIBLING_TAGS = ['ol'] + class SemiSaneUListProcessor(markdown.blockprocessors.UListProcessor): SIBLING_TAGS = ['ul'] + class SemiSaneListExtension(markdown.Extension): """An extension that causes lists to be treated the same way GitHub does. diff --git a/taiga/mdrender/extensions/spaced_link.py b/taiga/mdrender/extensions/spaced_link.py index c0d08d09..7f619cdb 100644 --- a/taiga/mdrender/extensions/spaced_link.py +++ b/taiga/mdrender/extensions/spaced_link.py @@ -20,6 +20,7 @@ SPACED_IMAGE_LINK_RE = markdown.inlinepatterns.IMAGE_LINK_RE.replace( SPACED_IMAGE_REFERENCE_RE = markdown.inlinepatterns.IMAGE_REFERENCE_RE.replace( r'\!' + BRK, r'\!' + BRK + SPACE) + class SpacedLinkExtension(markdown.Extension): """An extension that supports links and images with additional whitespace. diff --git a/taiga/mdrender/extensions/strikethrough.py b/taiga/mdrender/extensions/strikethrough.py index eabf87d2..c00a09d7 100644 --- a/taiga/mdrender/extensions/strikethrough.py +++ b/taiga/mdrender/extensions/strikethrough.py @@ -4,7 +4,8 @@ import markdown -STRIKE_RE = r'(~{2})(.+?)(~{2})' # ~~strike~~ +STRIKE_RE = r'(~{2})(.+?)(~{2})' # ~~strike~~ + class StrikethroughExtension(markdown.Extension): """An extension that supports PHP-Markdown style strikethrough. diff --git a/taiga/mdrender/extensions/wikilinks.py b/taiga/mdrender/extensions/wikilinks.py index 25a9d4d7..ea5cd3f9 100644 --- a/taiga/mdrender/extensions/wikilinks.py +++ b/taiga/mdrender/extensions/wikilinks.py @@ -5,20 +5,21 @@ from markdown.inlinepatterns import Pattern from markdown.util import etree import re + def build_url(label, base, end): """ Build a url from the label, a base, and an end. """ clean_label = re.sub(r'([ ]+_)|(_[ ]+)|([ ]+)', '_', label) - return '%s%s%s'% (base, clean_label, end) + return '%s%s%s' % (base, clean_label, end) class WikiLinkExtension(Extension): def __init__(self, configs): # set extension defaults self.config = { - 'base_url' : ['/', 'String to append to beginning or URL.'], - 'end_url' : ['/', 'String to append to end of URL.'], - 'html_class' : ['wikilink', 'CSS hook. Leave blank for none.'], - 'build_url' : [build_url, 'Callable formats URL from label.'], + 'base_url': ['/', 'String to append to beginning or URL.'], + 'end_url': ['/', 'String to append to end of URL.'], + 'html_class': ['wikilink', 'CSS hook. Leave blank for none.'], + 'build_url': [build_url, 'Callable formats URL from label.'], } configs = dict(configs) or {} # Override defaults with user settings diff --git a/tests/unit/test_mdrender.py b/tests/unit/test_mdrender.py index af794ae7..90a91550 100644 --- a/tests/unit/test_mdrender.py +++ b/tests/unit/test_mdrender.py @@ -1,14 +1,8 @@ from unittest.mock import patch, MagicMock -import pytest - -import taiga.base -from taiga.mdrender.extensions import mentions from taiga.mdrender.extensions import emojify from taiga.mdrender.service import render, cache_by_sha, get_diff_of_htmls, render_and_extract -from taiga.projects.references import services - from taiga.users.models import User from datetime import datetime @@ -17,14 +11,17 @@ dummy_project = MagicMock() dummy_project.id = 1 dummy_project.slug = "test" + def test_proccessor_valid_emoji(): result = emojify.EmojifyPreprocessor().run(["**:smile:**"]) assert result == ["****"] + def test_proccessor_invalid_emoji(): result = emojify.EmojifyPreprocessor().run(["**:notvalidemoji:**"]) assert result == ["**:notvalidemoji:**"] + def test_proccessor_valid_user_mention(): with patch("taiga.mdrender.extensions.mentions.User") as mock: instance = mock.objects.get.return_value @@ -33,6 +30,7 @@ def test_proccessor_valid_user_mention(): expected_result = "
" assert result == expected_result + def test_proccessor_invalid_user_mention(): with patch("taiga.mdrender.extensions.mentions.User") as mock: mock.DoesNotExist = User.DoesNotExist @@ -40,6 +38,7 @@ def test_proccessor_invalid_user_mention(): result = render(dummy_project, "**@notvaliduser**") assert result == '@notvaliduser
' + def test_proccessor_valid_us_reference(): with patch("taiga.mdrender.extensions.references.get_instance_by_ref") as mock: instance = mock.return_value @@ -49,97 +48,117 @@ def test_proccessor_valid_us_reference(): expected_result = '' assert result == expected_result + def test_proccessor_valid_issue_reference(): with patch("taiga.mdrender.extensions.references.get_instance_by_ref") as mock: instance = mock.return_value instance.content_type.model = "issue" instance.content_object.subject = "test" - result = render(dummy_project, "**#1**") - expected_result = '' + result = render(dummy_project, "**#2**") + expected_result = '' assert result == expected_result + def test_proccessor_valid_task_reference(): with patch("taiga.mdrender.extensions.references.get_instance_by_ref") as mock: instance = mock.return_value instance.content_type.model = "task" instance.content_object.subject = "test" - result = render(dummy_project, "**#1**") - expected_result = '' + result = render(dummy_project, "**#3**") + expected_result = '' assert result == expected_result + def test_proccessor_invalid_type_reference(): with patch("taiga.mdrender.extensions.references.get_instance_by_ref") as mock: instance = mock.return_value instance.content_type.model = "other" instance.content_object.subject = "test" - result = render(dummy_project, "**#1**") - assert result == "#1
" + result = render(dummy_project, "**#4**") + assert result == "#4
" + def test_proccessor_invalid_reference(): with patch("taiga.mdrender.extensions.references.get_instance_by_ref") as mock: mock.return_value = None - result = render(dummy_project, "**#1**") - assert result == "#1
" + result = render(dummy_project, "**#5**") + assert result == "#5
" + def test_render_wiki_strong(): assert render(dummy_project, "**test**") == "test
" assert render(dummy_project, "__test__") == "test
" + def test_render_wiki_italic(): assert render(dummy_project, "*test*") == "test
" assert render(dummy_project, "_test_") == "test
" + def test_render_wiki_strike(): assert render(dummy_project, "~~test~~") == "test
An example of reference link
" source = "An [example][id] of reference link\n [id]: http://example.com/ \"Title\"" assert render(dummy_project, source) == expected_result + def test_render_url_autolinks(): expected_result = "Test the http://example.com/ autolink
" source = "Test the http://example.com/ autolink" assert render(dummy_project, source) == expected_result + def test_render_url_autolinks_without_http(): expected_result = "Test the www.example.com autolink
" source = "Test the www.example.com autolink" assert render(dummy_project, source) == expected_result + def test_render_url_automail(): expected_result = "Test the example@example.com automail
" source = "Test the example@example.com automail" assert render(dummy_project, source) == expected_result + def test_render_absolute_image(): assert render(dummy_project, "") == "print("test")\n
print("test")\n
test
") assert result == "<p>test</p>" + def test_get_diff_of_htmls_deletions(): result = get_diff_of_htmls("test
", "") assert result == "test1
", "1test
") assert result == "<p>1test