Releases: t-strings/tdom
Rearchitect with future performance, error handling, and other features in mind
This release contains a significant under-the-hood rearchitecting of both the processor and the parsing layer.
The new architecture is substantially more mature than the previous, and provides us with new opportunities for future performance gains, improved error handling, and several other interesting new features.
Many thanks to @ianjosephwilson for his essential contributions here.
v0.1.11
Bugfixes and cleanup
This release fixes issue #60 and cleans up support for multiple placeholders where appropriate.
Allow multiple substitutions in attribute values
Previously, we only supported single substitutions in attribute values. Now we allow multiple, so this works:
first = "Alice"
last = "Smith"
button = html(t"<button data-name='{first} {last}'>Click me</button>")
# <button data-name="Alice Smith">Click me</button>Thanks to @koxudaxi for the PR!
Clarify rules for `children` in component invocations
children are now treated like all other attributes during component invocation:
- If there's an explicit
childrenparameter, we pass in a tuple. If there are no children in the underlying HTML, the tuple will be empty. - If there's a
**kwargsparameter, we always includechildren; the component is free to ignore this key. - If there's no
childrenparameter and no**kwargs, we ignore children in the underlying HTML if there are any.
Support class-based components
This release contains a big set of changes to support class-based components, as described in #53.
In addition to writing standard function-based components:
from typing import Iterable
from tdom import html
def FunctionComponent(children: Iterable[Node], something: int) -> Node:
return html(t"<div>Something: {something}<br />{children}</div>")
result = html(t"<{FunctionComponent} something={42}><p>hi</p></{FunctionComponent}>")
# <div>Something: 42<br /><p>hi</p></div>You can now write class-based components:
from dataclasses import dataclass, field
from typing import Any, Iterable
from tdom import Node, html
@dataclass
class Card:
children: Iterable[Node]
title: str
subtitle: str | None = None
def __call__(self) -> Node:
return html(t"""
<div class='card'>
<h2>{self.title}</h2>
{self.subtitle and t'<h3>{self.subtitle}</h3>'}
<div class="content">{self.children}</div>
</div>
""")
result = html(t"<{Card} title='My Card' subtitle='A subtitle'><p>Card content</p></{Card}>")
# <div class='card'>
# <h2>My Card</h2>
# <h3>A subtitle</h3>
# <div class="content"><p>Card content</p></div>
# </div>There are a number of under-the-hood changes to support this.
Also, we've now officially achieved 100% statement coverage.
Add explicit fragment support (JSX-like syntax), and support Components returning iterables.
We now explicitly support JSX-like fragment syntax. This is useful when implementing component functions:
def Items() -> Node:
return html(t"<><li>Item 1</li><li>Item 2</li></>")
result = html(t"<ul><{Items} /></ul>")
# <ul><li>Item 1</li><li>Item 2</li></ul>As an alternative, we also support returning typing.Iterables from components as well; these are treated as implicitly creating a tdom.nodes.Fragment:
def Items() -> Iterable[Node]:
for i in range(2):
yield t"<li>Item {i + 1}</li>"
result = html(t"<ul><{Items} /></ul>")
# <ul><li>Item 1</li><li>Item 2</li></ul>In practice, component functions can return any value and it will be converted to a Node in exactly the same way that any value substituted in children context would be normally (aka html(t"<div>{child_value}</div>")). The fallback case if a value isn't a special type is always simply to create a Text node from str(value).
It's a new world order.
We've updated tdom in many ways. See the README.md for details on the latest.
v0.0.7
Fix MicroPython early/eager import inspect which was failing.
Update and add package metadata.
v0.0.6 Add further classifiers/metadata