Without looking too far into this, I wanted to see what could be a simple way to adapt the JSX syntax of React to python. The simplest way would be the functional way: imagine that the various html elements are actual python functions (with props).
def div(props, *children):
return f'<div {format_props(props)}>{format_children(children)}</div>'
def h1(props, *children):
return f'<h1 {format_props(props)}>{format_children(children)}</h1>'
There is a lot of code repetition here, so we might as well refactor that a little bit:
def create_element(tag):
"""Generates a function to create HTML elements of the specified tag."""
def element(props=None, *children):
props_str = format_props(props) if props else ""
children_str = format_children(children)
return f'<{tag}{props_str}>{children_str}</{tag}>'
return element
# Creating specific HTML element functions
div = create_element("div")
p = create_element("p")
a = create_element("a")
Formatting the elements
We need few functions here:
def format_props(props):
"""Formats and returns a string of HTML attributes from a dictionary."""
if not props:
return ""
return " " + " ".join(
f'{key.replace("_", "-")}="{value}"'
for key, value in props.items()
if value is not None
)
def format_children(children):
"""Formats and returns a string of HTML content from children components."""
return "".join(str(child) for child in children)
def render(component):
return component
Trying it
Now I simply put everything together into a simple app, to try it:
# Flask app
app = Flask(__name__)
@app.route("/")
def hello_world():
content = div(
{"className": "container"},
div(
{"className": "row"},
div(
{"className": "col"},
p({}, "This is a paragraph inside a column."),
a({"href": "https://example.com"}, "Click here"),
),
),
)
return render(content)
if __name__ == "__main__":
app.run()
When I now run python app.py
and visit http://127.0.0.1:5000
I get the web page as expected.