Search code examples
djangodjango-templateswagtailhallo-js

Wagtail: How to override HTML tag output from database. Use <strong> or <em> instead of <b> or <i> for richtext template tag


I am trying to have my wagtail template output <strong></strong> instead of <b></b> and <em></em> instead of <i></i>.

I manually edited the content_json values within the wagtailcore_pagerevision table records so that the <b> tags are <strong> and the <i> tags are <em> but the output HTML continues to output <b> and <i> tags respectively.

In my template I have {{ block.value|richtext }} for block and {{ self.body|richtext }} for non blocks.

The wagtail code doing the work is:

@register.filter
def richtext(value):
    if isinstance(value, RichText):
        # passing a RichText value through the |richtext filter should have no effect
        return value
    elif value is None:
        html = ''
    else:
        html = expand_db_html(value)

    return mark_safe('<div class="rich-text">' + html + '</div>')

My question is.. how can i tell Wagtail or Django to use <strong> and <em> tags?

This does not seem to be a hallo-js WYSIWYG issue or setting, but rather some sort of configuration or other setting that I cannot seem to find.

BTW.. I am using Wagtail 1.13.1 (with default Hallo editor), Django 1.11 and MySQL as the database.

To overcome my issue, i am overriding with this code..

# override the wagtail version and replace <b>, <i>
@register.filter(name='richtext')
def richtext(value):
    if isinstance(value, RichText):
        # passing a RichText value through the |richtext filter should have no effect
        # return value
        html = value.source
    elif value is None:
        html = ''
    else:
        html = expand_db_html(value)

    html = html.replace('<b>', '<strong>').replace('</b>', '</strong>') \
            .replace('<i>', '<em>').replace('</i>', '</em>')

    return mark_safe('<div class="rich-text">' + html + '</div>')

but there should be a better, more efficient way.


Solution

  • I got the same issue and asked on the Wagtail Slack support channel. I got the advice to register a new rich text feature. The documentation shows a strikethrough example. Here are bold (strong) and italic (em):

    import wagtail.admin.rich_text.editors.draftail.features as draftail_features
    from wagtail.admin.rich_text.converters.html_to_contentstate import (
        InlineStyleElementHandler,
    )
    
    
    @hooks.register('register_rich_text_features')
    def register_strong_feature(features):
        """
        Registering the `strong` feature. It will render bold text with `strong` tag.
        Default Wagtail uses the `b` tag.
        """
        feature_name = 'strong'
        type_ = 'BOLD'
        tag = 'strong'
    
        # Configure how Draftail handles the feature in its toolbar.
        control = {
            'type': type_,
            'icon': 'bold',
            'description': 'Bold',
        }
    
        # Call register_editor_plugin to register the configuration for Draftail.
        features.register_editor_plugin(
            'draftail', feature_name, draftail_features.InlineStyleFeature(control)
        )
    
        # Configure the content transform from the DB to the editor and back.
        db_conversion = {
            'from_database_format': {tag: InlineStyleElementHandler(type_)},
            'to_database_format': {'style_map': {type_: tag}},
        }
    
        # Call register_converter_rule to register the content transformation conversion.
        features.register_converter_rule('contentstate', feature_name, db_conversion)
    

    And italics with the <em> tag:

    @hooks.register('register_rich_text_features')
    def register_em_feature(features):
        """
        Registering the `em` feature. It will render italic text with `em` tag.
        Default Wagtail uses the `i` tag.
        """
        feature_name = 'em'
        type_ = 'ITALIC'
        tag = 'em'
    
        control = {
            'type': type_,
            'icon': 'italic',
            'description': 'Italic',
        }
    
        features.register_editor_plugin(
            'draftail', feature_name, draftail_features.InlineStyleFeature(control)
        )
    
        db_conversion = {
            'from_database_format': {tag: InlineStyleElementHandler(type_)},
            'to_database_format': {'style_map': {type_: tag}},
        }
    
        features.register_converter_rule('contentstate', feature_name, db_conversion)
    

    Specify the features on your rich text fields. Don't forget to remove the old 'bold' and 'italic':

    from wagtail.core.fields import RichTextField
    
    class FooPage(Page):
        body = RichTextField(features=['strong', 'em'])