Skip to main content

htmldoom

Documentation PyPI version PyPI pyversions Build Status codecov Code style: black

Introducing htmldoom

htmldoom is an HTML rendering framework for Python that helps you define your HTML documents, templates, layouts and contents in an organised way, gives you the flexibility to use many different syntaxes, option to declare and debug different components and pages separately and more... all without making you worry about the runtime performance.

How does it work?

Understanding the working principle will get pretty intuitive if we go one feature at a time. Let's start with HTML escaping.

HTML escaping

In the center of htmldoom's functionality is the HTML escaping logic. Texts to be escaped are represented using str, while texts that should not be escaped are represented using bytes. The htmldoom.renders() function receives the texts as inputs, then for each input, it decides whether to escape it or not based on if it is str or bytes and returns the rendered text in str format.

We can use htmldoom.txt() to convert some string into HTML escaped text, and htmldoom.raw() to convert some string into HTML unescaped text. It should be noted that both the functions will return text formatted in bytes which can be passed to the htmldoom.render() to render it back to str.

HTML elements

HTML elements or tags can be defined using the htmldoom.composite_tag() and the htmldoom.leaf_tag() functions. Any tag that can have child elements (e.g. <p></p>) are defined using htmldoom.composite_tag().

For example:

p = composite_tag("p")

Tags that cannot have child elements are defined using htmldoom.leaf_tag().

For example:

input_ = leaf_tag("input")

So when we call p(class_="red")("foo", "bar") or input_(type_="button"), we get bytes encoded <p class="red">foobar</p> or <input type="button" /> respectively. The htmldoom.render() function will render them back to str.

HTML components / layouts

HTML components i.e. combination of several elements (tags and texts) can be defined using the @htmldoom.renders() decorator like below.

from htmldoom import renders, elements as e

@renders(
    e.p(class_="red")("{key1}", "{key2}"),
    e._input(type_="button")
)
def my_component(value1, value2):
    return {"key1": value1, "key2": value2}

Now we can render the component by calling it with the required arguments e.g.

my_document(value1="&amp;", value2=b"&amp;")

This will return a bytes encoded text. The value1 will be escaped to &amp;amp; since it is str. value2 is in bytes, hence it will remain the same and wil be rendered in the browser as &.

Calling this will return bytes encoded text

<p class="red">foobar</p><input type="button" />

which can be rendered into string using htmldoom.render().

This mechanism renders the template text during module load time. Hence there should be no performance drop in runtime.

NOTE: It is important to note that every { and } should be escaped with {{ and }} when it is not being used as a placeholder for some variable.

It is also possible to define the components using yaml syntax like below.

some:
  demo:
    p:
    - class: red
    - - "{key1}"
      - "{key2}"
    input:
    - type: button

And then define the component renderer like below.

from htmldoom import renders
from htmldoom.yaml_loader import loadyaml

@renders(loadyaml("path/to/component.yaml", ("some", "demo")))
def my_component(value1, value2):
    return {"key1": value1, "key2": value2}

We can also use escaped and raw loaders with the htmldoom.loadtxt() and htmldoom.loadraw() functions respectively. We only need to pass the file path as shown in the yaml example.

We can use the same syntax to define reusable layouts.

Separating values from templates

htmldoom provides us with a friendly way to separate values from layouts or components templates. The htmldoom.value_loader.loadvalues() function scans the given directory and returns a nested namedtuple with the file or directory names as element names and the loaded contents as the values. We can pass this to components like below.

from htmldoom import renders, elements as e
from htmldoom.value_loader import loadvalues

values = loadvalues("path/to/values")

@renders(
    e.p()("{v.title}"),
    e.p()("{v.content.line1}")
    e.p()("{v.content.line2}")
    e.p()("{v.content.line3}")
)
def my_component():
    return {"v": values}

So we need a directory structure like below.

values
├── title.txt
└── content
    ├── line1.txt
    ├── line2.html
    └── line3.yml

As you mught have guessed, this can load the values based of file types. You can use your own renderer for file types such as md or rst by extending the htmldoom.value_loader.EXTENSION_RENDERERS map and passing is to the htmldoom.value_loader.loadvalues() function like below.

from htmldoom import raw
from htmldoom.value_loader import loadvalues, EXTENSION_RENDERERS

def markdown_to_html(path):
    """Some function that reads the file, converts the content to HTML,
    and returns the converted data as string.
    """
    # The logic goes here...

MY_EXTENSION_RENDERERS = dict(
    md=lambda path: raw(markdown_to_html(path)),
    **EXTENSION_RENDERERS
)

values = loadvalues("path/to/values", extension_renderers=MY_EXTENSION_RENDERERS)

In fact, this documentation is generated using the same method.

Metadata

Release files for htmldoom 1.0.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for htmldoom 1.0.1
File Size Uploaded
htmldoom-1.0.1.tar.gz 14.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for htmldoom 1.0.1
File Interpreter ABI Platform
htmldoom-1.0.1-py3-none-any.whl Python 3 none any Details

Total release size: 28.6 kB

Release files / htmldoom-1.0.1.tar.gz

Download URL htmldoom-1.0.1.tar.gz
Size 14.0 kB
Tags Source
SHA-256 checksum
How to use checksums
d0c7b39f38cfcc47571d42998d54f6ad15d4dc9bd322021405abf30405787af4
BLAKE2b-256 checksum
How to use checksums
10ed9c853648c4bce8ef0b3f101fbab05ea3b8b2b3071af3112ee0a0b20882d3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.1.1 pkginfo/1.5.0.1 requests/2.23.0 setuptools/46.1.3 requests-toolbelt/0.9.1 tqdm/4.45.0 CPython/3.7.6

Release files / htmldoom-1.0.1-py3-none-any.whl

Download URL htmldoom-1.0.1-py3-none-any.whl
Size 14.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4a7c81eaf9f1bbcb742f1ad5fe10065ec91f965fd0057f13441536dd9739e409
BLAKE2b-256 checksum
How to use checksums
e04f1b9a777caebda11ff800598d90376f09ef5d8dd7fe5355fe443c5363f37a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.1.1 pkginfo/1.5.0.1 requests/2.23.0 setuptools/46.1.3 requests-toolbelt/0.9.1 tqdm/4.45.0 CPython/3.7.6

Release history Release notifications | RSS feed

This release

1.0.1 This release

2 release files

1.0.0

2 release files

0.10.0

2 release files

0.9.0

2 release files

0.8.0

2 release files

0.7.3

2 release files

0.7.2

2 release files

0.7.1

2 release files

0.7.0

2 release files

0.6.9

2 release files

0.6.8

2 release files

0.6.6

2 release files

0.6.5

2 release files

0.6.4

2 release files

0.6.3

2 release files

0.6.2

2 release files

0.6.1

2 release files

0.6

2 release files

0.5

2 release files

0.3.1

2 release files

0.3

2 release files

0.2.5

2 release files

0.2.4

2 release files

0.2.3

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2

2 release files

0.1.1

2 release files

0.1

2 release files

0.0.10

2 release files

0.0.9

2 release files

0.0.8

2 release files

0.0.7

2 release files

0.0.6

2 release files

0.0.5

2 release files

0.0.4

2 release files

0.0.3

2 release files

0.0.2

2 release files

0.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page