kopia lustrzana https://github.com/wagtail/wagtail
Template render richtext without wrapper, add wagtail.contrib.legacy.richtext
* Add wagtail.contrib.legacy.richtext with tests & docs * Make RichText.__html__ behave the same as template filter * Resolves #1214pull/6050/head
rodzic
eed16e0034
commit
a1a2c35c1c
|
@ -35,6 +35,7 @@ Changelog
|
|||
* Improve performance of empty search results by avoiding downloading the entire search index in these scenarios (Lars van de Kerkhof, Coen van der Kamp)
|
||||
* Replace `gulp-sass` with `gulp-dart-sass` to improve core development across different platforms (Thibaud Colas)
|
||||
* Add SVG icons to resolve accessibility and customisation issues and start using them in a subset of Wagtail's admin (Coen van der Kamp, Scott Cranfill, Thibaud Colas)
|
||||
* Remove markup around rich text rendering by default, provide a way to use old behaviour via `wagtail.contrib.legacy.richtext` (Coen van der Kamp, Dan Braghis)
|
||||
* Fix: Support IPv6 domain (Alex Gleason, Coen van der Kamp)
|
||||
* Fix: Ensure link to add a new user works when no users are visible in the users list (LB (Ben Johnston))
|
||||
* Fix: `AbstractEmailForm` saved submission fields are now aligned with the email content fields, `form.cleaned_data` will be used instead of `form.fields` (Haydn Greatnews)
|
||||
|
|
|
@ -202,11 +202,9 @@ Produces:
|
|||
|
||||
.. code-block:: html
|
||||
|
||||
<div class="rich-text">
|
||||
<p>
|
||||
<b>Welcome</b> to our new site!
|
||||
</p>
|
||||
</div>
|
||||
<p>
|
||||
<b>Welcome</b> to our new site!
|
||||
</p>
|
||||
|
||||
**Note:** You'll need to include ``{% load wagtailcore_tags %}`` in each
|
||||
template that uses Wagtail's tags. Django will throw a ``TemplateSyntaxError``
|
||||
|
|
|
@ -17,6 +17,7 @@ Wagtail ships with a variety of extra optional modules.
|
|||
searchpromotions
|
||||
table_block
|
||||
redirects
|
||||
legacy_richtext
|
||||
|
||||
|
||||
:doc:`settings`
|
||||
|
@ -72,3 +73,9 @@ Provides a TableBlock for adding HTML tables to pages.
|
|||
-----------------------
|
||||
|
||||
Provides a way to manage redirects.
|
||||
|
||||
|
||||
:doc:`legacy_richtext`
|
||||
-----------------------
|
||||
|
||||
Provides the legacy richtext wrapper (``<div class="rich-text"></div>``).
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
.. _legacy_richtext:
|
||||
|
||||
=====================
|
||||
Legacy richtext
|
||||
=====================
|
||||
|
||||
.. module:: wagtail.contrib.legacy.richtext
|
||||
|
||||
Provides the legacy richtext wrapper.
|
||||
|
||||
Place ``wagtail.contrib.legacy.richtext`` before ``wagtail.core`` in ``INSTALLED_APPS``.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
INSTALLED_APPS = [
|
||||
...
|
||||
"wagtail.contrib.legacy.richtext",
|
||||
"wagtail.core",
|
||||
...
|
||||
]
|
||||
|
||||
The ``{{ page.body|richtext }}`` template filter will now render:
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
<div class="rich-text">...</div>
|
|
@ -48,6 +48,7 @@ Other features
|
|||
* Improve performance of empty search results by avoiding downloading the entire search index in these scenarios (Lars van de Kerkhof, Coen van der Kamp)
|
||||
* Replace ``gulp-sass`` with ``gulp-dart-sass`` to improve core development across different platforms (Thibaud Colas)
|
||||
* Add SVG icons to resolve accessibility and customisation issues and start using them in a subset of Wagtail's admin (Coen van der Kamp, Scott Cranfill, Thibaud Colas)
|
||||
* Remove markup around rich text rendering by default, provide a way to use old behaviour via ``wagtail.contrib.legacy.richtext``. See :ref:`legacy_richtext`. (Coen van der Kamp, Dan Braghis)
|
||||
|
||||
|
||||
Bug fixes
|
||||
|
@ -66,6 +67,9 @@ Bug fixes
|
|||
Upgrade considerations
|
||||
======================
|
||||
|
||||
* Rich text will now be rendered without any markup, to use the old behaviour where a wrapper ``<div class="richt-text">`` is used see :ref:`legacy_richtext`.
|
||||
|
||||
|
||||
Removed support for Python 3.5
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
|
|
@ -323,8 +323,7 @@ class TestRichTextValue(TestCase):
|
|||
value = RichText(text)
|
||||
result = str(value)
|
||||
expected = (
|
||||
'<div class="rich-text"><p>To the <a href="'
|
||||
'/foo/pointless-suffix/">moon</a>!</p></div>')
|
||||
'<p>To the <a href="/foo/pointless-suffix/">moon</a>!</p>')
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
<div class="rich-text">{{ html|safe }}</div>
|
|
@ -0,0 +1,14 @@
|
|||
from django.test import TestCase
|
||||
|
||||
from wagtail.core.templatetags.wagtailcore_tags import richtext
|
||||
|
||||
|
||||
class TestTemplateTag(TestCase):
|
||||
def test_no_contrib_legacy_richtext_no_wrapper(self):
|
||||
self.assertEqual(richtext("Foo"), "Foo")
|
||||
|
||||
def test_contrib_legacy_richtext_renders_wrapper(self):
|
||||
with self.modify_settings(
|
||||
INSTALLED_APPS={"prepend": "wagtail.contrib.legacy.richtext"}
|
||||
):
|
||||
self.assertEqual(richtext("Foo"), """<div class="rich-text">Foo</div>""")
|
|
@ -1,4 +1,5 @@
|
|||
from django.db.models import Model
|
||||
from django.template.loader import render_to_string
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from wagtail.core.rich_text.feature_registry import FeatureRegistry
|
||||
|
@ -43,7 +44,7 @@ class RichText:
|
|||
self.source = (source or '')
|
||||
|
||||
def __html__(self):
|
||||
return '<div class="rich-text">' + expand_db_html(self.source) + '</div>'
|
||||
return render_to_string('wagtailcore/shared/richtext.html', {'html': expand_db_html(self.source)})
|
||||
|
||||
def __str__(self):
|
||||
return mark_safe(self.__html__())
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
{{ html|safe }}
|
|
@ -1,8 +1,8 @@
|
|||
from django import template
|
||||
from django.shortcuts import reverse
|
||||
from django.template.defaulttags import token_kwargs
|
||||
from django.template.loader import render_to_string
|
||||
from django.utils.encoding import force_str
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from wagtail import VERSION, __version__
|
||||
from wagtail.core.models import Page, Site
|
||||
|
@ -104,8 +104,7 @@ def richtext(value):
|
|||
html = expand_db_html(value)
|
||||
else:
|
||||
raise TypeError("'richtext' template filter received an invalid value; expected string, got {}.".format(type(value)))
|
||||
|
||||
return mark_safe('<div class="rich-text">' + html + '</div>')
|
||||
return render_to_string('wagtailcore/shared/richtext.html', {'html': html})
|
||||
|
||||
|
||||
class IncludeBlockNode(template.Node):
|
||||
|
|
|
@ -508,7 +508,7 @@ class TestRichTextBlock(TestCase):
|
|||
value = RichText('<p>Merry <a linktype="page" id="4">Christmas</a>!</p>')
|
||||
result = block.render(value)
|
||||
self.assertEqual(
|
||||
result, '<div class="rich-text"><p>Merry <a href="/events/christmas/">Christmas</a>!</p></div>'
|
||||
result, '<p>Merry <a href="/events/christmas/">Christmas</a>!</p>'
|
||||
)
|
||||
|
||||
def test_render_form(self):
|
||||
|
@ -1448,7 +1448,7 @@ class TestStructBlock(SimpleTestCase):
|
|||
'body': '<b>world</b>',
|
||||
})
|
||||
body_bound_block = struct_value.bound_blocks['body']
|
||||
expected = '<div class="rich-text"><b>world</b></div>'
|
||||
expected = '<b>world</b>'
|
||||
self.assertEqual(str(body_bound_block), expected)
|
||||
|
||||
def test_get_form_context(self):
|
||||
|
@ -1725,13 +1725,13 @@ class TestStructBlock(SimpleTestCase):
|
|||
block = SectionBlock()
|
||||
value = block.to_python({'title': 'Hello', 'body': '<i>italic</i> world'})
|
||||
result = block.render(value)
|
||||
self.assertEqual(result, """<h1>Hello</h1><div class="rich-text"><i>italic</i> world</div>""")
|
||||
self.assertEqual(result, """<h1>Hello</h1><i>italic</i> world""")
|
||||
|
||||
def test_render_block_with_extra_context(self):
|
||||
block = SectionBlock()
|
||||
value = block.to_python({'title': 'Bonjour', 'body': 'monde <i>italique</i>'})
|
||||
result = block.render(value, context={'language': 'fr'})
|
||||
self.assertEqual(result, """<h1 lang="fr">Bonjour</h1><div class="rich-text">monde <i>italique</i></div>""")
|
||||
self.assertEqual(result, """<h1 lang="fr">Bonjour</h1>monde <i>italique</i>""")
|
||||
|
||||
def test_render_structvalue(self):
|
||||
"""
|
||||
|
@ -1740,11 +1740,11 @@ class TestStructBlock(SimpleTestCase):
|
|||
block = SectionBlock()
|
||||
value = block.to_python({'title': 'Hello', 'body': '<i>italic</i> world'})
|
||||
result = value.__html__()
|
||||
self.assertEqual(result, """<h1>Hello</h1><div class="rich-text"><i>italic</i> world</div>""")
|
||||
self.assertEqual(result, """<h1>Hello</h1><i>italic</i> world""")
|
||||
|
||||
# value.render_as_block() should be equivalent to value.__html__()
|
||||
result = value.render_as_block()
|
||||
self.assertEqual(result, """<h1>Hello</h1><div class="rich-text"><i>italic</i> world</div>""")
|
||||
self.assertEqual(result, """<h1>Hello</h1><i>italic</i> world""")
|
||||
|
||||
def test_str_structvalue(self):
|
||||
"""
|
||||
|
@ -1769,7 +1769,7 @@ class TestStructBlock(SimpleTestCase):
|
|||
block = SectionBlock()
|
||||
value = block.to_python({'title': 'Bonjour', 'body': 'monde <i>italique</i>'})
|
||||
result = value.render_as_block(context={'language': 'fr'})
|
||||
self.assertEqual(result, """<h1 lang="fr">Bonjour</h1><div class="rich-text">monde <i>italique</i></div>""")
|
||||
self.assertEqual(result, """<h1 lang="fr">Bonjour</h1>monde <i>italique</i>""")
|
||||
|
||||
|
||||
class TestStructBlockWithCustomStructValue(SimpleTestCase):
|
||||
|
@ -2493,8 +2493,8 @@ class TestStreamBlock(WagtailTestUtils, SimpleTestCase):
|
|||
])
|
||||
|
||||
self.assertIn('<div class="block-heading">My title</div>', html)
|
||||
self.assertIn('<div class="block-paragraph"><div class="rich-text">My <i>first</i> paragraph</div></div>', html)
|
||||
self.assertIn('<div class="block-paragraph"><div class="rich-text">My second paragraph</div></div>', html)
|
||||
self.assertIn('<div class="block-paragraph">My <i>first</i> paragraph</div>', html)
|
||||
self.assertIn('<div class="block-paragraph">My second paragraph</div>', html)
|
||||
|
||||
def test_render_unknown_type(self):
|
||||
# This can happen if a developer removes a type from their StreamBlock
|
||||
|
@ -2510,7 +2510,7 @@ class TestStreamBlock(WagtailTestUtils, SimpleTestCase):
|
|||
])
|
||||
self.assertNotIn('foo', html)
|
||||
self.assertNotIn('Hello', html)
|
||||
self.assertIn('<div class="block-paragraph"><div class="rich-text">My first paragraph</div></div>', html)
|
||||
self.assertIn('<div class="block-paragraph">My first paragraph</div>', html)
|
||||
|
||||
def test_render_calls_block_render_on_children(self):
|
||||
"""
|
||||
|
@ -3674,7 +3674,7 @@ class TestIncludeBlockTag(TestCase):
|
|||
})
|
||||
|
||||
self.assertIn(
|
||||
"""<body><h1 lang="fr">Bonjour</h1><div class="rich-text">monde <i>italique</i></div></body>""",
|
||||
"""<body><h1 lang="fr">Bonjour</h1>monde <i>italique</i></body>""",
|
||||
result
|
||||
)
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ class TestCoreGlobalsAndFilters(TestCase):
|
|||
richtext = '<p>Merry <a linktype="page" id="2">Christmas</a>!</p>'
|
||||
self.assertEqual(
|
||||
self.render('{{ text|richtext }}', {'text': richtext}),
|
||||
'<div class="rich-text"><p>Merry <a href="/">Christmas</a>!</p></div>')
|
||||
'<p>Merry <a href="/">Christmas</a>!</p>')
|
||||
|
||||
def test_pageurl(self):
|
||||
page = Page.objects.get(pk=2)
|
||||
|
@ -95,7 +95,7 @@ class TestJinjaEscaping(TestCase):
|
|||
'value': stream_value,
|
||||
})
|
||||
|
||||
self.assertIn('<div class="rich-text"><p>Merry <a href="/events/christmas/">Christmas</a>!</p></div>', result)
|
||||
self.assertIn('<p>Merry <a href="/events/christmas/">Christmas</a>!</p>', result)
|
||||
|
||||
|
||||
class TestIncludeBlockTag(TestCase):
|
||||
|
@ -127,7 +127,7 @@ class TestIncludeBlockTag(TestCase):
|
|||
})
|
||||
|
||||
self.assertIn(
|
||||
"""<body><h1 lang="fr">Bonjour</h1><div class="rich-text">monde <i>italique</i></div></body>""",
|
||||
"""<body><h1 lang="fr">Bonjour</h1>monde <i>italique</i></body>""",
|
||||
result
|
||||
)
|
||||
|
||||
|
|
|
@ -67,7 +67,7 @@ class TestRichTextValue(TestCase):
|
|||
result = str(value)
|
||||
self.assertEqual(
|
||||
result,
|
||||
'<div class="rich-text"><p>Merry <a href="/events/christmas/">Christmas</a>!</p></div>'
|
||||
'<p>Merry <a href="/events/christmas/">Christmas</a>!</p>'
|
||||
)
|
||||
|
||||
def test_evaluate_value(self):
|
||||
|
|
|
@ -192,8 +192,8 @@ class TestStreamFieldRenderingBase(TestCase):
|
|||
|
||||
img_tag = self.image.get_rendition('original').img_tag()
|
||||
self.expected = ''.join([
|
||||
'<div class="block-rich_text"><div class="rich-text"><p>Rich text</p></div></div>',
|
||||
'<div class="block-rich_text"><div class="rich-text"><p>Привет, Микола</p></div></div>',
|
||||
'<div class="block-rich_text"><p>Rich text</p></div>',
|
||||
'<div class="block-rich_text"><p>Привет, Микола</p></div>',
|
||||
'<div class="block-image">{}</div>'.format(img_tag),
|
||||
'<div class="block-text">Hello, World!</div>',
|
||||
])
|
||||
|
|
|
@ -311,12 +311,12 @@ class TestResolveModelString(TestCase):
|
|||
class TestRichtextTag(TestCase):
|
||||
def test_call_with_text(self):
|
||||
result = richtext("Hello world!")
|
||||
self.assertEqual(result, '<div class="rich-text">Hello world!</div>')
|
||||
self.assertEqual(result, 'Hello world!')
|
||||
self.assertIsInstance(result, SafeString)
|
||||
|
||||
def test_call_with_none(self):
|
||||
result = richtext(None)
|
||||
self.assertEqual(result, '<div class="rich-text"></div>')
|
||||
self.assertEqual(result, '')
|
||||
|
||||
def test_call_with_invalid_value(self):
|
||||
with self.assertRaisesRegex(TypeError, "'richtext' template filter received an invalid value"):
|
||||
|
|
Ładowanie…
Reference in New Issue