Domonic
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.
Install / Use
/learn @byteface/DomonicREADME
A pure Python DOM that goes way beyond minidom
- Python
3.10+ - HTML, SVG, DOM, events, web APIs, animation, and a JavaScript-like runtime
- Built for generating, parsing, traversing, and manipulating real document trees
Install
python3 -m pip install domonic
python3 -m pip install --upgrade domonic
For development:
python3 -m pip install -r requirements-dev.txt
Creating HTML with Python 3
from domonic.html import *
print(html(body(h1('Hello, World!'))))
# <html><body><h1>Hello, World!</h1></body></html>
to pretty format and insert the doctype, use an f-string:
mydom = html(body(h1('Hello, World!'), a("somelink", _href="somepage.html")))
print(f"{mydom}")
<!DOCTYPE html>
<html>
<body>
<h1>Hello, World!</h1>
<a href="somepage.html">somelink</a>
</body>
</html>
Parsing html
from domonic import domonic
mydom = domonic.parseString('<somehtml...')
or parse an entire webpage with the window module...
from domonic.window import window
window.location = "https://example.com"
print(window.document.title)
html5lib is bundled as the default parser as it's pure python. However see the Parsers section below as other parser backends are supported and are much faster.
xpath or css
Use xpath or css selectors on command line...
domonic -x https://google.com '//a' | uniq | sort
More
- html : Generate html with Python 3 😎
- dom : DOM API in Python 3 😲
- javascript : js API in Python 3 😳 + (dQuery, d3)
- JSON : utils for loading / decorating / transforming
- SVG || mathml || aframe || x3d tags - generators for popular tags
- terminal || cmd : call terminal commands with Python3 😱
See the docs/code for more features or examples in the repo
Namespace
Simply import what you need...
from domonic import div, span, input as myinput, html as root
or use the tags package if you want a namespace. i.e.
import domonic.tags
print(domonic.tags.h1)
# or
import domonic.tags as tags
str(tags.div)
# or
import domonic.tags as html
print(html.span)
HTML attributes
Prepend attributes with an underscore ( avoids clashing with Python keywords )
test = label(_class='classname', _for="someinput")
print(test)
<label class="classname" for="someinput"></label>
Rendering DOM objects
domonic is a pure Python DOM whose tree is composed of objects. i.e
div()
# <domonic.html.div object at 0x106b0e6b0>
cast str() on any element to render it without formatting.
el = str(div())
print(el)
# <div></div>
There's also a render method that takes 2 parameters, some domonic and an optional output file.
page = div(span('Hello World'))
render(f"{page}", 'index.html') # notice use of f-string to pretty print the html
For rendering options see DOMConfig.
from domonic.dom import DOMConfig
print(DOMConfig.GLOBAL_AUTOESCAPE) # Default False
print(DOMConfig.RENDER_OPTIONAL_CLOSING_TAGS) # Default True
print(DOMConfig.RENDER_OPTIONAL_CLOSING_SLASH) # Defaults True
print(DOMConfig.SPACE_BEFORE_OPTIONAL_CLOSING_SLASH) # Default False
DOM
DOM manipulation with Python, built with the actual platform in mind.
createElement
Create your own elements with the DOM API
from domonic.dom import *
site = html()
el = document.createElement('myelement')
site.appendChild(el)
print(site)
# <html><myelement></myelement></html>
mysite.querySelectorAll('button')
mysite.querySelectorAll("a[rel=nofollow]")
mysite.querySelectorAll("a[href='#services']")
mysite.querySelectorAll("a[href$='technology']")
mysite.querySelectorAll('.fa-twitter')
somelinks = mysite.querySelectorAll("a[href*='twitter']")
for l in somelinks:
print(l.href)
To use the DOM either reference your root 'html' node or import the dom modules global 'document'
# access the document via the html tag
mydom = html()
# mydom.getElementbyID...
# or by importing the document global
from domonic.dom import document
# document.createElement...
print(document)
The aim is to track the real platform as closely as possible :
Check the code/docs to see what's currently implemented.
Javascript
There is a Javascript package that mirrors a large, practical slice of the JS API:
from domonic.javascript import Math
print(Math.random())
from domonic.javascript import Array
myArr=Array(1,2,3)
print(myArr.splice(1))
# [2, 3]
from domonic.javascript import URL
url = URL('https://somesite.com/blog/article-one#some-hash')
print(url.protocol) # https
print(url.host) # somesite.com
print(url.pathname) # /blog/article-one
print(url.hash) # #some-hash
# Use Global class to import all the js methods from the global namespace i.e
# from domonic.javascript import Global
# Global.decodeURIComponent(...
# Global.encodeComponent(...
# Global.setInterval(...
# from domonic.javascript import Date, String, Number
# etc..
Use setInterval and clearInterval with params
from domonic.javascript import setInterval, clearInterval
x=0
def hi(inc):
global x
x = x+inc
print(x)
test = setInterval(hi, 1000, 2)
import time
time.sleep(5)
clearInterval(test)
print(f"Final value of x:{x}")
Or for a single delayed function call use setTimeout, clearTimeout
from domonic.javascript import setTimeout, clearTimeout
timeoutID = setTimeout(hi, 1000)
You can call () on a stringvar to transform it into a Node
from domonic.javascript import String
test = String("Hi there!")
test('div', _style="font-color:red;")
str(test('div', _style="font-color:red;"))
# <div style="font-color:red;">Hi there!</div>
a-tags inherit URL:
from domonic.html import *
atag = a(_href="https://somesite.com:8000/blog/article-one#some-hash")
print('href:', atag.href)
# href: https://somesite.com:8000/blog/article-one#some-hash
print('protocol:', atag.protocol)
# protocol: https:
print('port:', atag.port)
# port: 8000
atag.protocol = "http"
atag.port = 8983
print(atag)
# <a href="http://somesite.com:8983/blog/article-one#some-hash">
For writing and using regular Javascript, load from a src...
script(_src="/docs/5.0/dist/js/bootstrap.bundle.min.js", _integrity="sha384-1234", _crossorigin="anonymous"),
# <script src="/docs/5.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-1234" crossorigin="anonymous"></script>
or do inline js by opening triple quotes...
script("""
let itbe = ""
"""),
Styling
Styling is supported. Styles get passed to the style tag on render...
mytag = div("hi", _id="test")
mytag.style.backgroundColor = "black"
mytag.style.fontSize = "12px"
print(mytag)
# <div id="test" style="background-color:black;font-size:12px;">hi</div>
To use css use a link tag as you usually would...
link(_href="styles.css", _rel="stylesheet"),
or use triple quotes to open style tag...
style("""
.placeholder-img {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
"""),
Decorators
use decorators to wrap elements around function results
from domonic.decorators import el
@el(html, True)
@el(body)
@el(div)
def test():
return 'hi!'
print(test())
# <html><body><div>hi!</div></body></html>
# returns pyml objects so call str to render
assert str(test()) == '<html><body><div>hi!</div></body></html>'
It 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.
data-tags
Python doesn't allow hyphens in parameter names. so use variable keyword argument syntax for custom data-tags
div("test", **{"_data-test":"test"} )
# <div data-test="test">test</div>
or for example a colon...
t = div( **{"_:test":"something"} )
str(t)
# <div :test="something"></div>
JSON (utils)
Decorate any function that returns Python objects to return json instead
from domonic.decorators import as_json
import domonic.JSON as JSON
@as_json
def somefunc():
myObj = {"hi":[1,2,3]}
return myObj
print( somefunc() )
# {"hi":[1,2,3]}
print( JSON.is_json(somefunc()) )
# True
convert json arrays into html tables...
Related Skills
node-connect
346.8kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
claude-opus-4-5-migration
107.6kMigrate prompts and code from Claude Sonnet 4.0, Sonnet 4.5, or Opus 4.1 to Opus 4.5
frontend-design
107.6kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
model-usage
346.8kUse CodexBar CLI local cost usage to summarize per-model usage for Codex or Claude, including the current (most recent) model or a full model breakdown. Trigger when asked for model-level usage/cost data from codexbar, or when you need a scriptable per-model summary from codexbar cost JSON.
