{"id":16545515,"url":"https://github.com/Parnassius/domify","last_synced_at":"2025-10-28T15:31:32.996Z","repository":{"id":37986634,"uuid":"424199646","full_name":"Parnassius/domify","owner":"Parnassius","description":"HTML generator using pure Python","archived":false,"fork":false,"pushed_at":"2024-09-10T18:25:36.000Z","size":274,"stargazers_count":2,"open_issues_count":0,"forks_count":2,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-09-10T20:12:29.912Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Parnassius.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","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}},"created_at":"2021-11-03T11:39:00.000Z","updated_at":"2024-09-10T18:25:40.000Z","dependencies_parsed_at":"2023-12-02T19:28:53.215Z","dependency_job_id":"8ba7f447-e755-414c-99b5-a49c12c589b7","html_url":"https://github.com/Parnassius/domify","commit_stats":{"total_commits":79,"total_committers":3,"mean_commits":"26.333333333333332","dds":"0.15189873417721522","last_synced_commit":"d07966666390953ace51a7a23ddf4d915d2f154f"},"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Parnassius%2Fdomify","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Parnassius%2Fdomify/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Parnassius%2Fdomify/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Parnassius%2Fdomify/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Parnassius","download_url":"https://codeload.github.com/Parnassius/domify/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":219859197,"owners_count":16556036,"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","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":[],"created_at":"2024-10-11T19:07:03.873Z","updated_at":"2025-10-28T15:31:32.991Z","avatar_url":"https://github.com/Parnassius.png","language":"Python","readme":"# domify\n\nHTML generator using pure Python.\n\n[![PyPI](https://img.shields.io/pypi/v/domify)](https://pypi.org/project/domify/)\n[![PyPI - Status](https://img.shields.io/pypi/status/domify)](https://pypi.org/project/domify/)\n[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/domify)](https://pypi.org/project/domify/)\n[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)\n[![Tests status](https://img.shields.io/github/actions/workflow/status/Parnassius/domify/ci-cd.yml?branch=main\u0026label=tests)](https://github.com/Parnassius/domify/actions/workflows/ci-cd.yml)\n![Coverage](https://img.shields.io/endpoint?url=https%3A%2F%2Fraw.githubusercontent.com%2FParnassius%2Fdomify%2Fcoverage-badge%2Fcoverage-badge.json)\n[![PyPI - License](https://img.shields.io/pypi/l/domify)](https://github.com/Parnassius/domify/blob/main/LICENSE)\n\nSimple example:\n```python\nfrom domify import html_elements as e\n\nhtml = e.Html(lang=\"en\")\nwith html:\n    with e.Head():\n        e.Meta(charset=\"utf-8\")\n        e.Title(\"Example page\")\n\n    with e.Body():\n        e.H1(\"Hello world\")\n        e.P(\"Lorem ipsum \", e.I(\"dolor sit amet\"))\n\nprint(str(html))\n```\n\nHTML output (formatted for legibility):\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml lang=\"en\"\u003e\n  \u003chead\u003e\n    \u003cmeta charset=\"utf-8\"\u003e\n    \u003ctitle\u003eExample page\u003c/title\u003e\n  \u003c/head\u003e\n  \u003cbody\u003e\n    \u003ch1\u003eHello world\u003c/h1\u003e\n    \u003cp\u003eLorem ipsum \u003ci\u003edolor sit amet\u003c/i\u003e\u003c/p\u003e\n  \u003c/body\u003e\n\u003c/html\u003e\n```\n\nNote: every example on this page assumes domify has already been imported:\n```python\nfrom domify import html_elements as e\n```\n\n`domify.html_elements` contains a class for each HTML element, with the first letter\nconverted to uppercase:\n```python\np = e.P(\"Lorem ipsum dolor sit amet\")\nprint(str(p))\n```\n```html\n\u003cp\u003eLorem ipsum dolor sit amet\u003c/p\u003e\n```\n\nYou can pass strings or additional elements as positional arguments, and they will be\ntreated as children:\n```python\np = e.P(\"Lorem ipsum dolor sit amet\", e.Br(), \"consectetur adipiscing elit.\")\nprint(str(p))\n```\n```html\n\u003cp\u003e\n  Lorem ipsum dolor sit amet\n  \u003cbr\u003e\n  consectetur adipiscing elit.\n\u003c/p\u003e\n```\n\nAttributes can be passed as keyword arguments, optionally appending an underscore to\nattributes which are reserved keywords in python (for example `class`). Integers and\nfloats are automatically converted to strings, while additional underscores are replaced\nwith dashes (especially useful for `data` and `aria` attributes):\n```python\nbtn = e.Button(\"Click!\", type=\"submit\", class_=\"someclass\", data_order=155)\nprint(str(btn))\n```\n```html\n\u003cbutton type=\"submit\" class=\"someclass\" data-order=\"155\"\u003eClick!\u003c/button\u003e\n```\n\nHTML5 boolean attributes accept a boolean value instead:\n```python\ntext_input = e.Input(type=\"text\", required=True, disabled=False)\nprint(str(text_input))\n```\n```html\n\u003cinput type=\"text\" required\u003e\n```\n\nAttributes can be added or modified by subscripting an element object:\n```python\nhtml = e.Html()\nhtml[\"lang\"] = \"en\"\nprint(str(html))\n```\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml lang=\"en\"\u003e\u003c/html\u003e\n```\n\nChildren can be modified (but not added) by subscripting as well:\n```python\np = e.P(\"Text node 1\", e.Br(), \"Text node 2\")\np[0] = \"Text node 3\"\np[1:] = [e.Hr()]\nprint(str(p))\n```\n```html\n\u003cp\u003e\n  Text node 3\n  \u003chr\u003e\n\u003c/p\u003e\n```\n\nThe `del` keyword can be used to delete both attributes and children:\n```python\ndiv = e.Div(\"foo\", e.Br(), \"bar\", e.Br(), \"bar\", id=\"someid\", class_=\"someclass\")\ndel div[\"class\"]\ndel div[3:]\nprint(str(div))\n```\n```html\n\u003cdiv id=\"someid\"\u003e\n  foo\n  \u003cbr\u003e\n  bar\n\u003c/div\u003e\n```\n\n`add_class` and `remove_class` can be used to manage classes:\n```python\ndiv = e.Div(class_=\"some-class some-other-class\")\ndiv.remove_class(\"some-class\")\ndiv.add_class(\"third-class\")\nprint(str(div))\n```\n```html\n\u003cdiv class=\"some-other-class third-class\"\u003e\u003c/div\u003e\n```\n\nChildren can be added using the `add` or `insert` methods, which return the newly added\nelement:\n```python\ndiv = e.Div()\nspan = div.add(e.Span())\nspan.add(\"First line\")\nspan.add(e.Br())\nspan.add(\"Second line\")\ndiv.insert(0, e.H1(\"Title\"))\nprint(str(div))\n```\n```html\n\u003cdiv\u003e\n  \u003ch1\u003eTitle\u003c/h1\u003e\n  \u003cspan\u003e\n    First line\n    \u003cbr\u003e\n    Second line\n  \u003c/span\u003e\n\u003c/div\u003e\n```\n\nContext managers can be used to add child elements too:\n```python\nwith e.Select() as select:\n    e.Option(\"Option 1\", value=1)\n    e.Option(\"Option 2\", value=2)\n    e.Option(\"Option 3\", value=3)\nprint(str(select))\n```\n```html\n\u003cselect\u003e\n  \u003coption value=\"1\"\u003eOption 1\u003c/option\u003e\n  \u003coption value=\"2\"\u003eOption 2\u003c/option\u003e\n  \u003coption value=\"3\"\u003eOption 3\u003c/option\u003e\n\u003c/select\u003e\n```\n\nThe `+` operator can be used to concatenate multiple elements and/or strings:\n```python\nusername = \"Username: \" + e.Input(type=\"text\", name=\"username\")\npassword = \"Password: \" + e.Input(type=\"password\", name=\"password\")\nlogin_form = e.Label(username) + e.Label(password)\nlogin_form += e.Button(\"Login\", type=\"submit\")\nprint(str(login_form))\n```\n```html\n\u003clabel\u003eUsername: \u003cinput type=\"text\" name=\"username\"\u003e\u003c/label\u003e\n\u003clabel\u003ePassword: \u003cinput type=\"password\" name=\"password\"\u003e\u003c/label\u003e\n\u003cbutton type=\"submit\"\u003eLogin\u003c/button\u003e\n```\n\nText nodes can be created using `TextNode` (this is usually not required, since strings\nare automatically coverted):\n```python\nwith e.P() as p:\n    e.TextNode(\"Lorem ipsum\")\nprint(str(p))\n```\n```html\n\u003cp\u003eLorem ipsum\u003c/p\u003e\n```\n\n`RawTextNode` can be used to add strings without escaping:\n```python\nwith e.P() as p:\n    e.TextNode(\"\u003ci\u003eTextNode\u003c/i\u003e\")\n    e.Br()\n    e.RawTextNode(\"\u003ci\u003eRawTextNode\u003c/i\u003e\")\nprint(str(p))\n```\n```html\n\u003cp\u003e\n  \u0026lt;i\u0026gt;TextNode\u0026lt;/i\u0026gt;\n  \u003cbr\u003e\n  \u003ci\u003eRawTextNode\u003c/i\u003e\n\u003c/p\u003e\n```\n","funding_links":[],"categories":["Libraries"],"sub_categories":["General HTML Generation"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FParnassius%2Fdomify","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FParnassius%2Fdomify","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FParnassius%2Fdomify/lists"}