diff --git a/openedx/core/djangolib/markup.py b/openedx/core/djangolib/markup.py
index 77b081737c..0cea1d4af9 100644
--- a/openedx/core/djangolib/markup.py
+++ b/openedx/core/djangolib/markup.py
@@ -3,6 +3,8 @@ Utilities for use in Mako markup.
"""
import markupsafe
+import bleach
+from mako.filters import decode
# Text() can be used to declare a string as plain text, as HTML() is used
# for HTML. It simply wraps markupsafe's escape, which will HTML-escape if
@@ -31,3 +33,24 @@ def HTML(html): # pylint: disable=invalid-name
"""
return markupsafe.Markup(html)
+
+
+def strip_all_tags_but_br(string_to_strip):
+ """
+ Strips all tags from a string except
+
+ Usage:
+ <%page expression_filter="h"/>
+ <%!
+ from openedx.core.djangolib.markup import strip_all_tags_but_br
+ %>
+ ${accomplishment_course_title | n, strip_all_tags_but_br}
+ """
+
+ if string_to_strip is None:
+ string_to_strip = ""
+
+ string_to_strip = decode.utf8(string_to_strip)
+ string_to_strip = bleach.clean(string_to_strip, tags=['br'], strip=True)
+
+ return string_to_strip
diff --git a/openedx/core/djangolib/tests/test_markup.py b/openedx/core/djangolib/tests/test_markup.py
index cd6b9b01ec..f8a347bace 100644
--- a/openedx/core/djangolib/tests/test_markup.py
+++ b/openedx/core/djangolib/tests/test_markup.py
@@ -11,7 +11,7 @@ from django.utils.translation import ungettext
from mako.template import Template
from nose.plugins.attrib import attr
-from openedx.core.djangolib.markup import HTML, Text
+from openedx.core.djangolib.markup import HTML, Text, strip_all_tags_but_br
@attr(shard=2)
@@ -74,3 +74,19 @@ class FormatHtmlTest(unittest.TestCase):
for i in [1, 2]:
out = Text(ungettext("1 & {}", "2 & {}", i)).format(HTML("<>"))
self.assertEqual(out, "{} & <>".format(i))
+
+ def test_strip_all_tags_but_br_filter(self):
+ """ Verify filter removes every tags except br """
+ template = Template(
+ """
+ <%page expression_filter="h"/>
+ <%!
+ from openedx.core.djangolib.markup import strip_all_tags_but_br
+ %>
+ ${" course
title