"""
domonic.html
====================================
Generate HTML using python.
"""
from domonic.dom import Document # HTMLOptionsCollection,
from domonic.dom import (Comment, DocumentType, DOMConfig, Element,
HTMLAnchorElement, HTMLAreaElement, HTMLAudioElement,
HTMLBaseElement, HTMLBaseFontElement, HTMLBodyElement,
HTMLBRElement, HTMLButtonElement, HTMLCanvasElement,
HTMLContentElement, HTMLDataElement,
HTMLDataListElement, HTMLDialogElement,
HTMLDivElement, HTMLDListElement, HTMLDocument,
HTMLElement, HTMLEmbedElement, HTMLFieldSetElement,
HTMLFormControlsCollection, HTMLFormElement,
HTMLFrameSetElement, HTMLHeadElement,
HTMLHeadingElement, HTMLHRElement, HTMLIFrameElement,
HTMLImageElement, HTMLInputElement,
HTMLIsIndexElement, HTMLKeygenElement,
HTMLLabelElement, HTMLLegendElement, HTMLLIElement,
HTMLLinkElement, HTMLMapElement, HTMLMediaElement,
HTMLMetaElement, HTMLMeterElement, HTMLModElement,
HTMLObjectElement, HTMLOListElement,
HTMLOptGroupElement, HTMLOptionElement,
HTMLOutputElement, HTMLParagraphElement,
HTMLParamElement, HTMLPictureElement, HTMLPreElement,
HTMLProgressElement, HTMLQuoteElement,
HTMLScriptElement, HTMLSelectElement,
HTMLShadowElement, HTMLSourceElement, HTMLSpanElement,
HTMLStyleElement, HTMLTableCaptionElement,
HTMLTableCellElement, HTMLTableColElement,
HTMLTableDataCellElement, HTMLTableElement,
HTMLTableHeaderCellElement, HTMLTableRowElement,
HTMLTableSectionElement, HTMLTemplateElement,
HTMLTextAreaElement, HTMLTimeElement,
HTMLTitleElement, HTMLTrackElement, HTMLUListElement,
HTMLUnknownElement, HTMLVideoElement, Node, Text)
from domonic.webapi.url import URL
html_tags = [
"figcaption",
"blockquote",
"textarea",
"progress",
"optgroup",
"noscript",
"fieldset",
"datalist",
"colgroup",
"summary",
"section",
"details",
"command",
"caption",
"article",
"address",
"submit",
"strong",
"source",
"select",
"script",
"output",
"option",
"legend",
"keygen",
"iframe",
"hgroup",
"header",
"footer",
"figure",
"canvas",
"button",
"video",
"track",
"title",
"thead",
"tfoot",
"tbody",
"table",
"style",
"small",
"param",
"meter",
"label",
"input",
"audio",
"aside",
"applet",
"object",
"basefont",
"center",
"embed",
"isindex",
"listing",
"menuitem",
"plaintext",
"strike",
"template",
"picture",
"dialog",
"data",
"time",
"span",
"samp",
"ruby",
"meta",
"menu",
"mark",
"link",
"html",
"head",
"form",
"font",
"code",
"cite",
"body",
"base",
"area",
"abbr",
"main",
"dir",
"wbr",
"var",
"sup",
"sub",
"nav",
"map",
"kbd",
"ins",
"img",
"div",
"dfn",
"del",
"col",
"bdo",
"bdi",
"pre",
"xmp",
"ul",
"tr",
"th",
"td",
"rt",
"rp",
"ol",
"li",
"hr",
"h6",
"h5",
"h4",
"h3",
"h2",
"h1",
"em",
"dt",
"dl",
"dd",
"br",
"u",
"s",
"q",
"p",
"i",
"b",
"a",
]
# big, blink, bold, tt, var, frameset
html_attributes = [
"accept",
"accesskey",
"loading",
"action",
"align",
"alt",
"async",
"autocomplete",
"autofocus",
"autoplay",
"bgcolor",
"border",
"charset",
"checked",
"cite",
"class",
"color",
"cols",
"colspan",
"content",
"contenteditable",
"controls",
"coords",
"data",
"datetime",
"default",
"defer",
"dir",
"dirname",
"disabled",
"download",
"draggable",
"enctype",
"for",
"form",
"formaction",
"headers",
"height",
"hidden",
"high",
"href",
"hreflang",
"id",
"ismap",
"kind",
"label",
"lang",
"list",
"loop",
"low",
"max",
"maxlength",
"media",
"method",
"min",
"multiple",
"muted",
"name",
"novalidate",
"onabort",
"onafterprint",
"onbeforeprint",
"onbeforeunload",
"onblur",
"oncanplay",
"oncanplaythrough",
"onchange",
"onclick",
"oncontextmenu",
"oncopy",
"oncuechange",
"oncut",
"ondblclick",
"ondrag",
"ondragend",
"ondragenter",
"ondragleave",
"ondragover",
"ondragstart",
"ondrop",
"ondurationchange",
"onemptied",
"onended",
"onerror",
"onfocus",
"onhashchange",
"oninput",
"oninvalid",
"onkeydown",
"onkeypress",
"onkeyup",
"onload",
"onloadeddata",
"onloadedmetadata",
"onloadstart",
"onmousedown",
"onmousemove",
"onmouseout",
"onmouseover",
"onmouseup",
"onmousewheel",
"onoffline",
"ononline",
"onpagehide",
"onpageshow",
"onpaste",
"onpause",
"onplay",
"onplaying",
"onpopstate",
"onprogress",
"onratechange",
"onreset",
"onresize",
"onscroll",
"onsearch",
"onseeked",
"onseeking",
"onselect",
"onstalled",
"onstorage",
"onsubmit",
"onsuspend",
"ontimeupdate",
"ontoggle",
"onunload",
"onvolumechange",
"onwaiting",
"onwheel",
"open",
"optimum",
"pattern",
"placeholder",
"poster",
"preload",
"readonly",
"rel",
"required",
"reversed",
"rows",
"rowspan",
"sandbox",
"scope",
"selected",
"shape",
"size",
"sizes",
"span",
"spellcheck",
"src",
"srcdoc",
"srclang",
"srcset",
"start",
"step",
"style",
"tabindex",
"target",
"title",
"translate",
"type",
"usemap",
"value",
"width",
"wrap",
"property",
"integrity",
"crossorigin",
"nonce",
"autocapitalize",
"enterkeyhint",
"inputmode",
"is",
"itemid",
"itemprop",
"itemref",
"itemscope",
"itemtype",
"part",
"slot",
"spellcheck",
"alink",
"nowrap",
"vlink",
"vspace",
"language",
"clear",
"hspace",
"xmlns",
"about",
"allowtransparency",
"datatype",
"inlist",
"prefix",
"resource",
"rev",
"typeof",
"vocab", # rdfa
"playsinline",
"autopictureinpicture",
"buffered",
"controlslist",
"disableremoteplayback", # video
]
[docs]def render(inp, outp="", to=None): # doctype='html5')
"""write the input to string or to a file.
Args:
inp (obj): A domonic tag. For example div()
outp (str): An optional output filename
to (str): An optional output type. if 'pyml' is specified then pyml is returned instead of html.
Returns:
str: A HTML rendered string
"""
if to == "pyml":
if outp != "":
with open(outp, "w+") as f:
f.write(inp.__pyml__())
return inp.__pyml__()
# else:
if outp != "":
with open(outp, "w+") as f:
f.write(str(inp))
return str(inp)
[docs]class TemplateError(IndexError):
def __init__(self, error, message="TemplateError: "):
"""[raised when a template error occurs]
Args:
error ([type]): [the error]
message (str, optional): [description]. Defaults to "Templating error: ".
"""
self.error = error
self.hint = ""
print(self.error)
if str(self.error) == "list index out of range":
self.hint = "MISSING UNDERSCORE ON AN ATTRIBUTE"
self.message = message + self.hint
super().__init__(self.message)
tag = Node # legacy support?. TODO - remove in future? 0.0.9
[docs]class closed_tag(Node):
def __str__(self):
if DOMConfig.RENDER_OPTIONAL_CLOSING_SLASH:
if DOMConfig.SPACE_BEFORE_OPTIONAL_CLOSING_SLASH:
return f"<{self.name}{self.__attributes__} />"
else:
return f"<{self.name}{self.__attributes__}/>"
return f"<{self.name}{self.__attributes__}>"
html = type("html", (HTMLDocument,), {"name": "html"})
body = type("body", (HTMLBodyElement,), {"name": "body"})
head = type("head", (HTMLHeadElement,), {"name": "head"})
script = type("script", (HTMLScriptElement,), {"name": "script"})
style = type("style", (HTMLStyleElement,), {"name": "style"})
h1 = type("h1", (HTMLHeadingElement,), {"name": "h1"})
h2 = type("h2", (HTMLHeadingElement,), {"name": "h2"})
h3 = type("h3", (HTMLHeadingElement,), {"name": "h3"})
h4 = type("h4", (HTMLHeadingElement,), {"name": "h4"})
h5 = type("h5", (HTMLHeadingElement,), {"name": "h5"})
h6 = type("h6", (HTMLHeadingElement,), {"name": "h6"})
p = type("p", (HTMLParagraphElement,), {"name": "p"})
i = type("i", (Element,), {"name": "i"}) # TODO - check which?
b = type("b", (Element,), {"name": "b"}) # TODO - check which?
portal = type("portal", (Element,), {"name": "portal"}) # TODO - check which?
def Atag(self, *args, **kwargs):
# print('Atag: ', args, kwargs)
# Node.__init__(self, *args, **kwargs)
# Element.__init__(self, *args, **kwargs)
# TODO - fix BUG. this stops having no href on a tags
if kwargs.get("_href", None) is not None:
URL.__init__(self, url=kwargs["_href"])
# else:
# Node.__init__(*args, **kwargs)
Element.__init__(self, *args, **kwargs)
# Node.__init__(self, *args, **kwargs)
# URL.__init__(self, *args, **kwargs)
def __update__(
self, *args, **kwargs
): # TODO - you removed this but where the unit test that you wrote it for in the first place?
# print('__update__: ', args, kwargs)
# URL.__update__(self)
# TODO - fix BUG. this stops having no href on a tags
if self.getattr("_href", None) is not None:
self.kwargs["_href"] = self.href
# Node.__init__(self, *args, **kwargs)
# URL.__init__(self, *args, **kwargs)
# self.__init__(*args, **kwargs)
Element.__init__(self, *args, **kwargs)
URL.__init__(self, *args, **kwargs)
a = type("a", (Element, URL), {"name": "a", "__init__": Atag}) # , "__update__": __update__})
ul = type("ul", (HTMLUListElement,), {"name": "ul"})
ol = type("ol", (HTMLOListElement,), {"name": "ol"})
li = type("li", (HTMLLIElement,), {"name": "li"})
div = type("div", (HTMLDivElement,), {"name": "div"})
strong = type("strong", (Element,), {"name": "strong"}) # TODO - check
blockquote = type("blockquote", (Element,), {"name": "blockquote"}) # TODO - check
table = type("table", (HTMLTableElement,), {"name": "table"})
tr = type("tr", (Element,), {"name": "tr"})
td = type("td", (Element,), {"name": "td"})
label = type("label", (Element,), {"name": "label"})
# label.__doc__ = '''
# .. highlight:: python
# .. code-block:: python
# # used to label form elements. i.e.
# label(_for=None, _text=None, **kwargs)
# # <label for=""></label>
# '''
submit = type("submit", (Element,), {"name": "submit"})
title = type("title", (HTMLTitleElement,), {"name": "title"})
noscript = type("noscript", (Element,), {"name": "noscript"})
section = type("section", (Element,), {"name": "section"})
nav = type("nav", (Element,), {"name": "nav"})
article = type("article", (Element,), {"name": "article"})
aside = type("aside", (Element,), {"name": "aside"})
hgroup = type("hgroup", (Element,), {"name": "hgroup"})
address = type("address", (Element,), {"name": "address"})
pre = type("pre", (HTMLPreElement,), {"name": "pre"})
dl = type("dl", (Element,), {"name": "dl"})
dt = type("dt", (Element,), {"name": "dt"})
dd = type("dd", (Element,), {"name": "dd"})
figure = type("figure", (Element,), {"name": "figure"})
figcaption = type("figcaption", (Element,), {"name": "figcaption"})
em = type("em", (Element,), {"name": "em"})
small = type("small", (Element,), {"name": "small"})
s = type("s", (Element,), {"name": "s"})
cite = type("cite", (Element,), {"name": "cite"})
q = type("q", (Element,), {"name": "q"})
dfn = type("dfn", (Element,), {"name": "dfn"})
abbr = type("abbr", (Element,), {"name": "abbr"})
code = type("code", (Element,), {"name": "code"})
var = type("var", (Element,), {"name": "var"})
samp = type("samp", (Element,), {"name": "samp"})
kbd = type("kbd", (Element,), {"name": "kbd"})
sub = type("sub", (Element,), {"name": "sub"})
sup = type("sup", (Element,), {"name": "sup"})
u = type("u", (Element,), {"name": "u"})
mark = type("mark", (Element,), {"name": "mark"})
ruby = type("ruby", (Element,), {"name": "ruby"})
rt = type("rt", (Element,), {"name": "rt"})
rp = type("rp", (Element,), {"name": "rp"})
bdi = type("bdi", (Element,), {"name": "bdi"})
bdo = type("bdo", (Element,), {"name": "bdo"})
span = type("span", (HTMLSpanElement,), {"name": "span"})
ins = type("ins", (Element,), {"name": "ins"})
iframe = type("iframe", (Element,), {"name": "iframe"})
video = type("video", (HTMLVideoElement,), {"name": "video"})
audio = type("audio", (HTMLAudioElement,), {"name": "audio"})
canvas = type("canvas", (HTMLCanvasElement,), {"name": "canvas"})
caption = type("caption", (Element,), {"name": "caption"})
colgroup = type("colgroup", (Element,), {"name": "colgroup"})
tbody = type("tbody", (Element,), {"name": "tbody"})
thead = type("thead", (Element,), {"name": "thead"})
tfoot = type("tfoot", (Element,), {"name": "tfoot"})
th = type("th", (Element,), {"name": "th"})
fieldset = type(
"fieldset", (HTMLFieldSetElement,), {"name": "fieldset"}
)
legend = type("legend", (Element,), {"name": "legend"})
button = type("button", (HTMLButtonElement,), {"name": "button"})
select = type("select", (HTMLSelectElement,), {"name": "select"})
datalist = type("datalist", (HTMLDataListElement,), {"name": "datalist"})
optgroup = type("optgroup", (HTMLOptGroupElement,), {"name": "optgroup"})
option = type("option", (HTMLOptionElement,), {"name": "option"})
textarea = type("textarea", (HTMLTextAreaElement,), {"name": "textarea"})
output = type("output", (HTMLOutputElement,), {"name": "output"})
progress = type("progress", (HTMLProgressElement,), {"name": "progress"})
meter = type("meter", (HTMLMeterElement,), {"name": "meter"})
details = type("details", (Element,), {"name": "details"})
summary = type("summary", (Element,), {"name": "summary"})
menu = type("menu", (Element,), {"name": "menu"})
menuitem = type("menuitem", (Element,), {"name": "menuitem"}) # dead but may be used
font = type("font", (Element,), {"name": "font"})
header = type("header", (Element,), {"name": "header"})
footer = type("footer", (Element,), {"name": "footer"})
# map_ = type('map_', (tag,), {'name': 'map_'})
# object_ = type('object_', (tag,), {'name': 'object_'})
# del_ = type('del_', (tag,), {'name': 'del_'})
# time = HTMLTimeElement # type('time', (tag,), {'name': 'time'})
data = type("data", (HTMLDataElement,), {"name": "data"})
base = type("base", (HTMLBaseElement,), {"name": "base"})
link = type("link", (closed_tag, HTMLLinkElement), {"name": "link"}) # HTMLLinkElement TODO - closed tags
meta = type("meta", (closed_tag, HTMLMetaElement), {"name": "meta"}) # HTMLMetaElement TODO - closed tags
hr = type("hr", (closed_tag, HTMLHRElement), {"name": "hr"})
br = type(
"br",
(
closed_tag,
HTMLBRElement,
),
{"name": "br"},
)
wbr = type("wbr", (closed_tag, Element), {"name": "wbr"})
img = type("img", (closed_tag, HTMLImageElement), {"name": "img"})
param = type("param", (closed_tag, HTMLParamElement), {"name": "param"})
source = type("source", (closed_tag, HTMLSourceElement), {"name": "source"})
track = type("track", (closed_tag, HTMLTrackElement), {"name": "track"})
area = type("area", (HTMLAreaElement,), {"name": "area"})
col = type("col", (closed_tag, HTMLTableColElement), {"name": "col"})
input = type("input", (closed_tag, HTMLInputElement), {"name": "input"})
keygen = type("keygen", (closed_tag, HTMLKeygenElement), {"name": "keygen"})
command = type("command", (closed_tag, Element), {"name": "command"})
main = type("main", (Element,), {"name": "main"})
# obsolete
applet = type("applet", (Element,), {"name": "applet"})
# object = type('object', (Element,), {'name': 'object'})
basefont = type("basefont", (HTMLBaseFontElement,), {"name": "basefont"})
center = type("center", (Element,), {"name": "center"})
# dir = type('dir', (Element,), {'name': 'dir'})
embed = type("embed", (HTMLEmbedElement,), {"name": "embed"})
isindex = type("isindex", (Element,), {"name": "isindex"})
listing = type("listing", (Element,), {"name": "listing"})
plaintext = type("plaintext", (Element,), {"name": "plaintext"})
strike = type("strike", (Element,), {"name": "strike"})
xmp = type("xmp", (Element,), {"name": "xmp"})
template = type("template", (Element,), {"name": "template"})
picture = type("picture", (HTMLPictureElement,), {"name": "picture"})
dialog = type("dialog", (HTMLDialogElement,), {"name": "dialog"})
# legacy.
doctype = type("doctype", (DocumentType,), {"name": "doctype"})
comment = type("comment", (Comment,), {"name": "comment"})
[docs]def create_element(name="custom_tag", *args, **kwargs):
"""
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>
"""
# checks if already exists
if name in html_tags:
return globals()[name](*args, **kwargs)
# NOTE: we care calling it custom_tag because it can't have hyphens
custom_tag = type("custom_tag", (Element,), {"name": name})
new_tag = custom_tag(*args, **kwargs)
new_tag.name = name
return new_tag