Skip to content

Commit 9806dc5

Browse files
authored
SafeString class and docs (#6)
* move code * consistency * classifiers * formatting * docs * safestring back to class * docs * no dataclass * type * str
1 parent 0e92bbd commit 9806dc5

File tree

8 files changed

+309
-288
lines changed

8 files changed

+309
-288
lines changed

MANIFEST

Lines changed: 0 additions & 7 deletions
This file was deleted.

README.md

Lines changed: 76 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
# simple_html
22

3-
### Template-less. Type-safe. Minified by default.
3+
### Template-less. Type-safe. Minified by default. Fast.
44

5-
simple_html is built to simplify HTML rendering in Python. No templates needed. Just create HTML in
6-
normal Python. In most cases, the code will be more concise than standard HTML. Other benefits include:
5+
simple_html allows you to create HTML in standard Python. Benefits include:
6+
- typically faster than jinja2 -- up to 15x faster
77
- typically renders fewer bytes than template-based rendering
8-
- types mean your editor and tools can help you write correct code faster
9-
- no framework needed
10-
- lightweight
8+
- types let your editor and tools help you write correct code faster
9+
- lightweight and framework agnostic
10+
- always renders valid html
1111

1212

1313
### Installation
@@ -17,82 +17,101 @@ normal Python. In most cases, the code will be more concise than standard HTML.
1717
### Usage
1818

1919
```python
20-
from simple_html.nodes import body, head, html, p
21-
from simple_html.render import render
22-
23-
node = html(
24-
head,
25-
body(
26-
p.attrs(id="hello")(
27-
"Hello World!"
28-
)
29-
)
30-
)
20+
from simple_html import div, h1, render, p
21+
22+
node = div({},
23+
h1({"id": "hello"},
24+
"Hello World!"),
25+
p({},
26+
"hooray!"))
27+
28+
render(node)
29+
# <div><h1 id="hello">Hello World!</h1><p>hooray!</p></div>
30+
```
31+
32+
There are several ways to render nodes:
33+
```python
34+
from simple_html import br, div, h1, img, render
35+
36+
# raw node
37+
render(br)
38+
# <br/>
3139

40+
# node with attributes only
41+
render(img({"src": "/some/image/url.jpg", "alt": "a great picture"}))
42+
# <img src="/some/image/url.jpg" alt="a great picture"/>
43+
44+
# node with children
3245
render(
33-
node) # returns: <html><head></head><body><p id="hello">Hello World!</p></body></html>
46+
div({},
47+
h1({},
48+
"something"))
49+
)
50+
# <div><h1>something</h1></div>'
3451
```
3552

53+
Tag attributes with `None` as the value will only render the attribute name:
54+
```python
55+
from simple_html import div, render
56+
57+
render(
58+
div({"empty-str-attribute": "",
59+
"key-only-attr": None})
60+
)
61+
# <div empty-str-attribute="" key-only-attr></div>
62+
```
3663

3764
Strings are escaped by default, but you can pass in `SafeString`s to avoid escaping.
3865

3966
```python
40-
from simple_html.nodes import br, p, safe_string
41-
from simple_html.render import render
67+
from simple_html import br, p, SafeString, render
4268

43-
node = p(
44-
"Escaped & stuff",
45-
br,
46-
safe_string("Not escaped & stuff")
47-
)
69+
node = p({},
70+
"Escaped & stuff",
71+
br,
72+
SafeString("Not escaped & stuff"))
4873

4974
render(node) # returns: <p>Escaped &amp; stuff<br/>Not escaped & stuff</p>
5075
```
5176

52-
For convenience, many tags are provided, but you can create your own as well:
53-
77+
Lists and generators are both valid collections of nodes:
5478
```python
55-
from simple_html.nodes import Tag
56-
from simple_html.render import render
79+
from typing import Generator
80+
from simple_html import div, render, Node, br
5781

58-
custom_elem = Tag("custom-elem")
5982

60-
render(
61-
custom_elem.attrs(id="some-custom-elem-id")(
62-
"Wow"
63-
)
64-
) # returns: <custom-elem id="some-custom-elem-id">Wow</custom-elem>
65-
```
83+
def get_list_of_nodes() -> list[Node]:
84+
return ["neat", br]
6685

67-
Likewise, some attributes have been created as type-safe presets. Note that there are multiple ways to create attributes.
68-
The examples below are all equivalent:
6986

70-
```python
71-
from simple_html.attributes import height, id_
72-
from simple_html.nodes import div
87+
render(div({}, get_list_of_nodes()))
88+
# <div>neat<br/></div>
7389

7490

75-
# **kwargs: recommended for most cases
76-
div.attrs(id="some-id", height="100")
91+
def node_generator() -> Generator[Node, None, None]:
92+
yield "neat"
93+
yield br
7794

78-
# *args: useful for attributes that may be reserved keywords or when type constraints are desired.
79-
# Presets, raw tuples, and kwargs can be used interchangeably.
80-
div.attrs(id_("some-id"),
81-
height(100),
82-
("class", "abc"),
83-
width="100")
8495

85-
# renders to: <div id="some-id" height="100" class="abc" width="100"></div>
96+
render(
97+
div({}, node_generator())
98+
)
99+
# <div>neat<br/></div>
86100
```
87101

88-
You can build your own presets, using `str_attr`, `int_attr`, or `bool_attr`. For instance, here are
89-
several of the attribute preset definitions
102+
103+
For convenience, many tags are provided, but you can also create your own:
90104

91105
```python
92-
from simple_html.attributes import bool_attr, int_attr, str_attr
106+
from simple_html import Tag, render
107+
108+
custom_elem = Tag("custom-elem")
109+
110+
# works the same as any other tag
111+
node = custom_elem(
112+
{"id": "some-custom-elem-id"},
113+
"Wow"
114+
)
93115

94-
checked = bool_attr('checked')
95-
class_ = str_attr('class')
96-
cols = int_attr('cols')
116+
render(node) # <custom-elem id="some-custom-elem-id">Wow</custom-elem>
97117
```
98-
But anything that renders to the type of `Attribute` will work.

bench/simple.py

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from typing import List, Tuple
22

3-
from simple_html.nodes import (
3+
from simple_html import (
44
h1,
55
html,
66
title,
@@ -10,12 +10,12 @@
1010
p,
1111
ul,
1212
li,
13-
safe_string,
13+
SafeString,
1414
br,
1515
meta,
1616
DOCTYPE_HTML5,
17+
render,
1718
)
18-
from simple_html.render import render
1919

2020

2121
def hello_world_empty(objs: List[None]) -> None:
@@ -39,7 +39,7 @@ def basic(objs: List[Tuple[str, str, List[str]]]) -> None:
3939
ul(
4040
{},
4141
[
42-
li({"class": "item-stuff"}, safe_string(ss))
42+
li({"class": "item-stuff"}, SafeString(ss))
4343
for ss in oks
4444
],
4545
),
@@ -55,7 +55,9 @@ def basic_long(objs: List[Tuple[str, str, List[str]]]) -> None:
5555
"<!doctype html>",
5656
html(
5757
{},
58-
head({}, title({}, title_)),
58+
head({},
59+
title({},
60+
title_)),
5961
body(
6062
{},
6163
h1({"class": "great header", "other_attr": "5", "id": "header1"}),
@@ -65,7 +67,7 @@ def basic_long(objs: List[Tuple[str, str, List[str]]]) -> None:
6567
ul(
6668
{},
6769
[
68-
li({"class": "item-stuff"}, safe_string(ss))
70+
li({"class": "item-stuff"}, SafeString(ss))
6971
for ss in oks
7072
],
7173
),
@@ -77,7 +79,7 @@ def basic_long(objs: List[Tuple[str, str, List[str]]]) -> None:
7779
ul(
7880
{},
7981
[
80-
li({"class": "item-stuff"}, safe_string(ss))
82+
li({"class": "item-stuff"}, SafeString(ss))
8183
for ss in oks
8284
],
8385
),
@@ -89,7 +91,7 @@ def basic_long(objs: List[Tuple[str, str, List[str]]]) -> None:
8991
ul(
9092
{},
9193
[
92-
li({"class": "item-stuff"}, safe_string(ss))
94+
li({"class": "item-stuff"}, SafeString(ss))
9395
for ss in oks
9496
],
9597
),
@@ -101,7 +103,7 @@ def basic_long(objs: List[Tuple[str, str, List[str]]]) -> None:
101103
ul(
102104
{},
103105
[
104-
li({"class": "item-stuff"}, safe_string(ss))
106+
li({"class": "item-stuff"}, SafeString(ss))
105107
for ss in oks
106108
],
107109
),
@@ -113,7 +115,7 @@ def basic_long(objs: List[Tuple[str, str, List[str]]]) -> None:
113115
ul(
114116
{},
115117
[
116-
li({"class": "item-stuff"}, safe_string(ss))
118+
li({"class": "item-stuff"}, SafeString(ss))
117119
for ss in oks
118120
],
119121
),

pyproject.toml

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,26 @@
11
[tool.poetry]
22
name = "simple-html"
3-
version = "0.7.0"
3+
version = "1.0.0"
44
readme = "README.md"
55
description = "Template-less html rendering in Python"
66
authors = ["Keith Philpott <[email protected]>"]
77
license = "MIT"
88
homepage = "https://github.com/keithasaurus/simple_html"
9-
keywords = ["html"]
9+
keywords = ["html", "type hints"]
10+
classifiers = [
11+
'Development Status :: 5 - Production/Stable',
12+
'Environment :: Console',
13+
'Environment :: MacOS X',
14+
'Environment :: Web Environment',
15+
'Intended Audience :: Developers',
16+
'Operating System :: MacOS',
17+
'Operating System :: Microsoft :: Windows',
18+
'Operating System :: POSIX :: Linux',
19+
'Operating System :: Unix',
20+
'Topic :: Software Development :: Libraries :: Python Modules',
21+
'Topic :: Utilities',
22+
'Typing :: Typed'
23+
]
1024

1125

1226
[tool.poetry.dependencies]

0 commit comments

Comments
 (0)