Welcome to htmlBuilder’s documentation¶
HtmlBuilder is a python library that allows you to render HTML files by writing python code. And to make use of python features, clean syntax, and object-oriented design to their full potential.
Why should you care about this library?¶
When rendering HTML programmatically, there are other options available (template engines and other rendering libraries). Still, these are often limited in what they can do, or it’s necessary to learn a new level of abstraction before being productive. HtmlBuilder tries to improve on this by following the next few ideas:
- Minimal learning curve: Users should need no more than Python and HTML knowledge to be productive using this tool.
- Real python code: The final code looks and behaves as you would expect from other python code.
- Easily testable: Users can introspect and unit test the HTML object structure before rendering the HTML string.
Table of content¶
Getting Started¶
A simple example¶
# import necessary tags and attributes
from htmlBuilder.tags import *
from htmlBuilder.attributes import Class, Style as InlineStyle
# html tags are represented by classes
html = Html([],
# any tag can receive another tag as constructor parameter
Head([],
Title([], "A beautiful site")
),
Body([Class('btn btn-success'), InlineStyle(background_color='red', bottom='35px')],
Hr(),
Div([],
Div()
)
)
)
# no closing tags are required
# call the render() method to return tag instances as html text
print(html.render(pretty=True))
Output:
<html>
<head>
<title>
A beautiful site
</title>
</head>
<body class='btn btn-success' style='background-color: red; bottom: 35px'>
<hr/>
<div>
<div></div>
</div>
</body>
</html>
A not so simple example¶
from htmlBuilder.attributes import Class
from htmlBuilder.tags import Html, Head, Title, Body, Nav, Div, Footer, Ul, Li
users = [ # declare data
{
"name": "Jose",
"movies": ['A beautiful mind', 'Red'],
"favorite-number": 42,
},
{
"name": "Jaime",
"movies": ['The breakfast club', 'Fight club'],
"favorite-number": 7,
},
{
"name": "Jhon",
"movies": ['The room', 'Yes man'],
"favorite-number": 987654321,
},
]
# functions can be used to handle recurring tag structures
def my_custom_nav():
# these functions can return a tag or a list of tags ( [tag1,tag2,tag3] )
return Nav([Class("nav pretty")],
Div([], "A beautiful NavBar")
)
html = Html([],
Head([],
Title([], "An awesome site")
),
Body([],
my_custom_nav(), # calling previously defined function
[Div([Class(f"user-{user['name'].lower()}")],
Div([], user['name']),
Ul([],
[Li([], movie) for movie in user["movies"]] # list comprehensions can be used to easily render multiple tags
) if user['favorite-number'] < 100 else "Favorite number is too high" # python's ternary operation is allowed too
) for user in users],
Footer([], "My Footer"),
)
)
print(html.render(pretty=True, doctype=True)) # pass doctype=True to add a document declaration
Output:
<!DOCTYPE html>
<html>
<head>
<title>
An awesome site
</title>
</head>
<body>
<nav class='nav pretty'>
<div>
A beautiful NavBar
</div>
</nav>
<div class='user-jose'>
<div>
Jose
</div>
<ul>
<li>
A beautiful mind
</li>
<li>
Red
</li>
</ul>
</div>
<div class='user-jaime'>
<div>
Jaime
</div>
<ul>
<li>
The breakfast club
</li>
<li>
Fight club
</li>
</ul>
</div>
<div class='user-jhon'>
<div>
Jhon
</div>
Favorite number is too high
</div>
<footer>
My Footer
</footer>
</body>
</html>
HTML tags¶
Each HTML element type has a corresponding class defined in the htmlBuilder.tags
module.
from htmlBuilder.tags import Div
html = Div()
print(html.render())
<div></div>
As you can see in the previous example, the Div
instance has a render()
method which returns a string with the resulting HTML. This is true for all HTML elements defined within htmlBuilder.tags
.
Adding content¶
We’ll continue by adding some text content into our HTML element.
from htmlBuilder.tags import Div, Span
html = Div([], "Hello world")
print(html.render())
html = Div([], Span())
print(html.render())
<div>Hello world</div>
<div><span></span></div>
When initializing a HTML element the first argument must be a list
, tuple
or iterable containing any number of htmlBuilder.attributes.HtmlTagAttribute
instances (see HTML attributes for more details). Then, zero or more htmlBuilder.tags.HtmlTag
, str
or iterable instance objects as the element’s content. That means that all of the following are valid and will render the same HTML:
Note
- All of the following examples in this page will exclude the following lines unless specified otherwise
from htmlBuilder.tags import *
print(html.render())
# All of the following will render:
# '<ul><li></li><li></li></ul>'
Ul([],
Li(),
Li(),
)
Ul([], [
Li(),
Li(),
])
Ul([],
Li(),
[Li()],
)
Ul([], (Li() for _ in range(2)))
#Any level of nesting is allowed when passing an iterable. So this is also valid:
Ul([], [[[[Li(), Li()]]]])
Adding a <!DOCTYPE> declaration¶
HTML documents should declare their type for browsers to know what to expect. So all HTML documents should start with a <!DOCTYPE>
declaration.
Users can pass the doctype=True
option to the render()
method to handle this.
html = Div()
print(html.render(doctype=True, pretty=True))
<!DOCTYPE html>
<div></div>
For information on how to control the render process and the pretty=True
option, see Controlling the render process.
HTML attributes¶
Each HTML attribute has a corresponding class defined in the htmlBuilder.attributes
module. These can be used when initializing htmlBuilder.tags.HtmlTag
instances.
from htmlBuilder.tags import Div
from htmlBuilder.attributes import Id, Class
html = Div([Id('main-div'), Class('pretty')])
print(html.render())
<div id='main-div' class='pretty'></div>
Every HtmlTag
is initialized with zero or more. If it receives one or more parameters, then the first must be a python iterable with zero or more HtmlTagAttribute
instances.
Note
- Attribute class names are created by “camel casing” their corresponding HTML names. This process is done by uppercasing each letter after a hyphen(-) and then removing each of the hyphens. E.g.
class
->Class
id
->Id
accept-charset
->AcceptCharset
onkeypress
->Onkeypress
Special attributes¶
Users can initialize all HtmlTagAttribute
classes by passing a single str
parameter with that attribute’s value. Also, there are some frequently used attributes with more support.
style
¶
This attribute can use keyword arguments to define each CSS property. Both of the following objects render the same HTML.
Note
- All of the following examples in this page will exclude the following lines unless specified otherwise
from htmlBuilder.tags import *
from htmlBuilder.attributes import *
print(html.render())
# Both objects represent the same html
# <div style='color: white; background_color: black'>Hello World</div>
Div([Style(color="white", background_color="black")], "Hello World")
Div([Style("color: white; background-color: black")], "Hello World")
Note
Notice that when using keyword arguments to initialize a Style
instance, the CSS property name is constructed by replacing _
with -
.
data-*
¶
Users can handle data-*
attributes using the htmlBuilder.attributes.Data_
class which expects a name
and a value
its __init__
first and second parameters respectively.
When rendered, the attribute name is constructed by appending the string "data-"
with the given name
.
# Both objects represent the same html
# <div data-message='Hello World'></div>
Div([Data_("message", "Hello World")])
Div([Data_(name="message", value="Hello World")])
Controlling the render process¶
Let’s consider the following code:
from htmlBuilder.tags import Html, Head, Title, Body, Ul, Li
from htmlBuilder.attributes import Id
html = Html([],
Head([],
Title([], "My website"),
),
Body([],
Ul([Id('main-list')],
Li([], 'Item 1'),
Li([], 'Item 2'),
)
)
)
print(html.render())
<html><head><title>My website</title></head><body><ul id='main-list'><li>Item 1</li><li>Item 2</li></ul></body></html>
By default, htmlBuilder
will try to keep the resulting HTML as small as possible. This is ideal for most cases and will not be a problem for browsers, but it can be for humans. So the htmlBuilder.tasks.HtmlTag.render() method allows you to control the output format of the rendered HTML.
Passing the option pretty=True
:
print(html.render(pretty=True))
<html>
<head>
<title>
My website
</title>
</head>
<body>
<ul id='main-list'>
<li>
Item 1
</li>
<li>
Item 2
</li>
</ul>
</body>
</html>
Examples¶
htmlBuilder
is designed to let users apply all of their python knowledge when constructing HTML. That is why other than understanding the basics of this library, the best learning tools will be those focused on Python itself.
This page contains a list of use-cases and examples that may be useful to readers.
How to contribute?¶
The complete source code is available on GitHub.
Feel free to open an Issue or to submit a pull request.
License¶
The project is licensed under the MIT license.