Daily Dev Notes 2024/06/17

I added a new utility to the site tonight: the Markdown editor I had created with Pyscript. This gave me some ideas about adding new Markdown extensions to the editor. But to make this work, I had to push an update to DJ Press to allow custom extension configs.

This, of course, required a bit of refactoring with the DJ Press Markdown rendering, which, in turn, required some refactoring of the tests. But the end result is that I removed the Markdown extensions I had previously included by default, and added a new setting to add extension configs.

md = markdown.Markdown(
    extensions=settings.MARKDOWN_EXTENSIONS,
    extension_configs=settings.MARKDOWN_EXTENSION_CONFIGS,
    output_format="html",
)

This gives you full control over what you want to do with the Markdown render. For example, for this site I have the following configuration:

MARKDOWN_EXTENSIONS: list = [
    "pymdownx.superfences",
    "pymdownx.highlight",
    "tables",
    "pymdownx.emoji",
]
MARKDOWN_EXTENSION_CONFIGS: dict = {
    "pymdownx.emoji": {"emoji_generator": pymdownx.emoji.to_alt},
}

This gives me better fenced code blocks, which was an issue I had already run in to: the default fenced code extension in the Markdown package does not support the fenced block being part of a list. I had figured out a workaround for this but I didn't like it. You can see this post for an example which now works properly.

And I added emoji support too. 😄 I found a Markdown emoji cheat sheet, so will need to keep this handy. 💀

Something else interesting I discovered tonight, was that my original Markdown editor had broken and I couldn't work out why. I managed to work out that this was being broken by the djhtml pre-commit hook I use, which nicely indents my Django templates. The working code, which looks like this:

  <script type="py" config='{"packages":["markdown", "pygments", "pymdown-extensions"]}'>
    import markdown
    import pymdownx.emoji
    from pyscript import document
    extension_configs = {
      "pymdownx.emoji": {"emoji_generator": pymdownx.emoji.to_alt},
      }
    md = markdown.Markdown(extensions=["pymdownx.superfences", "pymdownx.highlight", "pymdownx.emoji", "tables"], output_format="html", extension_configs=extension_configs)
    def preview(event):
      input = document.querySelector("#editor").value
      output = document.querySelector("#preview")
      output.innerHTML = md.convert(input)
      md.reset()
  </script>

was being reformatted to this:

  <script type="py" config='{"packages":["markdown", "pygments", "pymdown-extensions"]}'>
    import markdown
    import pymdownx.emoji
    from pyscript import document
    extension_configs = {
      "pymdownx.emoji": {"emoji_generator": pymdownx.emoji.to_alt},
      }
    md = markdown.Markdown(extensions=["pymdownx.superfences", "pymdownx.highlight", "pymdownx.emoji", "tables"], output_format="html", extension_configs=extension_configs)
    def preview(event):
      input = document.querySelector("#editor").value
      output = document.querySelector("#preview")
    output.innerHTML = md.convert(input)
    md.reset()
  </script>

Can you spot the difference? I couldn't at first!

To fix this, I just excluded this template file from the pre-commit hook. Not sure if it's worth reporting this bug, since Pyscript embedded in a Django template is a bit of an edge case...