GenerateHtml
is library for creating HTML files using Python code.
By utilizing object-oriented principles this library allows users to construct HTML elements as Python objects, manage complex structures, and easily manipulate attributes, child nodes, and styles.
# import tags and attributes
from generateHtml.tags import Div, H1, P, Hr
from generateHtml.attributes import Class
# both tags and attributes are represented by classes
div = Div(
# tags can be nested inside another just by passing them as argument in constructor
H1('Title'),
P('Paragraph'),
# attribute classes can be passed in constructor too
Class('container'),
# tags and attributes can be arranged freely in the constructor
Hr()
)
# result can be displayed with python's print function
print(div)
Output result
<div class="container">
<h1>
Title
</h1>
<p>
Paragraph
</p>
<hr>
</div>
All HTML element tags are stored inside generateHtml.tags
as separate classes named same as corresponding html element but with first letter uppercased.
Some tags have additional aliases classes inside generateHtml.tags
implemented too:
HTML Tag | Python class |
---|---|
<p> |
P, Paragraph |
You can create nested HTML structure by just passing tag objects as constructor arguments:
print(Div(H1(), Hr(), Paragraph()))
Outputs in:
<div>
<h1>
</h1>
<hr>
<p>
</p>
</div>
You can use built-in __str__
for displaying result or method display()
if you want to edit any of the displaying options.
print(Div(H1("Header")).display(pretty=False))
<div><h1>Header</h1></div>
For adding text into tags, you can just pass a str
as argument into tag constructor:
print(Paragraph("Text of the paragraph"))
Or you can use Text
class:
print(Paragraph(Text("Text of the paragraph")))
Outputs in same result:
<p>
Text of the paragraph
</p>
For HTML comment section you can use class Comment
:
print(Comment("Happy commenting!", P("Can contain another tags too")))
<!--
Happy commenting!
<p>
Can contain another tags too
</p>
-->
Comment
class supports IE specific conditional comments:
print(Comment("This is conditional comment", condition="IE 8"))
<!--[if IE 8]>
This is conditional comment
<![endif]-->
If you need to group some tags together (one after other) you can use Container
class:
print(Container(P("First paragraph"), P("Second paragraph")))
<p>
First paragraph
</p>
<p>
Second paragraph
</p>
You can initialize HTML table through Table
tag class in multiple ways:
Manually anotate every table data item
print(Table(
Tr(Th('Col 1'), Th('Col 2'), Th('Col 3')),
Tr(Td(1), Td(2), Td(3)),
Tr(Td(4), Td(5), Td(6)),
))
Col 1 | Col 2 | Col 3 |
---|---|---|
1 | 2 | 3 |
4 | 5 | 6 |
<table>
<tr>
<th>
Col 1
</th>
<th>
Col 2
</th>
<th>
Col 3
</th>
</tr>
<tr>
<td>
1
</td>
<td>
2
</td>
<td>
3
</td>
</tr>
<tr>
<td>
4
</td>
<td>
5
</td>
<td>
6
</td>
</tr>
</table>
Pass table data in constructor as list of lists
print(Table(
[['Col 1', 'Col 2', 'Col 3'], [1, 2, 3], [4, 5, 6]]
))
Col 1 | Col 2 | Col 3 |
1 | 2 | 3 |
4 | 5 | 6 |
You can pass header argument:
print(Table(
[[1, 2, 3], [4, 5, 6]], header=['Col 1', 'Col 2', 'Col 3']
))
Or explicitly set first row/col or both as header:
print(Table(
[['Col 1', 'Col 2', 'Col 3'], [1, 2, 3], [4, 5, 6]], header='row'
))
Both results in this table:
Col 1 | Col 2 | Col 3 |
---|---|---|
1 | 2 | 3 |
4 | 5 | 6 |
Attributes are like tag elements represented by classes. Class representing attribute have uppercased first letter and every letter after dash -
character in original attribute name.
So for example attribute accept-charset
has coresponding class name AcceptCharset
.
Some of attributes are in conflict with Tag element's names. For this situation underscore character '_'
is appended at the end of attribute class name. Here is table with conflicting names:
Attribute | Class |
---|---|
cite |
Cite_ |
data |
Data_ |
dir |
Dir_ |
form |
Form_ |
label |
Label_ |
span |
Span_ |
style |
Style_ |
title |
Title_ |
Attributes can be added into tags right at initialization process. Just add them as constructor parameters.
print(Div(P("First", Class("highlight")), Class("container"), Id("main"), P("Second")))
<div class="container" id="main">
<p class="highlight">
First
</p>
<p>
Second
</p>
</div>
Another way how to create attribute is to use keyword arguents in tag class constructor. Again replacing dashes -
to underscore _
and append underscore after reserved keywords:
Attribute | Class | Keyword argument |
---|---|---|
class |
Class |
class_ |
for |
For |
for_ |
accept-charset |
AcceptCharset |
accept_charset |
print(Form(action="/action_page.php", accept_charset="utf-8"))
<form action="/action_page.php" accept-charset="utf-8">
</form>
For creating inline styles of HTML tag elements you can use Style_
attribute class.
You can initialize style with raw CSS string in constructor of Style_
class or you can use keyword named arguments.
sty = Style_(border="2px solid powderblue", margin="50 px", font_size="12 px")
print(P("Styled paragraph", sty))
<p style="border: 2px solid powderblue;margin: 50 px;font-size: 12 px;">
Styled paragraph
</p>
With attribute class Data_
you can create data-*
attribute that allow us to store extra information on standard, semantic HTML elements without other hacks such as non-standard attributes, or extra properties on DOM.
data = Data_("hidden-id", "1")
print(Div(data, data_col=5))
<div data-col="5" data-hidden-id="1">
</div>
Two tags can be concatenated using +
operator. Results in parent Container
tag containing both concatenating tags.
p1 = P("First paragraph")
p2 = P("Second paragraph")
print(p1 + p2)
<p>
First paragraph
</p>
<p>
Second paragraph
</p>
New items into created tags can be added via add()
method.
- You can add tags, attributes or text into tag.
- Into text nodes you can append another text via
add()
method. - Adding into attributes you append text in attribute's value.
div = Div()
div.add(P("New paragraph").add(Class('paragraph_class')), Class("div_class"))
print(div)
<div class="div_class">
<p class="paragraph_class">
New paragraph
</p>
</div>
Tags can be multiplicated with positive int
number using *
multiplication sign. Results in parent Container
object:
p = P("Paragraph")
print(p * 3)
<p>
Paragraph
</p>
<p>
Paragraph
</p>
<p>
Paragraph
</p>
Child nodes of the tag can be accesed through python list notation:
div = Div(P("First paragraph"), Br(), P('Second paragraph class'))
div[2] = Strong('strong text')
del div[1]
print(div)
<div>
<p>
First paragraph
</p>
<strong>
strong text
</strong>
</div>
Attributes can be accesed, modified or deleted from tag object through dictionary notation:
div = Div(Class("container"), Id("main"))
del div['id']
div['class'] = "new_container"
print(div)
<div class="new_container">
</div>
HTML elements can be searched inside another using find
method:
div = Div(
P("Foo bar baz"),
Img(Src("img.png")),
Id("foo"),
Ol(Class("bar"),
*[Li(i) for i in range(10)]),
Em("bar"),
Div(Id("inner_div")))
div.find(Div()) # Finds all divs in div (including self)
# return 2 divs: [<:: Div element: 4 child nodes, 1 attributes ::>, <:: Div element: no childs, 1 attributes ::>]
div.find(Div(Id("inner_div"))) # Finds all divs with id="inner_div"
# return 1 div: [<:: Div element: no childs, 1 attributes ::>]
div.find(Li(1)) # Finds all li with text "1"
# return 1 li: [<:: Li element: 1 child nodes ::>]
div.find("bar") # Finds all Text nodes containing 'bar'
# return 2 Text nodes: [<:: Text: "Foo bar ba..." ::>, <:: Text: "bar" ::>]
Tags and attributes can be created using context manager. Just use with
keyword. You can even nest with
statements.
div: HtmlElement = None
with Div(H1("Header")) as div, P() as p:
with Span() as sp, Strong():
Text("foo")
Text("bar")
sp.add("baz")
sp[0] = "qux"
Hr()
print(div)
<div>
<h1>
Header
</h1>
<p>
<span>
qux
<strong>
foo
bar
</strong>
</span>
<hr>
</p>
</div>