minihtmlΒΆ

minihtml is a library to generate HTML documents from Python. It aims to provide an API that allows you to define the structure of an HTML document in a succinct and natural way.

By building up nested HTML elements using context managers, you can combine HTML generation with control flow statements in a way that is easy to read and does not obscure the structure of the resulting HTML document.

For example, this code:

from minihtml.tags import a, body, div, head, html, img, li, p, title, ul

links = [("Home", "/"), ("About Me", "/about"), ("Projects", "/projects")]

with html(lang="en") as elem:
    with head:
        title("hello, world!")
    with body, div["#content main"]:
        p("Welcome to ", a(href="https://example.com/")("my website"))
        img(src="hello.png", alt="hello")
        with ul:
            for title, url in links:
                li(a(href=url)(title))

print(elem)

produces this HTML:

<html lang="en">
  <head>
    <title>hello, world!</title>
  </head>
  <body>
    <div id="content" class="main">
      <p>Welcome to <a href="https://example.com/">my website</a></p>
      <img src="hello.png" alt="hello">
      <ul>
        <li><a href="/">Home</a></li>
        <li><a href="/about">About Me</a></li>
        <li><a href="/projects">Projects</a></li>
      </ul>
    </div>
  </body>
</html>

The short example above already shows a few key features of the API:

  • declarative API: Using the declarative style, you can use regular for loops and other control flow statements to build up nested elements:

    >>> from minihtml.tags import ul, li
    >>> with ul as ingredients:
    ...     for item in ("bacon", "lettuce", "tomato"):
    ...         li(item)
    <...>
    >>> print(ingredients)
    <ul>
      <li>bacon</li>
      <li>lettuce</li>
      <li>tomato</li>
    </ul>
    

    You can also use a list comprehension of course, but this tends to only work for very simple examples. As soon as you start nesting loops or have inline conditionals, readability suffers.

    >>> ingredients = ul(*[li(item) for item in ("bacon", "lettuce", "tomato")])
    >>> print(ingredients)
    <ul>
      <li>bacon</li>
      <li>lettuce</li>
      <li>tomato</li>
    </ul>
    
  • fluent API: Operations on elements can be chained to write code that is close to the generated HTML:

    >>> from minihtml.tags import a
    >>> link = a(href="http://example.com/")("My Website")
    >>> print(link)
    <a href="http://example.com/">My Website</a>
    
  • shortcuts: There are convenient shortcuts to set the common HTML attributes id and class:

    >>> from minihtml.tags import div
    >>> content = div["#content text-xl font-bold"]
    >>> print(content)
    <div id="content" class="text-xl font-bold"></div>
    
  • pretty printing: All HTML output is pretty-printed (indented) for easier debugging.

Some additional features:

Continue reading at Basics to learn more.