Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Markdown in Add-on Listing Fields #22956

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions requirements/prod.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1208,3 +1208,6 @@ watchdog[watchmedo]==3.0.0 \
django-node-assets==0.9.14 \
--hash=sha256:80cbe3d10521808309712b2aa5ef6d69799bbcafef844cf7f223d3c93f405768 \
--hash=sha256:d5b5c472136084d533268f52ab77897327863a102e25c81f484aae85eb806987
Markdown==3.7 \
--hash=sha256:2ae2471477cfd02dbbf038d5d9bc226d40def84b4fe2986e49b59b6b472bbed2 \
--hash=sha256:7eb6df5690b81a1d7942992c97fad2938e956e79df20cbc6186e9c3a77b1c803
12 changes: 7 additions & 5 deletions src/olympia/addons/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
from olympia.tags.models import Tag
from olympia.translations.fields import (
NoURLsField,
PurifiedField,
PurifiedMarkdownField,
TranslatedField,
save_signal,
)
Expand Down Expand Up @@ -501,12 +501,14 @@ class Addon(OnChangeMixin, ModelBase):
homepage = TranslatedField(max_length=255)
support_email = TranslatedField(db_column='supportemail', max_length=100)
support_url = TranslatedField(db_column='supporturl', max_length=255)
description = PurifiedField(short=False, max_length=15000)
description = PurifiedMarkdownField(short=False, max_length=15000)

summary = NoURLsField(max_length=250)
developer_comments = PurifiedField(db_column='developercomments', max_length=3000)
eula = PurifiedField(max_length=350000)
privacy_policy = PurifiedField(db_column='privacypolicy', max_length=150000)
developer_comments = PurifiedMarkdownField(
db_column='developercomments', max_length=3000
)
eula = PurifiedMarkdownField(max_length=350000)
privacy_policy = PurifiedMarkdownField(db_column='privacypolicy', max_length=150000)

average_rating = models.FloatField(
max_length=255, default=0, null=True, db_column='averagerating'
Expand Down
107 changes: 46 additions & 61 deletions src/olympia/addons/tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -964,6 +964,9 @@ def newlines_helper(self, string_before):
addon.save()
return addon.privacy_policy.localized_string_clean

def replace_helper(self, string_before):
return string_before.replace('<', '&lt;').replace('>', '&gt;')

def test_newlines_normal(self):
before = (
'Paragraph one.\n'
Expand All @@ -973,7 +976,14 @@ def test_newlines_normal(self):
"Should be four nl's before this line."
)

after = before # Nothing special; this shouldn't change.
# Markdown.
after = (
'Paragraph one.\n'
'This should be on the very next line.\n\n'
"Should be two nl's before this line.\n\n"
"Should be three nl's before this line.\n\n"
"Should be four nl's before this line."
)

assert self.newlines_helper(before) == after

Expand All @@ -986,13 +996,7 @@ def test_newlines_ul(self):
'</ul>'
)

after = (
'<ul>'
"<li>No nl's between the ul and the li.</li>"
"<li>No nl's between li's.\n\n"
'But there should be two before this line.</li>'
'</ul>'
)
after = self.replace_helper(before)

assert self.newlines_helper(before) == after

Expand All @@ -1003,11 +1007,7 @@ def test_newlines_ul_tight(self):
"There should be no nl's above this line."
)

after = (
'There should be one nl between this and the ul.\n'
'<ul><li>test</li><li>test</li></ul>'
"There should be no nl's above this line."
)
after = self.replace_helper(before)

assert self.newlines_helper(before) == after

Expand All @@ -1018,11 +1018,7 @@ def test_newlines_ul_loose(self):
'There should be one nl above this line.'
)

after = (
"There should be two nl's between this and the ul.\n\n"
'<ul><li>test</li><li>test</li></ul>\n'
'There should be one nl above this line.'
)
after = self.replace_helper(before)

assert self.newlines_helper(before) == after

Expand All @@ -1033,11 +1029,7 @@ def test_newlines_blockquote_tight(self):
"There should be no nl's above this."
)

after = (
'There should be one nl below this.\n'
'<blockquote>Hi</blockquote>'
"There should be no nl's above this."
)
after = self.replace_helper(before)

assert self.newlines_helper(before) == after

Expand All @@ -1048,11 +1040,7 @@ def test_newlines_blockquote_loose(self):
'There should be one nl above this.'
)

after = (
'There should be two nls below this.\n\n'
'<blockquote>Hi</blockquote>\n'
'There should be one nl above this.'
)
after = self.replace_helper(before)

assert self.newlines_helper(before) == after

Expand All @@ -1062,56 +1050,56 @@ def test_newlines_inline(self):
'<b>The newlines</b> should be kept'
)

after = before # Should stay the same
after = self.replace_helper(before)

assert self.newlines_helper(before) == after

def test_newlines_code_inline(self):
before = "Code tags aren't blocks.\n\n" '<code>alert(test);</code>\n\nSee?'

after = before # Should stay the same
after = self.replace_helper(before)

assert self.newlines_helper(before) == after

def test_newlines_li_newlines(self):
before = '<ul><li>\nxx</li></ul>'
after = '<ul><li>xx</li></ul>'
after = self.replace_helper(before)
assert self.newlines_helper(before) == after

before = '<ul><li>xx\n</li></ul>'
after = '<ul><li>xx</li></ul>'
after = self.replace_helper(before)
assert self.newlines_helper(before) == after

before = '<ul><li>xx\nxx</li></ul>'
after = '<ul><li>xx\nxx</li></ul>'
after = self.replace_helper(before)
assert self.newlines_helper(before) == after

before = '<ul><li></li></ul>'
after = '<ul><li></li></ul>'
after = self.replace_helper(before)
assert self.newlines_helper(before) == after

# All together now
before = '<ul><li>\nxx</li> <li>xx\n</li> <li>xx\nxx</li> <li></li>\n</ul>'

after = '<ul><li>xx</li> <li>xx</li> <li>xx\nxx</li> <li></li></ul>'
after = self.replace_helper(before)

assert self.newlines_helper(before) == after

def test_newlines_empty_tag(self):
before = 'This is a <b></b> test!'
after = before
after = self.replace_helper(before)

assert self.newlines_helper(before) == after

def test_newlines_empty_tag_nested(self):
before = 'This is a <b><i></i></b> test!'
after = before
after = self.replace_helper(before)

assert self.newlines_helper(before) == after

def test_newlines_empty_tag_block_nested(self):
b = 'Test.\n\n<blockquote><ul><li></li></ul></blockquote>\ntest.'
a = 'Test.\n\n<blockquote><ul><li></li></ul></blockquote>test.'
a = self.replace_helper(b)

assert self.newlines_helper(b) == a

Expand All @@ -1120,7 +1108,7 @@ def test_newlines_empty_tag_block_nested_spaced(self):
'Test.\n\n<blockquote>\n\n<ul>\n\n<li>'
'</li>\n\n</ul>\n\n</blockquote>\ntest.'
)
after = 'Test.\n\n<blockquote><ul><li></li></ul></blockquote>test.'
after = self.replace_helper(before)

assert self.newlines_helper(before) == after

Expand All @@ -1130,10 +1118,7 @@ def test_newlines_li_newlines_inline(self):
'<li>Test <b>test</b> test.</li></ul>'
)

after = (
'<ul><li><b>test\ntest\n\ntest</b></li>'
'<li>Test <b>test</b> test.</li></ul>'
)
after = self.replace_helper(before)

assert self.newlines_helper(before) == after

Expand All @@ -1143,7 +1128,7 @@ def test_newlines_li_all_inline(self):
'stuff</code> to see what happens.'
)

after = before # Should stay the same
after = self.replace_helper(before)

assert self.newlines_helper(before) == after

Expand All @@ -1152,31 +1137,31 @@ def test_newlines_spaced_blocks(self):
'<blockquote>\n\n<ul>\n\n<li>\n\ntest\n\n</li>\n\n</ul>\n\n</blockquote>'
)

after = '<blockquote><ul><li>test</li></ul></blockquote>'
after = self.replace_helper(before)

assert self.newlines_helper(before) == after

def test_newlines_spaced_inline(self):
before = "Line.\n\n<b>\nThis line is bold.\n</b>\n\nThis isn't."
after = before
after = self.replace_helper(before)

assert self.newlines_helper(before) == after

def test_newlines_nested_inline(self):
before = '<b>\nThis line is bold.\n\n<i>This is also italic</i></b>'
after = before
after = self.replace_helper(before)

assert self.newlines_helper(before) == after

def test_newlines_xss_script(self):
before = "<script>\n\nalert('test');\n</script>"
after = "&lt;script&gt;\n\nalert('test');\n&lt;/script&gt;"
after = self.replace_helper(before)

assert self.newlines_helper(before) == after

def test_newlines_xss_inline(self):
before = '<b onclick="alert(\'test\');">test</b>'
after = '<b>test</b>'
after = self.replace_helper(before)

assert self.newlines_helper(before) == after

Expand All @@ -1191,61 +1176,61 @@ def test_newlines_attribute_link_doublequote(self, mock_get_outgoing_url):

def test_newlines_attribute_singlequote(self):
before = "<abbr title='laugh out loud'>lol</abbr>"
after = '<abbr title="laugh out loud">lol</abbr>'
after = self.replace_helper(before)

assert self.newlines_helper(before) == after

def test_newlines_attribute_doublequote(self):
before = '<abbr title="laugh out loud">lol</abbr>'
after = before
after = self.replace_helper(before)

assert self.newlines_helper(before) == after

def test_newlines_attribute_nestedquotes_doublesingle(self):
before = '<abbr title="laugh \'out\' loud">lol</abbr>'
after = before
after = self.replace_helper(before)

assert self.newlines_helper(before) == after

def test_newlines_attribute_nestedquotes_singledouble(self):
before = '<abbr title=\'laugh "out" loud\'>lol</abbr>'
after = before
after = self.replace_helper(before)

assert self.newlines_helper(before) == after

def test_newlines_unclosed_b(self):
before = '<b>test'
after = '<b>test</b>'
after = self.replace_helper(before)

assert self.newlines_helper(before) == after

def test_newlines_unclosed_b_wrapped(self):
before = 'This is a <b>test'
after = 'This is a <b>test</b>'
after = self.replace_helper(before)

assert self.newlines_helper(before) == after

def test_newlines_unclosed_li(self):
before = '<ul><li>test</ul>'
after = '<ul><li>test</li></ul>'
after = self.replace_helper(before)

assert self.newlines_helper(before) == after

def test_newlines_malformed_faketag(self):
before = '<madonna'
after = '&lt;madonna'
after = self.replace_helper(before)

assert self.newlines_helper(before) == after

def test_newlines_correct_faketag(self):
before = '<madonna>'
after = '&lt;madonna&gt;'
after = self.replace_helper(before)

assert self.newlines_helper(before) == after

def test_newlines_malformed_tag(self):
before = '<strong'
after = '&lt;strong'
after = self.replace_helper(before)

assert self.newlines_helper(before) == after

Expand All @@ -1261,13 +1246,13 @@ def test_newlines_malformed_tag_surrounded(self):

def test_newlines_less_than(self):
before = '3 < 5'
after = '3 &lt; 5'
after = self.replace_helper(before)

assert self.newlines_helper(before) == after

def test_newlines_less_than_tight(self):
before = 'abc 3<5 def'
after = 'abc 3&lt;5 def'
after = self.replace_helper(before)

assert self.newlines_helper(before) == after

Expand Down
4 changes: 2 additions & 2 deletions src/olympia/devhub/templates/devhub/addons/edit/describe.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{% from "devhub/includes/macros.html" import tip, empty_unless, flags, select_cats, some_html_tip, trans_readonly %}
{% from "devhub/includes/macros.html" import tip, empty_unless, flags, select_cats, markdown_tip, trans_readonly %}

<form method="post" action="{{ url('devhub.addons.section', valid_slug, 'describe', 'edit') }}"
id="addon-edit-describe"
Expand Down Expand Up @@ -141,7 +141,7 @@ <h3>
<div class="char-count"
data-for-startswith="{{ main_form.description.auto_id }}_"
data-minlength="{{ main_form.description.field.min_length }}"></div>
{{ some_html_tip() }}
{{ markdown_tip() }}
{% else %}
{% call empty_unless(addon.description) %}
<div id="addon-description" class="prose">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{% from "devhub/includes/macros.html" import tip, some_html_tip, empty_unless, flags %}
{% from "devhub/includes/macros.html" import tip, markdown_tip, empty_unless, flags %}

<form method="post"
action="{{ url('devhub.addons.section', addon.slug, 'technical', 'edit') }}">
Expand Down Expand Up @@ -32,10 +32,10 @@ <h3>
{% if editable %}
{{ main_form.developer_comments }}
{{ main_form.developer_comments.errors }}
{{ some_html_tip() }}
{{ markdown_tip() }}
{% else %}
{% call empty_unless(addon.developer_comments) %}
<div id="developer_comments">{{ addon|all_locales('developer_comments') }}</div>
<div id="developer_comments">{{ addon|all_locales('developer_comments', nl2br=True) }}</div>
{% endcall %}
{% endif %}
</td>
Expand Down
Loading
Loading