Skip to content
This repository was archived by the owner on Sep 15, 2025. It is now read-only.

Commit 5fc0a08

Browse files
committed
Add pypi publish workflow and badges to README
1 parent 6d4e685 commit 5fc0a08

File tree

3 files changed

+98
-18
lines changed

3 files changed

+98
-18
lines changed

.github/workflows/pypi.yml

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
name: Publish Python Package
2+
3+
on:
4+
release:
5+
types: [created]
6+
7+
workflow_dispatch:
8+
9+
permissions:
10+
contents: read
11+
12+
jobs:
13+
test_and_build:
14+
runs-on: ubuntu-latest
15+
steps:
16+
- uses: actions/checkout@v4
17+
18+
- name: Set up Python 3.14.0-rc.2
19+
uses: actions/setup-python@v5
20+
with:
21+
python-version: 3.14.0-rc.2
22+
23+
- name: Install uv
24+
uses: astral-sh/setup-uv@v6
25+
26+
- name: Lint
27+
run: uv run ruff check
28+
29+
- name: Check formatting
30+
run: uv run ruff format --check
31+
32+
- name: Type check
33+
run: uv run pyright
34+
35+
- name: Run tests
36+
run: uv run pytest -v
37+
38+
- name: Build
39+
run: uv build
40+
41+
- name: Store the distribution packages
42+
uses: actions/upload-artifact@v4
43+
with:
44+
name: python-packages
45+
path: dist/
46+
47+
publish:
48+
name: Publish to PyPI
49+
runs-on: ubuntu-latest
50+
if: startsWith(github.ref, 'refs/tags/')
51+
needs: [test_and_build]
52+
environment: release
53+
permissions:
54+
id-token: write
55+
steps:
56+
- name: Download distribution packages
57+
uses: actions/download-artifact@v5
58+
with:
59+
name: python-packages
60+
path: dist/
61+
- name: Publish to PyPI
62+
uses: pypa/gh-action-pypi-publish@release/v1

README.md

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22

33
A 🤘 rockin' t-string HTML templating system for Python 3.14.
44

5+
[![PyPI](https://img.shields.io/pypi/v/html-tstring.svg)](https://pypi.org/project/html-tstring/)
6+
[![Tests](https://github.com/t-strings/html-tstring/actions/workflows/ci.yml/badge.svg)](https://github.com/t-strings/tdom/actions/workflows/pytest.yml)
7+
[![Changelog](https://img.shields.io/github/v/release/t-strings/html-tstring?include_prereleases&label=changelog)](https://github.com/t-strings/html-tstring/releases)
8+
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/t-strings/html-tstring/blob/main/LICENSE)
9+
510
## Installation
611

712
Just run:
@@ -251,31 +256,43 @@ The result is the same either way.
251256

252257
#### Component Functions
253258

254-
Create reusable template functions that work like custom HTML elements:
259+
You can create reusable component functions that generate templates with dynamic content and attributes. Use these like custom HTML elements in your templates.
260+
261+
The basic form of all component functions is:
255262

256263
```python
257-
def Alert(message: str, type: str = "info", **props) -> Template:
258-
alert_class = f"alert alert-{type}"
259-
attrs = {"class": alert_class, **props}
260-
return t'<div {attrs}>{message}</div>'
264+
from typing import Any
261265

262-
# Use your component
263-
warning = html(t'<{Alert} message="Be careful!" type="warning" id="main-alert" />')
266+
def MyComponent(*children: Node, **attrs: Any) -> Template:
267+
# Build your template using the provided props
268+
return t"<div {attrs}>{children}</div>"
264269
```
265270

266-
#### Fragment Rendering
271+
To _invoke_ your component within an HTML template, use the special `<{ComponentName} ... />` syntax:
272+
273+
```python
274+
result = html(t"<{MyComponent} id='comp1'>Hello, Component!</{MyComponent}>")
275+
# <div id="comp1">Hello, Component!</div>
276+
```
267277

268-
Templates can return multiple root elements:
278+
Because attributes are passed as keyword arguments, you can explicitly provide type hints for better editor support:
269279

270280
```python
271-
def TableColumns() -> Template:
272-
return t"<td>Column 1</td><td>Column 2</td>"
281+
from typing import Any
282+
283+
def Link(*, href: str, text: str, **props: Any) -> Template:
284+
return t'<a href="{href}" {props}>{text}</a>'
273285

274-
table = html(t"<table><tr><{TableColumns} /></tr></table>")
286+
result = html(t'<{Link} href="https://example.com" text="Example" target="_blank" />')
287+
# <a href="https://example.com" target="_blank">Example</a>
275288
```
276289

277-
The `html()` function returns a tree of nodes that can be converted to strings, manipulated programmatically, or composed with other templates for maximum flexibility.
290+
In addition to returning a `Template` directly, component functions may also return any `Node` type found in [`html_tstring.nodes`](./html_tstring/nodes.py). This allows you to build more complex components that manipulate the HTML structure programmatically.
278291

279292
#### Context
280293

281294
TODO: implement context feature
295+
296+
#### Working with `Node` Objects
297+
298+
TODO: say more about working with them directly

html_tstring/processor_test.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1+
import typing as t
12
from string.templatelib import Template
23

34
import pytest
45
from markupsafe import Markup
56

6-
from .nodes import Element, Fragment, Text
7+
from .nodes import Element, Fragment, Node, Text
78
from .processor import html
89

910
# --------------------------------------------------------------------------
@@ -456,14 +457,14 @@ def test_interpolated_style_attribute():
456457

457458

458459
def TemplateComponent(
459-
*children: Element | str, first: int, second: int, third: str, **props: str | None
460+
*children: Node, first: int, second: int, third: str, **attrs: t.Any
460461
) -> Template:
461-
attrs = {
462+
new_attrs = {
462463
"id": third,
463464
"data": {"first": first, "second": second},
464-
**props,
465+
**attrs,
465466
}
466-
return t"<div {attrs}>Component: {children}</div>"
467+
return t"<div {new_attrs}>Component: {children}</div>"
467468

468469

469470
def test_interpolated_template_component():

0 commit comments

Comments
 (0)