wagtail-nest / wagtail-hallo

Wagtail's legacy Hallo.js richtext editor
https://pypi.org/project/wagtail-hallo/
MIT License
5 stars 7 forks source link
hallo wagtail

Wagtail Hallo - Rich Text Editor

License: MIT Wagtail Hallo CI PyPI version

This is the legacy rich text editor for the Wagtail CMS. Based on Hallo.js.

As of Wagtail 2.0, the hallo.js editor is deprecated.

Status See supported versions for Wagtail compatibility, however, this package will no longer receive bug fixes or be actively maintained. Pull requests will be accepted and if maintainers wish to support this outside of the core Wagtail team, please raise an issue to discuss this.

Major risks of using this package

Release Notes

Supported Versions

Installing the Hallo Editor

To use wagtail-hallo on Wagtail, add the following to your settings:

WAGTAILADMIN_RICH_TEXT_EDITORS = {
    'hallo': {
        'WIDGET': 'wagtail_hallo.hallo.HalloRichTextArea'
    }
}

Using the Hallo Editor in RichTextField

# models.py
from wagtail.admin.panels import FieldPanel
from wagtail.fields import RichTextField
from wagtail.models import Page

class MyHalloPage(Page):
    body = RichTextField(editor='hallo')

    content_panels = Page.content_panels + [
        FieldPanel('body', classname='full'),
    ]
{% extends "base.html" %}
{% load wagtailcore_tags wagtailimages_tags %}

{% block content %}
    {% include "base/include/header.html" %}
    <div class="container">
        <div class="row">
            <div class="col-md-7">{{ page.body|richtext }}</div>
        </div>
    </div>
{% endblock content %}

Using the Hallo Editor in StreamField via RichTextBlock

# models.py
from wagtail.models import Page
from wagtail.blocks import CharBlock, RichTextBlock
from wagtail.admin.panels import FieldPanel
from wagtail.fields import StreamField

class MyOtherHalloPage(Page):
    body = StreamField([
        ('heading', CharBlock(form_classname="full title")),
        ('paragraph', RichTextBlock(editor='hallo')),
    ], blank=True)

    content_panels = Page.content_panels + [
        FieldPanel('body'),
    ]
{% extends "base.html" %}
{% load wagtailcore_tags wagtailimages_tags %}

{% block content %}
    {% include "base/include/header.html" %}
    <div class="container">
        <div class="row">
            <div class="col-md-7">{{ page.body }}</div>
        </div>
    </div>
{% endblock content %}

Extending the Hallo Editor

The legacy hallo.js editor’s functionality can be extended through plugins. For information on developing custom hallo.js plugins, see the project's page: https://github.com/bergie/hallo.

Once the plugin has been created, it should be registered through the feature registry's register_editor_plugin(editor, feature_name, plugin) method. For a hallo.js plugin, the editor parameter should always be 'hallo'.

A plugin halloblockquote, implemented in myapp/js/hallo-blockquote.js, that adds support for the <blockquote> tag, would be registered under the feature name block-quote as follows:

    from wagtail import hooks
    from wagtail_hallo.plugins import HalloPlugin

    @hooks.register('register_rich_text_features')
    def register_embed_feature(features):
        features.register_editor_plugin(
            'hallo', 'block-quote',
            HalloPlugin(
                name='halloblockquote',
                js=['myapp/js/hallo-blockquote.js'],
            )
        )

The constructor for HalloPlugin accepts the following keyword arguments:

When writing the front-end code for the plugin, Wagtail’s Hallo implementation offers two extension points:

Whitelisting rich text elements

After extending the editor to support a new HTML element, you'll need to add it to the whitelist of permitted elements - Wagtail's standard behaviour is to strip out unrecognised elements, to prevent editors from inserting styles and scripts (either deliberately, or inadvertently through copy-and-paste) that the developer didn't account for.

Elements can be added to the whitelist through the feature registry's register_converter_rule(converter, feature_name, ruleset) method. When the hallo.js editor is in use, the converter parameter should always be 'editorhtml'.

The following code will add the <blockquote> element to the whitelist whenever the block-quote feature is active:


    from wagtail.admin.rich_text.converters.editor_html import WhitelistRule
    from wagtail.whitelist import allow_without_attributes

    @hooks.register('register_rich_text_features')
    def register_blockquote_feature(features):
        features.register_converter_rule('editorhtml', 'block-quote', [
            WhitelistRule('blockquote', allow_without_attributes),
        ])

WhitelistRule is passed the element name, and a callable which will perform some kind of manipulation of the element whenever it is encountered. This callable receives the element as a BeautifulSoup Tag object.

The wagtail.whitelist module provides a few helper functions to assist in defining these handlers: allow_without_attributes, a handler which preserves the element but strips out all of its attributes, and attribute_rule which accepts a dict specifying how to handle each attribute, and returns a handler function. This dict will map attribute names to either True (indicating that the attribute should be kept), False (indicating that it should be dropped), or a callable (which takes the initial attribute value and returns either a final value for the attribute, or None to drop the attribute).

Contributing

All contributions are welcome as the Wagtail core team will no longer be actively maintaining this project.

Development instructions

Python (Django / Wagtail)

JavaScript & CSS (Frontend)

Currently the frontend tooling is based on Node & NPM and is only used to format and check code. This repository intentionally does not use any build tools and as such JavaScript and CSS must be written without that requirement.

Release checklist

Thanks

Many thanks to all of our supporters, contributors, and users of Wagtail who built upon the amazing Hallo.js editor. We are thankful to the Wagtail core team and developers at Torchbox who sponsored the majority of the initial development. Thank you to LB, who transferred the Hallo.js integration from Wagtail to the wagtail-hallo package. And a very special thanks to the original creator of the Hallo.js editor.