Typed HTML builder with generated tag helpers.
Project description
H
Typed HTML builder for Python. Call tag helpers in zen_html.h to build HTML directly in Python with strong typing. It runs solely on the standard library—no external dependencies. _base.py contains the rendering logic, and _generator.py autogenerates the tag API (zen_html.h) from _tag_spec.py.
pip install zenhtml
Features
- Fully typed API: Each tag exposes common props (
class_,id,name, …) plus Literal/boolean-restricted attributes. - Simple DOM composition: Nested iterables are accepted as children, so
H.div(list_of_nodes)just works. - Convenient helpers:
datasetdict →data-*,styledict → CSS strings, andpretty_html/pretty_dictfor debugging. - Reusable tokens:
to_token(),html_, anddict_can be used for streaming or structured rendering. - HTML5 coverage: 110+ tags (metadata, forms, tables, interactive elements…) are generated from
_tag_spec.py. SVG/MathML are intentionally out of scope. - Escaped by default: Text children/attribute values are HTML-escaped automatically. Wrap trusted fragments with
H.raw()when you really need unescaped output, and keepH.strict_validationenabled to fail fast on invalid props/void-tag children.
Usage
from typing import Literal
from zen_html.h import H
page: H = H.html(
H.head(
H.meta(charset="utf-8"),
H.title("Hello, H"),
),
H.body(
H.h1("Hello"),
H.p("Generated in Python.", class_="lead"),
H.button("Click", type="button", disabled=None),
),
lang="ja",
)
print(page.html_) # plain string
print(page.pretty_html()) # indented output
def button(kind: Literal["button", "submit"]) -> H:
return H.button("Click", type=kind)
button("button") # OK
button("invalid") # mypy error thanks to Literal
examples/sample.py includes Starlette/FastAPI helpers (HResponse, HDocumentResponse, select) showing real-world usage. examples/pandas_pivot.py demonstrates how to turn a pandas pivot table into an HTML table (pandas is an optional dependency for that example). Run it with python -m examples.pandas_pivot to keep imports working from the repo root.
Key properties & methods
html_: Concatenated HTML string for the node (eager render). Suitable for templates that just need a string.pretty_html(indent=0): Prints a human-readable representation, handy for debugging or inspection.to_token(): Generator yielding individual HTML tokens. Use it for streaming responses (StreamingResponse, ASGI, etc.).dict_: JSON-serializable tree containingtag, escapedprops, andchildren. Useful for client-side rendering or feeding into other serializers.
Escaping & validation
- All text nodes and attribute values are escaped automatically. If you need to inject a pre-escaped fragment, wrap it with
H.raw("<span>safe</span>"). - Runtime validation is enabled by default (
H.strict_validation = True) and raises when you pass children to void tags or supply unsupported Literal/bool values. Set it toFalsewhen you prefer warnings and best-effort rendering. Validation occurs during node construction, so token streaming (to_token()/HResponse) never yields partial or invalid HTML—errors surface up front.
Rendering via dict_ in JavaScript
dict_ returns a JSON-serializable structure. You can ship it to the browser and render it there:
import json
from zen_html.h import H
payload = json.dumps(H.div("Hi", class_="greeting").dict_)
<script type="module">
import { HRender } from "/examples/h_render.js";
const tree = JSON.parse({{ payload | tojson }});
document.body.appendChild(HRender(tree));
</script>
Regenerating tag API
H/h.py is generated from _tag_spec.py. After editing the spec, run:
python3 - <<'PY'
from zen_html._generator import generate_class
generate_class(output="H/h.py")
PY
Development notes
- Tooling (Black/Isort/djlint) is configured in
pyproject.toml. - Boolean props render only when
True;False/Noneare ignored. dataset={"fooBar": "baz"}→data-foo-bar="baz";style={"fontSize": "12px"}→font-size: 12px.- Requires Python 3.10+ so ParamSpec-based decorators keep IDE (VS Code) completions accurate.
License
See LICENSE.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file zenhtml-0.1.1.tar.gz.
File metadata
- Download URL: zenhtml-0.1.1.tar.gz
- Upload date:
- Size: 17.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f244f3c413754def886ef51efbd28f7dc6548c196046fb837ef960e8f98169ba
|
|
| MD5 |
a3cdca24a64d09167daa262a449d77f7
|
|
| BLAKE2b-256 |
b07d2c155c07ffdc34f7c9304e0ce061651b8a4d643c7ee66bfe6d928828ea43
|
File details
Details for the file zenhtml-0.1.1-py3-none-any.whl.
File metadata
- Download URL: zenhtml-0.1.1-py3-none-any.whl
- Upload date:
- Size: 14.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a4454ff4cdea7598ae5b4fa502b20cc48c93c7d563b941fae361312df4415e22
|
|
| MD5 |
47f72a7ac7310ece8fa0e2ad1820ebee
|
|
| BLAKE2b-256 |
faa2bbd1c3ac6c1a24eae3ef2986d75ede8de4869b93bcbb302a9d80b5fcf2b3
|