fasttag


Namefasttag JSON
Version 0.1.5 PyPI version JSON
download
home_pagehttps://github.com/adamritter/fasttag
SummaryExtremely fast HTML tag generator
upload_time2024-10-12 10:33:33
maintainerNone
docs_urlNone
authorAdam Ritter
requires_python>=3.6
licenseNone
keywords
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # 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 &lt;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 &lt;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"
}
        
Elapsed time: 0.62397s