html¶
with domonic you can create beautiful, clean <html> straight out of the box.
mydom = html(body(h1('Hello, World!')))
print(f"{mydom}")
<!DOCTYPE html>
<html>
<body>
<h1>Hello, World!</h1>
</body>
</html>
rendering¶
you can cast str() on any element to render it.
el_string = str(div())
print(el_string)
there’s also a render method that takes 2 parameters, some pyml and an optional output file.
from domonic.html import *
page = div(span('Hello World'))
render(page, 'index.html')
templating¶
from domonic.html import *
output = render(
html(
head(
style(),
script(),
),
body(
div("hello world"),
a("this is a link", _href="http://www.somesite.com", _style="font-size:10px;"),
ol(''.join([f'{li()}' for thing in range(5)])),
h1("test", _class="test"),
)
)
)
<html><head><style></style><script></script></head><body><div>hello world</div><a href="http://www.somesite.com" style="font-size:10px;">this is a link</a><ol><li></li><li></li><li></li><li></li><li></li></ol><h1 class="test">test</h1></body></html>
Take a look in tests/test_html.py at the bootstrap5 alpha examples. All tests passed on several templates.
usage¶
print(html(body(h1('Hello, World!'))))
<html><body><h1>Hello, World!</h1></body></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>
lists¶
just do list comprehension and join it to strip the square brackets
ul(''.join([f'{li()}' for thing in range(5)])),
<ul><li></li><li></li><li></li><li></li></ul>
Create Elements¶
to create your own custom elements you can use create_element
from domonic.html import *
create_element('custom_el', div('some content'), _id="test")
or you could use the DOM API…
from domonic.dom import *
from domonic.html import *
site = html()
el = document.createElement('myelement')
site.appendChild(el)
print(site)
For more info about the DOM API navigate to that section…
Decorators¶
You can use decorators to wrap elements around function results
from domonic.decorators import el
@el(html)
@el(body)
@el(div)
def test():
return 'hi!'
print(test())
# <html><body><div>hi!</div></body></html>
Magic methods¶
Multiply
You can quickly clone nodes with a multiplier which will return a list…
from domonic.html import *
mydivs = div()*100
but you will have to render them yourself by interating and calling string…
print(''.join([str(c) for c in mydivs]))
Divide
A divisor also creates more but will instead call render and give a list of strings…
from domonic.html import *
print(div()/100)
but this means they are now rendered and can’t be edited.
Although you could convert them back by calling parser then domonify. i.e.
mylist = li()/10
myobj = domonic.domonify(domonic.parse(mylist))
print(myobj)
OR
If other is anything, it is returned. Otherwise it returns self
from domonic.html import *
print(div() | False)
print(div() | True)
Another way is to use ternary i.e.
mything = div() if True else span(class-'warning')
In place add/minus
You can add to or remove from the children of a Node with the in-place operators…
myorderedlist = ol()
myorderedlist += str(li() / 10)
print(myorderedlist)
This also works for text nodes but be aware they will be irreversibly flattened if you render…
a1 = button()
a1 += "hi"
a1 += "how"
a1 += ["are", "you", "today"]
print(a1)
a1 -= "hi"
print(a1)
Pass a dictionary to the right shift operator to add/update an attribute… (don’t forget underscore or it will error)
a1 = img()
a1 >> {'_src': "http://www.someurl.com"}
print(a1)
Access an elements children as if it were a list…
mylist = ul(li(1), li(2), li(3))
print(mylist[1])
unpack children…
mylist = ul(li(), li(), li())
print(*mylist)
a1, b1, c1 = ul(li(1), li(2), li(3))
print(a1)
a1, b1, c1, d1, e1 = button() * 5
print(a1, b1, c1, d1, e1)
f-strings¶
To pretty print a domonic dom you can use a f-string…
print(f"{mydom}")
<!DOCTYPE html>
<html>
<body>
<h1>Hello, World!</h1>
</body>
</html>
which basically calls the format dunder on the tag. (if look at the code)
This is useful as it means use different ways to get output from domonic.
print(f"{mydom}")
print(f"{mydom!s}")
print(f"{mydom!r}")
print(f"{mydom!a}")
print(str(mydom))
print(mydom.__format__(''))
If the built in formatter is not up to your needs. You can also use other libraries that leverage beautifulsoup i.e.
output = render(html(body(h1('Hello, World!'))))
from html5print import HTMLBeautifier
print(HTMLBeautifier.beautify(output, 4))
For outputting pyml to a string there is a method in production called __pyml__() which may become repr. (but i’d been saving repr for logging)
You can also use this vscode plugin on .pyml and it does a nice job. (inpsiration for the ‘dentage’ method)
https://marketplace.visualstudio.com/items?itemName=mgesbert.indent-nested-dictionary
Quotes around attributes¶
The quotes around attributes can be finely controlled using the DOMConfig.ATTRIBUTE_QUOTES flag
By default everything is double quoted on render.
However a flag can be set to None which will not render quotes if the passed value is not a string.
Alternatively it can be set to use a single quotation mark or even False to use None at all and control it yourself.
Examples provided below.
>>> from domonic.html import *
>>> from domonic.dom import DOMConfig
>>> print(body(test="123"))
# <body test="123"></body>
>>> print(body(test=123))
# <body test="123"></body>
>>> DOMConfig.ATTRIBUTE_QUOTES = None
>>> print(body(test=123))
# <body test=123></body>
>>> print(body(test="123"))
# <body test="123"></body>
>>> DOMConfig.ATTRIBUTE_QUOTES = "'"
>>> print(body(test="123"))
# <body test='123'></body>
>>> DOMConfig.ATTRIBUTE_QUOTES = True
>>> print(body(test="123"))
# <body test="123"></body>
>>> print(body(test=123))
# <body test="123"></body>
>>> DOMConfig.ATTRIBUTE_QUOTES = False
>>> print(body(test="123"))
# <body test=123></body>
>>> print(body(test="TEXT"))
# <body test=TEXT></body>
loading .pyml templates¶
div("Hello World")
#<div>Hello tabs</div>
‘loads’ imports a pyml file and turns it into a program
this example loads a template and passing params for rendering
from domonic import loads
from domonic.html import *
# create some vars. you will see these referenced in the template file
brand = "MyBrand"
links = ['one', 'two', 'three']
# load a template and pass it some data
webpage = domonic.loads('templates/webpage.com.pyml', links=links, brand=brand)
render(webpage, 'webpage.html')
# ‘load’ is different to ‘loads’, it takes html strings and converts to a program
from domonic.dQuery import º
webpage = domonic.load('<html><head></head><body id="test"></body></html>')
º(webpage)
º('#test').append(div("Hello World"))
render(webpage, 'webpage2.html')
warning loads also is very basic and can only convert simple html as the parser is still in development
Notes on templating¶
while you can create a div with content like :
div("some content")
python doesn’t allow named params before unamed ones. So you can’t do this:
div(_class="container", p("Some content") )
or it will complain the params are in the wrong order. You have to instead put content before attributes:
div( p("Some content"), _class="container")
which is annoying when a div gets long.
You can get around this by using ‘html’ which is available on every Element:
div( _class="container" ).html("Some content")
This is NOT like jQuery html func that returns just the inner content. use innerHTML for that.
It is used specifically for rendering.
Common Errors¶
If a templates syntax is incorrect it will not work.
There’s a small learning curve in getting .pyml templates correct. Usually…
a missing comma between tags,
an underscore missing on an attribute or
params in the wrong order.
Use this reference when starting out to help when you get an error.
IndexError: list index out of range
# You most likely didn't put a underscore on an attribute.
SyntaxError: invalid syntax
# You are Missing a comma between attributes
SyntaxError: positional argument follows keyword argument
# You have to pass attributes LAST. and strings and objects first. *see notes on templating above*
TypeError: unsupported operand type(s) for ** or pow(): 'str' and 'dict'
# You are Missing a comma between attributes. before the **{}
parsing¶
https://github.com/byteface/domonic/issues/28
Basic useage…
An examples of using the parser…
import requests
import html5lib
from domonic.ext.html5lib_ import getTreeBuilder
r = requests.get("https://google.com")
parser = html5lib.HTMLParser(tree=getTreeBuilder())
page = parser.parse(r.content.decode("utf-8"))
# print the page with formatting
# print(f'{page}')
'''
links = page.getElementsByTagName('a')
for l in links:
try:
print(l.href)
except Exception as e:
# no href on this tag
pass
'''
# turn the downloaded site into .pyml ;)
print(page.__pyml__())
For a quick parse try the window module…
from domonic.window import *
window.location = "http://www.google.com"
print(window.document.title)
domonic.html¶
Generate HTML using python.
- exception domonic.html.TemplateError(error, message='TemplateError: ')[source]
- class domonic.html.a(*args, **kwargs)
- class domonic.html.abbr(*args, **kwargs)
- class domonic.html.address(*args, **kwargs)
- class domonic.html.applet(*args, **kwargs)
- class domonic.html.area(*args, **kwargs)
- class domonic.html.article(*args, **kwargs)
- class domonic.html.aside(*args, **kwargs)
- class domonic.html.audio(*args, autoplay: Optional[bool] = None, controls=None, loop=None, muted=None, preload=None, src=None, **kwargs)
- class domonic.html.b(*args, **kwargs)
- class domonic.html.base(*args, href=None, target=None, **kwargs)
- class domonic.html.basefont(*args, **kwargs)
- class domonic.html.bdi(*args, **kwargs)
- class domonic.html.bdo(*args, **kwargs)
- class domonic.html.blockquote(*args, **kwargs)
- class domonic.html.body(*args, aLink=None, background=None, bgColor=None, link=None, onload=None, onunload=None, text=None, vLink=None, **kwargs)
- class domonic.html.br(*args, **kwargs)
- class domonic.html.button(*args, disabled: Optional[bool] = None, form=None, formaction: Optional[str] = None, formenctype=None, formmethod=None, formnovalidate=None, formtarget=None, name=None, type=None, value=None, **kwargs)
- class domonic.html.canvas(*args, width: Optional[int] = None, height: Optional[int] = None, **kwargs)
- class domonic.html.caption(*args, **kwargs)
- class domonic.html.center(*args, **kwargs)
- class domonic.html.cite(*args, **kwargs)
- class domonic.html.closed_tag(*args, **kwargs)[source]
- class domonic.html.code(*args, **kwargs)
- class domonic.html.col(*args, **kwargs)
- class domonic.html.colgroup(*args, **kwargs)
- class domonic.html.command(*args, **kwargs)
- class domonic.html.comment(data)
- domonic.html.create_element(name='custom_tag', *args, **kwargs)[source]
A method for creating custom tags
tag name needs to be set due to custom tags with hyphens can’t be classnames. i.e. hypenated tags <some-custom-tag></some-custom-tag>
- class domonic.html.data(*args, **kwargs)
- class domonic.html.datalist(*args, **kwargs)
- class domonic.html.dd(*args, **kwargs)
- class domonic.html.details(*args, **kwargs)
- class domonic.html.dfn(*args, **kwargs)
- class domonic.html.dialog(*args, open=None, **kwargs)
- class domonic.html.div(*args, **kwargs)
- class domonic.html.dl(*args, **kwargs)
- class domonic.html.dt(*args, **kwargs)
- class domonic.html.em(*args, **kwargs)
- class domonic.html.embed(*args, **kwargs)
- class domonic.html.fieldset(*args, **kwargs)
- class domonic.html.figcaption(*args, **kwargs)
- class domonic.html.figure(*args, **kwargs)
- class domonic.html.font(*args, **kwargs)
- class domonic.html.footer(*args, **kwargs)
- class domonic.html.form(*args, **kwargs)[source]
- class domonic.html.h1(*args, **kwargs)
- class domonic.html.h2(*args, **kwargs)
- class domonic.html.h3(*args, **kwargs)
- class domonic.html.h4(*args, **kwargs)
- class domonic.html.h5(*args, **kwargs)
- class domonic.html.h6(*args, **kwargs)
- class domonic.html.head(*args, **kwargs)
- class domonic.html.header(*args, **kwargs)
- class domonic.html.hgroup(*args, **kwargs)
- class domonic.html.hr(*args, **kwargs)
- class domonic.html.html(*args, **kwargs)
- class domonic.html.i(*args, **kwargs)
- class domonic.html.iframe(*args, **kwargs)
- class domonic.html.img(*args, alt=None, src=None, crossorigin=None, height=None, ismap=None, longdesc=None, sizes=None, srcset=None, usemap=None, width=None, **kwargs)
- class domonic.html.input(*args, accept=None, alt=None, autocomplete=None, autofocus=None, checked=None, dirname=None, disabled=None, form=None, formaction=None, formenctype=None, formmethod=None, formnovalidate=None, formtarget=None, height=None, _list=None, _max=None, maxlength=None, _min=None, multiple=None, name=None, pattern=None, placeholder=None, readonly=None, required=None, size=None, src=None, step=None, type=None, value=None, width=None, **kwargs)
- class domonic.html.ins(*args, **kwargs)
- class domonic.html.isindex(*args, **kwargs)
- class domonic.html.kbd(*args, **kwargs)
- class domonic.html.keygen(*args, **kwargs)
- class domonic.html.label(*args, **kwargs)
- class domonic.html.legend(*args, **kwargs)
- class domonic.html.li(*args, **kwargs)
- class domonic.html.link(*args, **kwargs)
- class domonic.html.listing(*args, **kwargs)
- class domonic.html.main(*args, **kwargs)
- class domonic.html.mark(*args, **kwargs)
- class domonic.html.menu(*args, **kwargs)
- class domonic.html.menuitem(*args, **kwargs)
- class domonic.html.meta(*args, charset=None, content=None, http_equiv=None, name=None, **kwargs)
- class domonic.html.meter(*args, value=None, _min=None, _max=None, low=None, high=None, optimum=None, **kwargs)
- class domonic.html.nav(*args, **kwargs)
- class domonic.html.noscript(*args, **kwargs)
- class domonic.html.ol(*args, **kwargs)
- class domonic.html.optgroup(*args, **kwargs)
- class domonic.html.option(*args, disabled=None, label=None, selected=None, value=None, **kwargs)
- class domonic.html.output(*args, **kwargs)
- class domonic.html.p(*args, **kwargs)
- class domonic.html.param(*args, **kwargs)
- class domonic.html.picture(*args, **kwargs)
- class domonic.html.plaintext(*args, **kwargs)
- class domonic.html.portal(*args, **kwargs)
- class domonic.html.pre(*args, **kwargs)
- class domonic.html.progress(*args, **kwargs)
- class domonic.html.q(*args, **kwargs)
- domonic.html.render(inp, outp='', to=None)[source]
write the input to string or to a file.
- class domonic.html.rp(*args, **kwargs)
- class domonic.html.rt(*args, **kwargs)
- class domonic.html.ruby(*args, **kwargs)
- class domonic.html.s(*args, **kwargs)
- class domonic.html.samp(*args, **kwargs)
- class domonic.html.script(*args, **kwargs)
- class domonic.html.section(*args, **kwargs)
- class domonic.html.select(*args, autofocus: Optional[bool] = None, disabled: Optional[bool] = None, multiple: Optional[bool] = None, name: Optional[str] = None, required: Optional[bool] = None, size: Optional[int] = None, **kwargs)
- class domonic.html.small(*args, **kwargs)
- class domonic.html.source(*args, **kwargs)
- class domonic.html.span(*args, **kwargs)
- class domonic.html.strike(*args, **kwargs)
- class domonic.html.strong(*args, **kwargs)
- class domonic.html.style(*args, **kwargs)
- class domonic.html.sub(*args, **kwargs)
- class domonic.html.submit(*args, **kwargs)
- class domonic.html.summary(*args, **kwargs)
- class domonic.html.sup(*args, **kwargs)
- class domonic.html.table(*args, align: Optional[str] = None, bgcolor=None, border=None, cellpadding=None, cellspacing=None, frame=None, rules=None, summary=None, width=None, **kwargs)
- class domonic.html.tbody(*args, **kwargs)
- class domonic.html.td(*args, **kwargs)
- class domonic.html.template(*args, **kwargs)
- class domonic.html.textarea(*args, autofocus=None, cols=None, disabled=None, form=None, maxlength=None, name=None, placeholder=None, readonly=None, required=None, rows=None, wrap=None, **kwargs)
- class domonic.html.tfoot(*args, **kwargs)
- class domonic.html.th(*args, **kwargs)
- class domonic.html.thead(*args, **kwargs)
- class domonic.html.title(*args, **kwargs)
- class domonic.html.tr(*args, **kwargs)
- class domonic.html.track(*args, **kwargs)
- class domonic.html.u(*args, **kwargs)
- class domonic.html.ul(*args, **kwargs)
- class domonic.html.var(*args, **kwargs)
- class domonic.html.video(*args, autoplay=None, controls=None, height=None, loop=None, muted=None, poster=None, preload=None, src=None, width=None, **kwargs)
- class domonic.html.wbr(*args, **kwargs)
- class domonic.html.xmp(*args, **kwargs)