@@ -61,12 +61,82 @@ def _write_line(self, fp, value, indent=0):
6161 fp .write (value )
6262
6363
64+ class ElementBuilder :
65+ """
66+ Helper class returned by the 'with element as e:' context manager.
67+ It allows creating siblings attached to the parent element using a fluent syntax.
68+ """
69+ def __init__ (self , parent : Element ):
70+ self ._parent = parent
71+
72+ # Register common HTML tags as methods on this instance
73+ # This allows: e.div(...), e.h1(...)
74+ self .div = self ._factory ("div" )
75+ self .section = self ._factory ("section" )
76+ self .header = self ._factory ("header" )
77+ self .footer = self ._factory ("footer" )
78+ self .main = self ._factory ("main" )
79+ self .nav = self ._factory ("nav" )
80+
81+ self .h1 = self ._factory ("h1" )
82+ self .h2 = self ._factory ("h2" )
83+ self .h3 = self ._factory ("h3" )
84+ self .h4 = self ._factory ("h4" )
85+ self .h5 = self ._factory ("h5" )
86+ self .h6 = self ._factory ("h6" )
87+
88+ self .p = self ._factory ("p" )
89+ self .span = self ._factory ("span" )
90+ self .a = self ._factory ("a" )
91+ self .img = self ._factory ("img" )
92+
93+ self .ul = self ._factory ("ul" )
94+ self .ol = self ._factory ("ol" )
95+ self .li = self ._factory ("li" )
96+
97+ self .table = self ._factory ("table" )
98+ self .thead = self ._factory ("thead" )
99+ self .tbody = self ._factory ("tbody" )
100+ self .tr = self ._factory ("tr" )
101+ self .td = self ._factory ("td" )
102+ self .th = self ._factory ("th" )
103+
104+ self .form = self ._factory ("form" )
105+ self .input = self ._factory ("input" )
106+ self .button = self ._factory ("button" )
107+ self .label = self ._factory ("label" )
108+ self .select = self ._factory ("select" )
109+ self .option = self ._factory ("option" )
110+ self .textarea = self ._factory ("textarea" )
111+
112+ def tag (self , name : str , * content , ** kwargs ) -> Element :
113+ """
114+ Explicitly create a tag that isn't pre-defined.
115+ Usage: e.tag("my-custom-component", ...)
116+ """
117+ el = Element (name , * content , ** kwargs )
118+ self ._parent .add (el )
119+ return el
120+
121+ def _factory (self , tag_name : str ):
122+ """
123+ Internal helper that returns a function to create a specific tag.
124+ """
125+ def wrapper (* content , ** kwargs ) -> Element :
126+ return self .tag (tag_name , * content , ** kwargs )
127+
128+ # improved debugging representation
129+ wrapper .__name__ = tag_name
130+ wrapper .__qualname__ = f"ElementBuilder.{ tag_name } "
131+ return wrapper
132+
133+
64134class Element (Markup ):
65135 def __init__ (
66136 self ,
67137 tag : str ,
68- * content : Element ,
69138 text : str | None = None ,
139+ * content : Element ,
70140 classes : str | List [str ] | None = None ,
71141 id : str | None = None ,
72142 style : Style | None = None ,
@@ -89,6 +159,20 @@ def __init__(
89159 self ._parent = parent
90160 self ._attrs = attrs
91161
162+ def __enter__ (self ) -> ElementBuilder :
163+ """
164+ Enables the syntax:
165+ with doc.body as e:
166+ e.h1("Title")
167+ """
168+ return ElementBuilder (self )
169+
170+ def __exit__ (self , exc_type , exc_val , exc_tb ):
171+ """
172+ Standard context manager exit.
173+ """
174+ return False # Propagate exceptions if they occur
175+
92176 def id (self , id : str ) -> Self :
93177 self ._id = id
94178 return self
0 commit comments