Convert Markdown Files to HTML Automatically Using Python

Convert Markdown Files to HTML Automatically Using Python

Convert Markdown Files to HTML Automatically Using Python

 

Markdown is a popular format for writing documentation, notes, and content-rich articles. But sometimes you need to render your Markdown files into styled HTML pages — say, for building a documentation site or exporting reports. In this tutorial, you’ll learn how to automate the process of converting Markdown files into beautiful HTML pages using Python.

We’ll use markdown2 to convert Markdown to HTML and jinja2 to render the final HTML pages with a consistent layout. Along the way, you’ll learn scripting techniques, automation workflows, and tips for extending the solution for real-world use cases.

1. Project Setup and Dependencies

First, let’s set up the Python environment and install the required libraries:

pip install markdown2 jinja2

Create a basic project structure:

markdown-to-html/
├── templates/
│   └── base.html
├── markdown_files/
│   └── example.md
├── output/
├── converter.py

This layout separates the input Markdown files, Jinja2 templates, and output HTML files. It keeps your project organized and easy to manage.

2. Converting Markdown to HTML with markdown2

The markdown2 library extends standard Markdown processing with extras like fenced code blocks, footnotes, and tables. Here’s how to use it:

import markdown2

# Read markdown content
with open("markdown_files/example.md", "r", encoding="utf-8") as f:
    md_content = f.read()

# Convert to HTML
html_content = markdown2.markdown(md_content, extras=["fenced-code-blocks", "tables"])

print(html_content)

This yields the raw HTML content of your Markdown file. But to make the output more useful and presentable, we’ll wrap it in a styled HTML template using jinja2.

3. Using Jinja2 Templates for Styling

Now, create a Jinja2 template under templates/base.html:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>{{ title }}</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/water.css@2/out/water.css">
</head>
<body>
  <article>
    {{ content | safe }}
  </article>
</body>
</html>

This simple template applies the minimalistic Water.css stylesheet for quick styling. The Markdown content is injected via the {{ content | safe }} block to prevent escaping HTML tags.

Use the following Python code to render the final HTML page with Jinja2:

from jinja2 import Environment, FileSystemLoader
import os

# Set up the template environment
template_loader = FileSystemLoader('templates')
template_env = Environment(loader=template_loader)
template = template_env.get_template('base.html')

# Define template variables
html_output = template.render(title="Example Markdown Page", content=html_content)

# Save the rendered HTML
output_path = os.path.join("output", "example.html")
with open(output_path, "w", encoding="utf-8") as f:
    f.write(html_output)

You now have a fully rendered HTML page saved in the output folder!

4. Automate Conversion of Multiple Files

Don’t stop at one file. Automate the conversion of an entire directory of Markdown files with a loop:

import glob

md_files = glob.glob("markdown_files/*.md")

for md_file in md_files:
    with open(md_file, "r", encoding="utf-8") as f:
        md_content = f.read()

    html_content = markdown2.markdown(md_content, extras=["fenced-code-blocks", "tables"])
    title = os.path.splitext(os.path.basename(md_file))[0].title()
    html_output = template.render(title=title, content=html_content)

    output_file = os.path.join("output", f"{title.lower().replace(' ', '_')}.html")
    with open(output_file, "w", encoding="utf-8") as f:
        f.write(html_output)

    print(f"Converted: {md_file} → {output_file}")

This script reads all Markdown files, converts them to HTML with titles derived from filenames, and writes them to the output directory. It’s quick, scalable, and easy to integrate into CI/CD pipelines or documentation build systems.

5. Enhancements and Best Practices

Some bonus tips for scaling and improving your tool:

  • Error handling: Add try/except blocks for reading files and rendering templates.
  • CLI support: Add argparse to accept input/output directories.
  • Watch mode: Integrate watchdog to automatically rebuild HTML when Markdown files change.
  • Theme customization: Replace Water.css with your own CSS for brand consistency.
  • Static site integration: Use the tool as a backend processor for a static website (e.g., with GitHub Pages).

Here’s an example enhancement using argparse for flexible input/output configuration:

import argparse

parser = argparse.ArgumentParser(description="Convert Markdown files to HTML")
parser.add_argument("--input", default="markdown_files", help="Input directory")
parser.add_argument("--output", default="output", help="Output directory")
args = parser.parse_args()

This little change makes your script more dynamic and scriptable from other tools or environments.

Conclusion

With just a few lines of Python code and the powerful combination of markdown2 and jinja2, you’ve built a Markdown-to-HTML converter that is flexible, fast, and templatable. It’s a fantastic small tool that you can grow into a full documentation engine, PDF generator, or blogging system.

Start by automating your own notes or documentation site, and you’ll quickly see the time-saving benefits of such a tool. Happy coding!

 

Useful links: