On this site and a couple of other projects, I actively use markdown to write text, and then generate html code from it. And in the end, I wrote a couple of extensions that perform some specific functionality, which somewhat facilitates the support for generating html code on my projects.
For example, in one of the projects, images are added to the text that are added to the site and attached to the post. Accordingly, images have a specific url that nginx sends this image to. But I made the markdown image embed code look simpler for images that are uploaded to the site.
Image embed code description
That is, the image insertion code in this case looks like this
![](e272ed2bca9e46e8b017c20eddd1e5b2.webp)
In this code, there is only the name of the image file e272ed2bca9e46e8b017c20eddd1e5b2.webp . On the project where this is implemented, all images are loaded into one directory with a unique generated name using uuid, and the image is compressed and converted to WEBP format. You can learn more about how to do this in the article How to convert an image to WEBP format when saving to an ImageField .
So, when images are attached to a post, they are displayed on that project as a gallery under the text, but can also be added inside the post text. But in order not to confuse users with a long url to the image in markdown markup, and also to simplify further potential modification of image paths, a function was implemented to generate an html img tag from this simplified image code.
Adding python markdown extension
Generate html text with python markdown
The Python-Markdown package is used to generate the HTML. The generation code might look like this:
def generate_html(markdown_text): return markdown.markdown( markdown_text, extensions=['markdown.extensions.attr_list', 'markdown.extensions.tables', 'markdown.extensions.fenced_code', 'markdown.extensions.nl2br', 'markdown.extensions.toc'], output_format='html5' )
As you can see, when generating it is possible to enumerate extensions that can affect the result of code generation. It is in these extensions that we will add our extension.
Add extension
Let's say in a Django project we have an app called core. Let's create an extensions directory inside it with a __init__.py file that initializes the directory as a package, as well as a file with the name of the extension. It should look like this.
-
core/
-
extensions/
- __init__.py
- image.py
-
extensions/
Image.py file
Now let's add the contents of the image.py file.
# -*- coding: utf-8 -*- import markdown from markdown.util import etree class ImageExtension(markdown.Extension): def add_inline(self, md, name, klass, re): pattern = klass(re) pattern.md = md pattern.ext = self md.inlinePatterns.add(name, pattern, "<reference") def extendMarkdown(self, md, md_globals): self.add_inline(md, 'internal_image', InternalImage, r'!\[\]\((?P<internal_image>[a-zA-Z0-9]+).webp\)') class InternalImage(markdown.inlinepatterns.Pattern): def handleMatch(self, m): return render_image(m.group('internal_image')) def render_image(internal_image_name): img = etree.Element('img') img.set('src', '/media/photos/{}.webp'.format(internal_image_name)) img.set('class', 'd-block mx-auto mw-100 mvh-75') return img def makeExtension(**kwargs): return ImageExtension(**kwargs)
In this case, we are creating an
ImageExtension
extension that extends the
Markdown
markup using the
InternalImage
template.
This pattern is applied to all image tags that match the regular expression that is passed to the add_inline method, which ultimately adds the pattern to the list of patterns with the markdown code handler.
The makeExtension function is called under the hood of Python-Markdown and registers the extension.
Conclusion
As a final word, let's add your new extension to the generation of your html code.
def generate_html(markdown_text): return markdown.markdown( markdown_text, extensions=['core.extensions.image', 'markdown.extensions.attr_list', 'markdown.extensions.tables', 'markdown.extensions.fenced_code', 'markdown.extensions.nl2br', 'markdown.extensions.toc'], output_format='html5' )
Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку:
подменять ее на свою типа:
Добрый день.
Да, можно. Либо через такие же плагины, либо с постобработкой через python библиотеку Beautiful Soup