# FastTag
FastTag is a fast HTML generation module written in C for Python. It allows for efficient and easy generation of HTML tags with support for attributes and nested content.
It's almost as fast as string join, and it's built as a mostly drop in replacement for FastHTML's tag library (but 20x faster).
## Installation
You can install the module using pip:
```bash
pip install fasttag
```
## Usage:
```python
from fasttag import *
Div( # HTML Tags are exported in fasttag, but fasttag.tag("div", ...) can be used as well.
# Label("First Name") returns the HTML as a bytes (which is not escaped, just indented), but all passed strings in the element children and attribute values are escaped
Div(Label("First Name"), ": Joe"),
Div(Label("Last Name"), ": Blow"),
Div(Label("Email"), ": joe@blow.com")
# if a keyword starts with _, the first _ is ignored and the rest is used as an argument unchanged.
Button("Click To Edit", hx_get="/contact/1/edit", _class="btn primary"),
# If the keyword argument doesn't start with _, underscores are converted to hypens (-) in the attibute name
hx_target="this", hx_swap="outerHTML")
```
=>
```HTML
<div hx-target="this" hx-swap="outerHTML">
<div>
<label>First Name</label>
: Joe
</div>
<div>
<label>Last Name</label>
: Blow
</div>
<div>
<label>Email</label>
: joe@blow.com
</div>
<button hx-get="/contact/1/edit" class="btn primary">Click To Edit</button>
</div>
```
Keyword argument values can be string, boolean or numeric. Boolean values will appear as attributes without values if True, and not appear if False.
Numeric values are quoted.
```python
Input(type="checkbox", id="scales", name="scales", checked=True, disabled=False)
# => HTML('<input type="checkbox" id="scales" name="scales" checked>')
```
Values in attributes and children are converted to string automatically. The only exception is
tuples in children, which are concatenated:
```python
Div(a=[1,2,3], [4,5,6])
# => <div a='[1, 2, 3]'>[4, 5, 6]</div>
```
The HTML is represented as UTF-8. The bytes can be extracted / converted to str with:
```python
HTML('<div>Example HTML</div>').bytes() # => b'<div>Example HTML</div>'
str(HTML('<div>Example HTML</div>')) # => '<div>Example HTML</div>'
```
Text node can be created with Text (although it's automatically created for strings inside tags):
```python
Text('This is an <example> text ') # => HTML('This is an <example> text')
```
The DOCTYPE constant can be used to prepend DOCTYPE html:
```python
DOCTYPE + Html(Head(Title("Hello"), Body("Hello, world")))
```
=>
```html
<!DOCTYPE html>
<html>
<head>
<title>Hello</title>
<body>Hello, world</body>
</head>
</html>
```
Tag attribute can be used to get the tag
```python
Div("hello").tag # => "div"
```
### Changing indentation
Indentation can be set with fasttag.set_indent.
Default value is 2, but it can set to any non-negative number, or -1 which achieves no indentation and no newline between children.
It improves performance, memory usage and output size for large data.
1 space is still added between text children siblings even with -1 indentation.
```python
from fasttag import *
set_indent(-1)
Div("hello", Span("world"))
# => HTML('<div>hello<span>world</span></div>')
```
## HTML for custom objects:
Objects can implement the ```.__html__()``` method to return their HTML representation.
```python
class HTML_Test:
def __html__(self):
return "hello"
Div(HTML_Test()) # => <div>hello</div>
```
## Using with FastHTML:
FastTag was built to mostly mirror FastHTML API.
To use it, just import fasttag after fasthtml.common:
```python
from fasthtml.common import *
from fasttag import *
```
Also when returning data inside a handler, use ```.bytes()``` to convert it into ```bytes``` object.
```.__html__()``` returns the HTML as string, and ```.__ft()__``` returns the object itself (identity method) for compatibility with FastHTML.
## Benchmark:
```
fasttag latency: 0.17us 1x
join+html.escape latency: 0.53us 3x
dominate latency: 3.89us 23x
fasthtml latency: 4.99us 29x
lxml latency: 1.69us 10x
jinja2 latency: 6.83us 40x
```
## TODO:
Some missing features:
- Large table benchmarks with headers
- Comformance test vs FastHTML
- svg namespace
- parsing: attrs should get attributes
- parsing: children should extract children from text
Raw data
{
"_id": null,
"home_page": "https://github.com/adamritter/fasttag",
"name": "fasttag",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.6",
"maintainer_email": null,
"keywords": null,
"author": "Adam Ritter",
"author_email": "aritter@gmail.com",
"download_url": null,
"platform": null,
"description": "# FastTag\n\nFastTag is a fast HTML generation module written in C for Python. It allows for efficient and easy generation of HTML tags with support for attributes and nested content.\n\nIt's almost as fast as string join, and it's built as a mostly drop in replacement for FastHTML's tag library (but 20x faster).\n\n## Installation\n\nYou can install the module using pip:\n\n```bash\npip install fasttag\n```\n\n\n## Usage:\n\n```python\nfrom fasttag import *\nDiv( # HTML Tags are exported in fasttag, but fasttag.tag(\"div\", ...) can be used as well.\n # Label(\"First Name\") returns the HTML as a bytes (which is not escaped, just indented), but all passed strings in the element children and attribute values are escaped\n Div(Label(\"First Name\"), \": Joe\"),\n Div(Label(\"Last Name\"), \": Blow\"),\n Div(Label(\"Email\"), \": joe@blow.com\")\n # if a keyword starts with _, the first _ is ignored and the rest is used as an argument unchanged.\n Button(\"Click To Edit\", hx_get=\"/contact/1/edit\", _class=\"btn primary\"), \n # If the keyword argument doesn't start with _, underscores are converted to hypens (-) in the attibute name\n hx_target=\"this\", hx_swap=\"outerHTML\")\n```\n\n=>\n\n```HTML\n<div hx-target=\"this\" hx-swap=\"outerHTML\">\n<div>\n <label>First Name</label>\n : Joe\n</div>\n<div>\n <label>Last Name</label>\n : Blow\n</div>\n<div>\n <label>Email</label>\n : joe@blow.com\n</div>\n<button hx-get=\"/contact/1/edit\" class=\"btn primary\">Click To Edit</button>\n</div>\n```\n\nKeyword argument values can be string, boolean or numeric. Boolean values will appear as attributes without values if True, and not appear if False.\nNumeric values are quoted.\n\n```python\n Input(type=\"checkbox\", id=\"scales\", name=\"scales\", checked=True, disabled=False)\n # => HTML('<input type=\"checkbox\" id=\"scales\" name=\"scales\" checked>')\n```\n\nValues in attributes and children are converted to string automatically. The only exception is\ntuples in children, which are concatenated:\n\n```python\nDiv(a=[1,2,3], [4,5,6])\n# => <div a='[1, 2, 3]'>[4, 5, 6]</div>\n```\n\nThe HTML is represented as UTF-8. The bytes can be extracted / converted to str with:\n\n```python\n HTML('<div>Example HTML</div>').bytes() # => b'<div>Example HTML</div>'\n str(HTML('<div>Example HTML</div>')) # => '<div>Example HTML</div>'\n```\n\nText node can be created with Text (although it's automatically created for strings inside tags):\n\n```python\nText('This is an <example> text ') # => HTML('This is an <example> text')\n```\n\nThe DOCTYPE constant can be used to prepend DOCTYPE html:\n```python\nDOCTYPE + Html(Head(Title(\"Hello\"), Body(\"Hello, world\")))\n```\n\n=>\n```html\n<!DOCTYPE html>\n<html>\n <head>\n <title>Hello</title>\n <body>Hello, world</body>\n </head>\n</html>\n```\n\nTag attribute can be used to get the tag\n```python\nDiv(\"hello\").tag # => \"div\"\n```\n\n### Changing indentation\n\nIndentation can be set with fasttag.set_indent.\nDefault value is 2, but it can set to any non-negative number, or -1 which achieves no indentation and no newline between children.\nIt improves performance, memory usage and output size for large data.\n1 space is still added between text children siblings even with -1 indentation.\n\n```python\nfrom fasttag import *\nset_indent(-1)\nDiv(\"hello\", Span(\"world\"))\n# => HTML('<div>hello<span>world</span></div>')\n```\n\n## HTML for custom objects:\n\nObjects can implement the ```.__html__()``` method to return their HTML representation.\n\n```python\nclass HTML_Test:\n def __html__(self):\n return \"hello\"\n\nDiv(HTML_Test()) # => <div>hello</div>\n```\n\n## Using with FastHTML:\nFastTag was built to mostly mirror FastHTML API.\n\nTo use it, just import fasttag after fasthtml.common:\n\n```python\nfrom fasthtml.common import *\nfrom fasttag import *\n```\n\nAlso when returning data inside a handler, use ```.bytes()``` to convert it into ```bytes``` object.\n\n```.__html__()``` returns the HTML as string, and ```.__ft()__``` returns the object itself (identity method) for compatibility with FastHTML.\n\n\n## Benchmark:\n\n```\n fasttag latency: 0.17us 1x\n join+html.escape latency: 0.53us 3x\n dominate latency: 3.89us 23x\n fasthtml latency: 4.99us 29x\n lxml latency: 1.69us 10x\n jinja2 latency: 6.83us 40x\n```\n\n\n## TODO:\nSome missing features:\n- Large table benchmarks with headers\n- Comformance test vs FastHTML\n- svg namespace\n- parsing: attrs should get attributes\n- parsing: children should extract children from text\n",
"bugtrack_url": null,
"license": null,
"summary": "Extremely fast HTML tag generator",
"version": "0.1.5",
"project_urls": {
"Homepage": "https://github.com/adamritter/fasttag"
},
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "ba64ba5cd5ee88365f069d76ebfa44d2d71ff72471a3a4d66d5093b3ab386e44",
"md5": "76947037f4b108003f7f1f9622a87729",
"sha256": "13e4cc47d2b2b417545b8733d491d976fd2dff2251c68f599804ec0d96e4a901"
},
"downloads": -1,
"filename": "fasttag-0.1.5-cp312-cp312-macosx_14_0_arm64.whl",
"has_sig": false,
"md5_digest": "76947037f4b108003f7f1f9622a87729",
"packagetype": "bdist_wheel",
"python_version": "cp312",
"requires_python": ">=3.6",
"size": 18851,
"upload_time": "2024-10-12T10:33:33",
"upload_time_iso_8601": "2024-10-12T10:33:33.671474Z",
"url": "https://files.pythonhosted.org/packages/ba/64/ba5cd5ee88365f069d76ebfa44d2d71ff72471a3a4d66d5093b3ab386e44/fasttag-0.1.5-cp312-cp312-macosx_14_0_arm64.whl",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-10-12 10:33:33",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "adamritter",
"github_project": "fasttag",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "fasttag"
}