Skip to content

Commit

Permalink
move code
Browse files Browse the repository at this point in the history
  • Loading branch information
keithasaurus committed Oct 30, 2023
1 parent 0223d6a commit 4f46a81
Show file tree
Hide file tree
Showing 8 changed files with 288 additions and 275 deletions.
128 changes: 71 additions & 57 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
# simple_html

### Template-less. Type-safe. Minified by default.
### Template-less. Type-safe. Minified by default. Fast.

simple_html is built to simplify HTML rendering in Python. No templates needed. Just create HTML in
normal Python. In most cases, the code will be more concise than standard HTML. Other benefits include:
- typically renders fewer bytes than template-based rendering
simple_html allows you to create HTML in standard Python. Benefits include:
- it's typically faster than jinja2 -- up to 20x faster
- it typically renders fewer bytes than template-based rendering
- types mean your editor and tools can help you write correct code faster
- no framework needed
- lightweight
- lightweight and framework agnostic


### Installation
Expand All @@ -17,82 +16,97 @@ normal Python. In most cases, the code will be more concise than standard HTML.
### Usage

```python
from simple_html.nodes import body, head, html, p
from simple_html.render import render

node = html(
head,
body(
p.attrs(id="hello")(
"Hello World!"
)
)
)
from simple_html import div, h1, render

node = div({},
h1({"id": "hello"},
"Hello World!"
)
)

render(node)
# <div><h1 id="hello">Hello World!</h1></div>
```

There are several ways to render nodes:
```python
from simple_html import br, div, h1, img, render, span

# raw node
render(br)
# <br/>

# node with attributes only
render(img({"src": "/some/image/url.jpg", "alt": "a great picture"}))
# <img src="/some/image/url.jpg" alt="a great picture"/>

# node with children
render(
node) # returns: <html><head></head><body><p id="hello">Hello World!</p></body></html>
div({},
h1({},
"something"))
)
# <div><h1>something</h1></div>'
```

Node attributes with `None` as the value will only render the key
```python
from simple_html import div, render

render(div({"empty-str-attribute": "", "key-only-attr": None}))
# <div empty-str-attribute="" key-only-attr></div>
```

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

```python
from simple_html.nodes import br, p, safe_string
from simple_html.render import render
from simple_html import br, p, safe_string, render

node = p(
"Escaped & stuff",
br,
safe_string("Not escaped & stuff")
)
node = p({},
"Escaped & stuff",
br,
safe_string("Not escaped & stuff")
)

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

For convenience, many tags are provided, but you can create your own as well:

Lists and generators are both valid collections of nodes:
```python
from simple_html.nodes import Tag
from simple_html.render import render
from typing import Generator
from simple_html import div, render, Node, br

custom_elem = Tag("custom-elem")

render(
custom_elem.attrs(id="some-custom-elem-id")(
"Wow"
)
) # returns: <custom-elem id="some-custom-elem-id">Wow</custom-elem>
```
def list_of_nodes_function() -> list[Node]:
return ["neat", br]

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

```python
from simple_html.attributes import height, id_
from simple_html.nodes import div
render(div({}, list_of_nodes_function()))
# <div>neat<br/></div>


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

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

# renders to: <div id="some-id" height="100" class="abc" width="100"></div>
render(div({}, node_generator()))
# <div>neat<br/></div>
```

You can build your own presets, using `str_attr`, `int_attr`, or `bool_attr`. For instance, here are
several of the attribute preset definitions

For convenience, many tags are provided, but you can create your own as well:

```python
from simple_html.attributes import bool_attr, int_attr, str_attr
from simple_html import Tag, render

custom_elem = Tag("custom-elem")

checked = bool_attr('checked')
class_ = str_attr('class')
cols = int_attr('cols')
render(
custom_elem({"id": "some-custom-elem-id"},
"Wow"
)
) # returns: <custom-elem id="some-custom-elem-id">Wow</custom-elem>
```
But anything that renders to the type of `Attribute` will work.

Likewise, some attributes have been created as type-safe presets. Note that there are multiple ways to create attributes.
7 changes: 4 additions & 3 deletions bench/simple.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from typing import List, Tuple

from simple_html.nodes import (
from simple_html import (
h1,
html,
title,
Expand All @@ -12,9 +12,10 @@
li,
safe_string,
br,
meta, DOCTYPE_HTML5,
meta,
DOCTYPE_HTML5,
render
)
from simple_html.render import render


def hello_world_empty(objs: List[None]) -> None:
Expand Down
2 changes: 1 addition & 1 deletion poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "simple-html"
version = "0.7.0"
version = "1.0.0"
readme = "README.md"
description = "Template-less html rendering in Python"
authors = ["Keith Philpott <fakekeith@example.org>"]
Expand All @@ -19,9 +19,9 @@ mypy = "1.6.0"
pytest = "7.4.2"
setuptools = "68.2.2"
black = "23.9.1"
django = "^4.2.6"
fast-html = "^1.0.3"
dominate = "^2.8.0"
django = "4.2.6"
fast-html = "1.0.3"
dominate = "2.8.0"


[build-system]
Expand Down
Loading

0 comments on commit 4f46a81

Please sign in to comment.