# domify
HTML generator using pure Python.
[](https://pypi.org/project/domify/)
[](https://pypi.org/project/domify/)
[](https://pypi.org/project/domify/)
[](https://github.com/psf/black)
[](https://github.com/Parnassius/domify/actions/workflows/main.yml)
[](https://codecov.io/gh/Parnassius/domify)
[](https://github.com/Parnassius/domify/blob/main/LICENSE)
Simple example:
```python
from domify import html_elements as e
html = e.Html(lang="en")
with html:
with e.Head():
e.Meta(charset="utf-8")
e.Title("Example page")
with e.Body():
e.H1("Hello world")
e.P("Lorem ipsum ", e.I("dolor sit amet"))
print(str(html))
```
HTML output (formatted for legibility):
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Example page</title>
</head>
<body>
<h1>Hello world</h1>
<p>Lorem ipsum <i>dolor sit amet</i></p>
</body>
</html>
```
Note: every example on this page assumes domify has already been imported:
```python
from domify import html_elements as e
```
`domify.html_elements` contains a class for each HTML element, with the first letter
converted to uppercase:
```python
p = e.P("Lorem ipsum dolor sit amet")
print(str(p))
```
```html
<p>Lorem ipsum dolor sit amet</p>
```
You can pass strings or additional elements as positional arguments, and they will be
treated as children:
```python
p = e.P("Lorem ipsum dolor sit amet", e.Br(), "consectetur adipiscing elit.")
print(str(p))
```
```html
<p>
Lorem ipsum dolor sit amet
<br>
consectetur adipiscing elit.
</p>
```
Attributes can be passed as keyword arguments, optionally appending an underscore to
attributes which are reserved keywords in python (for example `class`). Integers and
floats are automatically converted to strings, while additional underscores are replaced
with dashes (especially useful for `data` and `aria` attributes):
```python
btn = e.Button("Click!", type="submit", class_="someclass", data_order=155)
print(str(btn))
```
```html
<button type="submit" class="someclass" data-order="155">Click!</button>
```
HTML5 boolean attributes accept a boolean value instead:
```python
text_input = e.Input(type="text", required=True, disabled=False)
print(str(text_input))
```
```html
<input type="text" required>
```
Attributes can be added or modified by subscripting an element object:
```python
html = e.Html()
html["lang"] = "en"
print(str(html))
```
```html
<!DOCTYPE html>
<html lang="en"></html>
```
Children can be modified (but not added) by subscripting as well:
```python
p = e.P("Text node 1", e.Br(), "Text node 2")
p[0] = "Text node 3"
p[1:] = [e.Hr()]
print(str(p))
```
```html
<p>
Text node 3
<hr>
</p>
```
The `del` keyword can be used to delete both attributes and children:
```python
div = e.Div("foo", e.Br(), "bar", e.Br(), "bar", id="someid", class_="someclass")
del div["class"]
del div[3:]
print(str(div))
```
```html
<div id="someid">
foo
<br>
bar
</div>
```
`add_class` and `remove_class` can be used to manage classes:
```python
div = e.Div(class_="some-class some-other-class")
div.remove_class("some-class")
div.add_class("third-class")
print(str(div))
```
```html
<div class="some-other-class third-class"></div>
```
Children can be added using the `add` or `insert` methods, which return the newly added
element:
```python
div = e.Div()
span = div.add(e.Span())
span.add("First line")
span.add(e.Br())
span.add("Second line")
div.insert(0, e.H1("Title"))
print(str(div))
```
```html
<div>
<h1>Title</h1>
<span>
First line
<br>
Second line
</span>
</div>
```
Context managers can be used to add child elements too:
```python
with e.Select() as select:
e.Option("Option 1", value=1)
e.Option("Option 2", value=2)
e.Option("Option 3", value=3)
print(str(select))
```
```html
<select>
<option value="1">Option 1</option>
<option value="2">Option 2</option>
<option value="3">Option 3</option>
</select>
```
The `+` operator can be used to concatenate multiple elements and/or strings:
```python
username = "Username: " + e.Input(type="text", name="username")
password = "Password: " + e.Input(type="password", name="password")
login_form = e.Label(username) + e.Label(password)
login_form += e.Button("Login", type="submit")
print(str(login_form))
```
```html
<label>Username: <input type="text" name="username"></label>
<label>Password: <input type="password" name="password"></label>
<button type="submit">Login</button>
```
Text nodes can be created using `TextNode` (this is usually not required, since strings
are automatically coverted):
```python
with e.P() as p:
e.TextNode("Lorem ipsum")
print(str(p))
```
```html
<p>Lorem ipsum</p>
```
`RawTextNode` can be used to add strings without escaping:
```python
with e.P() as p:
e.TextNode("<i>TextNode</i>")
e.Br()
e.RawTextNode("<i>RawTextNode</i>")
print(str(p))
```
```html
<p>
<i>TextNode</i>
<br>
<i>RawTextNode</i>
</p>
```