Package: wagtail-markdown
wagtail-markdown: Markdown fields and blocks for WagtailTired of annoying rich text editors getting in the way of your content
input?  Wish Wagtail worked more like a wiki?  Well, now it can.wagtail-markdownprovides Markdown field support forWagtail.
Specifically, it provides:Awagtailmarkdown.blocks.MarkdownBlockfor use in StreamFields.Awagtailmarkdown.fields.MarkdownFieldfor use in Page models.Awagtailmarkdown.edit_handlers.MarkdownPanelfor use in the editor interface.Amarkdowntemplate tag.The markdown rendered is based onpython-markdown, but with several
extensions to make it actually useful in Wagtail:Code highlighting.Inline links.Inline Markdown preview usingEasyMDETablesThese are implemented using thepython-markdownextension interface.InstallationAvailable on PyPI -https://pypi.org/project/wagtail-markdown/.Install using pip (pip install wagtail-markdown), poetry (poetry add wagtail-markdown) or your package manager of choice.After installing the package, addwagtailmarkdownto the list of installed apps in your settings file:# settings.pyINSTALLED_APPS=[# ..."wagtailmarkdown",]ConfigurationAllwagtail-markdownsettings are defined in a singleWAGTAILMARKDOWNdictionary in your settings file:# settings.pyWAGTAILMARKDOWN={"autodownload_fontawesome":False,"allowed_tags":[],# optional. a list of HTML tags. e.g. ['div', 'p', 'a']"allowed_styles":[],# optional. a list of styles"allowed_attributes":{},# optional. a dict with HTML tag as key and a list of attributes as value"allowed_settings_mode":"extend",# optional. Possible values: "extend" or "override". Defaults to "extend"."extensions":[],# optional. a list of python-markdown supported extensions"extension_configs":{},# optional. a dictionary with the extension name as key, and its configuration as value"extensions_settings_mode":"extend",# optional. Possible values: "extend" or "override". Defaults to "extend".}Note:allowed_tags,allowed_styles,allowed_attributes,extensionsandextension_configsare added to thedefault wagtail-markdown settings.Custom FontAwesome Configuration -autodownload_fontawesomeThe EasyMDE editor is compatible withFontAwesome 5.
By default, EasyMDE will get version 4.7.0 from a CDN. To specify your own version, set# settings.pyWAGTAILMARKDOWN={# ..."autodownload_fontawesome":False,}Get the desired FontAwesome version. For the latest version you can use:curl-H"Content-Type: application/json"\-d'{ "query": "query { release(version: \"latest\") { version } }" }'\https://api.fontawesome.comthen add the following to awagtail_hooksmodule in a registered app in your application:# Content of app_name/wagtail_hooks.pyfromwagtailimporthooksfromdjango.confimportsettingsfromdjango.utils.htmlimportformat_html@hooks.register("insert_global_admin_css")defimport_fontawesome_stylesheet():elem='<link rel="stylesheet" href="{}path/to/font-awesome.min.css">'.format(settings.STATIC_URL)returnformat_html(elem)Note that due to the way EasyMDE defines the toolbar icons it is not compatible withWagtail FontAwesomeUsing with django-compressorYou may have your own SCSS sources that you want to precompile on the fly.
We can invoke django-compressor to fetch our Font Awesome SCSS sources like this:# Content of app_name/wagtail_hooks.pyfromcompressor.cssimportCssCompressorfromwagtailimporthooksfromdjango.confimportsettingsfromdjango.utils.htmlimportformat_html@hooks.register("insert_global_admin_css")defimport_fontawesome_stylesheet():elem='<link rel="stylesheet" type="text/x-scss" href="{}scss/fontawesome.scss">'.format(settings.STATIC_URL)compressor=CssCompressor("css",content=elem)output=""forsincompressor.hunks():output+=sreturnformat_html(output)Markdown extensions -extensions/extension_configsYou can configure wagtail-markdown to use additional Markdown extensions using theextensionssetting.For example, to enable theTable of ContentsandSane Listsextensions:WAGTAILMARKDOWN={# ..."extensions":["toc","sane_lists"]}Extensions can be configured too:WAGTAILMARKDOWN={# ..."extension_configs":{"pymdownx.arithmatex":{"generic":True}}}Allowed HTML -allowed_styles/allowed_attributes/allowed_tagswagtail-markdown usesbleachto sanitise the input. To extend the default
bleach configurations, you can add your own allowed tags, styles or attributes:WAGTAILMARKDOWN={# ..."allowed_tags":["i"],"allowed_styles":["some_style"],"allowed_attributes":{"i":["aria-hidden"]},}Syntax highlightingSyntax highlighting using codehilite is an optional feature, which works by
adding CSS classes to the generated HTML. To use these classes, you will need
to install Pygments (pip install Pygments), and to generate an appropriate
stylesheet. You can generate one as per thePygments documentation, with:frompygments.formattersimportHtmlFormatterprint(HtmlFormatter().get_style_defs(".codehilite"))Save the output to a file and reference it somewhere that will be
picked up on pages rendering the relevant output, e.g. your base template:<linkrel="stylesheet"type="text/css"href="{%static'path/to/pygments.css'%}">EasyMDE configurationYou can customise theEasyMDE options. To do this,
create a JavaScript file in your app (for examplemy_app_name/static/js/easymde_custom.js) and add the following:window.wagtailMarkdown=window.wagtailMarkdown||{};window.wagtailMarkdown.options=window.wagtailMarkdown.options||{};window.wagtailMarkdown.options.spellChecker=false;This overrides a specific option and leaves any other ones untouched. If you want to override all options, you can do:window.wagtailMarkdown=window.wagtailMarkdown||{};window.wagtailMarkdown.options={spellChecker:false,}To make sure that your JavaScript is executed, create a hook inmy_app_name/wagtail_hooks.py:fromdjango.templatetags.staticimportstaticfromdjango.utils.htmlimportformat_htmlfromwagtailimporthooks@hooks.register("insert_global_admin_js",order=100)defglobal_admin_js():"""Add /static/js/admin/easymde_custom.js to the admin."""returnformat_html('<script src="{}"></script>',static("js/easymde_custom.js"))Inline linkswagtail-markdown supports custom inline links syntax:Link toSyntaxNotesPages[title](page:PAGE_ID)PAGE_IDis the page IDDocuments[title](doc:DOCUMENT_ID)DOCUMENT_IDis the document IDMedia[title](media:MEDIA_ID)Needswagtailmedia.MEDIA_IDis the media item IDImages![alt text](image:IMAGE_ID)Renders an image tag.IMAGE_IDis the image ID↳ with class attribute![alt text](image:IMAGE_ID,class=the-class-name)addsclass="the-class-name" to the` tag↳ with rendition filter![alt text](image:IMAGE_ID,filter=fill-200x200&#x7c;format-webp)Uses the same format asgenerating renditions in Python↳ class name and filter can be stacked![alt text](image:IMAGE_ID,class=the-class-name,filter=width-100)Previously we supported custom link tags that used the target object title. They had the following form:<:My page name|link title>or<:page:My page title><:doc:My fancy document.pdf><:image:My pretty image.jpeg>,<:image:My pretty image.jpeg|left>(leftclassname),<:image:My pretty image.jpeg|right>(rightclassname),<:image:My pretty image.jpeg|full>(full-nameclassname),<:image:My pretty image.jpeg|width=123>(outputs a rendition withwidth-123, and classleft)⚠️ these types of tags are not reliable as titles can and will change. Support for  will be removed in the future.UsageYou can use it as aStreamFieldblock:fromwagtail.blocksimportStreamBlockfromwagtailmarkdown.blocksimportMarkdownBlockclassMyStreamBlock(StreamBlock):markdown=MarkdownBlock(icon="code")# ...Or use as a page field:fromwagtail.admin.panelsimportFieldPanelfromwagtail.modelsimportPagefromwagtailmarkdown.fieldsimportMarkdownFieldclassMyPage(Page):body=MarkdownField()content_panels=[FieldPanel("title",classname="full title"),FieldPanel("body"),]And render the content in a template:{%loadwagtailmarkdown%}<article>{{self.body|markdown}}</article>Compatibilitywagtail-markdown supports Wagtail 4.1 and above, python-markdown 3.3 and above.ContributingAll contributions are welcome!InstallationTo make changes to this project, first clone this repository:gitclonegit@github.com:torchbox/wagtail-markdown.gitcdwagtail-markdownWith your preferred Python virtual environment activated, install testing dependencies:pipinstall-e'.[testing]'-Upre-commitNote that this project usespre-commit. To set up locally:# if you don't have it yet$pipinstallpre-commit# go to the project directory$cdwagtail-markdown# initialize pre-commit$pre-commitinstall# Optional, run all checks once for this, then the checks will run only on the changed files$pre-commitrun--all-filesHow to run testsTo run all tests in all environments:tox-pTo run tests for a specific environment:tox-epy311-django3.2-wagtail4.1or, a specific testtox-epy311-django3.2-wagtail4.1--tests.testapp.tests.test_admin.TestFieldsAdmin