-
Notifications
You must be signed in to change notification settings - Fork 0
/
tiny_html.py
116 lines (101 loc) · 5.21 KB
/
tiny_html.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
"""Very simple helper classes for creation of HTML documents."""
from __future__ import annotations
# ============================================================================
INDENT = ' ' # Intentation to be used.
LINEBR = '\n' # Linebreak character
# ============================================================================
class Tag(object):
"""Class to facilitate creating tags for HTML documents."""
# ========================================================================
def __init__(self, name: str, attributes: dict = {}, text: str = None) -> None:
self.name = name
self.attributes = attributes
self.text = text
self.children = []
# ========================================================================
# Add the given tag to the list of sub-tags.
def add(self, tag: Tag) -> None:
self.children.append(tag)
# ========================================================================
# Create a new sub-tag using the given parameters, add it to the
# current tag and return it to the caller.
def tag(self, name: str, attributes: dict = {}, text: str = None) -> Tag:
tag = Tag(name, attributes, text)
self.add(tag)
return tag
# ========================================================================
# Convert the Tag to an HTML string.
def html(self, indent='') -> str:
# ------------------------------------------------------------------------
s = indent + "<" + self.name
# ------------------------------------------------------------------------
if len(self.attributes) > 0:
for n in sorted(self.attributes):
s += ' ' + n + '="' + self.attributes[n] + '"'
# ------------------------------------------------------------------------
if (self.text is not None) or len(self.children) > 0:
# ------------------------------------------------------------------------
s += '>'
# ------------------------------------------------------------------------
has_children = len(self.children) > 0
multi_line = has_children
# ------------------------------------------------------------------------
if not multi_line:
if self.text is not None:
if ('\n' in self.text):
multi_line = True
# ------------------------------------------------------------------------
if multi_line:
s += LINEBR
# ------------------------------------------------------------------------
if self.text is not None:
if multi_line:
s += indent + INDENT
s += self.text
if multi_line:
s += LINEBR
# ------------------------------------------------------------------------
if has_children:
for child in self.children:
s += child.html(indent + INDENT)
# ------------------------------------------------------------------------
if multi_line:
s += indent
s += "</" + self.name
# ------------------------------------------------------------------------
else:
if self.name not in ['br']:
s += '/'
# ------------------------------------------------------------------------
s += '>' + LINEBR
# ------------------------------------------------------------------------
return s
# ============================================================================
class Html(Tag):
"""Class representing a HTML document."""
# ========================================================================
def __init__(self, create_head_and_body=True, charset='utf-8') -> None:
# ------------------------------------------------------------------------
super().__init__('html', {'lang': 'en'})
# ------------------------------------------------------------------------
self.charset = charset
# ------------------------------------------------------------------------
# Set preamble variable now.
# The user can overwrite it afterwards, if they want to.
self.preamble = '<!doctype html>' + LINEBR
# ------------------------------------------------------------------------
if create_head_and_body:
self.head = super().tag('head')
self.head.tag('meta', { 'charset':self.charset})
self.body = super().tag('body')
# ------------------------------------------------------------------------
# ========================================================================
def html(self) -> str:
return self.preamble + super().html()
# ========================================================================
def save(self, filename):
with open(filename, 'wt', encoding=self.charset, errors="surrogateescape") as f_out:
f_out.write(self.html())
# ============================================================================
# End of file.
# ============================================================================