예제 #1
0
class DraftailRichTextArea(WidgetWithScript, widgets.HiddenInput):
    # this class's constructor accepts a 'features' kwarg
    accepts_features = True

    def get_panel(self):
        return RichTextFieldPanel

    def __init__(self, *args, **kwargs):
        # note: this constructor will receive an 'options' kwarg taken from the WAGTAILADMIN_RICH_TEXT_EDITORS setting,
        # but we don't currently recognise any options from there (other than 'features', which is passed here as a separate kwarg)
        kwargs.pop('options', None)
        self.options = {}

        self.features = kwargs.pop('features', None)
        if self.features is None:
            self.features = feature_registry.get_default_features()

        for feature in self.features:
            plugin = feature_registry.get_editor_plugin('draftail', feature)
            if plugin:
                plugin.construct_options(self.options)

        self.converter = ContentstateConverter(self.features)

        super().__init__(*args, **kwargs)

    def translate_value(self, value):
        # Convert database rich text representation to the format required by
        # the input field

        if value is None:
            value = ''

        return self.converter.from_database_format(value)

    def render(self, name, value, attrs=None):
        if attrs is None:
            attrs = {}

        attrs['data-draftail-input'] = True

        translated_value = self.translate_value(value)
        return super().render(name, translated_value, attrs)

    def render_js_init(self, id_, name, value):
        return "window.draftail.initEditor('#{id}', {opts}, document.currentScript)".format(
            id=id_, opts=json.dumps(self.options))

    def value_from_datadict(self, data, files, name):
        original_value = super().value_from_datadict(data, files, name)
        if original_value is None:
            return None
        return self.converter.to_database_format(original_value)

    @property
    def media(self):
        return Media(js=[
            'wagtailadmin/js/draftail.js',
        ],
                     css={'all': ['wagtailadmin/css/panels/draftail.css']})
예제 #2
0
파일: __init__.py 프로젝트: sprymix/wagtail
class DraftailRichTextArea(WidgetWithScript, widgets.HiddenInput):
    # this class's constructor accepts a 'features' kwarg
    accepts_features = True

    def get_panel(self):
        return RichTextFieldPanel

    def __init__(self, *args, **kwargs):
        # note: this constructor will receive an 'options' kwarg taken from the WAGTAILADMIN_RICH_TEXT_EDITORS setting,
        # but we don't currently recognise any options from there (other than 'features', which is passed here as a separate kwarg)
        self.options = {}

        self.features = kwargs.pop('features', None)
        if self.features is None:
            self.features = feature_registry.get_default_features()

        for feature in self.features:
            plugin = feature_registry.get_editor_plugin('draftail', feature)
            if plugin:
                plugin.construct_options(self.options)

        self.converter = ContentstateConverter(self.features)

        super().__init__(*args, **kwargs)

    def translate_value(self, value):
        # Convert database rich text representation to the format required by
        # the input field

        if value is None:
            value = ''

        return self.converter.from_database_format(value)

    def render(self, name, value, attrs=None):
        if attrs is None:
            attrs = {}

        attrs['data-draftail-input'] = True

        translated_value = self.translate_value(value)
        return super().render(name, translated_value, attrs)

    def render_js_init(self, id_, name, value):
        return "window.draftail.initEditor('#{id}', {opts}, document.currentScript)".format(
            id=id_, opts=json.dumps(self.options))

    def value_from_datadict(self, data, files, name):
        original_value = super().value_from_datadict(data, files, name)
        if original_value is None:
            return None
        return self.converter.to_database_format(original_value)

    @property
    def media(self):
        return Media(js=[
            'wagtailadmin/js/draftail.js',
        ], css={
            'all': ['wagtailadmin/css/panels/draftail.css']
        })
예제 #3
0
 def test_paragraphs_retain_keys(self):
     converter = ContentstateConverter(features=[])
     contentState = json.dumps({
         'entityMap': {},
         'blocks': [
             {'inlineStyleRanges': [], 'text': 'Hello world!', 'depth': 0, 'type': 'unstyled', 'key': '00000', 'entityRanges': []},
             {'inlineStyleRanges': [], 'text': 'Goodbye world!', 'depth': 0, 'type': 'unstyled', 'key': '00001', 'entityRanges': []},
         ]
     })
     result = converter.to_database_format(contentState)
     self.assertHTMLEqual(result, '''
         <p data-block-key='00000'>Hello world!</p>
         <p data-block-key='00001'>Goodbye world!</p>
         ''')
예제 #4
0
    def test_reject_javascript_link(self):
        converter = ContentstateConverter(features=['link'])
        contentstate_json = json.dumps({
            'entityMap': {
                '0': {'mutability': 'MUTABLE', 'type': 'LINK', 'data': {'url': "javascript:alert('oh no')"}}
            },
            'blocks': [
                {
                    'inlineStyleRanges': [], 'text': 'an external link', 'depth': 0, 'type': 'unstyled', 'key': '00000',
                    'entityRanges': [{'offset': 3, 'length': 8, 'key': 0}]
                },
            ]
        })

        result = converter.to_database_format(contentstate_json)
        self.assertEqual(result, '<p data-block-key="00000">an <a>external</a> link</p>')
예제 #5
0
 def test_style_fallback(self):
     # Test a block which uses an invalid inline style, and will be removed
     converter = ContentstateConverter(features=[])
     result = converter.to_database_format(json.dumps({
         'entityMap': {},
         'blocks': [
             {
                 'inlineStyleRanges': [{'offset': 0, 'length': 12, 'style': 'UNDERLINE'}],
                 'text': 'Hello world!', 'depth': 0, 'type': 'unstyled', 'key': '00000', 'entityRanges': []
             },
         ]
     }))
     self.assertHTMLEqual(result, '''
         <p data-block-key="00000">
             Hello world!
         </p>
     ''')
예제 #6
0
 def test_wrapped_block_retains_key(self):
     # Test a block which uses a wrapper correctly receives the key defined on the inner element
     converter = ContentstateConverter(features=['h1', 'ol', 'bold', 'italic'])
     result = converter.to_database_format(json.dumps({
         'entityMap': {},
         'blocks': [
             {'inlineStyleRanges': [], 'text': 'The rules of Fight Club', 'depth': 0, 'type': 'header-one', 'key': '00000', 'entityRanges': []},
             {'inlineStyleRanges': [], 'text': 'You do not talk about Fight Club.', 'depth': 0, 'type': 'ordered-list-item', 'key': '00001', 'entityRanges': []},
             {
                 'inlineStyleRanges': [],
                 'text': 'You do not talk about Fight Club.', 'depth': 0, 'type': 'ordered-list-item', 'key': '00002', 'entityRanges': []
             },
         ]
     }))
     self.assertHTMLEqual(result, '''
         <h1 data-block-key='00000'>The rules of Fight Club</h1>
         <ol>
             <li data-block-key='00001'>You do not talk about Fight Club.</li>
             <li data-block-key='00002'>You do not talk about Fight Club.</li>
         </ol>
     ''')
예제 #7
0
class DraftailRichTextArea(widgets.HiddenInput):
    template_name = 'wagtailadmin/widgets/draftail_rich_text_area.html'
    is_hidden = False

    # this class's constructor accepts a 'features' kwarg
    accepts_features = True

    def get_panel(self):
        return RichTextFieldPanel

    def __init__(self, *args, **kwargs):
        # note: this constructor will receive an 'options' kwarg taken from the WAGTAILADMIN_RICH_TEXT_EDITORS setting,
        # but we don't currently recognise any options from there (other than 'features', which is passed here as a separate kwarg)
        kwargs.pop('options', None)
        self.options = {}

        self._media = Media(
            js=[
                versioned_static('wagtailadmin/js/draftail.js'),
            ],
            css={
                'all':
                [versioned_static('wagtailadmin/css/panels/draftail.css')]
            })

        self.features = kwargs.pop('features', None)
        if self.features is None:
            self.features = feature_registry.get_default_features()

        for feature in self.features:
            plugin = feature_registry.get_editor_plugin('draftail', feature)
            if plugin:
                plugin.construct_options(self.options)
                self._media += plugin.media

        self.converter = ContentstateConverter(self.features)

        default_attrs = {'data-draftail-input': True}
        attrs = kwargs.get('attrs')
        if attrs:
            default_attrs.update(attrs)
        kwargs['attrs'] = default_attrs

        super().__init__(*args, **kwargs)

    def format_value(self, value):
        # Convert database rich text representation to the format required by
        # the input field
        value = super().format_value(value)

        if value is None:
            value = ''

        return self.converter.from_database_format(value)

    def get_context(self, name, value, attrs):
        context = super().get_context(name, value, attrs)
        context['widget']['options_json'] = json.dumps(self.options)
        return context

    def value_from_datadict(self, data, files, name):
        original_value = super().value_from_datadict(data, files, name)
        if original_value is None:
            return None
        return self.converter.to_database_format(original_value)

    @property
    def media(self):
        return self._media
예제 #8
0
class DraftailRichTextArea(widgets.HiddenInput):
    template_name = "wagtailadmin/widgets/draftail_rich_text_area.html"
    is_hidden = False

    # this class's constructor accepts a 'features' kwarg
    accepts_features = True

    # Draftail has its own commenting
    show_add_comment_button = False

    def __init__(self, *args, **kwargs):
        # note: this constructor will receive an 'options' kwarg taken from the WAGTAILADMIN_RICH_TEXT_EDITORS setting,
        # but we don't currently recognise any options from there (other than 'features', which is passed here as a separate kwarg)
        kwargs.pop("options", None)
        self.options = {}
        self.plugins = []

        self.features = kwargs.pop("features", None)
        if self.features is None:
            self.features = feature_registry.get_default_features()

        for feature in self.features:
            plugin = feature_registry.get_editor_plugin("draftail", feature)
            if plugin is None:
                warnings.warn(
                    f"Draftail received an unknown feature '{feature}'.",
                    category=RuntimeWarning,
                )
            else:
                plugin.construct_options(self.options)
                self.plugins.append(plugin)

        self.converter = ContentstateConverter(self.features)

        default_attrs = {"data-draftail-input": True}
        attrs = kwargs.get("attrs")
        if attrs:
            default_attrs.update(attrs)
        kwargs["attrs"] = default_attrs

        super().__init__(*args, **kwargs)

    def format_value(self, value):
        # Convert database rich text representation to the format required by
        # the input field
        value = super().format_value(value)

        if value is None:
            value = ""

        return self.converter.from_database_format(value)

    def get_context(self, name, value, attrs):
        context = super().get_context(name, value, attrs)
        context["widget"]["options_json"] = json.dumps(self.options)
        return context

    def value_from_datadict(self, data, files, name):
        original_value = super().value_from_datadict(data, files, name)
        if original_value is None:
            return None
        return self.converter.to_database_format(original_value)

    @cached_property
    def media(self):
        media = Media(
            js=[
                versioned_static("wagtailadmin/js/draftail.js"),
            ],
            css={
                "all":
                [versioned_static("wagtailadmin/css/panels/draftail.css")]
            },
        )

        for plugin in self.plugins:
            media += plugin.media

        return media
예제 #9
0
class DraftailRichTextArea(widgets.HiddenInput):
    template_name = 'wagtailadmin/widgets/draftail_rich_text_area.html'

    # this class's constructor accepts a 'features' kwarg
    accepts_features = True

    def get_panel(self):
        return RichTextFieldPanel

    def __init__(self, *args, **kwargs):
        # note: this constructor will receive an 'options' kwarg taken from the WAGTAILADMIN_RICH_TEXT_EDITORS setting,
        # but we don't currently recognise any options from there (other than 'features', which is passed here as a separate kwarg)
        kwargs.pop('options', None)
        self.options = {}

        self._media = Media(js=[
            'wagtailadmin/js/draftail.js',
        ], css={
            'all': ['wagtailadmin/css/panels/draftail.css']
        })

        self.features = kwargs.pop('features', None)
        if self.features is None:
            self.features = feature_registry.get_default_features()

        for feature in self.features:
            plugin = feature_registry.get_editor_plugin('draftail', feature)
            if plugin:
                plugin.construct_options(self.options)
                self._media += plugin.media

        self.converter = ContentstateConverter(self.features)

        default_attrs = {'data-draftail-input': True}
        attrs = kwargs.get('attrs')
        if attrs:
            default_attrs.update(attrs)
        kwargs['attrs'] = default_attrs

        super().__init__(*args, **kwargs)

    def format_value(self, value):
        # Convert database rich text representation to the format required by
        # the input field
        value = super().format_value(value)

        if value is None:
            value = ''

        return self.converter.from_database_format(value)

    def get_context(self, name, value, attrs):
        context = super().get_context(name, value, attrs)
        context['widget']['options_json'] = json.dumps(self.options)
        return context

    def value_from_datadict(self, data, files, name):
        original_value = super().value_from_datadict(data, files, name)
        if original_value is None:
            return None
        return self.converter.to_database_format(original_value)

    @property
    def media(self):
        return self._media