{"id":16545509,"url":"https://github.com/niklasf/python-tinyhtml","last_synced_at":"2025-10-08T02:38:01.113Z","repository":{"id":62584825,"uuid":"305469405","full_name":"niklasf/python-tinyhtml","owner":"niklasf","description":"A tiny library to safely render compact HTML5 from Python expressions.","archived":false,"fork":false,"pushed_at":"2025-01-11T12:14:28.000Z","size":83,"stargazers_count":18,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-06-15T21:53:10.089Z","etag":null,"topics":["functional-programming","html","html5","python","python3","vdom"],"latest_commit_sha":null,"homepage":"https://pypi.org/project/tinyhtml/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/niklasf.png","metadata":{"files":{"readme":"README.rst","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE-APACHE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"niklasf"}},"created_at":"2020-10-19T17:55:11.000Z","updated_at":"2025-05-21T04:23:32.000Z","dependencies_parsed_at":"2024-10-11T19:17:16.795Z","dependency_job_id":null,"html_url":"https://github.com/niklasf/python-tinyhtml","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/niklasf/python-tinyhtml","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/niklasf%2Fpython-tinyhtml","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/niklasf%2Fpython-tinyhtml/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/niklasf%2Fpython-tinyhtml/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/niklasf%2Fpython-tinyhtml/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/niklasf","download_url":"https://codeload.github.com/niklasf/python-tinyhtml/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/niklasf%2Fpython-tinyhtml/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":269740361,"owners_count":24467759,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-10T02:00:08.965Z","response_time":71,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["functional-programming","html","html5","python","python3","vdom"],"created_at":"2024-10-11T19:07:03.767Z","updated_at":"2025-10-08T02:38:01.039Z","avatar_url":"https://github.com/niklasf.png","language":"Python","funding_links":["https://github.com/sponsors/niklasf"],"categories":["Libraries"],"sub_categories":["General HTML Generation"],"readme":"tinyhtml\n========\n\nA tiny library to safely render compact HTML5 from Python expressions.\n\n.. image:: https://github.com/niklasf/python-tinyhtml/workflows/Test/badge.svg\n    :target: https://github.com/niklasf/python-tinyhtml/actions\n    :alt: Test status\n\n.. image:: https://badge.fury.io/py/tinyhtml.svg\n    :target: https://pypi.python.org/pypi/tinyhtml\n    :alt: PyPI package\n\nIntroduction\n------------\n\nThis is the entire API. The following documentation is longer than the\nimplementation.\n\n.. code:: python\n\n    \u003e\u003e\u003e from tinyhtml import html, h, frag, raw\n\nThe most important function is ``h()``. Below you see how to render attributes,\nnormal elements, and void/self-closing elements.\n\n.. code:: python\n\n    \u003e\u003e\u003e html(lang=\"en\")(\n    ...     h(\"head\")(\n    ...         h(\"meta\", charset=\"utf-8\"),\n    ...     ),\n    ... ).render()\n    '\u003c!DOCTYPE html\u003e\u003chtml lang=\"en\"\u003e\u003chead\u003e\u003cmeta charset=\"utf-8\"\u003e\u003c/head\u003e\u003c/html\u003e'\n\nUse ``frag()`` to pass around groups of elements.\n\n.. code:: python\n\n    \u003e\u003e\u003e frag(\n    ...     h(\"h1\")(\"Lorem ipsum ...\"),\n    ...     h(\"p\")(\"... dolor sit amet.\"),\n    ... )\n    raw('\u003ch1\u003eLorem ipsum ...\u003c/h1\u003e\u003cp\u003e... dolor sit amet.\u003c/p\u003e')\n\nOf course all content and attributes are properly escaped. Use ``raw()`` as an\nescape hatch to render unescaped HTML.\n\n.. code:: python\n\n    \u003e\u003e\u003e print(h(\"a\", title=\"\u0026\u003c\u003e\\\"'\")(\"\u0026\u003c\u003e\\\"'\").render())\n    \u003ca title=\"\u0026amp;\u0026lt;\u0026gt;\u0026quot;'\"\u003e\u0026amp;\u0026lt;\u0026gt;\"'\u003c/a\u003e\n\n    \u003e\u003e\u003e print(raw(\"\u003c!-- 💥\"))\n    \u003c!-- 💥\n\n\nInstalling\n----------\n\n::\n\n    pip install tinyhtml\n\n\nFeatures and patterns\n---------------------\n\n* Output is compact: Naturally produces no superfluous whitespace between\n  elements.\n\n* Fragments provide ``_repr_html_()`` for Jupyter notebook integration and\n  ``__html__`` for integration with other ecosystems (see\n  `MarkupSafe \u003chttps://markupsafe.palletsprojects.com/en/stable/html/\u003e`_).\n\n* Fragments can include and render objects providing ``_repr_html_()`` and\n  ``__html__()``. This means objects that already render as HTML in a\n  Jupyter notebook will be rendered by tinyhtml.\n\n* Includes mypy typings.\n\n  .. code:: python\n\n      \u003e\u003e\u003e from tinyhtml import Frag\n\n* Write **templates** as functions.\n\n  .. code:: python\n\n      \u003e\u003e\u003e def layout(title: str, body: Frag) -\u003e Frag:\n      ...     return html()(\n      ...        h(\"head\")(\n      ...            h(\"title\")(title),\n      ...        ),\n      ...        h(\"body\")(body)\n      ...     )\n\n      \u003e\u003e\u003e layout(\"Hello world\", frag(\n      ...     h(\"h1\")(\"Hello world\"),\n      ...     h(\"p\")(\"Lorem ipsum dolor sit amet.\"),\n      ... ))\n      raw('\u003c!DOCTYPE html\u003e\u003chtml\u003e\u003chead\u003e\u003ctitle\u003eHello world\u003c/title\u003e\u003c/head\u003e\u003cbody\u003e\u003ch1\u003eHello world\u003c/h1\u003e\u003cp\u003eLorem ipsum dolor sit amet.\u003c/p\u003e\u003c/body\u003e\u003c/html\u003e')\n\n* Use ``str``, ``int``, other fragments, ``None``, or iterables of these as\n  **child elements**. (Note that rendering consumes the iterables, so fragments\n  using generators can be rendered only once.)\n\n  .. code:: python\n\n      \u003e\u003e\u003e h(\"ul\")(\n      ...     h(\"li\")(n) for n in range(3)\n      ... )\n      raw('\u003cul\u003e\u003cli\u003e0\u003c/li\u003e\u003cli\u003e1\u003c/li\u003e\u003cli\u003e2\u003c/li\u003e\u003c/ul\u003e')\n\n      \u003e\u003e\u003e h(\"ul\")(\n      ...     h(\"li\")(\"Foo\") if False else None,\n      ...     h(\"li\")(\"Bar\"),\n      ... )\n      raw('\u003cul\u003e\u003cli\u003eBar\u003c/li\u003e\u003c/ul\u003e')\n\n* Use ``str``, ``int``, ``None``, iterables of these, ``bool``, or dictionaries\n  with boolean values as **attributes**.\n\n  .. code:: python\n\n      \u003e\u003e\u003e h(\"input\", type=\"checkbox\", checked=True, disabled=False)\n      raw('\u003cinput type=\"checkbox\" checked\u003e')\n\n      \u003e\u003e\u003e h(\"body\", klass=[\"a\", \"b\"])()\n      raw('\u003cbody class=\"a b\"\u003e\u003c/body\u003e')\n\n      \u003e\u003e\u003e h(\"body\", klass={\n      ...    \"a\": True,\n      ...    \"b\": False,\n      ... })()\n      raw('\u003cbody class=\"a\"\u003e\u003c/body\u003e')\n\n\n* Use ``klass`` instead of ``class``, append a trailing underscore (``for_``),\n  or use underscores instead of dashes (``http_equiv``) for attribute names\n  that cannot be Python identifiers.\n\n  .. code:: python\n\n      \u003e\u003e\u003e h(\"div\", klass=\"container\")()\n      raw('\u003cdiv class=\"container\"\u003e\u003c/div\u003e')\n\n      \u003e\u003e\u003e h(\"label\", for_=\"name\")(\"Name\")\n      raw('\u003clabel for=\"name\"\u003eName\u003c/label\u003e')\n\n      \u003e\u003e\u003e h(\"meta\", http_equiv=\"refresh\", content=10)\n      raw('\u003cmeta http-equiv=\"refresh\" content=\"10\"\u003e')\n\n* Render fragments as ``str``, or into a list of ``str`` for efficient string\n  building.\n\n  .. code:: python\n\n      \u003e\u003e\u003e frag(\"Hello world\", \"!\").render()\n      'Hello world!'\n\n      \u003e\u003e\u003e builder = []\n      \u003e\u003e\u003e frag(\"Hello world\", \"!\").render_into(builder)\n      \u003e\u003e\u003e builder\n      ['Hello world', '!']\n      \u003e\u003e\u003e \"\".join(builder)\n      'Hello world!'\n\n* Does not support comment nodes, unescapable raw text elements\n  (like inline styles and scripts), or foreign elements (like inline SVG).\n  Instead, reference external files, or use ``raw()`` with appropriate caution.\n\n\nInteroperability\n----------------\n\nFragments implement ``_repr_html_`` and can be displayed in Jupyter notebooks\nas HTML, but they can also render object that implement ``_repr_html_``.\nSimilarly fragments can include and be included in other template systems that\nuse the ``__html__`` convention, such as Jinja2 via\n`MarkupSafe`_.\n\n* Render fragments into a Jinja2 template.\n\n  .. code:: python\n\n      \u003e\u003e\u003e import jinja2\n      \u003e\u003e\u003e\n      \u003e\u003e\u003e template = jinja2.Template('\u003cdiv\u003e{{ fragment }}\u003c/div\u003e')\n      \u003e\u003e\u003e frag = h('ul')(h('li')(i) for i in range(2))\n      \u003e\u003e\u003e template.render(fragment=frag)\n      '\u003cdiv\u003e\u003cul\u003e\u003cli\u003e0\u003c/li\u003e\u003cli\u003e1\u003c/li\u003e\u003c/ul\u003e\u003c/div\u003e'\n\n\n* Render an object the supports display in a Jupyter notebook, such as a pandas\n  dataframe.\n\n  .. code:: python\n\n      \u003e\u003e\u003e import pandas as pd\n      \u003e\u003e\u003e\n      \u003e\u003e\u003e table = pd.DataFrame({'Fruit': ['apple', 'pear'], 'Count': [3, 4]})\n      \u003e\u003e\u003e h('div')(h('h1')('A table'), table) # doctest: +ELLIPSIS\n      raw('\u003cdiv\u003e\u003ch1\u003eA table\u003c/h1\u003e\u003cdiv\u003e...\u003ctable ...\u003e...\u003ctd\u003eapple\u003c/td\u003e...\u003c/table\u003e...\u003c/div\u003e')\n\n\nLicense\n-------\n\nLicensed under the\n`Apache License, Version 2.0 \u003chttps://www.apache.org/licenses/LICENSE-2.0\u003e`_,\nor the `MIT license \u003chttps://opensource.org/licenses/MIT\u003e`_, at your option.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fniklasf%2Fpython-tinyhtml","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fniklasf%2Fpython-tinyhtml","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fniklasf%2Fpython-tinyhtml/lists"}