Purpose is to create a simple html generator for Python. Few other generators have been available since decade but they all seems to have small caveats. However combining features I've managed to create a library that fits better to my own projects.
Problems:
<my-tag dc:attr="" />Other requirements:
As simple implementation as possible, no need for complicated page generation methods, just basic functionality. Extending tags for structures like table, lists and svg graphics. Nesting tags and giving attribute names should be clean and intuitive. Pythonic.
In [1]:
class TAG(object):
def __init__(self, *args, **kw):
pass
def getAttribute(self, key):
pass
def setAttribute(self, key, value):
pass
def addContent(self, item):
pass
In [2]:
class htmlHelper(object):
def create(self, name):
pass
def __getattr__(self, tag):
pass
In [3]:
from remarkuple import helper as h, concat
In [4]:
# introducing the main flow of the nesting tags
print h.html(h.head(h.title("Simple html document")), h.body("Content"))
In [5]:
# a tag without content will be output as a short tag form
print h.br()
In [6]:
# if you pass empty string on tag content, closing tag will be generated
print h.script('')
In [7]:
# content can be a string, a numeric or other tag elements
print h.h1("Header ", 1, h.span(".1"))
In [8]:
# providing other content can yield unexpected results because all will be string normalized
print h.div([0,1], {'k': h.b()})
In [9]:
# content can be callable
print h.p(h.br)
In [10]:
# as said, content can be callable
def ul():
return h.ul(h.li)
print h.div(ul)
In [11]:
# adding more content inside the element
# operator used here += is same as tag.addContent method
h1 = h.h1('Header')
h1 += " 1."
h1 += h.span("2")
print h1
In [12]:
# concatenating elements
h1 = h.h1()
print concat(h1, h.h2(), h.h3)
In [13]:
# chain arguments
print h.h1(h.span(), h.span(), h.span())
In [14]:
# chain arguments by list
print h.h1(*[h.span, h.span, h.span])
In [15]:
# add attributes
print h.div(id="container", title="Content container")
In [16]:
# add attributes by dictionary
print h.div(**{'id': "container", 'title':"Content container"})
In [17]:
# using python reserved words can be tackled with uppercase letters or capitalization
# h.del or h.tag(class="") doesn't work but gives parse error. instead use something like:
print h.DEL(Class="reserved")
In [18]:
# but if you really want uppercase tag names or attributes,
# you can use setName and setAttribute methods
print h.create('DEL').setAttribute('Class', 'reserved')
In [19]:
# special attribute and tag names can be handled with setters.
# h.my-tag(dc:name = "special") doesn't work because of naming convention rules on python
# so you need to do:
print h.create("my-tag").addContent("content").setAttribute('dc:name', 'special')
In [20]:
class table(type(h.table())):
def __init__(self, *args, **kw):
pass
def addCaption(self, caption, **kw):
pass
def addColGroup(self, *cols, **kw):
pass
def addHeadRow(self, *trs, **kw):
pass
def addFootRow(self, *trs, **kw):
pass
def addBodyRow(self, *trs, **kw):
pass
def addBodyRows(self, *trs, **kw):
pass
In [21]:
# sure you can make tables with core table tags
tbl = h.table(CLASS="data")
tbl += h.thead(h.tr(*map(h.th, [1,2,3])))
tbl += h.tbody(*[h.tr(*map(h.td, ["1.%s"%i,"2.%s"%i,"3.%s"%i])) for i in [1,2,3]])
print tbl
tbl
Out[21]:
In [22]:
# but using special table factory function structuring table is easier
from remarkuple import table
# initialize table
t = table(**{'id': 'data'})
# add caption title
t.addCaption('Caption')
columns = [{'style': 'background-color: red'},
{'style': 'background-color: green'},
{'style': 'background-color: blue'}]
# add column definitions
t.addColGroup(*[h.col(**attr) for attr in columns])
header = ['Column 1', 'Column 2', 'Column 3']
# add header row with column titles
t.addHeadRow(h.tr(*map(h.th, header)))
# add body rows
for i in range(1,3):
t.addBodyRow(h.tr(*map(h.td, ["1.%s"%i,"2.%s"%i,"3.%s"%i])))
# add separate bodies with rows
for i in range(3,5):
t.addBodyRows(h.tr(*map(h.td, ["1.%s"%i,"2.%s"%i,"3.%s"%i])), id='tbody%s'%i)
# add footer row
t.addFootRow(h.tr(h.td('footer', colspan="3")))
t
Out[22]:
In [23]:
%%html
<style type="text/css">
table#data { margin: 1em auto; border-collapse: collapse; border: 0}
table#data caption { font-size: 1.2em; text-align: center; padding: 3px}
table#data th, table#data td { padding: .25em; border: 1px solid #000; font-family: sans-serif; color: white}
table#data th { color: #004900; font-weight: bold; text-align: left; }
table#data thead th { border-bottom: 3px double #000; background-color: #ddd; text-align: center; }
table#data tfoot td { border-top: 3px double #000; color: #fff; font-style: italic; font-size: .8em; text-align: center; background-color: brown}
table#data tbody th { color: #000; }
table#data #tbody3 {font-weight: bold;font-size: 1.5em;}
table#data #tbody4 {font-style: italic;}
</style>
In [24]:
class svg(type(h.svg())):
def __init__(self, *args, **kw):
pass
def set_grid(self, boolean):
pass
def set_axis(self, boolean):
pass
def set_origin(self, boolean):
pass
def set_size(self, width, height):
pass
def set_text(self, *args, **kw):
pass
def set_rectangle(self, *args, **kw):
pass
def set_group(self, *args, **kw):
pass
def set_defs(self, *args, **kw):
pass
def set_line(self, *args, **kw):
pass
def set_circle(self, *args, **kw):
pass
def set_triangle(self, *args, **kw):
pass
def set_square(self, *args, **kw):
pass
def set_pentagon(self, *args, **kw):
pass
def set_hexagon(self, *args, **kw):
pass
def set_regular_polygon(self, *args, **kw):
pass
def polygon_points(self, vertex):
pass
def vertex(self, cx = 0, cy = 0, sides = 4, radius = 1, degrees = 0):
pass
In [25]:
from remarkuple import svg
s = svg().set_axes().set_grid().set_origin()
s.set_circle(r=100, fill="darkgreen", stroke="white", style="fill-opacity: 75%")
s.set_circle(r=4, cx=0, cy=100)
s.set_text("(0,100)", x=5, y=105)
s
Out[25]:
In [26]:
from numpy import linspace, pi, sin, cos
s = svg(width=200, height=200)
for x, y in enumerate(linspace(-pi, pi, 51)):
s.set_circle(r=y+pi, cx=-100+x*2, cy=sin(y)*x)
s.set_circle(r=pi-y, cx=x*2, cy=sin(y)*x)
s.set_circle(r=pi-y, cx=x*2, cy=-sin(y)*x)
s.set_circle(r=y+pi, cx=-100+x*2, cy=-sin(y)*x)
s
Out[26]:
Copyright (c) 2014 Marko Manninen