Support additional custom handler for links in Rich text editor. (#5159)

pull/5190/head
Md. Arifin Ibne Matin 2019-04-03 21:50:39 +02:00 zatwierdzone przez Thibaud Colas
rodzic f4d3025022
commit 2b2c71a4d9
5 zmienionych plików z 97 dodań i 3 usunięć

Wyświetl plik

@ -28,6 +28,7 @@ Changelog
* Added name attributes to all built-in page action menu items (LB (Ben Johnston))
* Added validation on the filter string to the Jinja2 image template tag (Jonny Scholes)
* Changed the pages reodering UI toggle to make it easier to find (Katie Locke, Thibaud Colas)
* Added support for rich text link rewrite handlers for `external` and `email` links (Md Arifin Ibne Matin)
* Fix: Set `SERVER_PORT` to 443 in `Page.dummy_request()` for HTTPS sites (Sergey Fedoseev)
* Fix: Include port number in `Host` header of `Page.dummy_request()` (Sergey Fedoseev)
* Fix: Validation error messages in `InlinePanel` no longer count towards `max_num` when disabling the 'add' button (Todd Dembrey, Thibaud Colas)

Wyświetl plik

@ -97,6 +97,22 @@ The ``register_link_type`` method allows you to define a function to be called w
def register_report_link(features):
features.register_link_type('report', report_link_handler)
It is also possible to define link rewrite handler for Wagtails built-in ``external`` and ``email`` links, even though they do not have a predefined ``linktype``. For example, if you want external links to have a ``rel="nofollow"`` attribute for SEO purposes:
.. code-block:: python
from django.utils.html import escape
from wagtail.core import hooks
def external_link_handler(attrs):
href = attrs["href"]
return '<a href="%s" rel="nofollow">' % escape(href)
@hooks.register('register_rich_text_features')
def register_external_link(features):
features.register_link_type('external', external_link_handler)
Similarly you can use ``email`` linktype to add a custom rewrite handler for email links (e.g. to obfuscate emails in rich text).
Embed rewrite handlers
----------------------

Wyświetl plik

@ -54,6 +54,7 @@ Other features
* Added name attributes to all built-in page action menu items (LB (Ben Johnston))
* Added validation on the filter string to the Jinja2 image template tag (Jonny Scholes)
* Changed the pages reodering UI toggle to make it easier to find (Katie Locke, Thibaud Colas)
* Added support for rich text link rewrite handlers for ``external`` and ``email`` links (Md Arifin Ibne Matin)
Bug fixes

Wyświetl plik

@ -56,12 +56,28 @@ class LinkRewriter:
try:
link_type = attrs['linktype']
except KeyError:
# return ordinary links without a linktype unchanged
return match.group(0)
link_type = None
href = attrs.get('href', None)
if href:
# From href attribute we try to detect only the linktypes that we
# currently support (`external` & `email`, `page` has a default handler)
# from the link chooser.
if href.startswith(('http:', 'https:')):
link_type = 'external'
elif href.startswith('mailto:'):
link_type = 'email'
if not link_type:
# otherwise return ordinary links without a linktype unchanged
return match.group(0)
try:
rule = self.link_rules[link_type]
except KeyError:
if link_type in ['email', 'external']:
# If no rule is registered for supported types
# return ordinary links without a linktype unchanged
return match.group(0)
# unrecognised link type
return '<a>'

Wyświetl plik

@ -7,7 +7,7 @@ from wagtail.core.models import Page
from wagtail.core.rich_text import RichText, expand_db_html
from wagtail.core.rich_text.feature_registry import FeatureRegistry
from wagtail.core.rich_text.pages import PageLinkHandler, page_linktype_handler
from wagtail.core.rich_text.rewriters import extract_attrs
from wagtail.core.rich_text.rewriters import LinkRewriter, extract_attrs
class TestPageLinkHandler(TestCase):
@ -117,3 +117,63 @@ class TestFeatureRegistry(TestCase):
self.assertIsNone(
features.get_editor_plugin('hallo', 'made_up_feature')
)
class TestLinkRewriterTagReplacing(TestCase):
def test_should_follow_default_behaviour(self):
# we always have default `page` rules registered.
rules = {
'page': lambda attrs: '<a href="/article/{}">'.format(attrs['id'])
}
rewriter = LinkRewriter(rules)
page_type_link = rewriter('<a linktype="page" id="3">')
self.assertEqual(page_type_link, '<a href="/article/3">')
# but it should also be able to handle other supported
# link types (email, external) even if no rules is provided
external_type_link = rewriter('<a href="https://wagtail.io/">')
self.assertEqual(external_type_link, '<a href="https://wagtail.io/">')
email_type_link = rewriter('<a href="mailto:test@wagtail.io">')
self.assertEqual(email_type_link, '<a href="mailto:test@wagtail.io">')
# As well as link which don't have any linktypes
link_without_linktype = rewriter('<a data-link="https://wagtail.io">')
self.assertEqual(link_without_linktype, '<a data-link="https://wagtail.io">')
# But should not handle if a custom linktype is mentioned but no
# associate rules are registered.
link_with_custom_linktype = rewriter('<a linktype="custom" href="https://wagtail.io">')
self.assertNotEqual(link_with_custom_linktype, '<a href="https://wagtail.io">')
self.assertEqual(link_with_custom_linktype, '<a>')
def test_supported_type_should_follow_given_rules(self):
# we always have `page` rules by default
rules = {
'page': lambda attrs: '<a href="/article/{}">'.format(attrs['id']),
'external': lambda attrs: '<a rel="nofollow" href="{}">'.format(attrs['href']),
'email': lambda attrs: '<a data-email="true" href="{}">'.format(attrs['href']),
'custom': lambda attrs: '<a data-phone="true" href="{}">'.format(attrs['href']),
}
rewriter = LinkRewriter(rules)
page_type_link = rewriter('<a linktype="page" id="3">')
self.assertEqual(page_type_link, '<a href="/article/3">')
# It should call appropriate rule supported linktypes (external or email)
# based on the href value
external_type_link = rewriter('<a href="https://wagtail.io/">')
self.assertEqual(external_type_link, '<a rel="nofollow" href="https://wagtail.io/">')
external_type_link_http = rewriter('<a href="http://wagtail.io/">')
self.assertEqual(external_type_link_http, '<a rel="nofollow" href="http://wagtail.io/">')
email_type_link = rewriter('<a href="mailto:test@wagtail.io">')
self.assertEqual(email_type_link, '<a data-email="true" href="mailto:test@wagtail.io">')
# But not the unsupported ones.
link_with_no_linktype = rewriter('<a href="tel:+4917640206387">')
self.assertEqual(link_with_no_linktype, '<a href="tel:+4917640206387">')
# Also call the rule if a custom linktype is mentioned.
link_with_custom_linktype = rewriter('<a linktype="custom" href="tel:+4917640206387">')
self.assertEqual(link_with_custom_linktype, '<a data-phone="true" href="tel:+4917640206387">')