{"id":20815187,"url":"https://github.com/hoishing/ptag","last_synced_at":"2026-01-24T01:38:24.923Z","repository":{"id":253603494,"uuid":"843993909","full_name":"hoishing/ptag","owner":"hoishing","description":"pythonic way to create HTML/XML/SVG tags","archived":false,"fork":false,"pushed_at":"2024-10-07T03:28:10.000Z","size":137,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-11-10T01:57:51.386Z","etag":null,"topics":["html","python","svg","tag","template","xml"],"latest_commit_sha":null,"homepage":"https://pypi.org/project/ptag/","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/hoishing.png","metadata":{"files":{"readme":"README.md","changelog":null,"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":"2024-08-18T03:49:05.000Z","updated_at":"2024-10-07T03:28:13.000Z","dependencies_parsed_at":"2024-08-18T04:49:31.745Z","dependency_job_id":null,"html_url":"https://github.com/hoishing/ptag","commit_stats":null,"previous_names":["hoishing/ptag"],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hoishing%2Fptag","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hoishing%2Fptag/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hoishing%2Fptag/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hoishing%2Fptag/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hoishing","download_url":"https://codeload.github.com/hoishing/ptag/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225092153,"owners_count":17419606,"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":["html","python","svg","tag","template","xml"],"created_at":"2024-11-17T21:19:53.479Z","updated_at":"2026-01-24T01:38:24.917Z","avatar_url":"https://github.com/hoishing.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ptag\n\n[![ci-badge]][ci-url] [![pypi-badge]][pypi-url] [![MIT-badge]][MIT-url] [![black-badge]][black-url]\n\n\u003e generate html/svg tags hierarchy with context manager\n\n---\n\n\u003e [!NOTE]\n\u003e The repository has been archived. Initially, using a context manager to construct the DOM structure seemed \"Pythonic\" syntactically. However, I later discovered that this approach introduced an additional layer of complexity and negatively impacted performance at a larger scale. As a result, I developed **[tagit](https://github.com/hoishing/tagit)**, a much simpler and more performant DOM library. It exclusively handles string inputs and outputs without complex features, while still managing the DOM structure purely within Python code.\n\n- use ⭐️ context manager ⭐️ to create tag hierarchy\n- create value-less(boolean) attributes with positional argument\n    - handy for using with [UnoCSS] attributify mode\n- all standard html and svg elements are exported as functions\n- pure python, no external dependencies\n- high test coverage\n\n## Quick Start\n\n- Installation: `pip install ptag`\n- base signature\n    - `element(content = None, *args, **kwargs) -\u003e Tag`\n\n```python\n# common elements\nfrom ptag import div, img, p, ul, li, label, input_,\n# for creating custom element\nfrom ptag import Tag  \n# for pretty print\nfrom ptag import prettify  \n\n# empty tag\nprint(div())\n# \u003cdiv /\u003e\n\n# None content is ignored\nprint(div(None))\n# \u003cdiv /\u003e\n\n# empty string content creates closing tag\nprint(div(\"\"))\n# \u003cdiv\u003e\u003c/div\u003e\n\n# tag as content\nprint(div(img(src=\"url\"), id=\"bar\"))  \n# \u003cdiv id=\"bar\"\u003e\u003cimg src=\"url\"/\u003e\u003c/div\u003e\n\n# content mix with strings and tags\nprint(div([\"foo\", img(src=\"url\"), \"bar\")])\n# \u003cdiv\u003efoo\u003cimg src=\"url\"/\u003ebar\u003c/div\u003e\n```\n\n- use with context manager\n\n```python\nwith ul() as bullets:\n    li(\"foo\")\n    li(\"bar\")\n\nprint(bullets)\n# \u003cul\u003e\u003cli\u003efoo\u003c/li\u003e\u003cli\u003ebar\u003c/li\u003e\u003c/ul\u003e\n```\n\n- pretty print\n\n```python\nprint(bullets.prettify())\n# \u003cul\u003e\n#     \u003cli\u003efoo\u003c/li\u003e\n#     \u003cli\u003ebar\u003c/li\u003e\n# \u003c/ul\u003e\n```\n\n- use trailing underscore to work around python keyword and built-in functions\n- attributes:\n    - `class_` -\u003e `class`\n    - `for_` -\u003e `for`\n- elements:\n    - `del_` -\u003e `del`\n    - `input_` -\u003e `input`\n    - `map_` -\u003e `map`\n    - `object_` -\u003e `object`\n\n```python\nprint(label(\"foo\", for_=\"bar\"))\n# \u003clabel for=\"bar\"\u003efoo\u003c/label\u003e\n\nprint(input_(None, class_=\"foo\", name=\"bar\", type=\"checkbox\", value=\"baz\"))\n# \u003cinput name=\"bar\" type=\"checkbox\" value=\"baz\"/\u003e\n```\n\n- position args -\u003e value-less attribute.\n    - boolean attribute: eg. `checked`, `disabled`, `selected`\n    - assign tailwind classes with [UnoCSS] attributify mode\n\n```python\nprint(div(\"foo\", \"clear-both\", \"m-2\", \"rounded\", id=\"baz\"))\n# \u003cdiv clear-both m-2 rounded id=\"baz\"\u003efoo\u003c/div\u003e\n```\n\n- keyword argument with value None is ignored\n\n```python\ntag = div(None, \"m-2\", \"rounded\", id=\"baz\", style=None) \nprint(tag)  \n# \u003cdiv m-2 rounded id=\"baz\" /\u003e\n```\n\n- append content and attributes to existing tag\n\n```python\ntag = div()\ntag.affix(p(\"bar\"), \"m-2\", \"rounded\", id=\"baz\") \nprint(tag)  \n# \u003cdiv m-2 rounded id=\"baz\"\u003e\u003cp\u003ebar\u003c/p\u003e\u003c/div\u003e\n```\n\n- create custom element\n- signature:\n    - `Tag(name: str, content = None, *args, **kwargs) -\u003e str`\n\n```python\nmy_tag = Tag(\"MyTag\", \"foo\", \"bar\", \"corge\", id=\"baz\", class_=\"qux\")\nprint(my_tag)  \n# \u003cMyTag bar corge id=\"baz\" class=\"qux\"\u003efoo\u003c/MyTag\u003e\n```\n\n- more examples could be found in [tests] package\n\n## Limitations\n\n- `prettify()` method doesn't support attribute without value\n    - use kwargs instead of positional args if prettifying is needed\n    - eg. `selected` -\u003e `selected=\"\"`\n\n## Need Help?\n\n- [github issue]\n- [x.com posts]\n- [contact the author]\n\n[black-badge]: https://img.shields.io/badge/code%20style-black-000000.svg\n[black-url]: https://github.com/psf/black\n[ci-badge]: https://github.com/hoishing/ptag/actions/workflows/ci.yml/badge.svg\n[ci-url]: https://github.com/hoishing/ptag/actions/workflows/ci.yml\n[contact the author]: https://hoishing.github.io\n[github issue]: https://github.com/hoishing/ptag/issues\n[MIT-badge]: https://img.shields.io/github/license/hoishing/ptag\n[MIT-url]: https://opensource.org/licenses/MIT\n[pypi-badge]: https://img.shields.io/pypi/v/ptag\n[pypi-url]: https://pypi.org/project/ptag/\n[tests]: https://github.com/hoishing/ptag/tree/main/tests\n[UnoCSS]: https://github.com/unocss/unocss\n[x.com posts]: https://x.com/hoishing\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhoishing%2Fptag","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhoishing%2Fptag","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhoishing%2Fptag/lists"}