I'm trying to pass the contents of an.md file from my Django view for rendering using Showdown (JS code below), but I get: Uncaught SyntaxError: Invalid or unexpected token:var converter = new. Mar 30, 2020 To extend Markdown with our unique Django capabilities, we are going to develop an extension of our own. Creating a Markdown Extension to Process Inline Links. If you look at the source, you'll see that to convert markdown to HTML, Markdown uses different processors. One type of processor is an inline processor. Inline processors match specific.
Introduction
As part of managing the PB Python newsletter, I wanted to develop a simple way towrite emails once using plain text and turn them into responsive HTML emails for the newsletter.In addition, I needed to maintain a static archive page on the blog that links to the content of eachnewsletter. This article shows how to use python tools to transform a markdown file into a responsive HTMLemail suitable for a newsletter as well as a standalone page integrated into a pelican blog.
Rationale
I am a firm believer in having access to all of the content I create in a simple text format. That is partof the reason why I use pelican for the blog and write all content in restructured text.I also believe in hosting the blog using static HTML so it is fast for readers and simple to distribute.Since I spend a lot of time creating content, I want to make sure I can easily transform it into anotherformat if needed. Plain text files are the best format for my needs.
As I wrote in my previous post, Mailchimp was getting cost prohibitive. In addition, I didnot like playing around with formatting emails. I want to focus on content and turning it intoa clean and responsive email - not working with an online email editor. I also want the newsletterarchives available for people to view and search in a more integrated way with the blog.
One thing that Mailchimp does well is that it provides an archive of emailsand ability for the owner to download them in raw text. However, once you cancel your account,those archives will go away. It’s also not very search engine friendly so it’s hard to reference backto it and expose the content to others not subscribed to the newsletter.
With all that in mind, here is the high level process I had in mind:
HTML Email
Before I go through the python scripts, here’s some background on developing responsive HTML-basedemails. Unfortunately, building a template that works well in all email clients is not easy. I naively assumedthat the tips and tricks that work for a web site would work in an HTML email. Unfortunately that is not the case.The best information I could find is that you need to use HTML tables to format messages so they will look acceptablein all the email clients. Yuck. I feel like I’m back in Geocities.
This is one of the benefits that email vendors like Mailchimp provide. They will go through all thehard work of figuring out how to make templates that look good everywhere. For somethis makes complete sense. For my simple needs, it was overkill. Your mileage may vary.
Along the way, I found several resources that I leveraged for portions of my final solution.Here they are for reference:
- Building responsive email templates - Really useful templates that served as the basis for the final template.
- Free Responsive Simple HTML Template - Another good set of simple templates.
- Send email written in Markdown - A python repo that had a lot of good concepts for building the markdown email.
Besides having to use HTML tables, I learned that it is recommended that all the CSS be inlinedin the email. In other words, the email needs to have all the styling included in the tags using style
:
Once again this is very old school web and would be really painful if not for tools that will do the inliningfor you. I used the excellent premailer library to take an embedded CSS stylesheet and inline with the rest of the HTML.
You can find a full HTML template and all the code on github but here is a simple summary for reference.Please use the github version since this one is severely simplified and likely won’t work as is:
This is a jinja template and you will notice that there is a place for email_content
andtitle
. The next step in the process is to render a markdown text file into HTML and placethat HTML snippet into a template.
Markdown Article
Now that we know how we want the HTML to look, let’s create a markdown file.The only twist with this solution is that I want to create one markdown file thatcan be rendered in pelican and used for the HTML email.
Here is what a simple markdown file(sample_doc.md
) looks like thatwill work with pelican:
The required input file uses standard markdown. The one tricky aspect is that the top 5 lines contain meta-datathat pelican needs to make sure the correct url and templates are used when creating the output. Our final scriptwill need to remove them so that it does not get rendered into the newsletter email. If you are not trying toincorporate into your blog, you can remove these lines.
If you are interested in incorporating this in your pelican blog, here is how my content is structured:
All of the newsletter markdown files are stored in the newsletter directory and the blog postsare stored in the articles directory.
The final configuration I had to make in the pelicanconf.py
file was to make sure the pathswere setup correctly:
Now the blog is properly configured to render one of the newsletters.
Python code
Now that we have HTML template and the markdown document, we need a short python scriptto pull it all together. I will be using the following libraries so make sure they are all installed:
- python-markdown2 - Turn raw markdown into HTML
- jinja2 - Template engine to generate HTML
- premailer - Inline CSS
- BeautifulSoup - Clean up the HTML. This is optional but showing how to use it if you choose to.
Additionally, make sure you are using python3 so you have access to pathlib
andargparse
.
In order to keep the article compact, I am only including the key components. Please lookat the github repo for an approach that is a proper python standalone program that cantake arguments from the command line.
The first step, import everything:
Setup the input files and output HTML file:
Please refer to the pathlib article if you are not familiar with how or why to use it.
Now that the files are established, we need to read in the markdown file andparse out the header meta-data:
Django Markdown To Html Download
Using readlines
to read the file ensures that each line in the file is stored in a list.This approach works for our small file but could be problematic if you had a massive file thatyou did not want to read into memory at once. For an email newsletter you should be ok withusing readlines
.
Here is what it all_content[0:6]
looks like:
We can clean up the title line for insertion into the template:
Which renders a title PB Python - Newsletter Number 6
The final parsing step is to get the body into a single list without the header:
Convert the raw markdown into a simple HTML string:
Now that the HTML is ready, we need to insert it into our jinja template:
At this point, raw_html
has a fully formed HTML version of the newsletter.We need to use premailer’s transform
to get the CSS inlined. I am alsousing BeautifulSoup to do some cleaning up and formatting of the HTML.This is purely aesthetic but I think it’s simple enough to do so I am including it:
The final step is to make sure that the unsubscribe link does not get mangled. Dependingon your email provider, you may not need to do this:
Here is an example of the final email file:
You should be able to copy and paste the raw HTML into your email marketing campaign andbe good to go. In addition, this file will render properly in pelican. See this page for somepast examples.
Summary
Markdown is a simple text format that can be parsed and turned into HTML usingvarious python tools. In this case, the markdown file can be combined with a responsiveHTML email template to simplify the process of generating content for newsletters.The added bonus is that the content can be included in a static blog so that it is searchableand easily available to your readers.
This solution is not limited to just building emails. Now that newer versions of pandaswill include a native to_markdown
method, this general approach could be extendedto other uses. Using these principles you can build fairly robust reports and documentsusing markdown then incorporate the dataframe output into the final results. If there isinterest in an example, let me know in the comments.