You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
# Upper case names are template variables. You can modify them later.
40
-
doc.Head_
41
-
doc.h1.TitleText_("Demo") # Goes inside <h1> and updates <title> as well
42
-
43
42
# This has been a hard problem for DOM other such generators:
44
43
doc.p("A paragraph with ").a("a link", href="/files")(" and ").em("formatting")
45
44
45
+
# Use templates to render dynamic content
46
+
doc.h1("Demo")
47
+
doc.ul._(Item(Name="Apple"), Item(Name="Banana"))
48
+
46
49
# Use with for complex nesting (not often needed)
47
50
with doc.table(id="data"):
48
51
doc.tr.th("First").th("Second").th("Third")
49
-
doc.TableRows_
50
-
51
-
# Let's add something to the template variables
52
-
doc.Head._script("console.log('</script> escaping is weird')")
52
+
for row inrange(3):
53
+
doc.tr
54
+
for col inrange(3):
55
+
doc.td(row * col)
53
56
54
-
table = doc.TableRows
55
-
for row inrange(10):
56
-
table.tr
57
-
for col inrange(3):
58
-
table.td(row * col)
59
-
60
-
# Or remove the table data we just added
61
-
doc.TableRows =None
57
+
# Add inline scripts or styles with special escaping
58
+
doc.script("console.log('</script> escaping is weird')")
62
59
```
63
60
64
-
You can `str(doc)` to get the HTML code, and using `doc` directly usually has the desired effect as well (e.g. giving HTML responses). Jupyter Notebooks render it as HTML. For debugging, use `repr(doc)` where the templating variables are visible:
61
+
You can `str(doc)` to get the HTML code, and using `doc` directly usually has the desired effect as well (e.g. giving HTML responses). Jupyter Notebooks render it as HTML. For debugging, use `repr(doc)`:
《Head:<script>console.log('<\/script> escaping is weird')</script>》
75
-
<h1>《TitleText:Demo》</h1>
76
70
<p>A paragraph with <ahref="/files">a link</a> and <em>formatting</em>
71
+
<h1>Demo</h1>
72
+
<ul><li>Apple<li>Banana</ul>
77
73
<tableid=data>
78
74
<tr><th>First<th>Second<th>Third
79
-
《TableRows》
75
+
<tr><td>0<td>0<td>0
76
+
<tr><td>0<td>1<td>2
77
+
<tr><td>0<td>2<td>4
80
78
</table>
79
+
<script>console.log('<\/script> escaping is weird')</script>
81
80
```
82
81
83
82
The actual HTML output is similar. No whitespace is added to the document, it is all on one line unless the content contains newlines. You may notice that `body` and other familiar tags are missing and that the escaping is very minimal. This is HTML5: the document is standards-compliant with a lot less cruft.
84
83
85
-
## Templating (v1 deprecated)
84
+
## Templating
86
85
87
-
> ⚠️ **Deprecation notice:** The v1.3 templating API is deprecated as of html5tagger 1.4 and will be removed in 2.0. If you rely on it, pin `html5tagger<2`in your dependencies. Otherwise, upgrade to html5tagger 2.0 for the new templating API.
86
+
A document builder can be turned into a template by `Template(doc)`. Templates prebuild all static content as long strings, leaving only capitalized placeholders to be filled in at render time. This provides extremely fast rendering and allows building a complex page out of clean components.
88
87
89
-
The old API lets you mutate template tags inside a `Builder` and later render the document. html5tagger 2.0 replaces this with immutable `Template` objects that you render by calling them with the desired slot values. Placeholders no longer use an underscore suffix: `doc.TagName` adds the placeholder to the document (in v1 `doc.TagName_` did so), and `doc.TagName(value)` sets a default. To migrate, remove the underscore and use `Template(doc)` to compile your document into a static template that can be called with `TagName=` keyword arguments to render HTML output.
88
+
The example below defines a page with `Title` reused for both the `<title>` and `<h1>`, and an `Items` list populated from a product list. Parentheses directly after a placeholder set its default value (empty by default).
A builder can be finalized into a template by `Template(...)`. The resulting `Template` object is immutable and is called with keyword arguments to render the placeholders. Template values follow the same escaping rules as `doc(...)`, and a list of builders or strings is expanded in place.
90
122
91
123
## Nesting
92
124
93
125
In HTML5 elements such as `<p>` do not need any closing tag, so we can keep adding content without worrying of when it should close. This module does not use closing tags for any elements where those are optional or forbidden.
94
126
95
-
A tag is automatically closed when you add content to it or when another tag is added. Setting attributes alone does not close an element. Use `(None)`to close an empty element if any subsequent content is not meant to go inside it, e.g. `doc.script(None, src="...")`.
127
+
A tag is automatically closed when you add content to it or when another tag is added. Setting attributes alone does not close an element, so we can do `doc.div[".foo"]("inside")`where the content still goes inside the div. `None` may be passed for content to close without content, e.g. `doc.div(None)("after")` produces `<div></div>after`.
96
128
97
129
For elements like `<table>` and `<ul>`, you can use `with` blocks, pass sub-snippet arguments, or add a template variable.
98
130
99
131
```python
100
132
with doc.ul: # Nest using with
101
133
doc.li("Write HTML in Python")
102
-
doc.li("Simple syntax").ul(id="inner").InnerList_# Nest using template
134
+
doc.li("Simple syntax").ul(id="inner").InnerList# Nest using template
103
135
doc.li("No need for brackets or closing tags")
104
136
doc.ul(E.li("Easy").li("Peasy")) # Nest using (...)
105
137
```
@@ -126,9 +158,7 @@ Works perfectly in browsers.
126
158
127
159
## Name mangling and boolean attributes
128
160
129
-
Underscore at the end of name is ignored so that `for_` and other attributes may be used despite being reserved words in Python. Other underscores convert into hyphens.
130
-
131
-
⚠️ The above only is true for HTML elements and attributes, but template placeholders only use an ending underscore to denote that the it is to be placed on the document, rather than be fetched for use.
161
+
Underscore at the end of a name is ignored so that `for_` and other attributes may be used despite being reserved words in Python. Other underscores convert into hyphens.
132
162
133
163
Boolean values convert into short attributes.
134
164
@@ -212,9 +242,9 @@ In the above benchmark html5tagger created the entire document from scratch, one
212
242
213
243
## Further development
214
244
215
-
There have been no changes to the tagging API since 2018 when this module was brought to production use, and thus the interface is considered stable.
245
+
There have been no changes to the tagging API since 2018 when this module was brought to production use, and thus the interface is considered stable with only small incremental changes like the `script` and `style` special methods being added.
216
246
217
-
The legacy templating API added as a draft in version 1.3 is deprecated as of version 1.4 and will be removed in 2.0, where it is replaced by a redesigned templating system. Users who depend on the old templating behaviour should pin `html5tagger<2`; all others are encouraged to upgrade to 2.0.
247
+
The templating API added as a draft in version 1.3 is deprecated as of version 1.4 and is removed in 2.0, where it is replaced by a redesigned templating system. Users who depend on the old templating behaviour should pin `html5tagger<2`; all others are encouraged to upgrade to 2.0 which is faster and more versatile.
0 commit comments