Skip to content

Instantly share code, notes, and snippets.

@tvogels
Created March 10, 2022 20:41
Show Gist options
  • Save tvogels/0271ccf94f3cd1d97fb65554b77e3704 to your computer and use it in GitHub Desktop.
Save tvogels/0271ccf94f3cd1d97fb65554b77e3704 to your computer and use it in GitHub Desktop.
Python syntax for generating HTML, XML, or SVG programatically
from typing import Any, Dict, List, Union
def main():
# shortcuts
d = Dom()
svg, circle, rect, g = d.svg, d.circle, d.rect, d.g
print(
svg(
circle(x=3, y=4),
rect(x=2, z=3)(width=100),
g(id="hoi")(
[circle(i=i) for i in range(4)],
),
)
)
# Prints:
# <svg>
# <circle x="3" y="4" />
# <rect x="2" z="3" width="100" />
# <g id="hoi">
# <circle i="0" />
# <circle i="1" />
# <circle i="2" />
# <circle i="3" />
# </g>
# </svg>
class Node:
tag: str
children: List["Node"]
attributes: Dict[str, Any]
def __init__(self, tag: str):
self.tag = tag
self.children = []
self.attributes = {}
def __call__(
self, *children: Union["Node", List["Node"]], **attributes: Any
) -> "Node":
if len(self.children) > 0 and len(children) > 0:
raise RuntimeError(
"Cannot add children to a node that already has children"
)
new_node = Node(self.tag)
new_node.children = _flatten(list(children))
new_node.attributes = {**self.attributes, **attributes}
return new_node
def __str__(self):
attr_string = "".join(
[f' {key}="{value}"' for key, value in self.attributes.items()]
)
if self.children:
child_string = "\n".join([_indent(str(c), " ") for c in self.children])
return f"<{self.tag}{attr_string}>\n{child_string}\n</{self.tag}>"
else:
return f"<{self.tag}{attr_string} />"
class Dom:
def __getattr__(self, attr):
return Node(attr)
def _flatten(x: List) -> List:
r = []
for y in x:
if isinstance(y, list):
r.extend(_flatten(y))
else:
r.append(y)
return r
def _indent(x: str, indentation: str = "\t") -> str:
return "".join([indentation + l for l in x.splitlines(keepends=True)])
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment