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
3245render(
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
3764Strings 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
4974render(node) # returns: <p>Escaped & 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.
0 commit comments