T-strings for HTML¶
Parser-first HTML and T-HTML backends for PEP 750 template strings.
Python 3.14 introduces t-strings. They look like f-strings but give you structured access to the interpolation values instead of concatenating them into a string. This project uses that structure to parse the template as HTML first, then insert escaped values into the right slots. The result is always valid HTML, and XSS is not possible.
How it works¶
from html_tstring import render_html
name = "<script>alert('xss')</script>"
page = render_html(t"<div class='greeting'>Hello, {name}!</div>")
# <div class='greeting'>Hello, <script>alert('xss')</script>!</div>
The template is parsed into an AST. Interpolated values are validated and escaped, then placed into the AST. The rendered output is always well-formed HTML.
What is T-HTML?¶
T-HTML is a small DSL on top of t-strings. It adds one rule: a tag whose name starts with an uppercase letter (e.g. <Card>) is treated as a component call. The tag name is looked up as a Python callable, attributes become keyword arguments, and nested content is passed as children.
There is no virtual DOM, no state, no build step. It is just a way to write reusable HTML fragments as functions and compose them with <Tag> syntax inside t-strings.
from string.templatelib import Template
from thtml_tstring import component, thtml
@component
def Badge(*, children: str, tone: str = "info") -> Template:
return t'<span class="badge badge-{tone}">{children}</span>'
name = "cached"
result = thtml(t"<div><Badge tone='info'>{name}</Badge></div>")
html = result.render()
# <div><span class="badge badge-info">cached</span></div>
The @component decorator wraps Template return values into Renderable automatically, so you don't need RawHtml for component composition.
Packages¶
| Package | What it does | Install |
|---|---|---|
| html-tstring | Plain HTML rendering with auto-escaping | pip install html-tstring |
| thtml-tstring | Adds JSX-style component tags | pip install thtml-tstring |
tstring-html-bindings (the native extension) is pulled in automatically.
See also¶
- Installation
- Quick Start
- HTML usage
- T-HTML components
- Editor Integration (t-linter)
- API Reference
- Spec Conformance Status
- Architecture
Practical examples¶
The repository ships with typed examples that show realistic usage patterns:
Coverage snapshot¶
The current repo-local v1 conformance matrix includes:
- HTML
default: 34 cases - T-HTML
default: 47 cases
That matrix currently covers:
- HTML escaping,
RawHtml,Renderable, spread/class semantics, formatter raw-source fidelity, and seam-level semantic spans - T-HTML component resolution, captured scope, explicit scope,
Renderablecomposition, auto-wrap behavior, compiled-template scope behavior, and runtime-without-bindings boundaries