Package: wagtaildraftail
wagtaildraftail 🐦📝🍸Draft.js editor for Wagtail, built uponDraftailanddraftjs_exporter.This is alpha software, use at your own risk. Do not use in production (yet).Check outAwesome Wagtailfor more awesome packages and resources from the Wagtail community.InstallationGrab the package from pip withpip install wagtaildraftail, then addwagtaildraftailas an app in your Django settings.Note: this package contains compiled (bundled, minified) JavaScript and CSS, it can only be installed directly from pip.UsageThere is a basic test site set up in thetestsfolder for reference.With PagesFirst, add a Draftail field to some of your pages. Here is an example:fromwagtaildraftail.fieldsimportDraftailTextFieldclassMyPage(Page):body=DraftailTextField(blank=True)panels=[FieldPanel('body')]Then, when displaying those fields, use therichtextfilter in the templates.{% load wagtailcore_tags %}

{% block content %}
    {{ page.body|richtext }}
{% endblock %}With StreamFieldHere is an example using the ready-made block:fromwagtaildraftail.blocksimportDraftailTextBlockclassMyStructBlock(StructBlock):body=DraftailTextBlock()ConfigurationBothDraftailTextFieldandDraftailTextBlockaccept a string as keyword argumenteditorfor a per field customisation.Wagtail will look for aWAGTAILADMIN_RICH_TEXT_EDITORSconstants in the settings, find the requested editor, load the defined widget and pass the options (if defined) to it.Each editor defined inWAGTAILADMIN_RICH_TEXT_EDITORSis a dictionary with 2 keys:,WIDGET(mandatory) andOPTIONS(optional).WIDGETis a mandatory string set to the widget to use
-  should always be set towagtaildraftail.widgets.DraftailTextArea(or a subclass of it) to work with Draft.js contentOPTIONSis a dictionary which follows the format ofDraftail configuration options.
-  Draftail options which are JavaScript values are hydrated at runtime inclient/wagtaildraftail.jsWARNING:Thetypekey forblockTypes,inlineStylesandentityTypesshouldn’t be changed. It is what defines how content is rendered, and is saved as a JSON blob in the database which would make migrations really painful.WARNING:All the blocks/styles/entities defined in the editor config should have been configured to render properly in theexporter config.Here is a sample configuration file. This should live in your Django settings.fromdraftjs_exporter.constantsimportBLOCK_TYPES,ENTITY_TYPES,INLINE_STYLESfromdraftjs_exporter.defaultsimportBLOCK_MAPTERMS_BLOCK_ID='TERMS_AND_CONDITIONS_TEXT'DRAFT_BLOCK_TYPE_H3={'label':'H3','type':BLOCK_TYPES.HEADER_THREE}DRAFT_BLOCK_TYPE_H4={'label':'H4','type':BLOCK_TYPES.HEADER_FOUR}DRAFT_BLOCK_TYPE_UL={'label':'UL','type':BLOCK_TYPES.UNORDERED_LIST_ITEM,'icon':'icon-list-ul'}DRAFT_BLOCK_TYPE_OL={'label':'OL','type':BLOCK_TYPES.ORDERED_LIST_ITEM,'icon':'icon-list-ol'}DRAFT_BLOCK_TYPE_TERMS={'label':'T&Cs','type':TERMS_BLOCK_ID,'element':'div','class':'legals'}DRAFT_INLINE_STYLE_BOLD={'label':'Bold','type':INLINE_STYLES.BOLD,'icon':'icon-bold'}DRAFT_INLINE_STYLE_ITALIC={'label':'Italic','type':INLINE_STYLES.ITALIC,'icon':'icon-italic'}# It accepts a list of dicts with `label` and `value` keys (e.g. `{'label': 'Full width', 'value': 'fullwidth'}`)# or a special `__all__` value which will be intercepted and will load all image formats known to Wagtail.DRAFT_IMAGE_FORMATS='__all__'DRAFT_ENTITY_TYPE_IMAGE={'label':'Image','type':ENTITY_TYPES.IMAGE,'icon':'icon-image','imageFormats':DRAFT_IMAGE_FORMATS,'source':'ImageSource','decorator':'Image',}DRAFT_ENTITY_TYPE_EMBED={'label':'Embed','type':ENTITY_TYPES.EMBED,'icon':'icon-media','source':'EmbedSource','decorator':'Embed',}DRAFT_ENTITY_TYPE_LINK={'label':'Link','type':ENTITY_TYPES.LINK,'icon':'icon-link','source':'LinkSource','decorator':'Link',}DRAFT_ENTITY_TYPE_DOCUMENT={'label':'Document','type':ENTITY_TYPES.DOCUMENT,'icon':'icon-doc-full','source':'DocumentSource','decorator':'Document',}WAGTAILADMIN_RICH_TEXT_EDITORS={'default_draftail':{'WIDGET':'wagtaildraftail.widgets.DraftailTextArea','OPTIONS':{'enableHorizontalRule':True,'enableLineBreak':False,'entityTypes':[DRAFT_ENTITY_TYPE_LINK,DRAFT_ENTITY_TYPE_DOCUMENT,],'blockTypes':[DRAFT_BLOCK_TYPE_H3,DRAFT_BLOCK_TYPE_UL,],'inlineStyles':[DRAFT_INLINE_STYLE_BOLD,DRAFT_INLINE_STYLE_ITALIC,],}},'format_and_link':{'WIDGET':'wagtaildraftail.widgets.DraftailTextArea','OPTIONS':{'entityTypes':[DRAFT_ENTITY_TYPE_LINK,],'inlineStyles':[DRAFT_INLINE_STYLE_BOLD,DRAFT_INLINE_STYLE_ITALIC,],}},# Wagtail dependencies'default':{'WIDGET':'wagtail.wagtailadmin.rich_text.HalloRichTextArea'},'custom':{'WIDGET':'wagtail.tests.testapp.rich_text.CustomRichTextArea'},}DRAFT_EXPORTER_ENTITY_DECORATORS={ENTITY_TYPES.LINK:'wagtaildraftail.decorators.Link',ENTITY_TYPES.DOCUMENT:'wagtaildraftail.decorators.Document',ENTITY_TYPES.IMAGE:'wagtaildraftail.decorators.Image',ENTITY_TYPES.EMBED:'wagtaildraftail.decorators.Embed',ENTITY_TYPES.HORIZONTAL_RULE:'wagtaildraftail.decorators.HR',}DRAFT_EXPORTER_COMPOSITE_DECORATORS=['wagtaildraftail.decorators.BR',]DRAFT_EXPORTER_BLOCK_MAP=dict(BLOCK_MAP,**{BLOCK_TYPES.UNORDERED_LIST_ITEM:{'element':'li','wrapper':'ul','wrapper_props':{'class':'list-styled'},},BLOCK_TYPES.ORDERED_LIST_ITEM:{'element':'li','wrapper':'ol','wrapper_props':{'class':'list-numbered'},},TERMS_BLOCK_ID:{'element':'p','props':{'class':'legals'},},})Creating new content formatsTODOCreating blocks and inline stylesTODOCreating entitiesAn entity basically needs 4 elements:a pagedecorator.an editordecorator.an editorsource.an editorstrategy.Decorators define how the content needs to be displayed on the site’s pages, as well as within the editor.For the pages, they are defined in Python withdraftjs_exporter. Refer to the dedicated documentation onthe draftjs_exporter README.For the editor, they are defined in JS/React withdraftail. Refer to the dedicated documentation onthe Draftail README.Sources define the interface (usually a modal) through which the user will select an entity to insert into the editor.Strategies allow the editor to identify entities when it is loaded. Strategies are optional as the default one works fine in most cases.Both sources and strategies are defined in JS/React withdraftail. Refer to the dedicated documentation onthe Draftail README.To register decorators, sources or strategies towagtaildraftail, use the corresponding register function:window.wagtailDraftail.registerDecorators({LinkDecorator,ButtonDecorator});window.wagtailDraftail.registerSources({LinkSource});window.wagtailDraftail.registerStrategies({LinkStrategy});Note: In order forwagtailDraftailand its register functions to be available in the globalwindownamespace, make sure thatwagtaildraftailappears before any other app which will try to register an entity inINSTALED_APPS.DevelopmentInstallationRequirements:virtualenv,pyenv,twinegitclonegit@github.com:springload/wagtaildraftail.gitcdwagtaildraftail/virtualenv.venvsource./.venv/bin/activatemakeinit# Install all tested python versionspyenvinstall2.7.11&&pyenvinstall3.3.6&&pyenvinstall3.4.4&&pyenvinstall3.5.1pyenvglobalsystem2.7.113.3.63.4.43.5.1Commandsmakehelp# See what commands are available.makeinit# Install dependencies and initialise for development.makestart# Starts the development server and compilation tools.makelint# Lint the project.makeload-data# Prepares the database for usage.maketest# Test the project.maketest-coverage# Run the tests while generating test coverage data.maketest-ci# Continuous integration test suite.makeclean-pyc# Remove Python file artifacts.makedist# Compile the JS and CSS for release.makepublish# Publishes a new version to pypi.DebuggingTo get up and running,# Set up the development environment.makeinit# Start the development server.makestart# If necessary, start the JS compilation watchnpmrunstartThere are testing and linting tasks available both in the Makefile (Python) and package.json (JS).Updating test dataHere are useful commands:# Create new migrations from changes to the project.pythontests/manage.pymakemigrations# "Reset" the database.rmdb.sqlite3# Generate fixtures from DB data. Remember to clean them up so they do not overlap with data from migrations.pythontests/manage.pydumpdata>tests/fixtures/test_data.jsonReleasesMake a new branch for the release of the new version.Update theCHANGELOG.Update the version number inwagtaildraftail/__init__.pyandpackage.json, following semver.Make a PR and squash merge it.Back on master with the PR merged, usemake publish(confirm, and enter your password).Finally, go to GitHub and create a release and a tag for the new version.Done!DocumentationSee thedocsfolder