Add LaTeX Support & Code Highlight In Wagtail

Table of Contents

Wagtail Tutorial Series:

To learn more about Wagtail CMS, please check Build Blog With Wagtail CMS (4.0.0)

  1. Create Wagtail Project
  2. Modern Frontend Techs for Wagtail
  3. Dockerizing Wagtail App
  4. Add Blog Models to Wagtail
  5. How to write Wagtail page template
  6. Create Stylish Wagtail Pages with Tailwind CSS
  7. How to use StreamField in Wagtail
  8. Wagtail Routable Page
  9. Add Pagination Component to Wagtail
  10. Customize Wagtail Page URL
  11. Add Full Text Search to Wagtail
  12. Add Markdown Support to Wagtail
  13. Add LaTeX Support & Code Highlight In Wagtail
  14. How to Build Form Page in Wagtail
  15. How to Create and Manage Menus in Wagtail
  16. Wagtail SEO Guide
  17. Online Demo http://wagtail-blog.accordbox.com/
  18. Source code: https://github.com/AccordBox/wagtail-tailwind-blog

Wagtail Tips:

  1. Wagtail Tip #1: How to replace ParentalManyToManyField with InlinePanel
  2. Wagtail Tip #2: How to Export & Restore Wagtail Site

Write style in Wagtail:

  1. How to use SCSS/SASS in your Django project (Python Way)
  2. How to use SCSS/SASS in your Django project (NPM Way)

Other Wagtail Topics:

  1. How to make Wagtail project have good coding style
  2. How to do A/B Testing in Wagtail CMS 
  3. How to build a landing page using Wagtail CMS 
  4. How to support multi-language in Wagtail CMS 
  5. Add Bootstrap Theme to Wagtail

More Wagtail articles and eBooks written by me

Objective

By the end of this chapter, you should be able to:

  1. Customize Markdown Renderer
  2. Add Latex support to the Markdown

Background

In the previous chapter, we have used wagtail-markdown to help us write content in Markdown and render it to HTML.

The markdown renderer is built on python-markdown, you can check Github source code to learn more.

We can also add extension to change, extend the behavior of the parser without having to edit the actual source files. Some extensions have been included with python-markdown, you can check the official doc to get more detail. extension

Since many Python developers work in the AI/ML area, here we will add extension to make our post page support Latex.

LaTeX is a document preparation system for high-quality typesetting which includes features designed for the production of technical and scientific documentation

MathJax is an open-source JavaScript display engine for LaTeX, MathML, and AsciiMath notation that works in all modern browsers

So here is the workflow:

  1. We tell python-markdown content in $...$ and $$...$$ is Latex
  2. We use MathJax to display the Latex content on the browser.

python-markdown-math

Update requirements.txt to add python-markdown-math

python-markdown-math==0.8
$ docker-compose build
$ docker-compose up -d
$ docker-compose logs -f

Render Markdown

Create wagtail_app/blog/utils.py

import markdown


def render_markdown(value):
    html = markdown.markdown(
        value,
        extensions=[
            "extra",
            "mdx_math",
        ],
        output_format="html5",
    )
    return html

Notes:

  1. Here we created render_markdown function, it would run Python markdown to render the markdown content to HTML
  2. The extra is built-in extension from Python markdown
  3. mdx_math is from python-markdown-math

Templates

Update wagtail_app/blog/templatetags/blogapp_tags.py

from wagtail_app.blog.utils import render_markdown


@register.filter(name='markdown')
def markdown(value):
    return render_markdown(value)

We created a custom Django filter markdown

Update wagtail_app/templates/blog/components/streamfield.html

{% load static wagtailcore_tags blogapp_tags %}

{% with blocks=page.body %}
  {% for block in blocks %}
    {% if block.block_type == 'h1' %}
      <div>
        <h1>{{ block.value }}</h1>
      </div>
    {% elif block.block_type == 'h2' %}
      <div>
        <h2>{{ block.value }}</h2>
      </div>
    {% elif block.block_type == 'paragraph' %}
      <div>
        {{ block.value|richtext }}
      </div>
    {% elif block.block_type == 'image_text' %}
      <div>
        {% include 'blog/blocks/image_text.html' with block=block only %}
      </div>
    {% elif block.block_type == 'image_carousel' %}
      <div>
        {% include 'blog/blocks/image_carousel.html' with block=block only %}
      </div>
    {% elif block.block_type == 'markdown' %}
      {{ block.value|markdown|safe }}
    {% else %}
      <section class="block-{{ block.block_type }}">
        {{ block }}
      </section>
    {% endif %}
  {% endfor %}
{% endwith %}

Notes:

  1. For markdown type, we use the custom markdown filter to process it and render it to HTML.
  2. By default, Django would do auto-escape, we can disable this behavior with the safe filter. You can check Django doc: safe tag to learn more.
  3. If you want to sanitize html generated from markdown, please check bleach and this code

MathJax

Update wagtail_app/templates/blog/post_page.html

{% extends "base.html" %}

{% block content %}
   ...
{% endblock %}

{% block extra_js %}
  <script type="text/x-mathjax-config">
      MathJax.Hub.Config({
        extensions: ["tex2jax.js"],
        jax: ["input/TeX", "output/HTML-CSS"],
        tex2jax: {
          inlineMath: [['$','$']],
          displayMath: [['$$','$$']] ,
          processEscapes: true
        },
        "HTML-CSS": { availableFonts: ["TeX"] }
      });
  </script>
  <script type="text/javascript"
          src="https://cdn.jsdelivr.net/npm/[email protected]/MathJax.js">
  </script>
{% endblock %}

Notes:

  1. We added MathJax code to the extra_js block.
  2. What you should notice is the inlineMath and displayMath in the config section. Let's take a look at the final result.

Notes:

Python has great ecosystem, if you want to do more with Markdown, you can check:

  1. pymdown-extensions

Wagtail Tutorial Series:

To learn more about Wagtail CMS, please check Build Blog With Wagtail CMS (4.0.0)

  1. Create Wagtail Project
  2. Modern Frontend Techs for Wagtail
  3. Dockerizing Wagtail App
  4. Add Blog Models to Wagtail
  5. How to write Wagtail page template
  6. Create Stylish Wagtail Pages with Tailwind CSS
  7. How to use StreamField in Wagtail
  8. Wagtail Routable Page
  9. Add Pagination Component to Wagtail
  10. Customize Wagtail Page URL
  11. Add Full Text Search to Wagtail
  12. Add Markdown Support to Wagtail
  13. Add LaTeX Support & Code Highlight In Wagtail
  14. How to Build Form Page in Wagtail
  15. How to Create and Manage Menus in Wagtail
  16. Wagtail SEO Guide
  17. Online Demo http://wagtail-blog.accordbox.com/
  18. Source code: https://github.com/AccordBox/wagtail-tailwind-blog

Wagtail Tips:

  1. Wagtail Tip #1: How to replace ParentalManyToManyField with InlinePanel
  2. Wagtail Tip #2: How to Export & Restore Wagtail Site

Write style in Wagtail:

  1. How to use SCSS/SASS in your Django project (Python Way)
  2. How to use SCSS/SASS in your Django project (NPM Way)

Other Wagtail Topics:

  1. How to make Wagtail project have good coding style
  2. How to do A/B Testing in Wagtail CMS 
  3. How to build a landing page using Wagtail CMS 
  4. How to support multi-language in Wagtail CMS 
  5. Add Bootstrap Theme to Wagtail

More Wagtail articles and eBooks written by me

Launch Products Faster with Django

SaaS Hammer helps you launch products in faster way. It contains all the foundations you need so you can focus on your product.

Michael Yin

Michael is a Full Stack Developer from China who loves writing code, tutorials about Django, and modern frontend tech.

He has published some ebooks on leanpub and tech course on testdriven.io.

He is also the founder of the AccordBox which provides the web development services.

Django SaaS Template

It aims to save your time and money building your product

Learn More

This book will teach you how to build a SPA (single-page application) with React and Wagtail CMS

Read More
© 2018 - 2024 AccordBox