1+ import io
2+
3+ class Element (object ):
4+
5+ @classmethod
6+ def check_content_is_compat (cls , content ):
7+ if isinstance (content , str ) or isinstance (content , Element ):
8+ return True
9+ else :
10+ return False
11+
12+
13+ def __init__ (self , content = None , ** kwargs ):
14+ '''
15+ :param content: The string or element instance to initialize the element with.
16+ :param kwargs: Attributes that are associated with the content
17+ :return: Nothing
18+ '''
19+ self .tag = 'tag'
20+ self .data = []
21+ self .attr = kwargs
22+
23+ if content is not None :
24+ if Element .check_content_is_compat (content ):
25+ self .data .append (content )
26+ else :
27+ raise ValueError ("The 'content' argument must be a string or another Element" )
28+
29+
30+ def append (self , content , ** kwargs ):
31+ '''
32+ :param content: The string or element instance to add to the items already in the element
33+ :param kwargs: Attributes that are associated with the content
34+ :return: Nothing
35+ '''
36+
37+ self .attr .update (kwargs )
38+ if content is not None :
39+ if Element .check_content_is_compat (content ):
40+ self .data .append (content )
41+ else :
42+ raise ValueError ("The 'content' argument must be a string or another Element" )
43+
44+
45+ def _render_start_tag (self , file_out , ind , inline = True , self_closing = False ):
46+ try :
47+ if not inline :
48+ file_out .write ("\n {0}" .format (ind ))
49+ file_out .write ("<{0}" .format (self .tag ))
50+ for k ,v in self .attr .items ():
51+ file_out .write (' {0}="{1}"' .format (k , v ))
52+ if self_closing :
53+ file_out .write ("/>" )
54+ else :
55+ file_out .write (">" )
56+ except AttributeError :
57+ raise ValueError ("The 'file_out' argument must be a class or subclass of io.TextIOBase" )
58+
59+
60+ def _render_data (self , file_out , ind , inline = True ):
61+ sub_ind = " " * (len (ind ) + 3 )
62+
63+ for idx , item in enumerate (self .data ):
64+ try :
65+ # Assume it is an Element
66+ item .render (file_out , sub_ind )
67+ except AttributeError :
68+ # Guess not...assume it is a string :)
69+ try :
70+ if not inline :
71+ file_out .write ("\n {0}" .format (sub_ind ))
72+ file_out .write ("{0}" .format (item ))
73+ except AttributeError :
74+ raise ValueError ("The 'file_out' argument must be a class or subclass of io.TextIOBase" )
75+
76+
77+ def _render_end_tag (self , file_out , ind , inline = True ):
78+ try :
79+ if not inline :
80+ file_out .write ("\n {0}" .format (ind ))
81+ file_out .write ("</{0}>" .format (self .tag ))
82+ except AttributeError :
83+ raise ValueError ("The 'file_out' argument must be a class or subclass of io.TextIOBase" )
84+
85+
86+ def render (self , file_out , ind = "" ):
87+ '''
88+
89+ :param file_out: A io.TextIOBase file object
90+ :param ind: A string, which supplies the amount of indentation whitespace to use
91+ :return: Nothing
92+ '''
93+ self ._render_start_tag (file_out , ind , False , False )
94+ self ._render_data (file_out , ind , False )
95+ self ._render_end_tag (file_out , ind , False )
96+
97+
98+
99+ class Html (Element ):
100+ def __init__ (self , content = None , ** kwargs ):
101+ super ().__init__ (content , ** kwargs )
102+ self .tag = "html"
103+ self .data .append ("<!DOCTYPE html>" )
104+
105+
106+ class Body (Element ):
107+ def __init__ (self , content = None , ** kwargs ):
108+ super ().__init__ (content , ** kwargs )
109+ self .tag = "body"
110+
111+
112+ class P (Element ):
113+ def __init__ (self , content = None , ** kwargs ):
114+ super ().__init__ (content , ** kwargs )
115+ self .tag = "p"
116+
117+
118+ class Head (Element ):
119+ def __init__ (self , content = None , ** kwargs ):
120+ super ().__init__ (content , ** kwargs )
121+ self .tag = "head"
122+
123+ class Ul (Element ):
124+ def __init__ (self , content = None , ** kwargs ):
125+ super ().__init__ (content , ** kwargs )
126+ self .tag = "ul"
127+
128+ class Li (Element ):
129+ def __init__ (self , content = None , ** kwargs ):
130+ super ().__init__ (content , ** kwargs )
131+ self .tag = "li"
132+
133+
134+ class OneLineTag (Element ):
135+ def __init__ (self , content = None , ** kwargs ):
136+ super ().__init__ (content , ** kwargs )
137+ self .tag = "head"
138+
139+ def render (self , file_out , ind = "" ):
140+ '''
141+
142+ :param file_out: A io.TextIOBase file object
143+ :param ind: A string, which supplies the amount of indentation whitespace to use
144+ :return: Nothing
145+ '''
146+ self ._render_start_tag (file_out , ind , False , False )
147+ self ._render_data (file_out , ind , True )
148+ self ._render_end_tag (file_out , ind , True )
149+
150+
151+
152+ class Title (OneLineTag ):
153+ def __init__ (self , content = None , ** kwargs ):
154+ super ().__init__ (content , ** kwargs )
155+ self .tag = "title"
156+
157+ class H (OneLineTag ):
158+ def __init__ (self , hdr_lvl , content = None , ** kwargs ):
159+ super ().__init__ (content , ** kwargs )
160+ self .tag = "h{0}" .format (hdr_lvl )
161+
162+
163+ class SelfClosingTag (Element ):
164+ def __init__ (self , content = None , ** kwargs ):
165+ super ().__init__ (content , ** kwargs )
166+ self .tag = "selfclosing"
167+
168+ def render (self , file_out , ind = "" ):
169+ '''
170+
171+ :param file_out: A io.TextIOBase file object
172+ :param ind: A string, which supplies the amount of indentation whitespace to use
173+ :return: Nothing
174+ '''
175+ self ._render_start_tag (file_out , ind , True , True )
176+ self ._render_data (file_out , ind , True )
177+
178+
179+
180+ class Hr (SelfClosingTag ):
181+ def __init__ (self , content = None , ** kwargs ):
182+ super ().__init__ (content , ** kwargs )
183+ self .tag = "hr"
184+
185+ class Br (SelfClosingTag ):
186+ def __init__ (self , content = None , ** kwargs ):
187+ super ().__init__ (content , ** kwargs )
188+ self .tag = "br"
189+
190+ class Meta (SelfClosingTag ):
191+ def __init__ (self , content = None , ** kwargs ):
192+ super ().__init__ (content , ** kwargs )
193+ self .tag = "meta"
194+ self .attr ['charset' ]= "UTF-8"
195+
196+
197+ class A (Element ):
198+ def __init__ (self , link , content ):
199+ super ().__init__ (content , href = link )
200+ self .tag = "a"
0 commit comments