Skip to main content

Extremely fast HTML tag generator

Project description

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:

pip install fasttag

Usage:

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")

=>

<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.

    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:

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:

  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):

Text('This is an <example> text ') # => HTML('This is an &lt;example> text')

The DOCTYPE constant can be used to prepend DOCTYPE html:

DOCTYPE + Html(Head(Title("Hello"), Body("Hello, world")))

=>

<!DOCTYPE html>
<html>
  <head>
    <title>Hello</title>
    <body>Hello, world</body>
  </head>
</html>

Tag attribute can be used to get the tag

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.

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.

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:

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

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distribution

fasttag-0.1.5-cp312-cp312-macosx_14_0_arm64.whl (18.9 kB view details)

Uploaded CPython 3.12 macOS 14.0+ ARM64

File details

Details for the file fasttag-0.1.5-cp312-cp312-macosx_14_0_arm64.whl.

File metadata

File hashes

Hashes for fasttag-0.1.5-cp312-cp312-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 13e4cc47d2b2b417545b8733d491d976fd2dff2251c68f599804ec0d96e4a901
MD5 76947037f4b108003f7f1f9622a87729
BLAKE2b-256 ba64ba5cd5ee88365f069d76ebfa44d2d71ff72471a3a4d66d5093b3ab386e44

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page