Implement a registry for rich text features

pull/3754/head
Matt Westcott 2017-07-13 14:13:18 +01:00
rodzic 517f1871e7
commit 31cf4b68d1
3 zmienionych plików z 70 dodań i 1 usunięć

Wyświetl plik

@ -90,3 +90,11 @@ def polite_pages_only(parent_page, pages, request):
pages = pages.filter(slug__startswith='hello')
return pages
# register 'blockquote' as a rich text feature supported by a hallo.js plugin
@hooks.register('register_rich_text_features')
def register_blockquote_feature(features):
features.register_editor_plugin(
'hallo', 'blockquote', {'plugin_name': 'halloblockquote'}
)

Wyświetl plik

@ -202,3 +202,46 @@ class RichText(object):
def __bool__(self):
return bool(self.source)
__nonzero__ = __bool__
class FeatureRegistry(object):
"""
A central store of information about optional features that can be enabled in rich text
editors by passing a ``features`` list to the RichTextField, such as how to
whitelist / convert HTML tags, and how to enable the feature on various editors.
This information may come from diverse sources - for example, wagtailimages might define
an 'images' feature and a hallo.js plugin for it, while a third-party module might
define a TinyMCE plugin for the same feature. The information is therefore collected into
this registry via the 'register_rich_text_features' hook.
"""
def __init__(self):
# Has the register_rich_text_features hook been run for this registry?
self.has_scanned_for_features = False
# a dict of dicts, one for each editor (hallo.js, TinyMCE etc); each dict is a mapping
# of feature names to 'plugin' objects that define how to implement that feature
# (e.g. paths to JS files to import). The API of that plugin object is not defined
# here, and is specific to each editor.
self.plugins_by_editor = {}
def _scan_for_features(self):
for fn in hooks.get_hooks('register_rich_text_features'):
fn(self)
self.has_scanned_for_features = True
def register_editor_plugin(self, editor_name, feature_name, plugin):
plugins = self.plugins_by_editor.setdefault(editor_name, {})
plugins[feature_name] = plugin
def get_editor_plugin(self, editor_name, feature_name):
if not self.has_scanned_for_features:
self._scan_for_features()
try:
return self.plugins_by_editor[editor_name][feature_name]
except KeyError:
return None
features = FeatureRegistry()

Wyświetl plik

@ -6,7 +6,7 @@ from mock import patch
from wagtail.wagtailcore.models import Page
from wagtail.wagtailcore.rich_text import (
DbWhitelister, PageLinkHandler, RichText, expand_db_html, extract_attrs)
DbWhitelister, FeatureRegistry, PageLinkHandler, RichText, expand_db_html, extract_attrs)
class TestPageLinkHandler(TestCase):
@ -144,3 +144,21 @@ class TestRichTextValue(TestCase):
value = RichText('<p>wagtail</p>')
self.assertTrue(value)
class TestFeatureRegistry(TestCase):
def test_register_rich_text_features_hook(self):
# testapp/wagtail_hooks.py defines a 'blockquote' rich text feature with a hallo.js
# plugin, via the register_rich_text_features hook; test that we can retrieve it here
features = FeatureRegistry()
blockquote = features.get_editor_plugin('hallo', 'blockquote')
self.assertEqual(blockquote['plugin_name'], 'halloblockquote')
def test_missing_editor_plugin_returns_none(self):
features = FeatureRegistry()
self.assertIsNone(
features.get_editor_plugin('made_up_editor', 'blockquote')
)
self.assertIsNone(
features.get_editor_plugin('hallo', 'made_up_feature')
)