{"id":16545581,"url":"https://github.com/byteface/domonic","last_synced_at":"2025-05-16T05:05:34.811Z","repository":{"id":39658345,"uuid":"272436172","full_name":"byteface/domonic","owner":"byteface","description":"Create HTML with python 3 using a standard DOM API. Includes a python port of JavaScript for interoperability and tons of other cool features. A fast prototyping library.","archived":false,"fork":false,"pushed_at":"2025-04-11T22:07:46.000Z","size":49734,"stargazers_count":137,"open_issues_count":24,"forks_count":13,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-05-12T04:52:28.814Z","etag":null,"topics":["dom","dom-api","dom-manipulation","hacktoberfest","hacktoberfest2021","html","javascript","opensource","prototype","python","python3","terminal"],"latest_commit_sha":null,"homepage":"https://domonic.readthedocs.io/","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/byteface.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.txt","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,"zenodo":null}},"created_at":"2020-06-15T12:43:29.000Z","updated_at":"2025-04-13T17:42:14.000Z","dependencies_parsed_at":"2024-06-19T00:18:59.685Z","dependency_job_id":"ed02e540-c02e-4050-9a90-e5d55ad61f4d","html_url":"https://github.com/byteface/domonic","commit_stats":{"total_commits":429,"total_committers":14,"mean_commits":"30.642857142857142","dds":"0.13286713286713292","last_synced_commit":"04a0320a1da16c8093c4017eebcf4a4ace3bd957"},"previous_names":[],"tags_count":102,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/byteface%2Fdomonic","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/byteface%2Fdomonic/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/byteface%2Fdomonic/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/byteface%2Fdomonic/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/byteface","download_url":"https://codeload.github.com/byteface/domonic/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254471061,"owners_count":22076585,"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":["dom","dom-api","dom-manipulation","hacktoberfest","hacktoberfest2021","html","javascript","opensource","prototype","python","python3","terminal"],"created_at":"2024-10-11T19:07:04.778Z","updated_at":"2025-05-16T05:05:34.758Z","avatar_url":"https://github.com/byteface.png","language":"Python","readme":"\u003ch1 align=\"center\"\u003e\n    \u003cbr\u003e𖤐 domonic 𖤐\u003cbr\u003e\n\u003c/h1\u003e\n\n[![PyPI version](https://badge.fury.io/py/domonic.svg)](https://badge.fury.io/py/domonic.svg)\n[![Downloads](https://pepy.tech/badge/domonic)](https://pepy.tech/project/domonic)\n[![Python version](https://img.shields.io/pypi/pyversions/domonic.svg?style=flat)](https://img.shields.io/pypi/pyversions/domonic.svg?style=flat)\n[![Python package](https://github.com/byteface/domonic/actions/workflows/python-package.yml/badge.svg?branch=master)](https://github.com/byteface/domonic/actions/workflows/python-package.yml)\n[![readthedocs](https://readthedocs.org/projects/domonic/badge/?version=latest)](https://domonic.readthedocs.io)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![byteface github](https://img.shields.io/badge/GitHub-byteface-181717.svg?style=flat\u0026logo=github)](https://github.com/byteface)\n\n#### A DOM for making HTML with python 3! (and more)\n\n### Install\n\n```bash\npython3 -m pip install domonic\n# python3 -m pip install domonic --upgrade \n```\n\n## Creating HTML with Python 3\n\n```python\nfrom domonic.html import *\nprint(html(body(h1('Hello, World!'))))\n# \u003chtml\u003e\u003cbody\u003e\u003ch1\u003eHello, World!\u003c/h1\u003e\u003c/body\u003e\u003c/html\u003e\n```\n\nor to pretty format and insert the doctype, use an f-string:\n\n```python\nmydom = html(body(h1('Hello, World!'), a(\"somelink\", _href=\"somepage.html\")))\nprint(f\"{mydom}\")\n```\n\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n\t\u003cbody\u003e\n\t\t\u003ch1\u003eHello, World!\u003c/h1\u003e\n\t\t\u003ca href=\"somepage.html\"\u003esomelink\u003c/a\u003e\n\t\u003c/body\u003e\n\u003c/html\u003e\n```\n\n### parsing html\n\nBasic useage...\n\n```bash\nfrom domonic import domonic\nmydom = domonic.parseString('\u003csomehtml...')\n```\n\nTo quickly parse a webapge try the window module...\n\n```bash\nfrom domonic.window import window\nwindow.location = \"http://www.google.com\"\nprint(window.document.title)\n```\n\nAlso try the xpath or css selectors on command line...\n\n```bash\ndomonic -x https://google.com '//a' | uniq | sort\n```\n\n### More\n\n- [html](https://domonic.readthedocs.io/_modules/domonic/html.html) : Generate html with python 3 😎\n- [dom](https://domonic.readthedocs.io/_modules/domonic/dom.html) : DOM API in python 3 😲\n- [javascript](https://domonic.readthedocs.io/_modules/domonic/javascript.html) : js API in python 3 😳 + ([dQuery](https://domonic.readthedocs.io/packages/dQuery.html), [d3](https://domonic.readthedocs.io/packages/d3.html))\n- JSON : utils for loading / decorating / transforming\n- SVG || mathml || aframe || x3d tags - generators for popular tags\n- terminal || cmd : call terminal commands with python3 😱\n\nSee the [docs/code](https://domonic.readthedocs.io/) for more features...\n\nor examples in the [repo...](https://github.com/byteface/domonic/tree/master/examples)\n\n\n### Namespace\n\nUse the tags packaage if you want a namespace. i.e.\n\n```python\nimport domonic.tags\nprint(domonic.tags.h1)\n# or\nimport domonic.tags as tags\nstr(tags.div)\n# or \nimport domonic.tags as html\nprint(html.span)\n```\n\nor just import what you need...\n\n```python\nfrom domonic import div, span, input as myinput, html as root\n```\n\n### html attributes\n\nprepend attributes with an underscore ( avoids clashing with python keywords )\n\n```python\ntest = label(_class='classname', _for=\"someinput\")\nprint(test)\n```\n\n```html\n\u003clabel class=\"classname\" for=\"someinput\"\u003e\u003c/label\u003e\n```\n\n### rendering DOM objects\n\ndomonic is a pure python dom whos tree is composed of objects. i.e\n\n```python\ndiv()\n# \u003cdomonic.html.div object at 0x106b0e6b0\u003e\n```\n\ncast str() on any element to render it without formatting.\n\n```python\nel = str(div())\nprint(el)\n# \u003cdiv\u003e\u003c/div\u003e\n```\n\nThere's also a render method that takes 2 parameters, some domonic and an optional output file.\n\n```python\npage = div(span('Hello World'))\nrender(f\"{page}\", 'index.html')  # notice use of f-string to pretty print the html\n```\n\nThere's a few new rendering options. See DOMConfig.\n\n```python\nfrom domonic.dom import DOMConfig\nprint(DOMConfig.GLOBAL_AUTOESCAPE)  # Default False\nprint(DOMConfig.RENDER_OPTIONAL_CLOSING_TAGS)  # Default True\nprint(DOMConfig.RENDER_OPTIONAL_CLOSING_SLASH)  # Defaults True\nprint(DOMConfig.SPACE_BEFORE_OPTIONAL_CLOSING_SLASH)  # Default False\n```\n\n## DOM\n\nDOM manipulation with python.\n\n### createElement\n\nto create your own elements use the DOM API\n\n```python\nfrom domonic.dom import *\n\nsite = html()\nel = document.createElement('myelement')\nsite.appendChild(el)\nprint(site)\n# \u003chtml\u003e\u003cmyelement\u003e\u003c/myelement\u003e\u003c/html\u003e\n\n```\n\nThere's an evolving DOM API. To learn more about the webAPI [click here](https://developer.mozilla.org/en-US/docs/Web/API).\n\nAnd check the [code/docs](https://domonic.readthedocs.io/) to see what's currently been implemented.\n\n```python\nmysite.querySelectorAll('button') \nmysite.querySelectorAll(\"a[rel=nofollow]\")\nmysite.querySelectorAll(\"a[href='#services']\")\nmysite.querySelectorAll(\"a[href$='technology']\")\nmysite.querySelectorAll('.fa-twitter')\n\nsomelinks = mysite.querySelectorAll(\"a[href*='twitter']\")\nfor l in somelinks:\n    print(l.href)\n```\n\nTo use the DOM either reference your root 'html' node or import the dom modules global 'document'\n\n```python\n\n# access the document via the html tag\nmydom = html()\n# mydom.getElementbyID...\n\n# or by importing the document global\nfrom domonic.dom import document\n# document.createElement...\nprint(document)\n```\n\n### javascript\n\nThere is a javascript package that mimics the js API:\n\n```python\nfrom domonic.javascript import Math\nprint(Math.random())\n\nfrom domonic.javascript import Array\nmyArr=Array(1,2,3)\nprint(myArr.splice(1))\n# [2, 3]\n\nfrom domonic.javascript import URL\nurl = URL('https://somesite.com/blog/article-one#some-hash')\nprint(url.protocol)  # https\nprint(url.host)  # somesite.com\nprint(url.pathname)  # /blog/article-one\nprint(url.hash)  # #some-hash\n\n# Use Global class to import all the js methods from the global namespace i.e\n# from domonic.javascript import Global\n# Global.decodeURIComponent(...\n# Global.encodeComponent(...\n# Global.setInterval(...\n\n# from domonic.javascript import Date, String, Number\n# etc..\n```\n\nUse setInterval and clearInterval with params\n\n```python\nfrom domonic.javascript import setInterval, clearInterval\n\nx=0\n\ndef hi(inc):\n    global x\n    x = x+inc\n    print(x)\n\ntest = setInterval(hi, 1000, 2)\nimport time\ntime.sleep(5)\nclearInterval(test)\nprint(f\"Final value of x:{x}\")\n```\n\nOr for a single delayed function call use setTimeout, clearTimeout\n\n```python\nfrom domonic.javascript import setTimeout, clearTimeout\ntimeoutID = setTimeout(hi, 1000)\n```\n\nYou can call ```()``` on a stringvar to transform it into a Node\n\n```python\nfrom domonic.javascript import String\n\ntest = String(\"Hi there!\")\ntest('div', _style=\"font-color:red;\")\nstr(test('div', _style=\"font-color:red;\"))\n# \u003cdiv style=\"font-color:red;\"\u003eHi there!\u003c/div\u003e\n```\n\na-tags inherit URL:\n\n```python\nfrom domonic.html import *\n\natag = a(_href=\"https://somesite.com:8000/blog/article-one#some-hash\")\nprint('href:', atag.href)\n# href: https://somesite.com:8000/blog/article-one#some-hash\nprint('protocol:', atag.protocol)\n# protocol: https:\nprint('port:', atag.port)\n# port: 8000\n\natag.protocol = \"http\"\natag.port = 8983\nprint(atag)\n# \u003ca href=\"http://somesite.com:8983/blog/article-one#some-hash\"\u003e\n```\n\nFor writing and using regular javascript, load from a src...\n\n```python\nscript(_src=\"/docs/5.0/dist/js/bootstrap.bundle.min.js\", _integrity=\"sha384-1234\", _crossorigin=\"anonymous\"),\n# \u003cscript src=\"/docs/5.0/dist/js/bootstrap.bundle.min.js\" integrity=\"sha384-1234\" crossorigin=\"anonymous\"\u003e\u003c/script\u003e\n```\n\nor do inline js by opening triple quotes...\n\n```python\nscript(\"\"\"\nlet itbe = \"\"\n\"\"\"),\n```\n\n### Styling\n\nStyling is supported. Styles get passed to the style tag on render...\n\n```python\nmytag = div(\"hi\", _id=\"test\")\nmytag.style.backgroundColor = \"black\"\nmytag.style.fontSize = \"12px\"\nprint(mytag)\n# \u003cdiv id=\"test\" style=\"background-color:black;font-size:12px;\"\u003ehi\u003c/div\u003e\n```\n\nTo use css use a link tag as you usually would...\n\n```python\nlink(_href=\"styles.css\", _rel=\"stylesheet\"),\n```\n\nor use triple quotes to open style tag...\n\n```python\nstyle(\"\"\"\n.placeholder-img {\n    -webkit-user-select: none;\n    -moz-user-select: none;\n    -ms-user-select: none;\n    user-select: none;\n}\n\"\"\"),\n```\n\n### decorators\n\nuse decorators to wrap elements around function results\n\n```python\nfrom domonic.decorators import el\n\n@el(html, True)\n@el(body)\n@el(div)\ndef test():\n    return 'hi!'\n\nprint(test())\n# \u003chtml\u003e\u003cbody\u003e\u003cdiv\u003ehi!\u003c/div\u003e\u003c/body\u003e\u003c/html\u003e\n\n# returns pyml objects so call str to render\nassert str(test()) == '\u003chtml\u003e\u003cbody\u003e\u003cdiv\u003ehi!\u003c/div\u003e\u003c/body\u003e\u003c/html\u003e'\n```\n\nIt returns the tag object by default. You can pass True as a second param to the decorator to return a rendered string instead. Also accepts strings as first param i.e. custom tags.\n\n### data-tags\n\npython doesn't allow hyphens in parameter names. so use variable keyword argument syntax for custom data-tags\n\n```python\ndiv(\"test\", **{\"_data-test\":\"test\"} )\n# \u003cdiv data-test=\"test\"\u003etest\u003c/div\u003e\n```\n\nor for example a colon...\n\n```python\nt = div( **{\"_:test\":\"something\"} )\nstr(t)\n# \u003cdiv :test=\"something\"\u003e\u003c/div\u003e\n```\n\n### JSON (utils)\n\ndecorate any function that returns python objects to return json instead\n\n```python\nfrom domonic.decorators import as_json\nimport domonic.JSON as JSON\n\n@as_json\ndef somefunc():\n    myObj = {\"hi\":[1,2,3]}\n    return myObj\n\nprint( somefunc() )\n# {\"hi\":[1,2,3]}\nprint( JSON.is_json(somefunc()) )\n# True\n```\n\nconvert json arrays into html tables...\n\n```python\nimport domonic.JSON as JSON\n\n# i.e. containting flat json array of dicts... [{\"id\":\"01\",\"name\": \"some item\"},{\"id\":\"02\",\"name\": \"some other item\"}]\n\njson_data = JSON.parse_file('somefile.json')\nmytable = JSON.tablify(json_data)\nprint(mytable)\n```\n\nconvert json arrays into csv files...\n\n```python\nimport domonic.JSON as JSON\n\njson_data = JSON.parse_file('somefile.json')\nJSON.csvify(json_data, 'data.csv')\n```\n\nconvert csv files to json...\n\n```python\nimport domonic.JSON as JSON\n\njson_data =JSON.csv2json(\"data.csv\")\nprint(json_data)\n```\n\nmore to come...\n\n### SVG\n\nAll tags extend 'Element'. So will have DOM and magic methods available to them. See the [docs](https://domonic.readthedocs.io/).\n\n```python\ncirc = svg(\n    circle(_cx=\"50\", _cy=\"50\", _r=\"40\", _stroke=\"green\", **{\"_stroke-width\": \"4\"}, _fill=\"yellow\"),\n    _width=\"100\", _height=\"100\",\n)\nmysvg = svg()\nmysvg.appendChild(circ / 10)\nprint(mysvg)\n```\n\n### Tweening\n\nTween values with the tween library:\n\n```python\nfrom domonic.lerpy.easing import *\nfrom domonic.lerpy.tween import *\n\nsomeObj = {'x':0,'y':0,'z':0}\ntwn = Tween( someObj, { 'x':10, 'y':5, 'z':3 }, 6, Linear.easeIn )\ntwn.start()\n```\n\n### aframe / x3d\n\n3d tags can be used if you import the js\n\n```python\nfrom domonic.html import *\nfrom domonic.xml.aframe import *\nfrom domonic.CDN import *\n\n_scene = scene(\n      box(_position=\"-1 0.5 -3\", _rotation=\"0 45 0\", _color=\"#4CC3D9\"),\n      sphere(_position=\"0 1.25 -5\", _radius=\"1.25\", _color=\"#EF2D5E\"),\n      cylinder(_position=\"1 0.75 -3\", _radius=\"0.5\", _height=\"1.5\", _color=\"#FFC65D\"),\n      plane(_position=\"0 0 -4\", _rotation=\"-90 0 0\", _width=\"4\", _height=\"4\", _color=\"#7BC8A4\"),\n      sky(_color=\"#ECECEC\")\n    )\n\n_webpage = html(head(),body(\n    script(_src=CDN_JS.AFRAME_1_2), # \u003c NOTICE you need to import aframe to use it\n    str(_scene)\n    )\n)\n\nrender( _webpage, 'hello.html' )\n```\n\n### dQuery (NEW)\n\ndQuery uses the º symbol (alt+0).\n\n```python\nfrom domonic.html import *\nfrom domonic.dQuery import º\n\nd = html(head(body(li(_class='things'), div(_id=\"test\"))))\n\nprint( º('#test') )\n# \u003cdiv id=\"test\"\u003e\nprint( º('.things') )\n# \u003cli class=\"things\"\u003e\nmydiv = º('\u003cdiv class=\"test2\"\u003e\u003c/div\u003e')\n# \u003cdomonic.dQuery.o object at 0x107d5c9a0\u003e\n\nb = º('#test').append(mydiv)\nprint(b)\n# \u003cdiv id=\"test\"\u003e\u003cdiv class=\"test2\"\u003e\u003c/div\u003e\u003c/div\u003e\n```\n\nOnly recently started so check to see what's implemented.\n\n### terminal\n\nThere is a command line package that can call bash/unix/posix and other apps on the command line:\n\nThis package only works on nix systems as it effectively just passes stuff off to subprocess.\n\n```python\nfrom domonic.terminal import *\n\nprint(ls())\nprint(ls(\"-al\"))\nprint(ls(\"../\"))\nprint(pwd())\nprint(mkdir('somedir'))\nprint(touch('somefile'))\nprint(git('status'))\n\nfor file in ls( \"-al\" ):\n    print(\"Line : \", file)\n\nfor f in ls():\n    try:\n        print(f)\n        print(cat(f))\n    except Exception as e:\n        pass\n\nfor i, l in enumerate(cat('LICENSE.txt')):\n    print(i,l)\n\nprint(man(\"ls\"))\nprint(echo('test'))\nprint(df())\nprint(du())\n\nfor thing in du():\n    print(thing)\n\nprint(find('.'))\n# print(ping('eventual.technology'))# \u003c TODO - need to strean output\nprint(cowsay('moo'))\n# print(wget('eventual.technology'))\nprint(date())\nprint(cal())\n```\n\nor just run arbitrary commands...\n\n```python\nfrom domonic.terminal import command\ncommand.run(\"echo hi\")\n```\n\nTake a look at the code in 'terminal.py' to see all the commands as there's loads. (Disclaimer: not all tested.)\n\nWindows users can use now use cmd.\n\n```python\nfrom domonic.cmd import *\nprint(dir())\nprint(dir(\"..\\\\\")) \n```\n\n### DOCS\n\n[https://domonic.readthedocs.io/](https://domonic.readthedocs.io/)\n\n### CLI\n\nUse the command line interface to help you out.\n\nTo view the online the docs:\n\n```python\ndomonic -h\n```\n\nTo see the version:\n\n```bash\ndomonic -v\n```\n\nTo quickly create a domonic project for prototyping:\n\n```bash\ndomonic -p myproject\n```\n\nTo evaluate some domonic pyml:\n\n```bash\ndomonic -e 'html(head(),body(div()))'\n```\n\nTo use xpath on a website from the command line:\n\n```bash\ndomonic -x https://google.com '//a'\n```\n\nTo use css selectors on a website from the command line:\n\n```bash\ndomonic -q https://google.com 'a'\n```\n\n### EXAMPLE PROJECTS\n\n[Blueberry](https://github.com/byteface/Blueberry/) : A browser based file OS. Working example of how components can work.\n\n[ezcron](https://github.com/byteface/ezcron/) : A cron viewer\n\n[bombdisposer](https://github.com/byteface/bombdisposer/) : A basic game\n\n[htmlx](https://github.com/byteface/htmlx/tree/master/htmlx) : A low dependency lightweight (DOM only) version of domonic\n\nCheckout [the docs](https://domonic.readthedocs.io/) for more examples i.e. generating sitemaps or using domonic with server frameworks like flask, django, sanic, fastapi and others.\n\nThere's also several useage examples in the repo so pull and have a look.\n\n### Join-In\n\nFeel free to contribute if you find it useful. (I'd be grateful for help on all fronts)\n\nEmail me, message me directly if you like or create a discussion on here. Or join the [discord](https://discord.gg/a9pSZv4V5f).\n\nIf there are any methods you want that are missing or not complete yet or you think you can help make it better just update the code and send a pull request. I'll merge and releaese asap.\n\nIn the repo there's a requirements-dev.txt which is mostly the libs used in the examples.\n\nrequirements.txt are the libs used for packaging just the lib.\n\nSee also the CONTRIBUTING.md\n\n### running examples\n\n```bash\n. venv/bin/activate\npip install -r requirements-dev.txt\ncd examples\npython lifecalendar.py\n```\n\n### run tests\n\nThere are tests used during dev. They are useful as code examples and to see what still needs doing.\n\nSee Makefile to run all tests:\n\n```bash\nmake test  # default tests ubuntu. so will fail on window when terminal test runs. comment out locally if that's the case\n```\n\nor to test a single function:\n\n```bash\npython -m unittest tests.test_javascript.TestCase.test_javascript_array\npython -m unittest tests.test_dQuery.TestCase.test_addClass\npython -m unittest tests.test_geom.TestCase.test_vec2\npython3 -m unittest tests.test_cmd.TestCase.test_cmd_dir  # only windows\n```\n\nor to test a whole module\n\n```bash\npython -m unittest tests.test_html\npython -m unittest tests.test_CDN\n```\n\nto see coverage\n\n```bash\ncoverage run -m unittest discover tests/\ncoverage report\n```\n\nor...\n\n```bash\npip install pytest\npytest tests\n```\n\n\n### Disclaimer\n\nThere's several more widely supported libraries doing HTML generation, DOM reading/manipulation, terminal wrappers etc. Maybe use one of those for production due to strictness and support.\n\nThis is more of a fast prototyping library.\n","funding_links":[],"categories":["Libraries"],"sub_categories":["General HTML Generation"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbyteface%2Fdomonic","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbyteface%2Fdomonic","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbyteface%2Fdomonic/lists"}