# Simple Pythonic HTML Creator (sphc) 🐍✨
A super simple and *Pythonic* way to create HTML, for Python 3.
- ✅ Ultra simple and it just works!
- 🐍 Pythonic syntax you'll love.
- 🚀 Modern and built for Python 3.
```python
>>> from sphc import tf
>>> adiv = tf.DIV("Hello World!", id="header_1", Class="header")
>>> print(adiv)
<DIV id="header_1" Class="header">Hello World!</DIV>
```
## 📖 It's super easy to learn!
### Hello World!
```python
>>> import sphc
>>> tf = sphc.TagFactory()
>>> header = tf.H1("Hello World!")
>>> print(header)
<H1>Hello World!</H1>
```
### Constructing a Page 📄
```python
>>> doc = tf.HTML()
>>> doc.body.content = tf.H1("The content")
>>> print(doc)
<HTML><BODY><H1>The content</H1></BODY></HTML>
```
### Using Lists of Tags 📋
Especially useful for constructing tables and select options.
```python
>>> data = [('One', '1'), ('Two', '2'), ('Three', '3')]
>>> atable = tf.TABLE()
>>> for element in data:
... row = tf.TR()
... row.cells = [tf.TD(element[0]), tf.TD(element[1])]
... atable.row = row
>>> print(atable)
<TABLE><TR><TD>One</TD><TD>1</TD></TR><TR><TD>Two</TD><TD>2</TD></TR><TR><TD>Three</TD><TD>3</TD></TR></TABLE>
```
### Wrapping Content 🎁
```python
>>> block1 = tf.DIV(tf.DIV("content", Class="inner"), Class="outer")
>>> block2 = tf.DIV([tf.DIV(), tf.DIV()], Class="outer")
>>> content = tf.DIV([block1, block2])
```
### Chaining Methods ⛓️
The `set_required` method sets the `required` property on a Tag object AND returns the Tag object, so you can chain calls.
```python
>>> form = tf.FORM()
>>> form.username = tf.INPUT(name="username").set_required()
>>> print(form)
<FORM><INPUT name="username" required/></FORM>
```
### Properties with No Value ☑️
```python
>>> c = tf.INPUT(None, 'checked', type='checkbox', value='foo')
>>> print(c)
<INPUT type="checkbox" value="foo" checked/>
```
### Escaping Content 🔓
By default, content is escaped to prevent XSS attacks.
```python
>>> print(tf.C(' >> ')) # Default
<C> >> </C>
>>> print(tf.C(' >> ', escape=False))
<C> >> </C>
```
## 🚀 More Experimental Stuff
Ready for more? Let's dive into some advanced features in `sphc.more`.
### Hello `sphc.more` 👋
```python
>>> import sphc.more
>>> tf = sphc.TagFactory()
>>> class MyPage(sphc.more.HTML5Page):
... def footer(self):
... return tf.FOOTER("Footer text")
>>> my_page = MyPage()
>>> my_page.render()
```
This will return a complete HTML5 page as a string, just like you'd expect.
### Building a Form 📝
```python
>>> import sphc
>>> import sphc.more
>>>
>>> tf = sphc.TagFactory()
>>>
>>> form = sphc.more.Form(classes=['vform'])
>>> form.add_field('Username', tf.INPUT(type="TEXT", id='username', name="username").set_required())
>>> form.add_field('Password', tf.INPUT(type="password", id='password', name="password"))
>>> form.add_buttons(tf.BUTTON("Log In", id='login-btn', type='button'))
>>> print(form.build())
<FORM method="POST" Class="vform"><DIV Class="field"><DIV Class="field-label"><LABEL For="username">Username</LABEL></DIV><DIV Class="field-input"><INPUT type="TEXT" id="username" name="username" required/><C> *</C></DIV></DIV><DIV Class="field"><DIV Class="field-label"><LABEL For="password">Password</LABEL></DIV><DIV Class="field-input"><INPUT type="password" id="password" name="password"/></DIV></DIV><DIV Class="action-status"></DIV><DIV Class="buttons"><BUTTON id="login-btn" type="button">Log In</BUTTON></DIV></FORM>
```
### Forms with Fieldsets 🗂️
```python
>>> form = sphc.more.Form()
>>>
>>> about = form.add(sphc.more.Fieldset())
>>> about.add(sphc.tf.LEGEND('About'))
>>> about.add_field('Name', sphc.tf.INPUT(name='name', type='text'))
>>>
>>> contact = form.add(sphc.more.Fieldset())
>>> contact.add(sphc.tf.LEGEND('Contact'))
>>> contact.add_field('Email', sphc.tf.INPUT(name='email', type='email'))
>>> print(form.build())
<FORM method="POST"><FIELDSET><LEGEND>About</LEGEND><DIV Class="field"><DIV Class="field-label"><LABEL For="form-name">Name</LABEL></DIV><DIV Class="field-input"><INPUT name="name" type="text" id="form-name"/></DIV></DIV></FIELDSET><FIELDSET><LEGEND>Contact</LEGEND><DIV Class="field"><DIV Class="field-label"><LABEL For="form-email">Email</LABEL></DIV><DIV Class="field-input"><INPUT name="email" type="email" id="form-email"/></DIV></DIV></FIELDSET></FORM>
```
## 💻 Source
Find the source code on GitHub:
[https://github.com/shon/sphc](https://github.com/shon/sphc)
## 🛠️ Building from Source
For instructions on how to build and distribute the package from source, please see [BUILD.md](BUILD.md).
---
## 🚀 Performance
A small, informal benchmark was conducted to compare `sphc` with some other popular template/html generation libraries. The benchmark generates a 100-row HTML table 1000 times. The results below show the time taken in seconds (lower is better).
Please note that these benchmarks are not comprehensive and your results may vary depending on the specific use case and hardware.
| Library | Time (seconds) | Chart (longer is slower) |
|--------------|----------------|------------------------------------------------------------|
| [Mako] | 1.81 | `████` |
| [Jinja2] | 4.08 | `█████████` |
| [sphc] | 11.33 | `██████████████████████████` |
| [dominate] | 17.26 | `████████████████████████████████████████` |
*These results were generated on a generic cloud instance and should be taken with a grain of salt.*
[Mako]: https://www.makotemplates.org/
[Jinja2]: https://jinja.palletsprojects.com/
[dominate]: https://github.com/Knio/dominate
[sphc]: https://github.com/shon/sphc
Raw data
{
"_id": null,
"home_page": null,
"name": "sphc",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3",
"maintainer_email": null,
"keywords": "html, pythonic, html-generator, web-development",
"author": null,
"author_email": "Shekhar Tiwatne <pythonic@gmail.com>",
"download_url": "https://files.pythonhosted.org/packages/76/94/09486a8571a8740193500c7f22338a897cb9d3271d1f05aa853c80d33e01/sphc-1.0.1.tar.gz",
"platform": null,
"description": "# Simple Pythonic HTML Creator (sphc) \ud83d\udc0d\u2728\n\nA super simple and *Pythonic* way to create HTML, for Python 3.\n\n- \u2705 Ultra simple and it just works!\n- \ud83d\udc0d Pythonic syntax you'll love.\n- \ud83d\ude80 Modern and built for Python 3.\n\n```python\n>>> from sphc import tf\n>>> adiv = tf.DIV(\"Hello World!\", id=\"header_1\", Class=\"header\")\n>>> print(adiv)\n<DIV id=\"header_1\" Class=\"header\">Hello World!</DIV>\n```\n\n## \ud83d\udcd6 It's super easy to learn!\n\n### Hello World!\n\n```python\n>>> import sphc\n>>> tf = sphc.TagFactory()\n>>> header = tf.H1(\"Hello World!\")\n>>> print(header)\n<H1>Hello World!</H1>\n```\n\n### Constructing a Page \ud83d\udcc4\n\n```python\n>>> doc = tf.HTML()\n>>> doc.body.content = tf.H1(\"The content\")\n>>> print(doc)\n<HTML><BODY><H1>The content</H1></BODY></HTML>\n```\n\n### Using Lists of Tags \ud83d\udccb\n\nEspecially useful for constructing tables and select options.\n\n```python\n>>> data = [('One', '1'), ('Two', '2'), ('Three', '3')]\n>>> atable = tf.TABLE()\n>>> for element in data:\n... row = tf.TR()\n... row.cells = [tf.TD(element[0]), tf.TD(element[1])]\n... atable.row = row\n>>> print(atable)\n<TABLE><TR><TD>One</TD><TD>1</TD></TR><TR><TD>Two</TD><TD>2</TD></TR><TR><TD>Three</TD><TD>3</TD></TR></TABLE>\n```\n\n### Wrapping Content \ud83c\udf81\n\n```python\n>>> block1 = tf.DIV(tf.DIV(\"content\", Class=\"inner\"), Class=\"outer\")\n>>> block2 = tf.DIV([tf.DIV(), tf.DIV()], Class=\"outer\")\n>>> content = tf.DIV([block1, block2])\n```\n\n### Chaining Methods \u26d3\ufe0f\n\nThe `set_required` method sets the `required` property on a Tag object AND returns the Tag object, so you can chain calls.\n\n```python\n>>> form = tf.FORM()\n>>> form.username = tf.INPUT(name=\"username\").set_required()\n>>> print(form)\n<FORM><INPUT name=\"username\" required/></FORM>\n```\n\n### Properties with No Value \u2611\ufe0f\n\n```python\n>>> c = tf.INPUT(None, 'checked', type='checkbox', value='foo')\n>>> print(c)\n<INPUT type=\"checkbox\" value=\"foo\" checked/>\n```\n\n### Escaping Content \ud83d\udd13\n\nBy default, content is escaped to prevent XSS attacks.\n\n```python\n>>> print(tf.C(' >> ')) # Default\n<C> >> </C>\n\n>>> print(tf.C(' >> ', escape=False))\n<C> >> </C>\n```\n\n## \ud83d\ude80 More Experimental Stuff\n\nReady for more? Let's dive into some advanced features in `sphc.more`.\n\n### Hello `sphc.more` \ud83d\udc4b\n\n```python\n>>> import sphc.more\n>>> tf = sphc.TagFactory()\n>>> class MyPage(sphc.more.HTML5Page):\n... def footer(self):\n... return tf.FOOTER(\"Footer text\")\n>>> my_page = MyPage()\n>>> my_page.render()\n```\nThis will return a complete HTML5 page as a string, just like you'd expect.\n\n### Building a Form \ud83d\udcdd\n\n```python\n>>> import sphc\n>>> import sphc.more\n>>>\n>>> tf = sphc.TagFactory()\n>>>\n>>> form = sphc.more.Form(classes=['vform'])\n>>> form.add_field('Username', tf.INPUT(type=\"TEXT\", id='username', name=\"username\").set_required())\n>>> form.add_field('Password', tf.INPUT(type=\"password\", id='password', name=\"password\"))\n>>> form.add_buttons(tf.BUTTON(\"Log In\", id='login-btn', type='button'))\n>>> print(form.build())\n<FORM method=\"POST\" Class=\"vform\"><DIV Class=\"field\"><DIV Class=\"field-label\"><LABEL For=\"username\">Username</LABEL></DIV><DIV Class=\"field-input\"><INPUT type=\"TEXT\" id=\"username\" name=\"username\" required/><C> *</C></DIV></DIV><DIV Class=\"field\"><DIV Class=\"field-label\"><LABEL For=\"password\">Password</LABEL></DIV><DIV Class=\"field-input\"><INPUT type=\"password\" id=\"password\" name=\"password\"/></DIV></DIV><DIV Class=\"action-status\"></DIV><DIV Class=\"buttons\"><BUTTON id=\"login-btn\" type=\"button\">Log In</BUTTON></DIV></FORM>\n```\n\n### Forms with Fieldsets \ud83d\uddc2\ufe0f\n\n```python\n>>> form = sphc.more.Form()\n>>>\n>>> about = form.add(sphc.more.Fieldset())\n>>> about.add(sphc.tf.LEGEND('About'))\n>>> about.add_field('Name', sphc.tf.INPUT(name='name', type='text'))\n>>>\n>>> contact = form.add(sphc.more.Fieldset())\n>>> contact.add(sphc.tf.LEGEND('Contact'))\n>>> contact.add_field('Email', sphc.tf.INPUT(name='email', type='email'))\n>>> print(form.build())\n<FORM method=\"POST\"><FIELDSET><LEGEND>About</LEGEND><DIV Class=\"field\"><DIV Class=\"field-label\"><LABEL For=\"form-name\">Name</LABEL></DIV><DIV Class=\"field-input\"><INPUT name=\"name\" type=\"text\" id=\"form-name\"/></DIV></DIV></FIELDSET><FIELDSET><LEGEND>Contact</LEGEND><DIV Class=\"field\"><DIV Class=\"field-label\"><LABEL For=\"form-email\">Email</LABEL></DIV><DIV Class=\"field-input\"><INPUT name=\"email\" type=\"email\" id=\"form-email\"/></DIV></DIV></FIELDSET></FORM>\n```\n\n## \ud83d\udcbb Source\n\nFind the source code on GitHub:\n[https://github.com/shon/sphc](https://github.com/shon/sphc)\n\n## \ud83d\udee0\ufe0f Building from Source\n\nFor instructions on how to build and distribute the package from source, please see [BUILD.md](BUILD.md).\n\n---\n\n## \ud83d\ude80 Performance\n\nA small, informal benchmark was conducted to compare `sphc` with some other popular template/html generation libraries. The benchmark generates a 100-row HTML table 1000 times. The results below show the time taken in seconds (lower is better).\n\nPlease note that these benchmarks are not comprehensive and your results may vary depending on the specific use case and hardware.\n\n| Library | Time (seconds) | Chart (longer is slower) |\n|--------------|----------------|------------------------------------------------------------|\n| [Mako] | 1.81 | `\u2588\u2588\u2588\u2588` |\n| [Jinja2] | 4.08 | `\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588` |\n| [sphc] | 11.33 | `\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588` |\n| [dominate] | 17.26 | `\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588` |\n\n*These results were generated on a generic cloud instance and should be taken with a grain of salt.*\n\n[Mako]: https://www.makotemplates.org/\n[Jinja2]: https://jinja.palletsprojects.com/\n[dominate]: https://github.com/Knio/dominate\n[sphc]: https://github.com/shon/sphc\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Simple Pythonic HTML Creator",
"version": "1.0.1",
"project_urls": {
"Homepage": "https://shon.github.io",
"Source": "https://github.com/shon/sphc"
},
"split_keywords": [
"html",
" pythonic",
" html-generator",
" web-development"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "323ee8690be84e89feceeda112bb931c8589c019f0fb2cfd509a3b1ccb5e24e1",
"md5": "5acea42b36476a85f60e0db1ee94e7c7",
"sha256": "647cbd8e1104bd4865e68c607429063429210ea327069ef909705a14eddfb355"
},
"downloads": -1,
"filename": "sphc-1.0.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "5acea42b36476a85f60e0db1ee94e7c7",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3",
"size": 9161,
"upload_time": "2025-08-16T07:51:57",
"upload_time_iso_8601": "2025-08-16T07:51:57.269072Z",
"url": "https://files.pythonhosted.org/packages/32/3e/e8690be84e89feceeda112bb931c8589c019f0fb2cfd509a3b1ccb5e24e1/sphc-1.0.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "769409486a8571a8740193500c7f22338a897cb9d3271d1f05aa853c80d33e01",
"md5": "7ec8462f7ebf0093f2e7828a5e23ce45",
"sha256": "2ab8de7ee46bff5cbc80a85de14251ca3950e0ec5d0675a71c5d6d166eb54cae"
},
"downloads": -1,
"filename": "sphc-1.0.1.tar.gz",
"has_sig": false,
"md5_digest": "7ec8462f7ebf0093f2e7828a5e23ce45",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3",
"size": 9144,
"upload_time": "2025-08-16T07:51:58",
"upload_time_iso_8601": "2025-08-16T07:51:58.865324Z",
"url": "https://files.pythonhosted.org/packages/76/94/09486a8571a8740193500c7f22338a897cb9d3271d1f05aa853c80d33e01/sphc-1.0.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-08-16 07:51:58",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "shon",
"github_project": "sphc",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "sphc"
}