kopia lustrzana https://github.com/wagtail/wagtail
Implement a registry for rich text features
rodzic
517f1871e7
commit
31cf4b68d1
|
@ -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'}
|
||||
)
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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')
|
||||
)
|
||||
|
|
Ładowanie…
Reference in New Issue