Adding back underlines to Wagtail Rich Text

#python #django #programming #wagtail

Wagtail is a popular CMS choice for Django, but I'm really rethinking if I should move from Django CMS due to some of its choices and flaws.

I'm assuming a Google search brought you here or you're familiar with the subject at hand. As the Wagtail website says, Wagtail is the the leading open-source Python CMS and to my experience that is mostly true. It can act as a headless CMS, it has native REST support and the editor is simply sublime.

The issue

While working at Queo I've been using Django CMS for almost a decade and I've been increasingly bothered by their editing choices. Due to their choice of frontend editing moving from Django CMS 2 to 3, users have to bother splitting their time managing two backoffices, one for regular pages (frontend editing) and other for features outside the CMS scope (backend editing). Almost a decade later, I'm still salty about the transition from backend to frontend editing.

Not everything works as well as I wanted to. I've been spoiled by the immense choice Django CMS and CKEditor gives to the user and that's one of the things the Wagtail team simply refuses to do. Case in point: the underline.

It's not the first and probably won't be the last. WriteFreely does the same, there's no option for an underline because Markdown doesn't use it and it's deprecated in HTML5.

Despite that, I have clients, and clients have needs. I need to keep them happy in order to be paid. As long as underline is supported and they think it's the best thing ever since italics, it'll be my mission to place them regardless of my feelings.

There's another huge issue with multilingual support I'll talk later but for now, enough griping.

Fixing the issue

Wagtail has very good documentation. One of the thinks it allows us to do is to extend richtext features

For this specific purpose where you have an inline tag (<u>), it's easy to do by writing the following in your wagtail_hooks.py

@hooks.register("register_rich_text_features")
def register_underline_feature(features):
    """
    Registering the `underline` feature, which uses the `UNDERLINE` Draft.js inline style type,
    and is stored as HTML with a `<u>` tag.
    """
    feature_name = "underline"
    type_ = "UNDERLINE"
    tag = "u"

    control = {
        "type": type_,
        # icon doesn't work when it should. Intentional??
        # "icon": "underline",
        "label": "U͟",
        "description": "Underline",
        "style": {"textDecoration": "underline"},
    }

    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)

    features.default_features.append("underline")

Don't forget to add underline to the settings if you're limiting options on your WAGTAILADMIN_RICH_TEXT_EDITORS

WAGTAILADMIN_RICH_TEXT_EDITORS = {
    "default": {
        "WIDGET": "wagtail.admin.rich_text.DraftailRichTextArea",
        "OPTIONS": {
-            "features": ["bold", "italic", "link", "superscript", "subscript"],
+            "features": ["bold", "italic", "underline", "link", "superscript", "subscript"],
        },
    },
}